diff --git a/.gitignore b/.gitignore index b136c7ae2..12cbc32f5 100644 --- a/.gitignore +++ b/.gitignore @@ -150,10 +150,14 @@ INSTALL /lib/dirent.h /lib/langinfo.h /lib/wctype.h +/lib/poll.h +/lib/sys/select.h +/lib/sys/times.h /build-aux/ar-lib /build-aux/test-driver *.trs /test-suite/standalone/test-smob-mark /test-suite/standalone/test-scm-values /test-suite/standalone/test-scm-to-latin1-string +/test-suite/standalone/test-scm-c-bind-keyword-arguments /libguile/vm-operations.h diff --git a/doc/ref/api-compound.texi b/doc/ref/api-compound.texi index 1990d777d..94e01450e 100644 --- a/doc/ref/api-compound.texi +++ b/doc/ref/api-compound.texi @@ -689,22 +689,18 @@ Vectors can literally be entered in source code, just like strings, characters or some of the other data types. The read syntax for vectors is as follows: A sharp sign (@code{#}), followed by an opening parentheses, all elements of the vector in their respective read syntax, -and finally a closing parentheses. The following are examples of the -read syntax for vectors; where the first vector only contains numbers -and the second three different object types: a string, a symbol and a -number in hexadecimal notation. +and finally a closing parentheses. Like strings, vectors do not have to +be quoted. + +The following are examples of the read syntax for vectors; where the +first vector only contains numbers and the second three different object +types: a string, a symbol and a number in hexadecimal notation. @lisp #(1 2 3) #("Hello" foo #xdeadbeef) @end lisp -Like lists, vectors have to be quoted: - -@lisp -'#(a b c) @result{} #(a b c) -@end lisp - @node Vector Creation @subsubsection Dynamic Vector Creation and Validation @@ -735,7 +731,7 @@ The inverse operation is @code{vector->list}: Return a newly allocated list composed of the elements of @var{v}. @lisp -(vector->list '#(dah dah didah)) @result{} (dah dah didah) +(vector->list #(dah dah didah)) @result{} (dah dah didah) (list->vector '(dididit dah)) @result{} #(dididit dah) @end lisp @end deffn @@ -796,8 +792,8 @@ Return the number of elements in @var{vec} as a @code{size_t}. Return the contents of position @var{k} of @var{vec}. @var{k} must be a valid index of @var{vec}. @lisp -(vector-ref '#(1 1 2 3 5 8 13 21) 5) @result{} 8 -(vector-ref '#(1 1 2 3 5 8 13 21) +(vector-ref #(1 1 2 3 5 8 13 21) 5) @result{} 8 +(vector-ref #(1 1 2 3 5 8 13 21) (let ((i (round (* 2 (acos -1))))) (if (inexact? i) (inexact->exact i) diff --git a/doc/ref/libguile-smobs.texi b/doc/ref/libguile-smobs.texi index 6f7c0f45f..572bcf316 100644 --- a/doc/ref/libguile-smobs.texi +++ b/doc/ref/libguile-smobs.texi @@ -31,7 +31,6 @@ datatypes described here.) * Creating Smob Instances:: * Type checking:: * Garbage Collecting Smobs:: -* Garbage Collecting Simple Smobs:: * Remembering During Operations:: * Double Smobs:: * The Complete Example:: @@ -40,31 +39,10 @@ datatypes described here.) @node Describing a New Type @subsection Describing a New Type -To define a new type, the programmer must write four functions to +To define a new type, the programmer must write two functions to manage instances of the type: @table @code -@item mark -Guile will apply this function to each instance of the new type it -encounters during garbage collection. This function is responsible for -telling the collector about any other @code{SCM} values that the object -has stored. The default smob mark function does nothing. -@xref{Garbage Collecting Smobs}, for more details. - -@item free -Guile will apply this function to each instance of the new type that is -to be deallocated. The function should release all resources held by -the object. This is analogous to the Java finalization method-- it is -invoked at an unspecified time (when garbage collection occurs) after -the object is dead. The default free function frees the smob data (if -the size of the struct passed to @code{scm_make_smob_type} is non-zero) -using @code{scm_gc_free}. @xref{Garbage Collecting Smobs}, for more -details. - -This function operates while the heap is in an inconsistent state and -must therefore be careful. @xref{Smobs}, for details about what this -function is allowed to do. - @item print Guile will apply this function to each instance of the new type to print the value, as for @code{display} or @code{write}. The default print @@ -81,6 +59,32 @@ never @code{equal?} unless they are @code{eq?}. @end table +When the only resource associated with a smob is memory managed by the +garbage collector---i.e., memory allocated with the @code{scm_gc_malloc} +functions---this is sufficient. However, when a smob is associated with +other kinds of resources, it may be necessary to define one of the +following functions, or both: + +@table @code +@item mark +Guile will apply this function to each instance of the new type it +encounters during garbage collection. This function is responsible for +telling the collector about any other @code{SCM} values that the object +has stored, and that are in memory regions not already scanned by the +garbage collector. @xref{Garbage Collecting Smobs}, for more details. + +@item free +Guile will apply this function to each instance of the new type that is +to be deallocated. The function should release all resources held by +the object. This is analogous to the Java finalization method---it is +invoked at an unspecified time (when garbage collection occurs) after +the object is dead. @xref{Garbage Collecting Smobs}, for more details. + +This function operates while the heap is in an inconsistent state and +must therefore be careful. @xref{Smobs}, for details about what this +function is allowed to do. +@end table + To actually register the new smob type, call @code{scm_make_smob_type}. It returns a value of type @code{scm_t_bits} which identifies the new smob type. @@ -164,35 +168,11 @@ word of a smob, you should use the macros @code{SCM_SMOB_OBJECT} and @code{SCM_SET_SMOB_OBJECT} to access it. Creating a smob instance can be tricky when it consists of multiple -steps that allocate resources and might fail. It is recommended that -you go about creating a smob in the following way: - -@itemize -@item -Allocate the memory block for holding the data with -@code{scm_gc_malloc}. -@item -Initialize it to a valid state without calling any functions that might -cause a non-local exits. For example, initialize pointers to NULL. -Also, do not store @code{SCM} values in it that must be protected. -Initialize these fields with @code{SCM_BOOL_F}. - -A valid state is one that can be safely acted upon by the @emph{mark} -and @emph{free} functions of your smob type. -@item -Create the smob using @code{scm_new_smob}, passing it the initialized -memory block. (This step will always succeed.) -@item -Complete the initialization of the memory block by, for example, -allocating additional resources and making it point to them. -@end itemize - -This procedure ensures that the smob is in a valid state as soon as it -exists, that all resources that are allocated for the smob are -properly associated with it so that they can be properly freed, and -that no @code{SCM} values that need to be protected are stored in it -while the smob does not yet completely exist and thus can not protect -them. +steps that allocate resources. Most of the time, this is mainly about +allocating memory to hold associated data structures. Using memory +managed by the garbage collector simplifies things: the garbage +collector will automatically scan those data structures for pointers, +and reclaim them when they are no longer referenced. Continuing the example from above, if the global variable @code{image_tag} contains a tag returned by @code{scm_make_smob_type}, @@ -229,44 +209,19 @@ make_image (SCM name, SCM s_width, SCM s_height) */ image->name = name; image->pixels = - scm_gc_malloc (width * height, "image pixels"); + scm_gc_malloc_pointerless (width * height, "image pixels"); return smob; @} @end example -Let us look at what might happen when @code{make_image} is called. +We use @code{scm_gc_malloc_pointerless} for the pixel buffer to tell the +garbage collector not to scan it for pointers. Calls to +@code{scm_gc_malloc}, @code{scm_new_smob}, and +@code{scm_gc_malloc_pointerless} raise an exception in out-of-memory +conditions; the garbage collector is able to reclaim previously +allocated memory if that happens. -The conversions of @var{s_width} and @var{s_height} to @code{int}s might -fail and signal an error, thus causing a non-local exit. This is not a -problem since no resources have been allocated yet that would have to be -freed. - -The allocation of @var{image} in step 1 might fail, but this is likewise -no problem. - -Step 2 can not exit non-locally. At the end of it, the @var{image} -struct is in a valid state for the @code{mark_image} and -@code{free_image} functions (see below). - -Step 3 can not exit non-locally either. This is guaranteed by Guile. -After it, @var{smob} contains a valid smob that is properly initialized -and protected, and in turn can properly protect the Scheme values in its -@var{image} struct. - -But before the smob is completely created, @code{scm_new_smob} might -cause the garbage collector to run. During this garbage collection, the -@code{SCM} values in the @var{image} struct would be invisible to Guile. -It only gets to know about them via the @code{mark_image} function, but -that function can not yet do its job since the smob has not been created -yet. Thus, it is important to not store @code{SCM} values in the -@var{image} struct until after the smob has been created. - -Step 4, finally, might fail and cause a non-local exit. In that case, -the complete creation of the smob has not been successful, but it does -nevertheless exist in a valid state. It will eventually be freed by -the garbage collector, and all the resources that have been allocated -for it will be correctly freed by @code{free_image}. @node Type checking @subsection Type checking @@ -310,8 +265,17 @@ to @code{scm_remember_upto_here_1}. @subsection Garbage Collecting Smobs Once a smob has been released to the tender mercies of the Scheme -system, it must be prepared to survive garbage collection. Guile calls -the @emph{mark} and @emph{free} functions of the smob to manage this. +system, it must be prepared to survive garbage collection. In the +example above, all the memory associated with the smob is managed by the +garbage collector because we used the @code{scm_gc_} allocation +functions. Thus, no special care must be taken: the garbage collector +automatically scans them and reclaims any unused memory. + +However, when data associated with a smob is managed in some other +way---e.g., @code{malloc}'d memory or file descriptors---it is possible +to specify a @emph{free} function to release those resources when the +smob is reclaimed, and a @emph{mark} function to mark Scheme objects +otherwise invisible to the garbage collector. As described in more detail elsewhere (@pxref{Conservative GC}), every object in the Scheme system has a @dfn{mark bit}, which the garbage @@ -343,7 +307,9 @@ values will have become dangling references. To mark an arbitrary Scheme object, the @emph{mark} function calls @code{scm_gc_mark}. -Thus, here is how we might write @code{mark_image}: +Thus, here is how we might write @code{mark_image}---again this is not +needed in our example since we used the @code{scm_gc_} allocation +routines, so this is just for the sake of illustration: @example @group @@ -398,7 +364,8 @@ type of the @emph{free} function should be @code{size_t}, an unsigned integral type; the @emph{free} function should always return zero. Here is how we might write the @code{free_image} function for the image -smob type: +smob type---again for the sake of illustration, since our example does +not need it thanks to the use of the @code{scm_gc_} allocation routines: @example size_t free_image (SCM image_smob) @@ -426,37 +393,12 @@ during garbage collection; keep the @emph{mark} and @emph{free} functions very simple. Since collections occur at unpredictable times, it is easy for any unusual activity to interfere with normal code. - -@node Garbage Collecting Simple Smobs -@subsection Garbage Collecting Simple Smobs - -It is often useful to define very simple smob types --- smobs which have -no data to mark, other than the cell itself, or smobs whose immediate -data word is simply an ordinary Scheme object, to be marked recursively. -Guile provides some functions to handle these common cases; you can use -this function as your smob type's @emph{mark} function, if your smob's -structure is simple enough. - -If the smob refers to no other Scheme objects, then no action is -necessary; the garbage collector has already marked the smob cell -itself. In that case, you can use zero as your mark function. - -If the smob refers to exactly one other Scheme object via its first -immediate word, you can use @code{scm_markcdr} as its mark function. -Its definition is simply: - -@smallexample -SCM -scm_markcdr (SCM obj) -@{ - return SCM_SMOB_OBJECT (obj); -@} -@end smallexample - @node Remembering During Operations @subsection Remembering During Operations @cindex remembering +@c FIXME: Remove this section? + It's important that a smob is visible to the garbage collector whenever its contents are being accessed. Otherwise it could be freed while code is still using it. @@ -516,6 +458,8 @@ while the collector runs.) @node Double Smobs @subsection Double Smobs +@c FIXME: Remove this section? + Smobs are called smob because they are small: they normally have only room for one @code{void*} or @code{SCM} value plus 16 bits. The reason for this is that smobs are directly implemented by using the diff --git a/doc/ref/srfi-modules.texi b/doc/ref/srfi-modules.texi index d97f49820..32ff271b7 100644 --- a/doc/ref/srfi-modules.texi +++ b/doc/ref/srfi-modules.texi @@ -677,8 +677,8 @@ Maps each seed value to next seed value. @item seed The state value for the unfold. -@item tail-gen -Creates the tail of the list; defaults to @code{(lambda (x) '())}. +@item tail +The tail of the list; defaults to @code{'()}. @end table @end deffn diff --git a/libguile/__scm.h b/libguile/__scm.h index 0a749bec5..31e395285 100644 --- a/libguile/__scm.h +++ b/libguile/__scm.h @@ -77,7 +77,7 @@ * 1) int foo (char arg) SCM_NORETURN; */ #ifdef __GNUC__ -#define SCM_NORETURN __attribute__ ((noreturn)) +#define SCM_NORETURN __attribute__ ((__noreturn__)) #else #define SCM_NORETURN #endif diff --git a/libguile/i18n.c b/libguile/i18n.c index dc6d07d12..0f607f331 100644 --- a/libguile/i18n.c +++ b/libguile/i18n.c @@ -1535,7 +1535,9 @@ SCM_DEFINE (scm_nl_langinfo, "nl-langinfo", 1, 1, 0, codeset = nl_langinfo (CODESET); } - c_result = strdup (c_result); + if (c_result != NULL) + c_result = strdup (c_result); + unlock_locale_mutex (); if (c_result == NULL) diff --git a/libguile/throw.c b/libguile/throw.c index 4b1885eed..244bcf153 100644 --- a/libguile/throw.c +++ b/libguile/throw.c @@ -442,7 +442,7 @@ scm_handle_by_throw (void *handler_data SCM_UNUSED, SCM tag, SCM args) } SCM -scm_ithrow (SCM key, SCM args, int noreturn SCM_UNUSED) +scm_ithrow (SCM key, SCM args, int no_return SCM_UNUSED) { return scm_throw (key, args); } diff --git a/libguile/throw.h b/libguile/throw.h index 6cf6790b6..62592d22e 100644 --- a/libguile/throw.h +++ b/libguile/throw.h @@ -79,7 +79,7 @@ SCM_API int scm_exit_status (SCM args); SCM_API SCM scm_catch_with_pre_unwind_handler (SCM tag, SCM thunk, SCM handler, SCM lazy_handler); SCM_API SCM scm_catch (SCM tag, SCM thunk, SCM handler); SCM_API SCM scm_with_throw_handler (SCM tag, SCM thunk, SCM handler); -SCM_API SCM scm_ithrow (SCM key, SCM args, int noreturn); +SCM_API SCM scm_ithrow (SCM key, SCM args, int no_return); SCM_API SCM scm_throw (SCM key, SCM args); SCM_INTERNAL void scm_init_throw (void); diff --git a/module/ice-9/psyntax-pp.scm b/module/ice-9/psyntax-pp.scm index 36194123d..eeffecf38 100644 --- a/module/ice-9/psyntax-pp.scm +++ b/module/ice-9/psyntax-pp.scm @@ -3053,7 +3053,14 @@ ((read-file (lambda (fn dir k) (let ((p (open-input-file - (if (absolute-file-name? fn) fn (in-vicinity dir fn))))) + (if (absolute-file-name? fn) + fn + (if dir + (in-vicinity dir fn) + (syntax-violation + 'include + "relative file name only allowed when the include form is in a file" + x)))))) (let ((enc (file-encoding p))) (set-port-encoding! p (let ((t enc)) (if t t "UTF-8"))) (let f ((x (read p)) (result '())) diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm index 4b66b8b04..5368785c2 100644 --- a/module/ice-9/psyntax.scm +++ b/module/ice-9/psyntax.scm @@ -3056,9 +3056,15 @@ (define read-file (lambda (fn dir k) (let* ((p (open-input-file - (if (absolute-file-name? fn) - fn - (in-vicinity dir fn)))) + (cond ((absolute-file-name? fn) + fn) + (dir + (in-vicinity dir fn)) + (else + (syntax-violation + 'include + "relative file name only allowed when the include form is in a file" + x))))) (enc (file-encoding p))) ;; Choose the input encoding deterministically.