~ 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