1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
|
@page
@node Scheme Primitives
@c @chapter Writing Scheme primitives in C
@c - according to the menu in guile.texi - NJ 2001/1/26
@chapter Relationship between Scheme and C functions
@c Chapter contents contributed by Thien-Thi Nguyen <ttn@gnu.org>.
Scheme procedures marked "primitive functions" have a regular interface
when calling from C, reflected in two areas: the name of a C function, and
the convention for passing non-required arguments to this function.
@c Although the vast majority of functions support these relationships,
@c there are some exceptions.
@menu
* Transforming Scheme name to C name::
* Structuring argument lists for C functions::
@c * Exceptions to the regularity::
@end menu
@node Transforming Scheme name to C name
@section Transforming Scheme name to C name
Normally, the name of a C function can be derived given its Scheme name,
using some simple textual transformations:
@itemize @bullet
@item
Replace @code{-} (hyphen) with @code{_} (underscore).
@item
Replace @code{?} (question mark) with "_p".
@item
Replace @code{!} (exclamation point) with "_x".
@item
Replace internal @code{->} with "_to_".
@item
Replace @code{<=} (less than or equal) with "_leq".
@item
Replace @code{>=} (greater than or equal) with "_geq".
@item
Replace @code{<} (less than) with "_less".
@item
Replace @code{>} (greater than) with "_gr".
@item
Replace @code{@@} with "at". [Omit?]
@item
Prefix with "gh_" (or "scm_" if you are ignoring the gh interface).
@item
[Anything else? --ttn, 2000/01/16 15:17:28]
@end itemize
Here is an Emacs Lisp command that prompts for a Scheme function name and
inserts the corresponding C function name into the buffer.
@example
(defun insert-scheme-to-C (name &optional use-gh)
"Transforms Scheme NAME, a string, to its C counterpart, and inserts it.
Prefix arg non-nil means use \"gh_\" prefix, otherwise use \"scm_\" prefix."
(interactive "sScheme name: \nP")
(let ((transforms '(("-" . "_")
("?" . "_p")
("!" . "_x")
("->" . "_to_")
("<=" . "_leq")
(">=" . "_geq")
("<" . "_less")
(">" . "_gr")
("@@" . "at"))))
(while transforms
(let ((trigger (concat "\\(.*\\)"
(regexp-quote (caar transforms))
"\\(.*\\)"))
(sub (cdar transforms))
(m nil))
(while (setq m (string-match trigger name))
(setq name (concat (match-string 1 name)
sub
(match-string 2 name)))))
(setq transforms (cdr transforms))))
(insert (if use-gh "gh_" "scm_") name))
@end example
@node Structuring argument lists for C functions
@section Structuring argument lists for C functions
The C function's arguments will be all of the Scheme procedure's
argumements, both required and optional; if the Scheme procedure takes a
``rest'' argument, that will be a final argument to the C function. The
C function's arguments, as well as its return type, will be @code{SCM}.
@c @node Exceptions to the regularity
@c @section Exceptions to the regularity
@c
@c There are some exceptions to the regular structure described above.
@page
@node I/O Extensions
@chapter Using and Extending Ports in C
@menu
* C Port Interface:: Using ports from C.
* Port Implementation:: How to implement a new port type in C.
@end menu
@node C Port Interface
@section C Port Interface
This section describes how to use Scheme ports from C.
@subsection Port basics
There are two main data structures. A port type object (ptob) is of
type @code{scm_ptob_descriptor}. A port instance is of type
@code{scm_port}. Given an @code{SCM} variable which points to a port,
the corresponding C port object can be obtained using the
@code{SCM_PTAB_ENTRY} macro. The ptob can be obtained by using
@code{SCM_PTOBNUM} to give an index into the @code{scm_ptobs}
global array.
@subsection Port buffers
An input port always has a read buffer and an output port always has a
write buffer. However the size of these buffers is not guaranteed to be
more than one byte (e.g., the @code{shortbuf} field in @code{scm_port}
which is used when no other buffer is allocated). The way in which the
buffers are allocated depends on the implementation of the ptob. For
example in the case of an fport, buffers may be allocated with malloc
when the port is created, but in the case of an strport the underlying
string is used as the buffer.
@subsection The @code{rw_random} flag
Special treatment is required for ports which can be seeked at random.
Before various operations, such as seeking the port or changing from
input to output on a bidirectional port or vice versa, the port
implemention must be given a chance to update its state. The write
buffer is updated by calling the @code{flush} ptob procedure and the
input buffer is updated by calling the @code{end_input} ptob procedure.
In the case of an fport, @code{flush} causes buffered output to be
written to the file descriptor, while @code{end_input} causes the
descriptor position to be adjusted to account for buffered input which
was never read.
The special treatment must be performed if the @code{rw_random} flag in
the port is non-zero.
@subsection The @code{rw_active} variable
The @code{rw_active} variable in the port is only used if
@code{rw_random} is set. It's defined as an enum with the following
values:
@table @code
@item SCM_PORT_READ
the read buffer may have unread data.
@item SCM_PORT_WRITE
the write buffer may have unwritten data.
@item SCM_PORT_NEITHER
neither the write nor the read buffer has data.
@end table
@subsection Reading from a port.
To read from a port, it's possible to either call existing libguile
procedures such as @code{scm_getc} and @code{scm_read_line} or to read
data from the read buffer directly. Reading from the buffer involves
the following steps:
@enumerate
@item
Flush output on the port, if @code{rw_active} is @code{SCM_PORT_WRITE}.
@item
Fill the read buffer, if it's empty, using @code{scm_fill_input}.
@item Read the data from the buffer and update the read position in
the buffer. Steps 2) and 3) may be repeated as many times as required.
@item Set rw_active to @code{SCM_PORT_READ} if @code{rw_random} is set.
@item update the port's line and column counts.
@end enumerate
@subsection Writing to a port.
To write data to a port, calling @code{scm_lfwrite} should be sufficient for
most purposes. This takes care of the following steps:
@enumerate
@item
End input on the port, if @code{rw_active} is @code{SCM_PORT_READ}.
@item
Pass the data to the ptob implementation using the @code{write} ptob
procedure. The advantage of using the ptob @code{write} instead of
manipulating the write buffer directly is that it allows the data to be
written in one operation even if the port is using the single-byte
@code{shortbuf}.
@item
Set @code{rw_active} to @code{SCM_PORT_WRITE} if @code{rw_random}
is set.
@end enumerate
@node Port Implementation
@section Port Implementation
This section describes how to implement a new port type in C.
As described in the previous section, a port type object (ptob) is
a structure of type @code{scm_ptob_descriptor}. A ptob is created by
calling @code{scm_make_port_type}.
All of the elements of the ptob, apart from @code{name}, are procedures
which collectively implement the port behaviour. Creating a new port
type mostly involves writing these procedures.
@code{scm_make_port_type} initializes three elements of the structure
(@code{name}, @code{fill_input} and @code{write}) from its arguments.
The remaining elements are initialized with default values and can be
set later if required.
@table @code
@item name
A pointer to a NUL terminated string: the name of the port type. This
is the only element of @code{scm_ptob_descriptor} which is not
a procedure. Set via the first argument to @code{scm_make_port_type}.
@item mark
Called during garbage collection to mark any SCM objects that a port
object may contain. It doesn't need to be set unless the port has
@code{SCM} components. Set using @code{scm_set_port_mark}.
@item free
Called when the port is collected during gc. It
should free any resources used by the port.
Set using @code{scm_set_port_free}.
@item print
Called when @code{write} is called on the port object, to print a
port description. e.g., for an fport it may produce something like:
@code{#<input: /etc/passwd 3>}. Set using @code{scm_set_port_print}.
@item equalp
Not used at present. Set using @code{scm_set_port_equalp}.
@item close
Called when the port is closed, unless it was collected during gc. It
should free any resources used by the port.
Set using @code{scm_set_port_close}.
@item write
Accept data which is to be written using the port. The port implementation
may choose to buffer the data instead of processing it directly.
Set via the third argument to @code{scm_make_port_type}.
@item flush
Complete the processing of buffered output data. Reset the value of
@code{rw_active} to @code{SCM_PORT_NEITHER}.
Set using @code{scm_set_port_flush}.
@item end_input
Perform any synchronisation required when switching from input to output
on the port. Reset the value of @code{rw_active} to @code{SCM_PORT_NEITHER}.
Set using @code{scm_set_port_end_input}.
@item fill_input
Read new data into the read buffer and return the first character. It
can be assumed that the read buffer is empty when this procedure is called.
Set via the second argument to @code{scm_make_port_type}.
@item input_waiting
Return a lower bound on the number of bytes that could be read from the
port without blocking. It can be assumed that the current state of
@code{rw_active} is @code{SCM_PORT_NEITHER}.
Set using @code{scm_set_port_input_waiting}.
@item seek
Set the current position of the port. The procedure can not make
any assumptions about the value of @code{rw_active} when it's
called. It can reset the buffers first if desired by using something
like:
@example
if (pt->rw_active == SCM_PORT_READ)
scm_end_input (object);
else if (pt->rw_active == SCM_PORT_WRITE)
ptob->flush (object);
@end example
However note that this will have the side effect of discarding any data
in the unread-char buffer, in addition to any side effects from the
@code{end_input} and @code{flush} ptob procedures. This is undesirable
when seek is called to measure the current position of the port, i.e.,
@code{(seek p 0 SEEK_CUR)}. The libguile fport and string port
implementations take care to avoid this problem.
The procedure is set using @code{scm_set_port_seek}.
@item truncate
Truncate the port data to be specified length. It can be assumed that the
current state of @code{rw_active} is @code{SCM_PORT_NEITHER}.
Set using @code{scm_set_port_truncate}.
@end table
@node Handling Errors
@chapter How to Handle Errors in C Code
Error handling is based on @code{catch} and @code{throw}. Errors are
always thrown with a @var{key} and four arguments:
@itemize @bullet
@item
@var{key}: a symbol which indicates the type of error. The symbols used
by libguile are listed below.
@item
@var{subr}: the name of the procedure from which the error is thrown, or
@code{#f}.
@item
@var{message}: a string (possibly language and system dependent)
describing the error. The tokens @code{~A} and @code{~S} can be
embedded within the message: they will be replaced with members of the
@var{args} list when the message is printed. @code{~A} indicates an
argument printed using @code{display}, while @code{~S} indicates an
argument printed using @code{write}. @var{message} can also be
@code{#f}, to allow it to be derived from the @var{key} by the error
handler (may be useful if the @var{key} is to be thrown from both C and
Scheme).
@item
@var{args}: a list of arguments to be used to expand @code{~A} and
@code{~S} tokens in @var{message}. Can also be @code{#f} if no
arguments are required.
@item
@var{rest}: a list of any additional objects required. e.g., when the
key is @code{'system-error}, this contains the C errno value. Can also
be @code{#f} if no additional objects are required.
@end itemize
In addition to @code{catch} and @code{throw}, the following Scheme
facilities are available:
@deffn primitive scm-error key subr message args rest
Throw an error, with arguments
as described above.
@end deffn
@deffn procedure error msg arg @dots{}
Throw an error using the key @code{'misc-error}. The error
message is created by displaying @var{msg} and writing the @var{args}.
@end deffn
The following are the error keys defined by libguile and the situations
in which they are used:
@itemize @bullet
@item
@code{error-signal}: thrown after receiving an unhandled fatal signal
such as SIGSEV, SIGBUS, SIGFPE etc. The @var{rest} argument in the throw
contains the coded signal number (at present this is not the same as the
usual Unix signal number).
@item
@code{system-error}: thrown after the operating system indicates an
error condition. The @var{rest} argument in the throw contains the
errno value.
@item
@code{numerical-overflow}: numerical overflow.
@item
@code{out-of-range}: the arguments to a procedure do not fall within the
accepted domain.
@item
@code{wrong-type-arg}: an argument to a procedure has the wrong thpe.
@item
@code{wrong-number-of-args}: a procedure was called with the wrong number
of arguments.
@item
@code{memory-allocation-error}: memory allocation error.
@item
@code{stack-overflow}: stack overflow error.
@item
@code{regex-error}: errors generated by the regular expression library.
@item
@code{misc-error}: other errors.
@end itemize
@section C Support
SCM scm_error (SCM key, char *subr, char *message, SCM args, SCM rest)
Throws an error, after converting the char * arguments to Scheme strings.
subr is the Scheme name of the procedure, NULL is converted to #f.
Likewise a NULL message is converted to #f.
The following procedures invoke scm_error with various error keys and
arguments. The first three call scm_error with the system-error key
and automatically supply errno in the "rest" argument: scm_syserror
generates messages using strerror, scm_sysmissing is used when
facilities are not available. Care should be taken that the errno
value is not reset (e.g. due to an interrupt).
@itemize @bullet
@item
void scm_syserror (char *subr);
@item
void scm_syserror_msg (char *subr, char *message, SCM args);
@item
void scm_sysmissing (char *subr);
@item
void scm_num_overflow (char *subr);
@item
void scm_out_of_range (char *subr, SCM bad_value);
@item
void scm_wrong_num_args (SCM proc);
@item
void scm_wrong_type_arg (char *subr, int pos, SCM bad_value);
@item
void scm_memory_error (char *subr);
@item
static void scm_regex_error (char *subr, int code); (only used in rgx.c).
@end itemize
Exception handlers can also be installed from C, using
scm_internal_catch, scm_lazy_catch, or scm_stack_catch from
libguile/throw.c. These have not yet been documented, however the
source contains some useful comments.
|