/* 1300, Thu 16 Sep 99

   SRL.H:  Global declarations for SRL compiler

   Copyright (C) 1998-2002 by Nevil Brownlee,
   CAIDA | University of Auckland */

/*
 * $Log: srl.h,v $
 * Revision 1.1.1.2.2.8  2002/02/23 01:57:42  nevil
 * Moving srl examples to examples/ directory.  Modified examples/Makefile.in
 *
 * Revision 1.1.1.2.2.3  2000/06/06 03:38:33  nevil
 * Combine NEW_ATR with TCP_ATR, various bug fixes
 *
 * Revision 1.1.1.2  1999/10/03 21:06:34  nevil
 * *** empty log message ***
 *
 * Revision 1.1.1.1.2.6  1999/09/22 05:34:11  nevil
 * Implement command-line defines
 * - Initialise scanner in init_symbol_table()
 * - Add get_command_define() to scanner.  This dummies up a define
 *      statement then calls push_include to invoke it
 * - Call get_command_define from main when we see a -D option
 *
 * Revision 1.1.1.1.2.5  1999/04/26 05:20:58  nevil
 * -Allow redeclaration of 'built-ins,' i.e. well-known ports, address
 *    families and transport types.  A warning is given telling the
 *    user what was redclared.
 * -Fix bug in checking of subroutine calls.  If a call appears before
 *    the subroutine declaration, it must have an integer label matching
 *    the highest one in the subroutine.  This is because the compiler
 *    doesn't emit dummy rules (to allow for returns) until after the
 *    declaration.
 * -Warn user that NeMaC doesn't handle return labels > 200.
 * -Warn user that NeMaC requires one SET and one FORMAT statement,
 *    and that every program should have at least one COUNT statement.
 *
 * Revision 1.1.1.1.2.4  1999/04/09 03:49:01  nevil
 * Implemented IPv6 addresses for SRL
 *   -D define V6 to enable the v6 code
 *   Added IPv4 and IPv6 as address families (IP => IPv4)
 *   Added get_v6address ro srl_scan
 *   v6err() routine to print v6 address errors
 *   V6DEBUG turns on v6 parser debugging
 *
 * Revision 1.1.1.1.2.3  1999/01/28 03:12:10  nevil
 * Mis-spelt attribute names are now correctly reported as errors
 *
 * Revision 1.1.1.1.2.2  1999/01/08 01:38:41  nevil
 * Distribution file for 4.3b7
 *
 * Revision 1.1.1.1.2.1  1998/12/16 02:59:10  nevil
 * Make compiler distinguish between 'save attrib' and 'save attrib = 0'
 * These both used to produce a rule which saved the whole attrib value!
 *
 * Revision 1.1.1.1  1998/11/16 03:57:33  nevil
 * Import of NeTraMet 4.3b3
 *
 * Revision 1.1.1.1  1998/11/16 03:22:03  nevil
 * Import of release 4.3b3
 *
 * Revision 1.1.1.1  1998/10/28 20:31:33  nevil
 * Import of NeTraMet 4.3b1
 *
 * Revision 1.1.2.1  1998/10/22 21:40:38  nevil
 * Moved srl from src/manager to its own subdirectory
 *
 * Revision 1.1.3.2  1998/10/18 23:44:14  nevil
 * Added Nicolai's patches, some 'tidying up' of the source
 *
 * Revision 1.1.3.1  1998/10/13 02:48:27  nevil
 * Import of Nicolai's 4.2.2
 *
 * Revision 1.1.1.1  1998/08/24 12:09:29  nguba
 * NetraMet 4.2 Original Distribution
 *
 * Revision 1.2  1998/07/21 00:43:57  rtfm
 * Change attrib numbers for 'New Attribs' I-D
 * First release version of SRL
 */

#ifndef SRLEXT
#define SRLEXT  extern
#define DECLARE  0
#define INIT(v)
#else
#define SRLEXT
#define DECLARE  1
#define INIT(v)  = v
#endif


SRLEXT int verbose, testing, optimise_level;
SRLEXT int list_source, sferrors, sfwarnings;


#define FNAME_LN         64  /* Max filename length */
#define IDENT_LN         32  /* Max identifier length */
#define INPUT_LN        256  /* Max source or intermediate line length */

#define MXINCL           10  /* Max include nesting depth */
#define MXIFGRP          10  /* Max IF group nesting depth */
#define MXCALLGRP        20  /* Max nbr of returns for a CALL */

#define MXSYMBOLS       500  /* Symbol table size */

#define IDTHASHBASE   65536  /* Id table hash modulus (power of 2) */
#define IDTOFLOWS     50000  /* Max ids outside hash base of id table */

#define PTNBLKSIZE      500  /* Nodes per parse-tree node block */

#define LBLTHASHBASE  65536  /* Id table hash modulus (power of 2) */
#define LBLTOFLOWS    50000  /* Max ids outside hash base of id table */

#define MXRETURNOFFSET  200  /* Max NeMaC will allow */

/* Parse tree */

struct pt_operand {
   int attrib;
   unsigned char value[RULE_ADDR_LEN];
   unsigned char mask[RULE_ADDR_LEN];
   unsigned int mask_nbr, tag_bits;  /* Decreasingly specific test order */
   int action;  char target[IDENT_LN+1];
   };   

struct pt_binop {
   int operator;
   };

struct pt_node {
   int type;
   struct pt_node *left, *right;
   int maxdepth;  /* Max push depth for this node */
   int grpsz;     /* Size of OR group starting at this node */
   union {
      struct pt_operand operand;
      struct pt_binop binop;
      } d;
   };

#define NT_OPERAND  1  /* Node types */
#define NT_BINOP    2

struct pt_node *alloc_node(void);  /* Allocate node */
void free_node(struct pt_node *b);  /* Return node to free list */
void free_pt(struct pt_node *t);  /* Free all nodes in t */
int set_mxd_pt(struct pt_node *n);  /* Set node push depths */
int set_grpsz_pt(struct pt_node *n);  /* Set OR-group sizes */
void print_pt(struct pt_node *n,  /* Display a parse tree */
   int depth, char *msg);


/* Symbol table */

#define ST_SYMBOL      1  /* Symbol types */
#define ST_DEFINE      2
#define ST_NEMAC_CMD   3

#define ST_BLOCK       4
#define ST_LABEL       5

#define ST_SUBROUTINE  6
#define ST_VARIABLE    7
#define ST_ADDRESS     8

SRLEXT char *sym_types[]
#if DECLARE
   = {"Other", "Symbol", "Define", "NeMaC command", "Block", "Label",
      "Subroutine", "Variable", "Address"
      }
#endif
   ;

struct subrt {  /* Info for ST_SUBROUTINEs */
   int first_param, n_params;  /* Param variable (Vn) range */
   int n_returns ;
   };

struct sub_arg {  /* Info for AT_ADDRESSes and ST_VARIABLES */
   int reg;     /* Meter variable to use */
   int attrib;  /* Attribute to pas as argument */
   };

struct symbol {
   int idx;   /* Index in id_table[] */
   int prev;  /* Chains back to previous use */
   int symtype;  /* From ST_ defines above */
   char name[IDENT_LN+1];
   union {
      char *def_str;  /* DEFINE value */
      struct subrt sub;
      struct sub_arg arg;  /* For ST_ADDRESSes and ST_VARIABLEs */
      } d;
   };

SRLEXT struct symbol st[MXSYMBOLS];
SRLEXT int st_top,st_ix, last_block_ix;
SRLEXT int subr_stx;  /* ST index of subroutine being declared */
SRLEXT int subr_reg;  /* Last parameter register allocated */


void start_st_block(char *block_name);
void add_symbol(int symtype);
void add_argument(int symtype, int reg, int attrib);
void clear_st_block(void);
void clear_st_subroutine(int stx);


/* Identifier table */

struct ident {
   int next;  /* For making hash chains */
   char id[IDENT_LN+1];
   int type;  /* From TOK_ defines below */
   unsigned int subtype;
   int stx;  /* Current index to st[] */
   };

#define IDTHASHMASK  (IDTHASHBASE-1)
#define IDTSIZE      (IDTHASHBASE+IDTOFLOWS)

SRLEXT struct ident id_table[IDTSIZE];
SRLEXT int id_top,id_index;


/* Scanner */

SRLEXT FILE *sfp;  /* Scanner globals */
SRLEXT char scan_sfname[FNAME_LN];
SRLEXT char *ibp, inbuf[INPUT_LN];
SRLEXT char token[IDENT_LN+1];
SRLEXT int lic, ic,  /* Last input char, current input char */
   line_nbr, iblisted, in_define;
SRLEXT int toktype, toksubtype, toklen;

#define TOK_UNUSED    0  /* Token types.  Returned by next() */
#define TOK_EOF       1

#define TOK_SPECIAL   2
#define TOK_NUMBER    3
#define TOK_STRING    4

#define TOK_SYMBOL    5

#define TOK_RSVWD     6
#define TOK_ATTRIB    7
#define TOK_AFTYPE    8
#define TOK_TRANSPR   9
#define TOK_WKP      10
#define TOK_PMEACT   11

#define TOK_LABEL    12

SRLEXT char *tok_types[]
#if DECLARE
   = {"Other", "EOF", "Special", "Number", "String", 
      "Symbol", "Rsvwd", "Attrib", "AF-type", "Trans-Prot",
      "WKP", "PME action", "Label"
      }
#endif
   ;

#define SC_EQUAL        1  /* == */
#define SC_ASSIGN       2  /* := */
#define SC_LAND         3  /* && */
#define SC_LOR          4  /* || */
#define SC_SAMEOR       5  /* ()  list of || for same attribute */

#define RW_INCLUDE      1  /* Pragmas */
#define RW_OPTIMISE     2
#define RW_SET          3
#define RW_STATS        4
#define RW_FORMAT       5

#define RW_ADDRESS     11  /* Reserved words */
#define RW_CALL        12
#define RW_COUNT       13
#define RW_DEFINE      14
#define RW_ELSE        15
#define RW_ENDCALL     16
#define RW_ENDSUB      17
#define RW_EXIT        18
#define RW_IF          19
#define RW_IGNORE      20
#define RW_NOMATCH     21
#define RW_RETURN      22
#define RW_SAVE        23
#define RW_SAVE_V      24  /* For 'save attrib = value' */
#define RW_STORE       25
#define RW_SUBROUTINE  26
#define RW_VARIABLE    27


struct incl_ent {
   FILE *fp;
   char sfname[FNAME_LN], buf[256], *bp;
   int lic,ic, line_nbr,iblisted, in_define;
   };

SRLEXT struct incl_ent incl_stack[MXINCL];
SRLEXT int incl_depth;


/* General-purpose functions declared in srl_scan.c */

unsigned char *strmov(unsigned char *d, unsigned char *s);
char *gnbr(unsigned long *n, char *s);
char *gcstring(char *s, int *len);

char *fmt_time(time_t *t);

unsigned char *sprintvalue(unsigned char *s, unsigned char *v);
unsigned char *sprintvalmsk(unsigned char *s, struct pt_node *n);
void printvalue(unsigned char *v);

void mask_from_width(unsigned char *m, int w);
int width_from_mask(unsigned char *m);

void err_msg(int err_type, char *fmt, ...);
#define ET_NULL  0
#define ET_WARN  1
#define ET_ERR   2

void get_cmd_define(char *cmd);

int parse_open(unsigned char *fn);
int next(void);
void dump_symbol_table(void);

void get_default_mask(unsigned char *v, int attrib);
int get_value(unsigned char *v, int attrib);
unsigned long get_number(void);


/* Code emission */

SRLEXT int asmint;  /* 1 => use words in intermediate files */

struct lbl_info {
   int next;      /* For making hash chains */
   char id[IDENT_LN+1];
   int type;
   unsigned int subtype;
   int stx;       /* ST index of originating symbol */
   int prev;      /* For chaining labels */
   int ngotos;    /* Nbr of rules targeting this label */
   int declared;  /* 0 = not declared yet */
   int in_expr;   /* 1 = within expression */
   int goto_ix;   /* Stmt is a Null: goto, target label ix in LT */
   };

#define LBLTHASHMASK  (LBLTHASHBASE-1)
#define LBLTSIZE      (LBLTHASHBASE+LBLTOFLOWS)

SRLEXT struct lbl_info lbl_table[LBLTSIZE];
SRLEXT int lbl_top,lbl_index;

int intermediate_open(char *fn_prefix);
void intermediate_close(void);
void emit_comment(char *fmt, ...);
void emit_label(char *lbl);
void emit_opt_level(int level);
void emit_goto(char *lbl);
int param_attrib(struct symbol *sp);
void emit_IF_level(int incr);
void emit_expression(struct pt_node *op,
   int which, char *succeed, char *next_if);
void emit_imperative(struct pt_node *op,
   int which, char *target);
void emit_return_code(struct pt_node *op,
   int which, char *target);
void emit_subr_call(int call_stx);
void emit_NeMaC_command(char *fmt, ...);
void emit_pass2(char *codefn);


#undef DECLARE
#undef INIT
