\input texinfo   @c -*-texinfo-*-
@c %**start of header
@setfilename sizzle-embed.info
@settitle Sizzle Embedding Manual
@iftex
@afourpaper
@end iftex
@c %**end of header

@set UPDATED 28 Sep 2000
@set EDITION 0.0.30
@set VERSION 0.0.30

@dircategory Sizzle Scheme Interpreter
@direntry
* sizzle-embed: (sizzle-embed).     Embedding Sizzle
@end direntry

@ifinfo
This file documents embedding of the Sizzle Scheme interpreter.

Copyright (C) 1999, 2000 Martin Grabmueller

Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
@end ifinfo



@c --- title page starts here ---

@titlepage
@title Sizzle
@subtitle Embedding Manual
@subtitle Version @value{VERSION}
@author Martin Grabmueller

@c  The following two commands
@c  start the copyright page.
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1999, 2000 Martin Grabmueller

Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
@end titlepage

@c --- title page ends here ---



@syncodeindex vr cp
@syncodeindex fn cp



@node Top, Introduction, (dir), (dir)
@comment  node-name,  next,  previous,  up

@ifinfo
This document describes how to embed Sizzle into C programs.

It applies to version @value{VERSION} of Sizzle.
@end ifinfo

@menu
* Introduction::                Introduction to Sizzle
* Embedding Sizzle::            How to embed Sizzle into your C programs
* Embedding API::               API functions provided for embedding
* Memory Management::           How memory is managed in Sizzle
* Creating Data Types::         How to create new Scheme data types
* Creating Port Types::         How to create new Scheme port types
* Adding Primitives::           How to add procedures written in C
* sizzle-gen-if::               Description of the interface generator
* Index::                       Function and variable index
@end menu



@node    Introduction, Embedding Sizzle, Top, Top
@comment  node-name,  next,  previous,  up
@chapter Introduction

Sizzle is an interpreter for a programming language. It is designed to
be used as an embedded extension language and as a scripting language
for a wide variety of purposes.

This manual documents how to master the embedding process needed to make
use of Sizzle's features in a C application.  For more information on
Sizzle, on Scheme programming and a reference of the variables and
procedures available in Sizzle see @ref{Top, , Introduction, sizzle-ref,
The Sizzle Reference Manual}.

Chapter 2 deals with embedding, containing a tutorial which shows how to
use Sizzle to parse the initialization file for a little example
program.  

In Chapter 3, the C API for embedding is documented.

The following Chapter 4 deals with mechanisms and concepts for extending
the Sizzle interpreter for special purposes by adding data types and
primitive procedures.



@node Embedding Sizzle, Embedding API, Introduction, Top
@comment  node-name,  next,  previous,  up
@chapter Embedding Sizzle

The Sizzle interpreter is implemented in the library @file{libsizzle}.
This library is installed when Sizzle is installed and actually is used
by the Sizzle interpreter @file{sizzle} for all its work.
@file{libsizzle} can be embedded in other programs very easily, and this
chapter will show how to do it.

@menu
* Compiling and Linking::         How to compile against libsizzle
* Parsing initialization files::  Using Sizzle for parsing init files
@end menu


@node Compiling and Linking, Parsing initialization files, Embedding Sizzle, Embedding Sizzle
@comment  node-name,  next,  previous,  up
@section Compiling and Linking

When compiling against the Sizzle library, you have to tell the compiler
where to find the Sizzle include files, and the linker, where to find
the library itself.  When you installed Sizzle in the standard location
(with @code{$prefix} set to @file{/usr/local/lib}), the files are likely
to be found, but embedding Sizzle should be possible when installed in
another location too.  That is the reason the script
@file{sizzle-config} was included in the distribution.  This script gets
installed in the same location as the @file{sizzle} interpreter, and can
be used to obtain information about the Sizzle installation.

@file{sizzle-config} understands three commands, which must be given
on the command line.  Either command causes the script to print out a
line of options, suitable for inclusion in the compiler or linker command.

@table @code
@item compile
Print the @code{-I} compiler option for finding the include files.
@item link
Print the options for linking against the Sizzle library (for example,
@code{-L/usr/local/lib -R/usr/local/lib -lsizzle -lm -ldl})
@item static-link
Print the options for linking statically against the Sizzle library (for
example, @code{/usr/local/lib/libsizzle.a -lm -ldl})
@end table

@node Parsing initialization files,  , Compiling and Linking, Embedding Sizzle
@comment  node-name,  next,  previous,  up
@section Parsing Initialization files

One design goal for Sizzle was to make it easy to use the interpreter
for parsing initialization files.  Using a complete programming language
for init files has the advantage that a lot intelligence for setting up
a program can be put into these init files.  One popular example is the
Emacs editor.  This chapter will explain in tutorial style which steps
are necessary to use Sizzle for this purpose.

The four steps in the following sub-section describe in detail what to
do if you want to include Sizzle into your application for the purpose
of parsing init files.  In the @file{examples} directory of the source
distribution of Sizzle are included the files @file{example.c} and
@file{startup.scm}, which illustrate the following steps.

@menu
* Initializing the library::    How to initialize libsizzle
* Declaring variables::         Makeing C variables accessible to Scheme
* Loading the init file::       Load a file of Scheme code
* Shutting down the library::   Free all memory used by the library
@end menu



@node Initializing the library, Declaring variables, Parsing initialization files, Parsing initialization files
@comment  node-name,  next,  previous,  up
@subsection Initializing the library

Before you can use the @file{libsizzle} library, you have to initialize
it.  Two steps are necessary to do that.  First, you have to tell it the
address of the top of the C stack.  This is done by declaring a local
dummy variable and passing its address to the function
@code{zzz_set_top_of_stack()}.

@example
int
main (int argc, char * argv[])
@{
  zzz_scm_t dummy;

  /* Announce top of stack to Sizzle library, so conservative marking
     works.  */
  zzz_set_top_of_stack (&dummy);
@end example
@noindent
Then the library initialization is performed by a call to
@code{zzz_initialize()}.
@example
  /* Initialize the library.  */
  zzz_initialize ();
@end example
@noindent
The last step is not mandatory, but very useful.  You can pass the
command line options given to your program to the interpreter to make it
available to your Scheme code.
@example
  /* Make command line options available to Scheme code.  The zero'th
     argument is handled specially to make pre-processing of the
     arguments easier (see src/sizzle.c for details).  */
  zzz_set_arguments (argc - 1, argv[0], argv + 1);
@end example



@node Declaring variables, Loading the init file, Initializing the library, Parsing initialization files
@comment  node-name,  next,  previous,  up
@subsection Declaring variables

When the library is correctly initialized, you can bind variables in
your C code to Scheme variables.  Thus you can directly modify variables
in your C program from Scheme code.

Three different data types are currently supported: integers, strings
and boolean values.  Whenever you bind the address of a C variable to a
Scheme variable you have to tell the interpreter of which data type the
variable is.  The interpreter will then type-check assignments and
signal errors whenever a value of a wrong type is stored into a
variable.  Additionaly, it is considered an error to store a string
which is too long into a string variable.

The example program declares five variables of different types.
@example
  /* Bind some variables of different types.  The last argument is a
     flag whether the variable is allowed to get changed by Scheme
     code.  */
  zzz_bind_int_variable ("binary-port", &binary_port, 0);
  zzz_bind_int_variable ("command-port", &command_port, 0);
  zzz_bind_bool_variable ("verbose", &verbose, 0);
  zzz_bind_string_variable ("hostname", hostname, sizeof (hostname), 0);
  zzz_bind_string_variable ("download-area", download_area,
                            sizeof (download_area), 0);
  zzz_bind_scm_variable ("kill-lines", &kill_lines, 0);
@end example
@noindent
The first argument in each of these calls is the name which will be
given to the Scheme variable, the second argument is the address of the
C variable and the last is a flag whether the variable should be
read-only on the Scheme level.  When declaring string variables, you
have to pass the maximal length of the variable also, so range-checking
can be performed.



@node Loading the init file, Shutting down the library, Declaring variables, Parsing initialization files
@comment  node-name,  next,  previous,  up
@subsection Loading the init file

A call to the function @code{zzz_evaluate_file()} finally loads the init
file, which may contain any valid Scheme code.  The Scheme code has
access to all variables defined above.  For details about the init file,
see the file @file{startup.scm} in the @file{examples} directory.
@example
  /* Evaluate startup file.  */
  if ((return_val = zzz_evaluate_file (zzz_toplevel_env, "startup.scm")) != 0)
    fprintf (stderr, "example: error while reading init file\n");
@end example
@noindent
The return value of @code{zzz_evaluate_file()} is zero when all went
right and a non-zero value otherwise.

The variable @code{kill-lines} was bound to a generic variable of type
@code{zzz_scm_t}. That means that any Scheme value can be stored in the
variable and that no type checking is performed as for the other
variables which have explicitly been bound to variable of type int,
boolean or string.  When using such variables, you must be careful when
interpreting the values stored there.  The following example shows how
to safely handle a variable which was supposed to hold a list of
strings.
@example
  /* Interpretation of bound variables of type zzz_scm_t must be done
     before the library is finalized, otherwise dangling pointers will
     make your life hard.  */

  /* Iterate over list.  */
  while (cons_p (kill_lines))
    @{
      /* Make sure we are dealing with strings.  */
      if (string_p (car (kill_lines)))
        @{
          printf ("Kill line: %s\n", string_val (car (kill_lines)));
        @}
      kill_lines = cdr (kill_lines);
    @}
@end example



@node Shutting down the library,  , Loading the init file, Parsing initialization files
@comment  node-name,  next,  previous,  up
@subsection Shutting down the library

After parsing the init file, you will normally want to free all memory
used by the interpreter.  This is done by a call to
@code{zzz_finalize()}.
@example
  /* Free all memory used by the interpreter.  */
  zzz_finalize ();
@end example
@noindent
Note that all Scheme values, even those which might be stored into C
variables using @code{zzz_bind_scm_variable()}, are no longer valid when
you have shut down the interpreter.

That's it!  Not to hard, methinks.



@node Embedding API, Memory Management, Embedding Sizzle, Top
@comment  node-name,  next,  previous,  up
@chapter Embedding API

This section documents the C API for embedding Sizzle into C applications.

The calling conventions of most API functions follow the same concept.
The return value of those functions is an error code, values computed by
the functions are normally returned in reference parameters.  This is a
little bit unconvenient when calling these functions, because a lot of
temporary variables for holding the intermediate results must be
declared, but provides a very powerful interface for error handling,
since not only the fact that an error occured can be signalled, but also
additional information about the error condition can be returned in the
result variable.

That is the reason why those return codes and parameters are also used
for implementing exceptions.  Whenever a call to an API function does
not return @code{RESULT_SUCCESS}, the error is immediately propagated up
the call chain.  So not only errors are passed up, but also exceptions.
The exception objects passed up together with the exception code can be
examined and particular exceptions can be caught using this technique.

@menu
* Initializing and Finalization::  Functions for starting up and shutting down.
* Scheme Variable Handling::    Creating and accessing Scheme variables.
* Hash table handling::         Accessing Scheme hash tables from C.
* C Variable Handling::         Binding C variables to Scheme names.
* Evaluation Functions::        Evaluate strings and files.
* Object constructors::         How to create Scheme objects.
* Type predicates::             Macros for determining the type of an object.
* Accessor functions::          Accessing properties of objects.
* Port Functions::              Using Scheme ports from C code.
* Defining Scheme Types::       API functions for defining new types.
* Misc C API Functions::        Leftovers in the C API.
@end menu



@node Initializing and Finalization, Scheme Variable Handling, Embedding API, Embedding API
@comment  node-name,  next,  previous,  up
@section Initializing and Finalization

When using the Sizzle library, you habe the choice of using one of two
methods.  @xref{Parsing initialization files}, where the first is shown
in detail. It consists of calling the functions
@code{zzz_set_top_of_stack()}, @code{zzz_initialize()} and
@code{zzz_finalize()}; the other method is used by the Sizzle
interpreter @file{sizzle} and uses only the call @code{zzz_run()}.  The
former is more easily to incorporate into existing programs whereas the
latter is much simpler and less error-prone.

@deftypefun void zzz_set_top_of_stack (zzz_scm_t * @var{cell})
Tell the Sizzle library that the pointer @var{cell} points to a location
on the C stack which marks the end of the stack as far as conservative
garbage collection is concerned.  Use this function before any other
call to the Sizzle library, or use the @code{zzz_run()} function.
@end deftypefun

@deftypefun void zzz_initialize (void)
Initialize the library.
@end deftypefun

@deftypefun void zzz_finalize (void)
Shut down the library and free all memory allocated by the interpreter.
@end deftypefun

@deftypefun void zzz_set_arguments (int @var{argc}, char * @var{argv0}, char * @var{argv}[])
Set the command line arguments which will be visible to running Scheme
code.  @var{argc} is the count of elements in the vector @var{argv},
@var{argv0} is the program name and @var{argv} is a vector of the
remaining command line arguments.
@end deftypefun

@deftypefun int zzz_run (int (* @var{main})(int argc, char * argv[]), int @var{argc}, char * @var{argv}[])
Intitialize the Sizzle library and call the function @var{main}, passing
@var{argc} and @var{argv} as arguments.  This is the recommended
function for using the Sizzle library and is used by the @file{sizzle}
program itself.  Returns the exit code of @var{main}.  You should not
call any function from @file{libsizzle} before calling this function and
you should not call any after calling it.  @code{zzz_run()} does all
necessary initialization and finalization.
@end deftypefun



@node Scheme Variable Handling, Hash table handling, Initializing and Finalization, Embedding API
@comment  node-name,  next,  previous,  up
@section Scheme Variable Handling

The function in this section all modify objects in the Scheme name
space.  They either create or modify Scheme variables, constants or
functions, but they can also be used to query those objects.

All functions below create their bindings in the outermost scope, even
below the toplevel environments.  The bindings are thus equivalent in
scope to the builtin variables and procedures (in fact, builtin bindings
are created using these functions).

@deftypefun result_t zzz_get_variable (zzz_scm_t @var{sym}, zzz_scm_t * @var{result})
Return the value of the variable @var{sym} in the global environment.
Returned is the value in the location pointed to by @var{result} and
@code{RESULT_SUCCESS} if no error occurs, otherwise an error code is
returned and an error object is stored in the location pointed to by
@var{result}.
@end deftypefun

@deftypefun result_t zzz_set_variable (zzz_scm_t @var{sym}, zzz_scm_t value, zzz_scm_t * @var{result})
Set the variable @var{sym} in the global environment to the value
@var{value}.  @code{RESULT_SUCCESS} is returned if no error occurs,
otherwise an error code is returned and an error object is stored in the
location pointed to by @var{result}.
@end deftypefun

@deftypefun zzz_scm_t zzz_define_variable (char * @var{name}, zzz_scm_t @var{value})
Define the variable @var{name}, which will be bound in the toplevel
environment to @var{value}.  Returns the symbol created for the
variable.
@end deftypefun

@deftypefun zzz_scm_t zzz_define_constant (char * @var{name}, zzz_scm_t @var{value})
Define the read-only variable @var{name}, which will be bound in the
toplevel environment to @var{value}.  Returns the symbol created for the
variable.  The difference between @code{zzz_define_constant()} and
@code{zzz_define_variable()} is that the variables defined with the
former can not be modified by @code{set!} operations.  Also, variables
defined using @code{zzz_define_constant()} are more efficient because
references to these constant variables are replaced by their values
during runtime.
@end deftypefun

@deftypefun zzz_scm_t zzz_define_function (char * @var{name}, result_t (* @var{func})(), int @var{param_format})
Define a function called @var{name} which refers to the builtin function
@var{func} and takes parameters as specified by @var{param_format}.
@end deftypefun

@deftypefun zzz_scm_t zzz_define_form (char * @var{name}, zzz_prim_t @var{func}, int preprocessing)
Define the special form @var{name}, which will be calling the C function
@var{func}.  Returns the symbol created for the function.  Note that
when functions for handling special forms are called, they are passed
the entire form, including the special form name as the first element of
the parameter list.  If @var{preprocessing} is true, the function
@var{func} will not evaluate the form, but only error check and replace
it with an immediate form for faster execution.
@end deftypefun



@node Hash table handling, C Variable Handling, Scheme Variable Handling, Embedding API
@comment  node-name,  next,  previous,  up
@section Hash table handling

Hash tables are represented as vectors which hold association lists.
When storing a key/value pair, or looking up the value for a given pair,
a hash value is calculated for the key and used as an index into the
vector.  Then the association list found at the index is scanned for the
key.

@deftypefun {unsigned long} zzz_hash_function (zzz_scm_t @var{object})
Return a hash value for the Scheme object @var{object}.
@end deftypefun

@deftypefun zzz_scm_t zzz_hashq_ref (zzz_scm_t @var{tab}, zzz_scm_t @var{key}, zzz_scm_t @var{def})
@deftypefunx zzz_scm_t zzz_hashv_ref (zzz_scm_t @var{tab}, zzz_scm_t @var{key}, zzz_scm_t @var{def})
@deftypefunx zzz_scm_t zzz_hash_ref (zzz_scm_t @var{tab}, zzz_scm_t @var{key}, zzz_scm_t @var{def})
Fetch the element associated with @var{key} from the hash table
@var{tab}.  If an error occurs or the @var{key} is not found, @var{def}
is returned.  @code{zzz_hashq_ref} uses @code{eq?} as the equality
predicate for searching for @var{key}, @code{zzz_hashv_ref} uses
@code{eqv?} and @code{zzz_hash_ref} uses @var{equal?}.
@end deftypefun

@deftypefun zzz_scm_t zzz_hashq_set (zzz_scm_t @var{tab}, zzz_scm_t @var{key}, zzz_scm_t @var{value})
@deftypefunx zzz_scm_t zzz_hashv_set (zzz_scm_t @var{tab}, zzz_scm_t @var{key}, zzz_scm_t @var{value})
@deftypefunx zzz_scm_t zzz_hash_set (zzz_scm_t @var{tab}, zzz_scm_t @var{key}, zzz_scm_t @var{value})
Add the association @var{key} => @var{value} to the hash table
@var{tab}.  If an association with @var{key} already exists, it is
overwritten with @var{value}.  If an error occurs or the @var{key} is
not found, @var{NULL} is returned, if everything went right, @var{value}
is returned.  @code{zzz_hashq_ref} uses @code{eq?} as the equality
predicate for searching for @var{key}, @code{zzz_hashv_ref} uses
@code{eqv?} and @code{zzz_hash_ref} uses @var{equal?}.
@end deftypefun



@node C Variable Handling, Evaluation Functions, Hash table handling, Embedding API
@comment  node-name,  next,  previous,  up
@section C Variable Handling

Another method for interfacing Scheme and C code is declare variables in
your C source and then bind the locations of these variables to Scheme
variable names.  The advantage is that you can then reference the values
stored into the variables by simply using the variables like normal C
variables.  Variables created with these functions are totally
transparent to the Scheme code, there is not even a method how the
Scheme code can find out whether a given variable is bound to a C
variable or not.

@deftypefun result_t zzz_protect_global (zzz_scm_t * @var{scm})
Protect the variable pointed to by @var{scm} globally from being garbage
collected.  You should call this functions whenever you create a
variable of type @code{zzz_scm_t}, but do not wish to bind that variable
to a Scheme variable using @code{zzz_bind_scm_variable()}.  Returns
@code{RESULT_SUCCESS} on success and an error code otherwise.
@end deftypefun

@deftypefun void zzz_bind_int_variable (char * @var{name}, int * @var{address}, int @var{read_only})
Create a toplevel Scheme variable named @var{name} of type integer which
is bound to the C variable pointed to by @var{address}.  The variable
will be read-only if @var{read_only} is true.
@end deftypefun

@deftypefun void zzz_bind_bool_variable (char * @var{name}, int * @var{address}, int @var{read_only})
Create a toplevel Scheme variable named @var{name} of type boolean which
is bound to the C variable pointed to by @var{address}.  The variable
will be read-only if @var{read_only} is true.
@end deftypefun

@deftypefun void zzz_bind_string_variable (char * @var{name}, char * @var{address}, int @var{len}, int @var{read_only})
Create a toplevel Scheme variable named @var{name} of type string which
is bound to the C variable pointed to by @var{address}.  The variable
will be read-only if @var{read_only} is true.
@end deftypefun

@deftypefun void zzz_bind_scm_variable (char * @var{name}, zzz_scm_t * @var{address}, int @var{read_only})
Create a toplevel Scheme variable named @var{name} of type zzz_scm_t
which is bound to the C variable pointed to by @var{address}.  The
variable will be read-only if @var{read_only} is true.  This functions
automatically takes care of protecting the passed location from garbage
collection, thus variables bound using this functions are safe.
@end deftypefun



@node Evaluation Functions, Object constructors, C Variable Handling, Embedding API
@comment  node-name,  next,  previous,  up
@section Evaluation Functions

Use one of these functions if you like to evaluate Scheme code.  The
functions which take an @dfn{environment} as a parameter evaluate the
given expression, string or file in that environment, that means that
all bindings which may be created are effectively created in the given
environment.  You can pass the variable @var{zzz_toplevel_env} for the
@var{env} parameter to these functions if you do not have any special
requirements.

@deftypefun int zzz_evaluate_file (zzz_scm_t @var{env}, const char * @var{filename})
Evaluate all Scheme expressions from the file called @var{filename} in
the environment @var{env}.  Returns 0 if no error occurs, -1 if the file
was not found, -2 if an error occured when evaluating the file or
another exit code if the file contained a call to @code{exit}.  All
expressions in the file are evaluated in the environment @var{env}.
Evaluation is aborted as soon as an error is encountered or evaluation
is aborted using @code{exit}.
@end deftypefun

@deftypefun int zzz_evaluate_string (zzz_scm_t @var{env}, const char * @var{str})
Evaluate all Scheme expressions from the string @var{str} in the
environment @var{env}.  Returns 0 if no error occurs, -2 if an
evaluation error is encountered or another exit code if the string
contained a call to @code{exit}.  All expressions in the string are
evaluated in the environment @var{env}.  Evaluation is aborted as soon
as an error is encountered or evaluation is aborted using @code{exit}.
@end deftypefun

@deftypefun int zzz_read_eval_print (void)
Execute Sizzle's read-eval-print loop.  Expressions will be read from
standard input, evaluated and the results will be written to standard
output.  Error messages will be sent to standard error.  Returns 0 if
terminated normally or another exitcode if the user enters the
@code{exit} command with an exit code.
@end deftypefun

@deftypefun result_t zzz_apply (zzz_scm_t @var{env}, zzz_scm_t @var{proc}, zzz_scm_t @var{param_list}, zzz_scm_t * @var{result})
Apply the procedure @var{proc} (which may be a primitive procedure or a
closure) to the parameter list @var{param_list}.  Evaluation takes place
in the environment @var{env}.  The result is returned in the location
pointed to by @var{result}.  On success, @code{RESULT_SUCCESS} is
returned, otherwise an error code and an error object is stored in
@var{result}.
@end deftypefun

@deftypefun result_t zzz_evaluate (zzz_scm_t @var{env}, zzz_scm_t @var{expr}, zzz_scm_t * @var{result})
Evaluate the Scheme expression @var{expr} in the environment @var{env}.
The result is returned in the location pointed to by @var{result}.  On
success, @code{RESULT_SUCCESS} is returned, otherwise an error code and
an error object is stored in @var{result}.
@end deftypefun



@node Object constructors, Type predicates, Evaluation Functions, Embedding API
@comment  node-name,  next,  previous,  up
@section Object constructors

When creating Scheme values, the functions defined in this section
should be used.  They guarantee correct interfacing to the memory
management system and the garbage collector.

@deftypefun zzz_scm_t zzz_cons (zzz_scm_t @var{car}, zzz_scm_t @var{cdr})
Creates a cons cell with car and cdr initialized to the values of
@var{car} and @var{cdr}, respectively.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_list (zzz_scm_t @var{first}, ...)
Create a Scheme list of all parameters.  @var{first} is the first element
of the resulting list, followed by the optional parameters.  The
parameter list must be terminated with a NULL pointer.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_n_list (int @var{n}, zzz_scm_t @var{first}, @dots{})
Create a Scheme list of exactly @var{n} parameters.  @var{first} is the
first element of the resulting list, followed by the optional
parameters.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_fixnum (long @var{number})
Create a fixnum object with integer value @var{number}.  If @var{number}
does not fit into the range of fixnums, its high bits are silently
truncated.  The fixnum range is between -268435456 and 268435455,
inclusive.

You should not use this function unless you are sure that the given
value fits into a fixnum.  Use @code{zzz_make_integer()} instead.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_integer (long @var{value})
Create an integer object with value @var{value}.  A fixnum is returned
if @var{value} fits into the range defined for fixnums, otherwise a long
object is returned which holds all 32 bits of information from
@var{value}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_string (const char * @var{s}, int @var{len})
Create a string of length @var{len} and initialize with the data pointed
to by @var{s}.  If @var{len} is less than zero, @var{s} is considered a
null-terminated string and the length is calculated by using
@code{strlen()}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_nstring (int @var{len})
Create a string of length @var{len}.  The contents of the returned
string is unspecified.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_ro_string (const char * @var{s}, int @var{len})
Create a constant string of length @var{len} and initialize with the
data pointed to by @var{s}.  If @var{len} is less than zero, @var{s} is
considered a null-terminated string and the length is calculated by
using @code{strlen()}.  The returned string is read-only and cannot be
modified with Scheme primitives like @code{string-set!}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_ro_nstring (int @var{len})
Create a constant string of length @var{len}.  The contents of the returned
string is unspecified.  The returned string is read-only and cannot be
modified with Scheme primitives like @code{string-set!}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_bool (long @var{b})
Create a boolean object.  If @var{b} is zero, the false Scheme object
@code{#f} is returned, otherwise the canonic true Scheme object
@code{#t} is returned.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_char (long @var{b})
Create a character object with character value @var{b}.  Only the lower
8 bits of @var{b} are actually used.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_float (double @var{d})
Create a real number object initialized with the value of @var{d}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_symbol (const char * @var{s}, int @var{len})
Create a Scheme symbol with the string representation @var{s} of length
@var{len}.  If @var{len} is less than zero, @code{strlen()} is used to
determine the string length.  This function will return the same object
for all strings with the same length and the same character contents.
@end deftypefun


@deftypefun zzz_scm_t zzz_make_func (zzz_prim_t @var{func}, const char * @var{name}, int @var{form}, int @var{param_format})
Create a primitive function object.  @var{func} is the address of the C
function that handles the primitive function, @var{name} is the Scheme
name under which the function will be available, @var{form} should be 0
for primitive functions and non-zero of syntactic forms and
@var{param_format} is a description of the parameter format the function
expects.  Use one of the @code{TAGGED_INFO_ARG_*_*_*} constants for this
parameters.
@end deftypefun


@deftypefun zzz_scm_t zzz_make_lambda (zzz_scm_t @var{expr})
Create a lambda object.  @var{expr} must be a list where the car is the
formal parameter list and the cdr must be the procedure body.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_closure (zzz_scm_t @var{proc}, zzz_scm_t @var{env})
Create a closure object which closes the procedure @var{proc} under the
environment @var{env}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_error (zzz_scm_t @var{msg}, zzz_scm_t @var{reference})
Create an error object.  @var{msg} is the error message, @var{reference}
is a list containing the file name, line number and column number where
the error occurred; or NULL if that information is not available.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_exception (zzz_scm_t @var{exception}, zzz_scm_t @var{msg})
Create an exception object. @var{exception} is the exception tag (any
atom) and @var{msg} is the exception message which may hold additional
information about the exception.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_environment (unsigned @var{size}, zzz_scm_t @var{static_link}, int @var{final}, int @var{read_only})
Create an environment object.  @var{static_link} is the link to the
including lexical environment in which variable binding will be
searched.  @var{size} denotes the size the hash table for the new
environment will have; it should be a prime number.

When @var{final} is true, variable lookups will not descend the static
chain further than to the created environment.

When @var{read_only} is true, variables defined in environments further
down the static link can only be read, but not modified.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_location (zzz_scm_t * @var{location}, int @var{read_only})
Create a location object.  A location object is an indirect object which
refers to a Scheme object variable address.  @var{location} points to
the location to redirect to and @var{read_only} specified whether this
location may be written to.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_lloc (zzz_scm_t @var{symbol}, int @var{env_ofs}, unsigned @var{hash_val})
Create a lloc object.  A lloc object is substituted for all local
variables which have been looked up once and which are not special
variables.  They are used to cache the location of variables and to
speed up references to local variables.  @var{symbol} is the variable
name this lloc stands for, @var{env_ofs} is the number of environments
to traverse down the static link and @var{hash_val} is the hash index
into the environment where we have to search for @var{symbol}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_gloc (zzz_scm_t @var{name}, zzz_scm_t * @var{address})
Create a gloc object.  A gloc is similar to a lloc, but only applies to
global variables not in an environment, but in the symbol table.
@var{name} is the variable name this gloc stands for, and @var{address}
is the location where the value of the variable can be found.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_constant (zzz_scm_t @var{value})
Create a constant object with value @var{value}.  A constant object is
special, since it value may be substituted whenever it is referenced,
and therefore references are faster than variable references.  Also
variables containing constant objects can not be modified.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_keyword (const char * @var{s}, int @var{len})
Create a Scheme keyword object with the string representation @var{s} of
length @var{len}.  If @var{len} is less than zero, @code{strlen()} is
used to determine the string length.  This function will return the same
object for all strings with the same length and the same character
contents.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_vector (int @var{len})
Create a vector object which holds @var{len} elements.  The vector
elements are initialized to the empty list @code{'()}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_ro_vector (int @var{len})
Create a constant vector object which holds @var{len} elements.  The
vector elements are initialized to the empty list @code{'()}.  The
returned vector is read-only and can not be modified using Scheme
primitives like @code{vector-set!}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_continuation (void)
Make a continuation object.  Note that the returned object is not
initialized, you have to capture the current continuation
explicitly using @code{zzz_capture_continuation()}.
@end deftypefun

@deftypefun zzz_scm_t zzz_create_tagged_cell (unsigned long @var{tag}, const void * @var{data0}, const void * @var{data1}, const void * @var{data2});
This is the generic object creation function for tagged types.  You have
to pass a type tag (maybe combined with one or more of the
@code{type_info_*} constants) in @var{tag}, and additional information
in the parameters @var{data0}, @var{data1} and @var{data2}.  The format
of the data parameters depends on what the internal constructor function
for the tagged type expects.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_values (zzz_scm_t @var{values})
Creates a multiple value object with the values in the list @var{values}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_regexp (const char * @var{str}, int @var{len}, int @var{flags})
Creates a regular expression object which matches the string @var{str}
of length @var{len}.  @var{flags} are used for compiling the regular
expression and may be any of the compile time flags specified for Posix
regular expressions.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_promise (zzz_scm_t @var{env}, zzz_scm_t @var{expression})
Creates a promise object.  The new object is closed
over the environment @var{env}, that means that the promise will be
evaluated in that environment once it is forced.  @var{expr} is the
expression to be delayed.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_macro (zzz_scm_t @var{code})
Creates a macro object with macro code @var{code}.  The car of
@var{code} must be the formal parameter list, the cdr must be the macro
body.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_syntax (zzz_scm_t @var{rules})
Creates a syantx object with syntax rules @var{rules}.  The rules must
have the same syntax as provided to a call to the Scheme form
@code{syntax-rules}.  body.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_fport (FILE * @var{file}, int @var{read}, int @var{write})
Creates a standard IO port for the file referenced by @var{file}.
@var{read} and @var{write} tell the input-output mode of the resulting
port object.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_fdport (int @var{fd}, int @var{read}, int @var{write})
Creates a file descriptor port for the file descriptor @var{fd}.
@var{read} and @var{write} tell the input-output mode of the resulting
port object.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_sport (int @var{start_len})
Creates a string port with a preallocated character buffer of size
@var{start_len}.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_sport_str (const char * @var{str})
Creates a string port with the initial contents of the null-terminated
string @var{str}.  The file pointer is initially set to zero.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_sport_str_n (const char * @var{str}, unsigned @var{len})
Creates a string port with the initial contents of the string @var{str}
with length @var{len}.  The file pointer is initially set to zero.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_sport_str_n_no_copy (char * @var{str}, unsigned @var{len})
Creates a string port with the initial contents of the string @var{str}
with length @var{len}.  The file pointer is initially set to zero.  This
function does not create a copy of the passed string, so you have to
make sure that the contents remains valid as long as the string port
does exists.  Use it for cnstant strings etc.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_@var{TAG}vector (int @var{len})
Create a homogenous numeric vector object which holds @var{len}
elements.  The vector elements are initialized to zero.

@var{TAG} in the constructor name may be replaced by @code{s8},
@code{u8}, @code{s16}, @code{u16}, @code{s32}, @code{u32}, @code{s64},
@code{u64}, @code{f32} or @code{f64}, depending on the needed datatype.
So there are actually ten of these constructor functions.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_ro_@var{TAG}vector (int @var{len})
Create a constant homogenous numeric vector object which holds @var{len}
elements.  The vector elements are initialized to zero.  The returned
vector is read-only and can not be modified using Scheme primitives like
@code{@var{TAG}vector-set!}.

@var{TAG} in the constructor name may be replaced by @code{s8},
@code{u8}, @code{s16}, @code{u16}, @code{s32}, @code{u32}, @code{s64},
@code{u64}, @code{f32} or @code{f64}, depending on the needed datatype.
So there are actually ten of these constructor functions.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_pointer (void * @var{address})
Create a pointer object which referencing @var{address}. 
@end deftypefun

@deftypefun zzz_scm_t zzz_make_pointer_n (void * @var{address}, unsigned @var{n})
Create a pointer object which referencing a memory area starting at
@var{address} and being @var{n} bytes long.
@end deftypefun

@deftypefun zzz_scm_t zzz_copy_list (zzz_scm_t @var{list})
Make a copy of the list @var{list}.  Note that @var{list} must be a
proper list.  This function only copies the spine of the list, that
means, that the list elements are shared, and only the cons cells
construcing the list are newly allocated.  If you need to make a
deep copy of a list, use @code{zzz_copy_tree()} instead.  
@end deftypefun

@deftypefun zzz_scm_t zzz_copy_tree (zzz_scm_t @var{tree})
Make a deep copy of the object @var{tree}.  That means, that vectors and
pairs are cloned recursively and all other objects are simply copied to
the returned object. 
@end deftypefun

@deftypefun zzz_scm_t zzz_make_not_available_exception (zzz_scm_t @var{args})
Create an exception object with the tag @code{not-available}, and the
additional exception data @var{args}.  This exception is thrown whenever
a primitive is called which is not supported under the currently running
version of Sizzle.
@end deftypefun

@deftypefun zzz_scm_t zzz_make_port (unsigned @var{port_type}, void * @var{info})
Create a port of the specified port type and install @var{info} as the
port's info field.
@end deftypefun


@node Type predicates, Accessor functions, Object constructors, Embedding API
@comment  node-name,  next,  previous,  up
@section Type predicates

These type predicates are safe in the sense that you do not risk a
segmentation fault when applying any of them to an arbitraty value of
type @code{zzz_scm_t}.  They simply return 0 if the condition they test
for is not satisfied.  Use them before using any of the accessor
functions (@pxref{Accessor functions}).

Note that the return values of these predicates are boolean values in
the C sense: zero means false and any other value means true.

@defmac null_p (@var{c})
@code{null_p(c)} returns a true value if @var{c} is the empty list.
@end defmac

@defmac fixnum_p (@var{c})
@code{fixnum_p(c)} returns a true value if @var{c} is a fixnum object.
@end defmac

@defmac imm_p (@var{c})
@code{imm_p(c)} returns a true value if @var{c} is an immediate value,
Immediate values are all values which are encoded into a pointer of type
@code{zzz_scm_t}, and which do not occupy any cells on the heap.  The
empty list, all fixnum values and immediate form objects are immediate
values.
@end defmac

@defmac immediate_p (@var{c})
@code{immediate_p(c)} returns a true value if @var{c} is an immediate
form.  Immediate forms are substituted for form applications to speed up
the evaluation of expressions.
@end defmac

@defmac cons_p (@var{c})
@code{cons_p(c)} returns a true value if @var{c} is a cons pair.
@end defmac

@defmac list_p (@var{c})
Returns a true value if @var{c} is a list.  A list is either a cons pair
or the empty list.
@end defmac

@defmac integer_p (@var{c})
@code{integer_p(c)} returns a true value if @var{c} is an integer
object. Both fixnum and long objects are integer objects.
@end defmac

@defmac procedure_p (@var{c})
@code{procedure_p(c)} returns a true value if @var{c} is a procedure
object.  Procedure objects are primitive procedures, syntax forms and
lambda expressions.
@end defmac

@defmac number_p (@var{c})
@code{number_p(c)} returns a true value if @var{c} is a number
object. Fixnum, long and real objects are numbers.
@end defmac

@defmac tagged_p (@var{c})
@code{tagged_p(c)} returns a true value if @var{c} is a tagged
object. This macro is true for all values which are neither immediate in
the sense of @code{immediate_p()} nor cons cells in the sense of
@code{cons_p()}.
@end defmac

@defmac string_p (@var{c})
@code{string_p(c)} returns returns a true value if @var{c} is a string object.
@end defmac

@defmac rostring_p (@var{c})
@code{rostring_p} returns returns a true value if @var{c} is a constant string
object.
@end defmac

@defmac bool_p (@var{c})
@code{bool_p(c)} returns a true value if @var{c} is a boolean object.
@end defmac

@defmac char_p (@var{c})
@code{char_p(c)} returns a true value if @var{c} is a character object.
@end defmac

@defmac float_p (@var{c})
@code{float_p(c)} returns a true value if @var{c} is a real number
object.
@end defmac

@defmac symbol_p (@var{c})
@code{symbol_p(c)} returns a true value if @var{c} is a symbol.
@end defmac

@defmac func_p (@var{c})
@code{func_p(c)} returns a true value if @var{c} is a primitive
procedure.
@end defmac

@defmac form_p (@var{c})
@code{form_p(c)} returns a true value if @var{c} is a syntactic form.
@end defmac

@defmac lambda_p (@var{c})
@code{lambda_p(c)} returns a true value if @var{c} is a lambda closure.
@end defmac

@defmac error_p (@var{c})
@code{error_p(c)} returns true if @var{c} is an error object.
@end defmac

@defmac except_p (@var{c})
@code{except_p(c)} returns true if @var{c} is an exception object.
@end defmac

@defmac long_p (@var{c})
@code{long_p(c)} returns true if @var{c} is a long integer object.
@end defmac

@defmac env_p (@var{c})
@code{env_p(c)} returns true if @var{c} is an environment.
@end defmac

@defmac location_p (@var{c})
@code{location_p(c)} returns true if @var{c} is a location object.
@end defmac

@defmac rolocation_p (@var{c})
@code{rolocation_p(c)} returns true if @var{c} is a constant location
object.
@end defmac

@defmac lloc_p (@var{c})
@code{lloc_p(c)} returns true if @var{c} is an lloc object.
@end defmac

@defmac gloc_p (@var{c})
@code{gloc_p(c)} returns true if @var{c} is a gloc object.
@end defmac

@defmac constant_p (@var{c})
@code{constant_p(c)} returns true if @var{c} is a constant value object.
@end defmac

@defmac keyword_p (@var{c})
@code{keyword_p(c)} returns true if @var{c} is a keyword.
@end defmac

@defmac vector_p (@var{c})
@code{vector_p(c)} returns a true value if @var{c} is a vector object.
@end defmac

@defmac rovector_p (@var{c})
@code{rovector_p(c)} returns a true value if @var{c} is a constant
vector object.
@end defmac

@defmac values_p (@var{c})
@code{values_p(c)} returns true if @var{c} is a multiple value object.
@end defmac

@defmac int_var_p (@var{c})
@defmacx ro_int_var_p (@var{c})
@code{int_var_p(c)} returns true if @var{c} is an integer variable
wrapper object, @code{ro_int_var_p(c)} returns true if @var{c} is a
read-only integer variable wrapper object.
@end defmac

@defmac bool_var_p (@var{c})
@defmacx ro_bool_var_p (@var{c})
@code{bool_var_p(c)} returns true if @var{c} is a boolean variable
wrapper object, @code{ro_bool_var_p(c)} returns true if @var{c} is a
read-only boolean variable wrapper object.
@end defmac

@defmac str_var_p (@var{c})
@defmacx ro_str_var_p (@var{c})
@code{str_var_p(c)} returns true if @var{c} is a string variable wrapper
object, @code{ro_str_var_p(c)} returns true if
@var{c} is a read-only string variable wrapper object.
@end defmac

@defmac regexp_p (@var{c})
@code{regexp_p(c)} returns true if @var{c} is a regular expression
object.
@end defmac

@defmac promise_p (@var{c})
@code{promise_p(c)} returns true if @var{c} is a promise object.
@end defmac

@defmac macro_p (@var{c})
@code{macro_p(c)} returns true if @var{c} is a macro code object.
@end defmac

@defmac syntax_p (@var{c})
@code{syntax_p(c)} returns true if @var{c} is a syntax object.
@end defmac

@defmac port_p (@var{c})
@code{port_p(c)} returns true if @var{c} is a port object.
@end defmac

@defmac fport_p (@var{c})
@code{fport_p(c)} returns true if @var{c} is a standard IO port object.
@end defmac

@defmac fdport_p (@var{c})
@code{fdport_p(c)} returns true if @var{c} is a file desccriptor port
object.
@end defmac

@defmac sport_p (@var{c})
@code{sport_p(c)} returns true if @var{c} is a string port object.
@end defmac

@defmac @var{TAG}vector_p (@var{c})
@code{@var{TAG}vector_p(c)} returns a true value if @var{c} is a
homogenous numeric vector object of the type indicated by @var{TAG}.

@var{TAG} in the predicate name may be replaced by @code{s8}, @code{u8},
@code{s16}, @code{u16}, @code{s32}, @code{u32}, @code{s64}, @code{u64},
@code{f32} or @code{f64}, depending on the needed datatype.  So there
are actually ten of these predicate macros.
@end defmac

@defmac ro_@var{TAG}vector_p (@var{c})
@code{ro_@var{TAG}vector_p(c)} returns a true value if @var{c} is a
homogenous numeric vector object of the type indicated by @var{TAG}.

@var{TAG} in the predicate name may be replaced by @code{s8}, @code{u8},
@code{s16}, @code{u16}, @code{s32}, @code{u32}, @code{s64}, @code{u64},
@code{f32} or @code{f64}, depending on the needed datatype.  So there
are actually ten of these predicate macros.
@end defmac


@node Accessor functions, Port Functions, Type predicates, Embedding API
@comment  node-name,  next,  previous,  up
@section Accessor functions

The macros and functions in this section are used to query the
properties of Scheme objects.  Before applying them to any object, you
have to check whether the object is of the correct type, because the
accessor macros and functions will not check for validity.

@defmac car (@var{c})
@defmacx cdr (@var{c})
Return the car or cdr of @var{c}, which must be a pair.
@end defmac

@defmac set_car (@var{c}, @var{value})
@defmacx set_cdr (@var{c}, @var{value})
Set the car or cdr of @var{c} to @var{value}.
@end defmac

@defmac car_addr (@var{c})
@defmacx cdr_addr (@var{c})
Return the address of the car or cdr of @var{c}.
@end defmac

@defmac tagged_type (@var{c})
Return the type of the tagged object @var{c}.
@end defmac

@defmac tagged_info (@var{c})
Return the tagged info field of the tagged object @var{c}.  The result
will be one of the @code{tagged_info_*} constants.
@end defmac

@defmac tagged_data0 (@var{c})
@defmacx tagged_data1 (@var{c})
@defmacx tagged_data2 (@var{c})
Returns the values of the data slots of the tagged object @var{c}.  The
results are of type @code{void *} and must be casted before being used.
@end defmac

@defmac immediate_val (@var{c})
Returns the value of the immediate form @var{c}.
@end defmac

@defmac fixnum_val (@var{c})
Returns the value of the fixnum @var{c}.
@end defmac

@defmac integer_val (@var{c})
Returns the integer value of @var{c}, which must be either a fixnum or a
long object.
@end defmac

@defmac string_val (@var{c})
Returns a pointer to the string contents of @var{c}.
@end defmac

@defmac string_len (@var{c})
Returns the length of the string @var{c}.
@end defmac

@defmac bool_val (@var{c})
Returns the value of the boolean object @var{c}.
@end defmac

@defmac char_val (@var{c})
Returns the value of the character object @var{c}.
@end defmac

@defmac float_val (@var{c})
Returns the value of the real number object @var{c}.
@end defmac

@defmac symbol_name (@var{c})
Returns the name of the symbol @var{c}.
@end defmac

@defmac symbol_value (@var{c})
Returns the global value of the symbol @var{c}.
@end defmac

@defmac symbol_name_addr (@var{c})
Returns the address of the name field of the symbol @var{c}.
@end defmac

@defmac symbol_value_addr (@var{c})
Returns the address of the value field of the symbol @var{c}.
@end defmac

@defmac set_symbol_name (@var{c}, @var{s})
Set the name of the symbol @var{c} to @var{s}.
@end defmac

@defmac set_symbol_value (@var{c}, @var{s})
Set the global value of the symbol @var{c} to @var{s}.
@end defmac

@defmac func_ptr (@var{c})
Returns the address of the C function which handles the primitive
procedure or syntactic form @var{c}.
@end defmac

@defmac func_name (@var{c})
Returns the name of the primitive procedure or syntactic form @var{c}.
@end defmac

@defmac func_form_p (@var{c})
Returns true if the primitive procedure or syntactic form @var{c} is
actually a syntactic form.
@end defmac

@defmac func_param (@var{c})
Returns the parameter specification of the primitive procedure or syntactic
form @var{c}.
@end defmac

@defmac lambda_name (@var{c})
Returns the name of the lambda expression @var{c}, or @code{NULL} if the
closure is anonymous.
@end defmac

@defmac lambda_args (@var{c})
Returns the formal argument list of the closure @var{c}.
@end defmac

@defmac lambda_body (@var{c})
Returns the closure body of @var{c}
@end defmac

@defmac lambda_env (@var{c})
Returns the environment the lambda expression @var{c} is closed over.
@end defmac

@defmac lambda_file (@var{c})
The file name in which the closure was defined, or NULL if not
available.
@end defmac

@defmac lambda_line (@var{c})
Returns the line number in the file where the closure was defined, or
NULL if not available.
@end defmac

@defmac long_val (@var{c})
Returns the value of the long integer object @var{c}.
@end defmac

@defmac env_val (@var{c})
Returns the environment vector of the environment @var{c}.
@end defmac

@defmac location_address (@var{c})
Returns the address the location object @var{c} refers to.
@end defmac

@defmac lloc_val (@var{c})
Returns the lloc list containing access data for memoized lloc objects.
@end defmac

@defmac gloc_name (@var{c})
Returns the name of the gloc @var{c}.
@end defmac

@defmac gloc_val (@var{c})
Returns the address the gloc @var{c} refers to.
@end defmac

@defmac constant_val (@var{c})
Returns the value of the constant value object @var{c}.
@end defmac

@defmac keyword_name (@var{c})
Returns the name of the keyword @var{c}.
@end defmac

@defmac vector_val (@var{c})
Returns a pointer to the array of vector elements of vector @var{c},
which are all of type @code{zzz_scm_t}.
@end defmac

@defmac vector_len (@var{c})
Returns the length of the vector @var{c}.
@end defmac

@defmac zzz_vector_put (@var{vector}, @var{index}, @var{value})
Store the object @var{value} at index @var{index} into @var{vector}.
Make sure that @var{index} is valid before calling this macro.
@end defmac

@defmac zzz_vector_get (@var{vector}, @var{index})
Fetch the object at index @var{index} from @var{vector}.
Make sure that @var{index} is valid before calling this macro.
@end defmac

@defmac values_val (@var{c})
Returns the value list of the muliple value object @var{c}.
@end defmac

@defmac int_var_addr (@var{c})
Returns the address of the integer variable the integer variable wrapper
@var{c} refers to.
@end defmac

@defmac bool_var_addr (@var{c})
Returns the address of the boolean variable the boolean variable wrapper
@var{c} refers to.
@end defmac

@defmac str_var_val (@var{c})
Returns the address of the string variable the string variable wrapper
@var{c} refers to.
@end defmac

@defmac str_var_len (@var{c})
Returns the length of the string variable the string variable wrapper
@var{c} refers to.
@end defmac

@defmac str_var_size (@var{c})
Returns the maximum size of the string variable the string variable
wrapper @var{c} refers to.
@end defmac

@defmac regexp_valid (@var{c})
Returns true if the regular expression object @var{c} was compiled
successfully.
@end defmac

@defmac regexp_string (@var{c})
Returns the string pattern which was compiled into the regular
expression object @var{c} as a Scheme string object.
@end defmac

@defmac regexp_regex (@var{c})
Returns the regular expression structure of type @code{regex_t}, into
which the regular expression was compiled.
@end defmac

@defmac promise_env (@var{c})
Returns the environment in which the promise @var{c} will be evaluated.
@end defmac

@defmac promise_result (@var{c})
Returns the result of the promise @var{c}.  Only a valid field if the
promise was already forced.
@end defmac

@defmac promise_expr (@var{c})
Returns the expression which was delayed in the promise @var{c}.
@end defmac

@defmac promise_thawed (@var{c})
Returns a true value if the promise @var{c} was already forced, false
otherwise.
@end defmac

@defmac macro_code (@var{c})
Returns the macro code of the macro object @var{c}.
@end defmac

@defmac syntax_rules (@var{c})
Returns the syntax rules of the syntax object @var{c}.
@end defmac

@defmac port_ptype (@var{c})
Returns the port type of the port object @var{c}.
@end defmac

@defmac port_open_p (@var{c})
Returns true if the port object @var{c} is open.
@end defmac

@defmac port_write_p (@var{c})
Returns true if the port object @var{c} is for output.
@end defmac

@defmac port_read_p (@var{c})
Returns true if the port object @var{c} is for input.
@end defmac

@defmac port_line_number (@var{c})
Returns the current line number of the port object @var{c}.
@end defmac

@defmac port_col_number (@var{c})
Returns the current column number of the port object @var{c}.
@end defmac

@defmac port_saved_col (@var{c})
Returns the last column number of the port object @var{c}.  This is
remembered to restore column numbers after a @code{port_ungetc()}
operation.
@end defmac

@defmac fport_file (@var{c})
Returns the file pointer of the standard IO file port @var{c}.
@end defmac

@defmac fdport_fd (@var{c})
Returns the file descriptor of the file descriptor port @var{c}.
@end defmac

@defmac fdport_has_unget (@var{c})
Returns true if the file descriptor port @var{c} has pushed back data.
@end defmac

@defmac fdport_unget (@var{c})
Returns the pushed back character of the file descriptor port @var{c}.
@end defmac

@defmac sport_val (@var{c})
Returns a pointer to the character buffer of the string port @var{c}.
@end defmac

@defmac sport_len (@var{c})
Returns the current length of valid data in the character buffer of the
string port @var{c}.
@end defmac

@defmac sport_size (@var{c})
Returns the allocated size of the character buffer of the string port
@var{c}.
@end defmac

@defmac sport_pos (@var{c})
Returns the current file pointer of the string port @var{c}.
@end defmac

@defmac @var{TAG}vector_val (@var{c})
Returns a pointer to the array of vector elements of the homogenous
numeric vector @var{c}, which are all of the type indicated by
@var{TAG}.

@var{TAG} in the constructor name may be replaced by @code{s8},
@code{u8}, @code{s16}, @code{u16}, @code{s32}, @code{u32}, @code{s64},
@code{u64}, @code{f32} or @code{f64}, depending on the needed datatype.
So there are actually ten of these accessor macros.
@end defmac

@defmac @var{TAG}vector_len (@var{c})
Returns the length of the homogenous numeric vector @var{c}.

@var{TAG} in the constructor name may be replaced by @code{s8},
@code{u8}, @code{s16}, @code{u16}, @code{s32}, @code{u32}, @code{s64},
@code{u64}, @code{f32} or @code{f64}, depending on the needed datatype.
So there are actually ten of these accessor macros.
@end defmac



@node Port Functions, Defining Scheme Types, Accessor functions, Embedding API
@comment  node-name,  next,  previous,  up
@section Port Functions

@deftypefun unsigned zzz_define_port_type (port_getc_t @var{port_getc}, port_ungetc_t @var{port_ungetc}, port_putc_t @var{port_putc}, port_puts_t @var{port_puts}, port_flush_t @var{port_flush}, port_close_t @var{port_close}, port_seek_t @var{port_seek}, port_tell_t @var{port_tell}, port_char_ready_p_t @var{port_char_ready_p}, port_free_t @var{port_free}, port_mark_t @var{port_mark})
Define a new port type.  Must be given functions for all supported port
operations.
@end deftypefun

@deftypefun result_t zzz_port_puts (zzz_scm_t @var{port}, char * @var{buf}, int @var{len}, zzz_scm_t * @var{result});
Put the string @var{buf} of length @var{len} onto the port @var{port}.
Returns @code{RESULT_SUCCESS} on success or an error code and an error
object in the location pointed to by @var{result} if an error occurs.
@end deftypefun

@deftypefun result_t zzz_port_putc (int @var{ch}, zzz_scm_t @var{port}, zzz_scm_t * @var{result})
Put the character @var{ch} to port @var{port}.  Returns
@code{RESULT_SUCCESS} on success or an error code and an error object in
the location pointed to by @var{result} if an error occurs.
@end deftypefun

@deftypefun result_t zzz_port_print (zzz_scm_t @var{port}, zzz_scm_t @var{cell}, zzz_print_state_t @var{state}, zzz_scm_t * @var{result})
Print the Scheme object @var{cell} to the port @var{port}.  Formatting
is specified via the passed @var{state} structure.  Returns
@code{RESULT_SUCCESS} on success or an error code and an error object in
the location pointed to by @var{result} if an error occurs.
@end deftypefun

@deftypefun result_t zzz_port_getc (zzz_scm_t @var{port}, int * @var{ch}, zzz_scm_t * @var{result})
Read a character from the port @var{port} and return it in the location
pointed to by @var{ch}.  Returns @code{RESULT_SUCCESS} on success or an
error code and an error object in the location pointed to by
@var{result} if an error occurs.
@end deftypefun

@deftypefun result_t zzz_port_ungetc (int @var{ch}, zzz_scm_t @var{port}, zzz_scm_t * @var{result})
Return the character @var{ch} back to the stream of characters from port
@var{port}.  Returns @code{RESULT_SUCCESS} on success or an error code
and an error object in the location pointed to by @var{result} if an
error occurs.
@end deftypefun

@deftypefun result_t zzz_port_close (zzz_scm_t @var{port}, zzz_scm_t * @var{result})
Close the port @var{port}.  After using this function, no more data can
be written to or read from @var{port}.  Returns @code{RESULT_SUCCESS} on
success or an error code and an error object in the location pointed to
by @var{result} if an error occurs.
@end deftypefun

@deftypefun result_t zzz_port_seek (zzz_scm_t @var{port}, long @var{ofs}, int @var{whence}, long * @var{res_ofs}, zzz_scm_t * @var{result})
Move the file pointer of port @var{port} to position @var{ofs}.
Interpretation of @var{ofs} depends on the parameter @var{whence}, which
is the same as in th C library function @code{fseek()}.  The new offset
after repositioning is returned in the location pointed to by
@var{res_ofs}.  Returns @code{RESULT_SUCCESS} on success or an error
code and an error object in the location pointed to by @var{result} if
an error occurs.
@end deftypefun

@deftypefun result_t zzz_port_tell (zzz_scm_t @var{port}, long * @var{res_ofs}, zzz_scm_t * @var{result})
Return the position of @var{port}'s file pointer in the location pointed
to by @var{res_ofs}.  Returns @code{RESULT_SUCCESS} on success or an
error code and an error object in the location pointed to by
@var{result} if an error occurs.
@end deftypefun

@deftypefun result_t zzz_port_flush (zzz_scm_t @var{port}, zzz_scm_t * @var{result});
Flushes all pending output of the port @var{port} which has not yet been
written to the underlying file.  Returns @code{RESULT_SUCCESS} on
success or an error code and an error object in the location pointed to
by @var{result} if an error occurs.
@end deftypefun

@deftypefun result_t zzz_port_char_ready_p (zzz_scm_t @var{port}, int * @var{ready}, zzz_scm_t * @var{result});
Checks whether data is available for reading on the input port
@var{port}.  A flag indicating the availability of data is returned in
the location pointed to by @var{ready}.  Returns @code{RESULT_SUCCESS}
on success or an error code and an error object in the location pointed
to by @var{result} if an error occurs.
@end deftypefun



@node Defining Scheme Types, Misc C API Functions, Port Functions, Embedding API
@comment  node-name,  next,  previous,  up
@section Defining Scheme Types

@deftypefun {unsigned long} zzz_define_tagged_type (void * (* @var{constructor_func}) (zzz_tagged_t tagged, const void * data0, const void * data1, const void * data2), void (* @var{print_func})(zzz_scm_t port, zzz_tagged_t tagged, zzz_print_state_t state), void (* @var{free_func}) (zzz_tagged_t tagged), void (* @var{mark_func}) (zzz_tagged_t tagged), int (* @var{equal_func}) (zzz_tagged_t tagged0, zzz_tagged_t tagged1))
This function defines a new Scheme type.  The functions
@var{constructor_func}, @var{print_func}, @var{free_func},
@var{mark_func} and @var{equal_func} are stored internally and are used
for all objects of the new type.  @code{zzz_define_tagged_type()}
returns a type tag for the new type.
@end deftypefun

The following two functions can be given as arguments to
@code{zzz_define_tagged_type()}, if the data fields of the tagged type
contain variables of type @code{zzz_scm_t}.

@deftypefun {void *} zzz_simple_constructor (zzz_tagged_t @var{tagged}, const void * @var{data0}, const void * @var{data1}, const void * @var{data2})
Constructor for simple types which store complete value state in the
data fields of the tagged cell.  Returns its argument @var{tagged}.
@end deftypefun

@deftypefun void zzz_simple_mark (zzz_tagged_t @var{tagged});
Mark function for types which hold zzz_scm_t values in their data slots
which should be protected from being GC'ed.
@end deftypefun

@deftypefun void zzz_mark_cell (zzz_scm_t @var{cell});
Use this functions from the marking function of your tagged type if you
have to mark a variable of type @code{zzz_scm_t}.
@end deftypefun



@node Misc C API Functions,  , Defining Scheme Types, Embedding API
@comment  node-name,  next,  previous,  up
@section Misc C API Functions

The following functions do not seem to fit into any of the previous
sections, but they may come in handy from time to time.

@deftypefun void zzz_garbage_collect (void)
Force immediate garbage collection.
@end deftypefun

@defmac zzz_eq (@var{first}, @var{second})
Returns 1 if @var{first} and @var{second} are equal in the sense of
@code{eq?}.  Returns 0 otherwise.

This macro can be undefined in the file @file{node.h}, which will cause
a function with the same functionality, but more error checking, to be
compiled in.
@end defmac

@deftypefun int zzz_eqv (zzz_scm_t @var{first}, zzz_scm_t @var{second})
Returns 1 if @var{first} and @var{second} are equal in the sense of
@code{eqv?}.  Returns 0 otherwise.
@end deftypefun

@deftypefun int zzz_equal (zzz_scm_t @var{first}, zzz_scm_t @var{second})
Returns 1 if @var{first} and @var{second} are equal in the sense of
@code{equal?}.  Returns 0 otherwise.
@end deftypefun

@deftypefun int zzz_list_length (zzz_scm_t @var{list});
Returns the length of list @var{list}.  Returns -1 if @var{list} is not
a proper list and returns -2 if @var{list} contains circular references.
A proper list is a list terminated by the empty list @code{'()} and a
circular list is a list which points to one of its own elements
somewhere.
@end deftypefun



@node Memory Management, Creating Data Types, Embedding API, Top
@comment  node-name,  next,  previous,  up
@chapter Memory Management

In this section, we will see how Sizzle represents Scheme objects
internally and how the memory needed for storing these objects is
managed.

@menu
* Cell Representation::         How data cells are represented in core
* Garbage Collection::          How storage is reclaimed
@end menu

@node Cell Representation, Garbage Collection, Memory Management, Memory Management
@comment  node-name,  next,  previous,  up
@section Cell Representation

The Sizzle interpreter makes a difference between four types of Scheme
objects: immediate values, fixnums, cons cells and tagged cells.  These
types are stored in memory differently, and we will look at the
representation of them in detail in the following section.

Most functions use the opaque data type @code{zzz_scm_t}, which is
defined as a pointer to @code{struct cell}.  A value of type
@code{zzz_scm_t} can represent four different kinds of data.  They are
differentiated by their two least significant bits.  

If these bits are zero, it is a pointer to a cons cell which in turn
holds two values of type @code{zzz_scm_t}.  Cons cells are used to build
the normal Scheme lists from.  Environments, procedures, hash tables
etc. are all build using lists, so objects of this type are quite
common.

Should the two least significant bits be 1, it represents an 29-bit,
two-complement integer value, a so-called fixnum; in order to get the
real value, the value must be right-shifted by three bits.

The third kind, encoded by a 2 in the two least significant bits is a
so-called tagged cell where the first word of the object pointed to is
the a combination of the @dfn{tagged data type} (a 16 bit unsigned int)
and additional 13 information bits.  The usage of the info bits depends
on the particular object type.  Function objects, for example, encode
the expected parameter formet in these bits; and read-only strings and
vectors have a bit set in the info field.  The next three words of the
tagged cell object (as you can calculate, a tagged object is at least 4
words long) are data words and the values stored there depend on the
data type.  Some types store a pointer to additional storage there,
others use the three words to hold values larger than one word (floating
point values, for example, store their 2-word value in the last two
words of the object).

A value of 3 in the two least significant bits of the @dfn{car} of a
cell means that the cell represents a so-called immediate value.
Immediate values do not point to any heap-allocated object, but stand
for themselves.  The immediate forms, into which most syntactic forms
are transformed on evaluation, are examples of this type of object.

Bit two is used to implement a marking garbage collector.  Cells
which have been seen during the scan phase of collection have this
bit set in the @dfn{car}.

Cons cells and tagged cells are allocated on two different heaps,
because they have a different size.

@subsubheading Pointer Layout

General layout of a variable of type @code{zzz_scm_t}:

@smallexample
@group
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|               |               |               |         | | | |
+---------------+---------------+---------------+---------+-+-+-+
                                                           | | |
                                 garbage collection mark --+ | |
                                                             | |
                                               node type ----+-+
                                               0 = cons cell,
                                                   '(),
                                                   immediate code
                                               1 = integer (shifted)
                                               2 = tagged cell
                                               3 = immediate value
@end group
@end smallexample

Cons cell pointers have zeros in their least significant bits.  They can
be used as pointers to structures of type @code{struct cell} without
further modification.  Note: when dealing with values of this type while
garbage collection is running is dangerous, because you have to mask out
bit #2 before dereferencing the pointer.

@smallexample
@group
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|0|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _________________________^___/
                                \/                         |
             32-bit pointer to value of type `struct cell' |
                                   Might be set during gc -+
@end group
@end smallexample

The null pointer (which is the representation of the empty list) is a
word of only zero bits.  Only during garbage collection the third bit
may be set and must be masked off.

@smallexample
@group
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0|x|0|0|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _________________________^___/
                                \/                         |
             32-bit pointer to value of type `struct cell' |
                                   Might be set during gc -+
@end group
@end smallexample

Integer values, aka fixnums, have the following layout.  The value of any
fixnum value can be obtained by arithmetically right-shifting the value
by three bits.

@smallexample
@group
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|1|
+---------------+---------------+---------------+---------+-+-+-+
 \___________________________  __________________________/ ^
                             \/                            |
                 Two-complement 29-bit-value               |
                                   Might be set during gc -+
@end group
@end smallexample
 
Tagged cells hold the value 2 in their two least significant bits and a
pointer to a tagged cell structure can be obtained by masking the lower
4 bits off.

@smallexample
@group
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x 0|x|1|0|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _______________________^_^___/
                                \/                       | |
             32-bit pointer to tagged object             | |
                                                         | |
    Zero, because tagged objects are aligned to 16 bytes + |
                                                           |
                                   Might be set during gc -+
@end group
@end smallexample

Immediate codes have their least significant two bits set and their
value encoded in the upper 29 bits.

@smallexample
@group
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|1|1|
+---------------+---------------+---------------+---------+-+-+-+
 \___________________________  __________________________/ ^
                             \/                            |
          any value, depending of the immediate value      |
                                   Might be set during gc -+
@end group
@end smallexample

@subsubheading Heap Cell Layout

When looking at any cell on one of the heaps, the values defined in the
following paragraphs are valid.

On the cons heap, any cell can be either free or in use.

Free cells carry a pointer to the next entry in the free list
in the cdr and the value `2' in the car.

@smallexample
@group
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0|0|1|0|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _____________________________/
                                \/
                     Pointer to next free cell
@end group
@end smallexample
 
Used cons cells can be in one of the following four states.

The car of a cons cell either contains a cons cell pointer (or NULL), a
tagged cell pointer, a fixnum or an immediate value.  During garbage
collection, bit #2 of the car may be set.

@smallexample
@group
                       Pointer to cons cell
  ______________________________/\____________________________
 /                                                            \
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|0|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|0|x|x|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _____________________________/
                                \/
                Any possible value of type zzz_scm_t

@end group
@end smallexample
 
@smallexample
@group
                      Pointer to tagged cell
  ______________________________/\____________________________
 /                                                            \
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|1|0|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|0|x|x|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _____________________________/
                                \/
               Any possible value of type zzz_scm_t

@end group
@end smallexample
 
@smallexample
@group
                          Integer value
  _____________________________/\_______________________
 /                                                      \
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|1|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|0|x|x|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _____________________________/
                                \/
                Any possible value of type zzz_scm_t

@end group
@end smallexample
 
@smallexample
@group
                         Immediate value
  _____________________________/\_______________________
 /                                                      \
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|1|1|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|0|x|x|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _____________________________/
                                \/
                Any possible value of type zzz_scm_t
@end group
@end smallexample

The first word of a tagged cell always containes a type tag (and maybe
information in the upper bits); the tag 0 stands for an unused cell.
The following three words may hold any value, they are not interpreted
by the memory manager.

Free tagged cell:

@smallexample
@group
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0|0|1|0|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
.\______________________________  _____________________________/.
.                               \/                              .
.                    Pointer to next free cell                  .
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _____________________________/
                                \/
                              Garbage
@end group
@end smallexample
 
A use tagged cell looks like this.  Note that the third bit of the first
word may be set during garbage collection, just like for cons cells.

@smallexample
@group
      Type information                Type tag
  ___________/\__________   _____________/\_____________
 /                       \ /                            \
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|0|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
+---------------+---------------+---------------+---------+-+-+-+
|x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
+---------------+---------------+---------------+---------+-+-+-+
 \______________________________  _____________________________/
                                \/
              Pointer(s) to cell data / immediate data
@end group
@end smallexample


@node Garbage Collection,  , Cell Representation, Memory Management
@comment  node-name,  next,  previous,  up
@section Garbage Collection

In order to free the programmer from the burden of memory management,
the Scheme runtime environment must reclaim storage when it is no longer
accessible by the running program.  This process is called @dfn{Garbage
Collection}, or GC for short.

Memory allocation in Sizzle works as follows: functions creating data
objects call either the function @code{zzz_alloc_tagged_cell()} or
@code{zzz_cons()} (which in turn calls @code{zzz_alloc_cons_cell()}).
After a certain number of calls to one of these functions, the garbage
collection is invoked.  When not enough free memory is reserved for
fulfilling the allocation request, more memory is requested from the
operating system and the space needed is reserved.  Note that Sizzle
does not invoke the garbage collector when the freelists are empty,
because it tries to avoid garbage collection when memory is nearly full.

The garbage collector uses a simple mark--and--sweep algorithm.  That
means, that garbage collection starts by marking all directly and
indirectly reachable objects as referenced.  In the second step, all
objects which are not marked are returned to the freelists of their
respective types.

For marking all referenced objects it is necessary to find the @dfn{root
pointers} through which all used objects can be reached.  Sizzle
performs @dfn{conservative marking}, that is, it marks all data objects
which are pointed to by values on the stack of the C program it runs in
and by marking all objects in locations which have been explicitly made
known to the interpreter.  This mechanism requires that the interpreter
knows how to find the beginning and the end of the stack.

Two methods are provided to make these addresses available: The first is
to make the embedding application calling a library function which calls
back to the procedure doing the applications work.  With this method,
the library can calculate the end of the stack automatically, but it
takes over the main control function of the program.  The Sizzle command
line interpreter uses this method.

The other method is to make the client code call explicitly a library
function and tell it where the end of the stack is by passing the
address of a local variable.  The tutorial in this manual is an example
for this procedure (@pxref{Parsing initialization files}).


@subsubheading Object Marking 

The marking phase is performed by traversing all objects pointed by the
root pointers.  Immediate objects do not need to get marked, because
they do not use heap memory at all.  What happens to other objects,
depends on their type.  Cons cells are directly known to the mark
function, and the funtion tries to reduce the needed stack space by
avoiding deep recursion.  Therefore, the spine of lists is marked in a
loop, marking recursively only the list elements.  Because lists in
Scheme are normally long and shallow, this speeds up marking a lot.

Tagged objects are marked by calling the mark function for the type of
the object.  The mark function is responsible for calling the mark
function recursively for all Scheme objects referenced by the object.


@node Creating Data Types, Creating Port Types, Memory Management, Top
@comment  node-name,  next,  previous,  up
@chapter Creating Data Types

Sizzle has been designed in a way that it is easy to add additional data
types.  For now, this section only crudely documents the method for
defining data types, so for details, please refer to the source code to
find out how to do it.  Start by reading the files @file{node.h} and
@file{node.c} where all builtin data types are defined.

The internal representation of all data is documented in @ref{Cell
Representation}.

The API functions for handling tagged types are documented briefly in
@ref{Defining Scheme Types}.

New data types in Sizzle are introduced by defining so-called
@dfn{tagged types}.  Objects of tagged types occupy at least one tagged
cell on the heap, but they may allocate additional memory and store
pointers to those allocated areas into the heap cells.  For every tagged
type, a bunch of function must be defined which tell the memory manager
to handle objects of these types without actually knowing the memory
layout of the types.

@menu
* Type Functions::              How to define type functions
* Defining Tagged Types::       Register the new type with Sizzle
@end menu

@node Type Functions, Defining Tagged Types, Creating Data Types, Creating Data Types
@comment  node-name,  next,  previous,  up
@section Type Functions

This section documents what type functions are, and how to write them.
First, I will summarize what functions are required, then I will
describe each function type in detail, giving examples as I go.

The following type functions are defined:
@table @asis
@item Constructor function
This function gets called when an object is created.  May allocate
memory which may be needed to store an object, and must initialize the
object from data passed to the constructor.
@item Print function
This gets called by primitives like @code{display} or @code{write}, and
is responsible for printing a textual representation of the object to a
port.
@item Free function
Destructor function, which must free all memory which has been allocated
by the constructor.
@item Mark function
Called by the garbage collector during the mark phase for traversing all
reachable objects.
@item Equal function
Equality predicate called by @code{equal?} to determine whether two
objects of the same type have the same structure.
@end table


@menu
* Constructor Function::        Function for initializing objects
* Print Function::              Function for printing objects
* Free Function::               Function for freeing object memory
* Equal Function::              Testing for object equality
* Mark Function::               Marking reachable objects
@end menu

@node Constructor Function, Print Function, Type Functions, Type Functions
@comment  node-name,  next,  previous,  up
@subsection Constructor Function

The constructor function is responsible for initializing a tagged
object.  When it is called, a tagged cell is already allocated on the
heap and has been initialized with the tagged type tag for the object.
The constructor has three formal arguments: The address of the allocated
cell, and three void pointer, which are used to pass arguments to the
constructor function.  The actual type and value of these arguments
depend on the object type the cosntructor function was defined for.

The prototype for constructor functions looks like this:
@example
typedef void * (* constructor_func_t) (zzz_tagged_t tagged, void * data0,
                                       void * data1, void * data2);
@end example

Often, types only need to store their three pointer arguments in the
three data slots of a tagged cell.  These types can use the library
function @code{zzz_simple_constructor()}, which does this cell
initialization.  User types are free to use this pre-defined constructor
functions for their types, if its specification suits their needs.

The constructor function for the string datatype is given below, to
serve as a non-trivial example.
@example
@group
static void *
string_constructor (zzz_tagged_t tagged, void * data0,
                    void * data1, void * data2)
@{
  char * p = (char *) data0;
  int len =  (int) ((long) data1);
  void * ret;

  ret = zzz_malloc (len + 1);   /* +1 for terminating '\0'.  */
  if (p)
    memmove ((char *) ret, p, len);
  ((char *) ret)[len] = '\0';
  tagged->fill[1] = (unsigned long) ret;
  tagged->fill[2] = (unsigned long) len;
  return tagged;
@}
@end group
@end example


@node Print Function, Free Function, Constructor Function, Type Functions
@comment  node-name,  next,  previous,  up
@subsection Print Function


Print functions must print a textual representation of an object to a
Scheme port.  They must match the following protoype:

@example
typedef void (* print_func_t) (zzz_scm_t port, zzz_tagged_t tagged,
                               zzz_print_state_t state);
@end example

The argument @var{port} specifies the Scheme port to print to,
@var{tagged} is the object, and @var{state} specifies the current state
for printing.  @code{zzz_print_state_t} is defined as a pointer to the
following structure, which currently includes only one field.  This
field is a bitset for which the @code{PRINT_*} macros have been defined.
@example
@group
struct zzz_print_state
@{
  int flags;
@};

#define PRINT_NEWLINE 0x01
#define PRINT_QUOTE   0x02
#define PRINT_ESCAPE  0x04
@end group
@end example

@code{PRINT_NEWLINE} is currently unused.  @code{PRINT_QUOTE} means,
that the print function should do all necessary quoting for making the
textual representation suitable for reading the object back in using
@code{read}.  @code{PRINT_ESCAPE} means that special characters must be
escaped in a way compatible with @code{read}.  @code{write} for example,
calls the print functions with both @code{PRINT_QUOTE} and
@code{PRINT_ESCAPE} set, @code{display} calls the function without
these flags.

The print function for strings is rather complicated, but because it
interprets the print flags, it makes a good example.
@example
@group
static void
string_print (zzz_scm_t port, zzz_tagged_t tagged, zzz_print_state_t state)
@{
  zzz_scm_t result;
  char * p = tagged_data0 (tagged);
  int len = (long) tagged_data1 (tagged);

  assert (len >= 0);
  if (!(state->flags & (PRINT_ESCAPE | PRINT_QUOTE)))
    zzz_port_puts (port, p, len, &result); /* Fast path for `display'.  */
  else
    @{
      if (state->flags & PRINT_QUOTE)
        zzz_port_putc ('"', port, &result);
      while (len-- > 0)
        @{
          if ((state->flags & PRINT_ESCAPE) && (*p == '\\' || *p == '"'))
            zzz_port_putc ('\\', port, &result);
          zzz_port_putc (*p, port, &result);
          p++;
        @}
      if (state->flags & PRINT_QUOTE)
        zzz_port_putc ('"', port, &result);
    @}
@}
@end group
@end example

@node Free Function, Equal Function, Print Function, Type Functions
@comment  node-name,  next,  previous,  up
@subsection Free Function

The free function must free all memory which might have been allocated
in the constructor.  As an example, here is the string type free
function.
@example
@group
static void
string_free (zzz_tagged_t tagged)
@{
  int len =  (long) tagged_data1 (tagged);
  zzz_free (tagged_data0 (tagged), len + 1); /* + 1 for terminating '\0' */
@}
@end group
@end example


@node Equal Function, Mark Function, Free Function, Type Functions
@comment  node-name,  next,  previous,  up
@subsection Equal Function

The equal function must determine whether two objects of the same type
have the same structure in the sense of @code{equal?}.  For strings,
that means that the strings must be tested whether they have the same
length and the same character contents.
@example
@group
static int
string_equal (zzz_tagged_t tagged0, zzz_tagged_t tagged1)
@{
  char * p1 = tagged_data0 (tagged0);
  char * p2 = tagged_data0 (tagged1);
  int len1 = (long) tagged_data1 (tagged0);
  int len2 = (long) tagged_data1 (tagged1);

  if (len1 != len2)
    return 0;
  if (len1 == 0)
    return 1;
  len1 = memcmp (p1, p2, len1);
  if (len1)
    return 0;
  else
    return 1;
@}
@end group
@end example


@node Mark Function,  , Equal Function, Type Functions
@comment  node-name,  next,  previous,  up
@subsection Mark Function

The mark function for strings is empty, because no other Scheme objects
are referenced.  It would be possible to pass a null pointer to the type
definition function also, if no mark function is required.
@example
@group
static void
string_mark (zzz_tagged_t tagged)
@{
@}
@end group
@end example

Here is a second example, the mark function for vector objects.  It
calls the library mark function for every vector element.

@example
@group
static int
vector_equal (zzz_tagged_t tagged0, zzz_tagged_t tagged1)
@{
  zzz_scm_t * vec1   = vector_val (tagged0);
  unsigned long len1 = vector_len (tagged0);
  zzz_scm_t * vec2   = vector_val (tagged1);
  unsigned long len2 = vector_len (tagged1);
  unsigned long x;

  if (len1 != len2)
    return 0;
  for (x = 0; x < len1; x++)
    @{
      if (!zzz_equal (vec1[x], vec2[x]))
        return 0;
    @}
  return 1;
@}
@end group
@end example

Like for the constructor function, a library function exists to be used
as a mark function when your tagged type has a certain structure.
Whenever a tagged type is to be created which should hold Scheme values
in the data slots of the tagged cells, you can use the function
@code{zzz_simple_mark()}.  This function simply calls the system's mark
function for all three data slots.


@node Defining Tagged Types,  , Type Functions, Creating Data Types
@comment  node-name,  next,  previous,  up
@section Defining Tagged Types

After writing the type functions, you have to register the new type with
the library.  This is done by calling the type definition function
@code{zzz_define_tagged_type()}, which has this protoype:

@example
@group
unsigned long zzz_define_tagged_type 
          (constructor_func_t constructor_func,
           print_func_t print_func,
           free_func_t free_func,
           mark_func_t mark_func,
           equal_func_t equal_func);
@end group
@end example

The return value of this function is the type tagged, which can then be
used to create objects of the given type.  It is used in calls to the
tagged typ creation function @code{zzz_create_tagged_type()}.  It is
called with the type tag obtained by the call to the register function
and three opaque pointers, which will be passed to the type's
constructor function.

@example
@group
zzz_scm_t zzz_create_tagged_cell (unsigned long tag, void * data0,
                                  void * data1, void * data2);
@end group
@end example


@node Creating Port Types, Adding Primitives, Creating Data Types, Top
@comment  node-name,  next,  previous,  up
@chapter Creating Port Types

New port types can be created on the C as well as on the Scheme level.
For now, refer to the files @file{sport.c} and @file{sport.h}, which
define string ports and which will be instructive if you want to build
your own port types in C.  The other port types are implemented in the
files @file{fport.[ch]}, @file{fdport.[ch]} and @file{scmport.[ch]}.

On the Scheme level, the procedure @code{make-soft-port} can be used to
create ports which handle in- and output in a special way.  Refer to the
Reference Manual for more information.  Scheme ports are implemented in
the files @file{scmport.c} and @file{scmport.h}.



@node Adding Primitives, sizzle-gen-if, Creating Port Types, Top
@comment  node-name,  next,  previous,  up
@chapter Adding Primitives

It is easy to add primitive procedures to the interpreter.  The process
involves two steps.  You have to write a C function which handles the
primitive procedure calls and you must tell the interpreter under which
name your function wants to be called.

@menu
* The C Function::                   How to write a primitive in C
* Adding the Function to the Core::  How to register the primitive
@end menu

@node The C Function, Adding the Function to the Core, Adding Primitives, Adding Primitives
@comment  node-name,  next,  previous,  up
@section The C Function

This is a small example for writing a C primitive.  The code is actually
taken from the code of the Sizzle library, it implements the primitive
function @code{eval}.

@smallexample
/*:doc
  eval
  (eval expr [environment]) => value(s)
  Evaluate the expression @var{expr} in the environment specified by
  @var{environment} and return the resulting value(s).  @var{environment}
  defaults to the current top-level environment.
  doc:*/
#define FUNC_NAME "eval"
static result_t
eval_func (zzz_scm_t env, zzz_scm_t form, zzz_scm_t new_env,
           zzz_scm_t * result)
@{
  static char * s_func_name = FUNC_NAME;
  zzz_scm_t res;

  if (zzz_eq (new_env, zzz_undefined))
    new_env = zzz_current_environment;
  else
    CHECK_TYPE (2, env_p (new_env), zzz_environment_type_name);
  return zzz_evaluate (new_env, form, result);
@}
#undef FUNC_NAME
@end smallexample

The first thing to notice is the definition of the CPP macro
@code{FUNC_NAME}.  This macro must always be defined to be the name of
the Scheme primitive this function stands for, because it is used in
error messages produced by several support macros.  @code{s_func_name}
must be declared always for the same reason, and in exactly the same
way.

@code{eval} takes an optional second parameter.  Therefore, the code
must check whether any value was given for that parameter, if not the
value of the parameter will be @code{zzz_undefined}.  Depending on this
check, @code{eval} either provides a default value or checks the given
value's type.  The macro @code{CHECK_TYPE} will produce an error message
and return from the function if it is not.  The first argument to
@code{CHECK_TYPE} is the parameter number to include in error messages,
the second is an expression which must evaluate to true in order to
proceed, and the last parameter is a string telling which parameter type
was expected.  When the test for the second argument fails,
@code{CHECK_TYPE} will generate an appropriate error message including
the error message from the last parameter and return immediately from
the current function.

When the parameters have been verified, the function
@code{zzz_evaluate()} is called to evaluate the first parameter.  The
return value if that call is simply returned, an the result pointer is
passed to the evaluation function, which will store the result value in
the given location.


@node Adding the Function to the Core,  , The C Function, Adding Primitives
@comment  node-name,  next,  previous,  up
@section Adding the Function to the Core

After writing the C function for a primitive, we have to announce to the
library what we have laborously achieved.  This is done using the API
function @code{zzz_define_function()}, like in the following example.

@smallexample
zzz_define_function ("eval", eval_func, argv_1_1_0);
@end smallexample

Here, @code{"eval"} is the name of the Schme primitive we want to bind
the function to, @var{eval_func} is the C function we have defined in
the previous section and @code{argv_1_1_0} is a descriptor of the
argument format our function expects.  There are several of those
@code{argv_*_*_*} macros defined in @file{node.h}.  The first number
stands for the number of fixed arguments the procedure expects, the
second number for the number of optional arguments and the last number
is 1 if a rest parameter will be accepted, to which a list of all
remaining arguments will be bound; and 0 if no rest argument is
acceptable.

@node sizzle-gen-if, Index, Adding Primitives, Top
@comment  node-name,  next,  previous,  up
@chapter sizzle-gen-if

Included in the Sizzle distribution is the script @file{sizzle-gen-if}.
This script can be used to automatically generate glue code for C
functions from an interface specification.  It is possible (in some
simple cases) to generate a primitive function for wrapping a C library
function without writing a single line of code.  An example for this is
the procedure @code{fnmatch}, which was included into the Sizzle core by
specifying its interface, and the rest (primitive procedure code,
parameter checking, parameter unboxing, return value boxing, primitive
definition, constant definition) was handled by @file{sizzle-gen-if}.

This section documents the use of the script.  For further information,
you can of course always refer to the source code and the file
@file{fnmatch.if} in the directory @file{libsizzle} of the distribution,
which demonstrates the use.


@menu
* sizzle-gen-if invocation::    How sizzle-gen-if must be called
* The Generation Process::      What does sizzle-gen-if?
* The Specification File::      How to specify interfaces
* A Simple Example strlen::     Example interface and output
* Manual Glue Code::            Write the glue code by hand
* Pointer arguments::           How sizzle-gen-if can handle pointers
@end menu

@node sizzle-gen-if invocation, The Generation Process, sizzle-gen-if, sizzle-gen-if
@comment  node-name,  next,  previous,  up
@section sizzle-gen-if invocation

@file{sizzle-gen-if} is used as follows.
@example
$ sizzle-gen-if infile outfile
@end example

The script must be invoked with the input file as the first and the
primary output file as the second argument.  It will copy the input file
to the output file and replace interface specification marked with a
@code{$} character with the corresponfing generated glue code.
Additionally, a @dfn{init file} will be created, with the name of the
output file with and @file{.x} appended.  This file will contain the
necessary initialization code for registering primitives, creating
constants and symbols and protecting global variables from garbage
collection.  The output file can then be @code{#include}'d into any C
source file, and the init file should be @code{#include}'d into the init
function of that source file, so that initialization can take place for
the generated wrapper code.

Suppose you have an interface specification file called
@file{fnmatch.if}, which specifies how the C function @code{fnmatch}
must be called, and which possibly defines some constants or symbols.
To generate the glue code and the initialization statements, you have to
call @file{sizzle-gen-if} with the name of the file and the name the output
file should have.
@example
mgrabmue@@tortoise (~/cvs/sizzle/scripts): sizzle-gen-if fnmatch.if fnmatch.c
mgrabmue@@tortoise (~/cvs/sizzle/scripts):
@end example
When no errors are found, @file{sizzle-gen-if} does not print any messages.
You can have a look at the current directory to see which files have
been created.
@example
mgrabmue@@tortoise (~/cvs/sizzle/scripts): ls -l fnmatch.*
-rw-r--r--   1 mgrabmue mgrabmue     3263 Aug 22 15:26 fnmatch.c
-rw-r--r--   1 mgrabmue mgrabmue      568 Aug 22 15:26 fnmatch.c.x
-rw-r--r--   1 mgrabmue mgrabmue      658 Aug 22 12:26 fnmatch.if
mgrabmue@@tortoise (~/cvs/sizzle/scripts):
@end example
As you can see, the output file @file{fnmatch.c} exists now, and it is
considerably bigger than the input file.  This can give you a feeling
how much typing you have saved by using @file{sizzle-gen-if} :-)

Additionally, the initialization file @file{fnmatch.c.x} was created.
It holds the code needed to register the newly generated primitive
procedure, so that is gets accessible to the outer world.


@node The Generation Process, The Specification File, sizzle-gen-if invocation, sizzle-gen-if
@comment  node-name,  next,  previous,  up
@section The Generation Process.

An interface specification file is processed by @file{sizzle-gen-if} under the following rules:

@itemize @bullet
@item All data is copied verbatim to the output file, except when
escaped with the escape character @code{$}, which indicates the
beginning of an interface specification.

@item The escape character is @code{$}.  After this character, a Scheme
object is read using the standard procedure @code{read} and processed as
an interface specification.  All whitespace following the specification
will be discarded.  The result of applying the interface specification
will then be written to the output file.

@item Additionally, data may be written to the initialization file as
needed.  This can be code for registering primitives, protecting global
variables from garbage collection and creation of symbols and constant
values.
@end itemize

@node  The Specification File, A Simple Example strlen, The Generation Process, sizzle-gen-if
@comment  node-name,  next,  previous,  up
@section The Specification File

A specification file can contain arbitrary text.  The use of interface
specifications must be explicitly announced with the character
@code{$}. All other data is simply copied to the output file.  This is
useful to include things like preprocessor statements, other variable
declarations or even helper functions in the interface file.

When a @code{$} character is read, a Scheme expression representing an
interface specification is expected.  After reading this expression
(which will discard any whitespace after the expression), character
copying starts again, until a @code{$} is read, and so on.

This is the grammar for an interface specification.
@example
<if-spec>        ::= <func-spec> | <cpp-const-spec> | 
                     <symbol-spec> | <exception-spec>
<func-spec>      ::= "(" "function" <ret-type> <func-name>
                     "(" <param-list> ")" [glue-code] ")"
<func-name>      ::= identifier
<ret-type>       ::= <type> | "<void>"
<param-list>     ::= <empty> | <param> <param-list>
<param>          ::= "(" <param-name> <param-type> [<keyword> ...] ")"
<param-name>     ::= identifier
<param-type>     ::= <type>
<keyword>        ::= "invalidate" | "unchecked" | "ignored" |
                     "optional" | "rest"
<type>           ::= "<int>" | "<string>" | "<real>" | "<file>" | 
                    "<pointer>" | "<object>"
<glue-code>      ::= string
<cpp-const-spec> ::= "(" "cpp-constant" <c-name> <type> ")"
<scheme-name>    ::= identifier
<symbol-spec>    ::= "(" "symbol" <scheme-name> <c-name> ")"
<exception-spec> ::= "(" "exception" <scheme-name> <c-name> ")"
<c-name>         ::= identifier
@end example

@var{<func-name>} must be the name of the C function to be wrapped.  The
wrapper function will be called @code{<func-name>_func}.
@var{<ret-type>} is the expected return type of the function and may be
@code{<void>} if it is to be ignored.  The return type <ret-type> is
used to construct the correct return value for the function's result.
The parameter list @var{<param-list>} specifies the names of the
parameters for the function and their types, so that type-checking code
can be emitted.

The option @code{unchecked} says that no type checking is performed for
this parameter, it will be passed through to the called function.  Note
that this seldom makes sense, except for debug printing or for wrapping
a function aware of Sizzle's Scheme types.

The option @code{ignored} tells the processor not to emit type checking
code for this parameter, and that it will not be passed to the wrapped
function.  It will be silently ignored.

The additional keyword @code{invalidate}, which can be passed as a third
element in a parameter specification, is currently only implemented for
pointer values (type @code{<pointer>}).  It will cause the emission of
extra code which will invalidate the parameter pointer object with a
call to @code{zzz_invalidate_pointer()}.  This is useful if the wrapped
function performed some action rendering the pointer in the pointer
object useless.  An invalidated pointer cannot be passed to any wrapped
function expecting @code{<pointer>} arguments after that, because they
check a pointer object's valid flag.  Thus pointer object handling gets
a little bit more safe.

When @code{optional} is passed as an option, then the passed parameter
is allowed to be undefined.  You should either specify @code{ignored}
also, to avoid passing an undefined value to the wrapped function, or
you must give your own @var{<glue-code>} which handles that case
properly.

The option @code{rest} may be given on the last argument.  When given,
it means that this argument will be the rest argument to which a list of
the remaining argument will be bound.  The type of this variable is
always a list, so no parameter type checking code is emitted.  The type
for this parameter should always be @code{<object>}.

The specifications for symbols and exception will create global
variables called @var{<c-name>} and bind symbol objects with the
contents @var{<scheme-name>} to them.  Also, the variables will be
protected from garbage collection.

The @var{<cpp-const-spec>} specification creates a Scheme constant which
is bound to the value which gets substituted by the CPP macro
@var{<c-name>}.  The @var{<type>} argument is needed to create the constructor
for the constant object.

@node A Simple Example strlen, Manual Glue Code, The Specification File, sizzle-gen-if
@comment  node-name,  next,  previous,  up
@section A Simple Example

To start with, I want to give a feeling of what @file{sizzle-gen-if} can do.
At first, it may seem extremely powerful, but sooner or later you will
find out that the C functions you want to wrap are not as well suited as
in this (contrived) example.

Take this specification:
@example
$(function <int> strlen ((string <string>)))
@end example
@noindent
Here we declare a function
@itemize @bullet
@item With the name @code{strlen}.
@item With the return value @code{<int>}.
@item Which expects one argument of type @code{<string>} with the name @code{string}.
@end itemize
@noindent
When passed through @file{sizzle-gen-if}, this specification is transformed to
this C function.
@example
/*:doc
  strlen
  (strlen string) => integer
  Apply the C function @code{strlen} to the following parameters:
  string: string
  doc:*/
#define FUNC_NAME "strlen"
static result_t 
strlen_func (zzz_scm_t env, zzz_scm_t string, zzz_scm_t * result)
@{
  static char * s_func_name = FUNC_NAME;
  zzz_scm_t __retval;

  CHECK_TYPE (1, string_p (string), zzz_string_type_name);
  @{
    int res = strlen (string_val (string));
    __retval = zzz_make_integer (res);
  @}
  *result = __retval;
  return RESULT_SUCCESS;
@}
#undef FUNC_NAME
@end example

Note how the type of the actual parameter is checked for correctnes.
Then the string value is extracted from the string object before calling
the wrapped function, and the result of the function call is stored into
an integer object before returning it.

The specification and will also generate an init file containing the
following code, which will register the primitive under the name
@code{strlen} as a function taking exactly one argument.

@example
  zzz_define_function ("strlen",
                       (zzz_prim_t) strlen_func,
                       argv_1_0_0);
@end example


@node Manual Glue Code, Pointer arguments, A Simple Example strlen, sizzle-gen-if
@comment  node-name,  next,  previous,  up
@section Manual Glue Code

The automatically generated wrapper functions are nice, but they are not
as flexible as often is needed.  For example, it is not possible to
specify @code{<number>} as an argument type and have the script
automatically generate code which selects the value depending on the
actual type of the parameter, which may be integer or real.  Therefor,
the additional parameter @var{<glue-code>} is provided for interface
specifications.  When this code is present, the body of the wrapper
procedure will not be generated, but instead @var{<glue-code>} will be
inserted.  The glue code must assign a return value to the variable
@var{__retval}, but the positive effect is that argument type checking
is performed, so the glue code can rely on the fact that the parameters
have the types specified in the interface specification.

Consider this specification for the primitive @code{sin}:
@example
$(function <real> sin ((x <number>))
"
    double d;
     
    if (integer_p (x))
      d = (double) integer_val (x);
    else if (float_p (x))
      d = float_val (x);
    else
      abort ();
    __retval = zzz_make_float (sin (d));
")
@end example

The glue code tests which number type the parameter @var{x} has, and
performs the correct action according to the type.  When processed with
@file{sizzle-gen-if}, the resulting code looks as follows:

@example
/*:doc
  sin
  (sin x) => real
  Apply the C function @code{sin} to the following parameters:
  x: <number>
  doc:*/
#define FUNC_NAME "sin"
static result_t 
sin_func (zzz_scm_t env, zzz_scm_t x, zzz_scm_t * result)
@{
  static char * s_func_name = FUNC_NAME;
  zzz_scm_t __retval;

  CHECK_TYPE (1, number_p (x), zzz_number_type_name);
  @{
    double d;
     
    if (integer_p (x))
      d = (double) integer_val (x);
    else if (float_p (x))
      d = float_val (x);
    else
      abort ();
    __retval = zzz_make_float (sin (d));
  @}
  *result = __retval;
  return RESULT_SUCCESS;
@}
#undef FUNC_NAME
@end example

Additionally, the following initialization file will be created:
@example
  zzz_define_function ("sin",
                       (zzz_prim_t) sin_func,
                       argv_1_0_0);
@end example


@node Pointer arguments,  , Manual Glue Code, sizzle-gen-if
@comment  node-name,  next,  previous,  up
@section Pointer arguments

A lot of C library functions take pointers as their arguments.  It is
not possible for @file{sizzle-gen-if} to understand the meaning of all
the possible weird argument passing techniques C programmers have
invented.  Thus, @file{sizzle-gen-if} decides that all data types it
cannot understand are opaque pointers.  This does not catch all cases,
but you already knew that @file{sizzle-gen-if}'s capabilities were
limited :-)

This is an example specification for the C library function @code{free()}.  It demonstrates how to use the option keyword @code{invalidate} with pointer arguments.

@example
$(function <void> free ((p <pointer> invalidate)))
@end example
expands to
@example 
/*:doc
  free
  (free p) => *unspecified*
  Apply the C function @code{free} to the following parameters:
  p: pointer
  doc:*/
#define FUNC_NAME "free"
static result_t 
free_func (zzz_scm_t env, zzz_scm_t p, zzz_scm_t * result)
@{
  static char * s_func_name = FUNC_NAME;
  zzz_scm_t __retval;

  CHECK_TYPE (1, valid_pointer_p (p), "pointer");
  @{
    free (pointer_val (p));
    __retval = zzz_unspecified;
    zzz_invalidate_pointer (p);
  @}
  *result = __retval;
  return RESULT_SUCCESS;
@}
#undef FUNC_NAME
@end example

When @code{free_func()} returns, the pointer @var{p} cannot be used with
wrapper functions anymore, because it has been invalidated.  This is
what you want after you free a pointer, isn't it?  Using this trick,
@file{sizzle-gen-if} can even make programming with pointers safer.


@node Index,  , sizzle-gen-if, Top
@comment    node-name,         next,       previous, up
@unnumbered Index
     
@printindex cp

@contents

@bye
