/*
 * Copyright (c) 2001-2026 James Bailie <jimmy@mammothcheese.ca>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *     * The name of James Bailie may not be used to endorse or promote
 * products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <term.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <dirent.h>
#include <termios.h>
#include <db.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/un.h>
#include <sys/mman.h>
#include <signal.h>
#include <regex.h>
#include <assert.h>
#include <math.h>
#include <pwd.h>
#include <grp.h>
#include <curses.h>
#include <libgen.h>
#include <calendar.h>
#include <glob.h>
#include <arpa/inet.h>
#include <syslog.h>

#ifdef SQL
#include "sqlite3.h"
#endif

#define HASH_SIZE 256
#define HASH_RESIZE 2
#define POOL_INC 65536
#define GC_FREQ 32768

#define STACK_PUSH( _s_, _o_ ) { if (( _s_ )->free )\
   {\
      if (( _s_ )->used ) ++( _s_ )->top;\
      --( _s_ )->free;\
      ++( _s_ )->used;\
      ( _s_ )->top->ptr = ( struct object *)( _o_ );\
   }\
   else stack_push( _s_, _o_ ); }

#define STACK_PUSH_INT( _s_, _o_ ) { if (( _s_ )->free )\
   {\
      if (( _s_ )->used ) ++( _s_ )->top;\
      --( _s_ )->free;\
      ++( _s_ )->used;\
      ( _s_ )->top->integer = ( int )( _o_ );\
   }\
   else stack_push_int( _s_, _o_ ); }

#define STACK_POP( _s_ ) ( !( _s_ )->used ? NULL : \
   ( ++( _s_ )->free, --( _s_ )->used, \
   ((( _s_ )->top == ( _s_ )->values ) ? ( _s_ )->top->ptr : \
   ( --( _s_ )->top, (( _s_ )->top + 1 )->ptr ))))

#define STACK_POP_INT( _s_ ) ( !( _s_ )->used ? 0 : \
   ( ++( _s_ )->free, --( _s_ )->used, \
   ((( _s_ )->top == ( _s_ )->values ) ? ( _s_ )->top->integer : \
   ( --( _s_ )->top, (( _s_ )->top + 1 )->integer ))))

#define STRING_APPEND( _s_, _c_ ) { if (( _s_ )->free )\
   {\
      --( _s_ )->free;\
      ++( _s_ )->used;\
      *( _s_ )->top++ = _c_;\
      *( _s_ )->top ='\0';\
   }\
   else string_append( _s_, _c_ ); }

#define STRING_CHOP( _s_ ) if (( _s_ )->used ) { *--( _s_ )->top = '\0'; --( _s_ )->used; ++( _s_ )->free; }
#define STRING_TRUNCATE( _s_ ) if (( _s_ )->used ) { ( _s_ )->free += ( _s_ )->used; ( _s_ )->used = 0; *( _s_ )->str = '\0'; ( _s_ )->top = ( _s_ )->str; }

#define print_object(p) do_printing(p,0)
#define bzero(n,m) { char *_ptr; int i; for( _ptr = ( char *)n, i = m; i; --i ) *_ptr++ = '\0'; }
#define bcopy(n,m,i) { char *_ptr = n, *_ptr2 = m; int j; for( j = i; j; --j ) *_ptr2++ = *_ptr++; }
#define abs(n) (( n ) < 0 ? -( n ) : ( n ))
#define FUNC(n) int do_ ## n ( char *, struct object * )

#define type(n) ( n & 15 )
#define set(n) ( n |= 16 )
#define unset(n) ( n &= 15 )
#define isitset(n) ( n & 16 )

#define setlist(n) ( n |= 1 )
#define islist(n) ( n & 1 )

#define mark(n) ( n |= 2 )
#define unmark(n) ( n &= -3 )
#define ismarked(n) ( n & 2 )

#define numberp(n) ( n & 4 )
#define setnumber(n) ( n |= 4 )

#define ATOM_SYMBOL     1
#define ATOM_STRING     2
#define ATOM_FIXNUM     3
#define ATOM_REGEXP     4
#define ATOM_TABLE      5
#define ATOM_STACK      6
#define ATOM_INTRINSIC  7
#define ATOM_DB         8
#define ATOM_CLOSURE    9
#define ATOM_MACRO      10
#define ATOM_ACT_RECORD 11
#define ATOM_RECORD     12
#define ATOM_SQL        13
#define ATOM_LIST       14
#define ATOM_ATOM       15

#define TOK_STRING  1
#define TOK_SYMBOL  2
#define TOK_FIXNUM  3
#define TOK_SPECIAL 4
#define TOK_OPEN    5
#define TOK_CLOSE   6
#define TOK_END     7
#define TOK_QUOTE   8
#define TOK_COMMENT 9
#define TOK_MINUS   10

#define ERR_ARGS         0
#define ERR_MISSING_ARGS 1
#define ERR_MISSING_ARG  2
#define ERR_MORE_ARGS    3
#define ERR_EVAL         4
#define ERR_ARG_TYPE     5
#define ERR_CONSTANT     6
                        
char *error_messages[] =
{
   "%s: called with argument(s).\n",
   "%s: called without argument(s).\n",
   "%s: called without argument %d.\n",
   "%s: called with more than %d argument(s).\n",
   "%s: evaluation of argument %d failed.\n",
   "%s: argument %d did not evaluate to a(n) %s.\n",
   "%s: argument %d evaluated to a constant.\n"
};

struct termios canon_termios;

char **first_arg, **last_arg, **arg_ptr;
char *syslog_name = NULL;

union stack_u {
   long int integer;
   void *ptr;
};

struct stack
{
   long int free, used;
   union stack_u *top, *values;
};

struct hash_elt
{
   union stack_u element;
   struct hash_elt *next;
   unsigned long int hash_key;
   struct atom *key;
};

struct table
{
   struct hash_elt **hash;
   unsigned long int size, items, resize;
};
	
struct lstring
{
   char *string;
   unsigned long int length;
};

struct object
{
   int flags;

   union {
      long int number;
      struct atom *atom;
      struct object *head;
   } data;

   struct object *next;
};

struct atom
{
   char *syntax;
   unsigned long int len;
   int id;

   union {
      regex_t *regexp;

      struct table *table;
      struct stack *stack;

#ifdef SQL
      sqlite3 *db;
      sqlite3_stmt *sql;
#endif

      int ( *function )( char *, struct object * );

      struct closure *closure;
      struct stack *act_record;
      struct lstring *string;

      union stack_u *record;
      long int number;
   } data;

   int flags;
};

struct closure
{
   struct object *text, *env;
};

struct string
{
   unsigned int free, used;
   char *top;
   char *str;
};

void sigchld_handler( int );
void sigalrm_handler( int );
void sigwinch_handler( int );
void sigterm_handler( int );

void set_sigalrm_intr();
void set_sigterm_intr();
void set_sigwinch_intr();

unsigned long int hash_key( char *, unsigned long int );
int pipe_open( char *, char *, int, int, int * );
void print_err( int, char *, int, int );
int evaluate_body( struct object *, int * );

DB *buffer = NULL;
DBT dbt_key, dbt_value;
recno_t key_data;

char *path = NULL;

regex_t find_poss_regex, merge_regex;

int string_inc = 256, stack_inc = 16, serv_fd = -1, isdaemon = 0, blocked = 0;
int totally_complete = 0, underscore_id = -1;
int tty_mode = 1, printer = 1, shared_len = 0;

volatile int sigterm = 0, sigalrm = 0;

char *shared_map = NULL;

struct object *sql_list = NULL;

struct stack *history;
int history_ptr;

struct hash_elt **env;
struct hash_elt **syntax;
unsigned long int syntax_size, syntax_resize, syntax_items;

struct object *local_env = NULL;
struct closure *current_closure = NULL;

struct stack *get_hash_key_ids( struct hash_elt **, int );
struct stack *get_hash_values( struct hash_elt **, int );
struct object *copy_object( struct object * );

void canon( char * );
void close_descriptors();

struct object *thrown = NULL, *empty;
struct string *token;

struct stack *input_stack, *quotes_pending, *seen, *buffer_stack,
   *stack, *open_envs;

struct object *object_pool, *object_pool_ptr;
struct hash_elt *hash_elt_pool, *hash_elt_pool_ptr;

void display_line( struct string *, struct string *,
                   char *, int, struct stack * );

struct stack *executables = NULL;

struct stack *object_pool_stack, *atom_pool_stack, *reclaimed_objects,
   *hash_elt_pool_stack, *reclaimed_hash_elts, *reclaimed_atoms, *reclaimed_ids;

int make_act_record( struct object *,
                     struct closure *,
                     struct stack *,
                     char *,
                     int );

struct atom *atom_pool, *old_atom_pool, *atom_pool_ptr;

pid_t child_pid = -1;

int object_pool_free, atom_pool_free, hash_elt_pool_free, fatal = 0, 
   lambda_id, macro_id, quote_id, stop = 0, stack_counter = 1,
   sql_counter = 1, zombies = 0, string_counter = -1,
   closure_counter = 1, child_fd = -1, child_eof = 0,
   scgi_header_len = 0, objects_allocated = 0, atoms_allocated = 0,
   objects_at_last_collect = 0, atoms_at_last_collect = 0,
   act_record_counter = 1, db_counter = 1, record_counter = 1,
   table_counter = 1, rx_counter = 1, gensym_counter = 1, atom_counter = 1,
   interactive = 0, next_iteration = 0, tailcall = 0,
   unix_server = 0;

char *tailcall_syntax = NULL;

struct stack *descriptors[ 3 ], *input_buffer_stack;

struct stack *string_stack;

struct hash_elt **bookmarks;
struct stack *bookmark_stack;
void adjust_bookmarks( int, int, int );
void delete_bookmarks( int, int );
void func_err( struct object *car );

struct object *make_object();
struct atom *make_atom();
struct hash_elt *make_hash_elt();

struct closure *make_closure();
int create_closure( struct object *, int );
struct atom *get_id( char *, unsigned long int, int );

void *memory( unsigned long int );
void free_executables();
struct object *duplicate_object( struct object * );

void fatal_signal_handler( int );
void unmark_objects();
void mark_bookmarks();
void mark_list( struct object * );
void mark_table( struct hash_elt **, int );
void mark_stack( struct stack * );
void mark_closure( struct closure * );
void mark_act_record( struct stack * );
void mark_object( struct object * );
void sweep_atoms();
void free_atom( struct atom * );
void collect_garbage();

int set_local( int, struct object * );

int load( char * );
void cleanup();
int evaluate();
void resume( char *, int );
int apply_closure( char *, struct closure *, struct object *, int );
int get_token( int, int );
int process_token( int, int );
int parse( int );
int getline_from_file( char *, int );

struct stack *make_stack();
void stack_push( struct stack *, void * );
void stack_push_int( struct stack *, long int );
struct object *stack_pop( struct stack * );
long int stack_pop_int( struct stack * );
void stack_truncate( struct stack *, long int );
void stack_free( struct stack * );

void do_printing( struct object *ptr, int recursive );

int insert_elt( struct hash_elt **, struct atom *, struct object*, unsigned long int );
void insert_elt_int( struct hash_elt **, struct atom *, long int );
int remove_elt( struct hash_elt **, struct atom *, unsigned long int );
void *lookup_elt( struct hash_elt **, struct atom *, unsigned long int );
int lookup_elt_int( struct hash_elt **, struct atom * );
void hash_free( struct hash_elt **, unsigned long int );

struct object *lookup_local( int id );

#define lookup_binding(n) ( struct object *)lookup_elt( env, n, HASH_SIZE )
#define insert_binding(a, m) insert_elt( env, a, m, HASH_SIZE )
#define remove_binding(n) remove_elt( env, n, HASH_SIZE )

struct object *make_atom_from_act_record( struct stack * );
struct object *make_atom_from_number( long int );
struct object *make_atom_from_closure( struct closure *, int );
struct object *make_atom_from_string( char *, unsigned long int );
struct object *make_atom_directly_from_string( char *, unsigned long int );

struct string *make_string();
void string_free( struct string * );
void string_prepend( struct string *, char );
void string_append( struct string *, char );
void string_chop( struct string * );
void string_truncate( struct string * );
void string_assign( struct string *, char *, int );
void string_erase( struct string *, int );

char *str_dup( char *, unsigned long int );

FUNC( file2string );
FUNC( progn );
FUNC( cons );
FUNC( quote );
FUNC( car );
FUNC( cdr );
FUNC( eq );
FUNC( atomp );
FUNC( append );
FUNC( set );
FUNC( eval );
FUNC( if );
FUNC( and );
FUNC( or );
FUNC( list );
FUNC( length );
FUNC( not );
FUNC( print );
FUNC( println );
FUNC( newline );
FUNC( load );
FUNC( getline );
FUNC( rescan_path );
FUNC( complete );
FUNC( cols );
FUNC( lines );
FUNC( fixnump );
FUNC( stringp );
FUNC( split );
FUNC( join );
FUNC( match );
FUNC( matches );
FUNC( substitute );
FUNC( regcomp );
FUNC( sort );
FUNC( sortlist );
FUNC( sortcar );
FUNC( while );
FUNC( until );
FUNC( do );
FUNC( throw );
FUNC( catch );
FUNC( die );
FUNC( stringify );
FUNC( digitize );
FUNC( intern );

FUNC( add );
FUNC( subtract );
FUNC( multiply );
FUNC( divide );
FUNC( modulo );
FUNC( lesser );
FUNC( lesser_or_eq );
FUNC( greater );
FUNC( greater_or_eq );

FUNC( abs );
FUNC( char );
FUNC( code );
FUNC( open );
FUNC( close );
FUNC( insert );
FUNC( delete );
FUNC( lastline );
FUNC( retrieve );
FUNC( filter );
FUNC( write );
FUNC( read );
FUNC( empty );
FUNC( slice );
FUNC( find );
FUNC( input );
FUNC( output );
FUNC( system );
FUNC( maxidx );
FUNC( chdir );
FUNC( mkdir );
FUNC( boundp );
FUNC( buffer );
FUNC( buffers );
FUNC( switch );
FUNC( version );
FUNC( gensym );
FUNC( libdir );
FUNC( substring );
FUNC( expand );
FUNC( interact );
FUNC( current );
FUNC( next );
FUNC( prev );
FUNC( rewind );
FUNC( pwd );
FUNC( exit );
FUNC( table );
FUNC( hash );
FUNC( unhash );
FUNC( lookup );
FUNC( keys );
FUNC( values );
FUNC( redirect );
FUNC( resume );
FUNC( warn );
FUNC( getenv );
FUNC( directory );
FUNC( chomp );
FUNC( chop );
FUNC( unlink );
FUNC( rmdir );
FUNC( rename );
FUNC( words );
FUNC( date );
FUNC( unless );
FUNC( when );
FUNC( test );
FUNC( continue );
FUNC( block );
FUNC( unblock );
FUNC( exists );
FUNC( suspend);
FUNC( beep );
FUNC( strcmp );
FUNC( fatal );
FUNC( nofatal );
FUNC( let );
FUNC( letn );
FUNC( labels );
FUNC( cond );

#ifdef SQL
FUNC( sqlite_open );
FUNC( sqlite_close );
FUNC( sqlite_exec );
FUNC( sqlite_prepare );
FUNC( sqlite_step );
FUNC( sqlite_finalize );
FUNC( sqlite_reset );
FUNC( sqlite_row );
FUNC( sqlite_bind );
FUNC( sqlitep );
FUNC( sqlp );
#endif

FUNC( stack );
FUNC( clear );
FUNC( push );
FUNC( pop );
FUNC( shift );
FUNC( unshift );
FUNC( store );
FUNC( index );
FUNC( time );
FUNC( random );
FUNC( topidx );
FUNC( extract );
FUNC( transfer );
FUNC( pipe );
FUNC( setenv );
FUNC( unsetenv );

FUNC( child_open );
FUNC( child_running );
FUNC( child_read );
FUNC( child_write );
FUNC( child_close );
FUNC( child_ready );
FUNC( child_wait );

FUNC( protect );
FUNC( tailcall );
FUNC( stat );
FUNC( access );

FUNC( setmark );
FUNC( getmark );

FUNC( noprinter );
FUNC( printer );
FUNC( shexec );
FUNC( exec );
FUNC( truncate );

FUNC( symbolp );
FUNC( regexpp );
FUNC( tablep );
FUNC( stackp );
FUNC( intrinsicp );
FUNC( closurep );
FUNC( macrop );
FUNC( recordp );

FUNC( dynamic_let );
FUNC( chmod );
FUNC( chown );
FUNC( basename );
FUNC( dirname );
FUNC( checkpass );
FUNC( setuid );
FUNC( setgid );
FUNC( setegid );
FUNC( seteuid );
FUNC( getuid );
FUNC( geteuid );
FUNC( getgid );

FUNC( seek );
FUNC( getchars );
FUNC( readlock );
FUNC( writelock );
FUNC( unlock );
FUNC( hostname );
FUNC( symlink );
FUNC( gecos );

FUNC( record );
FUNC( getfield );
FUNC( setfield );
FUNC( extend );
FUNC( for );
FUNC( iterate );
FUNC( dynamic_extent );
FUNC( timethen );
FUNC( inc );
FUNC( dec );
FUNC( setq );
FUNC( child_eof );
FUNC( crypt );
FUNC( loop );
FUNC( datethen );
FUNC( days2date );
FUNC( date2days );
FUNC( week );
FUNC( weekday );
FUNC( date2time );
FUNC( localtime );
FUNC( utctime );
FUNC( month );
FUNC( negate );

FUNC( getpid );
FUNC( getppid );
FUNC( setpgid );
FUNC( getpgrp );
FUNC( tcgetpgrp );
FUNC( tcsetpgrp );
FUNC( kill );
FUNC( killpg );
FUNC( fork );
FUNC( forkpipe );
FUNC( glob );
FUNC( wait );
FUNC( zombies );
FUNC( nozombies );
FUNC( stderr2stdout );
FUNC( stdout2stderr );
FUNC( zombiesp );

FUNC( nth );
FUNC( nthcdr );
FUNC( command_lookup );
FUNC( reset_history );

FUNC( dec2hex );
FUNC( hex2dec );

FUNC( listen );
FUNC( listen_unix );
FUNC( stop_listening );
FUNC( accept );
FUNC( getpeername );
FUNC( daemonize );
FUNC( syslog );
FUNC( flush_stdout );
FUNC( receive_descriptors );
FUNC( send_descriptors );

FUNC( busymap );
FUNC( nobusymap );
FUNC( busy );
FUNC( notbusy );
FUNC( busyp );

FUNC( base64_encode );
FUNC( base64_decode );

FUNC( eval_string );
FUNC( blind_eval_string );
FUNC( temporary );
FUNC( eval_buffer );

FUNC( chroot );
FUNC( getline_ub );

FUNC( pause );
FUNC( display );
FUNC( scrollup );
FUNC( scrolldn );
FUNC( clearscreen );
FUNC( goto );
FUNC( clearline );
FUNC( hide );
FUNC( show );
FUNC( insertln );
FUNC( getchar );
FUNC( pushback );
FUNC( canon );
FUNC( nocanon );
FUNC( boldface );
FUNC( normal );

FUNC( fg_black );
FUNC( fg_red );
FUNC( fg_green );
FUNC( fg_yellow );
FUNC( fg_blue );
FUNC( fg_magenta );
FUNC( fg_cyan );
FUNC( fg_white );

FUNC( bg_black );
FUNC( bg_red );
FUNC( bg_green );
FUNC( bg_yellow );
FUNC( bg_blue );
FUNC( bg_magenta );
FUNC( bg_cyan );
FUNC( bg_white );

FUNC( isatty );
FUNC( sleep );
FUNC( get_scgi_header );

FUNC( form_decode );
FUNC( form_encode );

FUNC( save_history );
FUNC( load_history );
FUNC( sigtermp );

char *cl, *ce, *cm, *ti, *te, *vi, *ve, *sf, *sr, *al, *sc, *rc, *bd, *me,
   *af, *ab, *nb;

int pushed_back = -1, sigwinch = 0;

int ( *intrinsics[] )( char *, struct object * ) =
{
   do_file2string,
   do_progn,
   do_cons,
   do_quote,
   do_car,
   do_cdr,
   do_eq,
   do_atomp,
   do_append,
   do_set,
   do_eval,
   do_if,
   do_and,
   do_or,
   do_list,
   do_not,
   do_print,
   do_println,
   do_newline,
   do_load,
   do_getline,
   do_rescan_path,
   do_complete,
   do_cols,
   do_lines,
   do_fixnump,
   do_stringp,
   do_split,
   do_join,
   do_match,
   do_matches,
   do_substitute,
   do_regcomp,
   do_sort,
   do_sortlist,
   do_sortcar,
   do_while,
   do_until,
   do_do,
   do_throw,
   do_catch,
   do_die,
   do_stringify,
   do_digitize,
   do_intern,

   do_add,
   do_subtract,
   do_multiply,
   do_divide,
   do_modulo,
   do_lesser,
   do_lesser_or_eq,
   do_greater,
   do_greater_or_eq,

   do_abs,
   do_char,
   do_code,
   do_open,
   do_close,
   do_insert,
   do_delete,
   do_lastline,
   do_retrieve,
   do_filter,
   do_write,
   do_read,
   do_empty,
   do_slice,
   do_find,
   do_input,
   do_output,
   do_system,
   do_maxidx,
   do_chdir,
   do_mkdir,
   do_boundp,
   do_buffer,
   do_buffers,
   do_switch,
   do_version,
   do_gensym,
   do_libdir,
   do_substring,
   do_expand,
   do_interact,
   do_current,
   do_next,
   do_prev,
   do_rewind,
   do_pwd,
   do_exit,
   do_table,
   do_hash,
   do_unhash,
   do_lookup,
   do_keys,
   do_values,
   do_redirect,
   do_resume,
   do_warn,
   do_getenv,
   do_directory,
   do_chomp,
   do_chop,
   do_unlink,
   do_rmdir,
   do_rename,
   do_words,
   do_date,
   do_when,
   do_unless,
   do_test,
   do_continue,
   do_block,
   do_unblock,
   do_exists,
   do_suspend,
   do_beep,
   do_length,
   do_strcmp,
   do_fatal,
   do_nofatal,
   do_let,
   do_letn,
   do_labels,
   do_cond,

#ifdef SQL
   do_sqlite_open,
   do_sqlite_close,
   do_sqlite_exec,
   do_sqlite_prepare,
   do_sqlite_step,
   do_sqlite_finalize,
   do_sqlite_reset,
   do_sqlite_row,
   do_sqlite_bind,
   do_sqlitep,
   do_sqlp,
#endif

   do_stack,
   do_clear,
   do_push,
   do_pop,
   do_store,
   do_index,
   do_time,
   do_random,
   do_topidx,
   do_extract,
   do_transfer,
   do_pipe,
   do_setenv,
   do_unsetenv,
   do_child_open,
   do_child_running,
   do_child_read,
   do_child_write,
   do_child_close,
   do_child_ready,
   do_child_wait,
   do_protect,
   do_tailcall,
   do_stat,
   do_access,
   do_setmark,
   do_getmark,
   do_shift,
   do_unshift,

   do_pause,
   do_display,
   do_scrollup,
   do_scrolldn,
   do_clearscreen,
   do_goto,
   do_clearline,
   do_hide,
   do_show,
   do_insertln,
   do_getchar,
   do_pushback,
   do_canon,
   do_nocanon,
   do_boldface,
   do_normal,

   do_noprinter,
   do_printer,
   do_shexec,
   do_exec,
   do_truncate,

   do_symbolp,
   do_regexpp,
   do_tablep,
   do_stackp,
   do_intrinsicp,
   do_closurep,
   do_macrop,
   do_recordp,
   do_dynamic_let,
   do_chmod,
   do_chown,
   do_basename,
   do_dirname,
   do_checkpass,
   do_setuid,
   do_setgid,
   do_setegid,
   do_seteuid,
   do_getuid,
   do_getgid,
   do_geteuid,
   do_seek,
   do_getchars,
   do_readlock,
   do_writelock,
   do_unlock,
   do_hostname,
   do_symlink,
   do_gecos,
   do_record,
   do_setfield,
   do_getfield,
   do_extend,
   do_for,
   do_iterate,
   do_dynamic_extent,
   do_timethen,
   do_inc,
   do_dec,
   do_setq,
   do_child_eof,
   do_crypt,
   do_loop,
   do_days2date,
   do_date2days,
   do_week,
   do_weekday,
   do_date2time,
   do_localtime,
   do_utctime,
   do_month,
   do_negate,
   do_getpid,
   do_getppid,
   do_setpgid,
   do_getpgrp,
   do_tcgetpgrp,
   do_tcsetpgrp,
   do_kill,
   do_killpg,
   do_fork,
   do_forkpipe,
   do_glob,
   do_wait,
   do_zombies,
   do_nozombies,
   do_stderr2stdout,
   do_stdout2stderr,
   do_nth,
   do_nthcdr,
   do_command_lookup,
   do_reset_history,
   do_zombiesp,
   do_dec2hex,
   do_hex2dec,
   do_listen,
   do_listen_unix,
   do_stop_listening,
   do_accept,
   do_receive_descriptors,
   do_send_descriptors,
   do_getpeername,
   do_daemonize,
   do_syslog,
   do_base64_encode,
   do_base64_decode,
   do_eval_string,
   do_blind_eval_string,
   do_flush_stdout,
   do_temporary,
   do_eval_buffer,
   do_datethen,
   do_chroot,
   do_getline_ub,
   do_isatty,
   do_busymap,
   do_nobusymap,
   do_busy,
   do_notbusy,
   do_busyp,
   do_sleep,
   do_get_scgi_header,
   do_form_decode,
   do_form_encode,
   do_fg_black,
   do_fg_red,
   do_fg_green,
   do_fg_yellow,
   do_fg_blue,
   do_fg_magenta,
   do_fg_cyan,
   do_fg_white,
   do_bg_black,
   do_bg_red,
   do_bg_green,
   do_bg_yellow,
   do_bg_blue,
   do_bg_magenta,
   do_bg_cyan,
   do_bg_white,
   do_save_history,
   do_load_history,
   do_sigtermp,
   NULL
};

char *intrinsic_syntax[] =
{
   "<FILE2STRING>",         "file2string",
   "<PROGN>",               "progn",
   "<CONS>",                "cons",
   "<QUOTE>",               "quote",
   "<CAR>",                 "car",
   "<CDR>",                 "cdr",
   "<EQ>",                  "eq",
   "<ATOMP>",               "atomp",
   "<APPEND>",              "append",
   "<SET>",                 "set",
   "<EVAL>",                "eval",
   "<IF>",                  "if",
   "<AND>",                 "and",
   "<OR>",                  "or",
   "<LIST>",                "list",
   "<NOT>",                 "not",
   "<PRINT>",               "print",
   "<PRINTLN>",             "println",
   "<NEWLINE>",             "newline",
   "<LOAD>",                "load",
   "<GETLINE>",             "getline",
   "<RESCAN_PATH>",         "rescan_path",
   "<COMPLETE>",            "complete",
   "<COLS>",                "cols",
   "<LINES>",               "lines",
   "<FIXNUMP>",             "fixnump",
   "<STRINGP>",             "stringp",
   "<SPLIT>",               "split",
   "<JOIN>",                "join",
   "<MATCH>",               "match",
   "<MATCHES>",             "matches",
   "<SUBSTITUTE>",          "substitute",
   "<REGCOMP>",             "regcomp",
   "<SORT>",                "sort",
   "<SORTLIST>",            "sortlist",
   "<SORTCAR>",             "sortcar",
   "<WHILE>",               "while",
   "<UNTIL>",               "until",
   "<DO>",                  "do",
   "<THROW>",               "throw",
   "<CATCH>",               "catch",
   "<DIE>",                 "die",
   "<STRINGIFY>",           "stringify",
   "<DIGITIZE>",            "digitize",
   "<INTERN>",              "intern",
   "<ADD>",                 "+",
   "<SUBTRACT>",            "-",
   "<MULTIPLY>",            "*",
   "<DIVIDE>",              "/",
   "<MODULO>",              "%",
   "<LESSER>",              "<",
   "<LESSER_OR_EQ>",        "<=",
   "<GREATER>",             ">",
   "<GREATER_OR_EQ>",       ">=",
   "<ABS>",                 "abs",
   "<CHAR>",                "char",
   "<CODE>",                "code",
   "<OPEN>",                "open",
   "<CLOSE>",               "close",
   "<INSERT>",              "insert",
   "<DELETE>",              "delete",
   "<LASTLINE>",            "lastline",
   "<RETRIEVE>",            "retrieve",
   "<FILTER>",              "filter",
   "<WRITE>",               "write",
   "<READ>",                "read",
   "<EMPTY>",               "empty",
   "<SLICE>",               "slice",
   "<FIND>",                "find",
   "<INPUT>",               "input",
   "<OUTPUT>",              "output",
   "<SYSTEM>",              "system",
   "<MAXIDX>",              "maxidx",
   "<CHDIR>",               "chdir",
   "<MKDIR>",               "mkdir",
   "<BOUNDP>",              "boundp",
   "<BUFFER>",              "buffer",
   "<BUFFERS>",             "buffers",
   "<SWITCH>",              "switch",
   "<VERSION>",             "version",
   "<GENSYM>",              "gensym",
   "<LIBDIR>",              "libdir",
   "<SUBSTRING>",           "substring",
   "<EXPAND>",              "expand",
   "<INTERACT>",            "interact",
   "<CURRENT>",             "current",
   "<NEXT>",                "next",
   "<PREV>",                "prev",
   "<REWIND>",              "rewind",
   "<PWD>",                 "pwd",
   "<EXIT>",                "exit",
   "<TABLE>",               "table",
   "<HASH>",                "hash",
   "<UNHASH>",              "unhash",
   "<LOOKUP>",              "lookup",
   "<KEYS>",                "keys",
   "<VALUES>",              "values",
   "<REDIRECT>",            "redirect",
   "<RESUME>",              "resume",
   "<WARN>",                "warn",
   "<GETENV>",              "getenv",
   "<DIRECTORY>",           "directory",
   "<CHOMP>",               "chomp",
   "<CHOP>",                "chop",
   "<UNLINK>",              "unlink",
   "<RMDIR>",               "rmdir",
   "<RENAME>",              "rename",
   "<WORDS>",               "words",
   "<DATE>",                "date",
   "<WHEN>",                "when",
   "<UNLESS>",              "unless",
   "<TEST>",                "test",
   "<CONTINUE>",            "continue",
   "<BLOCK>",               "block",
   "<UNBLOCK>",             "unblock",
   "<EXISTS>",              "exists",
   "<SUSPEND>",             "suspend",
   "<BEEP>",                "beep",
   "<LENGTH>",              "length",
   "<STRCMP>",              "strcmp",
   "<FATAL>",               "fatal",
   "<NOFATAL>",             "nofatal",
   "<LET>",                 "let",
   "<LETN>",                "letn",
   "<LABELS>",              "labels",
   "<COND>",                "cond",

#ifdef SQL
   "<SQLITE_OPEN>",         "sqlite_open",
   "<SQLITE_CLOSE>",        "sqlite_close",
   "<SQLITE_EXEC>",         "sqlite_exec",
   "<SQLITE_PREPARE>",      "sqlite_prepare",
   "<SQLITE_STEP>",         "sqlite_step",
   "<SQLITE_FINALIZE>",     "sqlite_finalize",
   "<SQLITE_RESET>",        "sqlite_reset",
   "<SQLITE_ROW>",          "sqlite_row",
   "<SQLITE_BIND>",         "sqlite_bind",
   "<SQLP>",                "sqlp",
   "<SQLITEP>",             "sqlitep",
#endif

   "<STACK>",               "stack",
   "<CLEAR>",               "clear",
   "<PUSH>",                "push",
   "<POP>",                 "pop",
   "<STORE>",               "store",
   "<INDEX>",               "index",
   "<TIME>",                "time",
   "<RANDOM>",              "random",
   "<TOPIDX>",              "topidx",
   "<EXTRACT>",             "extract",
   "<TRANSFER>",            "transfer",
   "<PIPE>",                "pipe",
   "<SETENV>",              "setenv",
   "<UNSETENV>",            "unsetenv",
   "<CHILD_OPEN>",          "child_open",
   "<CHILD_RUNNING>",       "child_running",
   "<CHILD_READ>",          "child_read",
   "<CHILD_WRITE>",         "child_write",
   "<CHILD_CLOSE>",         "child_close",
   "<CHILD_READY>",         "child_ready",
   "<CHILD_WAIT>",          "child_wait",
   "<PROTECT>",             "protect",
   "<TAILCALL>",            "tailcall",
   "<STAT>",                "stat",
   "<ACCESS>",              "access",
   "<SETMARK>",             "setmark",
   "<GETMARK>",             "getmark",
   "<SHIFT>",               "shift",
   "<UNSHIFT>",             "unshift",

   "<PAUSE>",               "pause",
   "<DISPLAY>",             "display",
   "<SCROLLUP>",            "scrollup",
   "<SCROLLDN>",            "scrolldn",
   "<CLEARSCREEN>",         "clearscreen",
   "<GOTO>",                "goto",
   "<CLEARLINE>",           "clearline",
   "<HIDE>",                "hide",
   "<SHOW>",                "show",
   "<INSERTLN>",            "insertln",
   "<GETCHAR>",             "getchar",
   "<PUSHBACK>",            "pushback",
   "<CANON>",               "canon",
   "<NOCANON>",             "nocanon",
   "<BOLDFACE>",            "boldface",
   "<NORMAL>",              "normal",

   "<NOPRINTER>",           "noprinter",
   "<PRINTER>",             "printer",
   "<SHEXEC>",              "shexec",
   "<EXEC>",                "exec",
   "<TRUNCATE>",            "truncate",

   "<SYMBOLP>",             "symbolp",
   "<REGEXPP>",             "regexpp",
   "<TABLEP>",              "tablep",
   "<STACKP>",              "stackp",
   "<INTRINSICP>",          "intrinsicp",
   "<CLOSUREP>",            "closurep",
   "<MACROP>",              "macrop",
   "<RECORDP>",             "recordp",

   "<DYNAMIC_LET>",         "dynamic_let",
   "<CHMOD>",               "chmod",
   "<CHOWN>",               "chown",
   "<BASENAME>",            "basename",
   "<DIRNAME>",             "dirname",
   "<CHECKPASS>",           "checkpass",
   "<SETUID>",              "setuid",
   "<SETGID>",              "setgid",
   "<SETEGID>",             "setegid",
   "<SETEUID>",             "seteuid",
   "<GETUID>",              "getuid",
   "<GETGID>",              "getgid",
   "<GETEUID>",             "geteuid",
   "<SEEK>",                "seek",
   "<GETCHARS>",            "getchars",
   "<READLOCK>",            "readlock",
   "<WRITELOCK>",           "writelock",
   "<UNLOCK>",              "unlock",
   "<HOSTNAME>",            "hostname",
   "<SYMLINK>",             "symlink",
   "<GECOS>",               "gecos",
   "<RECORD>",              "record",
   "<SETFIELD>",            "setfield",
   "<GETFIELD>",            "getfield",
   "<EXTEND>",              "extend",
   "<FOR>",                 "for",
   "<ITERATE>",             "iterate",
   "<DYNAMIC_EXTENT>",      "dynamic_extent",
   "<TIMETHEN>",            "timethen",
   "<INC>",                 "inc",
   "<DEC>",                 "dec",
   "<SETQ>",                "setq",
   "<CHILD_EOF>",           "child_eof",
   "<CRYPT>",               "crypt",
   "<LOOP>",                "loop",
   "<DAYS2DATE>",           "days2date",
   "<DATE2DAYS>",           "date2days",
   "<WEEK>",                "week",
   "<WEEKDAY>",             "weekday",
   "<DATE2TIME>",           "date2time",
   "<LOCALTIME>",           "localtime",
   "<UTCTIME>",             "utctime",
   "<MONTH>",               "month",
   "<NEGATE>",              "negate",

   "<GETPID>",              "getpid",
   "<GETPPID>",             "getppid",
   "<SETPGID>",             "setpgid",
   "<GETPRGP>",             "getpgrp",
   "<TCGETPGRP>",           "tcgetpgrp",
   "<TCSETPGRP>",           "tcsetpgrp",
   "<KILL>",                "kill",
   "<KILLPG>",              "killpg",
   "<FORK>",                "fork",
   "<FORKPIPE>",            "forkpipe",
   "<GLOB>",                "glob",
   "<WAIT>",                "wait",
   "<ZOMBIES>",             "zombies",
   "<NOZOMBIES>",           "nozombies",
   "<STDERR2STDOUT>",       "stderr2stdout",
   "<STDOUT2STDERR>",       "stdout2stderr",
   "<NTH>",                 "nth",
   "<NTHCDR>",              "nthcdr",
   "<COMMAND_LOOKUP>",      "command_lookup",
   "<RESET_HISTORY>",       "reset_history",
   "<ZOMBIESP>",            "zombiesp",
   "<DEC2HEX>",             "dec2hex",
   "<HEX2DEC>",             "hex2dec",
   "<LISTEN>",              "listen",
   "<LISTEN_UNIX>",         "listen_unix",
   "<STOP_LISTENING>",      "stop_listening",
   "<ACCEPT>",              "accept",

   "<RECEIVE_DESCRIPTORS>", "receive_descriptors",
   "<SEND_DESCRIPTORS>",    "send_descriptors",
   "<GETPEERNAME>",         "getpeername",
   "<DAEMONIZE>",           "daemonize",
   "<SYSLOG>",              "syslog",
   "<BASE64_ENCODE>",       "base64_encode",
   "<BASE64_DECODE>",       "base64_decode",
   
   "<EVAL_STRING>",         "eval_string",
   "<BLIND_EVAL_STRING>",    "blind_eval_string",
   "<FLUSH_STDOUT>",        "flush_stdout",
   "<TEMPORARY>",           "temporary",
   "<EVAL_BUFFER>",         "eval_buffer",
   "<DATETHEN>",            "datethen",
   "<CHROOT>",              "chroot",
   "<GETLINE_UB>",          "getline_ub",
   "<ISATTY>",              "isatty",
   "<BUSYMAP>",             "busymap",
   "<NOBUSYMAP>",           "nobusymap",
   "<BUSY>",                "busy",
   "<NOTBUSY>",             "notbusy",
   "<BUSP>",                "busyp",
   "<SLEEP>",               "sleep",
   "<GET_SCGI_HEADER>",     "get_scgi_header",
   "<FORM_DECODE>",         "form_decode",
   "<FORM_ENCODE>",         "form_encode",

   "<FG_BLACK>",          "fg_black",
   "<FG_RED>",            "fg_red",
   "<FG_GREEN>",          "fg_green",
   "<FG_YELLOW>",         "fg_yellow",
   "<FG_BLUE>",           "fg_blue",
   "<FG_MAGENTA>",        "fg_magenta",
   "<FG_CYAN>",           "fg_cyan",
   "<FG_WHITE>",          "fg_white",
   "<BG_BLACK>",          "bg_black",
   "<BG_RED>",            "bg_red",
   "<BG_GREEN>",          "bg_green",
   "<BG_YELLOW>",         "bg_yellow",
   "<BG_BLUE>",           "bg_blue",
   "<BG_MAGENTA>",        "bg_magenta",
   "<BG_CYAN>",           "bg_cyan",
   "<BG_WHITE>",          "bg_white",

   "<SAVE_HISTORY>",      "save_history",
   "<LOAD_HISTORY>",      "load_history",
   "<SIGTERMP>",          "sigtermp",
   NULL
};
