Fixes for Darwin/OSX.
[cl-gtk2.git] / glib / glib.lisp
1 (defpackage :glib
2   (:use :cl :cffi :iter)
3   (:export #:at-init
4            #:gsize
5            #:gssize
6            #:goffset
7            #:*glib-major-version*
8            #:*glib-minor-version*
9            #:*glib-micro-version*
10            #:*glib-binary-age*
11            #:*glib-interface-age*
12            #:g-free
13            #:glist
14            #:gstrv
15            #:g-malloc
16            #:g-strdup
17            #:g-string
18            #:gslist
19            #:g-quark
20            #:+g-priority-high+
21            #:+g-priority-default+
22            #:+g-priority-high-idle+
23            #:+g-priority-default-idle+
24            #:+g-priority-low+
25            #:g-idle-add-full
26            #:g-idle-add
27            #:g-timeout-add-full
28            #:g-source-remove
29            #:at-finalize
30            #:with-g-error
31            #:with-catching-to-g-error
32            #:g-error-condition
33            #:g-error-condition-domain
34            #:g-error-condition-code
35            #:g-error-condition-message
36            #:g-spawn-flags
37            #:push-library-version-features
38            #:foreign-library-minimum-version-mismatch
39            #:require-library-version)
40   (:documentation
41    "Cl-gtk2-glib is wrapper for @a[http://library.gnome.org/devel/glib/]{GLib}."))
42
43 (in-package :glib)
44
45 (eval-when (:compile-toplevel :load-toplevel :execute)
46   (defvar *initializers-table* (make-hash-table :test 'equalp))
47   (defvar *initializers* nil)
48   (defun register-initializer (key fn)
49     (unless (gethash key *initializers-table*)
50       (setf (gethash key *initializers-table*) t
51             *initializers* (nconc *initializers* (list fn)))))
52   (defvar *finalizers-table* (make-hash-table :test 'equalp))
53   (defvar *finalizers* nil)
54   (defun register-finalizer (key fn)
55     (unless (gethash key *finalizers-table*)
56       (setf (gethash key *finalizers-table*) t
57             *finalizers* (nconc *finalizers* (list fn))))))
58
59 (defun run-initializers ()
60   (iter (for fn in *initializers*)
61         (funcall fn)))
62
63 (defun run-finalizers ()
64   (iter (for fn in *finalizers*)
65         (funcall fn)))
66
67 #+sbcl
68 (pushnew 'run-initializers sb-ext:*init-hooks*)
69 #+openmcl
70 (pushnew 'run-initializers ccl:*restore-lisp-functions*)
71
72 #+sbcl
73 (pushnew 'run-finalizers sb-ext:*save-hooks*)
74 #+openmcl
75 (pushnew 'run-finalizers ccl:*save-exit-functions*)
76
77 (defmacro at-init ((&rest keys) &body body)
78   "
79 @arg[keys]{list of expression}
80 @arg[body]{the code}
81 Runs the code normally but also schedules the code to be run at image load time.
82 It is used to reinitialize the libraries when the dumped image is loaded. (Works only on SBCL for now).
83
84 At-init form may be called multiple times. The same code from should not be run multiple times at initialization time (in best case, this will only slow down initialization, in worst case, the code may crash). To ensure this, every @code{at-init} expression is added to hash-table with the @code{body} and @code{keys} as a composite key. This ensures that the same code is only executed once (once on the same set of parameters).
85
86 Example:
87 @begin{pre}
88 \(defmethod initialize-instance :after ((class gobject-class) &key &allow-other-keys)
89   (register-object-type (gobject-class-g-type-name class) (class-name class))
90   (at-init (class) (initialize-gobject-class-g-type class)))
91 @end{pre}
92
93 In this example, for every @code{class}, @code{(initialize-gobject-class-g-type class)} will be called only once.
94 "
95   `(progn (register-initializer (list ,@keys ',body) (lambda () ,@body))
96           ,@body))
97
98 (defmacro at-finalize ((&rest keys) &body body)
99   `(register-finalizer (list ,@keys ',body) (lambda () ,@body)))
100
101 (at-init ()
102   (eval-when (:compile-toplevel :load-toplevel :execute)
103     (define-foreign-library glib
104       ((:and :unix (:not :darwin)) (:or "libglib-2.0.so.0" "libglib-2.0.so"))
105       (:darwin (:or "libglib-2.0.0.dylib" "libglib-2.0.dylib"))
106       (:windows "libglib-2.0-0.dll")
107       (t (:default "libglib-2.0"))))
108   (eval-when (:compile-toplevel :load-toplevel :execute)
109     (define-foreign-library gthread
110       ((:and :unix (:not :darwin))  (:or "libgthread-2.0.so.0"  "libgthread-2.0.so"))
111       (:darwin (:or "libgthread-2.0.0.dylib"  "libgthread-2.0.dylib"))
112       (:windows "libgthread-2.0-0.dll")
113       (t "libgthread-2.0")))
114
115   (use-foreign-library glib)
116   (use-foreign-library gthread))
117
118 (defmacro push-library-version-features (library-name major-version-var minor-version-var &body versions)
119   `(eval-when (:load-toplevel :execute)
120      ,@(iter (for (major minor) on versions by #'cddr)
121              (collect
122                  `(when (or (and (= ,major-version-var ,major) (>= ,minor-version-var ,minor))
123                             (> ,major-version-var ,major))
124                     (pushnew ,(intern (format nil "~A-~A.~A" (string library-name) major minor) (find-package :keyword)) *features*))))))
125
126 (define-condition foreign-library-minimum-version-mismatch (error)
127   ((library :initarg :library :reader .library)
128    (minimum-version :initarg :minimum-version :reader .minimum-version)
129    (actual-version :initarg :actual-version :reader .actual-version))
130   (:report (lambda (c s)
131              (format s "Library ~A has too old version: it is ~A but required to be at least ~A"
132                      (.library c)
133                      (.actual-version c)
134                      (.minimum-version c)))))
135
136 (defun require-library-version (library min-major-version min-minor-version major-version minor-version)
137   (unless (or (> major-version min-major-version)
138               (and (= major-version min-major-version)
139                    (>= minor-version min-minor-version)))
140     (restart-case
141         (error 'foreign-library-minimum-version-mismatch
142                :library library
143                :minimum-version (format nil "~A.~A" min-major-version min-minor-version)
144                :actual-version (format nil "~A.~A" major-version minor-version))
145       (ignore () :report "Ignore version requirement" nil))))
146
147 ;;
148 ;; Glib Fundamentals
149 ;;
150
151 ;;
152 ;; Fundamentals - Basic types
153 ;;
154
155
156 ;; TODO: not sure about these: for amd64 they are ok
157 (eval-when (:compile-toplevel :load-toplevel :execute)
158   (cond
159     ((cffi-features:cffi-feature-p :x86-64) (defctype gsize :uint64))
160     ((cffi-features:cffi-feature-p :x86) (defctype gsize :ulong))
161     ((cffi-features:cffi-feature-p :ppc32) (defctype gsize :uint32))
162     ((cffi-features:cffi-feature-p :ppc64) (defctype gsize :uint64))
163     (t (error "Can not define 'gsize', unknown CPU architecture (known are x86 and x86-64)"))))
164
165 (defctype gssize :long)
166
167 (defctype goffset :uint64)
168
169
170 ;;
171 ;; Fundamentals - Version information
172 ;;
173
174 (defcvar (*glib-major-version* "glib_major_version" :read-only t :library glib) :uint)
175 (defcvar (*glib-minor-version* "glib_minor_version" :read-only t :library glib) :uint)
176 (defcvar (*glib-micro-version* "glib_micro_version" :read-only t :library glib) :uint)
177 (defcvar (*glib-binary-age* "glib_binary_age" :read-only t :library glib) :uint)
178 (defcvar (*glib-interface-age* "glib_interface_age" :read-only t :library glib) :uint)
179
180 (push-library-version-features glib *glib-major-version* *glib-micro-version*
181   2 2
182   2 4
183   2 6
184   2 8
185   2 10
186   2 12
187   2 14
188   2 16
189   2 18
190   2 20
191   2 22)
192
193 (require-library-version "Glib" 2 20 *glib-major-version* *glib-minor-version*)
194
195 ;;
196 ;; Omitted:
197 ;; Limits of Basic Types, Standard Macros, Type Conversion Macros, Byte Order Macros, 
198 ;; Numerical Definitions, Miscellaneous Macros, Atomic operations
199 ;;
200
201 ;; Core Application Support - The Main Event Loop
202
203 (defcstruct g-main-loop)
204 (defcstruct g-main-context)
205 (defcstruct g-source)
206 (defcstruct g-source-funcs
207   (prepare :pointer)
208   (check :pointer)
209   (dispatch :pointer)
210   (finalize :pointer)
211   (closure-callback :pointer)
212   (closure-marshal :pointer))
213 (defcstruct g-source-callback-funcs
214   (ref :pointer)
215   (unref :pointer)
216   (get :pointer))
217 (defcstruct g-cond)
218 (defcstruct g-mutex)
219
220 (defcstruct g-poll-fd
221   (fd :int) ;; TODO: #if defined (G_OS_WIN32) && GLIB_SIZEOF_VOID_P == 8
222   (events :ushort)
223   (revent :ushort))
224
225 (defcstruct g-time-val
226   (seconds :long)
227   (microseconds :long))
228
229 (defcstruct g-thread)
230
231 (defcfun (g-main-loop-new "g_main_loop_new" :library glib) (:pointer g-main-loop)
232   (context (:pointer g-main-context))
233   (is-running :boolean))
234
235 (defcfun (g-main-loop-ref "g_main_loop_ref" :library glib) (:pointer g-main-loop)
236   (loop (:pointer g-main-loop)))
237
238 (defcfun (g-main-loop-unref "g_main_loop_unref" :library glib) (:pointer g-main-loop)
239   (loop (:pointer g-main-loop)))
240
241 (defcfun (g-main-loop-run "g_main_loop_run" :library glib) :void
242   (loop (:pointer g-main-loop)))
243
244 (defcfun (g-main-loop-quit "g_main_loop_quit" :library glib) :void
245   (loop (:pointer g-main-loop)))
246
247 (defcfun (g-main-loop-is-running "g_main_loop_is_running" :library glib) :boolean
248   (loop (:pointer g-main-loop)))
249
250 (defcfun (g-main-loop-get-context "g_main_loop_get_context" :library glib) (:pointer g-main-context)
251   (loop (:pointer g-main-loop)))
252
253 (defconstant +g-priority-high+ -100 "Use this for high priority event sources. It is not used within GLib or GTK+.")
254 (defconstant +g-priority-default+ 0 "Use this for default priority event sources. In GLib this priority is used when adding timeout functions with g_timeout_add(). In GDK this priority is used for events from the X server.")
255 (defconstant +g-priority-high-idle+ 100 "Use this for high priority idle functions. GTK+ uses @variable{+g-priority-high-idle+} + 10 for resizing operations, and @variable{+g-priority-high-idle+} + 20 for redrawing operations. (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)")
256 (defconstant +g-priority-default-idle+ 200 "Use this for default priority idle functions. In GLib this priority is used when adding idle functions with g_idle_add().")
257 (defconstant +g-priority-low+ 300 "Use this for very low priority background tasks. It is not used within GLib or GTK+.")
258
259 (defcfun (g-main-context-new "g_main_context_new" :library glib) (:pointer g-main-context))
260
261 (defcfun (g-main-context-ref "g_main_context_ref" :library glib) (:pointer g-main-context)
262   (context (:pointer g-main-context)))
263
264 (defcfun (g-main-context-unref "g_main_context_unref" :library glib) (:pointer g-main-context)
265   (context (:pointer g-main-context)))
266
267 (defcfun (g-main-context-default "g_main_context_default" :library glib) (:pointer g-main-context))
268
269 (defcfun (g-main-context-iteration "g_main_context_iteration" :library glib) :boolean
270   (context (:pointer g-main-context))
271   (may-block :boolean))
272
273 (defcfun (g-main-context-pending "g_main_context_pending" :library glib) :boolean
274   (context (:pointer g-main-context)))
275
276 (defcfun (g-main-context-find-source-by-id "g_main_context_find_source_by_id" :library glib) (:pointer g-source)
277   (context (:pointer g-main-context))
278   (source-id :uint))
279
280 (defcfun (g-main-context-find-source-by-user-data "g_main_context_find_source_by_user_data" :library glib) (:pointer g-source)
281   (context (:pointer g-main-context))
282   (user-data :pointer))
283
284 (defcfun (g-main-context-find-source-by-funcs-user-data "g_main_context_find_source_by_funcs_user_data" :library glib) (:pointer g-source)
285   (context (:pointer g-main-context))
286   (funcs (:pointer g-source-funcs))
287   (user-data :pointer))
288
289 (defcfun (g-main-context-wakeup "g_main_context_wakeup" :library glib) :void
290   (context (:pointer g-main-context)))
291
292 (defcfun (g-main-context-acquire "g_main_context_acquire" :library glib) :boolean
293   (context (:pointer g-main-context)))
294
295 (defcfun (g-main-context-release "g_main_context_release" :library glib) :void
296   (context (:pointer g-main-context)))
297
298 (defcfun (g-main-context-is-owner "g_main_context_is_owner" :library glib) :boolean
299   (context (:pointer g-main-context)))
300
301 (defcfun (g-main-context-wait "g_main_context_wait" :library glib) :boolean
302   (context (:pointer g-main-context))
303   (cond (:pointer g-cond))
304   (mutex (:pointer g-mutex)))
305
306 (defcfun (g_main_context_prepare "g_main_context_prepare" :library glib) :boolean
307   (context (:pointer g-main-context))
308   (priority-ret (:pointer :int)))
309
310 (defcfun (g_main_context_query "g_main_context_query" :library glib) :int
311   (context (:pointer g-main-context))
312   (max-priority :int)
313   (timeout-ret (:pointer :int))
314   (fds-ret (:pointer g-poll-fd))
315   (n-dfs :int))
316
317 (defcfun (g-main-context-check "g_main_context_check" :library glib) :int
318   (context (:pointer g-main-context))
319   (max-priority :int)
320   (fds (:pointer g-poll-fd))
321   (n-fds :int))
322
323 (defcfun (g-main-context-dispatch "g_main_context_dispatch" :library glib) :void
324   (context (:pointer g-main-context)))
325
326 (defcfun (g-main-context-set-poll-func "g_main_context_set_poll_func" :library glib) :void
327   (context (:pointer g-main-context))
328   (func :pointer))
329
330 (defcfun (g-main-context-get-poll-func "g_main_context_get_poll_func" :library glib) :pointer
331   (context (:pointer g-main-context)))
332
333 (defcfun (g-main-context-add-poll "g_main_context_add_poll" :library glib) :void
334   (context (:pointer g-main-context))
335   (fd (:pointer g-poll-fd))
336   (priority :int))
337
338 (defcfun (g-main-context-remove-poll "g_main_context_remove_poll" :library glib) :void
339   (context (:pointer g-main-context))
340   (fd (:pointer g-poll-fd)))
341
342 (defcfun (g-main-depth "g_main_depth" :library glib) :int)
343
344 (defcfun (g-main-current-source "g_main_current_source" :library glib) (:pointer g-source))
345
346 (defcfun (g-timeout-source-new "g_timeout_source_new" :library glib) (:pointer g-source)
347   (interval-milliseconds :int))
348
349 (defcfun (g-timeout-source-new-seconds "g_timeout_source_new_seconds" :library glib) (:pointer g-source)
350   (interval-seconds :int))
351
352 (defcfun (g-timeout-add "g_timeout_add" :library glib) :uint
353   (interval-milliseconds :uint)
354   (function :pointer)
355   (data :pointer))
356
357 (defcfun (g-timeout-add-full "g_timeout_add_full" :library glib) :uint
358   (priority :int)
359   (interval-milliseconds :uint)
360   (function :pointer)
361   (data :pointer)
362   (destroy-notify :pointer))
363
364 (defcfun (g-timeout-add-seconds "g_timeout_add_seconds" :library glib) :uint
365   (interval-seconds :uint)
366   (function :pointer)
367   (data :pointer))
368
369 (defcfun (g-timeout-add-seconds-full "g_timeout_add_seconds_full" :library glib) :uint
370   (priority :int)
371   (interval-seconds :uint)
372   (function :pointer)
373   (data :pointer)
374   (destroy-notify :pointer))
375
376 (defcfun (g-idle-source-new "g_idle_source_new" :library glib) (:pointer g-source))
377
378 (defcfun (g-idle-add "g_idle_add" :library glib) :uint
379   (function :pointer)
380   (data :pointer))
381
382 (defcfun (g-idle-add-full "g_idle_add_full" :library glib) :uint
383   "A low-level function for adding callbacks to be called from main loop. Wrapper around g_idle_add_full.
384 Adds a function to be called whenever there are no higher priority events pending. If the function returns FALSE it is automatically removed from the list of event sources and will not be called again.
385 @arg[priority]{an integer specifying the priority. See @variable{+g-priority-default+}, @variable{+g-priority-default-idle+}, @variable{+g-priority-high+}, @variable{+g-priority-high-idle+}, @variable{+g-priority-low+}.}
386 @arg[function]{pointer to callback that will be called. Callback should accept a single pointer argument and return a boolean FALSE if it should be removed}
387 @arg[data]{pointer that will be passed to callback function}
388 @arg[notify]{function that will be called when callback is no more needed. It will receive the @code{data} argument}"
389   (priority :uint)
390   (function :pointer)
391   (data :pointer)
392   (notify :pointer))
393
394 (defcfun (g-idle-remove-by-data "g_idle_remove_by_data" :library glib) :boolean
395   (data :pointer))
396
397 ;(defctype g-pid :int) ;;TODO: might work on amd64 linux, but on others
398
399 ;; Omitted GPid, g_child_add_watch, g_child_add_watch_full
400
401 (defcfun (g-source-new "g_source_new" :library glib) (:pointer g-source)
402   (source-funcs (:pointer g-source-funcs))
403   (struct-size :uint))
404
405 (defcfun (g-source-ref "g_source_ref" :library glib) (:pointer g-source)
406   (source (:pointer g-source)))
407
408 (defcfun (g-source-unref "g_source_unref" :library glib) :void
409   (source (:pointer g-source)))
410
411 (defcfun (g-source-set-funcs "g_source_set_funcs" :library glib) :void
412   (source (:pointer g-source))
413   (funcs (:pointer g-source-funcs)))
414
415 (defcfun (g-source-attach "g_source_attach" :library glib) :uint
416   (source (:pointer g-source))
417   (context (:pointer g-main-context)))
418
419 (defcfun (g-source-destroy "g_source_destroy" :library glib) :void
420   (source (:pointer g-source)))
421
422 (defcfun (g-source-is-destroyed "g_source_is_destroyed" :library glib) :boolean
423   (source (:pointer g-source)))
424
425 (defcfun (g-source-set-priority "g_source_set_priority" :library glib) :void
426   (source (:pointer g-source))
427   (priority :int))
428
429 (defcfun (g-source-get-priority "g_source_get_priority" :library glib) :int
430   (source (:pointer g-source)))
431
432 (defcfun (g-source-set-can-recurse "g_source_set_can_recurse" :library glib) :void
433   (source (:pointer g-source))
434   (can-recurse :boolean))
435
436 (defcfun (g-source-get-can-recurse "g_source_get_can_recurse" :library glib) :boolean
437   (source (:pointer g-source)))
438
439 (defcfun (g-source-get-id "g_source_get_id" :library glib) :uint
440   (source (:pointer g-source)))
441
442 (defcfun (g-source-get-context "g_source_get_context" :library glib) (:pointer g-main-context)
443   (source (:pointer g-source)))
444
445 (defcfun (g-source-set-callback "g_source_set_callback" :library glib) :void
446   (source (:pointer g-source))
447   (func :pointer)
448   (data :pointer)
449   (notify :pointer))
450
451 (defcfun (g-source-add-poll "g_source_add_poll" :library glib) :void
452   (source (:pointer g-source))
453   (fd (:pointer g-poll-fd)))
454
455 (defcfun (g-source-remove-poll "g_source_remove_poll" :library glib) :void
456   (source (:pointer g-source))
457   (fd (:pointer g-poll-fd)))
458
459 (defcfun (g-source-get-current-time "g_source_get_current_time" :library glib) :void
460   (source (:pointer g-source))
461   (timeval-ret (:pointer g-time-val)))
462
463 (defcfun (g-source-remove "g_source_remove" :library glib) :boolean
464   (id :uint))
465
466 (defcfun (g-source-remove-by-funcs-user-data "g_source_remove_by_funcs_user_data" :library glib) :boolean
467   (funcs (:pointer g-source-funcs))
468   (data :pointer))
469
470 (defcfun (g-source-remove-by-user-data "g_source_remove_by_user_data" :library glib) :boolean
471   (data :pointer))
472
473 ;;
474 ;; Core Application Support - Threads
475 ;;
476
477 (defcenum g-thread-error
478   :g-thread-error-again)
479
480 ;omitted: struct GThreadFunctions
481
482 (defcfun (g-thread-init "g_thread_init") :void
483   (vtable :pointer))
484
485 (defcfun g-thread-get-initialized :boolean)
486
487 (at-init ()
488   (unless (g-thread-get-initialized)
489     (g-thread-init (null-pointer))))
490
491 (defcenum g-thread-priority
492   :g-thread-priority-low
493   :g-thread-priority-normal
494   :g-thread-priority-hight
495   :g-thread-priority-urgent)
496
497 ;omitted: g_thread_create, g_thread_create_full, g_thread_yield, g_thread_exit, g_thread_foreach
498
499 (defcfun (g-thread-self "g_thread_self" :library glib) (:pointer g-thread))
500
501 (defcfun (g-thread-join "g_thread_join" :library glib) :pointer
502   (thread (:pointer g-thread)))
503
504 (defcfun (g-thread-priority "g_thread_set_priority" :library glib) :void
505   (thread (:pointer g-thread))
506   (priority g-thread-priority))
507
508 ;;;; TODO: Commented g_mutex_*, g_cond* because they are not functions, but called through dispatch table
509
510 ;; (defcfun (g-mutex-new "g_mutex_new" :library glib) (:pointer g-mutex))
511
512 ;; (defcfun (g-mutex-lock "g_mutex_lock" :library glib) :void
513 ;;   (mutex (:pointer g-mutex)))
514
515 ;; (defcfun (g-mutex-try-lock "g_mutex_trylock" :library glib) :boolean
516 ;;   (mutex (:pointer g-mutex)))
517
518 ;; (defcfun (g-mutex-free "g_mutex_free" :library glib) :void
519 ;;   (mutex (:pointer g-mutex)))
520
521 ;omitted: GStaticMutex, GStaticRWLock stuff
522
523 ;; (defcfun (g-cond-new "g_cond_new" :library glib) (:pointer g-cond))
524
525 ;; (defcfun (g-cond-signal "g_cond_signal" :library glib) :void
526 ;;   (cond (:pointer g-cond)))
527
528 ;; (defcfun (g-cond-broadcast "g_cond_broadcast" :library glib) :void
529 ;;   (cond (:pointer g-cond)))
530
531 ;; (defcfun (g-cond-wait "g_cond_wait" :library glib) :void
532 ;;   (cond (:pointer g-cond))
533 ;;   (mutex (:pointer g-mutex)))
534
535 ;; (defcfun (g-cond-timed-wait "g_cond_timed_wait" :library glib) :boolean
536 ;;   (cond (:pointer g-cond))
537 ;;   (mutex (:pointer g-mutex))
538 ;;   (abs-time (:pointer g-time-val)))
539
540 ;; (defcfun (g-cond-free "g_cond_free" :library glib) :void
541 ;;   (cond (:pointer g-cond)))
542
543 ;omitted: GPrivate, GOnce stuff
544
545 ;omitted: Thread pools, Asynchronous queues, Dynamic Loading of Modules,
546 ; Memory Allocation, IO Channels, Error Reporting, Message Output and Debugging  Functions, Message Logging
547
548 (defcfun g-free :void
549   "@arg[ptr]{pointer previously obtained with @fun{g-malloc} or with g_malloc C function}
550 Frees the pointer by calling g_free on it."
551   (ptr :pointer))
552
553 (defcfun (g-malloc "g_malloc0") :pointer
554   "@arg[n-bytes]{an integer}
555 @return{pointer to beginning of allocated memory}
556 Allocates the specified number of bytes in memory. Calls g_malloc.
557 @see{g-free}"
558   (n-bytes gsize))
559
560 (defcfun g-strdup :pointer
561   "@arg[str]{a @class{string}}
562 @return{foreign pointer to new string}
563 Allocates a new string that is equal to @code{str}. Use @fun{g-free} to free it."
564   (str (:string :free-to-foreign t)))
565
566 ;omitted all GLib Utilites
567
568 (defbitfield g-spawn-flags
569   :leave-descriptors-open :do-not-reap-child :search-path :stdout-to-dev-null :stderr-to-dev-null
570   :child-inherits-stdin :file-and-argv-zero)
571
572 ;TODO: omitted Date and Time Functions