5 The scope of this interface is "operating system calls on a typical
6 Unixlike platform". This is section 2 of the Unix manual, plus
7 section 3 calls that are (a) typically found in libc, but (b) not part
8 of the C standard. For example, we intend to provide support for
9 opendir() and readdir(), but not for printf(). Note that we do not
10 assert or imply any claim of conformance with the official standards
11 issued by POSIX groups or SVID or anyone else: we're simply using
12 "POSIX" in a generic sense to refer to Unix and Unix-like systems.
14 Some facilities are omitted where they offer absolutely no additional
15 use over some portable function, or would be actively dangerous to the
16 consistency of Lisp. Not all functions are available on all
17 platforms. [TBD: unavailable functions should (a) not exist, or (b)
18 exist but signal some kind of "not available on this platform" error]
20 The general intent is for a low-level interface. There are three
21 reasons for this: it's easier to write a high-level interface given a
22 low-level one than vice versa, there are fewer philosophical
23 disagreements about what it should look like, and the work of
24 implementing it is easily parallelisable - and in fact, can be
25 attempted on an as-needed basis by the various people who want it.
29 In SBCL this interface is in the SB-POSIX package. This package
30 contains a Lisp function for each supported Unix function, and a
31 variable or constant for each supported unix constant. A symbol name
32 is derived from the C binding's name, by (a) uppercasing, then (b)
33 removing leading underscores (#\_) then replacing remaining underscore
34 characters with the hyphen (#\-). The requirement to uppercase is so
35 that in a standard upcasing reader the user may write posix:creat
36 instead of posix:|creat| as would otherise be required - some
37 extra-standard implementations may have alternative means to achieve
40 No other changes to "Lispify" symbol names are made, so creat()
41 becomes CREAT, not CREATE
43 The user is encouraged not to (USE-PACKAGE :SB-POSIX) but instead to
44 use the SB-POSIX: prefix on all references, as some of our symbols
45 have the same name as CL symbols (OPEN, CLOSE, SIGNAL etc).
47 [ Rationale: We use similar names to the C bindings so that unix
48 manual pages can be used for documentation. To avoid name clashes
49 with CL or other functions, the approaches considered were (a) prefix
50 the names of clashing symbols with "POSIX-" or similar, (b) prefix
51 _all_ symbols with "POSIX-", (c) use the packaging system to resolve
52 ambiguities. (a) was rejected as the set of symbols we may
53 potentially clash with is not fixed (for example, if new symbols are
54 added to SB-EXT) so symbols might have to be renamed over the lifetime
55 of SB-POSIX, which is not good. The choice between (b) and (c) was
56 made on the grounds that POSIX-OPEN is about as much typing as
57 SB-POSIX:OPEN anyway, and symbol munging is, the author feels,
58 slightly tacky, when there's a package system available to do it more
64 Some functions accept objects such as filenames or file
65 descriptors. In the C binding to POSIX these are represented as
66 strings and small integers respectively. For the Lisp programmer's
67 convenience we introduce designators such that CL pathnames or open
68 streams can be passed to these functions.
72 A file-descriptor is a non-negative small integer.
74 A file-stream is a designator for a file-descriptor: the streams file
75 descriptor is extracted. Note that mixing io operations on a stream
76 with operations directly on its descriptor may produce unexpected
77 results if the stream is buffered.
81 A filename is a string.
83 A pathname is a designator for a filename: the filename is computed
84 using the same mechanism as the implementation would use to map
85 pathnames to OS filenames internally.
87 In an implementation that supports pathnames to files on other hosts,
88 using mechanisms not available to the underlying OS (for example,
89 using an FTP or HTTP client in the Lisp implementation), the effect
90 of supplying this interface with a pathname to such a file is undefined.
95 A buffer is an opaque object which represents an area of memory that
96 system calls may access. It has accessors BUFFER-START and
97 BUFFER-LENGTH, and can be created using ALLOCATE-BUFFER or GET-BUFFER.
99 [ TODO: GET-BUFFER is a silly name. Come up with a better one ]
101 The object NIL is a designator for a buffer, meaning a NULL pointer.
103 A vector of (UNSIGNED-BYTE 8) is a designator for a buffer: it is
104 converted to a buffer of appropriate start and length using an
105 identity mapping. This may or may not involve creating a copy of the
108 A vector of CHARACTER is a designator for a buffer: it is converted to
109 a buffer of appropriate start and length using an implementation-
110 defined transformation that obviously depends on the implementation's
111 representation of characters. This may or may not involve creating a
114 Implementations may optionally extend these designators to include
115 other types - for example, types that already exist in the
116 implementation's FFI.
118 ** Structures, unions
120 C structures and unions are opaque to Lisp and may be implemented
121 using any appropriate method. Structure names are chosen according to
122 the general rules for symbols.
124 Accessors must be provided for each documented field in the
125 structure. These are named structure-name-field-name where the two
126 components are chosen according to the general rules, with the
127 exception that in cases where all fields in a given structure have a
128 common prefix, that prefix is omitted. For example, stat.st_dev in C
129 becomes STAT-DEV in Lisp.
131 For any structure that the user may need to allocate himself, there
132 must also be a MAKE-structure-name function. This takes keyword
133 arguments with names deriving from each documented field name
134 according to the general rules for symbols.
136 [ TDB: GC issues for buffers/structures/unions: probably a
137 WITHOUT-MOVING macro or similar that will stop them from being moved
138 or collected during its extent ]
141 ** Type conversion functions
143 For each of these types there is a function of the same name that
144 converts any valid designator for the type into an object of said type.
146 This example is merely an example: actual output will vary between
147 systems, implementations and environments
149 (with-open-file (o "/tmp/foo" :direction :output)
150 (sb-posix:file-descriptor o))
153 [ TBD: some memorable and nicely uniform protocol for transforming
154 objects of these new types into instances of the Lisp-friendly types
155 that may designate them: e.g how to get a stream from a fd ]
158 * Function parameters
160 The calling convention is modelled after that of CMUCL's UNIX package:
161 in particular, it's like the C interface except that
163 a) length arguments are omitted or optional where the sensible value
164 is obvious. For example,
166 (read fd buffer &optional (length (length buffer))) => bytes-read
168 b) where C simulates "out" parameters using pointers (for instance, in
169 pipe() or socketpair()) these may be optional or omitted in the Lisp
170 interface: if not provided, appropriate objects will be allocated and
171 returned (using multiple return values if necessary).
173 c) some functions accept objects such as filenames or file
174 descriptors. Wherever these are specified as such in the C bindings,
175 the Lisp interface accepts designators for them as specified in the
176 'Types' section above
178 [ Rationale: Keeping exact 1:1 correspondence with C conventions is
179 less important here, as the function argument list can easily be
180 accessed to find out exactly what the arguments are. Designators
181 are primarily a convenience feature ]
183 * Function return values
185 The return value is usually the same as for the C binding, except in
186 error cases: where the C function is defined as returning some
187 sentinel value and setting "errno" on error, we instead signal an
188 error of type SYSCALL-ERROR. The actual error value ("errno") is
189 stored in this condition and can be accessed with SYSCALL-ERRNO.
190 [TBA: some interface to strerror, to get the user-readable translation
193 We do not automatically translate the returned value into "Lispy"
194 objects - for example, SB-POSIX:OPEN returns a small integer, not a
195 stream. Exception: boolean-returning functions (or, more commonly,
196 macros) do not return a C integer, but instead a lisp boolean [ or
197 maybe "true"/"false" in CLtS parlance ]; the rationale behind this
198 exception is that there is nothing that can be meaningfully done with
199 the boolean except test for truth or falsity -- it cannot be passed
200 meaningfully to other POSIX functions.
202 [ Rationale: This is an interface to POSIX, not a high-level interface
203 that uses POSIX, and many people using it will actually want to mess
204 with the file descriptors directly. People needing Lispy interfaces
205 can implement them atop this - or indeed, use the existing COMMON-LISP
206 package, which already has many high-level constructs built on top of
207 the operating system ;-) ]
212 The initial implementation is in contrib/sb-posix, and being filled
213 out on an as-needed basis. Contributions following these style rules
214 are welcome from anyone who writes them, provided the author is happy
215 to release the code as Public Domain or MIT-style licence.
217 See/update the TODO list for current status
221 See designator.lisp, add a define-designator form
225 The use of DEFINE-CALL macro in interface.lisp should be obvious from
226 the existing examples, if less so from the macroexpansion
234 buffers that refer to C stuff are probably not movable by GC anyway
236 a buffer that refers to a Lisp object may have trouble if the Lisp