/*
 * Bawk constants and variable declarations.
 */
#include <stdlib.h>
#include <ctype.h>
/* #define ANSI_OFF */
#define DBUG_OFF
#include <dbug.h>

#ifdef BDS_C
#define EXTERN /* */
#else

#ifdef MAIN
#define EXTERN /* */
#else
#define EXTERN extern
#endif

#endif

/*
 * If QUOTE_STRING_HACK is defined then Bawk programs passed on the
 * command line may delimit strings with either `grave accent` or
 * "double quotes".
 */
#define QUOTE_STRING_HACK

/*
 * Table and buffer sizes
 */
#define MAXLINELEN	200	/* longest input line */
#define MAXWORDS	(MAXLINELEN/2)	/* max # of words in a line */
#define MAXWORKBUFLEN	4096	/* longest action or regular expression */
#define MAXVARTABSZ	50	/* max # of symbols */
#define MAXVARLEN	10	/* symbol name length */
#define MAXSTACKSZ	40	/* max value stack length (for expressions) */


/**********************************************************
 * Current Input File variables                           *
 **********************************************************/
/*
 * Current Input File pointer:
 */
#ifdef BDS_C
EXTERN char *Fileptr, Curfbuf[ BUFSIZ ];
#else
EXTERN FILE *Fileptr;
#endif
EXTERN char *Filename;		/* current input file name */
EXTERN int Linecount;		/* current input line number */
EXTERN int Recordcount;		/* record count */
/*
 * Working buffers.
 */
EXTERN char Linebuf[ MAXLINELEN+1 ];	/* current input line buffer */
EXTERN char *Fields[ MAXWORDS+1 ];	/* pointers to the words in Linebuf */
EXTERN int Fieldcount;			/* and the # of words */
EXTERN char Workbuf[ MAXWORKBUFLEN+1 ];	/* work area for C action and */
					/* regular expression parsers */

/**********************************************************
 * Regular Expression Parser variables                    *
 **********************************************************/
/*
 * Tokens:
 */
#define CHAR	1
#define BOL	2
#define EOL	3
#define ANY	4
#define CLASS	5
#define NCLASS	6
#define STAR	7
#define PLUS	8
#define MINUS	9
#define ALPHA	10
#define DIGIT	11
#define NALPHA	12
#define PUNCT	13
#define RANGE	14
#define ENDPAT	15


/**********************************************************
 * C Actions Interpreter variables                        *
 **********************************************************/
/*
 * Tokens:
 */
#define T_STRING	16	/* primaries: */
#define T_DOLLAR	17
#define T_REGEXP	18
#define T_REGEXP_ARG	19
#define T_CONSTANT	20
#define T_VARIABLE	21
#define T_FUNCTION	22
#define T_SEMICOLON	23	/* punctuation */
#define T_EOF		24
#define T_LBRACE	25
#define T_RBRACE	26
#define T_LPAREN	27
#define T_RPAREN	28
#define T_LBRACKET	29
#define T_RBRACKET	30
#define T_COMMA		31
#define T_ASSIGN	32	/* operators: */
#define T_STAR		33	/* *foo */
#define T_MUL		34
#define T_DIV		35
#define T_MOD		36
#define T_ADD		37
#define T_UMINUS	38	/* -foo */
#define T_SUB		39
#define T_SHL		40
#define T_SHR		41
#define T_LT		42
#define T_LE		43
#define T_GT		44
#define T_GE		45
#define T_EQ		46
#define T_NE		47
#define T_NOT		48
#define T_ADDROF	49	/* &foo */
#define T_AND		50
#define T_XOR		51
#define T_OR		52
#define T_LNOT		53
#define T_LAND		54
#define T_LOR		55
#define T_INCR		56
#define T_DECR		57
#define T_POSTINCR	58	/* foo++ */
#define T_POSTDECR	59	/* foo-- */
#define T_IF		60	/* keywords: */
#define T_ELSE		61
#define T_WHILE		62
#define T_BREAK		63
#define T_CHAR		64
#define T_INT		65
#define T_BEGIN		66
#define T_END		67
#define T_NF		68
#define T_NR		69
#define T_FS		70
#define T_RS		71
#define T_FILENAME	72
#define T_STATEMENT	73
#define T_DECLARE	74	/* char foo */
#define T_ARRAY_DECLARE	75	/* char foo[5] */

#define MAX_TOKEN	T_ARRAY_DECLARE

#ifndef DBUG_OFF
extern char *token_name[];
#endif

#define PATTERN	'P'	/* indicates C statement is within a pattern */
#define ACTION	'A'	/* indicates C statement is within an action */

/*
 * Symbol table
 */

struct variable {
	char	vname[ MAXVARLEN ];
	char	vclass;
	char	vsize;
	int	vlen;
	char	*vptr;
};
#define VARIABLE struct variable
EXTERN VARIABLE Vartab[ MAXVARTABSZ ], *Nextvar;
/* A variable may be redeclared. Is this a feature? Should we have block */
/* scopeing? vardecl stores the redeclaration info. */
struct vardecl {
	VARIABLE *variable;
	char	vclass;
	char	vsize;
};
#define VARDECL struct vardecl

/*
 * Symbol Table values
 */
#define ACTUAL		0
#define LVALUE		1
#define BYTE		1
#define WORD		(sizeof(char *))

/*
 * Value stack
 */
union datum {
	int	ival;
	char 	*dptr;
	char	**ptrptr;
};
#define DATUM union datum
struct item {
	char	class;
	char	lvalue;
	char	size;
	DATUM	value;
};
#define ITEM struct item
EXTERN ITEM Stackbtm[ MAXSTACKSZ ], *Stackptr, *Stacktop;
/*
 * parse tree
 */
struct expr_node {
	struct expr_node *left;
	struct expr_node *right;
	char operator;
};
#define EXPR_NODE struct expr_node
/*
 * Miscellaneous
 */
EXTERN char *Actptr;	/* pointer into Workbuf during compilation */
EXTERN char Token;	/* current input token */
EXTERN DATUM Value;	/* and its value */
EXTERN char Saw_break;	/* set when break stmt seen */
EXTERN char Where;	/* indicates whether C stmt is a PATTERN or ACTION */
EXTERN char Fieldsep[128];	/* field seperator */
EXTERN char Recordsep[128];	/* record seperator */
EXTERN EXPR_NODE *Beginact;	/* BEGINning of input actions */
EXTERN EXPR_NODE *Endact;	/* END of input actions */

/**********************************************************
 * Rules structure                                        *
 **********************************************************/
struct rule {
	struct {
		EXPR_NODE *start;/* C statements that match pattern start */
		EXPR_NODE *stop;/* C statements that match pattern end */
		char startseen;	/* set if both a start and stop pattern */
				/* given and if an input line matched the */
				/* start pattern */
	} pattern;
	EXPR_NODE *action;	/* quasi-C statements parse tree */
	struct rule *nextrule;	/* pointer to next rule */
};
#define RULE struct rule
EXTERN RULE *Rules,		/* rule structures linked list head */
	*Rulep;			/* working pointer */


/**********************************************************
 * Miscellaneous                                          *
 **********************************************************/
/*
 * Error exit values (returned to command shell)
 */
#define USAGE_ERROR	1	/* error in invokation */
#define FILE_ERROR	2	/* file not found errors */
#define RECORD_ERROR	3	/* input record too long */
#define RE_ERROR	4	/* bad regular expression */
#define ACT_ERROR	5	/* bad C action stmt */
#define MEM_ERROR	6	/* out of memory errors */
/*
 * Functions that return something special:
 */
#ifdef ANSI_OFF
extern EXPR_NODE *act_compile();
extern VARIABLE *addvar();
extern void assignment();
extern char *cclass();
extern void compile();
extern EXPR_NODE *decl_parse();
extern EXPR_NODE *declist_parse();
extern void doaction();
extern int dopattern();
extern void endfile();
extern void error();
extern EXPR_NODE *expr_parse(), *expr_left_to_right_parse();
extern int fetchint();
extern char *fetchptr();
extern VARIABLE *findvar();
extern void function();
extern int getcharacter();
extern EXPR_NODE *get_expr_node();
extern int getline();
extern char *getmemory();
extern char *get_clear_memory();
extern char getoken();
extern void init_pop_array();
extern int instr();
extern int isfunction();
extern int iskeyword();
extern int match();
extern void newfile ();
extern int parse();
extern EXPR_NODE *pat_compile();
extern char *pmatch();
extern int pop();
extern int popint();
extern void postincdec();
extern void preincdec();
extern EXPR_NODE *primary_parse();
extern void process();
extern void push();
extern void pushint();
extern int re_compile();
extern void stmt_lex();
extern EXPR_NODE *stmt_parse();
extern void storeint();
extern void storeptr();
extern char *str_compile();
extern void syntaxerror();
extern int ungetcharacter();
extern void unparse();
extern void usage();
extern void walk_tree();
#else ANSI_OFF
extern EXPR_NODE *act_compile(char *);
extern VARIABLE *addvar(char *);
extern void assignment(void);
extern char *cclass(char *);
extern void compile(void);
extern EXPR_NODE *decl_parse(int);
extern EXPR_NODE *declist_parse(void);
extern void doaction(EXPR_NODE *);
extern int dopattern(EXPR_NODE *);
extern void endfile(void);
extern void error(char *,int);
extern EXPR_NODE *expr_parse(void), *expr_left_to_right_parse(char);
extern int fetchint(char *);
extern char *fetchptr(char *);
extern VARIABLE *findvar(char *);
extern void function(int,EXPR_NODE *);
extern int getcharacter(void);
extern EXPR_NODE *get_expr_node(char);
extern int getline(void);
extern char *getmemory(unsigned);
extern char *get_clear_memory(unsigned);
extern char getoken(void);
extern void init_pop_array(void);
extern int instr(char,char *);
extern int isfunction(char *);
extern int iskeyword(char *);
extern int match(char *,char *);
extern void newfile (char *);
extern int parse(char *,char **,char *);
extern EXPR_NODE *pat_compile(char *);
extern char *pmatch(char *,char *,char *);
extern int pop(void);
extern int popint(void);
extern void postincdec(int);
extern void preincdec(int);
extern EXPR_NODE *primary_parse(void);
extern void process(void);
extern void push(char,char,char,DATUM *);
extern void pushint(int);
extern int re_compile(char *);
extern void stmt_lex(char *);
extern EXPR_NODE *stmt_parse(void);
extern void storeint(char *,int);
extern void storeptr(char *,char *);
extern char *str_compile(char *,char);
extern void syntaxerror(void);
extern int ungetcharacter(char);
extern void unparse(char **,int,char *,char *);
extern void usage(void);
extern void walk_tree(EXPR_NODE *);
#endif ANSI_OFF
