~ chicken-core (chicken-5) 8ef53edff4a27de64ae561a0b8bbaa89a032111e
commit 8ef53edff4a27de64ae561a0b8bbaa89a032111e
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Wed Apr 14 16:46:25 2010 +0200
Commit: Chicken <chicken@galinha.ucpel.tche.br>
CommitDate: Fri Apr 16 03:11:22 2010 -0300
merged manual changes from wiki
diff --git a/manual/Accessing external objects b/manual/Accessing external objects
index 8d1771b6..e81ef6c4 100644
--- a/manual/Accessing external objects
+++ b/manual/Accessing external objects
@@ -84,8 +84,21 @@ accessed in the current compilation unit, but the name can be
lexically shadowed. Note that {{STRING}} can name an arbitrary C
expression. If no assignments are performed, then {{STRING}} doesn't
even have to specify an lvalue.
-
-
+See that {{define-foreign-variable}} will not generate C declarations
+or memory allocation code; use it to include references to variables
+in external C code. To actually create Scheme variables visible from C,
+use {{define-external}} (see the Manual section on
+[[http://chicken.wiki.br/man/4/Callbacks|Callbacks]]).
+For example, the following code:
+<enscript lang="scheme">
+(import foreign)
+(define-foreign-variable x double "var_x")
+(print x)
+</enscript>
+will not work, because a reference to {{var_x}} will be inserted in the C code,
+but no declaration will be included (this can be easily verified by translating
+the program into C with {{csc -t program.scm}}). Changing the second line to
+{{(define-external x double 0.5)}} will work (and the value 0.5 will be printed).
=== foreign-lambda
<macro>(foreign-lambda RETURNTYPE NAME ARGTYPE ...)</macro>
@@ -141,7 +154,7 @@ function to call Scheme functions and allocate Scheme data-objects. See [[Callba
This is also similar to {{foreign-lambda*}} but the code will be executed
in a ''primitive'' CPS context, which means it will not actually return, but
-call it's continuation on exit. This means that code inside this form may
+call its continuation on exit. This means that code inside this form may
allocate Scheme data on the C stack (the ''nursery'') with {{C_alloc}}
(see below). If the {{RETURNTYPE}} is omitted it defaults to {{void}}.
You can return multiple values inside the body of the {{foreign-primitive}}
diff --git a/manual/C interface b/manual/C interface
index d85501c0..1fd00c9d 100644
--- a/manual/C interface
+++ b/manual/C interface
@@ -62,6 +62,220 @@ Like {{C_fitsinfixnump}} but for unsigned integers. This checks the
top ''two'' bits are zero, since fixnums '''always''' carry a sign.
+==== Scheme predicates
+
+These return Scheme booleans (ie, C_SCHEME_TRUE or C_SCHEME_FALSE).
+This means they can be used directly from Scheme using {{##core#inline}}.
+
+===== C_zero_length_p
+
+ [C macro] C_word C_zero_length_p(C_word x)
+
+Is {{x}} a Scheme object of zero length? Only accepts non-immediate objects.
+
+===== C_unboundvaluep
+
+ [C macro] C_word C_unboundvaluep(C_word x)
+
+Is {{x}} the special unbound variable placeholder {{C_SCHEME_UNBOUND}}?
+
+===== C_boundp
+
+ [C macro] C_word C_boundp(C_word x)
+
+Is {{x}} a bound value? Only accepts non-immediate objects.
+
+===== C_blockp
+
+ [C macro] C_word C_blockp(C_word x)
+
+Is {{x}} a "block" value?
+
+A "block" value is a value that contains a memory block, i.e. is not
+an immediate value.
+
+===== C_immp
+
+ [C macro] C_word C_immp(C_word x)
+
+Is {{x}} an immediate value?
+
+===== C_forwardedp
+
+ [C macro] C_word C_forwardedp(C_word x)
+
+Is {{x}} a GC-forwarded object?
+
+===== C_flonump
+
+ [C macro] C_word C_flonump(C_word x)
+
+Is {{x}} a Scheme flonum object? Accepts only non-immediate objects.
+
+===== C_stringp
+
+ [C macro] C_word C_stringp(C_word x)
+
+Is {{x}} a Scheme string object? Accepts only non-immediate objects.
+
+===== C_symbolp
+
+ [C macro] C_word C_symbolp(C_word x)
+
+Is {{x}} a symbol? Accepts only non-immediate objects.
+
+===== C_pairp
+
+ [C macro] C_word C_pairp(C_word x)
+
+Is {{x}} a pair? Accepts only non-immediate objects.
+
+===== C_closurep
+
+ [C macro] C_word C_closurep(C_word x)
+
+Is {{x}} a closure? Accepts only non-immediate objects.
+
+===== C_vectorp
+
+ [C macro] C_word C_vectorp(C_word x)
+
+Is {{x}} any kind of vector? Accepts only non-immediate objects.
+
+This returns true for both regular heterogenous R5RS vectors and
+bytevectors ("blobs"). However, it does ''not'' return true for
+SRFI-4 vectors, as those are actually bytevectors wrapped in a
+structure with a type tag.
+
+===== C_vectorp
+
+ [C macro] C_word C_bytevectorp(C_word x)
+
+Is {{x}} a bytevector ("blob")? Accepts only non-immediate objects.
+
+===== C_portp
+
+ [C macro] C_word C_portp(C_word x)
+
+Is {{x}} a port object? Accepts only non-immediate objects.
+
+===== C_structurep
+
+ [C macro] C_word C_structure(C_word x)
+
+Is {{x}} a structure (record) object? Accepts only non-immediate objects.
+
+===== C_locativep
+
+ [C macro] C_word C_locativep(C_word x)
+
+Is {{x}} a locative object? Accepts only non-immediate objects.
+
+===== C_charp
+
+ [C macro] C_word C_charp(C_word x)
+
+Is {{x}} a character object?
+
+===== C_booleanp
+
+ [C macro] C_word C_booleanp(C_word x)
+
+Is {{x}} a boolean object?
+
+===== C_eofp
+
+ [C macro] C_word C_eofp(C_word x)
+
+Is {{x}} the {{#!eof}} object?
+
+===== C_undefinedp
+
+ [C macro] C_word C_undefinedp(C_word x)
+
+Is {{x}} the undefined value?
+
+===== C_fixnump
+
+ [C macro] C_word C_fixnump(C_word x)
+
+Is {{x}} a fixnum object?
+
+===== C_nfixnump
+
+ [C macro] C_word C_nfixnump(C_word x)
+
+Is {{x}} ''not'' a fixnum object?
+
+===== C_i_numberp
+
+ [C function] C_word C_i_numberp(C_word x)
+
+Is {{x}} a number object (fixnum or flonum)?
+
+===== C_pointerp
+
+ [C macro] C_word C_pointerp(C_word x)
+
+Is {{x}} a C pointer object? Only accepts non-immediate objects.
+
+===== C_taggedpointerp
+
+ [C macro] C_word C_taggedpointerp(C_word x)
+
+Is {{x}} a tagged pointer object? Only accepts non-immediate objects.
+
+===== C_swigpointerp
+
+ [C macro] C_word C_swigpointerp(C_word x)
+
+Is {{x}} a SWIG pointer object? Only accepts non-immediate objects.
+
+===== C_anypointerp
+
+ [C macro] C_word C_anypointerp(C_word x)
+
+Is {{x}} any type of pointer object? Only accepts non-immediate objects.
+
+===== C_lambdainfop
+
+ [C macro] C_word C_lambdainfop(C_word x)
+
+Is {{x}} a lambda-info object? Only accepts non-immediate objects.
+
+===== C_byteblockp
+
+ [C macro] C_word C_byteblockp(C_word x)
+
+Is {{x}} a "byteblock" object? Only accepts non-immediate objects.
+
+Strings, flonums, bytevectors and lambda-info objects are considered
+"byteblock" objects, as they are not containers for Scheme objects but
+simply point to contiguous memory ranges of bytes.
+
+===== C_specialp
+
+ [C macro] C_word C_specialp(C_word x)
+
+Is {{x}} a "special" object? Only accepts non-immediate objects.
+
+Closures, ports, pointers and locatives are considered "special"
+objects, as they are not containers for Scheme objects (and they are
+not byte blocks either), so they have to be treated specially by the GC.
+
+===== C_nullp
+
+ [C macro] C_word C_nullp(C_word x)
+
+Is {{x}} the empty list, i.e. is it {{C_SCHEME_END_OF_LIST}}?
+
+===== C_anyp
+
+ [C macro] C_word C_anyp(C_word x)
+
+Always returns {{C_SCHEME_TRUE}}.
+
+
=== Constructors
==== Constructors for immediate Scheme objects
@@ -81,6 +295,10 @@ by a {{C_word}}. There's no additional memory used by them.
[C macro] C_word C_mk_bool(int truth_value)
+===== C_mk_nbool
+
+ [C macro] C_word C_mk_nbool(int truth_value_to_negate)
+
===== C_SCHEME_END_OF_LIST
[C macro] C_SCHEME_END_OF_LIST
@@ -461,6 +679,568 @@ milliseconds required for the garbage collection, if the collection
was a major one. For minor collections the value of the {{ms}} argument
is undefined.
+=== Type-specific macros and functions
+
+The following are macros and functions to ask information or perform
+operations on objects once their types are already known. If you call
+it on any object of another type, it is not defined what will happen
+and likely your program will crash, especially if you pass immediates
+to procedures expecting non-immediates.
+
+==== Vectors
+
+===== C_vemptyp
+
+ [C macro] C_word C_vemptyp(C_word v)
+
+Is the (byte- or heterogenous) vector {{v}} empty?
+
+===== C_notvemptyp
+
+ [C macro] C_word C_notvemptyp(C_word v)
+
+Is the (byte- or heterogenous) vector {{v}} nonempty?
+
+==== Numbers
+
+These procedures accept any type of number, so you can pass in either
+a fixnum or a flonum. You shouldn't pass in another type though,
+since that could crash your program.
+
+===== C_u_i_exactp
+
+ [C macro] C_word C_u_i_exactp(C_word x)
+
+Is {{x}} an exact number (i.e., a fixnum)?
+
+===== C_u_i_inexactp
+
+ [C macro] C_word C_u_i_inexactp(C_word x)
+
+Is {{x}} an inexact number (i.e., not a fixnum)?
+
+===== C_i_finitep
+
+ [C function] C_word C_i_finitep(C_word x)
+
+Is {{x}} a finite number? This returns false only when {{x}} is a
+flonum representing {{-inf}} or {{+inf}}.
+
+==== Fixnums
+
+Note: Fixnums are immediates, so there is no {{C_fixnum_equalp}}
+macro. You can just compare them without hassle (or use
+[[#c-eqp|C_eqp]] if you prefer).
+
+===== C_i_fixnumevenp
+
+ [C macro] C_word C_i_fixnumevenp(C_word x)
+
+Is {{x}} an even fixnum?
+
+===== C_i_fixnumoddp
+
+ [C macro] C_word C_i_fixnumoddp(C_word x)
+
+Is {{x}} an odd fixnum?
+
+===== C_fixnum_times
+
+ [C macro] C_word C_fixnum_times(C_word n1, C_word n2)
+
+Multiply fixnum n1 by fixnum n2.
+
+===== C_fixnum_plus
+
+ [C macro] C_word C_fixnum_plus(C_word n1, C_word n2)
+
+Add fixnum {{n1}} to fixnum {{n2}}.
+
+===== C_u_fixnum_plus
+
+ [C macro] C_word C_u_fixnum_plus(C_word n1, C_word n2)
+
+Like {{C_fixnum_plus}}, but unsafe (assumes no overflow/underflow).
+
+===== C_fixnum_difference
+
+ [C macro] C_word C_fixnum_difference(C_word n1, C_word n2)
+
+Calculate {{n1}} - {{n2}}.
+
+===== C_u_fixnum_difference
+
+ [C macro] C_word C_u_fixnum_difference(C_word n1, C_word n2)
+
+Like {{C_fixnum_difference}}, but unsafe (assumes no overflow/underflow).
+
+===== C_fixnum_divide
+
+ [C macro] C_word C_fixnum_divide(C_word n1, C_word n2)
+
+Divide {{n1}} by {{n2}}, returning the quotient (i.e., integer
+division).
+
+===== C_fixnum_modulo
+
+ [C macro] C_word C_fixnum_modulo(C_word n1, C_word n2)
+
+Calculate {{n1}} modulo {{n2}}.
+
+===== C_fixnum_and
+
+ [C macro] C_word C_fixnum_and(C_word n1, C_word n2)
+
+Calculate the bitwise {{AND}} of the integral values of {{n1}} and {{n2}}.
+
+===== C_u_fixnum_and
+
+ [C macro] C_word C_u_fixnum_and(C_word n1, C_word n2)
+
+Like {{C_fixnum_and}}, but unsafe.
+
+===== C_fixnum_or
+
+ [C macro] C_word C_fixnum_or(C_word n1, C_word n2)
+
+Calculate the bitwise {{OR}} of the integral values of {{n1}} and {{n2}}.
+
+===== C_u_fixnum_or
+
+ [C macro] C_word C_u_fixnum_or(C_word n1, C_word n2)
+
+Like {{C_fixnum_or}}, but unsafe.
+
+===== C_fixnum_xor
+
+ [C macro] C_word C_fixnum_xor(C_word n1, C_word n2)
+
+Calculate the bitwise {{XOR}} of the integral values of {{n1}} and {{n2}}.
+
+===== C_fixnum_not
+
+ [C macro] C_word C_fixnum_not(C_word n)
+
+Calculate the bitwise {{NOT}} (inversion of bits) of the integral
+value of {{n}}.
+
+===== C_fixnum_shift_left
+
+ [C macro] C_word C_fixnum_shift_left(C_word n1, C_word n2)
+
+Shift the integral value of {{n1}} left by {{n2}} positions.
+
+===== C_fixnum_shift_right
+
+ [C macro] C_word C_fixnum_shift_right(C_word n1, C_word n2)
+
+Shift the integral value of {{n1}} right by {{n2}}
+
+===== C_fixnum_negate
+
+ [C macro] C_word C_fixnum_negate(C_word n)
+
+Negate {{n}}, i.e. return {{-n}}.
+
+===== C_fixnum_greaterp
+
+ [C macro] C_word C_fixnum_greaterp(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} is greater than {{n2}},
+{{C_SCHEME_FALSE}} if not.
+
+===== C_fixnum_greater_or_equal_p
+
+ [C macro] C_word C_fixnum_greater_or_equalp(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} is greater than or equal to
+{{n2}}, {{C_SCHEME_FALSE}} if not.
+
+===== C_fixnum_lessp
+
+ [C macro] C_word C_fixnum_lessp(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} is less than {{n2}},
+{{C_SCHEME_FALSE}} if not.
+
+===== C_fixnum_less_or_equal_p
+
+ [C macro] C_word C_fixnum_less_or_equalp(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} is less than or equal to
+{{n2}}, {{C_SCHEME_FALSE}} if not.
+
+===== C_fixnum_increase
+
+ [C macro] C_word C_fixnum_increase(C_word n)
+
+Adds 1 to {{n}}
+
+===== C_u_fixnum_increase
+
+ [C macro] C_word C_u_fixnum_increase(C_word n)
+
+As {{C_fixnum_increase}}, but unsafe (assumes the result will not overflow).
+
+===== C_fixnum_decrease
+
+ [C macro] C_word C_fixnum_decrease(C_word n)
+
+Subtracts 1 from {{n}}
+
+===== C_u_fixnum_decrease
+
+ [C macro] C_word C_u_fixnum_decrease(C_word n)
+
+As {{C_fixnum_increase}}, but unsafe (assumes the result will not underflow).
+
+===== C_fixnum_abs
+
+ [C macro] C_word C_fixnum_abs(C_word n)
+
+Returns the absolute value of {{n}}.
+
+===== C_i_fixnum_min
+
+ [C function] C_word C_fixnum_min(C_word n1, C_word n2)
+
+Returns the smallest of the two fixnums {{n1}} and {{n2}}.
+
+===== C_i_fixnum_max
+
+ [C function] C_word C_fixnum_max(C_word n1, C_word n2)
+
+Returns the largest of the two fixnums {{n1}} and {{n2}}.
+
+
+==== Flonums
+
+===== C_flonum_equalp
+
+ [C macro] C_word C_flonum_equalp(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} and {{n2}} are equal flonums,
+{{C_SCHEME_FALSE}} otherwise.
+
+===== C_flonum_greaterp
+
+ [C macro] C_word C_flonum_greaterp(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} is greater than {{n2}},
+{{C_SCHEME_FALSE}} if not.
+
+===== C_flonum_greater_or_equal_p
+
+ [C macro] C_word C_flonum_greater_or_equal_p(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} is greater than or equal to {{n2}},
+{{C_SCHEME_FALSE}} if not.
+
+===== C_flonum_lessp
+
+ [C macro] C_word C_flonum_lessp(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} is less than {{n2}},
+{{C_SCHEME_FALSE}} if not.
+
+===== C_flonum_less_or_equal_p
+
+ [C macro] C_word C_flonum_less_or_equal_p(C_word n1, C_word n2)
+
+Returns {{C_SCHEME_TRUE}} when {{n1}} is less than or equal to {{n2}},
+{{C_SCHEME_FALSE}} if not.
+
+===== C_a_i_flonum_plus
+
+ [C macro] C_word C_a_i_flonum_plus(C_word **ptr, int c, C_word n1, C_word n2)
+
+Adds the flonum {{n1}} to the flonum {{n2}}, using the storage at
+{{ptr}}. {{c}} should always be 2.
+
+Example:
+
+<enscript highlight=scheme>
+#include <chicken.h>
+#include <stdio.h>
+
+int main(void)
+{
+ C_word *mema, *memb, *memresult;
+ C_word a, b, result;
+
+ mema = C_alloc(C_SIZEOF_FLONUM);
+ memb = C_alloc(C_SIZEOF_FLONUM);
+ memresult = C_alloc(C_SIZEOF_FLONUM);
+ a = C_flonum(&mema, 1.2);
+ b = C_flonum(&memb, 4.7);
+ result = C_a_i_flonum_plus(&memresult, 2, a, b);
+ printf("%lf\n", C_flonum_magnitude(result));
+ return 0;
+}
+</enscript>
+
+This will print {{5.9}}
+
+===== C_a_i_flonum_difference
+
+ [C macro] C_word C_a_i_flonum_difference(C_word **ptr, int c, C_word n1, C_word n2)
+
+Subtracts the flonum {{n2}} from the flonum {{n1}}, using the storage at
+{{ptr}}. {{c}} should always be 2.
+
+===== C_a_i_flonum_times
+
+ [C macro] C_word C_a_i_flonum_times(C_word **ptr, int c, C_word n1, C_word n2)
+
+Multiplies the flonum {{n1}} by the flonum {{n2}}, using the storage at
+{{ptr}}. {{c}} should always be 2.
+
+===== C_a_i_flonum_quotient
+
+ [C macro] C_word C_a_i_flonum_quotient(C_word **ptr, int c, C_word n1, C_word n2)
+
+Calculates the quotient of the flonum {{n1}} divided by the flonum
+{{n2}}, using the storage at {{ptr}}. {{c}} should always be 2.
+
+===== C_a_i_flonum_negate
+
+ [C macro] C_word C_a_i_flonum_negate(C_word **ptr, int c, C_word n)
+
+Negates the flonum {{n}}, using the storage at {{ptr}}. {{c}} should
+always be 1.
+
+===== C_a_i_flonum_truncate
+
+ [C macro] C_word C_a_i_flonum_truncate(C_word **ptr, int c, C_word n)
+
+Truncate the flonum {{n}}, using the storage at {{ptr}}. {{c}} should
+always be 1.
+
+===== C_a_i_flonum_ceiling
+
+ [C macro] C_word C_a_i_flonum_ceiling(C_word **ptr, int c, C_word n)
+
+Round the flonum {{n}}, rounding upwards, using the storage at
+{{ptr}}. {{c}} should always be 1.
+
+===== C_a_i_flonum_floor
+
+ [C macro] C_word C_a_i_flonum_floor(C_word **ptr, int c, C_word n)
+
+Round the flonum {{n}}, rounding downwards, using the storage at
+{{ptr}}. {{c}} should always be 1.
+
+===== C_a_i_flonum_round
+
+ [C macro] C_word C_a_i_flonum_round(C_word **ptr, int c, C_word n)
+
+Round the flonum {{n}}, rounding towards the nearest integer, using
+the storage at {{ptr}}. {{c}} should always be 1.
+
+This macro returns the value like returned by C's {{round()}}
+function. That means it rounds to the larger value (away from 0) when
+rounding numbers halfway between two integers.
+
+===== C_a_i_flonum_round_proper
+
+ [C macro] C_word C_a_i_flonum_round_proper(C_word **ptr, int c, C_word n)
+
+Round the flonum {{n}}, rounding towards the nearest integer, using
+the storage at {{ptr}}. {{c}} should always be 1.
+
+This macro returns the value like returned by Scheme's {{round}}
+procedure. That means it rounds to even numbers when rounding
+numbers halfway between two integers.
+
+===== C_a_i_flonum_sin
+
+ [C macro] C_word C_a_i_flonum_sin(C_word **ptr, int c, C_word n)
+
+Calculates the sine of {{n}} (in radians).
+
+===== C_a_i_flonum_cos
+
+ [C macro] C_word C_a_i_flonum_cos(C_word **ptr, int c, C_word n)
+
+Calculates the cosine of {{n}} (in radians).
+
+===== C_a_i_flonum_tan
+
+ [C macro] C_word C_a_i_flonum_tan(C_word **ptr, int c, C_word n)
+
+Calculates the tangent of {{n}} (in radians).
+
+===== C_a_i_flonum_asin
+
+ [C macro] C_word C_a_i_flonum_asin(C_word **ptr, int c, C_word n)
+
+Calculates the arc sine of {{n}} (in radians, in the range -pi/2 through +pi/2).
+
+===== C_a_i_flonum_acos
+
+ [C macro] C_word C_a_i_flonum_acos(C_word **ptr, int c, C_word n)
+
+Calculates the arc cosine of {{n}} (in radians, in the range 0 through pi).
+
+===== C_a_i_flonum_atan
+
+ [C macro] C_word C_a_i_flonum_atan(C_word **ptr, int c, C_word n)
+
+Calculates the arc tangent of {{n}} (in radians, in the range -pi/2 through +pi/2).
+
+Like C's {{atan()}} or Scheme's unary {{atan}}.
+
+===== C_a_i_flonum_atan2
+
+ [C macro] C_word C_a_i_flonum_atan2(C_word **ptr, int c, C_word n1, C_word n2)
+
+Calculates the arc tangent of {{n1/n2}} (in radians), using the sign of both
+to determine the quadrant of the result.
+
+Like C's {{atan2()}} or Scheme's binary {{atan}}.
+
+===== C_a_i_flonum_log
+
+ [C macro] C_word C_a_i_flonum_log(C_word **ptr, int c, C_word n)
+
+Calculate the natural (base {{e}}) logarithm of {{n}}.
+
+===== C_a_i_flonum_exp
+
+ [C macro] C_word C_a_i_flonum_exp(C_word **ptr, int c, C_word n)
+
+Calculates the base {{e}} exponent of {{n}} (i.e., the inverse
+operation of {{C_a_i_flonum_log}}).
+
+===== C_a_i_flonum_expt
+
+ [C macro] C_word C_a_i_flonum_expt(C_word **ptr, int c, C_word n1, C_word n2)
+
+Calculates {{n1}} raised to the power {{n2}}.
+
+===== C_a_i_flonum_sqrt
+
+ [C macro] C_word C_a_i_flonum_sqrt(C_word **ptr, int c, C_word n)
+
+Calculates the square root of {{n}}.
+
+===== C_a_i_flonum_abs
+
+ [C macro] C_word C_a_i_flonum_abs(C_word **ptr, int c, C_word n)
+
+Calculates the absolute value of {{n}}.
+
+
+==== Pointers
+
+===== C_null_pointerp
+
+ [C macro] C_word C_null_pointerp(C_word x)
+
+Is {{x}} a NULL pointer?
+
+===== C_a_i_address_to_pointer
+
+ [C macro] C_word C_a_i_address_to_pointer(C_word **ptr, int c, C_word addr)
+
+Convert {{addr}} to a pointer object using the storage at {{ptr}}.
+{{addr}} is can be either a flonum or a fixnum representing a memory
+address.
+
+===== C_a_i_pointer_to_address
+
+ [C macro] C_word C_a_i_pointer_to_address(C_word **ptr, int c, C_word pptr)
+
+Convert back the pointer {{pptr}} to an address number, possibly using
+the storage at {{ptr}}. The number returned can be either a fixnum or
+a flonum, so you will have to pass a memory storage that can hold a
+flonum at {{ptr}}. Whether it is actually used depends on the size of
+the address.
+
+
+==== Ports
+
+===== C_tty_portp
+
+ [C macro] C_word C_tty_portp(C_word x)
+
+Is {{x}} a TTY port object?
+
+==== Structures
+
+===== C_i_structurep
+
+ [C macro] C_word C_i_structurep(C_word x, C_word s)
+
+Is {{x}} a structure (record) object with type tag {{s}}? This is
+completely safe to use, because it checks whether x is an immediate or
+not.
+
+==== Characters
+
+These understand only ASCII characters.
+
+===== C_u_i_char_alphabeticp
+
+ [C macro] C_word C_u_i_char_alphabeticp(C_word c)
+
+Is {{c}} an alphabetic character?
+
+===== C_u_i_char_numericp
+
+ [C macro] C_word C_u_i_char_numericp(C_word c)
+
+Is {{c}} a numeric character?
+
+===== C_u_i_char_whitespacep
+
+ [C macro] C_word C_u_i_char_whitespacep(C_word c)
+
+Is {{c}} a whitespace character?
+
+===== C_u_i_char_upper_casep
+
+ [C macro] C_word C_u_i_char_upper_casep(C_word c)
+
+Is {{c}} an uppercase character?
+
+===== C_u_i_char_lower_casep
+
+ [C macro] C_word C_u_i_char_lower_casep(C_word c)
+
+Is {{c}} a lowercase character?
+
+
+=== Other Scheme procedures from C
+
+There are a number of Scheme procedures that have a direct C
+implementation, so you can call them from C too.
+
+==== C_eqp
+
+ [C macro] C_word C_eqp(C_word a, C_word b)
+
+The C version of {{(eq? a b)}}.
+
+==== C_equalp
+
+ [C macro] C_word C_equalp(C_word a, C_word b)
+
+The C version of {{(equal? a b)}}.
+
+==== C_i_pairp
+
+ [C function] C_word C_i_pair_p(C_word x)
+
+The C version of {{(pair? x)}}.
+
+==== C_i_not_pair_p
+
+ [C macro] C_word C_i_not_pair_p(C_word x)
+
+The C version of {{(not (pair? x))}}.
+
+
=== An example for simple calls to foreign code involving callbacks
% cat foo.scm
diff --git a/manual/Extensions b/manual/Extensions
index f069aeea..eb392a3a 100644
--- a/manual/Extensions
+++ b/manual/Extensions
@@ -333,6 +333,8 @@ macro.
=== Examples for extensions
+==== A simple library
+
The simplest case is a single file that does not export any syntax. For example
<enscript highlight=scheme>
@@ -384,12 +386,14 @@ execute the any files with the {{.setup}} extension it can find.
Use it like any other CHICKEN extension:
$ csi -q
- #;1> (require-extension hello)
+ #;1> (require-library hello)
; loading /usr/local/lib/chicken/4/hello.so ...
#;2> (hello "me")
Hello, me!
#;3>
+==== An application
+
Here we create a simple application:
<enscript highlight=scheme>
@@ -430,11 +434,113 @@ normally be {{/usr/local/bin}}. Note that you need write-permissions
for those locations and may have to run {{chicken-install}} with
administrative rights or use the {{-sudo}} option.
+The extension can be used from the command line:
+
+ $ hello2 one two three
+ Hello,
+ one two three !
+
De-installation is just as easy - use the {{chicken-uninstall}}
program to remove one or more extensions from the local repository:
$ chicken-uninstall hello2
+==== A module exporting syntax
+
+The hello module was just a shared library, and not a module.
+
+To create an extension that exports syntax see the chapter on
+[[http://chicken.wiki.br/man/4/Modules%20and%20macros|Modules and
+macros]]. We will show a simple example here: a module {{my-lib}}
+that exports one macro ({{prog1}}) and one procedure ({{my-sum}}):
+
+<enscript highlight=scheme>
+;;; my-lib.scm
+
+(module my-lib
+ *
+ (import scheme chicken)
+
+(define-syntax prog1
+ (syntax-rules ()
+ ((_ e1 e2 ...)
+ (let ((result e1))
+ (begin e2 ...)
+ result))))
+
+(define my-sum
+ (lambda (numbers)
+ (prog1
+ (apply + numbers)
+ (display "my-sum used one more time!")
+ (newline))))
+
+)
+</enscript>
+
+The {{prog1}} macro is similar to Common Lisp's {{prog1}}: it
+evaluates a list of forms, but returns the value of the first form.
+
+The meta file:
+
+<enscript highlight=scheme>
+;;; my-lib.meta
+
+((files "my-lib.setup"
+ "my-lib.scm")
+ (licence "BSD")
+ (author "Me again")
+ (synopsis "My own cool libraries"))
+</enscript>
+
+The setup file is:
+
+<enscript highlight=scheme>
+;;; my-lib.setup
+
+(compile -s -O3 -d1 "my-lib.scm" -j my-lib)
+(compile -c -O3 -d1 "my-lib.scm" -unit my-lib)
+(compile -s -O3 -d0 "my-lib.import.scm")
+
+(install-extension
+ 'my-lib
+ '("my-lib.o" "my-lib.so" "my-lib.import.so")
+ '((version 1.0)
+ (static "my-lib.o")))
+</enscript>
+
+The first line tells the compiler to create a shared ({{-s}}) library
+and to create an import file ({{my-lib.import.scm}}, because of the
+{{-j}} flag). The second line creates a static library
+{{my-lib.o}}. The third line compiles the import file created by the
+first one.
+
+IMPORTANT: the module name exported by my-lib.scm must be the same
+module name passed to the compiler using the -j option, otherwise the
+imports file will not be generated!
+
+Running {{chicken-install}} on the same directory will install the extension.
+
+Next, it should be possible to load the library:
+
+ $ csi -q
+ #;1> (use my-lib)
+ ; loading /usr/local/lib/chicken/5/my-lib.import.so ...
+ ; loading /usr/local/lib/chicken/5/scheme.import.so ...
+ ; loading /usr/local/lib/chicken/5/chicken.import.so ...
+ ; loading /usr/local/lib/chicken/5/my-lib.so ...
+ #;2> (my-sum '(10 20 30))
+ my-sum used one more time!
+ 60
+ #;3> (my-sum '(-1 1 0))
+ my-sum used one more time!
+ 0
+ #;4> (prog1 (+ 2 2) (print "---"))
+ ---
+ 4
+
+==== Notes on chicken-install
+
When running {{chicken-install}} with an argument {{NAME}}, for which
no associated {{.setup}} file exists, then it will try to download the
extension via HTTP from the CHICKEN code repository at
@@ -500,16 +606,59 @@ code is going to be evaluated. When {{chicken-install}} is run as
extension mechanism).
Security-conscious users should never run {{chicken-install}} as root.
-A simple remedy is to set the environment variable
-{{CHICKEN_REPOSITORY}}, which will transparently place the repository
-at an arbitrary user-selected location (don't forget to initialize it
-first with {{chicken-install -init <directory>}}). Alternatively
-obtain write/execute access to the default location of the repository
+A simple remedy is to keep the repository inside a user's home
+directory (see the section "Changing repository location" below).
+Alternatively obtain write/execute access to the default location of the repository
(usually {{/usr/local/lib/chicken}}) to avoid running as
root. {{chicken-install}} also provides a {{-sudo}} option to perform
the last installation steps as root user, but do building and other
-.setup script processing as normal.
+.setup script processing as normal. A third solution is to
+override {{VARDIR}} when building the system
+(for example by passing {{"VARDIR=/foo/bar"}} on the make command line,
+or by modifying {{config.make}}. Eggs will then be installed in
+{{$(VARDIR)/chicken/5}}.
+
+=== Changing repository location
+
+When Chicken is installed a repository for eggs is created and initialized
+in a default location (usually something like {{/usr/local/lib/chicken/5/}}).
+It is possible to keep an eggs repository in another location. This can be
+configured at build-time by passing {{VARDIR=<directory>}} to {{make(3)}}
+or by modifying the {{config.make}} configuration file. If you want to
+override this location after chicken is installed, you can create an
+initial repository directory with some default extensions and set the
+{{CHICKEN_REPOSITORY}} environment variable:
+
+First, initialize the new repository with
+
+ chicken-install -init ~/myeggs/lib/chicken/5
+
+Then set this environment variable:
+
+ export CHICKEN_REPOSITORY=~/myeggs/lib/chicken/5
+
+{{CHICKEN_REPOSITORY}} is the place where extensions are to be
+loaded from for all chicken-based programs (which includes all
+the tools).
+
+You can install eggs with
+
+ chicken-install -p ~/my_eggs <package>
+
+See that the argument to chicken-install is just {{~/myeggs}}, while everywhere else it's
+{{~/myeggs/lib/chicken/5}}.
+
+When you load eggs from the interpreter, you will see messages showing
+where libraries are being loaded from:
+ #;1> (use numbers)
+ ; loading /home/jdoe/myeggs/lib/chicken/5/numbers.import.so ...
+ ; loading /home/jdoe/myeggs/lib/chicken/5/scheme.import.so ...
+ ; loading /home/jdoe/myeggs/lib/chicken/5/chicken.import.so ...
+ ; loading /home/jdoe/myeggs/lib/chicken/5/foreign.import.so ...
+ ; loading /home/jdoe/myeggs/lib/chicken/5/regex.import.so ...
+ ; loading /home/jdoe/myeggs/lib/chicken/5/numbers.so ...
+ #;2>
=== Other modes of installation
diff --git a/manual/Getting started b/manual/Getting started
index b359d2ef..255803af 100644
--- a/manual/Getting started
+++ b/manual/Getting started
@@ -241,16 +241,6 @@ can pretty much ignore the C compiler once you have installed it.)
that comes with mingw. {{Makefile.mingw-msys}}
uses unix commands such as {{cp}} and {{rm}}. The end product is the
same.
-** Microsoft Visual Studio will soon be supported, including the
- Express edition, which is a non-free but no-cost compiler suite
- available from Microsoft
- ([[http://www.microsoft.com/express/vc]]). Chicken supports
- command-line building using the command-line C/C++ compiler.
-*** Visual
- Studio users will want to install the Unix Utilities, available at
- [[http://www.call-with-current-continuation.org/tarballs/UnxUtils.zip]],
- in order to get suitable versions of {{make}}, {{tar}}, {{gzip}}, and
- similar commands.
Refer to the {{README}} file for the version you're installing for
more information on the installation process.
@@ -284,11 +274,8 @@ proportional fonts, in particular.)
* Emacs ([[http://www.gnu.org/software/emacs]]) is an
extensible, customizable, self-documenting editor available for
-Linux/Unix, Macintosh, and Windows systems; CHICKEN provides Emacs
-support out of the box, with the {{hen.el}} Emacs Lisp file. Consult
-the `Emacs Guide for Chicken Users' (which will be available on the
-Chicken Wiki soon) for information on setting up and using Emacs with
-Chicken.
+Linux/Unix, Macintosh, and Windows systems; See
+[[/emacs]] for more information about the available options.
* Epsilon ([[http://www.lugaru.com]]) is a commercial (proprietary) text
editor whose design was inspired by Emacs. Although Scheme support
diff --git a/manual/Modules and macros b/manual/Modules and macros
index 9f901994..4c7addf6 100644
--- a/manual/Modules and macros
+++ b/manual/Modules and macros
@@ -22,7 +22,9 @@ a {{syntax-rules}} form. If {{syntax-rules}} is used, the usual R5RS
semantics apply. If {{TRANSFORMER}} is a procedure, then it will
be called on expansion with the complete s-expression of the macro
invocation, a rename procedure that hygienically renames identifiers
-and a comparison procedure that compares (possibly renamed) identifiers.
+and a comparison procedure that compares (possibly renamed) identifiers
+(see the section "Explicit renaming macros" below for a detailed explanation
+on non-R5RS macros).
{{define-syntax}} may be used to define local macros that are visible
throughout the rest of the body in which the definition occurred, i.e.
diff --git a/manual/Unit library b/manual/Unit library
index a152cd2a..697de3fa 100644
--- a/manual/Unit library
+++ b/manual/Unit library
@@ -688,20 +688,21 @@ subprocess is returned unaltered.
On a UNIX system, that value is the raw return value of waitpid(2), which contains signal, core dump and exit status. It is 0 on success. To pull out the signal number or exit status portably requires POSIX calls, but in a pinch you can use something like this:
- ;; Returns two values: #t if the process exited normally or #f otherwise;
- ;; and either the exit status, or the signal number if terminated via signal.
- (define (process-status rc)
- (define (wait-signaled? x) (not (= 0 (bitwise-and x 127))))
- (define (wait-signal x) (bitwise-and x 127))
- (define (wait-exit-status x) (arithmetic-shift x -8))
- (if (wait-signaled? rc)
- (values #f (wait-signal rc))
- (values #t (wait-exit-status rc))))
-
- #;> (process-status (system "exit 42"))
- #t
- 42
-
+<enscript highlight='scheme'>
+;; Returns two values: #t if the process exited normally or #f otherwise;
+;; and either the exit status, or the signal number if terminated via signal.
+(define (process-status rc)
+ (define (wait-signaled? x) (not (= 0 (bitwise-and x 127))))
+ (define (wait-signal x) (bitwise-and x 127))
+ (define (wait-exit-status x) (arithmetic-shift x -8))
+ (if (wait-signaled? rc)
+ (values #f (wait-signal rc))
+ (values #t (wait-exit-status rc))))
+
+#;> (process-status (system "exit 42"))
+#t
+42
+</enscript>
=== Execution time
diff --git a/manual/Using the compiler b/manual/Using the compiler
index 97f662d8..7fac33a5 100644
--- a/manual/Using the compiler
+++ b/manual/Using the compiler
@@ -130,7 +130,7 @@ Possible options are:
; -inline-limit THRESHOLD : Sets the maximum size of a potentially inlinable procedure. The default threshold is {{20}}.
-; -keyword-style STYLE : Enables alternative keyword syntax, where {{STYLE}} may be either {{prefix}} (as in Common Lisp), {{suffix}} (as in DSSSL) or {{none}}. Any other value is ignored. The default is {{suffix}}.
+; -keyword-style STYLE : Enables alternative keyword syntax, where {{STYLE}} may be either {{prefix}} (as in Common Lisp, e.g. :keyword), {{suffix}} (as in DSSSL, e.g. keyword:) or {{none}}. Any other value is ignored. The default is {{suffix}}.
; -keep-shadowed-macros : Do not remove macro definitions with the same name as assigned toplevel variables (the default is to remove the macro definition).
diff --git a/manual/Using the interpreter b/manual/Using the interpreter
index 743eb2c2..c1804906 100644
--- a/manual/Using the interpreter
+++ b/manual/Using the interpreter
@@ -37,7 +37,7 @@ The options recognized by the interpreter are:
; -I -include-path PATHNAME : Specifies an alternative search-path for files included via the {{include}} special form. This option may be given multiple times. If the environment variable {{CHICKEN_INCLUDE_PATH}} is set, it should contain a list of alternative include pathnames separated by {{;}}.
-; -k -keyword-style STYLE : Enables alternative keyword syntax, where {{STYLE}} may be either {{prefix}} (as in Common Lisp) or {{suffix}} (as in DSSSL). Any other value is ignored.
+; -K -keyword-style STYLE : Enables alternative keyword syntax, where {{STYLE}} may be either {{prefix}} (as in Common Lisp) or {{suffix}} (as in DSSSL). Any other value is ignored.
; -n -no-init : Do not load initialization-file. If this option is not given and the file {{./.csirc}} or {{$HOME/.csirc}} exists, then it is loaded before the read-eval-print loop commences.
diff --git a/manual/faq b/manual/faq
index 57324258..d4a54820 100644
--- a/manual/faq
+++ b/manual/faq
@@ -596,15 +596,16 @@ See the [[Extensions]] chapter for more information.
You can just set the {{CHICKEN_REPOSITORY}} environment variable.
It should contain the path where you want eggs to be installed:
- $ export CHICKEN_REPOSITORY=~/chicken/
- $ chicken-install -init
- $ chicken-install extensionname
+ $ export CHICKEN_REPOSITORY=~/eggs/lib/chicken/5
+ $ chicken-install -init ~/eggs/lib/chicken/5
+ $ chicken-install -p ~/eggs/ extensionname
+
+In order to make programs (including csi) see these eggs, you should set this variable when you run them. See the [[http://chicken.wiki.br/man/4/Extensions#changing-repository-location|Extensions/Changing repository location]] section of the manual for more information on that.
-In order to make programs (including csi) see these eggs, you should set this variable when you run them.
Alternatively, you can call the {{repository-path}} Scheme procedure before loading the eggs, as in:
<enscript highlight=scheme>
-(repository-path "/home/azul/chicken")
+(repository-path "/home/azul/eggs")
(use format-modular)
</enscript>
Trap