Edinburgh Speech Tools  2.1-release
slib.cc
Go to the documentation of this file.
1 /* Scheme In One Defun, but in C this time.
2 
3  * COPYRIGHT (c) 1988-1994 BY *
4  * PARADIGM ASSOCIATES INCORPORATED, CAMBRIDGE, MASSACHUSETTS. *
5  * ALL RIGHTS RESERVED *
6 
7 Permission to use, copy, modify, distribute and sell this software
8 and its documentation for any purpose and without fee is hereby
9 granted, provided that the above copyright notice appear in all copies
10 and that both that copyright notice and this permission notice appear
11 in supporting documentation, and that the name of Paradigm Associates
12 Inc not be used in advertising or publicity pertaining to distribution
13 of the software without specific, written prior permission.
14 
15 PARADIGM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 PARADIGM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 SOFTWARE.
22 
23 */
24 
25 /*
26 
27 gjc@paradigm.com, gjc@mitech.com
28 
29 Paradigm Associates Inc Phone: 617-492-6079
30 29 Putnam Ave, Suite 6
31 Cambridge, MA 02138
32 
33 
34  Release 1.0: 24-APR-88
35  Release 1.1: 25-APR-88, added: macros, predicates, load. With additions by
36  Barak.Pearlmutter@DOGHEN.BOLTZ.CS.CMU.EDU: Full flonum recognizer,
37  cleaned up uses of NULL/0. Now distributed with siod.scm.
38  Release 1.2: 28-APR-88, name changes as requested by JAR@AI.AI.MIT.EDU,
39  plus some bug fixes.
40  Release 1.3: 1-MAY-88, changed env to use frames instead of alist.
41  define now works properly. vms specific function edit.
42  Release 1.4 20-NOV-89. Minor Cleanup and remodularization.
43  Now in 3 files, siod.h, slib.c, siod.c. Makes it easier to write your
44  own main loops. Some short-int changes for lightspeed C included.
45  Release 1.5 29-NOV-89. Added startup flag -g, select stop and copy
46  or mark-and-sweep garbage collection, which assumes that the stack/register
47  marking code is correct for your architecture.
48  Release 2.0 1-DEC-89. Added repl_hooks, Catch, Throw. This is significantly
49  different enough (from 1.3) now that I'm calling it a major release.
50  Release 2.1 4-DEC-89. Small reader features, dot, backquote, comma.
51  Release 2.2 5-DEC-89. gc,read,print,eval, hooks for user defined datatypes.
52  Release 2.3 6-DEC-89. save_forms, obarray intern mechanism. comment char.
53  Release 2.3a......... minor speed-ups. i/o interrupt considerations.
54  Release 2.4 27-APR-90 gen_readr, for read-from-string.
55  Release 2.5 18-SEP-90 arrays added to SIOD.C by popular demand. inums.
56  Release 2.6 11-MAR-92 function prototypes, some remodularization.
57  Release 2.7 20-MAR-92 hash tables, fasload. Stack check.
58  Release 2.8 3-APR-92 Bug fixes, \n syntax in string reading.
59  Release 2.9 28-AUG-92 gc sweep bug fix. fseek, ftell, etc. Change to
60  envlookup to allow (a . rest) suggested by bowles@is.s.u-tokyo.ac.jp.
61  Release 2.9a 10-AUG-93. Minor changes for Windows NT.
62  Release 3.0 12-JAN-94. Release it, include changes/cleanup recommended by
63  andreasg@nynexst.com for the OS2 C++ compiler. Compilation and running
64  tested using DEC C, VAX C. WINDOWS NT. GNU C on SPARC.
65 
66  Festival/Edinburgh Speech Tools changes (awb@cstr.ed.ac.uk) 1996-1999
67  Note there have been substantial changes to this from its original
68  form which may have introduced bugs. Please contact Alan W Black
69  (awb@cstr.ed.ac.uk) first if you find problems unless you can confirm
70  they also exist in the original siod-3.0 release
71 
72  March 1999 split off functions into different files to make it easier
73  for our documentation purposes, sorry maybe this should be called
74  SNIOD now :-), or maybe Scheme in one Directory.
75 
76  */
77 
78 #include <cstdio>
79 #include <cstring>
80 #include <cctype>
81 #include <csignal>
82 #include <cmath>
83 #include <cstdlib>
84 #include <ctime>
85 
86 #include "EST_unix.h"
87 
88 #include "EST_cutils.h"
89 #include "siod.h"
90 #include "siodp.h"
91 
92 #ifdef WIN32
93 #include "winsock2.h"
94 #endif
95 
96 using namespace std;
97 
98 static int restricted_function_call(LISP l);
99 static long repl(struct repl_hooks *h);
100 static void gc_mark_and_sweep(void);
101 static void gc_ms_stats_start(void);
102 static void gc_ms_stats_end(void);
103 static void mark_protected_registers(void);
104 static void mark_locations(LISP *start,LISP *end);
105 static void gc_sweep(void);
106 static void mark_locations_array(LISP *x,long n);
107 static LISP lreadr(struct gen_readio *f);
108 static LISP lreadparen(struct gen_readio *f);
109 static LISP lreadstring(struct gen_readio *f);
110 
111 const char *siod_version(void)
112 {return("3.0 FIELD TEST");}
113 
119 long gc_status_flag = 0;
120 long show_backtrace = 0;
121 char *init_file = (char *) NULL;
122 char *tkbuffer = NULL;
127 LISP freelist;
128 
129 long nointerrupt = 1;
131 LISP oblistvar = NIL;
133 static LISP siod_backtrace = NIL;
135 LISP truth = NIL;
136 LISP eof_val = NIL;
138 static LISP sym_quote = NIL;
139 static LISP sym_dot = NIL;
141 LISP *obarray;
142 long obarray_dim = 100;
144 void (*repl_puts)(char *) = NULL;
145 LISP (*repl_read)(void) = NULL;
146 LISP (*repl_eval)(LISP) = NULL;
147 void (*repl_print)(LISP) = NULL;
150 LISP *inums;
151 LISP siod_docstrings = NIL; /* for builtin functions */
152 long inums_dim = 100;
156 double gc_rt;
158 static const char *user_ch_readm = "";
159 static const char *user_te_readm = "";
160 LISP (*user_readm)(int, struct gen_readio *) = NULL;
161 LISP (*user_readt)(char *,long, int *) = NULL;
162 void (*fatal_exit_hook)(void) = NULL;
163 FILE *fwarn=NULL;
165 static void err(const char *message, LISP x, const char *s) EST_NORETURN;
166 
167 extern "C" {
168 int el_pos = -1; // actually used by readline
169 }
170 const char *repl_prompt = "siod>";
171 const char *siod_prog_name = "siod";
172 const char *siod_primary_prompt = "siod> ";
173 const char *siod_secondary_prompt = "> ";
174 
175 // A list of objects with gc_free_once set in their user_type_hooks structure
176 // whose gc_free function has been called in the current GC sweep.
177 void **dead_pointers = NULL;
180 #define DEAD_POINTER_GROWTH (10)
181 
182 static LISP set_restricted(LISP l);
183 
185 long stack_size = 500000;
186 
187 void NNEWCELL(LISP *_into,long _type)
188 {if NULLP(freelist)
189  {
190  gc_for_newcell();
191  }
192  *_into = freelist;
193  freelist = CDR(freelist);
195 
196  (*_into)->gc_mark = 0;
197  (*_into)->type = (short) _type;
198 }
199 
200 void need_n_cells(int n)
201 {
202  /* Check there are N cells available, and force gc if not */
203  LISP x = NIL;
204  int i;
205 
206  for (i=0; i<n; i++)
207  x = cons(NIL,x);
208 
209  return;
210 }
211 
212 static void start_rememberring_dead(void)
213 {
215 }
216 
217 static int is_dead(void *ptr)
218 {
219  int i;
220  for(i=0; i<num_dead_pointers; i++)
221  if (dead_pointers[i] == ptr)
222  return 1;
223  return 0;
224 }
225 
226 static void mark_as_dead(void *ptr)
227 {
228  int i;
231 
232  for(i=0; i<num_dead_pointers; i++)
233  if (dead_pointers[i] == ptr)
234  return;
235 
236  dead_pointers[num_dead_pointers++] = ptr;
237 }
238 
240 {printf("Welcome to SIOD, Scheme In One Defun, Version %s\n",
241  siod_version());
242  printf("(C) Copyright 1988-1994 Paradigm Associates Inc.\n");
243  if (extra_info != "")
244  printf("%s\n", (const char *)extra_info);
245 }
246 
248 {
249  siod_print_welcome("");
250 }
251 
252 void print_hs_1(void)
253 {printf("heap_size = %ld cells, %ld bytes. %ld inums. GC is %s\n",
254  heap_size,(long)(heap_size*sizeof(struct obj)),
255  inums_dim,
256  (gc_kind_copying == 1) ? "stop and copy" : "mark and sweep");}
257 
258 void print_hs_2(void)
259 {if (gc_kind_copying == 1)
260  printf("heap_1 at %p, heap_2 at %p\n",(void *)heap_1,(void *)heap_2);
261  else
262  printf("heap_1 at %p\n",(void *)heap_1);}
263 
264 /* I don't have a clean way to do this but need to reset this if */
265 /* ctrl-c occurs. */
268 
269 static void err_ctrl_c(void)
270 {
271  audsp_mode = FALSE;
272  siod_ctrl_c = TRUE;
273  err("control-c interrupt",NIL);}
274 
275 long no_interrupt(long n)
276 {long x;
277  x = nointerrupt;
278  nointerrupt = n;
279  if ((nointerrupt == 0) && (interrupt_differed == 1))
280  {interrupt_differed = 0;
281  err_ctrl_c();}
282  return(x);}
283 
284 extern "C" void handle_sigfpe(int sig SIG_restargs)
285 {(void)sig;
286  signal(SIGFPE,handle_sigfpe);
287  /* Solaris seems to need a relse before it works again */
288 #ifdef __svr4__
289  sigrelse(SIGFPE);
290 #endif
291  /* linux needs to unmask sigfpe to allow for next one */
292 #ifdef __linux__
293  sigset_t set1;
294  sigemptyset(&set1);
295  sigaddset(&set1,SIGFPE);
296  sigprocmask(SIG_UNBLOCK,&set1,NULL);
297 #endif
298  signal(SIGFPE,handle_sigfpe);
299  err("floating point exception",NIL);}
300 
301 extern "C" void handle_sigint(int sig SIG_restargs)
302 {(void)sig;
303  signal(SIGINT,handle_sigint);
304  /* Solaris seems to need a relse before it works again */
305 #ifdef __svr4__
306  sigrelse(SIGINT);
307 #endif
308  /* linux needs to unmask sigint to allow for next one */
309 #ifdef __linux__
310  sigset_t set1;
311  sigemptyset(&set1);
312  sigaddset(&set1,SIGINT);
313  sigprocmask(SIG_UNBLOCK,&set1,NULL);
314 #endif
315  signal(SIGINT,handle_sigint);
316  if (nointerrupt == 1)
317  interrupt_differed = 1;
318  else
319  err_ctrl_c();}
320 
322 {
323  el_pos = -1; /* flush remaining input on that line */
325  interrupt_differed = 0;
326  nointerrupt = 0;
327 }
328 
329 long repl_driver(long want_sigint,long want_init,struct repl_hooks *h)
330 {int k;
331  struct repl_hooks hd;
332  LISP stack_start;
333  stack_start_ptr = &stack_start;
335  est_errjmp = walloc(jmp_buf,1);
336  k = setjmp(*est_errjmp);
337  if(k)
338  {
339  sock_acknowledge_error(); /* if there is a client let them know */
341  }
342  if (k == 2) return(2);
343  siod_ctrl_c = FALSE;
344  if (want_sigint) signal(SIGINT,handle_sigint);
346  catch_framep = (struct catch_frame *) NULL;
347  errjmp_ok = 1;
348  interrupt_differed = 0;
349  nointerrupt = 0;
350  if (want_init && init_file && (k == 0)) vload(init_file,0);
351  // Can't see where else to put this
352  if ((siod_interactive) && (!isatty(0)))
353  { // editline (or its replacement) would do this if stdin was a terminal
354  fprintf(stdout,"%s",repl_prompt);
355  fflush(stdout);
356  }
357  if (!h)
358  {hd.repl_puts = repl_puts;
359  hd.repl_read = repl_read;
360  hd.repl_eval = repl_eval;
361  hd.repl_print = repl_print;
362  return(repl(&hd));}
363  else
364  return(repl(h));}
365 
366 static void ignore_puts(char *st)
367 {(void)st;}
368 
369 static void noprompt_puts(char *st)
370 {if (strcmp(st,"> ") != 0)
371  put_st(st);}
372 
373 static char *repl_c_string_arg = NULL;
374 static long repl_c_string_flag = 0;
375 
376 static LISP repl_c_string_read(void)
377 {LISP s;
378  if (repl_c_string_arg == NULL)
379  return(eof_val);
380  s = strcons(strlen(repl_c_string_arg),repl_c_string_arg);
381  repl_c_string_arg = NULL;
382  return(read_from_string(get_c_string(s)));}
383 
384 static void ignore_print(LISP x)
385 {(void)x;
386  repl_c_string_flag = 1;}
387 
388 static void not_ignore_print(LISP x)
389 {repl_c_string_flag = 1;
390  pprint(x);}
391 
392 long repl_c_string(char *str,
393  long want_sigint,long want_init,long want_print)
394 {struct repl_hooks h;
395  long retval;
396  if (want_print)
397  h.repl_puts = noprompt_puts;
398  else
399  h.repl_puts = ignore_puts;
400  h.repl_read = repl_c_string_read;
401  h.repl_eval = NULL;
402  if (want_print)
403  h.repl_print = not_ignore_print;
404  else
405  h.repl_print = ignore_print;
406  repl_c_string_arg = str;
407  repl_c_string_flag = 0;
408  retval = repl_driver(want_sigint,want_init,&h);
409  if (retval != 0)
410  return(retval);
411  else if (repl_c_string_flag == 1)
412  return(0);
413  else
414  return(2);}
415 
416 #ifdef __unix__
417 #include <sys/types.h>
418 #include <sys/times.h>
419 double myruntime(void)
420 {double total;
421  struct tms b;
422  times(&b);
423  total = b.tms_utime;
424  total += b.tms_stime;
425  return(total / 60.0);}
426 #else
427 #if defined(WIN32) | defined(VMS)
428 #ifndef CLOCKS_PER_SEC
429 #define CLOCKS_PER_SEC CLK_TCK
430 #endif
431 double myruntime(void)
432 {return(((double) clock()) / ((double) CLOCKS_PER_SEC));}
433 #else
434 double myruntime(void)
435 {time_t x;
436  time(&x);
437  return((double) x);}
438 #endif
439 #endif
440 
441 void set_repl_hooks(void (*puts_f)(char *),
442  LISP (*read_f)(void),
443  LISP (*eval_f)(LISP),
444  void (*print_f)(LISP))
445 {repl_puts = puts_f;
446  repl_read = read_f;
447  repl_eval = eval_f;
448  repl_print = print_f;}
449 
450 void fput_st(FILE *f,const char *st)
451 {long flag;
452  if (f != NULL) /* so we can block warning messages easily */
453  {
454  flag = no_interrupt(1);
455  fprintf(f,"%s",st);
456  no_interrupt(flag);
457  }
458 }
459 
460 void put_st(const char *st)
461 {fput_st(stdout,st);}
462 
463 void grepl_puts(char *st,void (*repl_putss)(char *))
464 {if (repl_putss == NULL)
465  {fput_st(fwarn,st);
466  if (fwarn != NULL) fflush(stdout);}
467  else
468  (*repl_putss)(st);}
469 
470 static void display_backtrace(LISP args)
471 {
472  /* Display backtrace information */
473  LISP l;
474  int i;
475  int local_show_backtrace = show_backtrace;
476  show_backtrace = 0; // so we don't recurse if an error occurs
477 
478  if (cdr(args) == NIL)
479  {
480  printf("BACKTRACE:\n");
481  for (i=0,l=siod_backtrace; l != NIL; l=cdr(l),i++)
482  {
483  fprintf(stdout,"%4d: ",i);
484  pprintf(stdout,car(l),3,72,2,2);
485  fprintf(stdout,"\n");
486  }
487  }
488  else if (FLONUMP(car(cdr(args))))
489  {
490  printf("BACKTRACE:\n");
491  int nth = (int)FLONM(car(cdr(args)));
492  LISP frame = siod_nth(nth,siod_backtrace);
493  fprintf(stdout,"%4d: ",nth);
494  pprintf(stdout,frame,3,72,-1,-1);
495  fprintf(stdout,"\n");
496  }
497 
498  show_backtrace = local_show_backtrace;
499 }
500 
501 static long repl(struct repl_hooks *h)
502 {LISP x,cw = 0;
503  double rt;
504  gc_kind_copying = 0;
505  while(1)
506  {
507 #if 0
508  if ((gc_kind_copying == 1) && ((gc_status_flag) || heap >= heap_end))
509  {rt = myruntime();
511  sprintf(tkbuffer,
512  "GC took %g seconds, %ld compressed to %ld, %ld free\n",
514  (long)(heap-heap_org),(long)(heap_end-heap));
516  /* grepl_puts("> ",h->repl_puts); */
517 #endif
518  if (h->repl_read == NULL)
519  x = lread();
520  else
521  x = (*h->repl_read)();
522  if EQ(x,eof_val) break;
523  rt = myruntime();
524  if (gc_kind_copying == 1)
525  cw = heap;
526  else
527  {gc_cells_allocated = 0;
528  gc_time_taken = 0.0;}
529  /* Check if its a debugger command */
530  if ((TYPE(x) == tc_cons) &&
531  (TYPE(car(x)) == tc_symbol) &&
532  (streq(":backtrace",get_c_string(car(x)))))
533  {
534  display_backtrace(x);
535  x = NIL;
536  }
537  else if ((restricted != NIL) &&
538  (restricted_function_call(x) == FALSE))
539  err("Expression contains functions not in restricted list",x);
540  else
541  {
542  siod_backtrace = NIL; /* reset backtrace info */
543  if (h->repl_eval == NULL)
544  x = leval(x,NIL);
545  else
546  x = (*h->repl_eval)(x);
547  }
548  if (gc_kind_copying == 1)
549  sprintf(tkbuffer,
550  "Evaluation took %g seconds %ld cons work\n",
551  myruntime()-rt,
552  (long)(heap-cw));
553  else
554  sprintf(tkbuffer,
555  "Evaluation took %g seconds (%g in gc) %ld cons work\n",
556  myruntime()-rt,
560  setvar(rintern("!"),x,NIL); /* save value in var called '!' */
561  if (h->repl_print == NULL)
562  {
563  if (siod_interactive)
564  pprint(x); /* pretty print the result */
565  }
566  else
567  (*h->repl_print)(x);}
568  return(0);}
569 
570 void set_fatal_exit_hook(void (*fcn)(void))
571 {fatal_exit_hook = fcn;}
572 
573 static void err(const char *message, LISP x, const char *s)
574 {
575  nointerrupt = 1;
576  if NNULLP(x)
577  {
578  fprintf(stderr,"SIOD ERROR: %s %s: ",
579  (message) ? message : "?",
580  (s) ?s : ""
581  );
582  lprin1f(x,stderr);
583  fprintf(stderr,"\n");
584  fflush(stderr);
585  }
586  else
587  {
588  fprintf(stderr,"SIOD ERROR: %s %s\n",
589  (message) ? message : "?",
590  (s) ? s : ""
591  );
592  fflush(stderr);
593  }
594 
595  if (show_backtrace == 1)
596  display_backtrace(NIL);
597 
598  if (errjmp_ok == 1) {setvar(sym_errobj,x,NIL); longjmp(*est_errjmp,1);}
599  close_open_files(); /* can give clue to where error is */
600  fprintf(stderr,"%s: fatal error exiting.\n",siod_prog_name);
601  if (fatal_exit_hook) {
602  (*fatal_exit_hook)();
603 
604  }
605  exit(1);
606 }
607 
608 void err(const char *message, LISP x)
609 {
610  err(message, x, NULL);
611 }
612 
613 void err(const char *message, const char *x)
614 {
615  err(message, NULL, x);
616 }
617 
618 void errswitch(void)
619 {err("BUG. Reached impossible case",NIL);}
620 
621 void err_stack(char *ptr)
622  /* The user could be given an option to continue here */
623 {(void)ptr;
624  err("the currently assigned stack limit has been exceeded",NIL);}
625 
626 LISP stack_limit(LISP amount,LISP silent)
627 {if NNULLP(amount)
628  {stack_size = get_c_int(amount);
630  if NULLP(silent)
631  {sprintf(tkbuffer,"Stack_size = %ld bytes, [%p,%p]\n",
632  stack_size,(void *)stack_start_ptr,(void *)stack_limit_ptr);
633  put_st(tkbuffer);
634  return(NIL);}
635  else
636  return(flocons(stack_size));}
637 
638 const char *get_c_string(LISP x)
639 {
640  if (NULLP(x))
641  return "nil";
642  else if TYPEP(x,tc_symbol)
643  return(PNAME(x));
644  else if TYPEP(x,tc_flonum)
645  {
646  if (FLONMPNAME(x) == NULL)
647  {
648  char b[TKBUFFERN];
649  sprintf(b,"%.8g",FLONM(x));
650  FLONMPNAME(x) = (char *)must_malloc(strlen(b)+1);
651  sprintf(FLONMPNAME(x),"%s",b);
652  }
653  return FLONMPNAME(x);
654  }
655  else if TYPEP(x,tc_string)
656  return(x->storage_as.string.data);
657  else
658  err("not a symbol or string",x);
659  return(NULL);}
660 
661 LISP lerr(LISP message, LISP x)
662 {err(get_c_string(message),x);
663  return(NIL);}
664 
665 void gc_fatal_error(void)
666 {err("ran out of storage",NIL);}
667 
668 LISP newcell(long type)
669 {LISP z;
670  NEWCELL(z,type);
671  return(z);}
672 
673 LISP flocons(double x)
674 {LISP z;
675  long n=0;
676  if ((inums_dim > 0) &&
677  ((x - (n = (long)x)) == 0) &&
678  (x >= 0) &&
679  (n < inums_dim))
680  return(inums[n]);
681  NEWCELL(z,tc_flonum);
682  FLONMPNAME(z) = NULL;
683  FLONM(z) = x;
684  return(z);}
685 
686 LISP symcons(char *pname,LISP vcell)
687 {LISP z;
688  NEWCELL(z,tc_symbol);
689  PNAME(z) = pname;
690  VCELL(z) = vcell;
691  return(z);}
692 
693 char *must_malloc(unsigned long size)
694 {char *tmp;
695  tmp = walloc(char,size);
696  if (tmp == (char *)NULL) err("failed to allocate storage from system",NIL);
697  return(tmp);}
698 
699 LISP gen_intern(char *name,int require_copy)
700 {LISP l,sym,sl;
701  const unsigned char *cname;
702  long hash=0,n,c,flag;
703  flag = no_interrupt(1);
704  if (name == NULL)
705  return NIL;
706  else if (obarray_dim > 1)
707  {hash = 0;
708  n = obarray_dim;
709  cname = (unsigned char *)name;
710  while((c = *cname++)) hash = ((hash * 17) ^ c) % n;
711  sl = obarray[hash];}
712  else
713  sl = oblistvar;
714  for(l=sl;NNULLP(l);l=CDR(l))
715  if (strcmp(name,PNAME(CAR(l))) == 0)
716  {no_interrupt(flag);
717  return(CAR(l));}
718  /* Need a new symbol */
719  if (require_copy)
720  sym = symcons(wstrdup(name),unbound_marker);
721  else
722  sym = symcons(name,unbound_marker);
723  if (obarray_dim > 1) obarray[hash] = cons(sym,sl);
724  oblistvar = cons(sym,oblistvar);
725  no_interrupt(flag);
726  return(sym);}
727 
728 LISP cintern(const char *name)
729 {
730  char *dname = (char *)(void *)name;
731  return(gen_intern(dname,FALSE));
732 }
733 
734 LISP rintern(const char *name)
735 {
736  if (name == 0)
737  return NIL;
738  char *dname = (char *)(void *)name;
739  return gen_intern(dname,TRUE);
740 }
741 
742 LISP intern(LISP name)
743 {return(rintern(get_c_string(name)));}
744 
745 LISP subrcons(long type, const char *name, SUBR_FUNC f)
746 {LISP z;
747  NEWCELL(z,type);
748  (*z).storage_as.subr.name = name;
749  (*z).storage_as.subr0.f = f;
750  return(z);}
751 
752 LISP closure(LISP env,LISP code)
753 {LISP z;
754  NEWCELL(z,tc_closure);
755  (*z).storage_as.closure.env = env;
756  (*z).storage_as.closure.code = code;
757  return(z);}
758 
759 void gc_unprotect(LISP *location)
760 {
761  /* allow LISP values in a location top be gc'ed again */
762  struct gc_protected *reg,*l;
763  for(l=0,reg = protected_registers; reg; reg = reg->next)
764  {
765  if (reg->location == location)
766  break;
767  l = reg;
768  }
769  if (reg == 0)
770  {
771  fprintf(stderr,"Cannot unprotected %lx: never protected\n",
772  (unsigned long)*location);
773  fflush(stderr);
774  }
775  else if (l==0) /* its the first one in the list that needs to be deleted */
776  {
777  reg = protected_registers;
778  protected_registers = reg->next;
779  wfree(reg);
780  }
781  else
782  {
783  reg = l->next;
784  l->next = reg->next;
785  wfree(reg);
786  }
787 
788  return;
789 }
790 
791 void gc_protect(LISP *location)
792 {
793  struct gc_protected *reg;
794  for(reg = protected_registers; reg; reg = reg->next)
795  {
796  if (reg->location == location)
797  return; // already protected
798  }
799  // not protected so add it
800  gc_protect_n(location,1);
801 }
802 
803 void gc_protect_n(LISP *location,long n)
804 {struct gc_protected *reg;
805  reg = (struct gc_protected *) must_malloc(sizeof(struct gc_protected));
806  (*reg).location = location;
807  (*reg).length = n;
808  (*reg).next = protected_registers;
809  protected_registers = reg;}
810 
811 void gc_protect_sym(LISP *location,const char *st)
812 {*location = cintern(st);
813  gc_protect(location);}
814 
815 void scan_registers(void)
816 {struct gc_protected *reg;
817  LISP *location;
818  long j,n;
819  for(reg = protected_registers; reg; reg = (*reg).next)
820  {location = (*reg).location;
821  n = (*reg).length;
822  for(j=0;j<n;++j)
823  location[j] = gc_relocate(location[j]);}}
824 
825 static void init_storage_1(int init_heap_size)
826 {LISP ptr,next,end;
827  long j;
828  tkbuffer = (char *) must_malloc(TKBUFFERN+1);
829  heap_1 = (LISP) must_malloc(sizeof(struct obj)*init_heap_size);
830  heap = heap_1;
831  which_heap = 1;
832  heap_org = heap;
833  heap_end = heap + init_heap_size;
834  if (gc_kind_copying == 1)
835  heap_2 = (LISP) must_malloc(sizeof(struct obj)*init_heap_size);
836  else
837  {ptr = heap_org;
838  end = heap_end;
839  while(1)
840  {(*ptr).type = tc_free_cell;
841  next = ptr + 1;
842  if (next < end)
843  {CDR(ptr) = next;
844  ptr = next;}
845  else
846  {CDR(ptr) = NIL;
847  break;}}
848  freelist = heap_org;}
850  gc_protect(&siod_backtrace);
852  if (obarray_dim > 1)
853  {obarray = (LISP *) must_malloc(sizeof(LISP) * obarray_dim);
854  for(j=0;j<obarray_dim;++j)
855  obarray[j] = NIL;
856  gc_protect_n(obarray,obarray_dim);}
857  unbound_marker = cons(cintern("**unbound-marker**"),NIL);
859  eof_val = cons(cintern("eof"),NIL);
862  gc_protect_sym(&truth,"t");
864  setvar(cintern("nil"),NIL,NIL);
865  setvar(cintern("let"),cintern("let-internal-macro"),NIL);
866  gc_protect_sym(&sym_errobj,"errobj");
868  gc_protect_sym(&sym_quote,"quote");
869  gc_protect_sym(&sym_dot,".");
871  if (inums_dim > 0)
872  {inums = (LISP *) must_malloc(sizeof(LISP) * inums_dim);
873  for(j=0;j<inums_dim;++j)
874  {NEWCELL(ptr,tc_flonum);
875  FLONM(ptr) = j;
876  FLONMPNAME(ptr) = NULL;
877  inums[j] = ptr;}
878  gc_protect_n(inums,inums_dim);}}
879 
880 void init_storage(int init_heap_size)
881 {
882  init_storage_1(init_heap_size);
883  LISP stack_start;
884  stack_start_ptr = &stack_start;
886 }
887 
888 void init_subr(const char *name, long type, SUBR_FUNC fcn)
889 {setvar(cintern(name),subrcons(type,name,fcn),NIL);}
890 void init_subr(const char *name, long type, SUBR_FUNC fcn,const char *doc)
891 {LISP lname = cintern(name);
892  setvar(lname,subrcons(type,name,fcn),NIL);
893  setdoc(lname,cstrcons(doc));}
894 
895 /* New versions requiring documentation strings */
896 void init_subr_0(const char *name, LISP (*fcn)(void),const char *doc)
897 {init_subr(name,tc_subr_0,(SUBR_FUNC)fcn,doc);}
898 void init_subr_1(const char *name, LISP (*fcn)(LISP),const char *doc)
899 {init_subr(name,tc_subr_1,(SUBR_FUNC)fcn,doc);}
900 void init_subr_2(const char *name, LISP (*fcn)(LISP,LISP),const char *doc)
901 {init_subr(name,tc_subr_2,(SUBR_FUNC)fcn,doc);}
902 void init_subr_3(const char *name, LISP (*fcn)(LISP,LISP,LISP),const char *doc)
903 {init_subr(name,tc_subr_3,(SUBR_FUNC)fcn,doc);}
904 void init_subr_4(const char *name, LISP (*fcn)(LISP,LISP,LISP,LISP),const char *doc)
905 {init_subr(name,tc_subr_4,(SUBR_FUNC)fcn,doc);}
906 void init_lsubr(const char *name, LISP (*fcn)(LISP),const char *doc)
907 {init_subr(name,tc_lsubr,(SUBR_FUNC)fcn,doc);}
908 void init_fsubr(const char *name, LISP (*fcn)(LISP,LISP),const char *doc)
909 {init_subr(name,tc_fsubr,(SUBR_FUNC)fcn,doc);}
910 void init_msubr(const char *name, LISP (*fcn)(LISP *,LISP *),const char *doc)
911 {init_subr(name,tc_msubr,(SUBR_FUNC)fcn,doc);}
912 
914 {long n;
915  if (user_types == NULL)
916  {n = sizeof(struct user_type_hooks) * tc_table_dim;
917  user_types = (struct user_type_hooks *) must_malloc(n);
918  memset(user_types,0,n);}
919  if ((type >= 0) && (type < tc_table_dim))
920  return(&user_types[type]);
921  else
922  err("type number out of range",NIL);
923  return(NULL);}
924 
925 int siod_register_user_type(const char *name)
926 {
927  // Register a new object type for LISP
928  static int siod_user_type = tc_first_user_type;
929  int new_type = siod_user_type;
930  struct user_type_hooks *th;
931 
932  if (new_type == tc_table_dim)
933  {
934  cerr << "SIOD: no more new types allowed, tc_table_dim needs increased"
935  << endl;
936  return tc_table_dim-1;
937  }
938  else
939  siod_user_type++;
940 
941  th=get_user_type_hooks(new_type);
942  th->name = wstrdup(name);
943  return new_type;
944 }
945 
946 void set_gc_hooks(long type,
947  int gc_free_once,
948  LISP (*rel)(LISP),
949  LISP (*mark)(LISP),
950  void (*scan)(LISP),
951  void (*free)(LISP),
952  void (*clear)(LISP),
953  long *kind)
954 {struct user_type_hooks *p;
955  p = get_user_type_hooks(type);
957  p->gc_relocate = rel;
958  p->gc_scan = scan;
959  p->gc_mark = mark;
960  p->gc_free = free;
961  p->gc_clear = clear;
962  *kind = gc_kind_copying;}
963 
964 LISP gc_relocate(LISP x)
965 {LISP nw;
966  struct user_type_hooks *p;
967  if EQ(x,NIL) return(NIL);
968  if ((*x).gc_mark == 1) return(CAR(x));
969  switch TYPE(x)
970  {case tc_flonum:
971  if (FLONMPNAME(x) != NULL)
972  wfree(FLONMPNAME(x)); /* free the print name */
973  FLONMPNAME(x) = NULL;
974  case tc_cons:
975  case tc_symbol:
976  case tc_closure:
977  case tc_subr_0:
978  case tc_subr_1:
979  case tc_subr_2:
980  case tc_subr_3:
981  case tc_subr_4:
982  case tc_lsubr:
983  case tc_fsubr:
984  case tc_msubr:
985  if ((nw = heap) >= heap_end) gc_fatal_error();
986  heap = nw+1;
987  memcpy(nw,x,sizeof(struct obj));
988  break;
989  default:
990  p = get_user_type_hooks(TYPE(x));
991  if (p->gc_relocate)
992  nw = (*p->gc_relocate)(x);
993  else
994  {if ((nw = heap) >= heap_end) gc_fatal_error();
995  heap = nw+1;
996  memcpy(nw,x,sizeof(struct obj));}}
997  (*x).gc_mark = 1;
998  CAR(x) = nw;
999  return(nw);}
1000 
1001 LISP get_newspace(void)
1002 {LISP newspace;
1003  if (which_heap == 1)
1004  {newspace = heap_2;
1005  which_heap = 2;}
1006  else
1007  {newspace = heap_1;
1008  which_heap = 1;}
1009  heap = newspace;
1010  heap_org = heap;
1011  heap_end = heap + heap_size;
1012  return(newspace);}
1013 
1014 void scan_newspace(LISP newspace)
1015 {LISP ptr;
1016  struct user_type_hooks *p;
1017  for(ptr=newspace; ptr < heap; ++ptr)
1018  {switch TYPE(ptr)
1019  {case tc_cons:
1020  case tc_closure:
1021  CAR(ptr) = gc_relocate(CAR(ptr));
1022  CDR(ptr) = gc_relocate(CDR(ptr));
1023  break;
1024  case tc_symbol:
1025  VCELL(ptr) = gc_relocate(VCELL(ptr));
1026  break;
1027  case tc_flonum:
1028  case tc_subr_0:
1029  case tc_subr_1:
1030  case tc_subr_2:
1031  case tc_subr_3:
1032  case tc_subr_4:
1033  case tc_lsubr:
1034  case tc_fsubr:
1035  case tc_msubr:
1036  break;
1037  default:
1038  p = get_user_type_hooks(TYPE(ptr));
1039  if (p->gc_scan) (*p->gc_scan)(ptr);}}}
1040 
1041 void free_oldspace(LISP space,LISP end)
1042 {LISP ptr;
1043  struct user_type_hooks *p;
1044  for(ptr=space; ptr < end; ++ptr)
1045  if (ptr->gc_mark == 0)
1046  switch TYPE(ptr)
1047  {case tc_cons:
1048  case tc_closure:
1049  case tc_symbol:
1050  break;
1051  case tc_flonum:
1052  if (FLONMPNAME(ptr) != NULL)
1053  wfree(FLONMPNAME(ptr)); /* free the print name */
1054  FLONMPNAME(ptr) = NULL;
1055  break;
1056  case tc_string:
1057  wfree(ptr->storage_as.string.data);
1058  break;
1059  case tc_subr_0:
1060  case tc_subr_1:
1061  case tc_subr_2:
1062  case tc_subr_3:
1063  case tc_subr_4:
1064  case tc_lsubr:
1065  case tc_fsubr:
1066  case tc_msubr:
1067  break;
1068  default:
1069  p = get_user_type_hooks(TYPE(ptr));
1070  if (p->gc_free)
1071  (*p->gc_free)(ptr);
1072  }
1073 }
1074 
1076 {LISP newspace,oldspace,end;
1077  long flag;
1078  int ej_ok;
1079  flag = no_interrupt(1);
1080  fprintf(stderr,"GC ing \n");
1081  ej_ok = errjmp_ok;
1082  errjmp_ok = 0;
1083  oldspace = heap_org;
1084  end = heap;
1085  old_heap_used = end - oldspace;
1086  newspace = get_newspace();
1087  scan_registers();
1088  scan_newspace(newspace);
1089  free_oldspace(oldspace,end);
1090  errjmp_ok = ej_ok;
1091  no_interrupt(flag);}
1092 
1093 void gc_for_newcell(void)
1094 {long flag;
1095  int ej_ok;
1096 /* if (errjmp_ok == 0) gc_fatal_error(); */
1097  flag = no_interrupt(1);
1098  ej_ok = errjmp_ok;
1099  errjmp_ok = 0;
1100  gc_mark_and_sweep();
1101  errjmp_ok = ej_ok;
1102  no_interrupt(flag);
1103  if NULLP(freelist) gc_fatal_error();}
1104 
1105 static void gc_mark_and_sweep(void)
1106 {LISP stack_end;
1107  gc_ms_stats_start();
1108  if (setjmp(save_regs_gc_mark)) {
1109  fprintf(stderr, "[GC mark and sweep: setjmp failed: Aborting GC collection]\n");
1110  gc_ms_stats_end();
1111  return;
1112  }
1113  mark_locations((LISP *) save_regs_gc_mark,
1114  (LISP *) (((char *) save_regs_gc_mark) + sizeof(save_regs_gc_mark)));
1115  mark_protected_registers();
1116  mark_locations((LISP *) stack_start_ptr,
1117  (LISP *) &stack_end);
1118  gc_sweep();
1119  gc_ms_stats_end();}
1120 
1121 static void gc_ms_stats_start(void)
1122 {gc_rt = myruntime();
1123  gc_cells_collected = 0;
1124  if (gc_status_flag)
1125  fprintf(stderr,"[starting GC]\n");}
1126 
1127 static void gc_ms_stats_end(void)
1128 {gc_rt = myruntime() - gc_rt;
1130  if (gc_status_flag)
1131  fprintf(stderr,"[GC took %g cpu seconds, %ld cells collected]\n",
1132  gc_rt,
1134 
1135 void gc_mark(LISP ptr)
1136 {struct user_type_hooks *p;
1137 
1138  gc_mark_loop:
1139  if NULLP(ptr) return;
1140  if ((*ptr).gc_mark) return;
1141  (*ptr).gc_mark = 1;
1142  switch ((*ptr).type)
1143  {case tc_flonum:
1144  break;
1145  case tc_cons:
1146  gc_mark(CAR(ptr));
1147  ptr = CDR(ptr);
1148  goto gc_mark_loop;
1149  case tc_symbol:
1150  ptr = VCELL(ptr);
1151  goto gc_mark_loop;
1152  case tc_closure:
1153  gc_mark((*ptr).storage_as.closure.code);
1154  ptr = (*ptr).storage_as.closure.env;
1155  goto gc_mark_loop;
1156  case tc_subr_0:
1157  case tc_subr_1:
1158  case tc_subr_2:
1159  case tc_subr_3:
1160  case tc_subr_4:
1161  break;
1162  case tc_string:
1163  break;
1164  case tc_lsubr:
1165  case tc_fsubr:
1166  case tc_msubr:
1167  break;
1168  default:
1169  p = get_user_type_hooks(TYPE(ptr));
1170  if (p->gc_mark)
1171  (*p->gc_mark)(ptr);}}
1172 
1173 static void mark_protected_registers(void)
1174 {struct gc_protected *reg;
1175  LISP *location;
1176  long j,n;
1177  for(reg = protected_registers; reg; reg = (*reg).next)
1178  {
1179  location = (*reg).location;
1180  n = (*reg).length;
1181  for(j=0;j<n;++j)
1182  gc_mark(location[j]);}}
1183 
1184 static void mark_locations(LISP *start,LISP *end)
1185 {LISP *tmp;
1186  long n;
1187  if (start > end)
1188  {tmp = start;
1189  start = end;
1190  end = tmp;}
1191  n = end - start;
1192  mark_locations_array(start,n);}
1193 
1194 static void mark_locations_array(LISP *x,long n)
1195 {int j;
1196  LISP p;
1197  for(j=0;j<n;++j)
1198  {p = x[j];
1199  if ((p >= heap_org) &&
1200  (p < heap_end) &&
1201  (((((char *)p) - ((char *)heap_org)) % sizeof(struct obj)) == 0) &&
1202  NTYPEP(p,tc_free_cell))
1203  gc_mark(p);}}
1204 
1205 static void gc_sweep(void)
1206 {LISP ptr,end,nfreelist;
1207  long n;
1208  struct user_type_hooks *p;
1209  end = heap_end;
1210  n = 0;
1211  nfreelist = NIL;
1212  start_rememberring_dead();
1213  for(ptr=heap_org; ptr < end; ++ptr)
1214  if (((*ptr).gc_mark) == 0)
1215  {switch((*ptr).type)
1216  {case tc_flonum:
1217  if (FLONMPNAME(ptr) != NULL)
1218  wfree(FLONMPNAME(ptr)); /* free the print name */
1219  FLONMPNAME(ptr) = NULL;
1220  break;
1221  case tc_string:
1222  wfree(ptr->storage_as.string.data);
1223  break;
1224  case tc_free_cell:
1225  case tc_cons:
1226  case tc_closure:
1227  case tc_symbol:
1228  case tc_subr_0:
1229  case tc_subr_1:
1230  case tc_subr_2:
1231  case tc_subr_3:
1232  case tc_subr_4:
1233  case tc_lsubr:
1234  case tc_fsubr:
1235  case tc_msubr:
1236  break;
1237  default:
1238  p = get_user_type_hooks(TYPE(ptr));
1239  if (p->gc_free)
1240  {
1241  if (p->gc_free_once)
1242  {
1243  if (!is_dead(USERVAL(ptr)))
1244  {
1245  (*p->gc_free)(ptr);
1246  mark_as_dead(USERVAL(ptr));
1247  }
1248  }
1249  else
1250  (*p->gc_free)(ptr);
1251  }
1252  }
1253  ++n;
1254  (*ptr).type = tc_free_cell;
1255  CDR(ptr) = nfreelist;
1256  nfreelist = ptr;
1257  }
1258  else
1259  {
1260  (*ptr).gc_mark = 0;
1261  p = get_user_type_hooks(TYPE(ptr));
1262  if (p->gc_clear)
1263  (*p->gc_clear)(ptr);
1264  }
1265  gc_cells_collected = n;
1266  freelist = nfreelist;
1267 }
1268 
1269 LISP user_gc(LISP args)
1270 {long old_status_flag,flag;
1271  int ej_ok;
1272  if (gc_kind_copying == 1)
1273  err("implementation cannot GC at will with stop-and-copy\n",
1274  NIL);
1275  flag = no_interrupt(1);
1276  ej_ok = errjmp_ok;
1277  errjmp_ok = 0;
1278  old_status_flag = gc_status_flag;
1279  if NNULLP(args)
1280  {
1281  if NULLP(car(args))
1282  gc_status_flag = 0;
1283  else
1284  gc_status_flag = 1;
1285  }
1286  gc_mark_and_sweep();
1287  gc_status_flag = old_status_flag;
1288  errjmp_ok = ej_ok;
1289  no_interrupt(flag);
1290 
1291  return(NIL);}
1292 
1293 LISP set_backtrace(LISP n)
1294 {
1295  if (n)
1296  show_backtrace = 1;
1297  else
1298  show_backtrace = 0;
1299  return n;
1300 }
1301 
1302 LISP gc_status(LISP args)
1303 {LISP l;
1304  int n;
1305  if NNULLP(args)
1306  {
1307  if NULLP(car(args)) gc_status_flag = 0; else gc_status_flag = 1;
1308  }
1309  if (gc_kind_copying == 1)
1310  {if (gc_status_flag)
1311  fput_st(fwarn,"garbage collection is on\n");
1312  else
1313  fput_st(fwarn,"garbage collection is off\n");
1314  sprintf(tkbuffer,"%ld allocated %ld free\n",
1315  (long)(heap - heap_org),(long)(heap_end - heap));
1317  else
1318  {if (gc_status_flag)
1319  fput_st(fwarn,"garbage collection verbose\n");
1320  else
1321  fput_st(fwarn,"garbage collection silent\n");
1322  {for(n=0,l=freelist;NNULLP(l); ++n) l = CDR(l);
1323  sprintf(tkbuffer,"%ld allocated %ld free\n",
1324  (long)((heap_end - heap_org) - n),(long)n);
1325  fput_st(fwarn,tkbuffer);}}
1326  return(NIL);}
1327 
1328 LISP leval_args(LISP l,LISP env)
1329 {LISP result,v1,v2,tmp;
1330  if NULLP(l) return(NIL);
1331  if NCONSP(l) err("bad syntax argument list",l);
1332  result = cons(leval(CAR(l),env),NIL);
1333  for(v1=result,v2=CDR(l);
1334  CONSP(v2);
1335  v1 = tmp, v2 = CDR(v2))
1336  {tmp = cons(leval(CAR(v2),env),NIL);
1337  CDR(v1) = tmp;}
1338  if NNULLP(v2) err("bad syntax argument list",l);
1339  return(result);}
1340 
1341 LISP extend_env(LISP actuals,LISP formals,LISP env)
1342 {
1343  if SYMBOLP(formals)
1344  return(cons(cons(cons(formals,NIL),cons(actuals,NIL)),env));
1345  else
1346  return(cons(cons(formals,actuals),env));
1347 }
1348 
1349 #define ENVLOOKUP_TRICK 1
1352 
1353 LISP envlookup(LISP var,LISP env)
1354 {LISP frame,al,fl,tmp;
1355  global_var = var;
1356  global_env = env;
1357  for(frame=env;CONSP(frame);frame=CDR(frame))
1358  {tmp = CAR(frame);
1359  if NCONSP(tmp) err("damaged frame",tmp);
1360  for(fl=CAR(tmp),al=CDR(tmp);CONSP(fl);fl=CDR(fl),al=CDR(al))
1361  {if NCONSP(al) err("too few arguments",tmp);
1362  if EQ(CAR(fl),var) return(al);}
1363  /* suggested by a user. It works for reference (although conses)
1364  but doesn't allow for set! to work properly... */
1365 #if (ENVLOOKUP_TRICK)
1366  if (SYMBOLP(fl) && EQ(fl, var)) return(cons(al, NIL));
1367 #endif
1368  }
1369  if NNULLP(frame)
1370  err("damaged env",env);
1371  return(NIL);}
1372 
1373 void set_eval_hooks(long type,LISP (*fcn)(LISP, LISP *,LISP *))
1374 {struct user_type_hooks *p;
1375  p = get_user_type_hooks(type);
1376  p->leval = fcn;}
1377 
1378 LISP leval(LISP x,LISP qenv)
1379 {LISP tmp,arg1,rval;
1380  LISP env;
1381  struct user_type_hooks *p;
1382  env = qenv;
1383  STACK_CHECK(&x);
1384  siod_backtrace = cons(x,siod_backtrace);
1385  loop:
1386  INTERRUPT_CHECK();
1387  current_env = env;
1388  switch TYPE(x)
1389  {case tc_symbol:
1390  tmp = envlookup(x,env);
1391  if NNULLP(tmp)
1392  {
1393  siod_backtrace = cdr(siod_backtrace);
1394  return(CAR(tmp));
1395  }
1396  tmp = VCELL(x);
1397  if EQ(tmp,unbound_marker) err("unbound variable",x);
1398  siod_backtrace = cdr(siod_backtrace);
1399  return tmp;
1400  case tc_cons:
1401  tmp = CAR(x);
1402  switch TYPE(tmp)
1403  {case tc_symbol:
1404  tmp = envlookup(tmp,env);
1405  if NNULLP(tmp)
1406  {tmp = CAR(tmp);
1407  break;}
1408  tmp = VCELL(CAR(x));
1409  if EQ(tmp,unbound_marker) err("unbound variable",CAR(x));
1410  break;
1411  case tc_cons:
1412  tmp = leval(tmp,env);
1413  break;}
1414  switch TYPE(tmp)
1415  {case tc_subr_0:
1416  rval = SUBR0(tmp)();
1417  siod_backtrace = cdr(siod_backtrace);
1418  return rval;
1419  case tc_subr_1:
1420  rval = SUBR1(tmp)(leval(car(CDR(x)),env));
1421  siod_backtrace = cdr(siod_backtrace);
1422  return rval;
1423  case tc_subr_2:
1424  x = CDR(x);
1425  arg1 = leval(car(x),env);
1426  x = NULLP(x) ? NIL : CDR(x);
1427  rval = SUBR2(tmp)(arg1,leval(car(x),env));
1428  siod_backtrace = cdr(siod_backtrace);
1429  return rval;
1430  case tc_subr_3:
1431  x = CDR(x);
1432  arg1 = leval(car(x),env);
1433  x = NULLP(x) ? NIL : CDR(x);
1434  rval = SUBR3(tmp)(arg1,leval(car(x),env),leval(car(cdr(x)),env));
1435  siod_backtrace = cdr(siod_backtrace);
1436  return rval;
1437  case tc_subr_4:
1438  x = CDR(x);
1439  arg1 = leval(car(x),env);
1440  x = NULLP(x) ? NIL : CDR(x);
1441  rval = SUBR4(tmp)(arg1,leval(car(x),env),
1442  leval(car(cdr(x)),env),
1443  leval(car(cdr(cdr(x))),env));
1444  siod_backtrace = cdr(siod_backtrace);
1445  return rval;
1446  case tc_lsubr:
1447  rval = SUBR1(tmp)(leval_args(CDR(x),env));
1448  siod_backtrace = cdr(siod_backtrace);
1449  return rval;
1450  case tc_fsubr:
1451  rval = SUBR2(tmp)(CDR(x),env);
1452  siod_backtrace = cdr(siod_backtrace);
1453  return rval;
1454  case tc_msubr:
1455  if NULLP(SUBRM(tmp)(&x,&env))
1456  {
1457  siod_backtrace = cdr(siod_backtrace);
1458  return(x);
1459  }
1460  goto loop;
1461  case tc_closure:
1462  env = extend_env(leval_args(CDR(x),env),
1463  car((*tmp).storage_as.closure.code),
1464  (*tmp).storage_as.closure.env);
1465  x = cdr((*tmp).storage_as.closure.code);
1466  goto loop;
1467  case tc_symbol:
1468  x = cons(tmp,cons(cons(sym_quote,cons(x,NIL)),NIL));
1469  x = leval(x,NIL);
1470  goto loop;
1471  default:
1472  p = get_user_type_hooks(TYPE(tmp));
1473  if (p->leval)
1474  {if NULLP((*p->leval)(tmp,&x,&env))
1475  {
1476  siod_backtrace = cdr(siod_backtrace);
1477  return(x);
1478  }
1479  else
1480  goto loop;}
1481  err("bad function",tmp);}
1482  default:
1483  siod_backtrace = cdr(siod_backtrace);
1484  return(x);}}
1485 
1486 void set_print_hooks(long type,
1487  void (*prin1)(LISP, FILE *),
1488  void (*print_string)(LISP, char *)
1489  )
1490 {struct user_type_hooks *p;
1491  p = get_user_type_hooks(type);
1492  p->prin1 = prin1;
1494 }
1495 
1496 void set_io_hooks(long type,
1497  LISP (*fast_print)(LISP,LISP),
1498  LISP (*fast_read)(int,LISP))
1499 
1500 {struct user_type_hooks *p;
1501  p = get_user_type_hooks(type);
1502  p->fast_print = fast_print;
1503  p->fast_read = fast_read;
1504 }
1505 
1506 void set_type_hooks(long type,
1507  long (*c_sxhash)(LISP,long),
1508  LISP (*equal)(LISP,LISP))
1509 
1510 
1511 {struct user_type_hooks *p;
1512  p = get_user_type_hooks(type);
1513  p->c_sxhash = c_sxhash;
1514  p->equal = equal;
1515 }
1516 
1517 int f_getc(FILE *f)
1518 {long iflag;
1519  int c;
1520  iflag = no_interrupt(1);
1521  c = getc(f);
1522  if ((c == '\n') && (f == stdin) && (siod_interactive))
1523  {
1524  fprintf(stdout,"%s",repl_prompt);
1525  fflush(stdout);
1526  }
1527  no_interrupt(iflag);
1528  return(c);}
1529 
1530 void f_ungetc(int c, FILE *f)
1531 {ungetc(c,f);}
1532 
1533 #ifdef WIN32
1534 int winsock_unget_buffer;
1535 bool winsock_unget_buffer_unused=true;
1536 bool use_winsock_unget_buffer;
1537 
1538 int f_getc_winsock(HANDLE h)
1539 {long iflag,dflag;
1540  char c;
1541  DWORD lpNumberOfBytesRead;
1542  iflag = no_interrupt(1);
1543  if (use_winsock_unget_buffer)
1544  {
1545  use_winsock_unget_buffer = false;
1546  return winsock_unget_buffer;
1547  }
1548 
1549  if (SOCKET_ERROR == recv((SOCKET)h,&c,1,0))
1550  {
1551  if (WSAECONNRESET == GetLastError()) // The connection was closed.
1552  c=EOF;
1553  else
1554  cerr << "f_getc_winsock(): error reading from socket\n";
1555  }
1556 
1557  winsock_unget_buffer=c;
1558  winsock_unget_buffer_unused = false;
1559 
1560  no_interrupt(iflag);
1561  return(c);}
1562 
1563 void f_ungetc_winsock(int c, HANDLE h)
1564 {
1565  if (winsock_unget_buffer_unused)
1566  {
1567  cerr << "f_ungetc_winsock: tried to unget before reading socket\n";
1568  }
1569 use_winsock_unget_buffer = true;}
1570 #endif
1571 
1572 int flush_ws(struct gen_readio *f,const char *eoferr)
1573 {int c,commentp;
1574  commentp = 0;
1575  while(1)
1576  {c = GETC_FCN(f);
1577  if (c == EOF) { if (eoferr) err(eoferr,NIL); else return(c); }
1578  if (commentp) {if (c == '\n') commentp = 0;}
1579  else if (c == ';') commentp = 1;
1580  else if (!isspace(c)) return(c);}}
1581 
1582 LISP lreadf(FILE *f)
1583 {struct gen_readio s;
1584  if ((f == stdin) && (isatty(0)) && (siod_interactive))
1585  { /* readline (if selected) stuff -- only works with a terminal */
1586  s.getc_fcn = (int (*)(char *))siod_fancy_getc;
1587  s.ungetc_fcn = (void (*)(int, char *))siod_fancy_ungetc;
1588  s.cb_argument = (char *) f;
1589  }
1590  else /* normal stuff */
1591  {
1592  s.getc_fcn = (int (*)(char *))f_getc;
1593  s.ungetc_fcn = (void (*)(int, char *))f_ungetc;
1594  s.cb_argument = (char *) f;
1595  }
1596  return(readtl(&s));}
1597 
1598 #ifdef WIN32
1599 LISP lreadwinsock(void)
1600 {
1601  struct gen_readio s;
1602  s.getc_fcn = (int (*)(char *))f_getc_winsock;
1603  s.ungetc_fcn = (void (*)(int, char *))f_ungetc_winsock;
1604  s.cb_argument = (char *) siod_server_socket;
1605  return(readtl(&s));}
1606 #endif
1607 
1608 LISP readtl(struct gen_readio *f)
1609 {int c;
1610  c = flush_ws(f,(char *)NULL);
1611  if (c == EOF) return(eof_val);
1612  UNGETC_FCN(c,f);
1613  return(lreadr(f));}
1614 
1615 void set_read_hooks(char *all_set,char *end_set,
1616  LISP (*fcn1)(int, struct gen_readio *),
1617  LISP (*fcn2)(char *,long, int *))
1618 {user_ch_readm = all_set;
1619  user_te_readm = end_set;
1620  user_readm = fcn1;
1621  user_readt = fcn2;}
1622 
1623 static LISP lreadr(struct gen_readio *f)
1624 {int c,j;
1625  char *p;
1626  const char *pp, *last_prompt;
1627  LISP rval;
1628  STACK_CHECK(&f);
1629  p = tkbuffer;
1630  c = flush_ws(f,"end of file inside read");
1631  switch (c)
1632  {case '(':
1633  last_prompt = repl_prompt;
1635  rval = lreadparen(f);
1636  repl_prompt = last_prompt;
1637  return rval;
1638  case ')':
1639  err("unexpected close paren",NIL);
1640  case '\'':
1641  return(cons(sym_quote,cons(lreadr(f),NIL)));
1642  case '`':
1643  return(cons(cintern("+internal-backquote"),lreadr(f)));
1644  case ',':
1645  c = GETC_FCN(f);
1646  switch(c)
1647  {case '@':
1648  pp = "+internal-comma-atsign";
1649  break;
1650  case '.':
1651  pp = "+internal-comma-dot";
1652  break;
1653  default:
1654  pp = "+internal-comma";
1655  UNGETC_FCN(c,f);}
1656  return(cons(cintern(pp),lreadr(f)));
1657  case '"':
1658  last_prompt = repl_prompt;
1660  rval = lreadstring(f);
1661  repl_prompt = last_prompt;
1662  return rval;
1663  default:
1664  if ((user_readm != NULL) && strchr(user_ch_readm,c))
1665  return((*user_readm)(c,f));}
1666  *p++ = c;
1667  for(j = 1; j<TKBUFFERN; ++j)
1668  {c = GETC_FCN(f);
1669  if (c == EOF) return(lreadtk(j));
1670  if (isspace(c)) return(lreadtk(j));
1671  if (strchr("()'`,;\"",c) || strchr(user_te_readm,c))
1672  {UNGETC_FCN(c,f);return(lreadtk(j));}
1673  *p++ = c;}
1674  err("symbol larger than maxsize (can you use a string instead?)",NIL);}
1675 
1676 #if 0
1677 LISP lreadparen(struct gen_readio *f)
1678 {int c;
1679  LISP tmp;
1680  c = flush_ws(f,"end of file inside list");
1681  if (c == ')') return(NIL);
1682  UNGETC_FCN(c,f);
1683  tmp = lreadr(f);
1684  if EQ(tmp,sym_dot)
1685  {tmp = lreadr(f);
1686  c = flush_ws(f,"end of file inside list");
1687  if (c != ')') err("missing close paren",NIL);
1688  return(tmp);}
1689  return(cons(tmp,lreadparen(f)));}
1690 #endif
1691 
1692 /* Iterative version of the above */
1693 static LISP lreadparen(struct gen_readio *f)
1694 {
1695  int c;
1696  LISP tmp,l=NIL;
1697  LISP last=l;
1698 
1699  while ((c = flush_ws(f,"end of file inside list")) != ')')
1700  {
1701  UNGETC_FCN(c,f);
1702  tmp = lreadr(f);
1703  if EQ(tmp,sym_dot)
1704  {
1705  tmp = lreadr(f);
1706  c = flush_ws(f,"end of file inside list");
1707  if (c != ')') err("missing close paren",NIL);
1708  if (l == NIL) err("no car for dotted pair",NIL);
1709  CDR(last) = tmp;
1710  break;
1711  }
1712  if (l == NIL)
1713  {
1714  l = cons(tmp,NIL);
1715  last = l;
1716  }
1717  else
1718  {
1719  CDR(last) = cons(tmp,NIL);
1720  last = cdr(last);
1721  }
1722  }
1723  return l;
1724 }
1725 
1726 static LISP lreadstring(struct gen_readio *f)
1727 {
1728  int j,c,n;
1729  static int len=TKBUFFERN;
1730  static char *str = 0;
1731  char *q;
1732  LISP qq;
1733  j = 0;
1734  if (str == 0)
1735  str = (char *)must_malloc(len * sizeof(char));
1736  while(((c = GETC_FCN(f)) != '"') && (c != EOF))
1737  {
1738  if (c == '\\')
1739  {c = GETC_FCN(f);
1740  if (c == EOF) err("eof after \\",NIL);
1741  switch(c)
1742  {case 'n':
1743  c = '\n';
1744  break;
1745  case 't':
1746  c = '\t';
1747  break;
1748  case 'r':
1749  c = '\r';
1750  break;
1751  case 'd':
1752  c = 0x04;
1753  break;
1754  case 'N':
1755  c = 0;
1756  break;
1757  case 's':
1758  c = ' ';
1759  break;
1760  case '0':
1761  n = 0;
1762  while(1)
1763  {c = GETC_FCN(f);
1764  if (c == EOF) err("eof after \\0",NIL);
1765  if (isdigit(c))
1766  n = n * 8 + c - '0';
1767  else
1768  {UNGETC_FCN(c,f);
1769  break;}}
1770  c = n;}}
1771  if ((j + 1) >= len)
1772  {
1773  /* EST_String full so double the buffer, copy and continue */
1774  q = (char *)must_malloc(len*2*sizeof(char));
1775  strncpy(q,str,len);
1776  wfree(str);
1777  str = q;
1778  len = len*2;
1779  }
1780  str[j] = c;
1781  ++j;
1782  }
1783  str[j] = 0;
1784  qq = strcons(j,str);
1785  return qq;
1786 }
1787 
1788 LISP lreadtk(long j)
1789 {int flag;
1790  unsigned char *p;
1791  LISP tmp;
1792  int adigit;
1793  p = (unsigned char *)tkbuffer;
1794  p[j] = 0;
1795  if (user_readt != NULL)
1796  {tmp = (*user_readt)((char *)p,j,&flag);
1797  if (flag) return(tmp);}
1798  if (strcmp("nil",tkbuffer) == 0)
1799  return NIL;
1800  if (*p == '-') p+=1;
1801  adigit = 0;
1802  while((*p < 128) && (isdigit(*p))) {p+=1; adigit=1;}
1803  if (*p=='.')
1804  {p += 1;
1805  while((*p < 128) && (isdigit(*p))) {p+=1; adigit=1;}}
1806  if (!adigit) goto a_symbol;
1807  if (*p=='e')
1808  {p+=1;
1809  if (*p=='-'||*p=='+') p+=1;
1810  if ((!isdigit(*p) || (*p > 127))) goto a_symbol; else p+=1;
1811  while((*p < 128) && (isdigit(*p))) p+=1;}
1812  if (*p) goto a_symbol;
1813  return(flocons(atof(tkbuffer)));
1814  a_symbol:
1815  return(rintern(tkbuffer));}
1816 
1817 LISP siod_quit(void)
1818 {open_files = NIL; // will be closed on exit with no warnings
1819  if (errjmp_ok) longjmp(*est_errjmp,2);
1820  else exit(0);
1821  return(NIL);}
1822 
1823 LISP l_exit(LISP arg)
1824 {
1825  if (arg == NIL)
1826  exit(0);
1827  else
1828  exit((int)FLONM(arg));
1829 
1830  // never happens
1831  return NULL;
1832 }
1833 
1834 LISP lfwarning(LISP mode)
1835 {
1836  /* if mode is non-nil switch warnings on */
1837  if (mode == NIL)
1838  fwarn = NULL;
1839  else
1840  fwarn = stdout;
1841  return NIL;
1842 }
1843 
1844 LISP closure_code(LISP exp)
1845 {return(exp->storage_as.closure.code);}
1846 
1847 LISP closure_env(LISP exp)
1848 {return(exp->storage_as.closure.env);}
1849 
1850 long int get_c_int(LISP x)
1851 {if NFLONUMP(x) err("not a number",x);
1852  return((long int)FLONM(x));}
1853 
1854 double get_c_double(LISP x)
1855 {if NFLONUMP(x) err("not a number",x);
1856  return(FLONM(x));}
1857 
1858 float get_c_float(LISP x)
1859 {if NFLONUMP(x) err("not a number",x);
1860  return((float)FLONM(x));}
1861 
1862 
1864 {
1865  init_subr_2("eval",leval,
1866  "(eval DATA)\n\
1867  Evaluate DATA and return result.");
1868  init_lsubr("gc-status",gc_status,
1869  "(gc-status OPTION)\n\
1870  Control summary information during garbage collection. If OPTION is t,\n\
1871  output information at each garbage collection, if nil do gc silently.");
1872  init_lsubr("gc",user_gc,
1873  "(gc)\n\
1874  Collect garbage now, where gc method supports it.");
1875  init_subr_2("error",lerr,
1876  "(error MESSAGE DATA)\n\
1877  Prints MESSAGE about DATA and throws an error.");
1878  init_subr_0("quit",siod_quit,
1879  "(quit)\n\
1880  Exit from program, does not return.");
1881  init_subr_1("exit",l_exit,
1882  "(exit [RCODE])\n\
1883  Exit from program, if RCODE is given it is given as an argument to\n\
1884  the system call exit.");
1885  init_subr_2("env-lookup",envlookup,
1886  "(env-lookup VARNAME ENVIRONMENT)\n\
1887  Return value of VARNAME in ENVIRONMENT.");
1888  init_subr_1("fwarning",lfwarning,
1889  "(fwarning MODE)\n\
1890  For controlling various levels of warning messages. If MODE is nil, or\n\
1891  not specified stop all warning messages from being displayed. If MODE\n\
1892  display warning messages.");
1893  init_subr_2("%%stack-limit",stack_limit,
1894  "(%%stack-limit AMOUNT SILENT)\n\
1895  Set stacksize to AMOUNT, if SILENT is non nil do it silently.");
1896  init_subr_1("intern",intern,
1897  "(intern ATOM)\n\
1898  Intern ATOM on the oblist.");
1899  init_subr_2("%%closure",closure,
1900  "(%%closure ENVIRONMENT CODE)\n\
1901  Make a closure from given environment and code.");
1902  init_subr_1("%%closure-code",closure_code,
1903  "(%%closure-code CLOSURE)\n\
1904  Return code part of closure.");
1905  init_subr_1("%%closure-env",closure_env,
1906  "(%%closure-env CLOSURE)\n\
1907  Return environment part of closure.");
1908  init_subr_1("set_backtrace",set_backtrace,
1909  "(set_backtrace arg)\n\
1910  If arg is non-nil a backtrace will be display automatically after errors\n\
1911  if arg is nil, a backtrace will not automatically be displayed (use\n\
1912  (:backtrace) for display explicitly.");
1913  init_subr_1("set_server_safe_functions",set_restricted,
1914  "(set_server_safe_functions LIST)\n\
1915  Sets restricted list to LIST. When restricted list is non-nil only\n\
1916  functions whose names appear in this list may be executed. This\n\
1917  is used so that clients in server mode may be restricted to a small\n\
1918  number of safe commands. [see Server/client API]");
1919 
1920 }
1921 
1922 void init_subrs(void)
1923 {
1924  init_subrs_base();
1925  init_subrs_core();
1926  init_subrs_doc();
1927  init_subrs_file();
1929  init_subrs_list();
1930  init_subrs_math();
1931  init_subrs_str();
1932  init_subrs_sys();
1933  init_subrs_xtr(); // arrays and hash tables
1934 }
1935 
1936 /* err0,pr,prp are convenient to call from the C-language debugger */
1937 
1938 void err0(void)
1939 {err("0",NIL);}
1940 
1941 void pr(LISP p)
1942 {if ((p >= heap_org) &&
1943  (p < heap_end) &&
1944  (((((char *)p) - ((char *)heap_org)) % sizeof(struct obj)) == 0))
1945  pprint(p);
1946  else
1947  put_st("invalid\n");}
1948 
1949 void prp(LISP *p)
1950 {if (!p) return;
1951  pr(*p);}
1952 
1953 LISP siod_make_typed_cell(long type, void *s)
1954 {
1955  LISP ptr;
1956 
1957  NEWCELL(ptr,type);
1958  USERVAL(ptr) = s;
1959 
1960  return ptr;
1961 }
1962 
1963 static LISP set_restricted(LISP l)
1964 {
1965  // Set restricted list
1966 
1967  if (restricted == NIL)
1969 
1970  restricted = l;
1971  return NIL;
1972 }
1973 
1974 static int restricted_function_call(LISP l)
1975 {
1976  // Checks l recursively to ensure all function calls
1977  // are in the restricted list
1978  LISP p;
1979 
1980  if (l == NIL)
1981  return TRUE;
1982  else if (!consp(l))
1983  return TRUE;
1984  else if (TYPE(car(l)) == tc_symbol)
1985  {
1986  if (streq("quote",get_c_string(car(l))))
1987  return TRUE;
1988  else if (siod_member_str(get_c_string(car(l)),restricted) == NIL)
1989  return FALSE;
1990  }
1991  else if (restricted_function_call(car(l)) == FALSE)
1992  return FALSE;
1993 
1994  // As its some type of list with a valid car, check the cdr
1995  for (p=cdr(l); consp(p); p=cdr(p))
1996  if (restricted_function_call(car(p)) == FALSE)
1997  return FALSE;
1998  return TRUE;
1999 }
2000 
void(* gc_free)(LISP)
Definition: siodp.h:48
LISP closure_env(LISP exp)
Definition: slib.cc:1847
LISP(* repl_eval)(LISP)
Definition: siod_defs.h:196
void init_subrs(void)
Definition: slib.cc:1922
Definition: siod_defs.h:32
int siod_register_user_type(const char *name)
Definition: slib.cc:925
void gc_protect_sym(LISP *location, const char *st)
Definition: slib.cc:811
#define tc_first_user_type
Definition: siod_defs.h:141
void ** dead_pointers
Definition: slib.cc:177
long nointerrupt
Definition: slib.cc:129
LISP(* fast_print)(LISP, LISP)
Definition: siodp.h:54
char * wstrdup(const char *s)
Definition: walloc.c:117
LISP freelist
Definition: slib.cc:127
void err_stack(char *ptr)
Definition: slib.cc:621
float end(const EST_Item &item)
Definition: EST_item_aux.cc:96
LISP siod_docstrings
Definition: slib.cc:151
#define tc_fsubr
Definition: siod_defs.h:112
#define walloc(TYPE, SIZE)
Definition: EST_walloc.h:52
void set_fatal_exit_hook(void(*fcn)(void))
Definition: slib.cc:570
void(* gc_clear)(LISP)
Definition: siodp.h:49
LISP envlookup(LISP var, LISP env)
Definition: slib.cc:1353
void init_subr_0(const char *name, LISP(*fcn)(void), const char *doc)
Definition: slib.cc:896
#define NTYPEP(x, y)
Definition: siod_defs.h:101
LISP readtl(struct gen_readio *f)
Definition: slib.cc:1608
LISP newcell(long type)
Definition: slib.cc:668
#define INTERRUPT_CHECK()
Definition: siodp.h:87
#define SIG_restargs
Definition: siodp.h:104
void fput_st(FILE *f, const char *st)
Definition: slib.cc:450
long errjmp_ok
Definition: EST_error.c:204
repl_getc_fn siod_fancy_getc
Definition: slib.cc:148
LISP intern(LISP name)
Definition: slib.cc:742
LISP global_env
Definition: slib.cc:1351
#define STACK_LIMIT(_ptr, _amt)
Definition: siodp.h:91
long repl_driver(long want_sigint, long want_init, struct repl_hooks *h)
Definition: slib.cc:329
const char * siod_version(void)
Definition: slib.cc:111
#define SUBRM(x)
Definition: siod_defs.h:85
void setdoc(LISP name, LISP doc)
Definition: slib_doc.cc:20
long gc_cells_allocated
Definition: slib.cc:124
#define tc_symbol
Definition: siod_defs.h:106
LISP heap_2
Definition: slib.cc:114
#define NULLP(x)
Definition: siod_defs.h:95
#define EST_NORETURN
Definition: EST_common.h:59
void set_type_hooks(long type, long(*c_sxhash)(LISP, long), LISP(*equal)(LISP, LISP))
Definition: slib.cc:1506
char * init_file
Definition: slib.cc:121
#define SUBR1(x)
Definition: siod_defs.h:81
long no_interrupt(long n)
Definition: slib.cc:275
void sock_acknowledge_error()
Definition: slib_server.cc:57
long heap_size
Definition: slib.cc:116
void(* repl_ungetc_fn)(int, FILE *)
Definition: siodp.h:18
void(* ungetc_fcn)(int, char *)
Definition: siod_defs.h:187
void gc_protect_n(LISP *location, long n)
Definition: slib.cc:803
#define NIL
Definition: siod_defs.h:92
#define STACK_CHECK(_ptr)
Definition: siodp.h:94
LISP symcons(char *pname, LISP vcell)
Definition: slib.cc:686
#define DEFAULT_HEAP_SIZE
Definition: siod_defs.h:29
int nth(EST_String name, EST_TList< EST_String > &lex)
Definition: confusion.cc:46
#define TKBUFFERN
Definition: siodp.h:97
LISP current_env
Definition: slib.cc:132
int siod_ctrl_c
Definition: slib.cc:267
void init_subrs_list(void)
Definition: slib_list.cc:183
LISP strcons(long length, const char *data)
Definition: slib_str.cc:27
LISP(* user_readm)(int, struct gen_readio *)
Definition: slib.cc:160
LISP gc_status(LISP args)
Definition: slib.cc:1302
long show_backtrace
Definition: slib.cc:120
void set_repl_hooks(void(*puts_f)(char *), LISP(*read_f)(void), LISP(*eval_f)(LISP), void(*print_f)(LISP))
Definition: slib.cc:441
#define EQ(x, y)
Definition: siod_defs.h:93
double gc_rt
Definition: slib.cc:156
#define SYMBOLP(x)
Definition: siod_defs.h:155
float get_c_float(LISP x)
Definition: slib.cc:1858
FILE * fwarn
Definition: slib.cc:163
#define SUBR3(x)
Definition: siod_defs.h:83
LISP heap_org
Definition: slib.cc:115
void init_subr_4(const char *name, LISP(*fcn)(LISP, LISP, LISP, LISP), const char *doc)
Definition: slib.cc:904
#define NEWCELL(_into, _type)
Definition: siodp.h:69
STATIC char * reg(int paren, int *flagp)
Definition: regexp.cc:293
int siod_server_socket
Definition: slib_server.cc:18
#define SUBR2(x)
Definition: siod_defs.h:82
#define streq(X, Y)
Definition: EST_cutils.h:57
LISP eof_val
Definition: slib.cc:136
LISP leval_args(LISP l, LISP env)
Definition: slib.cc:1328
void gc_stop_and_copy(void)
Definition: slib.cc:1075
void(* repl_print)(LISP)
Definition: siod_defs.h:197
LISP heap_1
Definition: slib.cc:114
void init_subrs_xtr(void)
Definition: slib_xtr.cc:592
#define tc_flonum
Definition: siod_defs.h:105
void need_n_cells(int n)
Definition: slib.cc:200
struct gc_protected * next
Definition: siodp.h:67
void set_print_hooks(long type, void(*prin1)(LISP, FILE *), void(*print_string)(LISP, char *))
Definition: slib.cc:1486
LISP(* gc_mark)(LISP)
Definition: siodp.h:47
#define NFLONUMP(x)
Definition: siod_defs.h:159
void gc_mark(LISP ptr)
Definition: slib.cc:1135
void init_subrs_math(void)
Definition: slib_math.cc:209
char * stack_limit_ptr
Definition: slib.cc:184
LISP lerr(LISP message, LISP x)
Definition: slib.cc:661
struct gc_protected * protected_registers
Definition: slib.cc:154
LISP user_gc(LISP args)
Definition: slib.cc:1269
#define TYPE(x)
Definition: siod_defs.h:98
LISP siod_nth(int nth, LISP list)
Definition: siod.cc:214
LISP unbound_marker
Definition: slib.cc:140
LISP * stack_start_ptr
Definition: slib.cc:126
#define tc_table_dim
Definition: siod_defs.h:143
LISP equal(LISP, LISP)
Definition: slib_list.cc:133
LISP heap_end
Definition: slib.cc:115
void(* gc_scan)(LISP)
Definition: siodp.h:46
double gc_time_taken
Definition: slib.cc:125
void(* prin1)(LISP, FILE *)
Definition: siodp.h:50
LISP extend_env(LISP actuals, LISP formals, LISP env)
Definition: slib.cc:1341
void init_subrs_file(void)
Definition: slib_file.cc:661
const char * get_c_string(LISP x)
Definition: slib.cc:638
#define VCELL(x)
Definition: siod_defs.h:79
void handle_sigint(int sig SIG_restargs)
Definition: slib.cc:301
void siod_print_welcome(EST_String extra_info)
Definition: slib.cc:239
void(* print_string)(LISP, char *)
Definition: siodp.h:51
#define PNAME(x)
Definition: siod_defs.h:78
LISP vload(const char *fname, long cflag)
Definition: slib_file.cc:632
void(* repl_puts)(char *)
Definition: siod_defs.h:194
int audsp_mode
Definition: slib.cc:266
LISP(* leval)(LISP, LISP *, LISP *)
Definition: siodp.h:52
LISP lreadtk(long j)
Definition: slib.cc:1788
void pprint(LISP exp)
Definition: slib_file.cc:95
LISP gc_relocate(LISP x)
Definition: slib.cc:964
void init_subrs_format(void)
Definition: slib_format.cc:354
void errswitch(void)
Definition: slib.cc:618
#define tc_lsubr
Definition: siod_defs.h:111
LISP open_files
Definition: slib_file.cc:19
const char * siod_primary_prompt
Definition: slib.cc:172
LISP rintern(const char *name)
Definition: slib.cc:734
#define SUBR0(x)
Definition: siod_defs.h:80
LISP(* equal)(LISP, LISP)
Definition: siodp.h:56
#define tc_msubr
Definition: siod_defs.h:113
void(* repl_print)(LISP)
Definition: slib.cc:147
void(* fatal_exit_hook)(void)
Definition: slib.cc:162
#define NCONSP(x)
Definition: siod_defs.h:158
void init_subr(const char *name, long type, SUBR_FUNC fcn)
Definition: slib.cc:888
LISP cons(LISP x, LISP y)
Definition: slib_list.cc:97
void scan_registers(void)
Definition: slib.cc:815
char gc_free_once
Definition: siodp.h:44
LISP(* user_readt)(char *, long, int *)
Definition: slib.cc:161
void init_subr_3(const char *name, LISP(*fcn)(LISP, LISP, LISP), const char *doc)
Definition: slib.cc:902
LISP sym_errobj
Definition: slib.cc:137
LISP setvar(LISP var, LISP val, LISP env)
Definition: slib_core.cc:18
LISP subrcons(long type, const char *name, SUBR_FUNC f)
Definition: slib.cc:745
void free_oldspace(LISP space, LISP end)
Definition: slib.cc:1041
LISP read_from_string(const char *)
Definition: slib_str.cc:65
void pprintf(FILE *fd, LISP exp, int indent, int width, int depth, int length)
Definition: slib_file.cc:21
void err(const char *message, LISP x)
Definition: slib.cc:608
#define wrealloc(PTR, TYPE, SIZE)
Definition: EST_walloc.h:53
long gc_kind_copying
Definition: slib.cc:123
#define tc_cons
Definition: siod_defs.h:104
double myruntime(void)
Definition: slib.cc:434
long stack_size
Definition: slib.cc:185
#define FLONUMP(x)
Definition: siod_defs.h:154
#define tc_free_cell
Definition: siod_defs.h:115
long interrupt_differed
Definition: slib.cc:130
void grepl_puts(char *st, void(*repl_putss)(char *))
Definition: slib.cc:463
#define FALSE
Definition: EST_bool.h:119
void init_msubr(const char *name, LISP(*fcn)(LISP *, LISP *), const char *doc)
Definition: slib.cc:910
void set_io_hooks(long type, LISP(*fast_print)(LISP, LISP), LISP(*fast_read)(int, LISP))
Definition: slib.cc:1496
void init_subr_2(const char *name, LISP(*fcn)(LISP, LISP), const char *doc)
Definition: slib.cc:900
long which_heap
Definition: slib.cc:118
void NNEWCELL(LISP *_into, long _type)
Definition: slib.cc:187
void f_ungetc(int c, FILE *f)
Definition: slib.cc:1530
const char * repl_prompt
Definition: slib.cc:170
LISP(* repl_read)(void)
Definition: slib.cc:145
LISP restricted
Definition: slib.cc:134
void init_subrs_base(void)
Definition: slib.cc:1863
void set_eval_hooks(long type, LISP(*fcn)(LISP, LISP *, LISP *))
Definition: slib.cc:1373
float time(const EST_Item &item)
Definition: EST_item_aux.cc:82
#define tc_subr_0
Definition: siod_defs.h:107
LISP global_var
Definition: slib.cc:1350
long repl_c_string(char *str, long want_sigint, long want_init, long want_print)
Definition: slib.cc:392
NULL
Definition: EST_WFST.cc:55
LISP consp(LISP x)
Definition: slib_list.cc:112
int silent
Definition: rxp.c:20
f
Definition: EST_item_aux.cc:48
LISP heap
Definition: slib.cc:115
void scan_newspace(LISP newspace)
Definition: slib.cc:1014
void init_subr_1(const char *name, LISP(*fcn)(LISP), const char *doc)
Definition: slib.cc:898
jmp_buf * est_errjmp
Definition: EST_error.c:203
LISP(* fast_read)(int, LISP)
Definition: siodp.h:55
#define tc_subr_3
Definition: siod_defs.h:110
void set_gc_hooks(long type, int gc_free_once, LISP(*rel)(LISP), LISP(*mark)(LISP), void(*scan)(LISP), void(*free)(LISP), void(*clear)(LISP), long *kind)
Definition: slib.cc:946
LISP flocons(double x)
Definition: slib.cc:673
void gc_fatal_error(void)
Definition: slib.cc:665
long gc_cells_collected
Definition: slib.cc:157
void gc_unprotect(LISP *location)
Definition: slib.cc:759
getString int
Definition: EST_item_aux.cc:50
LISP * location
Definition: siodp.h:65
void pr(LISP p)
Definition: slib.cc:1941
#define tc_closure
Definition: siod_defs.h:114
void init_subrs_sys(void)
Definition: slib_sys.cc:94
long obarray_dim
Definition: slib.cc:142
int(* repl_getc_fn)(FILE *)
Definition: siodp.h:17
#define SUBR4(x)
Definition: siod_defs.h:84
LISP closure(LISP env, LISP code)
Definition: slib.cc:752
#define TYPEP(x, y)
Definition: siod_defs.h:100
repl_ungetc_fn siod_fancy_ungetc
Definition: slib.cc:149
LISP truth
Definition: slib.cc:135
#define CAR(x)
Definition: siod_defs.h:76
void handle_sigfpe(int sig SIG_restargs)
Definition: slib.cc:284
int(* getc_fcn)(char *)
Definition: siod_defs.h:186
char * name
Definition: siodp.h:43
char * cb_argument
Definition: siod_defs.h:188
LISP lreadf(FILE *f)
Definition: slib.cc:1582
#define tc_string
Definition: siod_defs.h:116
void init_lsubr(const char *name, LISP(*fcn)(LISP), const char *doc)
Definition: slib.cc:906
LISP lread(void)
Definition: slib_file.cc:553
const char * siod_secondary_prompt
Definition: slib.cc:173
LISP set_backtrace(LISP n)
Definition: slib.cc:1293
LISP(* gc_relocate)(LISP)
Definition: siodp.h:45
void print_hs_2(void)
Definition: slib.cc:258
struct user_type_hooks * user_types
Definition: slib.cc:153
LISP(* SUBR_FUNC)(void)
Definition: siod_defs.h:151
float start(const EST_Item &item)
Definition: EST_item_aux.cc:52
int f_getc(FILE *f)
Definition: slib.cc:1517
char * must_malloc(unsigned long size)
Definition: slib.cc:693
void prp(LISP *p)
Definition: slib.cc:1949
void set_read_hooks(char *all_set, char *end_set, LISP(*fcn1)(int, struct gen_readio *), LISP(*fcn2)(char *, long, int *))
Definition: slib.cc:1615
struct user_type_hooks * get_user_type_hooks(long type)
Definition: slib.cc:913
#define tc_subr_2
Definition: siod_defs.h:109
void init_storage(int init_heap_size)
Definition: slib.cc:880
LISP * obarray
Definition: slib.cc:141
char * tkbuffer
Definition: slib.cc:122
void init_fsubr(const char *name, LISP(*fcn)(LISP, LISP), const char *doc)
Definition: slib.cc:908
#define GETC_FCN(x)
Definition: siod_defs.h:190
const char * siod_prog_name
Definition: slib.cc:171
void init_subrs_str(void)
Definition: slib_str.cc:335
void print_hs_1(void)
Definition: slib.cc:252
#define tc_subr_4
Definition: siod_defs.h:122
long gc_status_flag
Definition: slib.cc:119
LISP cstrcons(const char *data)
Definition: slib_str.cc:40
void gc_protect(LISP *location)
Definition: slib.cc:791
LISP siod_make_typed_cell(long type, void *s)
Definition: slib.cc:1953
void init_subrs_core(void)
Definition: slib_core.cc:288
void gc_for_newcell(void)
Definition: slib.cc:1093
void init_subrs_doc(void)
Definition: slib_doc.cc:244
LISP * inums
Definition: slib.cc:150
#define tc_subr_1
Definition: siod_defs.h:108
void err0(void)
Definition: slib.cc:1938
LISP siod_quit(void)
Definition: slib.cc:1817
double get_c_double(LISP x)
Definition: slib.cc:1854
LISP gen_intern(char *name, int require_copy)
Definition: slib.cc:699
#define UNGETC_FCN(c, x)
Definition: siod_defs.h:191
LISP car(LISP x)
Definition: slib_list.cc:115
#define USERVAL(x)
Definition: siod_defs.h:89
#define DEAD_POINTER_GROWTH
Definition: slib.cc:180
LISP l_exit(LISP arg)
Definition: slib.cc:1823
LISP stack_limit(LISP amount, LISP silent)
Definition: slib.cc:626
LISP lfwarning(LISP mode)
Definition: slib.cc:1834
LISP(* repl_eval)(LISP)
Definition: slib.cc:146
LISP lprin1f(LISP exp, FILE *f)
Definition: slib_file.cc:471
void wfree(void *p)
Definition: walloc.c:131
#define FLONMPNAME(x)
Definition: siod_defs.h:88
long inums_dim
Definition: slib.cc:152
int size_dead_pointers
Definition: slib.cc:178
#define TRUE
Definition: EST_bool.h:118
long(* c_sxhash)(LISP, long)
Definition: siodp.h:53
int num_dead_pointers
Definition: slib.cc:179
int flush_ws(struct gen_readio *f, const char *eoferr)
Definition: slib.cc:1572
struct catch_frame * catch_framep
Definition: slib.cc:143
LISP siod_member_str(const char *key, LISP list)
Definition: siod.cc:167
long old_heap_used
Definition: slib.cc:117
jmp_buf save_regs_gc_mark
Definition: slib.cc:155
void(* repl_puts)(char *)
Definition: slib.cc:144
#define CONSP(x)
Definition: siod_defs.h:153
LISP closure_code(LISP exp)
Definition: slib.cc:1844
void put_st(const char *st)
Definition: slib.cc:460
LISP leval(LISP x, LISP qenv)
Definition: slib.cc:1378
LISP(* repl_read)(void)
Definition: siod_defs.h:195
void siod_reset_prompt(void)
Definition: slib.cc:321
long int get_c_int(LISP x)
Definition: slib.cc:1850
LISP get_newspace(void)
Definition: slib.cc:1001
LISP cdr(LISP x)
Definition: slib_list.cc:124
int el_pos
Definition: slib.cc:168
int siod_interactive
Definition: slib.cc:164
void close_open_files(void)
Definition: slib_file.cc:610
#define CDR(x)
Definition: siod_defs.h:77
LISP oblistvar
Definition: slib.cc:131
#define FLONM(x)
Definition: siod_defs.h:87
#define NNULLP(x)
Definition: siod_defs.h:96
LISP cintern(const char *name)
Definition: slib.cc:728