/*
 * mgl.h  -  Definitions for the Menu Generation Language
 *
 * Copyright (C) 1997-2003 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: mgl.h,v 1.4 2003/01/25 23:29:44 gkminix Exp $
 */


/*
 ***************************************************************************
 *
 * Miscellaneous defines
 */
#define YY_NO_UNPUT			/* don't let flex include yyunput */
#define MAX_INT		0x7fff		/* max value for integer */
#define MAX_CHAR	0xff		/* max value for character */
#define MAX_ID_LEN	16		/* max length of symbold name */
#define MAX_STR_LEN	255		/* max length for strings */
#define MAX_ERRS	32		/* max number of compiler errors */
#define MAX_EXPRS	8		/* max number of expressions */
#define MAX_LEVELS	8		/* max number of nesting levels */
#define MAX_ARRAY_SIZE	16384		/* max size of an array in bytes */
#define MAX_REC_SIZE	8096		/* max size of a record in bytes */

/* Define addresses in data segment for predefined variables */
#define ADDR_SERVERNAME	0x0100			/* server name */
#define ADDR_HOSTNAME	0x0200			/* clients host name */
#define PREDEF_SIZE	((MAX_STR_LEN+1) * 2)	/* total size of predef vars */



/*
 ***************************************************************************
 *
 * Type for addresses. This has to be signed in order to allow for negative
 * address offsets. For the same reason we need at least 32 bits even though
 * all addresses are always 16 bits.
 */
#if SIZEOF_UNSIGNED_SHORT >= 4
typedef short addr_t;
#else
# if SIZEOF_UNSIGNED_INT >= 4
typedef int addr_t;
# else
typedef long addr_t;
# endif
#endif



/*
 ***************************************************************************
 *
 * Command codes in expressions
 */
#define CMD_NONE	0x00		/* no command */
#define CMD_CONST	0x01		/* expression is a constant */
#define CMD_VAR		0x02		/* expression is a variable */
#define CMD_EQ		0x03		/* equal */
#define CMD_GT		0x04		/* greater than */
#define CMD_GE		0x05		/* greater or equal */
#define CMD_LT		0x06		/* lower than */
#define CMD_LE		0x07		/* lower or equal */
#define CMD_NE		0x08		/* not equal */
#define CMD_CMP		0x09		/* comparison - not used by parser */
#define CMD_OR		0x0a
#define CMD_XOR		0x0b
#define CMD_AND		0x0c
#define CMD_NOT		0x0d
#define CMD_ORD		0x0e		/* get ordinal number of scalar */
#define CMD_ODD		0x0f		/* odd function */
#define CMD_CHR		0x10		/* convert a number into a character */
#define CMD_SUCC	0x11		/* increase scalar to next ordinal no */
#define CMD_PRED	0x12		/* decrease scalar to next ordinal no */
#define CMD_ABS		0x13		/* abs function */
#define CMD_SQR		0x14		/* square function */

#define CMD_FIRSTFUNC	0x60		/* ID of first function */
#define CMD_USERFUNC	0x60		/* user defined function */
#define CMD_MENU	0x61		/* menu */
#define CMD_FIRSTINT	0x62		/* ID of first internal function */

/* Internal functions. These values are also passed to the runtime dispatcher */
#define CMD_CLS		0x62		/* clear screen */
#define CMD_GOTOXY	0x63		/* got a screen position */
#define CMD_GETBOOTP	0x64		/* get string from BOOTP record */
#define CMD_PUTBOOTP	0x65		/* get string from BOOTP record */
#define CMD_STRLEN	0x66		/* determine length of string */
#define CMD_STRSUB	0x67		/* return substring */


/* Check for conditional command */
#define iscmdcond(a)	((a)->opcode >= CMD_EQ && (a)->opcode <= CMD_NE)

/* Check for general scalar commands */
#define iscmdscalar(a)	((a)->opcode == CMD_ORD || (a)->opcode == CMD_PRED || \
			 (a)->opcode == CMD_SUCC)

/* Check for logical command */
#define iscmdlogical(a)	((a)->opcode >= CMD_OR && (a)->opcode <= CMD_NOT)

/* Check for associative command, e.g.  A^(B^C) == (A^B)^C  */
#define iscmdassoc(a)	((a)->opcode == '+' || (a)->opcode == '*' || \
			 (a)->opcode == CMD_OR || (a)->opcode == CMD_XOR || \
			 (a)->opcode == CMD_AND)

/* Check for commutative command, e.g.  A^B == B^A  */
#define iscmdcommut(a)	((a)->opcode == '+' || (a)->opcode == '*' || \
			 (a)->opcode == CMD_EQ || (a)->opcode == CMD_NE || \
			 (a)->opcode == CMD_OR || (a)->opcode == CMD_XOR || \
			 (a)->opcode == CMD_AND)

/* Check for function command */
#define iscmdfunc(a)	((a)->opcode >= CMD_FIRSTFUNC)

/* Check for internal function command */
#define iscmdintfunc(a)	((a)->opcode >= CMD_FIRSTINT)



/*
 ***************************************************************************
 *
 * Encoding of types.
 */
/* Basic types */
typedef enum {
	EXPR_NONE,			/* no assigned type */
	EXPR_STRING,			/* string type */
	EXPR_NUM,			/* numerical type */
	EXPR_BOOL,			/* boolean type */
	EXPR_CHAR,			/* character type */
	EXPR_ENUM,			/* enumeration type */
	EXPR_ARRAY,			/* array type */
	EXPR_RECORD			/* record type */
} basictypes;

/* Definitions for scalar types */
struct scalar_type {
	int    min;			/* Minimum value for scalar type */
	int    max;			/* Maximum value for scalar type */
	addr_t boundaddr;		/* Addr of bounds in const seg */
};

/* Definitions for array type (also for strings) */
struct array_type {
	int              elementnum;	/* Number of elements in array */
	struct typesdef *indextype;	/* Type of index */
	struct typesdef *basetype;	/* Type of each element */
};

/* Definitions for record type */
struct record_type {
	int          elementnum;	/* Number of elements in record */
	struct sym  *elements;		/* Symbols for all elements */
};					/* These symbols are NOT part of */
					/* ... the global symbol list!!! */

/* Global structure holding all type information */
struct typesdef {
	basictypes       type;		/* Identifier for type */
	addr_t           size;		/* Total size of type */
	union {
		struct scalar_type s;	/* Definitions for scalar types */
		struct array_type  a;	/* Definitions for an array */
		struct record_type r;	/* Definitions for a record */
	} def;
	struct typesdef *next;		/* Pointer to next type */
};

/* Predefined type definitions */
extern struct typesdef none_type;	/* type not defined */
extern struct typesdef int_type;	/* integer type */
extern struct typesdef string_type;	/* string type */
extern struct typesdef strindex_type;	/* default string index type */
extern struct typesdef char_type;	/* character type */
extern struct typesdef bool_type;	/* boolean type */

/* Check if a type is scalar */
#define isscalar(a)	((a)->type == EXPR_NUM || (a)->type == EXPR_CHAR || \
			 (a)->type == EXPR_BOOL || (a)->type == EXPR_ENUM)

/* Check if a type is non-scalar type, only strings as of yet */
#define isnonscalar(a)	((a)->type == EXPR_STRING || \
			 (a)->type == EXPR_ARRAY || \
			 (a)->type == EXPR_RECORD)



/*
 ***************************************************************************
 *
 * Attributes for variables and function arguments
 */
typedef enum {
	ATTR_NONE,		/* no special attribute, normal variable */
	ATTR_REF,		/* variable is an arg passed by reference */
	ATTR_CONST		/* passed by value but never changed */
} varattrib;



/*
 ***************************************************************************
 *
 * Encoding of symbols. The level value is the current nesting level. If
 * it's greater than zero, the address is relative to the level's frame
 * pointer.
 */
struct vardef {
	struct typesdef *t;		/* type definition of variable */
	varattrib        attr;		/* attribute of variable */
};

struct constdef {
	struct typesdef *t;		/* type of constant */
	union {
		int   i;		/* constant integer value */
		char *s;		/* constant string value */
		char  c;		/* constant character value */
		int   b;		/* constant boolean value */
		int   e;		/* constant enumeration value */
	} val;
};

struct funcdef {
	addr_t           restartaddr;	/* Restartaddress */
	addr_t           retaddr;	/* BP relative address of return value */
	int              opcode;	/* command value (see below) */
	int              argnum;	/* Number of arguments */
	struct typesdef *ret;		/* return type of function */
	struct typesdef *args[MAX_EXPRS];	/* expression types of args */
	varattrib        attribs[MAX_EXPRS];	/* argument attributes */
};


/* Special symbols are only used within the lexer, never passed to the parser */
struct specialdef {
	int  token;			/* token to return to parser */
};



/*
 ***************************************************************************
 *
 * Symbol table
 */
typedef enum symtype {
	nosym,
	specialsym,
	varsym,
	constsym,
	typesym,
	funcsym
} symtype;

struct sym {
	symtype    type;		/* symbol type */
	char      *name;		/* name of symbol */
	addr_t     addr;		/* address of symbol */
	int        level;		/* nesting level of symbol */
	union {
		struct funcdef     f;	/* function declaration */
		struct specialdef  s;	/* special symbol for lexer */
		struct vardef      v;	/* variable declaration */
		struct constdef    c;	/* constant declaration */
		struct typesdef   *t;	/* type declaration */
	} def;
	struct sym *next;		/* pointer to next symbol */
};

/* Check if symbol is not declared yet */
#define isnosym(a)	((a) != NULL && (a)->type == nosym)

/* Check for special lexer symbol */
#define isspecialsym(a)	((a) != NULL && (a)->type == specialsym)

/* Check for variable symbol */
#define isvarsym(a)	((a) != NULL && (a)->type == varsym)

/* Check for constant symbol */
#define isconstsym(a)	((a) != NULL && (a)->type == constsym)

/* Check for function symbol */
#define isfuncsym(a)	((a) != NULL && (a)->type == funcsym)

/* Check for function symbol */
#define istypesym(a)	((a) != NULL && (a)->type == typesym)



/*
 *****************************************************************************
 *
 * In order to create a symbol list like <symbol>,<symbol>,... for enume-
 * rations or variable declarations, we use a temporary list, which contains
 * the symbol links. Analogous we use a type list.
 */
struct symlist {
	int             num;		/* Current symbol number */
	struct sym     *sym;		/* Pointer to symbol */
	struct symlist *next;		/* Pointer to next list entry */
};

struct typelist {
	struct typesdef *t;		/* Pointer to type */
	struct typelist *next;		/* Pointer to next list entry */
};



/*
 ***************************************************************************
 *
 * Definitions to build expression tree
 */
/* Structure to hold variable information in an expression */
struct varinfo {
	struct sym      *symbol;		/* pointer to variable symbol */
	struct typesdef *type;			/* type of variable */
	struct expr     *index;			/* index in an array */
	struct varinfo  *next;			/* pointer to next record in */
};						/* ... record definition */

/* Structure of one expression node */
struct expr {
	struct typesdef *type;			/* type of expression */
	int              opcode;		/* type of operation */
	int              exprnum;		/* number of subexpressions */
	struct expr     *exprlist[MAX_EXPRS];	/* list of subexpressions */
	union {
		struct constdef  cval;		/* constant value */
		struct varinfo   var;		/* variable definition */
		struct sym      *func;		/* function pointer */
	} spec;
};

#define left	exprlist[0]			/* left (or only) expr tree */
#define right	exprlist[1]			/* right expression tree */

/* Get expression type - this is used so often, that it's better in a macro */
#define exprtype(a)	((a)->type == NULL ? EXPR_NONE : (a)->type->type)

/* Check if an expression is constant */
#define isconst(a)	((a)->opcode == CMD_CONST && (a)->exprnum == 0)

/* Check if an expression is a variable */
#define isvariable(a)	((a)->opcode == CMD_VAR && (a)->exprnum == 0)

/* Check if an expression is a leaf node */
#define isleaf(a)	((a)->exprnum == 0 && \
			 ((a)->opcode == CMD_VAR || \
			  (a)->opcode == CMD_CONST))

/* Check if an expression is a procedure call */
#define isproc(a)	((a)->type == NULL && iscmdfunc(a))

/* Check if an expression is a function call */
#define isfunc(a)	((a)->type != NULL && iscmdfunc(a))



/*
 ***************************************************************************
 *
 * Definition of operation codes to be used in the interface from the
 * parser to the code generator.
 */
typedef enum {
	CODE_PROC_START,
	CODE_PROC_END,
	CODE_RESTART,
	CODE_CALL_PROC,
	CODE_ASSIGN,
	CODE_INT_PRINT,
	CODE_STR_PRINT,
	CODE_CHAR_PRINT,
	CODE_INT_GET,
	CODE_STR_GET,
	CODE_CHAR_GET,
	CODE_PUSH_IPADDR,
	CODE_LOAD,
	CODE_IF,
	CODE_ELSE,
	CODE_WHILE,
	CODE_REPEAT,
	CODE_SELECT,
	CODE_ITEM,
	CODE_ENDNEST,
	CODE_BREAK
} codes;



/*
 ***************************************************************************
 *
 * External functions
 */
extern void interror __P((int num, char *msg));
extern void warning __P((char *msg));
extern void error __P((char *msg));
extern void yyerror __P((char *msg));
extern int yylex __P((void));
extern int yyparse __P((void));
extern void yylexinit __P((char *infile));
extern void yylexterm __P((void));
extern void print_token __P((void));
extern int getord __P((struct expr *ep));
extern void delexpr __P((struct expr *ep));
extern struct expr *reorg __P((struct expr *ep));
extern void docmd __P((codes cmd, struct sym *sp,
					struct expr *ep1, struct expr *ep2));



/*
 ***************************************************************************
 *
 * External variables
 */
extern char *curfile;			/* name of current input file */
extern struct sym *symtab;		/* symbol table */
extern struct sym *curproc;		/* pointer to current menu */
extern struct typesdef *typetab;	/* types table */
extern int lineno;			/* current line number */
extern int warnings;			/* number of warnings */
extern int errors;			/* number of errors */
extern int curlevel;			/* current nesting level */
extern char *yytext;			/* current token */



syntax highlighted by Code2HTML, v. 0.9.1