/*
 *             BBSINDEX.H
 *     
 *             All the standard variables and other stuff used by all the modules
 *             of BBSindex, and standard BBS-PC! headers (with a few modifications).
 *
 *             Important note: This header file cannot be precompiled with
 *             Lattice C V5.02, because of a bug which prevents bit fields
 *             from working properly when they are precompiled.
 */

#include "bbs.h"

#define TRUE   1
#define FALSE  0

#define BTOK(x) (((x)+1023)>>10)       /* Convert file size into K */

/*
 *             Default values for command line parameters and script commands
 */

#define FORMAT         "%15n %w %-6x-%b{B,T}  %c\n"
#define UDNAME         "UDHEAD.DAT"
#define CFGNAME                "CFGINFO.DAT"
#define PROGSCRIPT     "BBSCRIPT"
#define DEFSCRIPT      "BBSindex.scr"

/*
 *     Blocksize determines the largest contiguous memory segment which is
 *     needed. Larger values give faster processing, but need more continuous
 *     memory.
 */

#define        BLOCKSIZE       160                             /* Number of records/block (~16K)               */
#define MAXOUT         1024                    /* The maximum length of an output line */
#define        MAXCOM          1024                    /* Maximum size of a single command             */
#define MAXSUB         256                             /* Maximum size of a sub format string  */
#define FRAGBLOCK      8192                    /* Memory block to allocate in mymalloc */
#define FRAGTHRESH     200                             /* Threshold for mem reqs in mymalloc   */
#define BUFSIZE                8192                    /* Maximum size of output buffer                */
#define MAXEXPR                100                             /* Max number of items in an expression */
#define MAXDIRENT      1000                    /* Maximum number of unknown dir files  */
#define DIRFRAG                100                             /* Number of dir entries/block alloced  */
#define DIRNAMESIZE    80                              /* Maximum length of directory name             */
#define MACROLEN       20                              /* Maximum length of macro name                 */
#define MAXMACRO       50                              /* Maximum number of macros allowed             */
#define MAXNEST                10                              /* Max number of macro nesting levels   */
#define MAXCONST       20                              /* Maximum length of a constant name    */

/* Note: MAXSUB above is allocated on the stack, so don't make it too big */

/*
 *             This structure is used to build a tree structure representing
 *             the expression given with the SELECT command.
 */
struct expr {
       int             field;                  /* Field to test, or boolean operator   */
       int             op;                             /* Operator to test against, if any             */
       int             num;                    /* First data field                                             */
       char    *text;                  /* Second data field                                    */
       struct  expr *left;             /* Left subtree                                                 */
       struct  expr *right;    /* Right subtree                                                */
};

typedef struct expr EXPR;

/*
 *             This structure is used to hold the name of a file found in
 *             a BBS-PC! file directory during CHECKFILES, which does not
 *             exist in the BBS-PC! file catalogue.
 */
typedef struct {
       char    name[32];               /* Disk filename                                                */
       short   date;                   /* In BBS-PC! format, max 16 bits               */
       short   dirnum;                 /* The directory number it was in               */
       long    size;                   /* The size of the file, in bytes               */
} DIRENTRY;

#define DIRENTRYSIZE   sizeof(DIRENTRY)

/*
 *             This structure holds the names of files to be "ignored" during a
 *             CHECKFILES. I.e. they are marked as valid, even if their filesize
 *             on disk doesn't match that in the file catalogue. This structure
 *             is built up with the IGNORE command.
 */
struct ignore {
       struct ignore *next;
       char name[CAT_LEN+1];
};

typedef struct ignore IGNORE;

/*
 *             This structure is used to store macro definitions. Note that
 *             a single block is used to store both the macro and its definition.
 *             The structure is dynamically sized at runtime, to fit whatever
 *             size definition is given. The text[] array (nominally 1) gets
 *             expanded to hold the definition.
 */
typedef struct {
       char    name[MACROLEN]; /* Name of this macro                                   */
       int             size;                   /* Size of macro text                                   */
       char    text[1];                /* Start of macro text                                  */
} MACRO;

#define MACROSIZE              (sizeof(MACRO) - 1)             /* The -1 is for text[1] */

/*
 *             This structure holds a block of parameters for a macro that is
 *             executing.
 */
typedef struct {
       int             size;                   /* Size of parameter block                              */
       char    params[1];              /* Start of parameter block                             */
} PARAM;

#define PARAMSIZE              (sizeof(PARAM) - 1)             /* The -1 is for params[1] */


/*
 *             This macro checks to make sure that the file database has been
 *             read in. This is delayed until as late as possible, so that if
 *             the script file contains errors, the errors will be spotted BEFORE
 *             the database is read in. The primary goal here is to save the user
 *             having to wait for 200K or so of database to be read in, just so
 *             they can see they have an error in their script. Instead, the
 *             database is only read in when a command cannot execute without
 *             having access to the files. Such commands are SORT, SCAN, LIST,
 *             CHECKFILES and FOREIGN.
 */
#define CHECKDATABASE() {if (!readfiles) readdatabase(databasename);}

/*
 *             Global variables, accessible to all modules
 */

#ifdef GLOBAL
#undef GLOBAL
#endif
#ifdef MAIN
#define GLOBAL
#else
#define GLOBAL extern
#endif

GLOBAL char *script;                   /* Array for storing the script                         */
GLOBAL long scriptsize;                        /* The size of the current script                       */
GLOBAL long scriptpos;                 /* Position in the current script                       */
GLOBAL long linenum;                   /* Line number in script file                           */
GLOBAL char out[MAXOUT];               /* Array for storing the output lines           */
GLOBAL char combuf[MAXCOM];            /* Buffer to hold a single command                      */
GLOBAL char formatstring[MAXCOM];/* Used to store the output format string     */
GLOBAL char databasename[256]; /* The name of the BBS-PC! file database        */
GLOBAL char configname[256];   /* The name of the BBS-PC! config file          */
GLOBAL char scriptname[256];   /* The name of the current script file          */
GLOBAL UDHEAD **ptrblock;              /* Array of pointers to file records            */
GLOBAL long numrecs;                   /* The number of file headers read in           */
GLOBAL long compos;                            /* Position on the current command line         */
GLOBAL long comlen;                            /* Length of current command line                       */
GLOBAL BPTR outfile;                   /* Output file (Default is stdout)                      */
GLOBAL BPTR errorfile;                 /* Standard error file (screen usually)         */
GLOBAL BPTR dirlock;                   /* Lock used when scanning directories          */
GLOBAL struct FileInfoBlock *fib;/* Global fib struct on longword boundary     */
GLOBAL int checkfiles;                 /* TRUE if file directories were scanned        */
GLOBAL int readfiles;                  /* TRUE if database file has been read in       */
GLOBAL int toscreen;                   /* TRUE if output is to screen                          */
GLOBAL int totalbytes;                 /* Total number of bytes output so far          */
GLOBAL int totalfiles;                 /* Total number of files output so far          */
GLOBAL int curbytes;                   /* Number of bytes output by last LIST/SCAN     */
GLOBAL int curfiles;                   /* Number of files output by last LIST/SCAN     */
GLOBAL int sorted;                             /* True if file array has been sorted           */
GLOBAL EXPR tree[MAXEXPR];             /* Array to hold parsed SELECT expression       */
GLOBAL int numdirentries;              /* Number of fake directory entries                     */
GLOBAL DIRENTRY *direntries[MAXDIRENT];/* Storage for ptrs to dir entries      */
GLOBAL char dirnames[NUM_SECT][DIRNAMESIZE];/* Storage for directory names     */
GLOBAL CFGINFO config[1];              /* BBS-PC! Configuration file structure         */
GLOBAL MACRO *macros[MAXMACRO];        /* Array of ptrs to macro definitions           */
GLOBAL int nummacros;                  /* Number of macros currently defined           */
GLOBAL PARAM *params[MAXNEST]; /* Array of pointers to macro parameters        */
GLOBAL int nestlevel;                  /* Current macro nest level                                     */
GLOBAL int tracemode;                  /* Trace mode; TRUE if tracing enabled          */
GLOBAL IGNORE *firstignore;            /* Pointer to first filename to ignore          */

/*
 *             Global functions, accessible everywhere
 */

char *format();                /* Format output string from file header + format spec  */
char *echoformat();    /* Formats output string for ECHO command                               */
char *itoa();          /* Convert integer into ASCII format                                    */
char *getstring();     /* Get next string from command buffer                                  */
void *mymalloc();      /* Safe memory tracker that handles out of memory               */
void *SafeAllocMem();/* Safe AllocMem that handles out of memory                       */
void execscript();     /* Executes all the commands in the current script              */
void Cleanup();                /* Frees resources and exits program                                    */
void chkabort();       /* Checks for Control-C, and aborts if detected                 */
void putstring();      /* Outputs string to standard I/O                                               */
void flushout();       /* Flushes data buffer to output file                                   */
void parse();          /* Parse command line and build expression tree                 */
void readdatabase();/* Reads in the BBS-PC! UDHEAD.DAT file database           */
void readconfigfile();/* Reads in the BBS-PC! CFGINFO.DAT file                         */
void print();          /* Prints a string to stderr                                                    */
void com_select();     /* SELECT, specifies criteria for files to select               */
void com_checkfiles();/* Scans file directories, updating catlague entries     */
void com_sort();       /* Sorts file catalogue into a particular order                 */
void com_foreign();    /* Prints a list of all the unknown foreign files               */
void com_norequest();/* Stop AmigaDos from putting up requesters                       */
int match();           /* Returns TRUE if record matches current selection             */
int scandir();         /* Scans directory for files, returns TRUE if continue  */
int sortcmp();         /* Internal routine used for sorting files                              */

/*
 *             print3()
 *             --------
 *             Prints 3 strings to standard error
 */
#define print2(s1,s2)   (print(s1), print(s2))
#define print3(s1,s2,s3) (print(s1), print(s2), print(s3))

/*
 *             The list of identifiers used by SORT and SELECT.
 */

#define MAXINDEX 16

#define I_ANY                  0
#define I_ACCESS               1
#define I_BINARY               2
#define I_COMMENT              3
#define I_DISKNAME             4
#define I_SECTION              5
#define I_ONLINE               6
#define I_LOCAL                        7
#define I_NAME                 8
#define I_OWNER                        9
#define I_PATHNAME             10
#define I_DIRECTORY            11
#define I_DISKDIRNUM   12
#define I_VALID                        13
#define I_DATE                 14
#define I_SIZE                 15
#define I_KSIZE                        16

GLOBAL struct {
       int tag;
       char *name;
} indexes[MAXINDEX]
#ifdef MAIN
= {

{      I_ACCESS,               "ACCESS"},              /* Number of times file was accessed    */
{      I_BINARY,               "BINARY"},              /* True if Binary, False if text                */
{      I_COMMENT,              "COMMENT"},             /* The file comment                                             */
{      I_DISKNAME,             "DISKNAME"},    /* The name of the file on disk                 */
{      I_SECTION,              "SECTION"},             /* # of the section the file is in              */
{      I_ONLINE,               "ONLINE"},              /* True if file online                                  */
{      I_LOCAL,                "LOCAL"},               /* True if file uploaded locally                */
{      I_NAME,                 "NAME"},                /* The name of the file in the catalog  */
{      I_OWNER,                "OWNER"},               /* The name of uploader of the file             */
{      I_PATHNAME,             "PATHNAME"},    /* Pathname to file on disk                             */
{      I_DIRECTORY,    "DIRECTORY"},   /* # of directory file is in                    */
{      I_DISKDIRNUM,   "DISKDIRNUM"},  /* # of disk directory file is in               */
{      I_VALID,                "VALID"},               /* True if file is Valid                                */
{      I_DATE,                 "DATE"},                /* The date the file was uploaded               */
{      I_SIZE,                 "SIZE"},                /* The size of the file                                 */
{      I_KSIZE,                "KSIZE"}                /* The size of the file in K                    */
}
#endif
;

GLOBAL char *months[]
#ifdef MAIN
= {
       "xxx",
       "Jan", "Feb", "Mar", "Apr", "May", "Jun",
       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
}
#endif
;

/*
 *             Special characters that can occur in the script
 */
#define CHAR_TAB               '\t'
#define CHAR_SPACE             ' '
#define CHAR_HASH              '#'
#define CHAR_NL                        '\n'
#define CHAR_ESC               '\\'
#define CHAR_QUOTE             '\''
#define CHAR_QUOTES            '\"'
#define CHAR_SEMI              ';'
#define CHAR_COMMA             ','
#define CHAR_EQUALS            '='
#define CHAR_DOLLAR            '$'
#define CHAR_NULL              '\0'

#define CHAR_ASCEND            '+'
#define CHAR_DESCEND   '-'

/*
 *             The following symbols are used in the expression tree
 */

/*
 *             Boolean operations, which share storage with field selectors
 */

#define E_AND          30      /* <left> AND <right>   */
#define        E_OR            31      /* <left> OR <right>    */
#define        E_NOT           32      /* NOT <left>                   */
#define E_ALL          33      /* Always true                  */

/*
 *             Comparison operators, used for comparing record elements
 */
#define        E_EQ            34      /* Record == Value              */
#define E_NE           35      /* Record != Value              */
#define E_LT           36      /* Record <  Value              */
#define E_GT           37      /* Record >  Value              */
#define E_LE           38      /* Record <= Value              */
#define E_GE           39      /* Record >= Value              */

#define E_OPENPAR      40      /* Open parameter token         */
#define E_CLOSEPAR     41      /* Close parameter token        */

#define E_NUMBER       42      /* Any numeric value            */
#define E_STRING       43      /* Anything in quotes           */
#define E_END          44      /* End of command line          */

#define E_TEXT         45      /* File is a text file          */
#define E_REMOTE       46      /* File is a remote file        */
#define E_INVALID      47      /* File is invalid                      */
#define E_OFFLINE      48      /* File is offline                      */


/*
 *             Wildcard special fields for strings
 */
#define tokentowild(x) ((x)+50)

#define W_OWNER                tokentowild(I_OWNER)
#define W_NAME         tokentowild(I_NAME)
#define W_DISKNAME     tokentowild(I_DISKNAME)
#define W_COMMENT      tokentowild(I_COMMENT)
