Blame libdjvu/miniexp.h

Packit df99a1
/* -*- C -*-
Packit df99a1
// -------------------------------------------------------------------
Packit df99a1
// MiniExp - Library for handling lisp expressions
Packit df99a1
// Copyright (c) 2005  Leon Bottou
Packit df99a1
//
Packit df99a1
// This software is subject to, and may be distributed under, the
Packit df99a1
// GNU General Public License, either Version 2 of the license,
Packit df99a1
// or (at your option) any later version. The license should have
Packit df99a1
// accompanied the software or you may obtain a copy of the license
Packit df99a1
// from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//
Packit df99a1
// This program is distributed in the hope that it will be useful,
Packit df99a1
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
// GNU General Public License for more details.
Packit df99a1
// -------------------------------------------------------------------
Packit df99a1
*/
Packit df99a1
Packit df99a1
#ifndef MINIEXP_H
Packit df99a1
#define MINIEXP_H
Packit df99a1
Packit df99a1
#ifdef __cplusplus
Packit df99a1
extern "C" { 
Packit df99a1
# ifndef __cplusplus
Packit df99a1
}
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#ifndef MINILISPAPI
Packit df99a1
# ifdef _WIN32
Packit df99a1
#  ifdef MINILISPAPI_EXPORT
Packit df99a1
#   define MINILISPAPI __declspec(dllexport)
Packit df99a1
#  else
Packit df99a1
#   define MINILISPAPI __declspec(dllimport)
Packit df99a1
#  endif
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
#ifndef MINILISPAPI
Packit df99a1
# define MINILISPAPI /**/
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#ifndef __cplusplus
Packit df99a1
# ifndef inline
Packit df99a1
#  if defined(__GNUC__)
Packit df99a1
#   define inline __inline__
Packit df99a1
#  elif defined(_MSC_VER)
Packit df99a1
#   define inline __inline
Packit df99a1
#  else
Packit df99a1
#   define inline /**/
Packit df99a1
#  endif
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#include <stddef.h>  
Packit df99a1
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
/* LISP EXPRESSIONS                                   */
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
Packit df99a1
/* miniexp_t -- 
Packit df99a1
   Opaque pointer type representing a lisp expression,
Packit df99a1
   also known as s-expression. 
Packit df99a1
   S-expressions can be viewed as a simple and powerful 
Packit df99a1
   alternative to XML.  DjVu uses s-expressions to handle
Packit df99a1
   annotations. Both the decoding api <ddjvuapi.h> and 
Packit df99a1
   program <djvused> use s-expressions to describe the 
Packit df99a1
   hidden text information and the navigation 
Packit df99a1
   information */
Packit df99a1
Packit df99a1
Packit df99a1
typedef struct miniexp_s* miniexp_t;
Packit df99a1
Packit df99a1
Packit df99a1
/* There are four basic types of lisp expressions,
Packit df99a1
   numbers, symbols, pairs, and objects.
Packit df99a1
   The latter category can represent any c++ object
Packit df99a1
   that inherits class <miniobj_t> defined later in this file.
Packit df99a1
   Strings and floating point numbers are implemented this way.*/
Packit df99a1
Packit df99a1
Packit df99a1
/* -------- NUMBERS -------- */
Packit df99a1
Packit df99a1
/* Minilisp numbers represent integers 
Packit df99a1
   covering at least range [-2^29...2^29-1] */
Packit df99a1
Packit df99a1
Packit df99a1
/* miniexp_numberp --
Packit df99a1
   Tests if an expression is a number. */
Packit df99a1
Packit df99a1
static inline int miniexp_numberp(miniexp_t p) {
Packit df99a1
  return (((size_t)(p)&3)==3);
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_to_int --
Packit df99a1
   Returns the integer corresponding to a lisp expression.
Packit df99a1
   Assume that the expression is indeed a number. */
Packit df99a1
Packit df99a1
static inline int miniexp_to_int(miniexp_t p) {
Packit df99a1
  return (((int)(size_t)(p))>>2);
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_number --
Packit df99a1
   Constructs the expression corresponding to an integer. */
Packit df99a1
Packit df99a1
static inline miniexp_t miniexp_number(int x) {
Packit df99a1
  return (miniexp_t) (size_t) ((x<<2)|3);
Packit df99a1
}
Packit df99a1
   
Packit df99a1
Packit df99a1
Packit df99a1
/* -------- SYMBOLS -------- */
Packit df99a1
Packit df99a1
/* The textual representation of a minilisp symbol is a 
Packit df99a1
   sequence of printable characters forming an identifier. 
Packit df99a1
   Each symbol has a unique representation and remain 
Packit df99a1
   permanently allocated. To compare two symbols, 
Packit df99a1
   simply compare the <miniexp_t> pointers. */
Packit df99a1
Packit df99a1
Packit df99a1
/* miniexp_symbolp --
Packit df99a1
   Tests if an expression is a symbol. */
Packit df99a1
Packit df99a1
static inline int miniexp_symbolp(miniexp_t p) {
Packit df99a1
  return ((((size_t)p)&3)==2);
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_to_name --
Packit df99a1
   Returns the symbol name as a string.
Packit df99a1
   Returns NULL if the expression is not a symbol. */
Packit df99a1
   
Packit df99a1
MINILISPAPI const char* miniexp_to_name(miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_symbol --
Packit df99a1
   Returns the unique symbol expression with the specified name. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_symbol(const char *name);
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/* -------- PAIRS -------- */
Packit df99a1
Packit df99a1
/* Pairs (also named "cons") are the basic building blocks for 
Packit df99a1
   minilisp lists. Each pair contains two expression:
Packit df99a1
   - the <car> represents the first element of a list.
Packit df99a1
   - the <cdr> usually is a pair representing the rest of the list.
Packit df99a1
   The empty list is represented by a null pointer. */
Packit df99a1
Packit df99a1
Packit df99a1
/* miniexp_nil --
Packit df99a1
   The empty list. */
Packit df99a1
Packit df99a1
#define miniexp_nil ((miniexp_t)(size_t)0)
Packit df99a1
Packit df99a1
/* miniexp_dummy --
Packit df99a1
   An invalid expression used to represent
Packit df99a1
   various exceptional conditions. */
Packit df99a1
Packit df99a1
#define miniexp_dummy ((miniexp_t)(size_t)2)
Packit df99a1
Packit df99a1
/* miniexp_listp --
Packit df99a1
   Tests if an expression is either a pair or the empty list. */   
Packit df99a1
Packit df99a1
static inline int miniexp_listp(miniexp_t p) {
Packit df99a1
  return ((((size_t)p)&3)==0);
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_consp --
Packit df99a1
   Tests if an expression is a pair. */
Packit df99a1
Packit df99a1
static inline int miniexp_consp(miniexp_t p) {
Packit df99a1
  return p && miniexp_listp(p);
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_length --
Packit df99a1
   Returns the length of a list.
Packit df99a1
   Returns 0 for non lists, -1 for circular lists. */
Packit df99a1
Packit df99a1
MINILISPAPI int miniexp_length(miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_car --
Packit df99a1
   miniexp_cdr --
Packit df99a1
   Returns the car or cdr of a pair. */
Packit df99a1
Packit df99a1
static inline miniexp_t miniexp_car(miniexp_t p) {
Packit df99a1
  if (miniexp_consp(p))
Packit df99a1
    return ((miniexp_t*)p)[0];
Packit df99a1
  return miniexp_nil;
Packit df99a1
}
Packit df99a1
Packit df99a1
static inline miniexp_t miniexp_cdr(miniexp_t p) {
Packit df99a1
  if (miniexp_consp(p))
Packit df99a1
    return ((miniexp_t*)p)[1];
Packit df99a1
  return miniexp_nil;
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_cXXr --
Packit df99a1
   Represent common combinations of car and cdr. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_caar (miniexp_t p);
Packit df99a1
MINILISPAPI miniexp_t miniexp_cadr (miniexp_t p);
Packit df99a1
MINILISPAPI miniexp_t miniexp_cdar (miniexp_t p);
Packit df99a1
MINILISPAPI miniexp_t miniexp_cddr (miniexp_t p);
Packit df99a1
MINILISPAPI miniexp_t miniexp_caddr(miniexp_t p);
Packit df99a1
MINILISPAPI miniexp_t miniexp_cdddr(miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_nth --
Packit df99a1
   Returns the n-th element of a list. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_nth(int n, miniexp_t l);
Packit df99a1
Packit df99a1
/* miniexp_cons --
Packit df99a1
   Constructs a pair. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_cons(miniexp_t car, miniexp_t cdr);
Packit df99a1
Packit df99a1
/* miniexp_rplaca --
Packit df99a1
   miniexp_rplacd --
Packit df99a1
   Changes the car or the cdr of a pair. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_rplaca(miniexp_t pair, miniexp_t newcar);
Packit df99a1
MINILISPAPI miniexp_t miniexp_rplacd(miniexp_t pair, miniexp_t newcdr);
Packit df99a1
Packit df99a1
/* miniexp_reverse --
Packit df99a1
   Reverses a list in place. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_reverse(miniexp_t p);
Packit df99a1
Packit df99a1
Packit df99a1
/* -------- OBJECTS (GENERIC) -------- */
Packit df99a1
Packit df99a1
/* Object expressions represent a c++ object
Packit df99a1
   that inherits class <miniobj_t> defined later.
Packit df99a1
   Each object expression has a symbolic class name
Packit df99a1
   and a pointer to the c++ object. */
Packit df99a1
Packit df99a1
/* miniexp_objectp --
Packit df99a1
   Tests if an expression is an object. */
Packit df99a1
Packit df99a1
static inline int miniexp_objectp(miniexp_t p) {
Packit df99a1
  return ((((size_t)p)&3)==1);
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_classof --
Packit df99a1
   Returns the symbolic class of an expression.
Packit df99a1
   Returns nil if the expression is not an object. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_classof(miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_isa --
Packit df99a1
   If 

is an instance of class named <c> or one of

Packit df99a1
   its subclasses, returns the actual class name.
Packit df99a1
   Otherwise returns miniexp_nil. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_isa(miniexp_t p, miniexp_t c);
Packit df99a1
Packit df99a1
Packit df99a1
/* -------- OBJECTS (STRINGS) -------- */
Packit df99a1
Packit df99a1
/* miniexp_stringp --
Packit df99a1
   Tests if an expression is a string. */
Packit df99a1
Packit df99a1
MINILISPAPI int miniexp_stringp(miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_to_str --
Packit df99a1
   Returns the c string represented by the expression.
Packit df99a1
   Returns NULL if the expression is not a string.
Packit df99a1
   The c string remains valid as long as the
Packit df99a1
   corresponding lisp object exists. */
Packit df99a1
Packit df99a1
MINILISPAPI const char *miniexp_to_str(miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_string --
Packit df99a1
   Constructs a string expression by copying string s. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_string(const char *s);
Packit df99a1
Packit df99a1
/* miniexp_substring --
Packit df99a1
   Constructs a string expression by copying 
Packit df99a1
   at most n character from string s. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_substring(const char *s, int n);
Packit df99a1
Packit df99a1
/* miniexp_concat --
Packit df99a1
   Concat all the string expressions in list <l>. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_concat(miniexp_t l);
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/* -------- OBJECTS (FLOATNUM) -------- */
Packit df99a1
Packit df99a1
/* miniexp_floatnump --
Packit df99a1
   Tests if an expression is an object
Packit df99a1
   representing a floating point number. */
Packit df99a1
Packit df99a1
MINILISPAPI int miniexp_floatnump(miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_floatnum --
Packit df99a1
   Returns a new floating point number object. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_floatnum(double x);
Packit df99a1
Packit df99a1
/* miniexp_doublep --
Packit df99a1
   Tests if an expression can be converted
Packit df99a1
   to a double precision number. */
Packit df99a1
Packit df99a1
static inline int miniexp_doublep(miniexp_t p) {
Packit df99a1
  return miniexp_numberp(p) || miniexp_floatnump(p);
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_to_double --
Packit df99a1
   Returns a double precision number corresponding to 
Packit df99a1
   a lisp expression (a number or a floatnum.) */
Packit df99a1
Packit df99a1
MINILISPAPI double miniexp_to_double(miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_double --
Packit df99a1
   Returns a lisp expression representing a double
Packit df99a1
   precision number. This will be a number if it fits
Packit df99a1
   and a floatnum otherwise.
Packit df99a1
 */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_double(double x);
Packit df99a1
Packit df99a1
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
/* GARBAGE COLLECTION                                 */
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
Packit df99a1
Packit df99a1
/* The garbage collector reclaims the memory allocated for
Packit df99a1
   lisp expressions no longer in use.  It is automatically
Packit df99a1
   invoked by the pair and object allocation functions when
Packit df99a1
   the available memory runs low.  It is however possible to
Packit df99a1
   temporarily disable it.
Packit df99a1
Packit df99a1
   The trick is to determine which lisp expressions are in
Packit df99a1
   use at a given moment. This package takes a simplistic
Packit df99a1
   approach. All objects of type <minivar_t> are chained and
Packit df99a1
   can reference an arbitrary lisp expression.  Garbage
Packit df99a1
   collection preserves all lisp expressions referenced by a
Packit df99a1
   minivar, as well as all lisp expressions that can be
Packit df99a1
   accessed from these. When called automatically, 
Packit df99a1
   garbage collection also preserves the sixteen most recently 
Packit df99a1
   created miniexps in order to make sure that temporaries do 
Packit df99a1
   not vanish in the middle of complicated C expressions.
Packit df99a1
     
Packit df99a1
   The minivar class is designed such that C++ program can
Packit df99a1
   directly use instances of <minivar_t> as normal
Packit df99a1
   <miniexp_t> variables.  There is almost no overhead
Packit df99a1
   accessing or changing the lisp expression referenced by a
Packit df99a1
   minivar. However, the minivar chain must be updated
Packit df99a1
   whenever the minivar object is constructed or destructed.
Packit df99a1
   
Packit df99a1
   Example (in C++ only):
Packit df99a1
     miniexp_t copy_in_reverse(miniexp_t p) {
Packit df99a1
        minivar_t l = miniexp_nil;
Packit df99a1
        while (miniexp_consp(p)) {
Packit df99a1
          l = miniexp_cons(miniexp_car(p), l); 
Packit df99a1
          p = miniexp_cdr(p); 
Packit df99a1
        }
Packit df99a1
        return l;
Packit df99a1
     }
Packit df99a1
Packit df99a1
   When to use minivar_t instead of miniexp_t?
Packit df99a1
Packit df99a1
   * A function that only navigates properly secured
Packit df99a1
     s-expressions without modifying them does not need to
Packit df99a1
     bother about minivars.
Packit df99a1
Packit df99a1
   * Only the following miniexp functions can cause a
Packit df99a1
     garbage collection: miniexp_cons(), miniexp_object(),
Packit df99a1
     miniexp_string(), miniexp_substring(), miniexp_pname(),
Packit df99a1
     miniexp_concat(), miniexp_pprin(), miniexp_pprint(),
Packit df99a1
     miniexp_gc(), and minilisp_release_gc_lock().  A
Packit df99a1
     function that does not cause calls to these functions
Packit df99a1
     does not need to bother about minivars.
Packit df99a1
Packit df99a1
   * Other functions should make sure that all useful
Packit df99a1
     s-expression are directly or indirectly secured by a
Packit df99a1
     minivar_t object. In case of doubt, use minivars
Packit df99a1
     everywhere.
Packit df99a1
Packit df99a1
   * Function arguments should remain <miniexp_t> in order
Packit df99a1
     to allow interoperability with the C language. 
Packit df99a1
     It is assumed that these arguments have been properly
Packit df99a1
     secured by the caller and cannot disappear if a 
Packit df99a1
     garbage collection occurs.
Packit df99a1
Packit df99a1
   C programs cannot use minivars as easily as C++ programs.
Packit df99a1
   Wrappers are provided to allocate minivars and to access
Packit df99a1
   their value. This is somehow inconvenient.  It might be
Packit df99a1
   more practical to control the garbage collector
Packit df99a1
   invocations with <minilisp_acquire_gc_lock()> and
Packit df99a1
   <minilisp_release_gc_lock()>...  */
Packit df99a1
   
Packit df99a1
Packit df99a1
/* minilisp_gc --
Packit df99a1
   Invokes the garbage collector now. */
Packit df99a1
Packit df99a1
MINILISPAPI void minilisp_gc(void);
Packit df99a1
Packit df99a1
/* minilisp_info --
Packit df99a1
   Prints garbage collector statistics. */
Packit df99a1
Packit df99a1
MINILISPAPI void minilisp_info(void);
Packit df99a1
Packit df99a1
/* minilisp_acquire_gc_lock --
Packit df99a1
   minilisp_release_gc_lock --
Packit df99a1
   Temporarily disables automatic garbage collection.
Packit df99a1
   Acquire/release pairs may be nested. 
Packit df99a1
   Both functions return their argument unmodified.
Packit df99a1
   This is practical because <minilisp_release_gc_lock>
Packit df99a1
   can invoke the garbage collector. Before doing
Packit df99a1
   so it stores its argument in a minivar to 
Packit df99a1
   preserve it. 
Packit df99a1
Packit df99a1
   Example (in C):
Packit df99a1
     miniexp_t copy_in_reverse(miniexp_t p) {
Packit df99a1
        miniexp_t l = 0;
Packit df99a1
        minilisp_acquire_gc_lock(0);
Packit df99a1
        while (miniexp_consp(p)) {
Packit df99a1
          l = miniexp_cons(miniexp_car(p), l); 
Packit df99a1
          p = miniexp_cdr(p); 
Packit df99a1
        }
Packit df99a1
        return minilisp_release_gc_lock(l); 
Packit df99a1
     }
Packit df99a1
   
Packit df99a1
   Disabling garbage collection for a long time 
Packit df99a1
   increases the memory consumption. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t minilisp_acquire_gc_lock(miniexp_t);
Packit df99a1
MINILISPAPI miniexp_t minilisp_release_gc_lock(miniexp_t);
Packit df99a1
Packit df99a1
/* minivar_t --
Packit df99a1
   The minivar type. */
Packit df99a1
#ifdef __cplusplus
Packit df99a1
class minivar_t;
Packit df99a1
#else
Packit df99a1
typedef struct minivar_s minivar_t;
Packit df99a1
#endif
Packit df99a1
Packit df99a1
/* minivar_alloc --
Packit df99a1
   minivar_free --
Packit df99a1
   Wrappers for creating and destroying minivars in C. */
Packit df99a1
Packit df99a1
MINILISPAPI minivar_t *minivar_alloc(void);
Packit df99a1
MINILISPAPI void minivar_free(minivar_t *v);
Packit df99a1
Packit df99a1
/* minivar_pointer --
Packit df99a1
   Wrappers to access the lisp expression referenced
Packit df99a1
   by a minivar. This function returns a pointer
Packit df99a1
   to the actual miniexp_t variable. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t *minivar_pointer(minivar_t *v);
Packit df99a1
Packit df99a1
/* minilisp_debug -- 
Packit df99a1
   Setting the debug flag runs the garbage collector 
Packit df99a1
   very often. This is extremely slow, but can be
Packit df99a1
   useful to debug memory allocation problems. */
Packit df99a1
Packit df99a1
MINILISPAPI void minilisp_debug(int debugflag);
Packit df99a1
Packit df99a1
/* minilisp_finish --
Packit df99a1
   Deallocates everything.  This is only useful when using
Packit df99a1
   development tools designed to check for memory leaks.  
Packit df99a1
   No miniexp function can be used after calling this. */
Packit df99a1
Packit df99a1
MINILISPAPI void minilisp_finish(void);
Packit df99a1
Packit df99a1
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
/* INPUT/OUTPUT                                       */
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
Packit df99a1
/* Notes about the textual representation of miniexps.
Packit df99a1
Packit df99a1
   - Special characters are:
Packit df99a1
     * the parenthesis <(> and <)>,
Packit df99a1
     * the double quote <">,
Packit df99a1
     * the vertical bar <|>,
Packit df99a1
     * any other ascii character with a non zero entry 
Packit df99a1
       in the macro character array.
Packit df99a1
     * the dieze character <#>, when followed by another
Packit df99a1
       dieze or by an ascii character with a non zero entry 
Packit df99a1
       in the dieze character array.
Packit df99a1
Packit df99a1
   - Symbols are represented by their name.
Packit df99a1
     Symbols whose name contains blanks, special characters, 
Packit df99a1
     non printable characters, non ascii characters, 
Packit df99a1
     or can be confused for a number are delimited
Packit df99a1
     by vertical bars <|> and can contain two consecutive
Packit df99a1
     vertical bars to represent a single vertical bar character.
Packit df99a1
     
Packit df99a1
   - Numbers follow the syntax specified by the C
Packit df99a1
     function strtol() with base=0, but are required
Packit df99a1
     to start with a digit or with a sign character
Packit df99a1
     followed by another character.
Packit df99a1
Packit df99a1
   - Floating point follow the syntax specified by the C
Packit df99a1
     function strtod() with base=0, but are required
Packit df99a1
     to start with a digit or with a sign character
Packit df99a1
     followed by another character.
Packit df99a1
Packit df99a1
   - Strings are delimited by double quotes. 
Packit df99a1
     All non printable ASCII characters must be escaped. 
Packit df99a1
     Besides all the usual C string escape sequences,
Packit df99a1
     UTF8-encoded Unicode characters in range 0..0x10ffff
Packit df99a1
     can be represented by escape sequence <\u> followed
Packit df99a1
     by four hexadecimal digits or escape sequence <\U>
Packit df99a1
     followed by six hexadecimal digits. Surrogate pairs
Packit df99a1
     are always recognized as a single Unicode character.
Packit df99a1
     The effect of invalid escape sequences is unspecified.
Packit df99a1
Packit df99a1
   - List are represented by an open parenthesis <(>
Packit df99a1
     followed by the space separated list elements,
Packit df99a1
     followed by a closing parenthesis <)>.
Packit df99a1
     When the cdr of the last pair is non zero,
Packit df99a1
     the closed parenthesis is preceded by 
Packit df99a1
     a space, a dot <.>, a space, and the textual 
Packit df99a1
     representation of the cdr.
Packit df99a1
Packit df99a1
   - When the parser encounters an ascii character corresponding
Packit df99a1
     to a non zero function pointer in the macro character array,
Packit df99a1
     the function is invoked and must return a possibly empty
Packit df99a1
     list of miniexps to be returned by subsequent 
Packit df99a1
     invocations of the parser. The same process happens when
Packit df99a1
     the parser encounters a dieze character followed by an 
Packit df99a1
     ascii character corresponding to a non zero function pointer
Packit df99a1
     int the dieze character array. */
Packit df99a1
Packit df99a1
Packit df99a1
/* miniexp_pname --
Packit df99a1
   Returns a string containing the textual representation
Packit df99a1
   of a minilisp expression. Set argument <width> to zero
Packit df99a1
   to output a single line, or to a positive value to
Packit df99a1
   perform pretty line breaks for this intended number of columns.
Packit df99a1
   This function can cause a garbage collection to occur. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_pname(miniexp_t p, int width);
Packit df99a1
Packit df99a1
Packit df99a1
/* miniexp_io_t -- 
Packit df99a1
   This structure is used to describe how to perform input/output
Packit df99a1
   operations. Input/output operations are performed through function 
Packit df99a1
   pointers <fputs>, <fgetc>, and <ungetc>, which are similar to their 
Packit df99a1
   stdio counterparts. Variable <data> defines four pointers that can 
Packit df99a1
   be used as a closure by the I/O functions.
Packit df99a1
      Variable <p_flags> optionally points to a flag word that customize the
Packit df99a1
   printing operation. All ASCII control characters present in strings are
Packit df99a1
   displayed using C escapes sequences. Flag <miniexp_io_print7bits> causes
Packit df99a1
   all other non ASCII characters to be escaped. Flag <miniexp_io_u6escape>
Packit df99a1
   and <miniexp_io_u4escape> respectively authorize using the long and
Packit df99a1
   short utf8 escape sequences "\U" and "\u". Their absence may force
Packit df99a1
   using surrogate short escape sequences or only octal sequences.
Packit df99a1
   Flag <miniexp_io_quotemoresyms> causes the output code to also quote
Packit df99a1
   all symbols that start with a digit or with a sign character followed
Packit df99a1
   by another character.
Packit df99a1
      When both <p_macrochar> and <p_macroqueue> are non zero, a non zero 
Packit df99a1
   entry in <p_macrochar[c]> defines a special parsing function that is called
Packit df99a1
   when <miniexp_read_r> encounters the character <c> (in range 0 to 127.)
Packit df99a1
   When both <p_diezechar> and <p_macroqueue> are non zero, a non zero entry
Packit df99a1
   in <p_diezechar[c]> defines a special parsing function that is called when
Packit df99a1
   <miniexp_read_r> encounters the character '#' followed by character <c> (in
Packit df99a1
   range 0 to 127.)  These parsing functions return a list of <miniexp_t> that
Packit df99a1
   function <miniexp_read_r> returns one-by-one before processing more
Packit df99a1
   input. This list is stored in the variable pointed by <io.p_macroqueue>.  
Packit df99a1
*/
Packit df99a1
Packit df99a1
typedef struct miniexp_io_s miniexp_io_t;
Packit df99a1
typedef miniexp_t (*miniexp_macrochar_t)(miniexp_io_t*);
Packit df99a1
Packit df99a1
struct miniexp_io_s
Packit df99a1
{
Packit df99a1
  int (*fputs)(miniexp_io_t*, const char*);
Packit df99a1
  int (*fgetc)(miniexp_io_t*);
Packit df99a1
  int (*ungetc)(miniexp_io_t*, int);
Packit df99a1
  void *data[4];
Packit df99a1
  int *p_flags; /* previously named p_print7bits */
Packit df99a1
  miniexp_macrochar_t *p_macrochar;
Packit df99a1
  miniexp_macrochar_t *p_diezechar;
Packit df99a1
  minivar_t *p_macroqueue;
Packit df99a1
  minivar_t *p_reserved;
Packit df99a1
};
Packit df99a1
Packit df99a1
#define miniexp_io_print7bits          0x1
Packit df99a1
#define miniexp_io_u4escape            0x2
Packit df99a1
#define miniexp_io_u6escape            0x4
Packit df99a1
#define miniexp_io_quotemoresymbols    0x20
Packit df99a1
Packit df99a1
/* miniexp_io_init --
Packit df99a1
   Initialize a default <miniexp_io_t> structure
Packit df99a1
   that reads from stdin and prints to stdout. 
Packit df99a1
   Field <data[0]> is used to hold the stdin file pointer.
Packit df99a1
   Field <data[1]> is used to hold the stdout file pointer.
Packit df99a1
   Fields <p_flags>, <p_macrochar>, <p_diezechar>
Packit df99a1
   and <p_macroqueue> are set to point to zero-initialized
Packit df99a1
   shared variables. */
Packit df99a1
Packit df99a1
MINILISPAPI void miniexp_io_init(miniexp_io_t *io);
Packit df99a1
Packit df99a1
/* miniexp_io_set_{input,output} --
Packit df99a1
   Override the file descriptor used for input or output.
Packit df99a1
   You must call <miniexp_io_init> before. */
Packit df99a1
Packit df99a1
#if defined(stdin)
Packit df99a1
MINILISPAPI void miniexp_io_set_output(miniexp_io_t *io, FILE *f);
Packit df99a1
MINILISPAPI void miniexp_io_set_input(miniexp_io_t *io, FILE *f);
Packit df99a1
#endif
Packit df99a1
Packit df99a1
/* miniexp_read_r --
Packit df99a1
   Reads an expression by repeatedly
Packit df99a1
   invoking <minilisp_getc> and <minilisp_ungetc>.
Packit df99a1
   Returns <miniexp_dummy> when an error occurs. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_read_r(miniexp_io_t *io);
Packit df99a1
Packit df99a1
/* miniexp_prin_r, miniexp_print_r --
Packit df99a1
   Prints a minilisp expression by repeatedly invoking <minilisp_puts>.
Packit df99a1
   Only <minilisp_print> outputs a final newline character. 
Packit df99a1
   These functions are safe to call anytime. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_prin_r(miniexp_io_t *io, miniexp_t p);
Packit df99a1
MINILISPAPI miniexp_t miniexp_print_r(miniexp_io_t *io, miniexp_t p);
Packit df99a1
Packit df99a1
/* miniexp_pprin_r, miniexp_pprint_r --
Packit df99a1
   Prints a minilisp expression with reasonably pretty line breaks. 
Packit df99a1
   Argument <width> is the intended number of columns. 
Packit df99a1
   Only <minilisp_pprint> outputs a final newline character. 
Packit df99a1
   These functions can cause a garbage collection to occur. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_pprin_r(miniexp_io_t *io, miniexp_t p, int w);
Packit df99a1
MINILISPAPI miniexp_t miniexp_pprint_r(miniexp_io_t *io, miniexp_t p, int w);
Packit df99a1
Packit df99a1
/* miniexp_io, miniexp_read, miniexp_{,p}prin{,t} --
Packit df99a1
   Variable <miniexp_io> contains the pre-initialized input/output data
Packit df99a1
   structure that is used by the non-reentrant input/output functions. */
Packit df99a1
Packit df99a1
extern MINILISPAPI miniexp_io_t miniexp_io;
Packit df99a1
MINILISPAPI miniexp_t miniexp_read(void);
Packit df99a1
MINILISPAPI miniexp_t miniexp_prin(miniexp_t p);
Packit df99a1
MINILISPAPI miniexp_t miniexp_print(miniexp_t p);
Packit df99a1
MINILISPAPI miniexp_t miniexp_pprin(miniexp_t p, int width);
Packit df99a1
MINILISPAPI miniexp_t miniexp_pprint(miniexp_t p, int width);
Packit df99a1
Packit df99a1
Packit df99a1
/* Backward compatibility (will eventually disappear) */
Packit df99a1
extern MINILISPAPI int (*minilisp_puts)(const char *);
Packit df99a1
extern MINILISPAPI int (*minilisp_getc)(void);
Packit df99a1
extern MINILISPAPI int (*minilisp_ungetc)(int);
Packit df99a1
extern MINILISPAPI miniexp_t (*minilisp_macrochar_parser[128])(void);
Packit df99a1
extern MINILISPAPI miniexp_t (*minilisp_diezechar_parser[128])(void);
Packit df99a1
extern MINILISPAPI miniexp_macrochar_t miniexp_macrochar[128];
Packit df99a1
extern MINILISPAPI minivar_t miniexp_macroqueue;
Packit df99a1
extern MINILISPAPI int minilisp_print_7bits;
Packit df99a1
#if defined(stdin)
Packit df99a1
MINILISPAPI void minilisp_set_output(FILE *f);
Packit df99a1
MINILISPAPI void minilisp_set_input(FILE *f);
Packit df99a1
#endif
Packit df99a1
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
/* STUFF FOR C++ ONLY                                 */
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
Packit df99a1
#ifdef __cplusplus
Packit df99a1
# ifndef __cplusplus
Packit df99a1
{
Packit df99a1
# endif
Packit df99a1
} // extern "C"
Packit df99a1
Packit df99a1
typedef void minilisp_mark_t(miniexp_t *pp);
Packit df99a1
Packit df99a1
/* -------- MINIVARS -------- */
Packit df99a1
Packit df99a1
/* minivar_t --
Packit df99a1
   A class for protected garbage collector variables. */
Packit df99a1
Packit df99a1
class MINILISPAPI 
Packit df99a1
minivar_t 
Packit df99a1
{
Packit df99a1
  miniexp_t data;
Packit df99a1
  minivar_t *next;
Packit df99a1
  minivar_t **pprev;
Packit df99a1
public:
Packit df99a1
  minivar_t();
Packit df99a1
  minivar_t(miniexp_t p);
Packit df99a1
  minivar_t(const minivar_t &v);
Packit df99a1
  operator miniexp_t&() { return data; }
Packit df99a1
  miniexp_t* operator&() { return &dat;; }
Packit df99a1
  minivar_t& operator=(miniexp_t p) { data = p; return *this; }
Packit df99a1
  minivar_t& operator=(const minivar_t &v) { data = v.data; return *this; }
Packit df99a1
  ~minivar_t();
Packit df99a1
#ifdef MINIEXP_IMPLEMENTATION
Packit df99a1
  static minivar_t *vars;
Packit df99a1
  static void mark(minilisp_mark_t*);
Packit df99a1
#endif
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
/* -------- MINIOBJ -------- */
Packit df99a1
Packit df99a1
Packit df99a1
/* miniobj_t --
Packit df99a1
   The base class for c++ objects 
Packit df99a1
   represented by object expressions. */
Packit df99a1
Packit df99a1
class MINILISPAPI 
Packit df99a1
miniobj_t {
Packit df99a1
 public:
Packit df99a1
  virtual ~miniobj_t();
Packit df99a1
Packit df99a1
  /* --- stuff defined by MINIOBJ_DECLARE --- */
Packit df99a1
  /* classname: a symbol characterizing this class. */
Packit df99a1
  static const miniexp_t classname;
Packit df99a1
  /* classof: class name symbol for this object. */
Packit df99a1
  virtual miniexp_t classof() const = 0;
Packit df99a1
  /* isa -- tests if this is an instance of <classname>. */
Packit df99a1
  virtual bool isa(miniexp_t classname) const;
Packit df99a1
Packit df99a1
  /* --- optional stuff --- */
Packit df99a1
  /* pname: returns a printable name for this object.
Packit df99a1
     The caller must deallocate the result with delete[]. */
Packit df99a1
  virtual char *pname() const;
Packit df99a1
  /* mark: calls action() on all member miniexps of the object,
Packit df99a1
     for garbage collecting purposes. */
Packit df99a1
  virtual void mark(minilisp_mark_t *action);
Packit df99a1
  /* destroy: called by the garbage collector to
Packit df99a1
     deallocate the object. Defaults to 'delete this'. */
Packit df99a1
  virtual void destroy();
Packit df99a1
     
Packit df99a1
};
Packit df99a1
Packit df99a1
/* MINIOBJ_DECLARE --
Packit df99a1
   MINIOBJ_IMPLEMENT --
Packit df99a1
   Useful code fragments for implementing 
Packit df99a1
   the mandatory part of miniobj subclasses. */
Packit df99a1
Packit df99a1
#define MINIOBJ_DECLARE(cls, supercls, name) \
Packit df99a1
  public: static const miniexp_t classname; \
Packit df99a1
          virtual miniexp_t classof() const; \
Packit df99a1
          virtual bool isa(miniexp_t) const; 
Packit df99a1
Packit df99a1
#define MINIOBJ_IMPLEMENT(cls, supercls, name)\
Packit df99a1
  const miniexp_t cls::classname = miniexp_symbol(name);\
Packit df99a1
  miniexp_t cls::classof() const {\
Packit df99a1
    return cls::classname; }\
Packit df99a1
  bool cls::isa(miniexp_t n) const {\
Packit df99a1
    return (cls::classname==n) || (supercls::isa(n)); }
Packit df99a1
Packit df99a1
Packit df99a1
/* miniexp_to_obj --
Packit df99a1
   Returns a pointer to the object represented by an lisp
Packit df99a1
   expression. Returns NULL if the expression is not an
Packit df99a1
   object expression.
Packit df99a1
*/
Packit df99a1
Packit df99a1
static inline miniobj_t *miniexp_to_obj(miniexp_t p) {
Packit df99a1
  if (miniexp_objectp(p))
Packit df99a1
    return ((miniobj_t**)(((size_t)p)&~((size_t)3)))[0];
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
/* miniexp_object --
Packit df99a1
   Create an object expression for a given object. */
Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_object(miniobj_t *obj);
Packit df99a1
Packit df99a1
Packit df99a1
/* miniexp_mutate -- 
Packit df99a1
   Atomically modifies a member of a garbage collected object. 
Packit df99a1
   The object implementation must call this function to change 
Packit df99a1
   the contents of a member variable <v> of object <obj>.
Packit df99a1
   Returns 

*/

Packit df99a1
Packit df99a1
MINILISPAPI miniexp_t miniexp_mutate(miniexp_t obj, miniexp_t *v, miniexp_t p);
Packit df99a1
Packit df99a1
Packit df99a1
#endif /* __cplusplus */
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
/* THE END                                            */
Packit df99a1
/* -------------------------------------------------- */
Packit df99a1
Packit df99a1
#endif /* MINIEXP_H */