/[guile]/guile/guile-core/doc/ref/scm.texi
ViewVC logotype

Diff of /guile/guile-core/doc/ref/scm.texi

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.2.4 by ossau, Fri Mar 15 09:23:18 2002 UTC revision 1.1.2.5 by ossau, Sat Mar 16 13:35:23 2002 UTC
# Line 107  C function's arguments, as well as its r Line 107  C function's arguments, as well as its r
107  @c There are some exceptions to the regular structure described above.  @c There are some exceptions to the regular structure described above.
108    
109    
 @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  
 implementation 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 synchronization 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 {Scheme Procedure} scm-error key subr message args rest  
 Throw an error, with arguments  
 as described above.  
 @end deffn  
   
 @deffn {Scheme 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 SIGSEGV, 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 type.  
   
 @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.  
   
110  @c scm.texi ends here  @c scm.texi ends here

Legend:
Removed from v.1.1.2.4  
changed lines
  Added in v.1.1.2.5

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26