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