Raymond Toy pushed to branch rtoy-issue-76-add-ansi-tests-to-ci at cmucl / cmucl

Commits:

12 changed files:

Changes:

  • .gitlab-ci.yml
    ... ... @@ -14,7 +14,7 @@ linux-runner:
    14 14
         - mkdir snapshot
    
    15 15
         - (cd snapshot; tar xjf ../cmucl-$version-linux.tar.bz2; tar xjf ../cmucl-$version-linux.extra.tar.bz2)
    
    16 16
       script:
    
    17
    -    - bin/build.sh $bootstrap -C "" -o snapshot/bin/lisp
    
    17
    +    - bin/build.sh $bootstrap -R -C "" -o snapshot/bin/lisp
    
    18 18
         - bin/make-dist.sh -I dist linux-4
    
    19 19
         - bin/run-tests.sh -l dist/bin/lisp 2>&1 | tee test.log
    
    20 20
         - cd ansi-test
    
    ... ... @@ -31,7 +31,7 @@ osx-runner:
    31 31
         - mkdir snapshot
    
    32 32
         - (cd snapshot; tar xjf ../cmucl-$version-darwin.tar.bz2)
    
    33 33
       script:
    
    34
    -    - bin/build.sh $bootstrap -C "" -o snapshot/bin/lisp
    
    34
    +    - bin/build.sh $bootstrap -R -C "" -o snapshot/bin/lisp
    
    35 35
         - bin/make-dist.sh -I dist darwin-4
    
    36 36
         - bin/run-tests.sh -l dist/bin/lisp 2>&1 | tee test.log
    
    37 37
         - cd ansi-test
    

  • src/code/unix-glibc2.lisp deleted
    1
    -;;; -*- Package: UNIX -*-
    
    2
    -;;;
    
    3
    -;;; **********************************************************************
    
    4
    -;;; This code was written as part of the CMU Common Lisp project at
    
    5
    -;;; Carnegie Mellon University, and has been placed in the public domain.
    
    6
    -;;;
    
    7
    -(ext:file-comment
    
    8
    -  "$Header: src/code/unix-glibc2.lisp $")
    
    9
    -;;;
    
    10
    -;;; **********************************************************************
    
    11
    -;;;
    
    12
    -;;; This file contains the UNIX low-level support for glibc2.  Based
    
    13
    -;;; on unix.lisp 1.56, converted for glibc2 by Peter Van Eynde (1998).
    
    14
    -;;; Alpha support by Julian Dolby, 1999.
    
    15
    -;;;
    
    16
    -;;; All the functions with #+(or) in front are work in progress,
    
    17
    -;;; and mostly don't work.
    
    18
    -;;;
    
    19
    -;; Todo: #+(or)'ed stuff and ioctl's
    
    20
    -;;
    
    21
    -;;
    
    22
    -;; Large File Support (LFS) added by Pierre Mai and Eric Marsden, Feb
    
    23
    -;; 2003. This is necessary to be able to read/write/stat files that
    
    24
    -;; are larger than 2GB on a 32-bit system. From a C program, defining
    
    25
    -;; a preprocessor macro _LARGEFILE64_SOURCE makes the preproccessor
    
    26
    -;; replace a call to open() by open64(), and similarly for stat,
    
    27
    -;; fstat, lstat, lseek, readdir and friends. Furthermore, certain data
    
    28
    -;; types, that are normally 32 bits wide, are replaced by 64-bit wide
    
    29
    -;; equivalents: off_t -> off64_t etc. The libc.so fiddles around with
    
    30
    -;; weak symbols to support this mess.
    
    31
    -;;
    
    32
    -;; >From CMUCL, we make FFI calls to the xxx64 functions, and use the
    
    33
    -;; 64-bit wide versions of the data structures. The most ugly aspect
    
    34
    -;; is that some of the stat functions are not available via dlsym, so
    
    35
    -;; we reference them explicitly from linux-stubs.S. Another amusing
    
    36
    -;; fact is that on glibc 2.2, stat64() returns a struct stat with a
    
    37
    -;; 32-bit ino_t, whereas readdir64() returns a struct dirent that
    
    38
    -;; contains a 64-bit ino_t.  On glibc 2.1, OTOH, both stat64 and
    
    39
    -;; readdir64 use structs with 32-bit ino_t.
    
    40
    -;;
    
    41
    -;; The current version deals with this by going with the glibc 2.2
    
    42
    -;; definitions, unless the keyword :glibc2.1 also occurs on *features*,
    
    43
    -;; in addition to :glibc2, in which case we go with the glibc 2.1
    
    44
    -;; definitions.  Note that binaries compiled against glibc 2.1 do in
    
    45
    -;; fact work fine on glibc 2.2, because readdir64 is available in both
    
    46
    -;; glibc 2.1 and glibc 2.2 versions in glibc 2.2, disambiguated through
    
    47
    -;; ELF symbol versioning.  We use an entry for readdir64 in linux-stubs.S
    
    48
    -;; in order to force usage of the correct version of readdir64 at runtime.
    
    49
    -;;
    
    50
    -;; So in order to compile for glibc 2.2 and newer, just compile CMUCL
    
    51
    -;; on a glibc 2.2 system, and make sure that :glibc2.1 doesn't appear
    
    52
    -;; on the *features* list.  In order to compile for glibc 2.1 and newer,
    
    53
    -;; compile CMUCL on a glibc 2.1 system, and make sure that :glibc2.1 does
    
    54
    -;; appear on the *features* list.
    
    55
    -
    
    56
    -(in-package "UNIX")
    
    57
    -(use-package "ALIEN")
    
    58
    -(use-package "C-CALL")
    
    59
    -(use-package "SYSTEM")
    
    60
    -(use-package "EXT")
    
    61
    -(intl:textdomain "cmucl-unix-glibc2")
    
    62
    -
    
    63
    -;; Check the G_BROKEN_FILENAMES environment variable; if set the encoding
    
    64
    -;; is locale-dependent...else use :utf-8 on Unicode Lisps.  On 8 bit Lisps
    
    65
    -;; it must be set to :iso8859-1 (or left as NIL), making files with
    
    66
    -;; non-Latin-1 characters "mojibake", but otherwise they'll be inaccessible.
    
    67
    -;; Must be set to NIL initially to enable building Lisp!
    
    68
    -(defvar *filename-encoding* nil)
    
    69
    -
    
    70
    -(pushnew :unix *features*)
    
    71
    -(pushnew :glibc2 *features*)
    
    72
    -
    
    73
    -;; needed for bootstrap
    
    74
    -(eval-when (:compile-toplevel :load-toplevel :execute)
    
    75
    -  (defmacro %name->file (string)
    
    76
    -    `(if *filename-encoding*
    
    77
    -	 (string-encode ,string *filename-encoding*)
    
    78
    -	 ,string))
    
    79
    -  (defmacro %file->name (string)
    
    80
    -    `(if *filename-encoding*
    
    81
    -	 (string-decode ,string *filename-encoding*)
    
    82
    -	 ,string)))
    
    83
    -
    
    84
    -(defconstant +max-u-long+ 4294967295)
    
    85
    -
    
    86
    -(def-alien-type size-t #-alpha unsigned-int #+alpha long)
    
    87
    -(def-alien-type time-t long)
    
    88
    -
    
    89
    -(def-alien-type uquad-t #+alpha unsigned-long
    
    90
    -		#-alpha (array unsigned-long 2))
    
    91
    -(def-alien-type u-int32-t unsigned-int)
    
    92
    -(def-alien-type int64-t (signed 64))
    
    93
    -(def-alien-type u-int64-t (unsigned 64))
    
    94
    -
    
    95
    -(def-alien-type dev-t #-amd64 uquad-t #+amd64 u-int64-t)
    
    96
    -(def-alien-type uid-t unsigned-int)
    
    97
    -(def-alien-type gid-t unsigned-int)
    
    98
    -(def-alien-type ino-t #-amd64 u-int32-t #+amd64 u-int64-t)
    
    99
    -(def-alien-type ino64-t u-int64-t)
    
    100
    -(def-alien-type mode-t u-int32-t)
    
    101
    -(def-alien-type nlink-t #-amd64 unsigned-int #+amd64 u-int64-t)
    
    102
    -(def-alien-type off-t int64-t)
    
    103
    -(def-alien-type blkcnt-t u-int64-t)
    
    104
    -
    
    105
    -;;;; Common machine independent structures.
    
    106
    -
    
    107
    -
    
    108
    -;; Needed early in bootstrap.
    
    109
    -(defun unix-current-directory ()
    
    110
    -  _N"Put the absolute pathname of the current working directory in BUF.
    
    111
    -   If successful, return BUF.  If not, put an error message in
    
    112
    -   BUF and return NULL.  BUF should be at least PATH_MAX bytes long."
    
    113
    -  ;; 5120 is some randomly selected maximum size for the buffer for getcwd.
    
    114
    -  (with-alien ((buf (array c-call:char 5120)))
    
    115
    -    (let ((result (alien-funcall
    
    116
    -		    (extern-alien "getcwd"
    
    117
    -				  (function (* c-call:char)
    
    118
    -					    (* c-call:char) c-call:int))
    
    119
    -		    (cast buf (* c-call:char))
    
    120
    -		    5120)))
    
    121
    -      
    
    122
    -      (values (not (zerop (sap-int (alien-sap result))))
    
    123
    -	      (%file->name (cast buf c-call:c-string))))))
    
    124
    -
    
    125
    -;;; fcntlbits.h
    
    126
    -(defconstant o_read    o_rdonly _N"Open for reading")
    
    127
    -(defconstant o_write   o_wronly _N"Open for writing")
    
    128
    -
    
    129
    -(defconstant o_rdonly  0 _N"Read-only flag.") 
    
    130
    -(defconstant o_wronly  1 _N"Write-only flag.")
    
    131
    -(defconstant o_rdwr    2 _N"Read-write flag.")
    
    132
    -(defconstant o_accmode 3 _N"Access mode mask.")
    
    133
    -
    
    134
    -#-alpha
    
    135
    -(progn
    
    136
    -  (defconstant o_creat   #o100 _N"Create if nonexistant flag. (not fcntl)") 
    
    137
    -  (defconstant o_excl    #o200 _N"Error if already exists. (not fcntl)")
    
    138
    -  (defconstant o_noctty  #o400 _N"Don't assign controlling tty. (not fcntl)")
    
    139
    -  (defconstant o_trunc   #o1000 _N"Truncate flag. (not fcntl)")
    
    140
    -  (defconstant o_append  #o2000 _N"Append flag.")
    
    141
    -  (defconstant o_ndelay  #o4000 _N"Non-blocking I/O")
    
    142
    -  (defconstant o_nonblock #o4000 _N"Non-blocking I/O")
    
    143
    -  (defconstant o_ndelay  o_nonblock)
    
    144
    -  (defconstant o_sync    #o10000 _N"Synchronous writes (on ext2)")
    
    145
    -  (defconstant o_fsync    o_sync)
    
    146
    -  (defconstant o_async   #o20000 _N"Asynchronous I/O"))
    
    147
    -#+alpha
    
    148
    -(progn
    
    149
    -  (defconstant o_creat   #o1000 _N"Create if nonexistant flag. (not fcntl)") 
    
    150
    -  (defconstant o_trunc   #o2000 _N"Truncate flag. (not fcntl)")
    
    151
    -  (defconstant o_excl    #o4000 _N"Error if already exists. (not fcntl)")
    
    152
    -  (defconstant o_noctty  #o10000 _N"Don't assign controlling tty. (not fcntl)")
    
    153
    -  (defconstant o_nonblock #o4 _N"Non-blocking I/O")
    
    154
    -  (defconstant o_append  #o10 _N"Append flag.")
    
    155
    -  (defconstant o_ndelay  o_nonblock)
    
    156
    -  (defconstant o_sync    #o40000 _N"Synchronous writes (on ext2)")
    
    157
    -  (defconstant o_fsync    o_sync)
    
    158
    -  (defconstant o_async   #o20000 _N"Asynchronous I/O"))
    
    159
    -
    
    160
    -#-alpha
    
    161
    -(progn
    
    162
    -  (defconstant f-getlk    5   _N"Get lock")
    
    163
    -  (defconstant f-setlk    6   _N"Set lock")
    
    164
    -  (defconstant f-setlkw   7   _N"Set lock, wait for release")
    
    165
    -  (defconstant f-setown   8  _N"Set owner (for sockets)")
    
    166
    -  (defconstant f-getown   9  _N"Get owner (for sockets)"))
    
    167
    -#+alpha
    
    168
    -(progn
    
    169
    -  (defconstant f-getlk    7   _N"Get lock")
    
    170
    -  (defconstant f-setlk    8   _N"Set lock")
    
    171
    -  (defconstant f-setlkw   9   _N"Set lock, wait for release")
    
    172
    -  (defconstant f-setown   5  _N"Set owner (for sockets)")
    
    173
    -  (defconstant f-getown   6  _N"Get owner (for sockets)"))
    
    174
    -
    
    175
    -(defconstant F-CLOEXEC 1 _N"for f-getfl and f-setfl")
    
    176
    -(defun unix-open (path flags mode)
    
    177
    -  _N"Unix-open opens the file whose pathname is specified by PATH
    
    178
    -   for reading and/or writing as specified by the FLAGS argument.
    
    179
    -   Returns an integer file descriptor.
    
    180
    -   The flags argument can be:
    
    181
    -
    
    182
    -     o_rdonly        Read-only flag.
    
    183
    -     o_wronly        Write-only flag.
    
    184
    -     o_rdwr          Read-and-write flag.
    
    185
    -     o_append        Append flag.
    
    186
    -     o_creat         Create-if-nonexistant flag.
    
    187
    -     o_trunc         Truncate-to-size-0 flag.
    
    188
    -     o_excl          Error if the file already exists
    
    189
    -     o_noctty        Don't assign controlling tty
    
    190
    -     o_ndelay        Non-blocking I/O
    
    191
    -     o_sync          Synchronous I/O
    
    192
    -     o_async         Asynchronous I/O
    
    193
    -
    
    194
    -   If the o_creat flag is specified, then the file is created with
    
    195
    -   a permission of argument MODE if the file doesn't exist."
    
    196
    -  (declare (type unix-pathname path)
    
    197
    -	   (type fixnum flags)
    
    198
    -	   (type unix-file-mode mode))
    
    199
    -  (int-syscall ("open64" c-string int int) (%name->file path) flags mode))
    
    200
    -
    
    201
    -;;; asm/errno.h
    
    202
    -(eval-when (compile eval)
    
    203
    -
    
    204
    -(defparameter *compiler-unix-errors* nil)
    
    205
    -
    
    206
    -(defmacro def-unix-error (name number description)
    
    207
    -  `(progn
    
    208
    -     (eval-when (compile eval)
    
    209
    -       (push (cons ,number ,description) *compiler-unix-errors*))
    
    210
    -     (defconstant ,name ,number ,description)
    
    211
    -     (export ',name)))
    
    212
    -
    
    213
    -(defmacro emit-unix-errors ()
    
    214
    -  (let* ((max (apply #'max (mapcar #'car *compiler-unix-errors*)))
    
    215
    -	 (array (make-array (1+ max) :initial-element nil)))
    
    216
    -    (dolist (error *compiler-unix-errors*)
    
    217
    -      (setf (svref array (car error)) (cdr error)))
    
    218
    -    `(progn
    
    219
    -       (defvar *unix-errors* ',array)
    
    220
    -       (declaim (simple-vector *unix-errors*)))))
    
    221
    -
    
    222
    -)
    
    223
    -
    
    224
    -(def-unix-error ESUCCESS 0 _N"Successful")
    
    225
    -(def-unix-error EPERM 1 _N"Operation not permitted")
    
    226
    -(def-unix-error ENOENT 2 _N"No such file or directory")
    
    227
    -(def-unix-error ESRCH 3 _N"No such process")
    
    228
    -(def-unix-error EINTR 4 _N"Interrupted system call")
    
    229
    -(def-unix-error EIO 5 _N"I/O error")
    
    230
    -(def-unix-error ENXIO 6 _N"No such device or address")
    
    231
    -(def-unix-error E2BIG 7 _N"Arg list too long")
    
    232
    -(def-unix-error ENOEXEC 8 _N"Exec format error")
    
    233
    -(def-unix-error EBADF 9 _N"Bad file number")
    
    234
    -(def-unix-error ECHILD 10 _N"No children")
    
    235
    -(def-unix-error EAGAIN 11 _N"Try again")
    
    236
    -(def-unix-error ENOMEM 12 _N"Out of memory")
    
    237
    -(def-unix-error EACCES 13 _N"Permission denied")
    
    238
    -(def-unix-error EFAULT 14 _N"Bad address")
    
    239
    -(def-unix-error ENOTBLK 15 _N"Block device required")
    
    240
    -(def-unix-error EBUSY 16 _N"Device or resource busy")
    
    241
    -(def-unix-error EEXIST 17 _N"File exists")
    
    242
    -(def-unix-error EXDEV 18 _N"Cross-device link")
    
    243
    -(def-unix-error ENODEV 19 _N"No such device")
    
    244
    -(def-unix-error ENOTDIR 20 _N"Not a director")
    
    245
    -(def-unix-error EISDIR 21 _N"Is a directory")
    
    246
    -(def-unix-error EINVAL 22 _N"Invalid argument")
    
    247
    -(def-unix-error ENFILE 23 _N"File table overflow")
    
    248
    -(def-unix-error EMFILE 24 _N"Too many open files")
    
    249
    -(def-unix-error ENOTTY 25 _N"Not a typewriter")
    
    250
    -(def-unix-error ETXTBSY 26 _N"Text file busy")
    
    251
    -(def-unix-error EFBIG 27 _N"File too large")
    
    252
    -(def-unix-error ENOSPC 28 _N"No space left on device")
    
    253
    -(def-unix-error ESPIPE 29 _N"Illegal seek")
    
    254
    -(def-unix-error EROFS 30 _N"Read-only file system")
    
    255
    -(def-unix-error EMLINK 31 _N"Too many links")
    
    256
    -(def-unix-error EPIPE 32 _N"Broken pipe")
    
    257
    -;;; 
    
    258
    -;;; Math
    
    259
    -(def-unix-error EDOM 33 _N"Math argument out of domain")
    
    260
    -(def-unix-error ERANGE 34 _N"Math result not representable")
    
    261
    -;;; 
    
    262
    -(def-unix-error  EDEADLK         35     _N"Resource deadlock would occur")
    
    263
    -(def-unix-error  ENAMETOOLONG    36     _N"File name too long")
    
    264
    -(def-unix-error  ENOLCK          37     _N"No record locks available")
    
    265
    -(def-unix-error  ENOSYS          38     _N"Function not implemented")
    
    266
    -(def-unix-error  ENOTEMPTY       39     _N"Directory not empty")
    
    267
    -(def-unix-error  ELOOP           40     _N"Too many symbolic links encountered")
    
    268
    -(def-unix-error  EWOULDBLOCK     11     _N"Operation would block")
    
    269
    -(def-unix-error  ENOMSG          42     _N"No message of desired type")
    
    270
    -(def-unix-error  EIDRM           43     _N"Identifier removed")
    
    271
    -(def-unix-error  ECHRNG          44     _N"Channel number out of range")
    
    272
    -(def-unix-error  EL2NSYNC        45     _N"Level 2 not synchronized")
    
    273
    -(def-unix-error  EL3HLT          46     _N"Level 3 halted")
    
    274
    -(def-unix-error  EL3RST          47     _N"Level 3 reset")
    
    275
    -(def-unix-error  ELNRNG          48     _N"Link number out of range")
    
    276
    -(def-unix-error  EUNATCH         49     _N"Protocol driver not attached")
    
    277
    -(def-unix-error  ENOCSI          50     _N"No CSI structure available")
    
    278
    -(def-unix-error  EL2HLT          51     _N"Level 2 halted")
    
    279
    -(def-unix-error  EBADE           52     _N"Invalid exchange")
    
    280
    -(def-unix-error  EBADR           53     _N"Invalid request descriptor")
    
    281
    -(def-unix-error  EXFULL          54     _N"Exchange full")
    
    282
    -(def-unix-error  ENOANO          55     _N"No anode")
    
    283
    -(def-unix-error  EBADRQC         56     _N"Invalid request code")
    
    284
    -(def-unix-error  EBADSLT         57     _N"Invalid slot")
    
    285
    -(def-unix-error  EDEADLOCK       EDEADLK     _N"File locking deadlock error")
    
    286
    -(def-unix-error  EBFONT          59     _N"Bad font file format")
    
    287
    -(def-unix-error  ENOSTR          60     _N"Device not a stream")
    
    288
    -(def-unix-error  ENODATA         61     _N"No data available")
    
    289
    -(def-unix-error  ETIME           62     _N"Timer expired")
    
    290
    -(def-unix-error  ENOSR           63     _N"Out of streams resources")
    
    291
    -(def-unix-error  ENONET          64     _N"Machine is not on the network")
    
    292
    -(def-unix-error  ENOPKG          65     _N"Package not installed")
    
    293
    -(def-unix-error  EREMOTE         66     _N"Object is remote")
    
    294
    -(def-unix-error  ENOLINK         67     _N"Link has been severed")
    
    295
    -(def-unix-error  EADV            68     _N"Advertise error")
    
    296
    -(def-unix-error  ESRMNT          69     _N"Srmount error")
    
    297
    -(def-unix-error  ECOMM           70     _N"Communication error on send")
    
    298
    -(def-unix-error  EPROTO          71     _N"Protocol error")
    
    299
    -(def-unix-error  EMULTIHOP       72     _N"Multihop attempted")
    
    300
    -(def-unix-error  EDOTDOT         73     _N"RFS specific error")
    
    301
    -(def-unix-error  EBADMSG         74     _N"Not a data message")
    
    302
    -(def-unix-error  EOVERFLOW       75     _N"Value too large for defined data type")
    
    303
    -(def-unix-error  ENOTUNIQ        76     _N"Name not unique on network")
    
    304
    -(def-unix-error  EBADFD          77     _N"File descriptor in bad state")
    
    305
    -(def-unix-error  EREMCHG         78     _N"Remote address changed")
    
    306
    -(def-unix-error  ELIBACC         79     _N"Can not access a needed shared library")
    
    307
    -(def-unix-error  ELIBBAD         80     _N"Accessing a corrupted shared library")
    
    308
    -(def-unix-error  ELIBSCN         81     _N".lib section in a.out corrupted")
    
    309
    -(def-unix-error  ELIBMAX         82     _N"Attempting to link in too many shared libraries")
    
    310
    -(def-unix-error  ELIBEXEC        83     _N"Cannot exec a shared library directly")
    
    311
    -(def-unix-error  EILSEQ          84     _N"Illegal byte sequence")
    
    312
    -(def-unix-error  ERESTART        85     _N"Interrupted system call should be restarted _N")
    
    313
    -(def-unix-error  ESTRPIPE        86     _N"Streams pipe error")
    
    314
    -(def-unix-error  EUSERS          87     _N"Too many users")
    
    315
    -(def-unix-error  ENOTSOCK        88     _N"Socket operation on non-socket")
    
    316
    -(def-unix-error  EDESTADDRREQ    89     _N"Destination address required")
    
    317
    -(def-unix-error  EMSGSIZE        90     _N"Message too long")
    
    318
    -(def-unix-error  EPROTOTYPE      91     _N"Protocol wrong type for socket")
    
    319
    -(def-unix-error  ENOPROTOOPT     92     _N"Protocol not available")
    
    320
    -(def-unix-error  EPROTONOSUPPORT 93     _N"Protocol not supported")
    
    321
    -(def-unix-error  ESOCKTNOSUPPORT 94     _N"Socket type not supported")
    
    322
    -(def-unix-error  EOPNOTSUPP      95     _N"Operation not supported on transport endpoint")
    
    323
    -(def-unix-error  EPFNOSUPPORT    96     _N"Protocol family not supported")
    
    324
    -(def-unix-error  EAFNOSUPPORT    97     _N"Address family not supported by protocol")
    
    325
    -(def-unix-error  EADDRINUSE      98     _N"Address already in use")
    
    326
    -(def-unix-error  EADDRNOTAVAIL   99     _N"Cannot assign requested address")
    
    327
    -(def-unix-error  ENETDOWN        100    _N"Network is down")
    
    328
    -(def-unix-error  ENETUNREACH     101    _N"Network is unreachable")
    
    329
    -(def-unix-error  ENETRESET       102    _N"Network dropped connection because of reset")
    
    330
    -(def-unix-error  ECONNABORTED    103    _N"Software caused connection abort")
    
    331
    -(def-unix-error  ECONNRESET      104    _N"Connection reset by peer")
    
    332
    -(def-unix-error  ENOBUFS         105    _N"No buffer space available")
    
    333
    -(def-unix-error  EISCONN         106    _N"Transport endpoint is already connected")
    
    334
    -(def-unix-error  ENOTCONN        107    _N"Transport endpoint is not connected")
    
    335
    -(def-unix-error  ESHUTDOWN       108    _N"Cannot send after transport endpoint shutdown")
    
    336
    -(def-unix-error  ETOOMANYREFS    109    _N"Too many references: cannot splice")
    
    337
    -(def-unix-error  ETIMEDOUT       110    _N"Connection timed out")
    
    338
    -(def-unix-error  ECONNREFUSED    111    _N"Connection refused")
    
    339
    -(def-unix-error  EHOSTDOWN       112    _N"Host is down")
    
    340
    -(def-unix-error  EHOSTUNREACH    113    _N"No route to host")
    
    341
    -(def-unix-error  EALREADY        114    _N"Operation already in progress")
    
    342
    -(def-unix-error  EINPROGRESS     115    _N"Operation now in progress")
    
    343
    -(def-unix-error  ESTALE          116    _N"Stale NFS file handle")
    
    344
    -(def-unix-error  EUCLEAN         117    _N"Structure needs cleaning")
    
    345
    -(def-unix-error  ENOTNAM         118    _N"Not a XENIX named type file")
    
    346
    -(def-unix-error  ENAVAIL         119    _N"No XENIX semaphores available")
    
    347
    -(def-unix-error  EISNAM          120    _N"Is a named type file")
    
    348
    -(def-unix-error  EREMOTEIO       121    _N"Remote I/O error")
    
    349
    -(def-unix-error  EDQUOT          122    _N"Quota exceeded")
    
    350
    -
    
    351
    -;;; And now for something completely different ...
    
    352
    -(emit-unix-errors)
    
    353
    -
    
    354
    -(def-alien-type nil
    
    355
    -    (struct passwd
    
    356
    -	    (pw-name (* char))          ; user's login name
    
    357
    -	    (pw-passwd (* char))        ; no longer used
    
    358
    -	    (pw-uid uid-t)              ; user id
    
    359
    -	    (pw-gid gid-t)              ; group id
    
    360
    -	    (pw-gecos (* char))         ; typically user's full name
    
    361
    -	    (pw-dir (* char))           ; user's home directory
    
    362
    -	    (pw-shell (* char))))       ; user's login shell
    
    363
    -
    
    364
    -;;;; System calls.
    
    365
    -
    
    366
    -(def-alien-routine ("os_get_errno" unix-get-errno) int)
    
    367
    -(def-alien-routine ("os_set_errno" unix-set-errno) int (newvalue int))
    
    368
    -(defun unix-errno () (unix-get-errno))
    
    369
    -(defun (setf unix-errno) (newvalue) (unix-set-errno newvalue))
    
    370
    -
    
    371
    -;;; GET-UNIX-ERROR-MSG -- public.
    
    372
    -;;; 
    
    373
    -(defun get-unix-error-msg (&optional (error-number (unix-errno)))
    
    374
    -  _N"Returns a string describing the error number which was returned by a
    
    375
    -  UNIX system call."
    
    376
    -  (declare (type integer error-number))
    
    377
    -  
    
    378
    -  (if (array-in-bounds-p *unix-errors* error-number)
    
    379
    -      (svref *unix-errors* error-number)
    
    380
    -      (format nil (intl:gettext "Unknown error [~d]") error-number)))
    
    381
    -
    
    382
    -(defmacro syscall ((name &rest arg-types) success-form &rest args)
    
    383
    -  `(let ((result (alien-funcall (extern-alien ,name (function int ,@arg-types))
    
    384
    -				,@args)))
    
    385
    -     (if (minusp result)
    
    386
    -	 (values nil (unix-errno))
    
    387
    -	 ,success-form)))
    
    388
    -
    
    389
    -;;; Like syscall, but if it fails, signal an error instead of returning error
    
    390
    -;;; codes.  Should only be used for syscalls that will never really get an
    
    391
    -;;; error.
    
    392
    -;;;
    
    393
    -(defmacro syscall* ((name &rest arg-types) success-form &rest args)
    
    394
    -  `(let ((result (alien-funcall (extern-alien ,name (function int ,@arg-types))
    
    395
    -				,@args)))
    
    396
    -     (if (minusp result)
    
    397
    -	 (error (intl:gettext "Syscall ~A failed: ~A") ,name (get-unix-error-msg))
    
    398
    -	 ,success-form)))
    
    399
    -
    
    400
    -(defmacro void-syscall ((name &rest arg-types) &rest args)
    
    401
    -  `(syscall (,name ,@arg-types) (values t 0) ,@args))
    
    402
    -
    
    403
    -(defmacro int-syscall ((name &rest arg-types) &rest args)
    
    404
    -  `(syscall (,name ,@arg-types) (values result 0) ,@args))
    
    405
    -
    
    406
    -;;; Unix-write accepts a file descriptor, a buffer, an offset, and the
    
    407
    -;;; length to write.  It attempts to write len bytes to the device
    
    408
    -;;; associated with fd from the the buffer starting at offset.  It returns
    
    409
    -;;; the actual number of bytes written.
    
    410
    -
    
    411
    -(defun unix-write (fd buf offset len)
    
    412
    -  _N"Unix-write attempts to write a character buffer (buf) of length
    
    413
    -   len to the file described by the file descriptor fd.  NIL and an
    
    414
    -   error is returned if the call is unsuccessful."
    
    415
    -  (declare (type unix-fd fd)
    
    416
    -	   (type (unsigned-byte 32) offset len))
    
    417
    -  (int-syscall ("write" int (* char) int)
    
    418
    -	       fd
    
    419
    -	       (with-alien ((ptr (* char) (etypecase buf
    
    420
    -					    ((simple-array * (*))
    
    421
    -					     (vector-sap buf))
    
    422
    -					    (system-area-pointer
    
    423
    -					     buf))))
    
    424
    -		 (addr (deref ptr offset)))
    
    425
    -	       len))
    
    426
    -
    
    427
    -(defun unix-pipe ()
    
    428
    -  _N"Unix-pipe sets up a unix-piping mechanism consisting of
    
    429
    -  an input pipe and an output pipe.  Unix-Pipe returns two
    
    430
    -  values: if no error occurred the first value is the pipe
    
    431
    -  to be read from and the second is can be written to.  If
    
    432
    -  an error occurred the first value is NIL and the second
    
    433
    -  the unix error code."
    
    434
    -  (with-alien ((fds (array int 2)))
    
    435
    -    (syscall ("pipe" (* int))
    
    436
    -	     (values (deref fds 0) (deref fds 1))
    
    437
    -	     (cast fds (* int)))))
    
    438
    -
    
    439
    -;;; UNIX-READ accepts a file descriptor, a buffer, and the length to read.
    
    440
    -;;; It attempts to read len bytes from the device associated with fd
    
    441
    -;;; and store them into the buffer.  It returns the actual number of
    
    442
    -;;; bytes read.
    
    443
    -
    
    444
    -(defun unix-read (fd buf len)
    
    445
    -  _N"UNIX-READ attempts to read from the file described by fd into
    
    446
    -   the buffer buf until it is full.  Len is the length of the buffer.
    
    447
    -   The number of bytes actually read is returned or NIL and an error
    
    448
    -   number if an error occured."
    
    449
    -  (declare (type unix-fd fd)
    
    450
    -	   (type (unsigned-byte 32) len))
    
    451
    -  #+gencgc
    
    452
    -  ;; With gencgc, the collector tries to keep raw objects like strings
    
    453
    -  ;; in separate pages that are not write-protected.  However, this
    
    454
    -  ;; isn't always true.  Thus, BUF will sometimes be write-protected
    
    455
    -  ;; and the kernel doesn't like writing to write-protected pages.  So
    
    456
    -  ;; go through and touch each page to give the segv handler a chance
    
    457
    -  ;; to unprotect the pages.  (This is taken from unix.lisp.)
    
    458
    -  (without-gcing
    
    459
    -   (let* ((page-size (get-page-size))
    
    460
    -	  (1-page-size (1- page-size))
    
    461
    -	  (sap (etypecase buf
    
    462
    -		 (system-area-pointer buf)
    
    463
    -		 (vector (vector-sap buf))))
    
    464
    -	  (end (sap+ sap len)))
    
    465
    -     (declare (type (and fixnum unsigned-byte) page-size 1-page-size)
    
    466
    -	      (type system-area-pointer sap end)
    
    467
    -	      (optimize (speed 3) (safety 0)))
    
    468
    -     ;; Touch the beginning of every page
    
    469
    -     (do ((sap (int-sap (logand (sap-int sap)
    
    470
    -				(logxor 1-page-size (ldb (byte 32 0) -1))))
    
    471
    -	       (sap+ sap page-size)))
    
    472
    -	 ((sap>= sap end))
    
    473
    -       (declare (type system-area-pointer sap))
    
    474
    -       (setf (sap-ref-8 sap 0) (sap-ref-8 sap 0)))))
    
    475
    -  (int-syscall ("read" int (* char) int) fd buf len))
    
    476
    -
    
    477
    -;;; Unix-getpagesize returns the number of bytes in the system page.
    
    478
    -
    
    479
    -(defun unix-getpagesize ()
    
    480
    -  _N"Unix-getpagesize returns the number of bytes in a system page."
    
    481
    -  (int-syscall ("getpagesize")))
    
    482
    -
    
    483
    -;;; sys/stat.h
    
    484
    -
    
    485
    -(defmacro extract-stat-results (buf)
    
    486
    -  `(values T
    
    487
    -           #+(or alpha amd64)
    
    488
    -	   (slot ,buf 'st-dev)
    
    489
    -           #-(or alpha amd64)
    
    490
    -           (+ (deref (slot ,buf 'st-dev) 0)
    
    491
    -	      (* (+ +max-u-long+  1)
    
    492
    -	         (deref (slot ,buf 'st-dev) 1)))   ;;; let's hope this works..
    
    493
    -	   (slot ,buf 'st-ino)
    
    494
    -	   (slot ,buf 'st-mode)
    
    495
    -	   (slot ,buf 'st-nlink)
    
    496
    -	   (slot ,buf 'st-uid)
    
    497
    -	   (slot ,buf 'st-gid)
    
    498
    -           #+(or alpha amd64)
    
    499
    -	   (slot ,buf 'st-rdev)
    
    500
    -           #-(or alpha amd64)
    
    501
    -           (+ (deref (slot ,buf 'st-rdev) 0)
    
    502
    -	      (* (+ +max-u-long+  1)
    
    503
    -	         (deref (slot ,buf 'st-rdev) 1)))   ;;; let's hope this works..
    
    504
    -	   (slot ,buf 'st-size)
    
    505
    -	   (slot ,buf 'st-atime)
    
    506
    -	   (slot ,buf 'st-mtime)
    
    507
    -	   (slot ,buf 'st-ctime)
    
    508
    -	   (slot ,buf 'st-blksize)
    
    509
    -	   (slot ,buf 'st-blocks)))
    
    510
    -
    
    511
    -;;; bits/stat.h
    
    512
    -
    
    513
    -(def-alien-type nil
    
    514
    -  (struct stat
    
    515
    -    (st-dev dev-t)
    
    516
    -    #-(or alpha amd64) (st-pad1 unsigned-short)
    
    517
    -    (st-ino ino-t)
    
    518
    -    #+alpha (st-pad1 unsigned-int)
    
    519
    -    #-amd64 (st-mode mode-t)
    
    520
    -    (st-nlink  nlink-t)
    
    521
    -    #+amd64 (st-mode mode-t)
    
    522
    -    (st-uid  uid-t)
    
    523
    -    (st-gid  gid-t)
    
    524
    -    (st-rdev dev-t)
    
    525
    -    #-alpha (st-pad2  unsigned-short)
    
    526
    -    (st-size off-t)
    
    527
    -    #-alpha (st-blksize unsigned-long)
    
    528
    -    #-alpha (st-blocks blkcnt-t)
    
    529
    -    (st-atime time-t)
    
    530
    -    #-alpha (unused-1 unsigned-long)
    
    531
    -    (st-mtime time-t)
    
    532
    -    #-alpha (unused-2 unsigned-long)
    
    533
    -    (st-ctime time-t)
    
    534
    -    #+alpha (st-blocks int)
    
    535
    -    #+alpha (st-pad2 unsigned-int)
    
    536
    -    #+alpha (st-blksize unsigned-int)
    
    537
    -    #+alpha (st-flags unsigned-int)
    
    538
    -    #+alpha (st-gen unsigned-int)
    
    539
    -    #+alpha (st-pad3 unsigned-int)
    
    540
    -    #+alpha (unused-1 unsigned-long)
    
    541
    -    #+alpha (unused-2 unsigned-long)
    
    542
    -    (unused-3 unsigned-long)
    
    543
    -    (unused-4 unsigned-long)
    
    544
    -    #-alpha (unused-5 unsigned-long)))
    
    545
    -
    
    546
    -(defun unix-stat (name)
    
    547
    -  _N"UNIX-STAT retrieves information about the specified
    
    548
    -   file returning them in the form of multiple values.
    
    549
    -   See the UNIX Programmer's Manual for a description
    
    550
    -   of the values returned.  If the call fails, then NIL
    
    551
    -   and an error number is returned instead."
    
    552
    -  (declare (type unix-pathname name))
    
    553
    -  (when (string= name "")
    
    554
    -    (setf name "."))
    
    555
    -  (with-alien ((buf (struct stat)))
    
    556
    -    (syscall ("stat64" c-string (* (struct stat)))
    
    557
    -	     (extract-stat-results buf)
    
    558
    -	     (%name->file name) (addr buf))))
    
    559
    -
    
    560
    -(defun unix-fstat (fd)
    
    561
    -  _N"UNIX-FSTAT is similar to UNIX-STAT except the file is specified
    
    562
    -   by the file descriptor FD."
    
    563
    -  (declare (type unix-fd fd))
    
    564
    -  (with-alien ((buf (struct stat)))
    
    565
    -    (syscall ("fstat64" int (* (struct stat)))
    
    566
    -	     (extract-stat-results buf)
    
    567
    -	     fd (addr buf))))
    
    568
    -
    
    569
    -(defun unix-lstat (name)
    
    570
    -  _N"UNIX-LSTAT is similar to UNIX-STAT except the specified
    
    571
    -   file must be a symbolic link."
    
    572
    -  (declare (type unix-pathname name))
    
    573
    -  (with-alien ((buf (struct stat)))
    
    574
    -    (syscall ("lstat64" c-string (* (struct stat)))
    
    575
    -	     (extract-stat-results buf)
    
    576
    -	     (%name->file name) (addr buf))))
    
    577
    -
    
    578
    -;; Encoding of the file mode.
    
    579
    -
    
    580
    -(defconstant s-ifmt   #o0170000 _N"These bits determine file type.")
    
    581
    -
    
    582
    -;; File types.
    
    583
    -
    
    584
    -(defconstant s-ififo  #o0010000 _N"FIFO")
    
    585
    -(defconstant s-ifchr  #o0020000 _N"Character device")
    
    586
    -(defconstant s-ifdir  #o0040000 _N"Directory")
    
    587
    -(defconstant s-ifblk  #o0060000 _N"Block device")
    
    588
    -(defconstant s-ifreg  #o0100000 _N"Regular file")
    
    589
    -
    
    590
    -;; These don't actually exist on System V, but having them doesn't hurt.
    
    591
    -
    
    592
    -(defconstant s-iflnk  #o0120000 _N"Symbolic link.")
    
    593
    -(defconstant s-ifsock #o0140000 _N"Socket.")
    
    594
    -(defun unix-file-kind (name &optional check-for-links)
    
    595
    -  _N"Returns either :file, :directory, :link, :special, or NIL."
    
    596
    -  (declare (simple-string name))
    
    597
    -  (multiple-value-bind (res dev ino mode)
    
    598
    -		       (if check-for-links
    
    599
    -			   (unix-lstat name)
    
    600
    -			   (unix-stat name))
    
    601
    -    (declare (type (or fixnum null) mode)
    
    602
    -	     (ignore dev ino))
    
    603
    -    (when res
    
    604
    -      (let ((kind (logand mode s-ifmt)))
    
    605
    -	(cond ((eql kind s-ifdir) :directory)
    
    606
    -	      ((eql kind s-ifreg) :file)
    
    607
    -	      ((eql kind s-iflnk) :link)
    
    608
    -	      (t :special))))))
    
    609
    -
    
    610
    -(defun unix-maybe-prepend-current-directory (name)
    
    611
    -  (declare (simple-string name))
    
    612
    -  (if (and (> (length name) 0) (char= (schar name 0) #\/))
    
    613
    -      name
    
    614
    -      (multiple-value-bind (win dir) (unix-current-directory)
    
    615
    -	(if win
    
    616
    -	    (concatenate 'simple-string dir "/" name)
    
    617
    -	    name))))
    
    618
    -
    
    619
    -;; Values for the second argument to access.
    
    620
    -
    
    621
    -;;; Unix-access accepts a path and a mode.  It returns two values the
    
    622
    -;;; first is T if the file is accessible and NIL otherwise.  The second
    
    623
    -;;; only has meaning in the second case and is the unix errno value.
    
    624
    -
    
    625
    -(defun unix-access (path mode)
    
    626
    -  _N"Given a file path (a string) and one of four constant modes,
    
    627
    -   unix-access returns T if the file is accessible with that
    
    628
    -   mode and NIL if not.  It also returns an errno value with
    
    629
    -   NIL which determines why the file was not accessible.
    
    630
    -
    
    631
    -   The access modes are:
    
    632
    -	r_ok     Read permission.
    
    633
    -	w_ok     Write permission.
    
    634
    -	x_ok     Execute permission.
    
    635
    -	f_ok     Presence of file."
    
    636
    -  (declare (type unix-pathname path)
    
    637
    -	   (type (mod 8) mode))
    
    638
    -  (void-syscall ("access" c-string int) (%name->file path) mode))
    
    639
    -
    
    640
    -(defconstant l_set 0 _N"set the file pointer")
    
    641
    -(defconstant l_incr 1 _N"increment the file pointer")
    
    642
    -(defconstant l_xtnd 2 _N"extend the file size")
    
    643
    -
    
    644
    -(defun unix-lseek (fd offset whence)
    
    645
    -  _N"UNIX-LSEEK accepts a file descriptor and moves the file pointer ahead
    
    646
    -   a certain OFFSET for that file.  WHENCE can be any of the following:
    
    647
    -
    
    648
    -   l_set        Set the file pointer.
    
    649
    -   l_incr       Increment the file pointer.
    
    650
    -   l_xtnd       Extend the file size.
    
    651
    -  "
    
    652
    -  (declare (type unix-fd fd)
    
    653
    -	   (type (signed-byte 64) offset)
    
    654
    -	   (type (integer 0 2) whence))
    
    655
    -  (let ((result (alien-funcall
    
    656
    -                 (extern-alien "lseek64" (function off-t int off-t int))
    
    657
    -                 fd offset whence)))
    
    658
    -    (if (minusp result)
    
    659
    -        (values nil (unix-errno))
    
    660
    -        (values result 0))))
    
    661
    -;;; Unix-close accepts a file descriptor and attempts to close the file
    
    662
    -;;; associated with it.
    
    663
    -
    
    664
    -(defun unix-close (fd)
    
    665
    -  _N"Unix-close takes an integer file descriptor as an argument and
    
    666
    -   closes the file associated with it.  T is returned upon successful
    
    667
    -   completion, otherwise NIL and an error number."
    
    668
    -  (declare (type unix-fd fd))
    
    669
    -  (void-syscall ("close" int) fd))
    
    670
    -
    
    671
    -;;; Unix-creat accepts a file name and a mode.  It creates a new file
    
    672
    -;;; with name and sets it mode to mode (as for chmod).
    
    673
    -
    
    674
    -(defun unix-creat (name mode)
    
    675
    -  _N"Unix-creat accepts a file name and a mode (same as those for
    
    676
    -   unix-chmod) and creates a file by that name with the specified
    
    677
    -   permission mode.  It returns a file descriptor on success,
    
    678
    -   or NIL and an error  number otherwise.
    
    679
    -
    
    680
    -   This interface is made obsolete by UNIX-OPEN."
    
    681
    -  
    
    682
    -  (declare (type unix-pathname name)
    
    683
    -	   (type unix-file-mode mode))
    
    684
    -  (int-syscall ("creat64" c-string int) (%name->file name) mode))
    
    685
    -
    
    686
    -(defun unix-resolve-links (pathname)
    
    687
    -  _N"Returns the pathname with all symbolic links resolved."
    
    688
    -  (declare (simple-string pathname))
    
    689
    -  (let ((len (length pathname))
    
    690
    -	(pending pathname))
    
    691
    -    (declare (fixnum len) (simple-string pending))
    
    692
    -    (if (zerop len)
    
    693
    -	pathname
    
    694
    -	(let ((result (make-string 100 :initial-element (code-char 0)))
    
    695
    -	      (fill-ptr 0)
    
    696
    -	      (name-start 0))
    
    697
    -	  (loop
    
    698
    -	    (let* ((name-end (or (position #\/ pending :start name-start) len))
    
    699
    -		   (new-fill-ptr (+ fill-ptr (- name-end name-start))))
    
    700
    -	      ;; grow the result string, if necessary.  the ">=" (instead of
    
    701
    -	      ;; using ">") allows for the trailing "/" if we find this
    
    702
    -	      ;; component is a directory.
    
    703
    -	      (when (>= new-fill-ptr (length result))
    
    704
    -		(let ((longer (make-string (* 3 (length result))
    
    705
    -					   :initial-element (code-char 0))))
    
    706
    -		  (replace longer result :end1 fill-ptr)
    
    707
    -		  (setq result longer)))
    
    708
    -	      (replace result pending
    
    709
    -		       :start1 fill-ptr
    
    710
    -		       :end1 new-fill-ptr
    
    711
    -		       :start2 name-start
    
    712
    -		       :end2 name-end)
    
    713
    -	      (let ((kind (unix-file-kind (if (zerop name-end) "/" result) t)))
    
    714
    -		(unless kind (return nil))
    
    715
    -		(cond ((eq kind :link)
    
    716
    -		       (multiple-value-bind (link err) (unix-readlink result)
    
    717
    -			 (unless link
    
    718
    -			   (error (intl:gettext "Error reading link ~S: ~S")
    
    719
    -				  (subseq result 0 fill-ptr)
    
    720
    -				  (get-unix-error-msg err)))
    
    721
    -			 (cond ((or (zerop (length link))
    
    722
    -				    (char/= (schar link 0) #\/))
    
    723
    -				;; It's a relative link
    
    724
    -				(fill result (code-char 0)
    
    725
    -				      :start fill-ptr
    
    726
    -				      :end new-fill-ptr))
    
    727
    -			       ((string= result "/../" :end1 4)
    
    728
    -				;; It's across the super-root.
    
    729
    -				(let ((slash (or (position #\/ result :start 4)
    
    730
    -						 0)))
    
    731
    -				  (fill result (code-char 0)
    
    732
    -					:start slash
    
    733
    -					:end new-fill-ptr)
    
    734
    -				  (setf fill-ptr slash)))
    
    735
    -			       (t
    
    736
    -				;; It's absolute.
    
    737
    -				(and (> (length link) 0)
    
    738
    -				     (char= (schar link 0) #\/))
    
    739
    -				(fill result (code-char 0) :end new-fill-ptr)
    
    740
    -				(setf fill-ptr 0)))
    
    741
    -			 (setf pending
    
    742
    -			       (if (= name-end len)
    
    743
    -				   link
    
    744
    -				   (concatenate 'simple-string
    
    745
    -						link
    
    746
    -						(subseq pending name-end))))
    
    747
    -			 (setf len (length pending))
    
    748
    -			 (setf name-start 0)))
    
    749
    -		      ((= name-end len)
    
    750
    -		       (when (eq kind :directory)
    
    751
    -			 (setf (schar result new-fill-ptr) #\/)
    
    752
    -			 (incf new-fill-ptr))
    
    753
    -		       (return (subseq result 0 new-fill-ptr)))
    
    754
    -		      ((eq kind :directory)
    
    755
    -		       (setf (schar result new-fill-ptr) #\/)
    
    756
    -		       (setf fill-ptr (1+ new-fill-ptr))
    
    757
    -		       (setf name-start (1+ name-end)))
    
    758
    -		      (t
    
    759
    -		       (return nil))))))))))
    
    760
    -
    
    761
    -(defun unix-simplify-pathname (src)
    
    762
    -  (declare (simple-string src))
    
    763
    -  (let* ((src-len (length src))
    
    764
    -	 (dst (make-string src-len))
    
    765
    -	 (dst-len 0)
    
    766
    -	 (dots 0)
    
    767
    -	 (last-slash nil))
    
    768
    -    (macrolet ((deposit (char)
    
    769
    -			`(progn
    
    770
    -			   (setf (schar dst dst-len) ,char)
    
    771
    -			   (incf dst-len))))
    
    772
    -      (dotimes (src-index src-len)
    
    773
    -	(let ((char (schar src src-index)))
    
    774
    -	  (cond ((char= char #\.)
    
    775
    -		 (when dots
    
    776
    -		   (incf dots))
    
    777
    -		 (deposit char))
    
    778
    -		((char= char #\/)
    
    779
    -		 (case dots
    
    780
    -		   (0
    
    781
    -		    ;; Either ``/...' or ``...//...'
    
    782
    -		    (unless last-slash
    
    783
    -		      (setf last-slash dst-len)
    
    784
    -		      (deposit char)))
    
    785
    -		   (1
    
    786
    -		    ;; Either ``./...'' or ``..././...''
    
    787
    -		    (decf dst-len))
    
    788
    -		   (2
    
    789
    -		    ;; We've found ..
    
    790
    -		    (cond
    
    791
    -		     ((and last-slash (not (zerop last-slash)))
    
    792
    -		      ;; There is something before this ..
    
    793
    -		      (let ((prev-prev-slash
    
    794
    -			     (position #\/ dst :end last-slash :from-end t)))
    
    795
    -			(cond ((and (= (+ (or prev-prev-slash 0) 2)
    
    796
    -				       last-slash)
    
    797
    -				    (char= (schar dst (- last-slash 2)) #\.)
    
    798
    -				    (char= (schar dst (1- last-slash)) #\.))
    
    799
    -			       ;; The something before this .. is another ..
    
    800
    -			       (deposit char)
    
    801
    -			       (setf last-slash dst-len))
    
    802
    -			      (t
    
    803
    -			       ;; The something is some random dir.
    
    804
    -			       (setf dst-len
    
    805
    -				     (if prev-prev-slash
    
    806
    -					 (1+ prev-prev-slash)
    
    807
    -					 0))
    
    808
    -			       (setf last-slash prev-prev-slash)))))
    
    809
    -		     (t
    
    810
    -		      ;; There is nothing before this .., so we need to keep it
    
    811
    -		      (setf last-slash dst-len)
    
    812
    -		      (deposit char))))
    
    813
    -		   (t
    
    814
    -		    ;; Something other than a dot between slashes.
    
    815
    -		    (setf last-slash dst-len)
    
    816
    -		    (deposit char)))
    
    817
    -		 (setf dots 0))
    
    818
    -		(t
    
    819
    -		 (setf dots nil)
    
    820
    -		 (setf (schar dst dst-len) char)
    
    821
    -		 (incf dst-len))))))
    
    822
    -    (when (and last-slash (not (zerop last-slash)))
    
    823
    -      (case dots
    
    824
    -	(1
    
    825
    -	 ;; We've got  ``foobar/.''
    
    826
    -	 (decf dst-len))
    
    827
    -	(2
    
    828
    -	 ;; We've got ``foobar/..''
    
    829
    -	 (unless (and (>= last-slash 2)
    
    830
    -		      (char= (schar dst (1- last-slash)) #\.)
    
    831
    -		      (char= (schar dst (- last-slash 2)) #\.)
    
    832
    -		      (or (= last-slash 2)
    
    833
    -			  (char= (schar dst (- last-slash 3)) #\/)))
    
    834
    -	   (let ((prev-prev-slash
    
    835
    -		  (position #\/ dst :end last-slash :from-end t)))
    
    836
    -	     (if prev-prev-slash
    
    837
    -		 (setf dst-len (1+ prev-prev-slash))
    
    838
    -		 (return-from unix-simplify-pathname "./")))))))
    
    839
    -    (cond ((zerop dst-len)
    
    840
    -	   "./")
    
    841
    -	  ((= dst-len src-len)
    
    842
    -	   dst)
    
    843
    -	  (t
    
    844
    -	   (subseq dst 0 dst-len)))))
    
    845
    -
    
    846
    -(defun unix-gethostname ()
    
    847
    -  _N"Unix-gethostname returns the name of the host machine as a string."
    
    848
    -  (with-alien ((buf (array char 256)))
    
    849
    -    (syscall* ("gethostname" (* char) int)
    
    850
    -	      (cast buf c-string)
    
    851
    -	      (cast buf (* char)) 256)))
    
    852
    -
    
    853
    -;;; Unix-dup returns a duplicate copy of the existing file-descriptor
    
    854
    -;;; passed as an argument.
    
    855
    -
    
    856
    -(defun unix-dup (fd)
    
    857
    -  _N"Unix-dup duplicates an existing file descriptor (given as the
    
    858
    -   argument) and return it.  If FD is not a valid file descriptor, NIL
    
    859
    -   and an error number are returned."
    
    860
    -  (declare (type unix-fd fd))
    
    861
    -  (int-syscall ("dup" int) fd))
    
    862
    -
    
    863
    -;;; Unix-dup2 makes the second file-descriptor describe the same file
    
    864
    -;;; as the first. If the second file-descriptor points to an open
    
    865
    -;;; file, it is first closed. In any case, the second should have a 
    
    866
    -;;; value which is a valid file-descriptor.
    
    867
    -
    
    868
    -(defun unix-dup2 (fd1 fd2)
    
    869
    -  _N"Unix-dup2 duplicates an existing file descriptor just as unix-dup
    
    870
    -   does only the new value of the duplicate descriptor may be requested
    
    871
    -   through the second argument.  If a file already exists with the
    
    872
    -   requested descriptor number, it will be closed and the number
    
    873
    -   assigned to the duplicate."
    
    874
    -  (declare (type unix-fd fd1 fd2))
    
    875
    -  (void-syscall ("dup2" int int) fd1 fd2))
    
    876
    -
    
    877
    -;;; Unix-exit terminates a program.
    
    878
    -
    
    879
    -(defun unix-exit (&optional (code 0))
    
    880
    -  _N"Unix-exit terminates the current process with an optional
    
    881
    -   error code.  If successful, the call doesn't return.  If
    
    882
    -   unsuccessful, the call returns NIL and an error number."
    
    883
    -  (declare (type (signed-byte 32) code))
    
    884
    -  (void-syscall ("exit" int) code))
    
    885
    -
    
    886
    -(def-alien-routine ("getuid" unix-getuid) int
    
    887
    -  _N"Unix-getuid returns the real user-id associated with the
    
    888
    -   current process.")
    
    889
    -
    
    890
    -;;; Unix-chdir accepts a directory name and makes that the
    
    891
    -;;; current working directory.
    
    892
    -
    
    893
    -(defun unix-chdir (path)
    
    894
    -  _N"Given a file path string, unix-chdir changes the current working 
    
    895
    -   directory to the one specified."
    
    896
    -  (declare (type unix-pathname path))
    
    897
    -  (void-syscall ("chdir" c-string) (%name->file path)))
    
    898
    -
    
    899
    -;;; Unix-chmod accepts a path and a mode and changes the mode to the new mode.
    
    900
    -
    
    901
    -(defun unix-chmod (path mode)
    
    902
    -  _N"Given a file path string and a constant mode, unix-chmod changes the
    
    903
    -   permission mode for that file to the one specified. The new mode
    
    904
    -   can be created by logically OR'ing the following:
    
    905
    -
    
    906
    -      setuidexec        Set user ID on execution.
    
    907
    -      setgidexec        Set group ID on execution.
    
    908
    -      savetext          Save text image after execution.
    
    909
    -      readown           Read by owner.
    
    910
    -      writeown          Write by owner.
    
    911
    -      execown           Execute (search directory) by owner.
    
    912
    -      readgrp           Read by group.
    
    913
    -      writegrp          Write by group.
    
    914
    -      execgrp           Execute (search directory) by group.
    
    915
    -      readoth           Read by others.
    
    916
    -      writeoth          Write by others.
    
    917
    -      execoth           Execute (search directory) by others.
    
    918
    -
    
    919
    -  Thus #o444 and (logior unix:readown unix:readgrp unix:readoth)
    
    920
    -  are equivalent for 'mode.  The octal-base is familar to Unix users.
    
    921
    -  
    
    922
    -  It returns T on successfully completion; NIL and an error number
    
    923
    -  otherwise."
    
    924
    -  (declare (type unix-pathname path)
    
    925
    -	   (type unix-file-mode mode))
    
    926
    -  (void-syscall ("chmod" c-string int) (%name->file path) mode))
    
    927
    -
    
    928
    -;;; Unix-fchmod accepts a file descriptor ("fd") and a file protection mode
    
    929
    -;;; ("mode") and changes the protection of the file described by "fd" to 
    
    930
    -;;; "mode".
    
    931
    -
    
    932
    -(defun unix-fchmod (fd mode)
    
    933
    -  _N"Given an integer file descriptor and a mode (the same as those
    
    934
    -   used for unix-chmod), unix-fchmod changes the permission mode
    
    935
    -   for that file to the one specified. T is returned if the call
    
    936
    -   was successful."
    
    937
    -  (declare (type unix-fd fd)
    
    938
    -	   (type unix-file-mode mode))
    
    939
    -  (void-syscall ("fchmod" int int) fd mode))
    
    940
    -
    
    941
    -(defun unix-readlink (path)
    
    942
    -  _N"Unix-readlink invokes the readlink system call on the file name
    
    943
    -  specified by the simple string path.  It returns up to two values:
    
    944
    -  the contents of the symbolic link if the call is successful, or
    
    945
    -  NIL and the Unix error number."
    
    946
    -  (declare (type unix-pathname path))
    
    947
    -  (with-alien ((buf (array char 1024)))
    
    948
    -    (syscall ("readlink" c-string (* char) int)
    
    949
    -	     (let ((string (make-string result)))
    
    950
    -	       #-unicode
    
    951
    -	       (kernel:copy-from-system-area
    
    952
    -		(alien-sap buf) 0
    
    953
    -		string (* vm:vector-data-offset vm:word-bits)
    
    954
    -		(* result vm:byte-bits))
    
    955
    -	       #+unicode
    
    956
    -	       (let ((sap (alien-sap buf)))
    
    957
    -		 (dotimes (k result)
    
    958
    -		   (setf (aref string k) (code-char (sap-ref-8 sap k)))))
    
    959
    -	       (%file->name string))
    
    960
    -	     (%name->file path) (cast buf (* char)) 1024)))
    
    961
    -
    
    962
    -;;; Unix-unlink accepts a name and deletes the directory entry for that
    
    963
    -;;; name and the file if this is the last link.
    
    964
    -
    
    965
    -(defun unix-unlink (name)
    
    966
    -  _N"Unix-unlink removes the directory entry for the named file.
    
    967
    -   NIL and an error code is returned if the call fails."
    
    968
    -  (declare (type unix-pathname name))
    
    969
    -  (void-syscall ("unlink" c-string) (%name->file name)))
    
    970
    -
    
    971
    -;;; fcntl.h
    
    972
    -;;;
    
    973
    -;;; POSIX Standard: 6.5 File Control Operations	<fcntl.h>
    
    974
    -
    
    975
    -(defconstant r_ok 4 _N"Test for read permission")
    
    976
    -(defconstant w_ok 2 _N"Test for write permission")
    
    977
    -(defconstant x_ok 1 _N"Test for execute permission")
    
    978
    -(defconstant f_ok 0 _N"Test for presence of file")
    
    979
    -
    
    980
    -(defun unix-fcntl (fd cmd arg)
    
    981
    -  _N"Unix-fcntl manipulates file descriptors accoridng to the
    
    982
    -   argument CMD which can be one of the following:
    
    983
    -
    
    984
    -   F-DUPFD         Duplicate a file descriptor.
    
    985
    -   F-GETFD         Get file descriptor flags.
    
    986
    -   F-SETFD         Set file descriptor flags.
    
    987
    -   F-GETFL         Get file flags.
    
    988
    -   F-SETFL         Set file flags.
    
    989
    -   F-GETOWN        Get owner.
    
    990
    -   F-SETOWN        Set owner.
    
    991
    -
    
    992
    -   The flags that can be specified for F-SETFL are:
    
    993
    -
    
    994
    -   FNDELAY         Non-blocking reads.
    
    995
    -   FAPPEND         Append on each write.
    
    996
    -   FASYNC          Signal pgrp when data ready.
    
    997
    -   FCREAT          Create if nonexistant.
    
    998
    -   FTRUNC          Truncate to zero length.
    
    999
    -   FEXCL           Error if already created.
    
    1000
    -   "
    
    1001
    -  (declare (type unix-fd fd)
    
    1002
    -	   (type (unsigned-byte 32) cmd)
    
    1003
    -	   (type (unsigned-byte 32) arg))
    
    1004
    -  (int-syscall ("fcntl" int unsigned-int unsigned-int) fd cmd arg))
    
    1005
    -
    
    1006
    -;;;; Memory-mapped files
    
    1007
    -
    
    1008
    -(defconstant +null+ (sys:int-sap 0))
    
    1009
    -
    
    1010
    -(defconstant prot_read 1)
    
    1011
    -(defconstant prot_write 2)
    
    1012
    -(defconstant prot_exec 4)
    
    1013
    -(defconstant prot_none 0)
    
    1014
    -
    
    1015
    -(defconstant map_shared 1)
    
    1016
    -(defconstant map_private 2)
    
    1017
    -(defconstant map_fixed 16)
    
    1018
    -(defconstant map_anonymous 32)
    
    1019
    -
    
    1020
    -(defconstant ms_async 1)
    
    1021
    -(defconstant ms_sync 4)
    
    1022
    -(defconstant ms_invalidate 2)
    
    1023
    -
    
    1024
    -;; The return value from mmap that means mmap failed.
    
    1025
    -(defconstant map_failed (int-sap (1- (ash 1 vm:word-bits))))
    
    1026
    -
    
    1027
    -(defun unix-mmap (addr length prot flags fd offset)
    
    1028
    -  (declare (type (or null system-area-pointer) addr)
    
    1029
    -	   (type (unsigned-byte 32) length)
    
    1030
    -           (type (integer 1 7) prot)
    
    1031
    -	   (type (unsigned-byte 32) flags)
    
    1032
    -	   (type (or null unix-fd) fd)
    
    1033
    -	   (type (signed-byte 32) offset))
    
    1034
    -  ;; Can't use syscall, because the address that is returned could be
    
    1035
    -  ;; "negative".  Hence we explicitly check for mmap returning
    
    1036
    -  ;; MAP_FAILED.
    
    1037
    -  (let ((result
    
    1038
    -	 (alien-funcall (extern-alien "mmap" (function system-area-pointer
    
    1039
    -						       system-area-pointer
    
    1040
    -						       size-t int int int off-t))
    
    1041
    -			(or addr +null+) length prot flags (or fd -1) offset)))
    
    1042
    -    (if (sap= result map_failed)
    
    1043
    -	(values nil (unix-errno))
    
    1044
    -	(values result 0))))
    
    1045
    -
    
    1046
    -(defun unix-munmap (addr length)
    
    1047
    -  (declare (type system-area-pointer addr)
    
    1048
    -	   (type (unsigned-byte 32) length))
    
    1049
    -  (syscall ("munmap" system-area-pointer size-t) t addr length))
    
    1050
    -
    
    1051
    -(defun unix-msync (addr length flags)
    
    1052
    -  (declare (type system-area-pointer addr)
    
    1053
    -	   (type (unsigned-byte 32) length)
    
    1054
    -	   (type (signed-byte 32) flags))
    
    1055
    -  (syscall ("msync" system-area-pointer size-t int) t addr length flags))
    
    1056
    -
    
    1057
    -;;; Unix-rename accepts two files names and renames the first to the second.
    
    1058
    -
    
    1059
    -(defun unix-rename (name1 name2)
    
    1060
    -  _N"Unix-rename renames the file with string name1 to the string
    
    1061
    -   name2.  NIL and an error code is returned if an error occured."
    
    1062
    -  (declare (type unix-pathname name1 name2))
    
    1063
    -  (void-syscall ("rename" c-string c-string)
    
    1064
    -		(%name->file name1) (%name->file name2)))
    
    1065
    -
    
    1066
    -;;; Unix-rmdir accepts a name and removes the associated directory.
    
    1067
    -
    
    1068
    -(defun unix-rmdir (name)
    
    1069
    -  _N"Unix-rmdir attempts to remove the directory name.  NIL and
    
    1070
    -   an error number is returned if an error occured."
    
    1071
    -  (declare (type unix-pathname name))
    
    1072
    -  (void-syscall ("rmdir" c-string) (%name->file name)))
    
    1073
    -
    
    1074
    -(def-alien-type fd-mask #-alpha unsigned-long #+alpha unsigned-int)
    
    1075
    -
    
    1076
    -(defconstant fd-setsize 1024)
    
    1077
    -(defconstant nfdbits 32)
    
    1078
    -  
    
    1079
    -(def-alien-type nil
    
    1080
    -  (struct fd-set
    
    1081
    -	  (fds-bits (array fd-mask #.(/ fd-setsize nfdbits)))))
    
    1082
    -
    
    1083
    -;; not checked for linux...
    
    1084
    -(defmacro fd-clr (offset fd-set)
    
    1085
    -  (let ((word (gensym))
    
    1086
    -	(bit (gensym)))
    
    1087
    -    `(multiple-value-bind (,word ,bit) (floor ,offset nfdbits)
    
    1088
    -       (setf (deref (slot ,fd-set 'fds-bits) ,word)
    
    1089
    -	     (logand (deref (slot ,fd-set 'fds-bits) ,word)
    
    1090
    -		     (32bit-logical-not
    
    1091
    -		      (truly-the (unsigned-byte 32) (ash 1 ,bit))))))))
    
    1092
    -
    
    1093
    -;; not checked for linux...
    
    1094
    -(defmacro fd-isset (offset fd-set)
    
    1095
    -  (let ((word (gensym))
    
    1096
    -	(bit (gensym)))
    
    1097
    -    `(multiple-value-bind (,word ,bit) (floor ,offset nfdbits)
    
    1098
    -       (logbitp ,bit (deref (slot ,fd-set 'fds-bits) ,word)))))
    
    1099
    -
    
    1100
    -;; not checked for linux...
    
    1101
    -(defmacro fd-set (offset fd-set)
    
    1102
    -  (let ((word (gensym))
    
    1103
    -	(bit (gensym)))
    
    1104
    -    `(multiple-value-bind (,word ,bit) (floor ,offset nfdbits)
    
    1105
    -       (setf (deref (slot ,fd-set 'fds-bits) ,word)
    
    1106
    -	     (logior (truly-the (unsigned-byte 32) (ash 1 ,bit))
    
    1107
    -		     (deref (slot ,fd-set 'fds-bits) ,word))))))
    
    1108
    -
    
    1109
    -;; not checked for linux...
    
    1110
    -(defmacro fd-zero (fd-set)
    
    1111
    -  `(progn
    
    1112
    -     ,@(loop for index upfrom 0 below (/ fd-setsize nfdbits)
    
    1113
    -	 collect `(setf (deref (slot ,fd-set 'fds-bits) ,index) 0))))
    
    1114
    -
    
    1115
    -;;; TTY ioctl commands.
    
    1116
    -
    
    1117
    -(eval-when (compile load eval)
    
    1118
    -
    
    1119
    -(defconstant iocparm-mask #x3fff)
    
    1120
    -(defconstant ioc_void #x00000000)
    
    1121
    -(defconstant ioc_out #x40000000)
    
    1122
    -(defconstant ioc_in #x80000000)
    
    1123
    -(defconstant ioc_inout (logior ioc_in ioc_out))
    
    1124
    -
    
    1125
    -(defmacro define-ioctl-command (name dev cmd &optional arg parm-type)
    
    1126
    -  _N"Define an ioctl command. If the optional ARG and PARM-TYPE are given
    
    1127
    -  then ioctl argument size and direction are included as for ioctls defined
    
    1128
    -  by _IO, _IOR, _IOW, or _IOWR. If DEV is a character then the ioctl type
    
    1129
    -  is the characters code, else DEV may be an integer giving the type."
    
    1130
    -  (let* ((type (if (characterp dev)
    
    1131
    -		   (char-code dev)
    
    1132
    -		   dev))
    
    1133
    -	 (code (logior (ash type 8) cmd)))
    
    1134
    -    (when arg
    
    1135
    -      (setf code `(logior (ash (logand (alien-size ,arg :bytes) ,iocparm-mask)
    
    1136
    -			       16)
    
    1137
    -			  ,code)))
    
    1138
    -    (when parm-type
    
    1139
    -      (let ((dir (ecase parm-type
    
    1140
    -		   (:void ioc_void)
    
    1141
    -		   (:in ioc_in)
    
    1142
    -		   (:out ioc_out)
    
    1143
    -		   (:inout ioc_inout))))
    
    1144
    -	(setf code `(logior ,dir ,code))))
    
    1145
    -    `(eval-when (eval load compile)
    
    1146
    -       (defconstant ,name ,code))))
    
    1147
    -)
    
    1148
    -
    
    1149
    -;;; TTY ioctl commands.
    
    1150
    -
    
    1151
    -(define-ioctl-command TIOCGWINSZ #\T #x13)
    
    1152
    -(define-ioctl-command TIOCSWINSZ #\T #x14)
    
    1153
    -(define-ioctl-command TIOCNOTTY  #\T #x22)
    
    1154
    -(define-ioctl-command TIOCSPGRP  #\T #x10)
    
    1155
    -(define-ioctl-command TIOCGPGRP  #\T #x0F)
    
    1156
    -
    
    1157
    -;;; File ioctl commands.
    
    1158
    -(define-ioctl-command FIONREAD #\T #x1B)
    
    1159
    -
    
    1160
    -;;; ioctl-types.h
    
    1161
    -
    
    1162
    -(def-alien-type nil
    
    1163
    -  (struct winsize
    
    1164
    -    (ws-row unsigned-short)		; rows, in characters
    
    1165
    -    (ws-col unsigned-short)		; columns, in characters
    
    1166
    -    (ws-xpixel unsigned-short)		; horizontal size, pixels
    
    1167
    -    (ws-ypixel unsigned-short)))	; veritical size, pixels
    
    1168
    -
    
    1169
    -(defconstant f-getfl    3  _N"Get file flags")
    
    1170
    -(defconstant f-setfl    4  _N"Set file flags")
    
    1171
    -
    
    1172
    -;;; Define some more compatibility macros to be backward compatible with
    
    1173
    -;;; BSD systems which did not managed to hide these kernel macros. 
    
    1174
    -
    
    1175
    -(defconstant FAPPEND  o_append _N"depricated stuff")
    
    1176
    -(defconstant FFSYNC   o_fsync  _N"depricated stuff")
    
    1177
    -(defconstant FASYNC   o_async  _N"depricated stuff")
    
    1178
    -(defconstant FNONBLOCK  o_nonblock _N"depricated stuff")
    
    1179
    -(defconstant FNDELAY  o_ndelay _N"depricated stuff")
    
    1180
    -
    
    1181
    -(defun unix-mprotect (addr length prot)
    
    1182
    -  (declare (type system-area-pointer addr)
    
    1183
    -	   (type (unsigned-byte 32) length)
    
    1184
    -           (type (integer 1 7) prot))
    
    1185
    -  (syscall ("mprotect" system-area-pointer size-t int)
    
    1186
    -	   t addr length prot))
    
    1187
    -  
    
    1188
    -;;;; Lisp types used by syscalls.
    
    1189
    -
    
    1190
    -(deftype unix-pathname () 'simple-string)
    
    1191
    -(deftype unix-fd () `(integer 0 ,most-positive-fixnum))
    
    1192
    -
    
    1193
    -(deftype unix-file-mode () '(unsigned-byte 32))
    
    1194
    -(deftype unix-pid () '(unsigned-byte 32))
    
    1195
    -(deftype unix-uid () '(unsigned-byte 32))
    
    1196
    -(deftype unix-gid () '(unsigned-byte 32))
    
    1197
    -
    
    1198
    -;;; Operations on Unix Directories.
    
    1199
    -
    
    1200
    -;;; direntry.h
    
    1201
    -
    
    1202
    -(def-alien-type nil
    
    1203
    -  (struct dirent
    
    1204
    -    #+glibc2.1
    
    1205
    -    (d-ino ino-t)                       ; inode number of entry
    
    1206
    -    #-glibc2.1
    
    1207
    -    (d-ino ino64-t)                     ; inode number of entry
    
    1208
    -    (d-off off-t)                       ; offset of next disk directory entry
    
    1209
    -    (d-reclen unsigned-short)		; length of this record
    
    1210
    -    (d_type unsigned-char)
    
    1211
    -    (d-name (array char 256))))		; name must be no longer than this
    
    1212
    -
    
    1213
    -(export '(open-dir read-dir close-dir))
    
    1214
    -
    
    1215
    -(defstruct (%directory
    
    1216
    -	     (:constructor make-directory)
    
    1217
    -	     (:conc-name directory-)
    
    1218
    -	     (:print-function %print-directory))
    
    1219
    -  name
    
    1220
    -  (dir-struct (required-argument) :type system-area-pointer))
    
    1221
    -
    
    1222
    -(defun %print-directory (dir stream depth)
    
    1223
    -  (declare (ignore depth))
    
    1224
    -  (format stream "#<Directory ~S>" (directory-name dir)))
    
    1225
    -
    
    1226
    -(defun open-dir (pathname)
    
    1227
    -  (declare (type unix-pathname pathname))
    
    1228
    -  (when (string= pathname "")
    
    1229
    -    (setf pathname "."))
    
    1230
    -  (let ((kind (unix-file-kind pathname)))
    
    1231
    -    (case kind
    
    1232
    -      (:directory
    
    1233
    -       (let ((dir-struct
    
    1234
    -	      (alien-funcall (extern-alien "opendir"
    
    1235
    -					   (function system-area-pointer
    
    1236
    -						     c-string))
    
    1237
    -			     (%name->file pathname))))
    
    1238
    -	 (if (zerop (sap-int dir-struct))
    
    1239
    -	     (values nil (unix-errno))
    
    1240
    -	     (make-directory :name pathname :dir-struct dir-struct))))
    
    1241
    -      ((nil)
    
    1242
    -       (values nil enoent))
    
    1243
    -      (t
    
    1244
    -       (values nil enotdir)))))
    
    1245
    -
    
    1246
    -(defun read-dir (dir)
    
    1247
    -  (declare (type %directory dir))
    
    1248
    -  (let ((daddr (alien-funcall (extern-alien "readdir64"
    
    1249
    -					    (function system-area-pointer
    
    1250
    -						      system-area-pointer))
    
    1251
    -			      (directory-dir-struct dir))))
    
    1252
    -    (declare (type system-area-pointer daddr))
    
    1253
    -    (if (zerop (sap-int daddr))
    
    1254
    -	nil
    
    1255
    -	(with-alien ((dirent (* (struct dirent)) daddr))
    
    1256
    -	  (values (%file->name (cast (slot dirent 'd-name) c-string))
    
    1257
    -		  (slot dirent 'd-ino))))))
    
    1258
    -
    
    1259
    -(defun close-dir (dir)
    
    1260
    -  (declare (type %directory dir))
    
    1261
    -  (alien-funcall (extern-alien "closedir"
    
    1262
    -			       (function void system-area-pointer))
    
    1263
    -		 (directory-dir-struct dir))
    
    1264
    -  nil)
    
    1265
    -
    
    1266
    -(defconstant rusage_self 0 _N"The calling process.")
    
    1267
    -(defconstant rusage_children -1 _N"Terminated child processes.")
    
    1268
    -(defconstant rusage_both -2)
    
    1269
    -
    
    1270
    -(def-alien-type nil
    
    1271
    -  (struct rusage
    
    1272
    -    (ru-utime (struct timeval))		; user time used
    
    1273
    -    (ru-stime (struct timeval))		; system time used.
    
    1274
    -    (ru-maxrss long)                    ; Maximum resident set size (in kilobytes)
    
    1275
    -    (ru-ixrss long)			; integral shared memory size
    
    1276
    -    (ru-idrss long)			; integral unshared data "
    
    1277
    -    (ru-isrss long)			; integral unshared stack "
    
    1278
    -    (ru-minflt long)			; page reclaims
    
    1279
    -    (ru-majflt long)			; page faults
    
    1280
    -    (ru-nswap long)			; swaps
    
    1281
    -    (ru-inblock long)			; block input operations
    
    1282
    -    (ru-oublock long)			; block output operations
    
    1283
    -    (ru-msgsnd long)			; messages sent
    
    1284
    -    (ru-msgrcv long)			; messages received
    
    1285
    -    (ru-nsignals long)			; signals received
    
    1286
    -    (ru-nvcsw long)			; voluntary context switches
    
    1287
    -    (ru-nivcsw long)))
    
    1288
    -
    
    1289
    -(declaim (inline unix-fast-getrusage))
    
    1290
    -(defun unix-fast-getrusage (who)
    
    1291
    -  _N"Like call getrusage, but return only the system and user time, and returns
    
    1292
    -   the seconds and microseconds as separate values."
    
    1293
    -  (declare (values (member t)
    
    1294
    -		   (unsigned-byte 31) (mod 1000000)
    
    1295
    -		   (unsigned-byte 31) (mod 1000000)))
    
    1296
    -  (with-alien ((usage (struct rusage)))
    
    1297
    -    (syscall* ("getrusage" int (* (struct rusage)))
    
    1298
    -	      (values t
    
    1299
    -		      (slot (slot usage 'ru-utime) 'tv-sec)
    
    1300
    -		      (slot (slot usage 'ru-utime) 'tv-usec)
    
    1301
    -		      (slot (slot usage 'ru-stime) 'tv-sec)
    
    1302
    -		      (slot (slot usage 'ru-stime) 'tv-usec))
    
    1303
    -	      who (addr usage))))
    
    1304
    -
    
    1305
    -(defun unix-getrusage (who)
    
    1306
    -  _N"Unix-getrusage returns information about the resource usage
    
    1307
    -   of the process specified by who.  Who can be either the
    
    1308
    -   current process (rusage_self) or all of the terminated
    
    1309
    -   child processes (rusage_children).  NIL and an error number
    
    1310
    -   is returned if the call fails."
    
    1311
    -  (with-alien ((usage (struct rusage)))
    
    1312
    -    (syscall ("getrusage" int (* (struct rusage)))
    
    1313
    -	      (values t
    
    1314
    -		      (+ (* (slot (slot usage 'ru-utime) 'tv-sec) 1000000)
    
    1315
    -			 (slot (slot usage 'ru-utime) 'tv-usec))
    
    1316
    -		      (+ (* (slot (slot usage 'ru-stime) 'tv-sec) 1000000)
    
    1317
    -			 (slot (slot usage 'ru-stime) 'tv-usec))
    
    1318
    -		      (slot usage 'ru-maxrss)
    
    1319
    -		      (slot usage 'ru-ixrss)
    
    1320
    -		      (slot usage 'ru-idrss)
    
    1321
    -		      (slot usage 'ru-isrss)
    
    1322
    -		      (slot usage 'ru-minflt)
    
    1323
    -		      (slot usage 'ru-majflt)
    
    1324
    -		      (slot usage 'ru-nswap)
    
    1325
    -		      (slot usage 'ru-inblock)
    
    1326
    -		      (slot usage 'ru-oublock)
    
    1327
    -		      (slot usage 'ru-msgsnd)
    
    1328
    -		      (slot usage 'ru-msgrcv)
    
    1329
    -		      (slot usage 'ru-nsignals)
    
    1330
    -		      (slot usage 'ru-nvcsw)
    
    1331
    -		      (slot usage 'ru-nivcsw))
    
    1332
    -	      who (addr usage))))
    
    1333
    -
    
    1334
    -;;;; Socket support.
    
    1335
    -
    
    1336
    -;;; Looks a bit naked.
    
    1337
    -
    
    1338
    -(def-alien-routine ("socket" unix-socket) int
    
    1339
    -  (domain int)
    
    1340
    -  (type int)
    
    1341
    -  (protocol int))
    
    1342
    -
    
    1343
    -(def-alien-routine ("connect" unix-connect) int
    
    1344
    -  (socket int)
    
    1345
    -  (sockaddr (* t))
    
    1346
    -  (len int))
    
    1347
    -
    
    1348
    -(def-alien-routine ("bind" unix-bind) int
    
    1349
    -  (socket int)
    
    1350
    -  (sockaddr (* t))
    
    1351
    -  (len int))
    
    1352
    -
    
    1353
    -(def-alien-routine ("listen" unix-listen) int
    
    1354
    -  (socket int)
    
    1355
    -  (backlog int))
    
    1356
    -
    
    1357
    -(def-alien-routine ("accept" unix-accept) int
    
    1358
    -  (socket int)
    
    1359
    -  (sockaddr (* t))
    
    1360
    -  (len int :in-out))
    
    1361
    -
    
    1362
    -(def-alien-routine ("recv" unix-recv) int
    
    1363
    -  (fd int)
    
    1364
    -  (buffer c-string)
    
    1365
    -  (length int)
    
    1366
    -  (flags int))
    
    1367
    -
    
    1368
    -(def-alien-routine ("send" unix-send) int
    
    1369
    -  (fd int)
    
    1370
    -  (buffer c-string)
    
    1371
    -  (length int)
    
    1372
    -  (flags int))
    
    1373
    -
    
    1374
    -(def-alien-routine ("getpeername" unix-getpeername) int
    
    1375
    -  (socket int)
    
    1376
    -  (sockaddr (* t))
    
    1377
    -  (len (* unsigned)))
    
    1378
    -
    
    1379
    -(def-alien-routine ("getsockname" unix-getsockname) int
    
    1380
    -  (socket int)
    
    1381
    -  (sockaddr (* t))
    
    1382
    -  (len (* unsigned)))
    
    1383
    -
    
    1384
    -(def-alien-routine ("getsockopt" unix-getsockopt) int
    
    1385
    -  (socket int)
    
    1386
    -  (level int)
    
    1387
    -  (optname int)
    
    1388
    -  (optval (* t))
    
    1389
    -  (optlen unsigned :in-out))
    
    1390
    -
    
    1391
    -(def-alien-routine ("setsockopt" unix-setsockopt) int
    
    1392
    -  (socket int)
    
    1393
    -  (level int)
    
    1394
    -  (optname int)
    
    1395
    -  (optval (* t))
    
    1396
    -  (optlen unsigned))
    
    1397
    -
    
    1398
    -;; Datagram support
    
    1399
    -
    
    1400
    -(def-alien-routine ("recvfrom" unix-recvfrom) int
    
    1401
    -  (fd int)
    
    1402
    -  (buffer c-string)
    
    1403
    -  (length int)
    
    1404
    -  (flags int)
    
    1405
    -  (sockaddr (* t))
    
    1406
    -  (len int :in-out))
    
    1407
    -
    
    1408
    -(def-alien-routine ("sendto" unix-sendto) int
    
    1409
    -  (fd int)
    
    1410
    -  (buffer c-string)
    
    1411
    -  (length int)
    
    1412
    -  (flags int)
    
    1413
    -  (sockaddr (* t))
    
    1414
    -  (len int))
    
    1415
    -
    
    1416
    -(def-alien-routine ("shutdown" unix-shutdown) int
    
    1417
    -  (socket int)
    
    1418
    -  (level int))
    
    1419
    -
    
    1420
    -;;; sys/select.h
    
    1421
    -
    
    1422
    -;;; UNIX-FAST-SELECT -- public.
    
    1423
    -;;;
    
    1424
    -(defmacro unix-fast-select (num-descriptors
    
    1425
    -			    read-fds write-fds exception-fds
    
    1426
    -			    timeout-secs &optional (timeout-usecs 0))
    
    1427
    -  _N"Perform the UNIX select(2) system call."
    
    1428
    -  (declare (type (integer 0 #.FD-SETSIZE) num-descriptors) 
    
    1429
    -	   (type (or (alien (* (struct fd-set))) null) 
    
    1430
    -		 read-fds write-fds exception-fds) 
    
    1431
    -	   (type (or null (unsigned-byte 31)) timeout-secs) 
    
    1432
    -	   (type (unsigned-byte 31) timeout-usecs) 
    
    1433
    -	   (optimize (speed 3) (safety 0) (inhibit-warnings 3)))
    
    1434
    -  `(let ((timeout-secs ,timeout-secs))
    
    1435
    -     (with-alien ((tv (struct timeval)))
    
    1436
    -       (when timeout-secs
    
    1437
    -	 (setf (slot tv 'tv-sec) timeout-secs)
    
    1438
    -	 (setf (slot tv 'tv-usec) ,timeout-usecs))
    
    1439
    -       (int-syscall ("select" int (* (struct fd-set)) (* (struct fd-set))
    
    1440
    -		     (* (struct fd-set)) (* (struct timeval)))
    
    1441
    -		    ,num-descriptors ,read-fds ,write-fds ,exception-fds
    
    1442
    -		    (if timeout-secs (alien-sap (addr tv)) (int-sap 0))))))
    
    1443
    -
    
    1444
    -
    
    1445
    -;;; Unix-select accepts sets of file descriptors and waits for an event
    
    1446
    -;;; to happen on one of them or to time out.
    
    1447
    -
    
    1448
    -(defmacro num-to-fd-set (fdset num)
    
    1449
    -  `(if (fixnump ,num)
    
    1450
    -       (progn
    
    1451
    -	 (setf (deref (slot ,fdset 'fds-bits) 0) ,num)
    
    1452
    -	 ,@(loop for index upfrom 1 below (/ fd-setsize nfdbits)
    
    1453
    -	     collect `(setf (deref (slot ,fdset 'fds-bits) ,index) 0)))
    
    1454
    -       (progn
    
    1455
    -	 ,@(loop for index upfrom 0 below (/ fd-setsize nfdbits)
    
    1456
    -	     collect `(setf (deref (slot ,fdset 'fds-bits) ,index)
    
    1457
    -			    (ldb (byte nfdbits ,(* index nfdbits)) ,num))))))
    
    1458
    -
    
    1459
    -(defmacro fd-set-to-num (nfds fdset)
    
    1460
    -  `(if (<= ,nfds nfdbits)
    
    1461
    -       (deref (slot ,fdset 'fds-bits) 0)
    
    1462
    -       (+ ,@(loop for index upfrom 0 below (/ fd-setsize nfdbits)
    
    1463
    -	      collect `(ash (deref (slot ,fdset 'fds-bits) ,index)
    
    1464
    -			    ,(* index nfdbits))))))
    
    1465
    -
    
    1466
    -(defun unix-select (nfds rdfds wrfds xpfds to-secs &optional (to-usecs 0))
    
    1467
    -  _N"Unix-select examines the sets of descriptors passed as arguments
    
    1468
    -   to see if they are ready for reading and writing.  See the UNIX
    
    1469
    -   Programmers Manual for more information."
    
    1470
    -  (declare (type (integer 0 #.FD-SETSIZE) nfds)
    
    1471
    -	   (type unsigned-byte rdfds wrfds xpfds)
    
    1472
    -	   (type (or (unsigned-byte 31) null) to-secs)
    
    1473
    -	   (type (unsigned-byte 31) to-usecs)
    
    1474
    -	   (optimize (speed 3) (safety 0) (inhibit-warnings 3)))
    
    1475
    -  (with-alien ((tv (struct timeval))
    
    1476
    -	       (rdf (struct fd-set))
    
    1477
    -	       (wrf (struct fd-set))
    
    1478
    -	       (xpf (struct fd-set)))
    
    1479
    -    (when to-secs
    
    1480
    -      (setf (slot tv 'tv-sec) to-secs)
    
    1481
    -      (setf (slot tv 'tv-usec) to-usecs))
    
    1482
    -    (num-to-fd-set rdf rdfds)
    
    1483
    -    (num-to-fd-set wrf wrfds)
    
    1484
    -    (num-to-fd-set xpf xpfds)
    
    1485
    -    (macrolet ((frob (lispvar alienvar)
    
    1486
    -		 `(if (zerop ,lispvar)
    
    1487
    -		      (int-sap 0)
    
    1488
    -		      (alien-sap (addr ,alienvar)))))
    
    1489
    -      (syscall ("select" int (* (struct fd-set)) (* (struct fd-set))
    
    1490
    -		(* (struct fd-set)) (* (struct timeval)))
    
    1491
    -	       (values result
    
    1492
    -		       (fd-set-to-num nfds rdf)
    
    1493
    -		       (fd-set-to-num nfds wrf)
    
    1494
    -		       (fd-set-to-num nfds xpf))
    
    1495
    -	       nfds (frob rdfds rdf) (frob wrfds wrf) (frob xpfds xpf)
    
    1496
    -	       (if to-secs (alien-sap (addr tv)) (int-sap 0))))))
    
    1497
    -
    
    1498
    -(defun unix-symlink (name1 name2)
    
    1499
    -  _N"Unix-symlink creates a symbolic link named name2 to the file
    
    1500
    -   named name1.  NIL and an error number is returned if the call
    
    1501
    -   is unsuccessful."
    
    1502
    -  (declare (type unix-pathname name1 name2))
    
    1503
    -  (void-syscall ("symlink" c-string c-string)
    
    1504
    -		(%name->file name1) (%name->file name2)))
    
    1505
    -
    
    1506
    -(def-alien-routine ("gethostid" unix-gethostid) unsigned-long
    
    1507
    -  _N"Unix-gethostid returns a 32-bit integer which provides unique
    
    1508
    -   identification for the host machine.")
    
    1509
    -
    
    1510
    -(def-alien-routine ("getpid" unix-getpid) int
    
    1511
    -  _N"Unix-getpid returns the process-id of the current process.")
    
    1512
    -
    
    1513
    -;;;; User and group database structures: <pwd.h> and <grp.h>
    
    1514
    -(defstruct user-info
    
    1515
    -  (name "" :type string)
    
    1516
    -  (password "" :type string)
    
    1517
    -  (uid 0 :type unix-uid)
    
    1518
    -  (gid 0 :type unix-gid)
    
    1519
    -  (gecos "" :type string)
    
    1520
    -  (dir "" :type string)
    
    1521
    -  (shell "" :type string))
    
    1522
    -
    
    1523
    -(defun unix-getpwuid (uid)
    
    1524
    -  _N"Return a USER-INFO structure for the user identified by UID, or NIL if not found."
    
    1525
    -  (declare (type unix-uid uid))
    
    1526
    -  (with-alien ((buf (array c-call:char 1024))
    
    1527
    -	       (user-info (struct passwd))
    
    1528
    -               (result (* (struct passwd))))
    
    1529
    -    (let ((returned
    
    1530
    -	   (alien-funcall
    
    1531
    -	    (extern-alien "getpwuid_r"
    
    1532
    -			  (function c-call:int
    
    1533
    -                                    c-call:unsigned-int
    
    1534
    -                                    (* (struct passwd))
    
    1535
    -                                    (* c-call:char)
    
    1536
    -                                    c-call:unsigned-int
    
    1537
    -                                    (* (* (struct passwd)))))
    
    1538
    -	    uid
    
    1539
    -	    (addr user-info)
    
    1540
    -	    (cast buf (* c-call:char))
    
    1541
    -	    1024
    
    1542
    -            (addr result))))
    
    1543
    -      (when (zerop returned)
    
    1544
    -        (make-user-info
    
    1545
    -         :name (string (cast (slot result 'pw-name) c-call:c-string))
    
    1546
    -         :password (string (cast (slot result 'pw-passwd) c-call:c-string))
    
    1547
    -         :uid (slot result 'pw-uid)
    
    1548
    -         :gid (slot result 'pw-gid)
    
    1549
    -         :gecos (string (cast (slot result 'pw-gecos) c-call:c-string))
    
    1550
    -         :dir (string (cast (slot result 'pw-dir) c-call:c-string))
    
    1551
    -         :shell (string (cast (slot result 'pw-shell) c-call:c-string)))))))
    
    1552
    -
    
    1553
    -(declaim (inline unix-gettimeofday))
    
    1554
    -(defun unix-gettimeofday ()
    
    1555
    -  _N"If it works, unix-gettimeofday returns 5 values: T, the seconds and
    
    1556
    -   microseconds of the current time of day, the timezone (in minutes west
    
    1557
    -   of Greenwich), and a daylight-savings flag.  If it doesn't work, it
    
    1558
    -   returns NIL and the errno."
    
    1559
    -  (with-alien ((tv (struct timeval))
    
    1560
    -	       (tz (struct timezone)))
    
    1561
    -    (syscall* ("gettimeofday" (* (struct timeval)) 
    
    1562
    -			      (* (struct timezone)))
    
    1563
    -	      (values T
    
    1564
    -		      (slot tv 'tv-sec)
    
    1565
    -		      (slot tv 'tv-usec)
    
    1566
    -		      (slot tz 'tz-minuteswest)
    
    1567
    -		      (slot tz 'tz-dsttime))
    
    1568
    -	      (addr tv)
    
    1569
    -	      (addr tz))))
    
    1570
    -
    
    1571
    -;;; Unix-utimes changes the accessed and updated times on UNIX
    
    1572
    -;;; files.  The first argument is the filename (a string) and
    
    1573
    -;;; the second argument is a list of the 4 times- accessed and
    
    1574
    -;;; updated seconds and microseconds.
    
    1575
    -
    
    1576
    -(defun unix-utimes (file atime-sec atime-usec mtime-sec mtime-usec)
    
    1577
    -  _N"Unix-utimes sets the 'last-accessed' and 'last-updated'
    
    1578
    -   times on a specified file.  NIL and an error number is
    
    1579
    -   returned if the call is unsuccessful."
    
    1580
    -  (declare (type unix-pathname file)
    
    1581
    -	   (type (alien unsigned-long)
    
    1582
    -		 atime-sec atime-usec
    
    1583
    -		 mtime-sec mtime-usec))
    
    1584
    -  (with-alien ((tvp (array (struct timeval) 2)))
    
    1585
    -    (setf (slot (deref tvp 0) 'tv-sec) atime-sec)
    
    1586
    -    (setf (slot (deref tvp 0) 'tv-usec) atime-usec)
    
    1587
    -    (setf (slot (deref tvp 1) 'tv-sec) mtime-sec)
    
    1588
    -    (setf (slot (deref tvp 1) 'tv-usec) mtime-usec)
    
    1589
    -    (void-syscall ("utimes" c-string (* (struct timeval)))
    
    1590
    -		  file
    
    1591
    -		  (cast tvp (* (struct timeval))))))
    
    1592
    -
    
    1593
    -(def-alien-routine ("ttyname" unix-ttyname) c-string
    
    1594
    -  (fd int))
    
    1595
    -
    
    1596
    -(def-alien-routine ("isatty" unix-isatty) boolean
    
    1597
    -  _N"Accepts a Unix file descriptor and returns T if the device
    
    1598
    -  associated with it is a terminal."
    
    1599
    -  (fd int))
    
    1600
    -
    
    1601
    -;;; pty.h
    
    1602
    -
    
    1603
    -(defun unix-openpty (name termp winp)
    
    1604
    -  _N"Create pseudo tty master slave pair with NAME and set terminal
    
    1605
    -   attributes according to TERMP and WINP and return handles for both
    
    1606
    -   ends in AMASTER and ASLAVE."
    
    1607
    -  (with-alien ((amaster int)
    
    1608
    -	       (aslave int))
    
    1609
    -    (values
    
    1610
    -     (int-syscall ("openpty" (* int) (* int) c-string (* (struct termios))
    
    1611
    -			     (* (struct winsize)))
    
    1612
    -		  (addr amaster) (addr aslave) name termp winp)
    
    1613
    -     amaster aslave)))
    
    1614
    -
    
    1615
    -(def-alien-type nil
    
    1616
    -  (struct utsname
    
    1617
    -    (sysname (array char 65))
    
    1618
    -    (nodename (array char 65))
    
    1619
    -    (release (array char 65))
    
    1620
    -    (version (array char 65))
    
    1621
    -    (machine (array char 65))
    
    1622
    -    (domainname (array char 65))))
    
    1623
    -
    
    1624
    -(defun unix-uname ()
    
    1625
    -  _N"Unix-uname returns the name and information about the current kernel. The
    
    1626
    -  values returned upon success are: sysname, nodename, release, version,
    
    1627
    -  machine, and domainname. Upon failure, 'nil and the 'errno are returned."
    
    1628
    -  (with-alien ((utsname (struct utsname)))
    
    1629
    -    (syscall* ("uname" (* (struct utsname)))
    
    1630
    -	      (values (cast (slot utsname 'sysname) c-string)
    
    1631
    -		      (cast (slot utsname 'nodename) c-string)
    
    1632
    -		      (cast (slot utsname 'release) c-string)
    
    1633
    -		      (cast (slot utsname 'version) c-string)
    
    1634
    -		      (cast (slot utsname 'machine) c-string)
    
    1635
    -		     (cast (slot utsname 'domainname) c-string))
    
    1636
    -	      (addr utsname))))
    
    1637
    -
    
    1638
    -;;; sys/ioctl.h
    
    1639
    -
    
    1640
    -(defun unix-ioctl (fd cmd arg)
    
    1641
    -  _N"Unix-ioctl performs a variety of operations on open i/o
    
    1642
    -   descriptors.  See the UNIX Programmer's Manual for more
    
    1643
    -   information."
    
    1644
    -  (declare (type unix-fd fd)
    
    1645
    -	   (type (unsigned-byte 32) cmd))
    
    1646
    -  (int-syscall ("ioctl" int unsigned-int (* char)) fd cmd arg))
    
    1647
    -
    
    1648
    -
    
    1649
    -;;; Unix-mkdir accepts a name and a mode and attempts to create the
    
    1650
    -;;; corresponding directory with mode mode.
    
    1651
    -
    
    1652
    -(defun unix-mkdir (name mode)
    
    1653
    -  _N"Unix-mkdir creates a new directory with the specified name and mode.
    
    1654
    -   (Same as those for unix-chmod.)  It returns T upon success, otherwise
    
    1655
    -   NIL and an error number."
    
    1656
    -  (declare (type unix-pathname name)
    
    1657
    -	   (type unix-file-mode mode))
    
    1658
    -  (void-syscall ("mkdir" c-string int) (%name->file name) mode))
    
    1659
    -
    
    1660
    -;;; timebits.h
    
    1661
    -
    
    1662
    -;; A time value that is accurate to the nearest
    
    1663
    -;; microsecond but also has a range of years.  
    
    1664
    -(def-alien-type nil
    
    1665
    -  (struct timeval
    
    1666
    -	  (tv-sec time-t)	; seconds
    
    1667
    -	  (tv-usec time-t)))	; and microseconds
    
    1668
    -
    
    1669
    -;;; sys/time.h
    
    1670
    -
    
    1671
    -;; Structure crudely representing a timezone.
    
    1672
    -;;   This is obsolete and should never be used. 
    
    1673
    -(def-alien-type nil
    
    1674
    -  (struct timezone
    
    1675
    -    (tz-minuteswest int)		; minutes west of Greenwich
    
    1676
    -    (tz-dsttime	int)))			; type of dst correction
    
    1677
    -
    
    1678
    -;; Type of the second argument to `getitimer' and
    
    1679
    -;; the second and third arguments `setitimer'. 
    
    1680
    -(def-alien-type nil
    
    1681
    -  (struct itimerval
    
    1682
    -    (it-interval (struct timeval))	; timer interval
    
    1683
    -    (it-value (struct timeval))))	; current value
    
    1684
    -
    
    1685
    -(defconstant ITIMER-REAL 0)
    
    1686
    -(defconstant ITIMER-VIRTUAL 1)
    
    1687
    -(defconstant ITIMER-PROF 2)
    
    1688
    -
    
    1689
    -(defun unix-getitimer (which)
    
    1690
    -  _N"Unix-getitimer returns the INTERVAL and VALUE slots of one of
    
    1691
    -   three system timers (:real :virtual or :profile). On success,
    
    1692
    -   unix-getitimer returns 5 values,
    
    1693
    -   T, it-interval-secs, it-interval-usec, it-value-secs, it-value-usec."
    
    1694
    -  (declare (type (member :real :virtual :profile) which)
    
    1695
    -	   (values t
    
    1696
    -		   (unsigned-byte 29)(mod 1000000)
    
    1697
    -		   (unsigned-byte 29)(mod 1000000)))
    
    1698
    -  (let ((which (ecase which
    
    1699
    -		 (:real ITIMER-REAL)
    
    1700
    -		 (:virtual ITIMER-VIRTUAL)
    
    1701
    -		 (:profile ITIMER-PROF))))
    
    1702
    -    (with-alien ((itv (struct itimerval)))
    
    1703
    -      (syscall* ("getitimer" int (* (struct itimerval)))
    
    1704
    -		(values T
    
    1705
    -			(slot (slot itv 'it-interval) 'tv-sec)
    
    1706
    -			(slot (slot itv 'it-interval) 'tv-usec)
    
    1707
    -			(slot (slot itv 'it-value) 'tv-sec)
    
    1708
    -			(slot (slot itv 'it-value) 'tv-usec))
    
    1709
    -		which (alien-sap (addr itv))))))
    
    1710
    -
    
    1711
    -(defun unix-setitimer (which int-secs int-usec val-secs val-usec)
    
    1712
    -  _N" Unix-setitimer sets the INTERVAL and VALUE slots of one of
    
    1713
    -   three system timers (:real :virtual or :profile). A SIGALRM signal
    
    1714
    -   will be delivered VALUE <seconds+microseconds> from now. INTERVAL,
    
    1715
    -   when non-zero, is <seconds+microseconds> to be loaded each time
    
    1716
    -   the timer expires. Setting INTERVAL and VALUE to zero disables
    
    1717
    -   the timer. See the Unix man page for more details. On success,
    
    1718
    -   unix-setitimer returns the old contents of the INTERVAL and VALUE
    
    1719
    -   slots as in unix-getitimer."
    
    1720
    -  (declare (type (member :real :virtual :profile) which)
    
    1721
    -	   (type (unsigned-byte 29) int-secs val-secs)
    
    1722
    -	   (type (integer 0 (1000000)) int-usec val-usec)
    
    1723
    -	   (values t
    
    1724
    -		   (unsigned-byte 29)(mod 1000000)
    
    1725
    -		   (unsigned-byte 29)(mod 1000000)))
    
    1726
    -  (let ((which (ecase which
    
    1727
    -		 (:real ITIMER-REAL)
    
    1728
    -		 (:virtual ITIMER-VIRTUAL)
    
    1729
    -		 (:profile ITIMER-PROF))))
    
    1730
    -    (with-alien ((itvn (struct itimerval))
    
    1731
    -		 (itvo (struct itimerval)))
    
    1732
    -      (setf (slot (slot itvn 'it-interval) 'tv-sec ) int-secs
    
    1733
    -	    (slot (slot itvn 'it-interval) 'tv-usec) int-usec
    
    1734
    -	    (slot (slot itvn 'it-value   ) 'tv-sec ) val-secs
    
    1735
    -	    (slot (slot itvn 'it-value   ) 'tv-usec) val-usec)
    
    1736
    -      (syscall* ("setitimer" int (* (struct timeval))(* (struct timeval)))
    
    1737
    -		(values T
    
    1738
    -			(slot (slot itvo 'it-interval) 'tv-sec)
    
    1739
    -			(slot (slot itvo 'it-interval) 'tv-usec)
    
    1740
    -			(slot (slot itvo 'it-value) 'tv-sec)
    
    1741
    -			(slot (slot itvo 'it-value) 'tv-usec))
    
    1742
    -		which (alien-sap (addr itvn))(alien-sap (addr itvo))))))
    
    1743
    -
    
    1744
    -
    
    1745
    -;;; termbits.h
    
    1746
    -
    
    1747
    -(def-alien-type cc-t unsigned-char)
    
    1748
    -(def-alien-type speed-t  unsigned-int)
    
    1749
    -(def-alien-type tcflag-t unsigned-int)
    
    1750
    -
    
    1751
    -(defconstant +NCCS+ 32
    
    1752
    -  _N"Size of control character vector.")
    
    1753
    -
    
    1754
    -(def-alien-type nil
    
    1755
    -  (struct termios
    
    1756
    -    (c-iflag tcflag-t)
    
    1757
    -    (c-oflag tcflag-t)
    
    1758
    -    (c-cflag tcflag-t)
    
    1759
    -    (c-lflag tcflag-t)
    
    1760
    -    (c-line cc-t)
    
    1761
    -    (c-cc (array cc-t #.+NCCS+))
    
    1762
    -    (c-ispeed speed-t)
    
    1763
    -    (c-ospeed speed-t)))
    
    1764
    -
    
    1765
    -;; c_cc characters
    
    1766
    -
    
    1767
    -(defmacro def-enum (inc cur &rest names)
    
    1768
    -  (flet ((defform (name)
    
    1769
    -	     (prog1 (when name `(defconstant ,name ,cur))
    
    1770
    -	       (setf cur (funcall inc cur 1)))))
    
    1771
    -    `(progn ,@(mapcar #'defform names))))
    
    1772
    -
    
    1773
    -(def-enum + 0 vintr vquit verase
    
    1774
    -	  vkill veof vtime
    
    1775
    -	  vmin vswtc vstart
    
    1776
    -	  vstop vsusp veol
    
    1777
    -	  vreprint vdiscard vwerase
    
    1778
    -	  vlnext veol2)
    
    1779
    -(defvar vdsusp vsusp)
    
    1780
    -
    
    1781
    -(def-enum + 0 tcsanow tcsadrain tcsaflush)
    
    1782
    -
    
    1783
    -;; c_iflag bits
    
    1784
    -(def-enum ash 1 tty-ignbrk tty-brkint tty-ignpar tty-parmrk tty-inpck
    
    1785
    -	  tty-istrip tty-inlcr tty-igncr tty-icrnl tty-iuclc
    
    1786
    -	  tty-ixon tty-ixany tty-ixoff 
    
    1787
    -	  tty-imaxbel)
    
    1788
    -
    
    1789
    -;; c_oflag bits
    
    1790
    -(def-enum ash 1 tty-opost tty-olcuc tty-onlcr tty-ocrnl tty-onocr
    
    1791
    -	  tty-onlret tty-ofill tty-ofdel tty-nldly)
    
    1792
    -
    
    1793
    -;; c_lflag bits
    
    1794
    -(def-enum ash 1 tty-isig tty-icanon tty-xcase tty-echo tty-echoe
    
    1795
    -	  tty-echok tty-echonl tty-noflsh
    
    1796
    -	  tty-tostop tty-echoctl tty-echoprt
    
    1797
    -	  tty-echoke tty-flusho
    
    1798
    -	  tty-pendin tty-iexten)
    
    1799
    -
    
    1800
    -(defun unix-tcgetattr (fd termios)
    
    1801
    -  _N"Get terminal attributes."
    
    1802
    -  (declare (type unix-fd fd))
    
    1803
    -  (void-syscall ("tcgetattr" int (* (struct termios))) fd termios))
    
    1804
    -
    
    1805
    -(defun unix-tcsetattr (fd opt termios)
    
    1806
    -  _N"Set terminal attributes."
    
    1807
    -  (declare (type unix-fd fd))
    
    1808
    -  (void-syscall ("tcsetattr" int int (* (struct termios))) fd opt termios))
    
    1809
    -
    
    1810
    -(defconstant writeown #o200 _N"Write by owner")
    
    1811
    -
    
    1812
    -;;; termios.h
    
    1813
    -
    
    1814
    -(defconstant terminal-speeds
    
    1815
    -  '#(0 50 75 110 134 150 200 300 600 1200 1800 2400
    
    1816
    -     4800 9600 19200 38400 57600 115200 230400))
    
    1817
    -
    
    1818
    -(defun unix-cfgetospeed (termios)
    
    1819
    -  _N"Get terminal output speed."
    
    1820
    -  (multiple-value-bind (speed errno)
    
    1821
    -      (int-syscall ("cfgetospeed" (* (struct termios))) termios)
    
    1822
    -    (if speed
    
    1823
    -	(values (svref terminal-speeds speed) 0)
    
    1824
    -      (values speed errno))))
    
    1825
    -
    
    1826
    -
    
    1827
    -;;; For asdf.  Well, only getenv, but might as well make it symmetric.
    
    1828
    -
    
    1829
    -;; Environment manipulation; man getenv(3)
    
    1830
    -(def-alien-routine ("getenv" unix-getenv) c-call:c-string
    
    1831
    -  (name c-call:c-string) 
    
    1832
    -  _N"Get the value of the environment variable named Name.  If no such
    
    1833
    -  variable exists, Nil is returned.")
    
    1834
    -
    
    1835
    -;; This doesn't exist in Solaris 8 but does exist in Solaris 10.
    
    1836
    -(def-alien-routine ("setenv" unix-setenv) c-call:int
    
    1837
    -  (name c-call:c-string)
    
    1838
    -  (value c-call:c-string)
    
    1839
    -  (overwrite c-call:int)
    
    1840
    -  _N"Adds the environment variable named Name to the environment with
    
    1841
    -  the given Value if Name does not already exist. If Name does exist,
    
    1842
    -  the value is changed to Value if Overwrite is non-zero.  Otherwise,
    
    1843
    -  the value is not changed.")
    
    1844
    -
    
    1845
    -
    
    1846
    -(def-alien-routine ("putenv" unix-putenv) c-call:int
    
    1847
    -  (name-value c-call:c-string)
    
    1848
    -  _N"Adds or changes the environment.  Name-value must be a string of
    
    1849
    -  the form \"name=value\".  If the name does not exist, it is added.
    
    1850
    -  If name does exist, the value is updated to the given value.")
    
    1851
    -
    
    1852
    -(def-alien-routine ("unsetenv" unix-unsetenv) c-call:int
    
    1853
    -  (name c-call:c-string)
    
    1854
    -  _N"Removes the variable Name from the environment")
    
    1855
    -
    
    1856
    -
    
    1857
    -;;; For slime, which wants to use unix-execve.
    
    1858
    -
    
    1859
    -(defmacro round-bytes-to-words (n)
    
    1860
    -  `(logand (the fixnum (+ (the fixnum ,n) 3)) (lognot 3)))
    
    1861
    -
    
    1862
    -;;;
    
    1863
    -;;; STRING-LIST-TO-C-STRVEC	-- Internal
    
    1864
    -;;; 
    
    1865
    -;;; STRING-LIST-TO-C-STRVEC is a function which takes a list of
    
    1866
    -;;; simple-strings and constructs a C-style string vector (strvec) --
    
    1867
    -;;; a null-terminated array of pointers to null-terminated strings.
    
    1868
    -;;; This function returns two values: a sap and a byte count.  When the
    
    1869
    -;;; memory is no longer needed it should be deallocated with
    
    1870
    -;;; vm_deallocate.
    
    1871
    -;;; 
    
    1872
    -(defun string-list-to-c-strvec (string-list)
    
    1873
    -  ;;
    
    1874
    -  ;; Make a pass over string-list to calculate the amount of memory
    
    1875
    -  ;; needed to hold the strvec.
    
    1876
    -  (let ((string-bytes 0)
    
    1877
    -	(vec-bytes (* 4 (1+ (length string-list)))))
    
    1878
    -    (declare (fixnum string-bytes vec-bytes))
    
    1879
    -    (dolist (s string-list)
    
    1880
    -      (check-type s simple-string)
    
    1881
    -      (incf string-bytes (round-bytes-to-words (1+ (length s)))))
    
    1882
    -    ;;
    
    1883
    -    ;; Now allocate the memory and fill it in.
    
    1884
    -    (let* ((total-bytes (+ string-bytes vec-bytes))
    
    1885
    -	   (vec-sap (system:allocate-system-memory total-bytes))
    
    1886
    -	   (string-sap (sap+ vec-sap vec-bytes))
    
    1887
    -	   (i 0))
    
    1888
    -      (declare (type (and unsigned-byte fixnum) total-bytes i)
    
    1889
    -	       (type system:system-area-pointer vec-sap string-sap))
    
    1890
    -      (dolist (s string-list)
    
    1891
    -	(declare (simple-string s))
    
    1892
    -	(let ((n (length s)))
    
    1893
    -	  ;; 
    
    1894
    -	  ;; Blast the string into place
    
    1895
    -	  #-unicode
    
    1896
    -	  (kernel:copy-to-system-area (the simple-string s)
    
    1897
    -				      (* vm:vector-data-offset vm:word-bits)
    
    1898
    -				      string-sap 0
    
    1899
    -				      (* (1+ n) vm:byte-bits))
    
    1900
    -	  #+unicode
    
    1901
    -	  (progn
    
    1902
    -	    ;; FIXME: Do we need to apply some kind of transformation
    
    1903
    -	    ;; to convert Lisp unicode strings to C strings?  Utf-8?
    
    1904
    -	    (dotimes (k n)
    
    1905
    -	      (setf (sap-ref-8 string-sap k)
    
    1906
    -		    (logand #xff (char-code (aref s k)))))
    
    1907
    -	    (setf (sap-ref-8 string-sap n) 0))
    
    1908
    -	  ;; 
    
    1909
    -	  ;; Blast the pointer to the string into place
    
    1910
    -	  (setf (sap-ref-sap vec-sap i) string-sap)
    
    1911
    -	  (setf string-sap (sap+ string-sap (round-bytes-to-words (1+ n))))
    
    1912
    -	  (incf i 4)))
    
    1913
    -      ;; Blast in last null pointer
    
    1914
    -      (setf (sap-ref-sap vec-sap i) (int-sap 0))
    
    1915
    -      (values vec-sap total-bytes))))
    
    1916
    -
    
    1917
    -(defun sub-unix-execve (program arg-list env-list)
    
    1918
    -  (let ((argv nil)
    
    1919
    -	(argv-bytes 0)
    
    1920
    -	(envp nil)
    
    1921
    -	(envp-bytes 0)
    
    1922
    -	result error-code)
    
    1923
    -    (unwind-protect
    
    1924
    -	(progn
    
    1925
    -	  ;; Blast the stuff into the proper format
    
    1926
    -	  (multiple-value-setq
    
    1927
    -	      (argv argv-bytes)
    
    1928
    -	    (string-list-to-c-strvec arg-list))
    
    1929
    -	  (multiple-value-setq
    
    1930
    -	      (envp envp-bytes)
    
    1931
    -	    (string-list-to-c-strvec env-list))
    
    1932
    -	  ;;
    
    1933
    -	  ;; Now do the system call
    
    1934
    -	  (multiple-value-setq
    
    1935
    -	      (result error-code)
    
    1936
    -	    (int-syscall ("execve"
    
    1937
    -			  c-string system-area-pointer system-area-pointer)
    
    1938
    -			 program argv envp)))
    
    1939
    -      ;; 
    
    1940
    -      ;; Deallocate memory
    
    1941
    -      (when argv
    
    1942
    -	(system:deallocate-system-memory argv argv-bytes))
    
    1943
    -      (when envp
    
    1944
    -	(system:deallocate-system-memory envp envp-bytes)))
    
    1945
    -    (values result error-code)))
    
    1946
    -
    
    1947
    -;;;; UNIX-EXECVE
    
    1948
    -(defun unix-execve (program &optional arg-list
    
    1949
    -			    (environment *environment-list*))
    
    1950
    -  _N"Executes the Unix execve system call.  If the system call suceeds, lisp
    
    1951
    -   will no longer be running in this process.  If the system call fails this
    
    1952
    -   function returns two values: NIL and an error code.  Arg-list should be a
    
    1953
    -   list of simple-strings which are passed as arguments to the exec'ed program.
    
    1954
    -   Environment should be an a-list mapping symbols to simple-strings which this
    
    1955
    -   function bashes together to form the environment for the exec'ed program."
    
    1956
    -  (check-type program simple-string)
    
    1957
    -  (let ((env-list (let ((envlist nil))
    
    1958
    -		    (dolist (cons environment)
    
    1959
    -		      (push (if (cdr cons)
    
    1960
    -				(concatenate 'simple-string
    
    1961
    -					     (string (car cons)) "="
    
    1962
    -					     (cdr cons))
    
    1963
    -				(car cons))
    
    1964
    -			    envlist))
    
    1965
    -		    envlist)))
    
    1966
    -    (sub-unix-execve (%name->file program) arg-list env-list)))
    
    1967
    -
    
    1968
    -(defun unix-fork ()
    
    1969
    -  _N"Executes the unix fork system call.  Returns 0 in the child and the pid
    
    1970
    -   of the child in the parent if it works, or NIL and an error number if it
    
    1971
    -   doesn't work."
    
    1972
    -  (int-syscall ("fork")))

  • src/lisp/Config.x86_common
    ... ... @@ -45,10 +45,11 @@ endif
    45 45
     CPPFLAGS := $(CPP_DEFINE_OPTIONS) $(CPP_INCLUDE_OPTIONS) 
    
    46 46
     CFLAGS += -Wstrict-prototypes -Wall -g -fno-omit-frame-pointer
    
    47 47
     
    
    48
    -# gcc 8.1.1 and 8.3.1 (and probably anything after 8.1.1?) won't
    
    49
    -# produce a working lisp with -O2.  Just use -O1.
    
    50
    -CFLAGS += -O1
    
    51
    -ASFLAGS = -g 
    
    48
    +# Default optimization level.  This can be changed in the individual
    
    49
    +# configs.
    
    50
    +COPT = -O2
    
    51
    +
    
    52
    +ASFLAGS = -g
    
    52 53
     
    
    53 54
     ASSEM_SRC = x86-assem.S
    
    54 55
     ARCH_SRC = x86-arch.c
    

  • src/lisp/Config.x86_darwin
    ... ... @@ -6,6 +6,7 @@ include Config.x86_common
    6 6
     # you have the SDK available.
    
    7 7
     MIN_VER = -mmacosx-version-min=10.6
    
    8 8
     
    
    9
    +CFLAGS += $(COPT)
    
    9 10
     CPPFLAGS += -DDARWIN $(MIN_VER) -m32
    
    10 11
     CFLAGS += -g3 -mtune=generic
    
    11 12
     ASFLAGS += -g3 $(MIN_VER)
    

  • src/lisp/Config.x86_freebsd
    ... ... @@ -3,6 +3,7 @@ include Config.x86_common
    3 3
     # Set the path to your verison of GCC here.
    
    4 4
     CC = gcc -m32
    
    5 5
     
    
    6
    +CFLAGS += $(COPT)
    
    6 7
     CPPFLAGS += -march=pentium4 -mfpmath=sse
    
    7 8
     
    
    8 9
     UNDEFSYMPATTERN = -Xlinker -u -Xlinker &
    

  • src/lisp/Config.x86_linux
    1 1
     # -*- Mode: makefile -*-
    
    2 2
     include Config.x86_common
    
    3 3
     
    
    4
    +# gcc 8.1.1 and 8.3.1 (and probably anything after 8.1.1?) won't
    
    5
    +# produce a working lisp with -O2.  Just use -O1.
    
    6
    +COPT = -O2
    
    7
    +CFLAGS += $(COPT)
    
    4 8
     CPPFLAGS += -m32 -D__NO_CTYPE -D_GNU_SOURCE
    
    5 9
     CFLAGS += -rdynamic  -march=pentium4 -mfpmath=sse -mtune=generic
    
    6 10
     
    

  • src/lisp/Config.x86_linux_clang
    ... ... @@ -3,6 +3,7 @@ include Config.x86_common
    3 3
     
    
    4 4
     CC = clang
    
    5 5
     CPPFLAGS += -m32 -D__NO_CTYPE -D_GNU_SOURCE
    
    6
    +CFLAGS += $(COPT)
    
    6 7
     CFLAGS += -march=pentium4 -mfpmath=sse -mtune=generic
    
    7 8
     
    
    8 9
     UNDEFSYMPATTERN = -Xlinker -u -Xlinker &
    

  • src/lisp/Config.x86_netbsd
    1 1
     # -*- Mode: makefile -*-
    
    2 2
     include Config.x86_common
    
    3 3
     
    
    4
    +CFLAGS += $(COPT)
    
    4 5
     CPPFLAGS += -march=pentium4 -mfpmath=sse
    
    5 6
     
    
    6 7
     UNDEFSYMPATTERN = -Xlinker -u -Xlinker &
    

  • src/lisp/Config.x86_solaris_sunc
    ... ... @@ -2,6 +2,7 @@
    2 2
     include Config.sparc_common
    
    3 3
     
    
    4 4
     CC = cc -xlibmieee -g
    
    5
    +CFLAGS += $(COPT)
    
    5 6
     CFLAGS += -Di386
    
    6 7
     CPP = cc -E
    
    7 8
     DEPEND_FLAGS = -xM1
    

  • src/lisp/gencgc.c
    ... ... @@ -8416,6 +8416,7 @@ char *
    8416 8416
     alloc(int nbytes)
    
    8417 8417
     {
    
    8418 8418
         void *new_obj;
    
    8419
    +
    
    8419 8420
     #if !(defined(sparc) || (defined(DARWIN) && defined(__ppc__)))
    
    8420 8421
         /*
    
    8421 8422
          * *current-region-free-pointer* is the same as alloc-tn (=
    
    ... ... @@ -8442,20 +8443,6 @@ alloc(int nbytes)
    8442 8443
     	    set_current_region_free((lispobj) new_free_pointer);
    
    8443 8444
                 break;
    
    8444 8445
     	} else if (bytes_allocated <= auto_gc_trigger) {
    
    8445
    -#if defined(i386) || defined(__x86_64)
    
    8446
    -            /*
    
    8447
    -             * Need to save and restore the FPU registers on x86, but only for
    
    8448
    -             * sse2.  See Ticket #61.
    
    8449
    -             *
    
    8450
    -             * Not needed by sparc or ppc because we never call alloc from
    
    8451
    -             * Lisp directly to do allocation.
    
    8452
    -             */
    
    8453
    -            FPU_STATE(fpu_state);
    
    8454
    -
    
    8455
    -            if (fpu_mode == SSE2) {
    
    8456
    -                save_fpu_state(fpu_state);
    
    8457
    -            }
    
    8458
    -#endif
    
    8459 8446
     	    /* Call gc_alloc.  */
    
    8460 8447
     	    boxed_region.free_pointer = (void *) get_current_region_free();
    
    8461 8448
     	    boxed_region.end_addr =
    
    ... ... @@ -8466,11 +8453,6 @@ alloc(int nbytes)
    8466 8453
     	    set_current_region_free((lispobj) boxed_region.free_pointer);
    
    8467 8454
     	    set_current_region_end((lispobj) boxed_region.end_addr);
    
    8468 8455
     
    
    8469
    -#if defined(i386) || defined(__x86_64)
    
    8470
    -            if (fpu_mode == SSE2) {
    
    8471
    -                restore_fpu_state(fpu_state);
    
    8472
    -            }
    
    8473
    -#endif
    
    8474 8456
                 break;
    
    8475 8457
     	} else {
    
    8476 8458
     	    /* Run GC and try again.  */
    

  • src/lisp/x86-arch.h
    ... ... @@ -17,16 +17,14 @@ extern boolean os_support_sse2(void);
    17 17
     #define FPU_STATE_SIZE 27
    
    18 18
     
    
    19 19
     /* 
    
    20
    - * Need 512 byte area, aligned on a 16-byte boundary.  So allocate
    
    21
    - * 512+16 bytes of space and let the routine adjust the appropriate
    
    22
    - * alignment.
    
    20
    + * Need 512 byte area, aligned on a 16-byte boundary.
    
    23 21
      */
    
    24
    -#define SSE_STATE_SIZE ((512+16)/4)
    
    22
    +#define SSE_STATE_SIZE 512
    
    25 23
     
    
    26 24
     /*
    
    27 25
      * Just use the SSE size for both x87 and sse2 since the SSE size is
    
    28
    - * enough for either.
    
    26
    + * enough for either.  Make sure it's on a 16-byte boundary.
    
    29 27
      */
    
    30
    -#define FPU_STATE(name)    int name[SSE_STATE_SIZE];
    
    28
    +#define FPU_STATE(name)    u_int8_t name[SSE_STATE_SIZE] __attribute__((aligned(16)))
    
    31 29
     
    
    32 30
     #endif

  • src/lisp/x86-assem.S
    ... ... @@ -382,7 +382,39 @@ ENDFUNC(fastcopy16)
    382 382
      * %eax = address
    
    383 383
      */
    
    384 384
     FUNCDEF(alloc_overflow_sse2)
    
    385
    -	STACK_PROLOGUE(20)
    
    385
    +	# Need 8*16 bytes for the xmm registers, and space to save ecx
    
    386
    +	# and edx, space for mxcsr, a temp, and one arg to pass to alloc.
    
    387
    +	# That's 8*16 + 5*4 = 148 bytes.  Might as well have a few
    
    388
    +	# more so the xmm0 area is 16-byte aligned. That makes it 160
    
    389
    +	# bytes.
    
    390
    +	#
    
    391
    +	# Stack looks like:
    
    392
    +	#
    
    393
    +	#      +160
    
    394
    +	#      +144 -> xmm7
    
    395
    +	#      +128 -> xmm6
    
    396
    +	#      +112 -> xmm5
    
    397
    +	#      +96  -> xmm4
    
    398
    +	#      +80  -> xmm3
    
    399
    +	#      +64  -> xmm2
    
    400
    +	#      +48  -> xmm1
    
    401
    +	#      +32  -> xmm0
    
    402
    +	#      +20  -> unused
    
    403
    +	#      +16  -> temp
    
    404
    +	#      +12  -> mxcsr
    
    405
    +	#      + 8  -> save ecx
    
    406
    +	#      + 4  -> save edx
    
    407
    +	#  esp + 0  -> arg for alloc
    
    408
    +	STACK_PROLOGUE(160)
    
    409
    +	movapd  %xmm0, (32 + 0*16)(%esp)
    
    410
    +	movapd  %xmm1, (32 + 1*16)(%esp)
    
    411
    +	movapd  %xmm2, (32 + 2*16)(%esp)
    
    412
    +	movapd  %xmm3, (32 + 3*16)(%esp)
    
    413
    +	movapd  %xmm4, (32 + 4*16)(%esp)
    
    414
    +	movapd  %xmm5, (32 + 5*16)(%esp)
    
    415
    +	movapd  %xmm6, (32 + 6*16)(%esp)
    
    416
    +	movapd  %xmm7, (32 + 7*16)(%esp)
    
    417
    +
    
    386 418
     	movl	%ecx, 8(%esp)	# Save ecx and edx registers
    
    387 419
     	movl	%edx, 4(%esp)
    
    388 420
     	stmxcsr 12(%esp)	# Save MXCSR
    
    ... ... @@ -398,10 +430,20 @@ FUNCDEF(alloc_overflow_sse2)
    398 430
     	movl	4(%esp), %edx	# Restore edx and ecx registers.  eax has the return value.
    
    399 431
     	movl	8(%esp), %ecx
    
    400 432
     	ldmxcsr	12(%esp)
    
    433
    +
    
    434
    +	movapd  (32 + 0*16)(%esp), %xmm0
    
    435
    +	movapd  (32 + 1*16)(%esp), %xmm1
    
    436
    +	movapd  (32 + 2*16)(%esp), %xmm2
    
    437
    +	movapd  (32 + 3*16)(%esp), %xmm3
    
    438
    +	movapd  (32 + 4*16)(%esp), %xmm4
    
    439
    +	movapd  (32 + 5*16)(%esp), %xmm5
    
    440
    +	movapd  (32 + 6*16)(%esp), %xmm6
    
    441
    +	movapd  (32 + 7*16)(%esp), %xmm7
    
    442
    +
    
    401 443
     	STACK_EPILOGUE
    
    402 444
     	ret
    
    403 445
     ENDFUNC(alloc_overflow_sse2)	
    
    404
    -		
    
    446
    +
    
    405 447
     #ifdef LINKAGE_TABLE
    
    406 448
     
    
    407 449
     /* Call into C code to resolve a linkage entry.  The initial code in the