/*
 * Copyright (c) 2001-2007 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 <regex.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 <signal.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 512
#define POOL_INC 2048

#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 FUNC(n) int do_ ## n ( char *, struct object * )

#define type(n) ( n & 127 )
#define set(n) ( n |= 128 )
#define unset(n) ( n &= 127 )
#define isitset(n) ( n & 128 )

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

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

#define number(n) ( ( int )n )
#define numberp(n) ( n & 4 )
#define toptr(n) (( struct atom *)n )
#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

enum token_types { TOK_STRING, TOK_SYMBOL, TOK_FIXNUM, TOK_SPECIAL, TOK_OPEN,
                   TOK_CLOSE, TOK_END, TOK_QUOTE, TOK_COMMENT, TOK_MINUS };

enum err_types { ERR_SYMBOL,       ERR_STRING,      ERR_FIXNUM,
                 ERR_REGEXP,       ERR_TABLE,       ERR_STACK,       
                 ERR_DB,           ERR_INTRINSIC,   ERR_ATOM,
                 ERR_CLOSURE,      ERR_RECORD,
                 ERR_SQL,          ERR_LIST,

                 ERR_ARGS,
                 ERR_MISSING_ARGS, ERR_MISSING_ARG, ERR_MORE_ARGS,
                 ERR_EVAL,         ERR_ARG_TYPE,    ERR_CONSTANT   };

char *err_strings[] = { "symbol", "string", "fixnum", "regexp", "table", 
                        "stack", "database", "intrinsic", "atom", 
                        "closure", "record", "prepared SQL statement",
                        "list" };

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 %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;

void sigchld_handler( int );
void sigwinch_handler( int );
int pipe_open( char *, char *, int, int, int * );
void print_err( enum err_types, char *, int, enum err_types );

struct stack
{
   int free, used;
   void **top, **values;
};

struct hash_elt
{
   struct object *element;
   struct hash_elt *next;
   int binding;
};

struct lstring 
{
   char *string;
   unsigned int length;
};

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

   union {
      regex_t *regexp;
      struct hash_elt **hash;
      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;
      void *record;
   } data;

   int flags;
};

struct object
{
   int flags;

   union {
      struct atom *atom;
      struct object *head;
   } data;

   struct object *next;
};

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

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

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

char *path = NULL;

regex_t find_poss_regex, merge_regex;

int stack_inc = 16, serv_fd = -1, isdaemon = 0, blocked = 0;
int totally_complete = 0;
int mode = 1, printer = 1;

struct object *sql_list = NULL;

struct stack *history;
int history_ptr;

struct hash_elt *env[ HASH_SIZE ];
struct hash_elt *atoms[ HASH_SIZE ];
struct hash_elt *syntax[ HASH_SIZE ];

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

struct stack *get_hash_keys( struct hash_elt ** );
struct stack *get_hash_values( struct hash_elt ** );
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, *arg_stack, *seen, *buffer_stack,
   *stack, *open_envs;

struct object *object_pool, *object_pool_ptr;

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

struct stack *executables = NULL;

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

int sigalrm = 0;

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, fatal = 0, closure_pool_free,
   lambda_id, macro_id, stop = 0, stack_counter = 1, 
   sql_counter = 1, zombies = 0, string_counter = -1,
   closure_counter = 1, child_fd = -1, child_eof = 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,
   gc, gc_on, gc_frequency;

char *tailcall_syntax = NULL;

struct stack *descriptors[ 3 ], *input_buffer_stack;

char *lambda_syntax, *macro_syntax;

struct stack *string_stack;
char *string_ptr;

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

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

void *memory( 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 ** );
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 * );
struct object *stack_pop( struct stack * );
void stack_truncate( struct stack *, int );
void stack_free( struct stack * );

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

void insert_elt( struct hash_elt **, int, struct object* );
void remove_elt( struct hash_elt **, int );
void *lookup_elt( struct hash_elt **, int );
void hash_free( struct hash_elt ** );

struct object *lookup_local( int id );

#define insert_binding(n,m) insert_elt( env, n, m )
#define insert_atom(n,m) insert_elt( atoms, n, ( struct object *)m )
#define remove_atom(n) remove_elt( atoms, n );
#define lookup_atom(n) ( struct atom*)lookup_elt( atoms, n )
#define lookup_binding(n) ( struct object *)lookup_elt( env, n )
#define remove_binding(n) remove_elt( env, n )

struct object *make_atom_from_act_record( struct stack * );
struct object *make_atom_from_number( int );
struct object *make_atom_from_closure( struct closure *, int );
struct object *make_atom_from_string( char *, int );
struct object *make_atom_directly_from_string( char *, 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 *, int );

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( used );
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( realpath );
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( gc );
FUNC( for );
FUNC( iterate );
FUNC( dynamic_extent );
FUNC( timediff );
FUNC( timethen );
FUNC( inc );
FUNC( dec );
FUNC( setq );
FUNC( gc_freq );
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( stop_listening );
FUNC( accept );
FUNC( getpeername );
FUNC( daemonize );
FUNC( syslog );
FUNC( flush_stdout );

FUNC( base64_encode );
FUNC( base64_decode );

FUNC( 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( isatty );

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

int pushed_back = -1, sigwinch = 0;

int ( *intrinsics[] )( char *, struct object * ) =
{
   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_used,
   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_realpath,
   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_gc,
   do_for,
   do_iterate,
   do_dynamic_extent,
   do_timediff,
   do_timethen,
   do_inc,
   do_dec,
   do_setq,
   do_gc_freq,
   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_stop_listening,
   do_accept,
   do_getpeername,
   do_daemonize,
   do_syslog,
   do_base64_encode,
   do_base64_decode,
   do_eval_string,
   do_flush_stdout,
   do_temporary,
   do_eval_buffer,
   do_datethen,
   do_chroot,
   do_getline_ub,
   do_isatty,
   NULL
};

char *intrinsic_syntax[] =
{
   "<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",
   "<USED>",           "used",
   "<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",
   "<REALPATH>",       "realpath",
   "<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",
   "<GC>",             "gc",
   "<FOR>",            "for",
   "<ITERATE>",        "iterate",
   "<DYNAMIC_EXTENT>", "dynamic_extent",
   "<TIMEDIFF>",       "timediff",
   "<TIMETHEN>",       "timethen",
   "<INC>",            "inc",
   "<DEC>",            "dec",
   "<SETQ>",           "setq",
   "<GC_FREQ>",        "gc_freq",
   "<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",
   "<STOP_LISTENING>", "stop_listening",
   "<ACCEPT>",         "accept",
   "<GETPEERNAME>",    "getpeername",
   "<DAEMONIZE>",      "daemonize",
   "<SYSLOG>",         "syslog",
   "<BASE64_ENCODE>",  "base64_encode",
   "<BASE64_DECODE>",  "base64_decode",
   "<EVAL_STRING>",    "eval_string",
   "<FLUSH_STDOUT>",   "flush_stdout",
   "<TEMPORARY>",      "temporary",
   "<EVAL_BUFFER>",    "eval_buffer",
   "<DATETHEN>",       "datethen",
   "<CHROOT>",         "chroot",
   "<GETLINE_UB>",     "getline_ub",
   "<ISATTY>",         "isatty"
};


syntax highlighted by Code2HTML, v. 0.9.1