/* libsizzle/cvar.h - C variable wrapper
 
  Copyright (C) 1999, 2000 Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
 
  This is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2, or (at your option)
  any later version.
  
  This software is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this package; see the file COPYING.  If not, write to the
  Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  MA 02111-1307, USA.  */

#ifndef __SIZZLE_CVAR_H__
#define __SIZZLE_CVAR_H__

#if HAVE_CONFIG_H
# include <config.h>
#endif 

#if __SIZZLE_IMPORT__
# define SIZZLE_API __declspec (dllimport)
#elif __SIZZLE_EXPORT__ 
# define SIZZLE_API __declspec (dllexport)
#else
# define SIZZLE_API
#endif

#include "node.h"

/* Discriminator and accessor macros for magic variables.  */
#define magic_var_p(c)       (tagged_p(c) && \
                              tagged_type(c) == zzz_tagged_type_magic_var)
#define ro_magic_var_p(c)    (magic_var_p(c) && \
                              tagged_info(c) == tagged_info_ro)
#define magic_var_data(c)    ((void *) tagged_data0(c))
#define magic_var_handler(c) ((int (*)(int, void *, zzz_scm_t *)) \
                              tagged_data1(c))

/* Information about magic string variables is stored in values of
   this structure type.  */
typedef struct str_var_descriptor * str_var_desc_t;
struct str_var_descriptor
{
  char * val;
  int len;
  int size;
};

/* Type tag for magic variables.  */
SIZZLE_API extern unsigned long zzz_tagged_type_magic_var;

/* Create a symbol called @var{name} and bind it to the integer
   variable located at address @var{*address}.  Mark the variable as
   read-only if @var{read_only} is true. */
SIZZLE_API void zzz_bind_int_variable (char * name, int * address,
				       int read_only);

/* Create a symbol called @var{name} and bind it to the integer
   variable located at address @var{*address}.  Mark the variable as
   read-only if @var{read_only} is true.  The difference to
   bind_int_variable() is that only boolean values can be stored into
   a variable created by bind_bool_variable. */
SIZZLE_API void zzz_bind_bool_variable (char * name, int * address,
					int read_only);

/* Create a symbol called @var{name} and bind it to the string
   variable located at address @var{*address}.  At most @var{size}
   bytes can be stored into the created variable. Mark the variable as
   read-only if @var{read_only} is true. */
SIZZLE_API void zzz_bind_string_variable (char * name, char * address, 
					  int size, int read_only);

/* Create a variable called @var{name} which is bound to the cell
   value pointed to by @var{address}.  The new variable is read-only
   if @var{read_only} is true.  */
SIZZLE_API void zzz_bind_scm_variable (char * name, zzz_scm_t * address,
				       int read_only);

/* Create a closure variable.  A variable of this type will be read
   from and written to by calling Scheme procedures.  @var{vec} must
   be a vector with three elements, the first being a procedure which
   is called with one argument for setting the variable, the second
   being a procedure for retrieving the variable's value and the third
   a procedure which is called for finalization, when the variable
   disappears.  */
void zzz_bind_closure_variable (char * name, zzz_scm_t vec, int read_only);

/* These mode constants are passed to the magic variables' handler
   functions to indicate what action to perform.  */
#define MAGIC_MODE_SET  0
#define MAGIC_MODE_GET  1
#define MAGIC_MODE_MARK 2
#define MAGIC_MODE_FREE 3

/* Create a magic variable called @var{name}.  Magic variables have a
   handler function and an opaque data pointer associated with them.

   When the variable is read, the handler is called with @var{mode}
   set to @code{MAGIC_MODE_GET} and must either a valid Scheme object
   in the location pointed to by the last parameter and return the
   value 0; or it must return a non-0 value and store an error object
   in the return parameter.

   When the variable is set, the handler is called with mode
   @code{MAGIC_MODE_SET} and the new value is passed per reference in
   the last parameter.  On success, the handler should return 0 and
   leave the last reference-parameter unchanged, on error it should
   return a non-0 value and store an error object in the location
   pointed to by the last parameter.

   When the garbage collection is invoked, the handler will be called
   with mode @code{MAGIC_MODE_MARK} and should then mark all necessary
   values of type zzz_scm_t with zzz_mark_cell().  It should always
   return 0 and leave the last reference parameter unchanged.  

   Mode @code{MAGIC_MODE_FREE} is used in calling the handler when a
   magic variable is not referenced any more.  It should be used to
   free any allocated memory.

   The handler is always called with the pointer @var{data}, so this
   value can be used as a pointer to a data structure for maintaining
   state. When @var{read_only} is true, the new magic variable cannot be set
   from the Scheme level.  */
SIZZLE_API void zzz_bind_magic_variable (char * name, void * data, 
					 int (* handler) (int mode, void *,
							  zzz_scm_t *),
					 int read_only);

/* Initialize the magic C variable modules.  Called once on library
   startup by the main initialization code.  */
SIZZLE_API result_t zzz_init_cvar (void);

#endif /* not __SIZZLE_CVAR_H__ */
