1 // externs.h                               Copyright (C) Codemist 1989-2021
2 
3 //
4 //   Main batch of extern declarations.
5 //
6 //
7 
8 /**************************************************************************
9  * Copyright (C) 2021, Codemist.                         A C Norman       *
10  *                                                                        *
11  * Redistribution and use in source and binary forms, with or without     *
12  * modification, are permitted provided that the following conditions are *
13  * met:                                                                   *
14  *                                                                        *
15  *     * Redistributions of source code must retain the relevant          *
16  *       copyright notice, this list of conditions and the following      *
17  *       disclaimer.                                                      *
18  *     * Redistributions in binary form must reproduce the above          *
19  *       copyright notice, this list of conditions and the following      *
20  *       disclaimer in the documentation and/or other materials provided  *
21  *       with the distribution.                                           *
22  *                                                                        *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    *
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT      *
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS      *
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE         *
27  * COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,   *
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,   *
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS  *
30  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
31  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR  *
32  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF     *
33  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
34  * DAMAGE.                                                                *
35  *************************************************************************/
36 
37 
38 // $Id: externs.h 5745 2021-03-20 17:35:28Z arthurcnorman $
39 
40 #ifndef header_externs_h
41 #define header_externs_h 1
42 
43 // Note that the Windows version exports a number of symbols, as listed
44 // in a ".def" file. In order for there to be a match between the symbol
45 // names in the object files and the names in the .def file it is vital
46 // that all those things be declared with C linkage and hence un-mangled
47 // names. Perhaps I need some strategy that lets me gain the extra security
48 // of C++ linkage for everything else... but that is for the future.
49 
50 #ifdef USE_MPI
51 #include "mpi.h"
52 extern int32_t mpi_rank,mpi_size;
53 #endif
54 
55 extern void **pages, **heap_pages, **vheap_pages;
56 
57 extern void **new_heap_pages, **new_vheap_pages;
58 
59 extern void *allocate_page(const char *why);
60 
61 extern size_t pages_count, heap_pages_count, vheap_pages_count;
62 
63 extern size_t new_heap_pages_count, new_vheap_pages_count;
64 
65 extern LispObject *list_bases[];
66 extern LispObject *nilsegment, *stacksegment;
67 extern LispObject *stackBase;
68 extern int32_t stack_segsize;  // measured in units of one CSL page
69 extern double max_store_size;
70 
71 extern bool restartp;
72 
73 // This version of the directory structure can cope with up to 2047
74 // modules in any single library. It can also cope with a directory
75 // being mapped onto an operating-system directory rather than my own
76 // sub-structure packed within a file.
77 
78 #define IMAGE_FORMAT_VERSION       '5'
79 
80 #define DIRECTORY_SIZE              8    // Initial directory size
81 
82 typedef struct _directory_header
83 {   char C, S, L, version;  // Identification: spells CSL or CCL.
84     unsigned char dirext,   // Extra bits for dirused, dirsize, this is
85              // so that in effect dirsize & dirused can be
86              // 12 bits wide.
87              dirsize,  // Number of directory entries provided.
88              dirused,  // Number currently in use.
89              updated;  // In need of compaction & other flags.
90     char eof[4];            // fseek/ftell location of end of file.
91     // Does this assume no fiules > 4G?
92 } directory_header;
93 
94 typedef struct _directory_entry
95 {   char data[44];
96 //
97 //  char newline;                * Makes file easier to read as a text file! *
98 //  char name[12];               * blank padded to 12 characters             *
99 //                               * but with special rules for root image etc *
100 //  char date[24];
101 //  char position[4];            * Machine byte-order insensitive format     *
102 //  char size[3];                * Ditto                                     *
103 //
104 } directory_entry;
105 
106 //
107 // I use these macros rather than just the structure definition shown above
108 // so that the behaviour of the code is not sensitive to attempts by a C
109 // compiler to align things for me.  Think C 5.0 on the Macintosh (and
110 // probably many other C compilers) put padder bytes in the original
111 // structure to give word-alignment.
112 //
113 #define D_newline     data[0]
114 #define D_name        data[1]
115 #define D_space       data[12]
116 #define D_date        data[13]
117 #define D_position    data[37]
118 #define D_size        data[41]
119 
120 #define name_size     12
121 #define date_size     24
122 
123 //
124 // The limit set here to the length of the name of a directory should only
125 // have an effect on cosmetics not functionality.
126 //
127 #define DIRNAME_LENGTH  256
128 #define NEWLINE_CHAR    0x0a
129 
130 //
131 // The D_newline location in a directory originally held a newline,
132 // because doing so resulted in image files being a little bit easier
133 // to interpret when looked at with a simple text editor. But then
134 // it turned out that the C value `\n' was not the same on all computers,
135 // and so I used a literal hex value 0x0a instead, expecting it to
136 // be the same as '\n' on "most" systems.
137 //
138 
139 typedef struct directory
140 {   directory_header h;
141     std::FILE *f;
142     const char *full_filename;    // nullptr unless native directory
143 // It is unexpectedly and unpleasantly the case that the "filename"
144 // field here must be the last one before the array of directory
145 // entries. This is because in the case where an image file is
146 // left pending at startup the structure is extended, overlapping where the
147 // directory entries will end up, to hold a full-length file name not merely
148 // one truncated to DIRNAME_LENGTH. I do not use a string here because
149 // I use a naive process of writing the bytes of a directory to disc when
150 // I create an image file, and I can not have any reasonable expectations on
151 // what string would look like.
152     char filename[DIRNAME_LENGTH];
153     directory_entry d[1];   // Will usually have many more entries
154 } directory;
155 
156 #ifdef COMMON
157 #  define MIDDLE_INITIAL   'C'
158 #else
159 #  define MIDDLE_INITIAL   'S'
160 #endif
161 
get_dirused(directory & d)162 inline int get_dirused(directory &d)
163 {   return d.h.dirused + ((d.h.dirext & 0x0f)<<8);
164 }
165 
get_dirsize(directory & d)166 inline int get_dirsize(directory &d)
167 {   return d.h.dirsize + ((d.h.dirext & 0xf0)<<4);
168 }
169 
170 //
171 // Flags for the UPDATED field
172 //
173 
174 #define D_WRITE_OK  1
175 #define D_UPDATED   2
176 #define D_COMPACT   4
177 #define D_PENDING   8
178 
179 extern char *mystrdup(const char *s);
180 
181 class stringBool
182 {
183 public:
184     string key;
185     bool flag;
stringBool(string k,bool f)186     stringBool(string k, bool f)
187     {   key = k;
188         flag = f;
189     }
190 };
191 
192 class stringBoolString
193 {
194 public:
195     string key;
196     bool flag;
197     string data;
stringBoolString(string k,bool f,string d)198     stringBoolString(string k, bool f, string d)
199     {   key = k;
200         flag = f;
201         data = d;
202     }
203 };
204 
205 class faslFileRecord
206 {
207 public:
208     bool inUse;
209     const char *name;
210     directory *dir;
211     bool isOutput;
faslFileRecord(const char * n,bool o)212     faslFileRecord(const char *n, bool o)
213     {   inUse = true;
214         name = n;
215         dir = nullptr;
216         isOutput = o;
217     }
~faslFileRecord()218     ~faslFileRecord()
219     {   if (dir != nullptr) delete [] reinterpret_cast<char *>(dir);
220     }
221 };
222 
223 extern std::vector<stringBoolString> symbolsToDefine;
224 extern std::vector<stringBoolString> stringsToDefine;
225 extern std::vector<string> stringsToEvaluate;
226 extern std::vector<faslFileRecord> fasl_files;
227 
228 extern char *big_chunk_start, *big_chunk_end;
229 
230 extern uintptr_t *C_stackbase, C_stacklimit;
231 
232 extern LispObject multiplication_buffer;
233 
234 #ifdef CONSERVATIVE
235 extern void write_barrier(atomic<LispObject> *p, LispObject q);
236 extern void write_barrier(LispObject *p, LispObject q);
237 #else // !CONSERVATIVE
write_barrier(atomic<LispObject> * p,LispObject q)238 inline void write_barrier(atomic<LispObject> *p, LispObject q)
239 {  *p = q;
240 }
write_barrier(LispObject * p,LispObject q)241 inline void write_barrier(LispObject *p, LispObject q)
242 {  *p = q;
243 }
244 #endif // !CONSERVATIVE
245 
246 // This tiny function exists just so that I can set a breakpoint on it.
247 
248 extern std::mutex debug_lock;
249 extern const char *debug_file;
250 extern int debug_line;
251 
252 extern void DebugTrace();
253 extern void DebugTrace(int i);
254 extern void DebugTrace(const char *msg);
255 extern void DebugTrace(const char *fmt, int i);
256 
257 // This is a macro that sets some global variables because I want Tr()
258 // without arguments to be valid, and until C++2a it seems impossible to
259 // combine __VA_ARGS__ with anything else because of fussiness about commas.
260 
261 #define Tr(...)                                        \
262    {   std::lock_guard<std::mutex> lk(debug_lock);     \
263        debug_file = __FILE__;                          \
264        debug_line = __LINE__;                          \
265        DebugTrace(__VA_ARGS__);                        \
266    }
267 
268 #define GC_USER_SOFT 0
269 #define GC_USER_HARD 1
270 #define GC_STACK     2
271 #define GC_CONS      3
272 #define GC_VEC       4
273 #define GC_BPS       5
274 
275 extern volatile char stack_contents_temp;
276 
277 #ifdef CHECK_STACK
278 extern int check_stack(const char *file, int line);
279 extern void show_stack();
280 
if_check_stack()281 inline void if_check_stack()
282 {   if (check_stack("@" __FILE__,__LINE__))
283     {   show_stack();
284         aerror("stack overflow");
285     }
286 }
287 #else
if_check_stack()288 inline void if_check_stack()
289 {   const char *_p_ = reinterpret_cast<const char *>(&_p_);
290     if (reinterpret_cast<uintptr_t>(_p_) < C_stacklimit)
291     {   if (C_stacklimit > 1024*1024) C_stacklimit -= 1024*1024;
292         aerror("stack overflow");
293     }
294 }
295 #endif
296 
297 //
298 // Extra debugging help...
299 //
300 
301 #ifdef DEBUG
302 
303 extern char debug_trail[32][32];
304 extern char debug_trail_file[32][32];
305 extern int debug_trail_line[32];
306 extern int debug_trailp;
307 extern void debug_record_raw(const char *data, const char *file,
308                              int line);
309 extern void debug_record_int_raw(const char *s, int n,
310                                  const char *file, int line);
311 extern void debug_show_trail_raw(const char *msg, const char *file,
312                                  int line);
313 
314 #define debug_record(data) debug_record_raw(data, __FILE__, __LINE__)
315 #define debug_record_int(s, n) debug_record_int_raw(s, n, __FILE__, __LINE__)
316 #define debug_record_string(s) debug_record((const char *)&celt(s, 0))
317 #define debug_record_symbol(x) debug_record_string(qpname(x))
318 #define debug_show_trail(data) debug_show_trail_raw(data, __FILE__, __LINE__)
319 
320 #define debug_assert(x) \
321   if (!(x)) { debug_show_trail("Assertion failed"); my_exit(); }
322 
323 #else
324 
325 #define debug_record(data)
326 #define debug_record_int(s, n)
327 #define debug_record_string(s)
328 #define debug_record_symbol(x)
329 #define debug_show_trail(x)
330 
331 #define debug_assert(x)
332 
333 #endif
334 
335 #define first_nil_offset         50     // GC collector marks from here up
336 
337 //
338 // A vector of 50 words is used by the interpreter when preparing args
339 // for functions and when handling multiple values.
340 //
341 
342 #define work_0_offset           250
343 
344 // Garbage collector marks up to but not including last_nil_offset
345 #define last_nil_offset         301
346 
347 //
348 // NIL_SEGMENT_SIZE must be over-large by enough to allow for
349 // space lost while rounding nil up to be a multiple of 8. Also in the
350 // Common Lisp case I need to give myself a spare word BEFORE the place
351 // where nil points. I also want this to be an even multiple of the
352 // size of LispObject.
353 //
354 #define NIL_SEGMENT_SIZE    (((1 + last_nil_offset) & ~1) * \
355                              sizeof(LispObject) + 32)
356 
357 //
358 // I give myself a margin of SPARE bytes at the end of a page so that I can
359 // always CONS that amount (even without a garbage collection check) and not
360 // corrupt anything.  The main use for this is that sometimes I need to
361 // convert a set of multiple values or of arguments from values on the
362 // (C-) stack or wherever va_arg() can find them into a list structure, and
363 // to avoid horrible potential problems with a garbage collection spotting]
364 // an exception (notably a ^C interrupt), running arbitrary code in an
365 // exception handler and then continuing, I need to cons those things up
366 // without any possible GC.  The function cons_no_gc does that, and
367 // I should then call cons_gc_test() afterwards to regularise the situation.
368 // 512 bytes here leaves room for 64 conses, and I support at most 50
369 // (multiple-) values so I hope this is safe.
370 //
371 
372 #define SPARE                   512
373 
374 //
375 // I want my table of addresses here to be 8-byte aligned on 64-bit
376 // machines...
377 //
378 
379 //
380 //            !COMMON  COMMON
381 //   32-bit    nil       nil
382 //   64-bit    nil+4     nil
383 //
384 
385 
386 #ifdef CONSERVATIVE
387 extern uintptr_t heapstart;
388 extern uintptr_t len;
389 extern uintptr_t xor_chain;
390 extern uintptr_t vheapstart;
391 extern uintptr_t vlen;
392 extern uintptr_t vxor_chain;
393 
394 extern LispObject *stackLimit;
395 
396 extern bool gcTest;
397 
398 #else // !CONSERVATIVE
399 extern LispObject *stackLimit;
400 #endif // !CONSERVATIVE
401 
402 extern atomic<uintptr_t> event_flag;
403 
404 extern intptr_t nwork;
405 
406 extern unsigned int exit_count;
407 extern uint64_t gensym_ser;
408 extern intptr_t print_precision, miscflags;
409 extern intptr_t current_modulus, fastget_size, package_bits;
410 extern intptr_t modulus_is_large;
411 
412 extern LispObject lisp_true, lambda, funarg, unset_var, opt_key,
413        rest_key;
414 extern LispObject quote_symbol, function_symbol, comma_symbol;
415 extern LispObject comma_at_symbol, cons_symbol, eval_symbol,
416        apply_symbol;
417 extern LispObject list_symbol, liststar_symbol, eq_symbol, eql_symbol;
418 extern LispObject cl_equal_symbol, equal_symbol, equalp_symbol;
419 extern LispObject work_symbol, evalhook, applyhook, macroexpand_hook;
420 extern LispObject go_symbol, cond_symbol;
421 extern LispObject append_symbol, exit_tag, exit_value, catch_tags;
422 extern LispObject current_package, startfn;
423 extern LispObject gensym_base, string_char_sym, boffo;
424 extern LispObject err_table, progn_symbol, gcknt_symbol;
425 extern LispObject lisp_work_stream, charvec, raise_symbol,
426        lower_symbol;
427 extern LispObject echo_symbol, codevec, litvec, supervisor, B_reg;
428 extern LispObject savedef, comp_symbol, compiler_symbol, faslvec;
429 extern LispObject tracedfn, lisp_terminal_io;
430 extern LispObject lisp_standard_output, lisp_standard_input,
431        lisp_error_output;
432 extern LispObject lisp_trace_output, lisp_debug_io, lisp_query_io;
433 extern LispObject prompt_thing, faslgensyms;
434 extern LispObject prinl_symbol, emsg_star, redef_msg;
435 extern LispObject expr_symbol, fexpr_symbol, macro_symbol;
436 extern LispObject big_divisor, big_dividend, big_quotient;
437 extern LispObject big_fake1, big_fake2, active_stream, current_module;
438 extern LispObject mv_call_symbol, features_symbol, lisp_package;
439 extern LispObject sys_hash_table, sxhash_hash_table;
440 extern LispObject help_index, cfunarg, lex_words;
441 extern LispObject get_counts, fastget_names, input_libraries;
442 extern LispObject output_library, current_file, break_function;
443 extern LispObject standard_output, standard_input, debug_io;
444 extern LispObject error_output, query_io, terminal_io;
445 extern LispObject trace_output, fasl_stream;
446 extern LispObject startup_symbol, mv_call_symbol, traceprint_symbol;
447 extern LispObject load_source_symbol, load_selected_source_symbol;
448 extern LispObject bytecoded_symbol, funcall_symbol, autoload_symbol;
449 extern LispObject gchook, resources, callstack, procstack, procmem;
450 extern LispObject trap_time, current_function, keyword_package;
451 extern LispObject all_packages, package_symbol, internal_symbol;
452 extern LispObject external_symbol, inherited_symbol;
453 extern LispObject key_key, allow_other_keys, aux_key;
454 extern LispObject format_symbol, expand_def_symbol, allow_key_key;
455 extern LispObject declare_symbol, special_symbol, large_modulus;
456 extern LispObject used_space, avail_space, eof_symbol, call_stack;
457 extern LispObject nicknames_symbol, use_symbol, and_symbol, or_symbol;
458 extern LispObject not_symbol, reader_workspace, named_character;
459 extern LispObject read_float_format, short_float, single_float,
460        double_float;
461 extern LispObject long_float, bit_symbol, pathname_symbol,
462        print_array_sym;
463 extern LispObject read_base, initial_element;
464 extern LispObject builtin0_symbol, builtin1_symbol, builtin2_symbol;
465 extern LispObject builtin3_symbol, builtin4_symbol;
466 
467 #ifdef OPENMATH
468 extern LispObject om_openFileDev(LispObject env, int nargs, ...);
469 extern LispObject om_openStringDev(LispObject env, LispObject lstr,
470                                    LispObject lenc);
471 extern LispObject om_closeDev(LispObject env, LispObject dev);
472 extern LispObject om_setDevEncoding(LispObject env, LispObject ldev,
473                                     LispObject lenc);
474 extern LispObject om_makeConn(LispObject env, LispObject ltimeout);
475 extern LispObject om_closeConn(LispObject env, LispObject lconn);
476 extern LispObject om_getConnInDevice(LispObject env,
477                                      LispObject lconn);
478 extern LispObject om_getConnOutDevice(LispObject env,
479                                       LispObject lconn);
480 extern LispObject om_connectTCP(LispObject env, int nargs, ...);
481 extern LispObject om_bindTCP(LispObject env, LispObject lconn,
482                              LispObject lport);
483 extern LispObject om_putApp(LispObject env, LispObject ldev);
484 extern LispObject om_putEndApp(LispObject env, LispObject ldev);
485 extern LispObject om_putAtp(LispObject env, LispObject ldev);
486 extern LispObject om_putEndAtp(LispObject env, LispObject ldev);
487 extern LispObject om_putAttr(LispObject env, LispObject ldev);
488 extern LispObject om_putEndAttr(LispObject env, LispObject ldev);
489 extern LispObject om_putBind(LispObject env, LispObject ldev);
490 extern LispObject om_putEndBind(LispObject env, LispObject ldev);
491 extern LispObject om_putBVar(LispObject env, LispObject ldev);
492 extern LispObject om_putEndBVar(LispObject env, LispObject ldev);
493 extern LispObject om_putError(LispObject env, LispObject ldev);
494 extern LispObject om_putEndError(LispObject env, LispObject ldev);
495 extern LispObject om_putObject(LispObject env, LispObject ldev);
496 extern LispObject om_putEndObject(LispObject env, LispObject ldev);
497 extern LispObject om_putInt(LispObject env, LispObject ldev,
498                             LispObject val);
499 extern LispObject om_putFloat(LispObject env, LispObject ldev,
500                               LispObject val);
501 extern LispObject om_putByteArray(LispObject env, LispObject ldev,
502                                   LispObject val);
503 extern LispObject om_putVar(LispObject env, LispObject ldev,
504                             LispObject val);
505 extern LispObject om_putString(LispObject env, LispObject ldev,
506                                LispObject val);
507 extern LispObject om_putSymbol(LispObject env, LispObject ldev,
508                                LispObject val);
509 extern LispObject om_putSymbol2(LispObject env, int nargs, ...);
510 extern LispObject om_getApp(LispObject env, LispObject ldev);
511 extern LispObject om_getEndApp(LispObject env, LispObject ldev);
512 extern LispObject om_getAtp(LispObject env, LispObject ldev);
513 extern LispObject om_getEndAtp(LispObject env, LispObject ldev);
514 extern LispObject om_getAttr(LispObject env, LispObject ldev);
515 extern LispObject om_getEndAttr(LispObject env, LispObject ldev);
516 extern LispObject om_getBind(LispObject env, LispObject ldev);
517 extern LispObject om_getEndBind(LispObject env, LispObject ldev);
518 extern LispObject om_getBVar(LispObject env, LispObject ldev);
519 extern LispObject om_getEndBVar(LispObject env, LispObject ldev);
520 extern LispObject om_getError(LispObject env, LispObject ldev);
521 extern LispObject om_getEndError(LispObject env, LispObject ldev);
522 extern LispObject om_getObject(LispObject env, LispObject ldev);
523 extern LispObject om_getEndObject(LispObject env, LispObject ldev);
524 extern LispObject om_getInt(LispObject env, LispObject ldev);
525 extern LispObject om_getFloat(LispObject env, LispObject ldev);
526 extern LispObject om_getByteArray(LispObject env, LispObject ldev);
527 extern LispObject om_getVar(LispObject env, LispObject ldev);
528 extern LispObject om_getString(LispObject env, LispObject ldev);
529 extern LispObject om_getSymbol(LispObject env, LispObject ldev);
530 extern LispObject om_getType(LispObject env, LispObject ldev);
531 
532 extern LispObject om_stringToStringPtr(LispObject env,
533                                        LispObject lstr);
534 extern LispObject om_stringPtrToString(LispObject env,
535                                        LispObject lpstr);
536 
537 extern LispObject om_read(LispObject env, LispObject dev);
538 extern LispObject om_supportsCD(LispObject env, LispObject lcd);
539 extern LispObject om_supportsSymbol(LispObject env, LispObject lcd,
540                                     LispObject lsym);
541 extern LispObject om_listCDs(LispObject env, int nargs, ...);
542 extern LispObject om_listSymbols(LispObject env, LispObject lcd);
543 extern LispObject om_whichCDs(LispObject env, LispObject lsym);
544 #endif
545 
546 extern LispObject workbase[51];
547 
548 extern LispObject user_base_0, user_base_1, user_base_2;
549 extern LispObject user_base_3, user_base_4, user_base_5;
550 extern LispObject user_base_6, user_base_7, user_base_8;
551 extern LispObject user_base_9;
552 
553 #define work_0              workbase[0]
554 #define work_1              workbase[1]
555 #define mv_1                workbase[1]
556 #define mv_2                workbase[2]
557 #define mv_3                workbase[3]
558 #define mv_4                workbase[4]
559 #define work_50             workbase[50]
560 
561 extern void copy_into_nilseg();
562 extern void copy_out_of_nilseg();
563 
564 extern void rehash_this_table(LispObject v);
565 extern void simple_print(LispObject x);
566 extern void simple_msg(const char *s, LispObject x);
567 extern uint64_t hash_equal(LispObject key);
568 
569 extern char *exit_charvec;
570 
571 //
572 // There is no reason to preserve this across restarts etc so making it a
573 // simple C variable makes it easier for me to initialise it early.
574 //
575 extern intptr_t exit_reason;
576 
577 extern int procstackp;
578 
579 extern bool garbage_collection_permitted;
580 
581 extern int csl_argc;
582 extern const char **csl_argv;
583 extern bool fasl_output_file;
584 extern size_t output_directory;
585 
586 extern LispObject *repeat_heap;
587 extern size_t repeat_count;
588 
589 #ifdef BUILTIN_IMAGE
590 extern const unsigned char *binary_read_filep;
591 #else
592 extern std::FILE *binary_read_file;
593 #endif
594 
595 extern std::FILE *binary_write_file;
596 
597 extern size_t boffop;
598 extern void packcharacter(int c);
599 extern void packbyte(int c);
600 #define boffo_char(i) ucelt(boffo, i)
601 
602 extern char **loadable_packages;
603 extern char **switches;
604 extern void review_switch_settings();
605 
606 #ifdef SOCKETS
607 extern bool sockets_ready;
608 extern void flush_socket();
609 #endif
610 
611 extern void report_file(const char *s);
612 
613 extern int errorset_min, errorset_max;
614 
615 extern bool force_verbos, force_echo, force_backtrace;
616 extern bool ignoreLoadTime;
617 extern bool stop_on_error;
618 extern uint64_t force_cons, force_vec;
619 
620 extern int init_flags;
621 
622 extern const char *standard_directory;
623 
624 extern int64_t gc_number;
625 extern int64_t reclaim_trap_count;
626 extern uintptr_t reclaim_stack_limit;
627 extern uint64_t reclaim_trigger_count, reclaim_trigger_target;
628 
629 #ifdef CONSERVATIVE
630 extern void reclaim(const char *why);
631 #else
632 extern LispObject reclaim(LispObject value_to_return, const char *why,
633                           int stg_class, size_t size);
634 #endif
635 extern void use_gchook(LispObject arg);
636 
637 extern uint64_t force_cons, force_vec;
638 extern bool next_gc_is_hard;
639 
cons_forced(size_t n)640 inline bool cons_forced(size_t n)
641 {
642 #ifdef DEBUG
643     if (force_cons == 0) return false;
644     if (force_cons <= n)
645     {   force_cons = 0;
646         next_gc_is_hard = true;
647         return true;
648     }
649     force_cons -= n;
650 #endif
651     return false;
652 }
653 
vec_forced(size_t n)654 inline bool vec_forced(size_t n)
655 {
656 #ifdef DEBUG
657     if (force_vec == 0) return false;
658     if (force_vec <= n)
659     {   force_vec = 0;
660         next_gc_is_hard = true;
661         return true;
662     }
663     force_vec -= n;
664 #endif
665     return false;
666 }
667 
668 #define INIT_QUIET      1
669 #define INIT_VERBOSE    2
670 #define INIT_EXPANDABLE 4
671 
672 #define Lispify_predicate(p)  ((p) ? lisp_true : nil)
673 
674 //
675 // variables used by the IO system.
676 //
677 
678 extern int tty_count;
679 extern std::FILE *spool_file;
680 extern char spool_file_name[128];
681 
682 //
683 // If there is no more than 100 bytes of data then I will deem
684 // file compression frivolous.  The compression code assumes that
685 // it has at least 2 bytes to work on, so do NOT cut this limit down to zero.
686 // Indeed more than that the limit must be greater than the length of
687 // the initial header record (112 bytes).
688 //
689 
690 #define CODESIZE                0x1000
691 
692 typedef struct _entry_point0
693 {   no_args *p;
694     const char *s;
695 } entry_point0;
696 
697 typedef struct _entry_point1
698 {   one_arg *p;
699     const char *s;
700 } entry_point1;
701 
702 typedef struct _entry_point2
703 {   two_args *p;
704     const char *s;
705 } entry_point2;
706 
707 typedef struct _entry_point3
708 {   three_args *p;
709     const char *s;
710 } entry_point3;
711 
712 typedef struct _entry_point4up
713 {   fourup_args *p;
714     const char *s;
715 } entry_point4up;
716 
717 extern entry_point0 entries_table0[];
718 extern entry_point1 entries_table1[];
719 extern entry_point2 entries_table2[];
720 extern entry_point3 entries_table3[];
721 extern entry_point4up entries_table4up[];
722 extern entry_point1 entries_tableio[];
723 
724 extern const char *linker_type;
725 extern const char *compiler_command[], *import_data[],
726        *config_header[], *csl_headers[];
727 
728 extern LispObject encapsulate_pointer(void *);
729 extern void *extract_pointer(LispObject a);
730 extern LispObject Lencapsulatedp(LispObject env, LispObject a);
731 typedef void initfn(LispObject *, LispObject **,
732                     LispObject * volatile *);
733 
734 extern LispObject characterify(LispObject a);
735 extern LispObject char_to_id(int ch);
736 
737 extern void Iinit();
738 extern void IreInit();
739 extern void Ilist();
740 extern bool open_output(const char *s, size_t len);
741 
742 #define IMAGE_CODE  ((size_t)(-1000))
743 #define HELP_CODE   ((size_t)(-1001))
744 #define BANNER_CODE ((size_t)(-1002))
745 
746 #define IOPEN_OUT       0
747 #define IOPEN_IN        1
748 
749 extern bool Iopen(const char *name, size_t len, int dirn,
750                   char *expanded_name);
751 extern bool Iopen_from_stdin(), Iopen_to_stdout();
752 extern bool IopenRoot(char *expanded_name, size_t hard,
753                       int sixtyfour);
754 extern bool Iwriterootp(char *expanded);
755 extern bool Iopen_banner(int code);
756 extern bool Imodulep1(int i, const char *name, size_t len,
757                       char *datestamp,
758                       size_t *size, char *expanded_name);
759 extern bool Imodulep(const char *name, size_t len, char *datestamp,
760                      size_t *size, char *expanded_name);
761 extern char *trim_module_name(char *name, size_t *lenp);
762 extern bool Icopy(const char *name, size_t len);
763 extern bool Idelete(const char *name, size_t len);
764 extern bool IcloseInput();
765 extern bool IcloseOutput();
766 extern bool Ifinished();
767 extern int  Igetc();
768 extern bool Iread(void *buff, size_t size);
769 extern bool Iputc(int ch);
770 extern bool Iwrite(const void *buff, size_t size);
771 extern bool def_init();
772 extern bool inf_init();
773 extern bool def_finish();
774 extern bool inf_finish();
775 extern int  Zgetc();
776 extern bool Zread(void *buff, size_t size);
777 extern bool Zputc(int ch);
778 extern bool Zwrite(const void *buff, size_t size);
779 extern long int Ioutsize();
780 extern const char *CSLtmpdir();
781 extern const char *CSLtmpnam(const char *suffix, size_t suffixlen);
782 extern int Cmkdir(const char *s);
783 extern char *look_in_lisp_variable(char *o, int prefix);
784 
785 extern void CSL_MD5_Init();
786 extern void CSL_MD5_Update(const unsigned char *data, size_t len);
787 extern void CSL_MD5_Final(unsigned char *md);
788 extern bool CSL_MD5_busy;
789 extern unsigned char *CSL_MD5(unsigned char *data, int n,
790                               unsigned char *md);
791 extern void checksum(LispObject a);
792 
793 extern void ensure_screen();
794 extern int window_heading;
795 extern void my_exit();
796 
797 extern uint64_t base_time;
798 extern std::chrono::high_resolution_clock::time_point base_walltime;
799 extern uint64_t gc_time;
800 extern bool trap_floating_overflow;
801 extern const volatile char *errorset_msg;
802 extern int errorset_code;
803 extern void unwind_stack(LispObject *, bool findcatch);
804 extern bool segvtrap;
805 extern bool batch_flag;
806 extern int escaped_printing;
807 extern void set_up_signal_handlers();
808 extern int async_interrupt(int a);
809 
810 extern void record_get(LispObject tag, bool found);
811 
812 //
813 // Functions used internally - not to be installed in Lisp function
814 // cells, but some of these may end up getting called using special
815 // non-standard conventions when the Lisp compiler has been at work.
816 //
817 
818 // Note that some things here are declared to use C rather than C++ linkage.
819 // These are things that will be exported for use by other applications that
820 // might arrange to build CSL/Reduce as a DLL and hook into it from outside.
821 // See impex.def for the list of names where this can happen. I have not tried
822 // building CSL as a DLL for some while and so I expect that any attempt to
823 // do so would call for careful review of linkage styles etc!
824 
825 extern bool        isprime(uint64_t);
826 extern LispObject  set_up_functions(int restartp);
827 extern void        get_user_files_checksum(unsigned char *);
828 extern LispObject  acons(LispObject a, LispObject b, LispObject c);
829 extern LispObject  ash(LispObject a, LispObject b);
830 extern LispObject  bytestream_interpret(size_t ppc, LispObject lit,
831                                         LispObject *entry_stack);
832 extern bool        complex_stringp(LispObject a);
833 extern LispObject  copy_string(LispObject a, size_t n);
834 extern LispObject  freshline_trace();
835 extern LispObject  freshline_debug();
836 extern LispObject  cons(LispObject a, LispObject b);
837 extern LispObject  cons_no_gc(LispObject a, LispObject b);
838 extern LispObject  acons_no_gc(LispObject a, LispObject b,
839                                LispObject c);
840 extern LispObject  cons_gc_test(LispObject a);
841 extern void        convert_fp_rep(void *p, int old_rep, int new_rep,
842                                   int type);
843 extern LispObject  eval(LispObject u, LispObject env);
844 extern uint32_t    Crand();
845 extern LispObject  Cremainder(LispObject a, LispObject b);
846 extern void        Csrand(uint32_t a);
847 extern void        discard(LispObject a);
848 extern bool        eql_fn(LispObject a, LispObject b);
849 extern bool        cl_equal_fn(LispObject a, LispObject b);
850 extern bool        equal_fn(LispObject a, LispObject b);
851 #ifdef TRACED_EQUAL
852 extern bool        traced_equal_fn(LispObject a, LispObject b,
853                                    const char *, int, int);
854 #define equal_fn(a, b) traced_equal_fn(a, b, __FILE__, __LINE__, 0)
855 extern void        dump_equals();
856 #endif
857 extern bool        equalp(LispObject a, LispObject b);
858 extern LispObject  apply(LispObject fn, LispObject args,
859                          LispObject env,
860                          LispObject from);
861 extern LispObject  apply_lambda(LispObject def, LispObject args,
862                                 LispObject env, LispObject name);
863 extern void        deallocate_pages();
864 extern void        drop_heap_segments();
865 extern LispObject  gcd(LispObject a, LispObject b);
866 extern LispObject  get_pname(LispObject a);
867 extern LispObject  get(LispObject a, LispObject b, LispObject c=nil);
868 extern LispObject  get_basic_vector(int tag, int type, size_t length);
869 extern LispObject  get_basic_vector_init(size_t n, LispObject v);
870 extern LispObject  reduce_basic_vector_size(LispObject v, size_t len);
871 extern LispObject  get_vector(int tag, int type, size_t length);
872 extern LispObject  get_vector_init(size_t n, LispObject v);
873 extern LispObject  reduce_vector_size(LispObject n, size_t length);
874 extern void        prepare_for_borrowing();
875 
zero_out(void * p)876 inline void zero_out(void *p)
877 {   char *p1 = reinterpret_cast<char *>(doubleword_align_up(
878                                             reinterpret_cast<uintptr_t>(p)));
879     std::memset(p1, 0, CSL_PAGE_SIZE);
880 }
881 extern LispObject borrow_basic_vector(int tag, int type,
882                                       size_t length);
883 extern LispObject borrow_vector(int tag, int type, size_t length);
884 extern void       finished_borrowing();
885 extern uint64_t   hash_lisp_string(LispObject s);
886 extern void lose_C_def(LispObject a);
887 extern bool       geq2(LispObject a, LispObject b);
888 extern bool       greaterp2(LispObject a, LispObject b);
889 extern bool       lesseq2(LispObject a, LispObject b);
890 extern bool       lessp2(LispObject a, LispObject b);
891 extern LispObject list2(LispObject a, LispObject b);
892 extern LispObject list2star(LispObject a, LispObject b, LispObject c);
893 extern LispObject list2starrev(LispObject a, LispObject b,
894                                LispObject c);
895 extern LispObject list3(LispObject a, LispObject b, LispObject c);
896 extern LispObject list3rev(LispObject a, LispObject b, LispObject c);
897 extern LispObject list3star(LispObject a, LispObject b,
898                             LispObject c, LispObject d);
899 extern LispObject list4(LispObject a, LispObject b,
900                         LispObject c, LispObject d);
901 extern LispObject lognot(LispObject a);
902 extern LispObject macroexpand(LispObject form, LispObject env);
903 extern LispObject make_package(LispObject name);
904 extern LispObject make_string(const char *b);
905 extern LispObject make_nstring(const char *b, size_t n);
906 extern LispObject make_undefined_symbol(const char *s);
907 extern LispObject make_symbol(char const *s, int restartp,
908                               no_args *f0, one_arg *f1, two_args *f2,
909                               three_args *f3, fourup_args *f4up);
910 extern void stdout_printf(const char *fmt, ...);
911 extern void term_printf(const char *fmt, ...);
912 extern void err_printf(const char *fmt, ...);
913 extern void debug_printf(const char *fmt, ...);
914 extern void trace_printf(const char *fmt, ...);
915 extern const char  *my_getenv(const char *name);
916 extern LispObject  ncons(LispObject a);
917 extern LispObject  ndelete(LispObject a, LispObject b);
918 extern LispObject  negate(LispObject a);
919 extern LispObject  nreverse(LispObject a);
920 extern LispObject  nreverse2(LispObject a, LispObject b);
921 extern std::FILE   *open_file(char *filename,
922                               const char *original_name,
923                               size_t n, const char *dirn,
924                               std::FILE *old_file);
925 extern LispObject  plus2(LispObject a, LispObject b);
926 extern void        preserve(const char *msg, size_t len);
927 extern LispObject prin(LispObject u);
928 extern void debugprint(LispObject a, int depth=10);
929 extern void debugprint(const char *s, LispObject a);
930 extern void debugprint(const char *s);
931 extern const char *get_string_data(LispObject a, const char *why,
932                                    size_t &len);
933 extern LispObject prin_to_stdout(LispObject u);
934 extern LispObject prin_to_terminal(LispObject u);
935 extern LispObject prin_to_debug(LispObject u);
936 extern LispObject prin_to_query(LispObject u);
937 extern LispObject prin_to_trace(LispObject u);
938 extern LispObject prinhex_to_trace(const char *msg, LispObject value);
939 extern LispObject prin_to_error(LispObject u);
940 extern LispObject loop_print_stdout(LispObject o);
941 extern LispObject loop_print_terminal(LispObject o);
942 extern LispObject loop_print_debug(LispObject o);
943 extern LispObject loop_print_query(LispObject o);
944 extern LispObject loop_print_trace(LispObject o);
945 extern LispObject loop_print_error(LispObject o);
946 extern LispObject internal_prin(LispObject u, int prefix);
947 extern LispObject  princ(LispObject u);
948 extern LispObject  print(LispObject u);
949 extern LispObject  printc(LispObject u);
950 extern void        print_bignum(LispObject u, bool blankp, int nobreak);
951 extern void        print_bighexoctbin(LispObject u, int radix, int width,
952                                       bool blankp, int nobreak);
953 extern void        print_newbignum(LispObject u, bool blankp, int nobreak);
954 extern void        print_newbighexoctbin(LispObject u,
955         int radix, int width, bool blankp, int nobreak);
956 extern LispObject  putprop(LispObject a, LispObject b,
957                            LispObject c);
958 extern LispObject  quot2(LispObject a, LispObject b);
959 extern LispObject  quotrem2(LispObject a, LispObject b);
960 extern LispObject  rational(LispObject a);
961 extern LispObject  read_eval_print(int noisy);
962 extern void        set_fns(LispObject sym, no_args *f0, one_arg *f1,
963                            two_args *f2, three_args *f3, fourup_args *f4up);
964 extern void        init_heap_segments(double size);
965 extern void        grab_more_memory(size_t npages);
966 extern bool        allocate_more_memory();
967 extern void        setup(int restartp, double storesize);
968 extern LispObject  set_up_variables(int restart_flag);
969 extern void        warm_setup();
970 extern void        write_everything();
971 extern LispObject  simplify_string(LispObject s);
972 extern bool        stringp(LispObject a);
973 extern LispObject  times2(LispObject a, LispObject b);
974 extern int32_t     thirty_two_bits(LispObject a);
975 extern uint32_t    thirty_two_bits_unsigned(LispObject a);
976 extern int64_t     sixty_four_bits(LispObject a);
977 extern uint64_t    sixty_four_bits_unsigned(LispObject a);
978 
979 extern uint64_t    crc64(uint64_t crc, const void *buf, size_t size);
980 
981 #ifdef DEBUG
982 extern void validate_string_fn(LispObject a, const char *f, int l);
983 #define validate_string(a) validate_string_fn(a, __FILE__, __LINE__)
984 #else
985 #define validate_string(a) // nothing
986 #endif
987 
988 // The next few provide support for multiple values.
989 // At present I do what may count as the naive thing and every function
990 // leaves the variable exit_count set to indicate how many results it is
991 // returning.
992 
onevalue(LispObject r)993 inline LispObject onevalue(LispObject r)
994 {   exit_count = 1;
995     return r;
996 }
997 
nvalues(LispObject r,int n)998 inline LispObject nvalues(LispObject r, int n)
999 {   exit_count = n;
1000     return r;
1001 }
1002 
1003 // If I define an instance of SingleValued at the head of a procedure
1004 // then every exit from it will set exit_count to 1. This would let me
1005 // write just "return x;" rather than "return onevalue(x);".
1006 
1007 class SingleValued
1008 {
1009 public:
SingleValued()1010     SingleValued()
1011     {}
~SingleValued()1012     ~SingleValued()
1013     {   exit_count = 1;
1014     }
1015 };
1016 
1017 // If I know how many results some function should deliver (and it is > 1)
1018 // I can use this at the procedure head.
1019 
1020 class MultiValued
1021 {
1022     int n;
1023 public:
MultiValued(int nn)1024     MultiValued(int nn)
1025     {   n = nn;
1026     }
~MultiValued()1027     ~MultiValued()
1028     {   exit_count = n;
1029     }
1030 };
1031 
1032 //
1033 // The function "equal" seems to be pretty critical (certainly for Standard
1034 // Lisp mode and Reduce). So I write out the top-level part of it in-line
1035 // and only call the (messy) function in cases where it might be worth-while.
1036 // For Common Lisp I will presumably look at eql and cl_equal as well.
1037 // The test here says:
1038 //   If a and b are EQ then they are EQUAL,
1039 //   else if a and b have different types they are not EQUAL
1040 //   else if a has type fixnum, odds, sfloat, symbol
1041 //            then they are not EQUAL (those types need to be EQ to be EQUAL)
1042 //   otherwise call equal_fn(a, b) to decide the issue.
1043 //
1044 
1045 // If I am using TRACED_EQUAL then the inline function defeats my attempt to
1046 // keep track of where equal() is called from - so I revert to use of a macro.
1047 
1048 #ifdef TRACED_EQUAL
1049 #define equal(a, b)                                  \
1050    ((a == b) ? true :                                \
1051     ((a & TAG_BITS) != (b & TAG_BITS)) ? false :     \
1052     (need_more_than_eq(a)) ? equal_fn(a, b) :        \
1053     false)
1054 #else
equal(LispObject a,LispObject b)1055 inline bool equal(LispObject a, LispObject b)
1056 {   if (a == b) return true;  // This may be bad for (equal NaN NaN) ?
1057     else if ((a & TAG_BITS) != (b & TAG_BITS)) return false;
1058     else if (need_more_than_eq(a)) return equal_fn(a, b);
1059     else return false;
1060 }
1061 #endif
1062 
1063 #ifdef TRACED_EQUAL
1064 #define cl_equal(a, b)                            \
1065    ((a == b) ? true :                             \
1066     ((a & TAG_BITS) != (b & TAG_BITS)) ? false :  \
1067     (need_more_than_eq(a)) ? cl_equal_fn(a, b) :  \
1068     false)
1069 #else
cl_equal(LispObject a,LispObject b)1070 inline bool cl_equal(LispObject a, LispObject b)
1071 {   if (a == b) return true;  // This may be bad for (equal NaN NaN) ?
1072     else if ((a & TAG_BITS) != (b & TAG_BITS)) return false;
1073     else if (need_more_than_eq(a)) return cl_equal_fn(a, b);
1074     else return false;
1075 }
1076 #endif
1077 
eql(LispObject a,LispObject b)1078 inline bool eql(LispObject a, LispObject b)
1079 {   if (a == b) return true;  // This may be bad for (equal NaN NaN) ?
1080     else if ((a & TAG_BITS) != (b & TAG_BITS)) return false;
1081     else if (need_more_than_eq(a)) return eql_fn(a, b);
1082     else return false;
1083 }
1084 
1085 extern no_args     *no_arg_functions[];
1086 extern one_arg     *one_arg_functions[];
1087 extern two_args    *two_arg_functions[];
1088 extern three_args  *three_arg_functions[];
1089 extern fourup_args *fourup_arg_functions[];
1090 
1091 extern bool no_arg_traceflags[];
1092 extern bool one_arg_traceflags[];
1093 extern bool two_arg_traceflags[];
1094 extern bool three_arg_traceflags[];
1095 extern bool fourup_arg_traceflags[];
1096 
1097 extern const char *no_arg_names[];
1098 extern const char *one_arg_names[];
1099 extern const char *two_arg_names[];
1100 extern const char *three_arg_names[];
1101 extern const char *fourup_arg_names[];
1102 
1103 
1104 typedef struct setup_type
1105 {   const char *name;
1106     no_args *zero;
1107     one_arg *one;
1108     two_args *two;
1109     three_args *three;
1110     fourup_args *fourup;
1111 } setup_type;
1112 
1113 // In many cases a function will take a fixed number of arguments,
1114 // and these will make those cases tidier to express.
1115 
1116 #define DEF_0(name, code)   {name, code, G1W0, G2W0, G3W0, G4W0}
1117 #define DEF_1(name, code)   {name, G0W1, code, G2W1, G3W1, G4W1}
1118 #define DEF_2(name, code)   {name, G0W2, G1W2, code, G3W2, G4W2}
1119 #define DEF_3(name, code)   {name, G0W3, G1W3, G2W3, code, G4W3}
1120 #define DEF_4up(name, code) {name, G0W4up, G1W4up, G2W4up, G3W4up, code}
1121 
1122 extern setup_type const
1123 arith06_setup[], arith08_setup[], arith10_setup[], arith12_setup[],
1124               arith13_setup[], char_setup[], eval1_setup[], eval2_setup[],
1125               eval3_setup[], funcs1_setup[], funcs2_setup[], funcs3_setup[],
1126               lisphash_setup[], print_setup[], read_setup[],
1127               restart_setup[], mpi_setup[];
1128 #ifdef ARITHLIB
1129 extern setup_type const arith_setup[];
1130 #endif
1131 
1132 extern setup_type const
1133 u01_setup[], u02_setup[], u03_setup[], u04_setup[],
1134           u05_setup[], u06_setup[], u07_setup[], u08_setup[], u09_setup[],
1135           u10_setup[], u11_setup[], u12_setup[], u13_setup[], u14_setup[],
1136           u15_setup[], u16_setup[], u17_setup[], u18_setup[], u19_setup[],
1137           u20_setup[], u21_setup[], u22_setup[], u23_setup[], u24_setup[],
1138           u25_setup[], u26_setup[], u27_setup[], u28_setup[], u29_setup[],
1139           u30_setup[], u31_setup[], u32_setup[], u33_setup[], u34_setup[],
1140           u35_setup[], u36_setup[], u37_setup[], u38_setup[], u39_setup[],
1141           u40_setup[], u41_setup[], u42_setup[], u43_setup[], u44_setup[],
1142           u45_setup[], u46_setup[], u47_setup[], u48_setup[], u49_setup[],
1143           u50_setup[], u51_setup[], u52_setup[], u53_setup[], u54_setup[],
1144           u55_setup[], u56_setup[], u57_setup[], u58_setup[], u59_setup[],
1145           u60_setup[];
1146 
1147 extern setup_type const *setup_tables[];
1148 
1149 #ifdef NAG
1150 extern setup_type const nag_setup[], asp_setup[];
1151 extern setup_type const socket_setup[], xdr_setup[], grep_setup[];
1152 extern setup_type const gr_setup[], axfns_setup[];
1153 #endif
1154 
1155 #ifdef OPENMATH
1156 extern setup_type const om_setup[];
1157 extern setup_type const om_parse_setup[];
1158 #endif
1159 
1160 extern const char *find_image_directory(int argc, const char *argv[]);
1161 extern char program_name[64];
1162 extern LispObject declare_fn(LispObject args, LispObject env);
1163 extern LispObject function_fn(LispObject args, LispObject env);
1164 extern LispObject let_fn_1(LispObject bvl, LispObject body,
1165                            LispObject env, int compilerp);
1166 extern LispObject mv_call_fn(LispObject args, LispObject env);
1167 extern LispObject go_fn(LispObject args, LispObject env);
1168 extern LispObject cond_fn(LispObject args, LispObject env);
1169 extern LispObject progn_fn(LispObject args, LispObject env);
1170 extern LispObject quote_fn(LispObject args, LispObject env);
1171 extern LispObject tagbody_fn(LispObject args, LispObject env);
1172 
1173 //
1174 // The variables here are always extern - they never survive in an image
1175 // file.
1176 //
1177 extern LispObject resource_exceeded();
1178 extern int64_t time_base,  space_base,  io_base,  errors_base;
1179 extern int64_t time_now,   space_now,   io_now,   errors_now;
1180 extern int64_t time_limit, space_limit, io_limit, errors_limit;
1181 
1182 //
1183 // Flags used to toggle the protection or otherwise of symbols, and
1184 // whether to warn about attempts to redefine them.
1185 //
1186 extern bool symbol_protect_flag, warn_about_protected_symbols;
1187 
1188 #ifdef HASH_STATISTICS
1189 extern uint64_t Nhget, Nhgetp, Nhput1, Nhputp1, Nhput2, Nhputp2,
1190        Nhputtmp;
1191 extern uint64_t Noget, Nogetp, Noput, Noputp, Noputtmp;
1192 #endif
1193 
1194 #endif // header_externs_h
1195 
1196 // end of externs.h
1197