1 | /* -*- C -*- |
2 | // ------------------------------------------------------------------- |
3 | // MiniExp - Library for handling lisp expressions |
4 | // Copyright (c) 2005 Leon Bottou |
5 | // |
6 | // This software is subject to, and may be distributed under, the |
7 | // GNU General Public License, either Version 2 of the license, |
8 | // or (at your option) any later version. The license should have |
9 | // accompanied the software or you may obtain a copy of the license |
10 | // from the Free Software Foundation at http://www.fsf.org . |
11 | // |
12 | // This program is distributed in the hope that it will be useful, |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | // GNU General Public License for more details. |
16 | // ------------------------------------------------------------------- |
17 | */ |
18 | |
19 | #ifndef MINIEXP_H |
20 | #define MINIEXP_H |
21 | |
22 | #ifdef __cplusplus |
23 | extern "C" { |
24 | # ifndef __cplusplus |
25 | } |
26 | # endif |
27 | #endif |
28 | |
29 | #ifndef MINILISPAPI |
30 | # ifdef WIN32 |
31 | # ifdef DLL_EXPORT |
32 | # define MINILISPAPI __declspec(dllexport) |
33 | # else |
34 | # define MINILISPAPI __declspec(dllimport) |
35 | # endif |
36 | # endif |
37 | #endif |
38 | #ifndef MINILISPAPI |
39 | # define MINILISPAPI /**/ |
40 | #endif |
41 | |
42 | #include <stddef.h> |
43 | |
44 | /* -------------------------------------------------- */ |
45 | /* LISP EXPRESSIONS */ |
46 | /* -------------------------------------------------- */ |
47 | |
48 | /* miniexp_t -- |
49 | Opaque pointer type representing a lisp expression, |
50 | also known as s-expression. |
51 | S-expressions can be viewed as a simple and powerful |
52 | alternative to XML. DjVu uses s-expressions to handle |
53 | annotations. Both the decoding api <ddjvuapi.h> and |
54 | program <djvused> use s-expressions to describe the |
55 | hidden text information and the navigation |
56 | information */ |
57 | |
58 | |
59 | typedef struct miniexp_s* miniexp_t; |
60 | |
61 | |
62 | /* There are four basic types of lisp expressions, |
63 | numbers, symbols, pairs, and objects. |
64 | The latter category can represent any c++ object |
65 | that inherits class <miniobj_t> defined later in this file. |
66 | The only such objects defined in this file are strings. */ |
67 | |
68 | |
69 | /* -------- NUMBERS -------- */ |
70 | |
71 | /* Minilisp numbers can represent any integer |
72 | in range [-2^29...2^29-1] */ |
73 | |
74 | |
75 | /* miniexp_numberp -- |
76 | Tests if an expression is a number. */ |
77 | |
78 | static inline int miniexp_numberp(miniexp_t p) { |
79 | return (((size_t)(p)&3)==3); |
80 | } |
81 | |
82 | /* miniexp_to_int -- |
83 | Returns the integer corresponding to a lisp expression. |
84 | Assume that the expression is indeed a number. */ |
85 | |
86 | static inline int miniexp_to_int(miniexp_t p) { |
87 | return (((int)(size_t)(p))>>2); |
88 | } |
89 | |
90 | /* miniexp_number -- |
91 | Constructs the expression corresponding to an integer. */ |
92 | |
93 | static inline miniexp_t miniexp_number(int x) { |
94 | return (miniexp_t) (size_t) ((x<<2)|3); |
95 | } |
96 | |
97 | |
98 | |
99 | /* -------- SYMBOLS -------- */ |
100 | |
101 | /* The textual representation of a minilisp symbol is a |
102 | sequence of printable characters forming an identifier. |
103 | Each symbol has a unique representation and remain |
104 | permanently allocated. To compare two symbols, |
105 | simply compare the <miniexp_t> pointers. */ |
106 | |
107 | |
108 | /* miniexp_symbolp -- |
109 | Tests if an expression is a symbol. */ |
110 | |
111 | static inline int miniexp_symbolp(miniexp_t p) { |
112 | return ((((size_t)p)&3)==2); |
113 | } |
114 | |
115 | /* miniexp_to_name -- |
116 | Returns the symbol name as a string. |
117 | Returns NULL if the expression is not a symbol. */ |
118 | |
119 | MINILISPAPI const char* miniexp_to_name(miniexp_t p); |
120 | |
121 | /* miniexp_symbol -- |
122 | Returns the unique symbol expression with the specified name. */ |
123 | |
124 | MINILISPAPI miniexp_t miniexp_symbol(const char *name); |
125 | |
126 | |
127 | |
128 | /* -------- PAIRS -------- */ |
129 | |
130 | /* Pairs (also named "cons") are the basic building blocks for |
131 | minilisp lists. Each pair contains two expression: |
132 | - the <car> represents the first element of a list. |
133 | - the <cdr> usually is a pair representing the rest of the list. |
134 | The empty list is represented by a null pointer. */ |
135 | |
136 | |
137 | /* miniexp_nil -- |
138 | The empty list. */ |
139 | |
140 | #define miniexp_nil ((miniexp_t)(size_t)0) |
141 | |
142 | /* miniexp_dummy -- |
143 | An invalid expression used to represent |
144 | various exceptional conditions. */ |
145 | |
146 | #define miniexp_dummy ((miniexp_t)(size_t)2) |
147 | |
148 | /* miniexp_listp -- |
149 | Tests if an expression is either a pair or the empty list. */ |
150 | |
151 | static inline int miniexp_listp(miniexp_t p) { |
152 | return ((((size_t)p)&3)==0); |
153 | } |
154 | |
155 | /* miniexp_consp -- |
156 | Tests if an expression is a pair. */ |
157 | |
158 | static inline int miniexp_consp(miniexp_t p) { |
159 | return p && miniexp_listp(p); |
160 | } |
161 | |
162 | /* miniexp_length -- |
163 | Returns the length of a list. |
164 | Returns 0 for non lists, -1 for circular lists. */ |
165 | |
166 | MINILISPAPI int miniexp_length(miniexp_t p); |
167 | |
168 | /* miniexp_car -- |
169 | miniexp_cdr -- |
170 | Returns the car or cdr of a pair. */ |
171 | |
172 | static inline miniexp_t miniexp_car(miniexp_t p) { |
173 | if (miniexp_consp(p)) |
174 | return ((miniexp_t*)p)[0]; |
175 | return miniexp_nil; |
176 | } |
177 | |
178 | static inline miniexp_t miniexp_cdr(miniexp_t p) { |
179 | if (miniexp_consp(p)) |
180 | return ((miniexp_t*)p)[1]; |
181 | return miniexp_nil; |
182 | } |
183 | |
184 | /* miniexp_cXXr -- |
185 | Represent common combinations of car and cdr. */ |
186 | |
187 | MINILISPAPI miniexp_t miniexp_caar (miniexp_t p); |
188 | MINILISPAPI miniexp_t miniexp_cadr (miniexp_t p); |
189 | MINILISPAPI miniexp_t miniexp_cdar (miniexp_t p); |
190 | MINILISPAPI miniexp_t miniexp_cddr (miniexp_t p); |
191 | MINILISPAPI miniexp_t miniexp_caddr(miniexp_t p); |
192 | MINILISPAPI miniexp_t miniexp_cdddr(miniexp_t p); |
193 | |
194 | /* miniexp_nth -- |
195 | Returns the n-th element of a list. */ |
196 | |
197 | MINILISPAPI miniexp_t miniexp_nth(int n, miniexp_t l); |
198 | |
199 | /* miniexp_cons -- |
200 | Constructs a pair. */ |
201 | |
202 | MINILISPAPI miniexp_t miniexp_cons(miniexp_t car, miniexp_t cdr); |
203 | |
204 | /* miniexp_rplaca -- |
205 | miniexp_rplacd -- |
206 | Changes the car or the cdr of a pair. */ |
207 | |
208 | MINILISPAPI miniexp_t miniexp_rplaca(miniexp_t pair, miniexp_t newcar); |
209 | MINILISPAPI miniexp_t miniexp_rplacd(miniexp_t pair, miniexp_t newcdr); |
210 | |
211 | /* miniexp_reverse -- |
212 | Reverses a list in place. */ |
213 | |
214 | MINILISPAPI miniexp_t miniexp_reverse(miniexp_t p); |
215 | |
216 | |
217 | /* -------- OBJECTS (GENERIC) -------- */ |
218 | |
219 | /* Object expressions represent a c++ object |
220 | that inherits class <miniobj_t> defined later. |
221 | Each object expression has a symbolic class name |
222 | and a pointer to the c++ object. */ |
223 | |
224 | /* miniexp_objectp -- |
225 | Tests if an expression is an object. */ |
226 | |
227 | static inline int miniexp_objectp(miniexp_t p) { |
228 | return ((((size_t)p)&3)==1); |
229 | } |
230 | |
231 | /* miniexp_classof -- |
232 | Returns the symbolic class of an expression. |
233 | Returns nil if the expression is not an object. */ |
234 | |
235 | MINILISPAPI miniexp_t miniexp_classof(miniexp_t p); |
236 | |
237 | /* miniexp_isa -- |
238 | If <p> is an instance of class named <c> or one of |
239 | its subclasses, returns the actual class name. |
240 | Otherwise returns miniexp_nil. */ |
241 | |
242 | MINILISPAPI miniexp_t miniexp_isa(miniexp_t p, miniexp_t c); |
243 | |
244 | |
245 | /* -------- OBJECTS (STRINGS) -------- */ |
246 | |
247 | /* miniexp_stringp -- |
248 | Tests if an expression is a string. */ |
249 | |
250 | MINILISPAPI int miniexp_stringp(miniexp_t p); |
251 | |
252 | /* miniexp_to_str -- |
253 | Returns the c string represented by the expression. |
254 | Returns NULL if the expression is not a string. |
255 | The c string remains valid as long as the |
256 | corresponding lisp object exists. */ |
257 | |
258 | MINILISPAPI const char *miniexp_to_str(miniexp_t p); |
259 | |
260 | /* miniexp_string -- |
261 | Constructs a string expression by copying string s. */ |
262 | |
263 | MINILISPAPI miniexp_t miniexp_string(const char *s); |
264 | |
265 | /* miniexp_substring -- |
266 | Constructs a string expression by copying |
267 | at most n character from string s. */ |
268 | |
269 | MINILISPAPI miniexp_t miniexp_substring(const char *s, int n); |
270 | |
271 | /* miniexp_concat -- |
272 | Concat all the string expressions in list <l>. */ |
273 | |
274 | MINILISPAPI miniexp_t miniexp_concat(miniexp_t l); |
275 | |
276 | |
277 | |
278 | |
279 | |
280 | /* -------------------------------------------------- */ |
281 | /* GARBAGE COLLECTION */ |
282 | /* -------------------------------------------------- */ |
283 | |
284 | |
285 | /* The garbage collector reclaims the memory allocated for |
286 | lisp expressions no longer in use. It is automatically |
287 | invoked by the pair and object allocation functions when |
288 | the available memory runs low. It is however possible to |
289 | temporarily disable it. |
290 | |
291 | The trick is to determine which lisp expressions are in |
292 | use at a given moment. This package takes a simplistic |
293 | approach. All objects of type <minivar_t> are chained and |
294 | can reference an arbitrary lisp expression. Garbage |
295 | collection preserves all lisp expressions referenced by a |
296 | minivar, as well as all lisp expressions that can be |
297 | accessed from these. When called automatically, |
298 | garbage collection also preserves the sixteen most recently |
299 | created miniexps in order to make sure that temporaries do |
300 | not vanish in the middle of complicated C expressions. |
301 | |
302 | The minivar class is designed such that C++ program can |
303 | directly use instances of <minivar_t> as normal |
304 | <miniexp_t> variables. There is almost no overhead |
305 | accessing or changing the lisp expression referenced by a |
306 | minivar. However, the minivar chain must be updated |
307 | whenever the minivar object is constructed or destructed. |
308 | |
309 | Example (in C++ only): |
310 | miniexp_t copy_in_reverse(miniexp_t p) { |
311 | minivar_t l = miniexp_nil; |
312 | while (miniexp_consp(p)) { |
313 | l = miniexp_cons(miniexp_car(p), l); |
314 | p = miniexp_cdr(p); |
315 | } |
316 | return l; |
317 | } |
318 | |
319 | When to use minivar_t instead of miniexp_t? |
320 | |
321 | * A function that only navigates properly secured |
322 | s-expressions without modifying them does not need to |
323 | bother about minivars. |
324 | |
325 | * Only the following miniexp functions can cause a |
326 | garbage collection: miniexp_cons(), miniexp_object(), |
327 | miniexp_string(), miniexp_substring(), |
328 | miniexp_concat(), miniexp_pprin(), miniexp_pprint(), |
329 | miniexp_gc(), and minilisp_release_gc_lock(). A |
330 | function that does not cause calls to these functions |
331 | does not need to bother about minivars. |
332 | |
333 | * Other functions should make sure that all useful |
334 | s-expression are directly or indirectly secured by a |
335 | minivar_t object. In case of doubt, use minivars |
336 | everywhere. |
337 | |
338 | * Function arguments should remain <miniexp_t> in order |
339 | to allow interoperability with the C language. As a |
340 | consequence, functions must often copy their arguments |
341 | into minivars in order to make sure they remain |
342 | allocated. A small performance improvement can be |
343 | achieved by deciding that the function should always be |
344 | called using properly secured arguments. This is more |
345 | difficult to get right. |
346 | |
347 | C programs cannot use minivars as easily as C++ programs. |
348 | Wrappers are provided to allocate minivars and to access |
349 | their value. This is somehow inconvenient. It might be |
350 | more practical to control the garbage collector |
351 | invocations with <minilisp_acquire_gc_lock()> and |
352 | <minilisp_release_gc_lock()>... */ |
353 | |
354 | |
355 | /* minilisp_gc -- |
356 | Invokes the garbage collector now. */ |
357 | |
358 | MINILISPAPI void minilisp_gc(void); |
359 | |
360 | /* minilisp_info -- |
361 | Prints garbage collector statistics. */ |
362 | |
363 | MINILISPAPI void minilisp_info(void); |
364 | |
365 | /* minilisp_acquire_gc_lock -- |
366 | minilisp_release_gc_lock -- |
367 | Temporarily disables automatic garbage collection. |
368 | Acquire/release pairs may be nested. |
369 | Both functions return their argument unmodified. |
370 | This is practical because <minilisp_release_gc_lock> |
371 | can invoke the garbage collector. Before doing |
372 | so it stores its argument in a minivar to |
373 | preserve it. |
374 | |
375 | Example (in C): |
376 | miniexp_t copy_in_reverse(miniexp_t p) { |
377 | miniexp_t l = 0; |
378 | minilisp_acquire_gc_lock(0); |
379 | while (miniexp_consp(p)) { |
380 | l = miniexp_cons(miniexp_car(p), l); |
381 | p = miniexp_cdr(p); |
382 | } |
383 | return minilisp_release_gc_lock(l); |
384 | } |
385 | |
386 | Disabling garbage collection for a long time |
387 | increases the memory consumption. */ |
388 | |
389 | MINILISPAPI miniexp_t minilisp_acquire_gc_lock(miniexp_t); |
390 | MINILISPAPI miniexp_t minilisp_release_gc_lock(miniexp_t); |
391 | |
392 | /* minivar_t -- |
393 | The minivar type. */ |
394 | #ifdef __cplusplus |
395 | class minivar_t; |
396 | #else |
397 | typedef struct minivar_s minivar_t; |
398 | #endif |
399 | |
400 | /* minivar_alloc -- |
401 | minivar_free -- |
402 | Wrappers for creating and destroying minivars in C. */ |
403 | |
404 | MINILISPAPI minivar_t *minivar_alloc(void); |
405 | MINILISPAPI void minivar_free(minivar_t *v); |
406 | |
407 | /* minivar_pointer -- |
408 | Wrappers to access the lisp expression referenced |
409 | by a minivar. This function returns a pointer |
410 | to the actual miniexp_t variable. */ |
411 | |
412 | MINILISPAPI miniexp_t *minivar_pointer(minivar_t *v); |
413 | |
414 | /* minilisp_debug -- |
415 | Setting the debug flag runs the garbage collector |
416 | very often. This is extremely slow, but can be |
417 | useful to debug memory allocation problems. */ |
418 | |
419 | MINILISPAPI void minilisp_debug(int debugflag); |
420 | |
421 | /* minilisp_finish -- |
422 | Deallocates everything. This is only useful when using |
423 | development tools designed to check for memory leaks. |
424 | No miniexp function can be used after calling this. */ |
425 | |
426 | MINILISPAPI void minilisp_finish(void); |
427 | |
428 | |
429 | /* -------------------------------------------------- */ |
430 | /* INPUT/OUTPUT */ |
431 | /* -------------------------------------------------- */ |
432 | |
433 | /* Notes about the textual representation of miniexps. |
434 | |
435 | - Special characters are: |
436 | * the parenthesis <(> and <)>, |
437 | * the double quote <">, |
438 | * the vertical bar <|>, |
439 | * the dieze character <#>, when followed by an |
440 | ascii character with a non zero entry in the |
441 | dieze character array. |
442 | * any other ascii character with a non zero entry |
443 | in the macro character array. |
444 | |
445 | - Symbols are represented by their name. |
446 | Vertical bars <|> can be used to delimit names that |
447 | contain blanks, special characters, non printable |
448 | characters, non ascii characters, or |
449 | can be confused for a number. |
450 | |
451 | - Numbers follow the syntax specified by the C |
452 | function strtol() with base=0. |
453 | |
454 | - Strings are delimited by double quotes. |
455 | All C string escapes are recognized. |
456 | Non printable ascii characters must be escaped. |
457 | |
458 | - List are represented by an open parenthesis <(> |
459 | followed by the space separated list elements, |
460 | followed by a closing parenthesis <)>. |
461 | When the cdr of the last pair is non zero, |
462 | the closed parenthesis is preceded by |
463 | a space, a dot <.>, a space, and the textual |
464 | representation of the cdr. |
465 | |
466 | - When the parser encounters an ascii character corresponding |
467 | to a non zero function pointer in the macro character array, |
468 | the function is invoked and must return a possibly empty |
469 | list of miniexps to be returned by subsequent |
470 | invocations of the parser. The same process happens when |
471 | the parser encounters a dieze character followed by an |
472 | ascii character corresponding to a non zero function pointer |
473 | int the dieze character array. */ |
474 | |
475 | |
476 | /* miniexp_pname -- |
477 | Returns a string containing the textual representation |
478 | of a minilisp expression. Set argument <width> to zero |
479 | to output a single line, or to a positive value to |
480 | perform pretty line breaks for this intended number of columns. |
481 | This function can cause a garbage collection to occur. */ |
482 | |
483 | MINILISPAPI miniexp_t miniexp_pname(miniexp_t p, int width); |
484 | |
485 | |
486 | /* miniexp_io_t -- |
487 | This structure is used to describe how to perform input/output |
488 | operations. Input/output operations are performed through function |
489 | pointers <fputs>, <fgetc>, and <ungetc>, which are similar to their |
490 | stdio counterparts. Variable <data> defines four pointers that can |
491 | be used as a closure by the I/O functions. |
492 | When <p_print7bits> is nonzero and points to a nonzero integer, all |
493 | non-ascii characters in strings are output as octal escapes. When both |
494 | <p_macrochar> and <p_macroqueue> are non zero, a non zero entry in |
495 | <p_macrochar[c]> defines a special parsing function that is called when |
496 | <miniexp_read_r> encounters the character <c> (in range 0 to 127.) |
497 | When both <p_diezechar> and <p_macroqueue> are non zero, a non zero |
498 | entry in <p_diezechar[c]> defines a special parsing function that |
499 | is called when <miniexp_read_r> encounters the character '#' followed |
500 | by character <c> (in range 0 to 127.) These parsing functions return |
501 | a list of <miniexp_t> that function <miniexp_read_r> returns one-by-one |
502 | before processing more input. This list is in fact stored in the |
503 | variable pointed by <io.p_macroqueue>. */ |
504 | |
505 | typedef struct miniexp_io_s miniexp_io_t; |
506 | typedef miniexp_t (*miniexp_macrochar_t)(miniexp_io_t*); |
507 | |
508 | struct miniexp_io_s |
509 | { |
510 | int (*fputs)(miniexp_io_t*, const char*); |
511 | int (*fgetc)(miniexp_io_t*); |
512 | int (*ungetc)(miniexp_io_t*, int); |
513 | void *data[4]; |
514 | int *p_print7bits; |
515 | miniexp_macrochar_t *p_macrochar; |
516 | miniexp_macrochar_t *p_diezechar; |
517 | minivar_t *p_macroqueue; |
518 | minivar_t *p_reserved; |
519 | }; |
520 | |
521 | /* miniexp_io_init -- |
522 | Initialize a default <miniexp_io_t> structure |
523 | that reads from stdin and prints to stdout. |
524 | Field <data[0]> is used to hold the stdin file pointer. |
525 | Field <data[1]> is used to hold the stdout file pointer. |
526 | Fields <p_print7bits>, <p_macrochar>, <p_diezechar> |
527 | and <p_macroqueue> are set to point to zero-initialized |
528 | shared variables. */ |
529 | |
530 | MINILISPAPI void miniexp_io_init(miniexp_io_t *io); |
531 | |
532 | /* miniexp_io_set_{input,output} -- |
533 | Override the file descriptor used for input or output. |
534 | You must call <miniexp_io_init> before. */ |
535 | |
536 | #if defined(stdin) |
537 | MINILISPAPI void miniexp_io_set_output(miniexp_io_t *io, FILE *f); |
538 | MINILISPAPI void miniexp_io_set_input(miniexp_io_t *io, FILE *f); |
539 | #endif |
540 | |
541 | /* miniexp_read_r -- |
542 | Reads an expression by repeatedly |
543 | invoking <minilisp_getc> and <minilisp_ungetc>. |
544 | Returns <miniexp_dummy> when an error occurs. */ |
545 | |
546 | MINILISPAPI miniexp_t miniexp_read_r(miniexp_io_t *io); |
547 | |
548 | /* miniexp_prin_r, miniexp_print_r -- |
549 | Prints a minilisp expression by repeatedly invoking <minilisp_puts>. |
550 | Only <minilisp_print> outputs a final newline character. |
551 | These functions are safe to call anytime. */ |
552 | |
553 | MINILISPAPI miniexp_t miniexp_prin_r(miniexp_io_t *io, miniexp_t p); |
554 | MINILISPAPI miniexp_t miniexp_print_r(miniexp_io_t *io, miniexp_t p); |
555 | |
556 | /* miniexp_pprin_r, miniexp_pprint_r -- |
557 | Prints a minilisp expression with reasonably pretty line breaks. |
558 | Argument <width> is the intended number of columns. |
559 | Only <minilisp_pprint> outputs a final newline character. |
560 | These functions can cause a garbage collection to occur. */ |
561 | |
562 | MINILISPAPI miniexp_t miniexp_pprin_r(miniexp_io_t *io, miniexp_t p, int w); |
563 | MINILISPAPI miniexp_t miniexp_pprint_r(miniexp_io_t *io, miniexp_t p, int w); |
564 | |
565 | /* miniexp_io, miniexp_read, miniexp_{,p}prin{,t} -- |
566 | Variable <miniexp_io> contains the pre-initialized input/output data |
567 | structure that is used by the non-reentrant input/output functions. */ |
568 | |
569 | extern MINILISPAPI miniexp_io_t miniexp_io; |
570 | MINILISPAPI miniexp_t miniexp_read(void); |
571 | MINILISPAPI miniexp_t miniexp_prin(miniexp_t p); |
572 | MINILISPAPI miniexp_t miniexp_print(miniexp_t p); |
573 | MINILISPAPI miniexp_t miniexp_pprin(miniexp_t p, int width); |
574 | MINILISPAPI miniexp_t miniexp_pprint(miniexp_t p, int width); |
575 | |
576 | /* miniexp_macrochar, miniexp_macroqueue -- |
577 | Function <miniexp_io_init> causes the corresponding pointers in the |
578 | <miniexp_io_t> structure to point to these variables. A non zero entry in |
579 | <io.macrochar> defines a special parsing function that runs when |
580 | <miniexp_read_r> encounters the corresponding character. The parsing |
581 | function return a list of <miniexp_t> that function <miniexp_read_r> |
582 | returns one-by-one before processing more input. This list is in fact |
583 | stored in the variable pointed to by <io.macroqueue>. */ |
584 | |
585 | extern MINILISPAPI miniexp_macrochar_t miniexp_macrochar[128]; |
586 | extern MINILISPAPI minivar_t miniexp_macroqueue; |
587 | |
588 | |
589 | /* Backward compatibility. */ |
590 | extern MINILISPAPI int (*minilisp_puts)(const char *); |
591 | extern MINILISPAPI int (*minilisp_getc)(void); |
592 | extern MINILISPAPI int (*minilisp_ungetc)(int); |
593 | extern MINILISPAPI miniexp_t (*minilisp_macrochar_parser[128])(void); |
594 | extern MINILISPAPI miniexp_t (*minilisp_diezechar_parser[128])(void); |
595 | extern MINILISPAPI int minilisp_print_7bits; |
596 | #if defined(stdin) |
597 | MINILISPAPI void minilisp_set_output(FILE *f); |
598 | MINILISPAPI void minilisp_set_input(FILE *f); |
599 | #endif |
600 | |
601 | /* -------------------------------------------------- */ |
602 | /* STUFF FOR C++ ONLY */ |
603 | /* -------------------------------------------------- */ |
604 | |
605 | #ifdef __cplusplus |
606 | # ifndef __cplusplus |
607 | { |
608 | # endif |
609 | } // extern "C" |
610 | |
611 | typedef void minilisp_mark_t(miniexp_t *pp); |
612 | |
613 | /* -------- MINIVARS -------- */ |
614 | |
615 | /* minivar_t -- |
616 | A class for protected garbage collector variables. */ |
617 | |
618 | class MINILISPAPI |
619 | minivar_t |
620 | { |
621 | miniexp_t data; |
622 | minivar_t *next; |
623 | minivar_t **pprev; |
624 | public: |
625 | minivar_t(); |
626 | minivar_t(miniexp_t p); |
627 | minivar_t(const minivar_t &v); |
628 | operator miniexp_t&() { return data; } |
629 | miniexp_t* operator&() { return &data; } |
630 | minivar_t& operator=(miniexp_t p) { data = p; return *this; } |
631 | minivar_t& operator=(const minivar_t &v) { data = v.data; return *this; } |
632 | ~minivar_t() { if ((*pprev = next)) next->pprev = pprev; } |
633 | #ifdef MINIEXP_IMPLEMENTATION |
634 | static minivar_t *vars; |
635 | static void mark(minilisp_mark_t*); |
636 | #endif |
637 | }; |
638 | |
639 | |
640 | /* -------- MINIOBJ -------- */ |
641 | |
642 | |
643 | /* miniobj_t -- |
644 | The base class for c++ objects |
645 | represented by object expressions. */ |
646 | |
647 | class MINILISPAPI |
648 | miniobj_t { |
649 | public: |
650 | virtual ~miniobj_t(); |
651 | |
652 | /* --- stuff defined by MINIOBJ_DECLARE --- */ |
653 | /* classname: a symbol characterizing this class. */ |
654 | static const miniexp_t classname; |
655 | /* classof: class name symbol for this object. */ |
656 | virtual miniexp_t classof() const = 0; |
657 | /* isa -- tests if this is an instance of <classname>. */ |
658 | virtual bool isa(miniexp_t classname) const; |
659 | |
660 | /* --- optional stuff --- */ |
661 | /* pname: returns a printable name for this object. |
662 | The caller must deallocate the result with delete[]. */ |
663 | virtual char *pname() const; |
664 | /* mark: iterates over miniexps contained by this object |
665 | for garbage collecting purposes. */ |
666 | virtual void mark(minilisp_mark_t*); |
667 | /* destroy: called by the garbage collector to |
668 | deallocate the object. Defaults to 'delete this'. */ |
669 | virtual void destroy(); |
670 | |
671 | }; |
672 | |
673 | /* MINIOBJ_DECLARE -- |
674 | MINIOBJ_IMPLEMENT -- |
675 | Useful code fragments for implementing |
676 | the mandatory part of miniobj subclasses. */ |
677 | |
678 | #define MINIOBJ_DECLARE(cls, supercls, name) \ |
679 | public: static const miniexp_t classname; \ |
680 | virtual miniexp_t classof() const; \ |
681 | virtual bool isa(miniexp_t) const; |
682 | |
683 | #define MINIOBJ_IMPLEMENT(cls, supercls, name)\ |
684 | const miniexp_t cls::classname = miniexp_symbol(name);\ |
685 | miniexp_t cls::classof() const {\ |
686 | return cls::classname; }\ |
687 | bool cls::isa(miniexp_t n) const {\ |
688 | return (cls::classname==n) || (supercls::isa(n)); } |
689 | |
690 | |
691 | /* miniexp_to_obj -- |
692 | Returns a pointer to the object represented by an lisp |
693 | expression. Returns NULL if the expression is not an |
694 | object expression. |
695 | */ |
696 | |
697 | static inline miniobj_t *miniexp_to_obj(miniexp_t p) { |
698 | if (miniexp_objectp(p)) |
699 | return ((miniobj_t**)(((size_t)p)&~((size_t)3)))[0]; |
700 | return 0; |
701 | } |
702 | |
703 | /* miniexp_object -- |
704 | Create an object expression for a given object. */ |
705 | |
706 | MINILISPAPI miniexp_t miniexp_object(miniobj_t *obj); |
707 | |
708 | |
709 | #endif /* __cplusplus */ |
710 | |
711 | |
712 | |
713 | |
714 | |
715 | /* -------------------------------------------------- */ |
716 | /* THE END */ |
717 | /* -------------------------------------------------- */ |
718 | |
719 | #endif /* MINIEXP_H */ |
720 | |