summaryrefslogtreecommitdiff
path: root/src/rtt
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-01-27 23:51:56 +0000
committerIgor Pashev <pashev.igor@gmail.com>2013-01-27 23:51:56 +0000
commit6ab0c0f5bf14ed9c15370407b9ee7e0b4b089ae1 (patch)
tree926065cf45450116098db664e3c61dced9e1f21a /src/rtt
downloadicon-6ab0c0f5bf14ed9c15370407b9ee7e0b4b089ae1.tar.gz
Initial upstream version 9.4.3upstream/9.4.3
Diffstat (limited to 'src/rtt')
-rw-r--r--src/rtt/Makefile87
-rw-r--r--src/rtt/ltoken.h117
-rw-r--r--src/rtt/rtt.h2
-rw-r--r--src/rtt/rtt1.h187
-rw-r--r--src/rtt/rttdb.c1440
-rw-r--r--src/rtt/rttgram.y1101
-rw-r--r--src/rtt/rttilc.c1402
-rw-r--r--src/rtt/rttinlin.c1950
-rw-r--r--src/rtt/rttlex.c356
-rw-r--r--src/rtt/rttmain.c402
-rw-r--r--src/rtt/rttmisc.c114
-rw-r--r--src/rtt/rttnode.c264
-rw-r--r--src/rtt/rttout.c3821
-rw-r--r--src/rtt/rttparse.c2992
-rw-r--r--src/rtt/rttproto.h92
-rw-r--r--src/rtt/rttsym.c722
16 files changed, 15049 insertions, 0 deletions
diff --git a/src/rtt/Makefile b/src/rtt/Makefile
new file mode 100644
index 0000000..db6445e
--- /dev/null
+++ b/src/rtt/Makefile
@@ -0,0 +1,87 @@
+# Makefile for the Icon run-time translator, rtt,
+# which is used to build the Icon run-time system.
+
+include ../../Makedefs
+
+
+ROBJS = rttparse.o rttmain.o rttlex.o rttsym.o rttnode.o rttout.o rttmisc.o\
+ rttdb.o rttinlin.o rttilc.o
+
+PP_DIR = ../preproc/
+P_DOT_H = $(PP_DIR)preproc.h $(PP_DIR)pproto.h ltoken.h ../h/mproto.h\
+ ../h/define.h ../h/config.h ../h/typedefs.h\
+ ../h/cstructs.h ../h/cpuconf.h
+POBJS = pout.o pchars.o perr.o pmem.o bldtok.o macro.o preproc.o\
+ evaluate.o files.o gettok.o pinit.o
+
+COBJS = ../common/getopt.o ../common/time.o ../common/filepart.o \
+ ../common/identify.o ../common/strtbl.o ../common/alloc.o \
+ ../common/rtdb.o ../common/munix.o ../common/literals.o
+
+OBJ = $(ROBJS) $(POBJS) $(COBJS)
+
+
+rtt: $(OBJ)
+ $(CC) $(LDFLAGS) -o rtt $(OBJ)
+ cp rtt ../../bin
+ strip ../../bin/rtt$(EXE)
+
+library: $(OBJ)
+ rm -rf rtt.a
+ ar qc rtt.a $(OBJ)
+
+$(COBJS):
+ cd ../common; $(MAKE)
+
+$(ROBJS): rtt.h rtt1.h rttproto.h $(P_DOT_H)
+
+rttdb.o: ../h/version.h
+rttparse.o : ../h/gsupport.h ../h/config.h ../h/cstructs.h \
+ ../h/mproto.h ../h/typedefs.h ../h/cpuconf.h ../h/define.h
+
+pout.o: $(PP_DIR)pout.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)pout.c
+
+pchars.o: $(PP_DIR)pchars.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)pchars.c
+
+perr.o: $(PP_DIR)perr.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)perr.c
+
+pmem.o: $(PP_DIR)pmem.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)pmem.c
+
+bldtok.o: $(PP_DIR)bldtok.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)bldtok.c
+
+macro.o: $(PP_DIR)macro.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)macro.c
+
+preproc.o: $(PP_DIR)preproc.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)preproc.c
+
+evaluate.o: $(PP_DIR)evaluate.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)evaluate.c
+
+files.o: $(PP_DIR)files.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)files.c
+
+gettok.o: $(PP_DIR)gettok.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)gettok.c
+
+pinit.o: $(PP_DIR)pinit.c $(P_DOT_H)
+ $(CC) -c $(CFLAGS) $(PP_DIR)pinit.c
+
+#
+# The following entry is commented out because it is not normally
+# necessary to recreate rttparse.c and ltoken.h unless the grammar
+# in rttgram.y for the run-time langauge is changed. Recreating these
+# files is not normally a part of the installation process. Note that
+# on some systems, yacc may not have large enough internal tables to
+# translate this grammar.
+#
+#rttparse.c ltoken.h: rttgram.y
+# yacc -d rttgram.y
+# fgrep -v -x "extern char *malloc(), *realloc();" y.tab.c > rttparse.c
+# rm y.tab.c
+# mv y.tab.h ltoken.h
diff --git a/src/rtt/ltoken.h b/src/rtt/ltoken.h
new file mode 100644
index 0000000..d426fcf
--- /dev/null
+++ b/src/rtt/ltoken.h
@@ -0,0 +1,117 @@
+
+typedef union {
+ struct token *t;
+ struct node *n;
+ long i;
+ } YYSTYPE;
+extern YYSTYPE yylval;
+# define Identifier 257
+# define StrLit 258
+# define LStrLit 259
+# define FltConst 260
+# define DblConst 261
+# define LDblConst 262
+# define CharConst 263
+# define LCharConst 264
+# define IntConst 265
+# define UIntConst 266
+# define LIntConst 267
+# define ULIntConst 268
+# define Arrow 269
+# define Incr 270
+# define Decr 271
+# define LShft 272
+# define RShft 273
+# define Leq 274
+# define Geq 275
+# define TokEqual 276
+# define Neq 277
+# define And 278
+# define Or 279
+# define MultAsgn 280
+# define DivAsgn 281
+# define ModAsgn 282
+# define PlusAsgn 283
+# define MinusAsgn 284
+# define LShftAsgn 285
+# define RShftAsgn 286
+# define AndAsgn 287
+# define XorAsgn 288
+# define OrAsgn 289
+# define Sizeof 290
+# define Intersect 291
+# define OpSym 292
+# define Typedef 293
+# define Extern 294
+# define Static 295
+# define Auto 296
+# define TokRegister 297
+# define Tended 298
+# define TokChar 299
+# define TokShort 300
+# define Int 301
+# define TokLong 302
+# define Signed 303
+# define Unsigned 304
+# define Float 305
+# define Doubl 306
+# define Const 307
+# define Volatile 308
+# define Void 309
+# define TypeDefName 310
+# define Struct 311
+# define Union 312
+# define TokEnum 313
+# define Ellipsis 314
+# define Case 315
+# define Default 316
+# define If 317
+# define Else 318
+# define Switch 319
+# define While 320
+# define Do 321
+# define For 322
+# define Goto 323
+# define Continue 324
+# define Break 325
+# define Return 326
+# define Runerr 327
+# define Is 328
+# define Cnv 329
+# define Def 330
+# define Exact 331
+# define Empty_type 332
+# define IconType 333
+# define Component 334
+# define Variable 335
+# define Any_value 336
+# define Named_var 337
+# define Struct_var 338
+# define C_Integer 339
+# define Arith_case 340
+# define C_Double 341
+# define C_String 342
+# define Tmp_string 343
+# define Tmp_cset 344
+# define Body 345
+# define End 346
+# define TokFunction 347
+# define Keyword 348
+# define Operator 349
+# define Underef 350
+# define Declare 351
+# define Suspend 352
+# define Fail 353
+# define Inline 354
+# define Abstract 355
+# define Store 356
+# define TokType 357
+# define New 358
+# define All_fields 359
+# define Then 360
+# define Type_case 361
+# define Of 362
+# define Len_case 363
+# define Constant 364
+# define Errorfail 365
+# define IfStmt 366
diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h
new file mode 100644
index 0000000..78ac812
--- /dev/null
+++ b/src/rtt/rtt.h
@@ -0,0 +1,2 @@
+#include "ltoken.h"
+#include "rtt1.h"
diff --git a/src/rtt/rtt1.h b/src/rtt/rtt1.h
new file mode 100644
index 0000000..76779c7
--- /dev/null
+++ b/src/rtt/rtt1.h
@@ -0,0 +1,187 @@
+#include "../preproc/preproc.h"
+#include "../preproc/pproto.h"
+
+#define IndentInc 3
+#define MaxCol 80
+
+#define Max(x,y) ((x)>(y)?(x):(y))
+
+/*
+ * cfile is used to create a list of cfiles created from a source file.
+ */
+struct cfile {
+ char *name;
+ struct cfile *next;
+ };
+
+/*
+ * srcfile is an entry of dependants of a source file.
+ */
+struct srcfile {
+ char *name;
+ struct cfile *dependents;
+ struct srcfile *next;
+ };
+
+#define ForceNl() nl = 1;
+extern int nl; /* flag: a new-line is needed in the output */
+
+/*
+ * The lexical analyzer recognizes 3 states. Operators are treated differently
+ * in each state.
+ */
+#define DfltLex 0 /* Covers most input. */
+#define OpHead 1 /* In head of an operator definition. */
+#define TypeComp 2 /* In abstract type computation */
+
+extern int lex_state; /* state of operator recognition */
+extern char *compiler_def; /* #define for COMPILER */
+extern FILE *out_file; /* output file */
+extern int def_fnd; /* C input defines something concrete */
+extern char *inclname; /* include file to be included by C compiler */
+extern int iconx_flg; /* flag: indicate that iconx style code is needed */
+extern int enable_out; /* enable output of C code */
+extern char *largeints; /* "Largeints" or "NoLargeInts" */
+
+/*
+ * The symbol table is used by the lexical analyser to decide whether an
+ * identifier is an ordinary identifier, a typedef name, or a reserved
+ * word. It is used by the parse tree builder to decide whether an
+ * identifier is an ordinary C variable, a tended variable, a parameter
+ * to a run-time routine, or the special variable "result".
+ */
+struct sym_entry {
+ int tok_id; /* Ident, TokType, or identification of reserved word */
+ char *image; /* image of symbol */
+ int id_type; /* OtherDcl, TndDesc, TndStr, TndBlk, Label, RtParm,
+ DrfPrm, RsltLoc */
+ union {
+ struct { /* RtParm: */
+ int param_num; /* parameter number */
+ int cur_loc; /* PrmTend, PrmCStr, PrmInt, or PrmDbl */
+ int non_tend; /* non-tended locations used */
+ int parm_mod; /* something may have modified it */
+ struct sym_entry *next;
+ } param_info;
+ struct { /* TndDesc, TndStr, TndBlk: */
+ struct node *init; /* initial value from declaration */
+ char *blk_name; /* TndBlk: struct name of block */
+ struct sym_entry *next;
+ } tnd_var;
+ struct { /* OtherDcl from "declare {...}": */
+ struct node *tqual; /* storage class, type qualifier list */
+ struct node *dcltor; /* declarator */
+ struct node *init; /* initial value from declaration */
+ struct sym_entry *next;
+ } declare_var;
+ int typ_indx; /* index into arrays of type information */
+ word lbl_num; /* label number used in in-line code */
+ int referenced; /* RsltLoc: is referenced */
+ } u;
+ int t_indx; /* index into tended array */
+ int il_indx; /* index used in in-line code */
+ int nest_lvl; /* 0 - reserved word, 1 - global, >= 2 - local */
+ int may_mod; /* may be modified in particular piece of code */
+ int ref_cnt;
+ struct sym_entry *next;
+ };
+
+/*
+ * Path-specific parameter information must be saved and merged for
+ * branching and joining of paths.
+ */
+struct parminfo {
+ int cur_loc;
+ int parm_mod;
+ };
+
+/*
+ * A list is maintained of information needed to initialize tended descriptors.
+ */
+struct init_tend {
+ int t_indx; /* index into tended array */
+ int init_typ; /* TndDesc, TndStr, TndBlk */
+ struct node *init; /* initial value from declaration */
+ int nest_lvl; /* level of nesting of current use of tended slot */
+ int in_use; /* tended slot is being used in current scope */
+ struct init_tend *next;
+ };
+
+
+extern int op_type; /* Function, Keyword, Operator, or OrdFunc */
+extern char lc_letter; /* f = function, o = operator, k = keyword */
+extern char uc_letter; /* F = function, O = operator, K = keyword */
+extern char prfx1; /* 1st char of unique prefix for operation */
+extern char prfx2; /* 2nd char of unique prefix for operation */
+extern char *fname; /* current source file name */
+extern int line; /* current source line number */
+extern struct implement *cur_impl; /* data base entry for current operator */
+extern struct token *comment; /* descriptive comment for current oper */
+extern int n_tmp_str; /* total number of string buffers needed */
+extern int n_tmp_cset; /* total number of cset buffers needed */
+extern int nxt_sbuf; /* index of next string buffer */
+extern int nxt_cbuf; /* index of next cset buffer */
+extern struct sym_entry *params; /* current list of parameters */
+extern struct sym_entry *decl_lst; /* declarations from "declare {...}" */
+extern struct init_tend *tend_lst; /* list of allocated tended slots */
+extern char *str_rslt; /* string "result" in string table */
+extern word lbl_num; /* next unused label number */
+extern struct sym_entry *v_len; /* symbol entry for size of varargs */
+extern int il_indx; /* next index into data base symbol table */
+
+/*
+ * lvl_entry keeps track of what is happening at a level of nested declarations.
+ */
+struct lvl_entry {
+ int nest_lvl;
+ int kind_dcl; /* IsTypedef, TndDesc, TndStr, TndBlk, or OtherDcl */
+ char *blk_name; /* for TndBlk, the struct name of the block */
+ int parms_done; /* level consists of parameter list which is complete */
+ struct sym_entry *tended; /* symbol table entries for tended variables */
+ struct lvl_entry *next;
+ };
+
+extern struct lvl_entry *dcl_stk; /* stack of declaration contexts */
+
+extern int fnc_ret; /* RetInt, RetDbl, RetNoVal, or RetSig for current func */
+
+#define NoAbstr -1001 /* no abstract return statement has been encountered */
+#define SomeType -1002 /* assume returned value is consistent with abstr ret */
+extern int abs_ret; /* type from abstract return statement */
+
+/*
+ * Definitions for use in parse tree nodes.
+ */
+
+#define PrimryNd 1 /* simply a token */
+#define PrefxNd 2 /* a prefix expression */
+#define PstfxNd 3 /* a postfix expression */
+#define BinryNd 4 /* a binary expression (not necessarily infix) */
+#define TrnryNd 5 /* an expression with 3 subexpressions */
+#define QuadNd 6 /* an expression with 4 subexpressions */
+#define LstNd 7 /* list of declaration parts */
+#define CommaNd 8 /* arg lst, declarator lst, or init lst, not comma op */
+#define StrDclNd 9 /* structure field declaration */
+#define PreSpcNd 10 /* prefix expression that needs a space after it */
+#define ConCatNd 11 /* two ajacent pieces of code with no other syntax */
+#define SymNd 12 /* a symbol (identifier) node */
+#define ExactCnv 13 /* (exact)integer or (exact)C_integer conversion */
+#define CompNd 14 /* compound statement */
+#define AbstrNd 15 /* abstract type computation */
+#define IcnTypNd 16 /* name of an Icon type */
+
+#define NewNode(size) (struct node *)alloc(\
+ sizeof(struct node) + (size-1) * sizeof(union field))
+
+union field {
+ struct node *child;
+ struct sym_entry *sym; /* used with SymNd & CompNd*/
+ };
+
+struct node {
+ int nd_id;
+ struct token *tok;
+ union field u[1]; /* actual size varies with node type */
+ };
+
+#include "rttproto.h"
diff --git a/src/rtt/rttdb.c b/src/rtt/rttdb.c
new file mode 100644
index 0000000..22368fe
--- /dev/null
+++ b/src/rtt/rttdb.c
@@ -0,0 +1,1440 @@
+/*
+ * rttdb.c - routines to read, manipulate, and write the data base of
+ * information about run-time routines.
+ */
+
+#include "rtt.h"
+#include "../h/version.h"
+
+#define DHSize 47
+#define MaxLine 80
+
+/*
+ * prototypes for static functions.
+ */
+static void max_pre (struct implement **tbl, char *pre);
+static int name_cmp (char *p1, char *p2);
+static int op_cmp (char *p1, char *p2);
+static void prt_dpnd (FILE *db);
+static void prt_impls (FILE *db, char *sect, struct implement **tbl,
+ int num, struct implement **sort_ary, int (*com)());
+static int prt_c_fl (FILE *db, struct cfile *clst, int line_left);
+static int put_case (FILE *db, struct il_code *il);
+static void put_ilc (FILE *db, struct il_c *ilc);
+static void put_inlin (FILE *db, struct il_code *il);
+static void put_ret (FILE *db, struct il_c *ilc);
+static void put_typcd (FILE *db, int typcd);
+static void put_var (FILE *db, int code, struct il_c *ilc);
+static void ret_flag (FILE *db, int flag, int may_fthru);
+static int set_impl (struct token *name, struct implement **tbl,
+ int num_impl, char *pre);
+static void set_prms (struct implement *ptr);
+static int src_cmp (char *p1, char *p2);
+
+static struct implement *bhash[IHSize]; /* hash area for built-in func table */
+static struct implement *ohash[IHSize]; /* hash area for operator table */
+static struct implement *khash[IHSize]; /* hash area for keyword table */
+
+static struct srcfile *dhash[DHSize]; /* hash area for file dependencies */
+
+static int num_fnc; /* number of function in data base */
+static int num_op = 0; /* number of operators in data base */
+static int num_key; /* number of keywords in data base */
+static int num_src = 0; /* number of source files in dependencies */
+
+static char fnc_pre[2]; /* next prefix available for functions */
+static char op_pre[2]; /* next prefix available for operators */
+static char key_pre[2]; /* next prefix available for keywords */
+
+static long min_rs; /* min result sequence of current operation */
+static long max_rs; /* max result sequence of current operation */
+static int rsm_rs; /* '+' at end of result sequencce of cur. oper. */
+
+static int newdb = 0; /* flag: this is a new data base */
+struct token *comment; /* comment associated with current operation */
+struct implement *cur_impl; /* data base entry for current operation */
+
+/*
+ * loaddb - load data base.
+ */
+void loaddb(dbname)
+char *dbname;
+ {
+ char *op;
+ struct implement *ip;
+ unsigned hashval;
+ int i;
+ char *srcname;
+ char *c_name;
+ struct srcfile *sfile;
+
+
+ /*
+ * Initialize internal data base.
+ */
+ for (i = 0; i < IHSize; i++) {
+ bhash[i] = NULL; /* built-in function table */
+ ohash[i] = NULL; /* operator table */
+ khash[i] = NULL; /* keyword table */
+ }
+ for (i = 0; i < DHSize; i++)
+ dhash[i] = NULL; /* dependency table */
+
+ /*
+ * Determine if this is a new data base or an existing one.
+ */
+ if (iconx_flg || !db_open(dbname, &largeints))
+ newdb = 1;
+ else {
+
+ /*
+ * Read information about built-in functions.
+ */
+ num_fnc = db_tbl("functions", bhash);
+
+ /*
+ * Read information about operators.
+ */
+ db_chstr("", "operators"); /* verify and skip "operators" */
+
+ while ((op = db_string()) != NULL) {
+ /*
+ * Read header information for the operator.
+ */
+ if ((ip = db_impl('O')) == NULL)
+ db_err2(1, "no implementation information for operator", op);
+ ip->op = op;
+
+ /*
+ * Read the descriptive comment and in-line code for the operator,
+ * then put the entry in the hash table.
+ */
+ db_code(ip);
+ hashval = (int)IHasher(op);
+ ip->blink = ohash[hashval];
+ ohash[hashval] = ip;
+ db_chstr("", "end"); /* verify and skip "end" */
+ ++num_op;
+ }
+ db_chstr("", "endsect"); /* verify and skip "endsect" */
+
+ /*
+ * Read information about keywords.
+ */
+ num_key = db_tbl("keywords", khash);
+
+ /*
+ * Read C file/source dependency information.
+ */
+ db_chstr("", "dependencies"); /* verify and skip "dependencies" */
+
+ while ((srcname = db_string()) != NULL) {
+ sfile = src_lkup(srcname);
+ while ((c_name = db_string()) != NULL)
+ add_dpnd(sfile, c_name);
+ db_chstr("", "end"); /* verify and skip "end" */
+ }
+ db_chstr("", "endsect"); /* verify and skip "endsect" */
+
+ db_close();
+ }
+
+ /*
+ * Determine the next available operation prefixes by finding the
+ * maximum prefixes currently in use.
+ */
+ max_pre(bhash, fnc_pre);
+ max_pre(ohash, op_pre);
+ max_pre(khash, key_pre);
+ }
+
+/*
+ * max_pre - find the maximum prefix in an implemetation table and set the
+ * prefix array to the next value.
+ */
+static void max_pre(tbl, pre)
+struct implement **tbl;
+char *pre;
+ {
+ register struct implement *ptr;
+ unsigned hashval;
+ int empty = 1;
+ char dmy_pre[2];
+
+ pre[0] = '0';
+ pre[1] = '0';
+ for (hashval = 0; hashval < IHSize; ++hashval)
+ for (ptr = tbl[hashval]; ptr != NULL; ptr = ptr->blink) {
+ empty = 0;
+ /*
+ * Determine if this prefix is larger than any found so far.
+ */
+ if (cmp_pre(ptr->prefix, pre) > 0) {
+ pre[0] = ptr->prefix[0];
+ pre[1] = ptr->prefix[1];
+ }
+ }
+ if (!empty)
+ nxt_pre(dmy_pre, pre, 2);
+ }
+
+
+/*
+ * src_lkup - return pointer to dependency information for the given
+ * source file.
+ */
+struct srcfile *src_lkup(srcname)
+char *srcname;
+ {
+ unsigned hashval;
+ struct srcfile *sfile;
+
+ /*
+ * See if the source file is already in the dependancy section of
+ * the data base.
+ */
+ hashval = (unsigned int)(unsigned long)srcname % DHSize;
+ for (sfile = dhash[hashval]; sfile != NULL && sfile->name != srcname;
+ sfile = sfile->next)
+ ;
+
+ /*
+ * If an entry for the source file was not found, create one.
+ */
+ if (sfile == NULL) {
+ sfile = NewStruct(srcfile);
+ sfile->name = srcname;
+ sfile->dependents = NULL;
+ sfile->next = dhash[hashval];
+ dhash[hashval] = sfile;
+ ++num_src;
+ }
+ return sfile;
+ }
+
+/*
+ * add_dpnd - add the given source/dependency relation to the dependency
+ * table.
+ */
+void add_dpnd(sfile, c_name)
+struct srcfile *sfile;
+char *c_name;
+ {
+ struct cfile *cf;
+
+ cf = NewStruct(cfile);
+ cf->name = c_name;
+ cf->next = sfile->dependents;
+ sfile->dependents = cf;
+ }
+
+/*
+ * clr_dpnd - delete all dependencies for the given source file.
+ */
+void clr_dpnd(srcname)
+char *srcname;
+ {
+ src_lkup(srcname)->dependents = NULL;
+ }
+
+/*
+ * dumpdb - write the updated data base.
+ */
+void dumpdb(dbname)
+char *dbname;
+ {
+ #ifdef Rttx
+ fprintf(stdout,
+ "rtt was compiled to only support the intepreter, use -x\n");
+ exit(EXIT_FAILURE);
+ #else /* Rttx */
+ FILE *db;
+ struct implement **sort_ary;
+ int ary_sz;
+ int i;
+
+ db = fopen(dbname, "wb");
+ if (db == NULL)
+ err2("cannot open data base for output:", dbname);
+ if(newdb)
+ fprintf(stdout, "creating new data base: %s\n", dbname);
+
+ /*
+ * The data base starts with a version number associated with this
+ * version of rtt and an indication of whether LargeInts was
+ * defined during the build.
+ */
+ fprintf(db, "%s %s\n\n", DVersion, largeints);
+
+ fprintf(db, "\ntypes\n\n"); /* start of type code section */
+ for (i = 0; i < num_typs; ++i)
+ fprintf(db, " T%d: %s\n", i, icontypes[i].id);
+ fprintf(db, "\n$endsect\n\n"); /* end of section for type codes */
+
+ fprintf(db, "\ncomponents\n\n"); /* start of component code section */
+ for (i = 0; i < num_cmpnts; ++i)
+ fprintf(db, " C%d: %s\n", i, typecompnt[i].id);
+ fprintf(db, "\n$endsect\n\n"); /* end of section for component codes */
+
+ /*
+ * Allocate an array for sorting operation entries. It must be
+ * large enough to hold functions, operators, or keywords.
+ */
+ ary_sz = Max(num_fnc, num_op);
+ ary_sz = Max(ary_sz, num_key);
+ if (ary_sz > 0)
+ sort_ary = alloc(ary_sz * sizeof(struct implement*));
+ else
+ sort_ary = NULL;
+
+ /*
+ * Sort and print to the data base the enties for each of the
+ * three operation sections.
+ */
+ prt_impls(db, "functions", bhash, num_fnc, sort_ary, name_cmp);
+ prt_impls(db, "\noperators", ohash, num_op, sort_ary, op_cmp);
+ prt_impls(db, "\nkeywords", khash, num_key, sort_ary, name_cmp);
+ if (ary_sz > 0)
+ free((char *)sort_ary);
+
+ /*
+ * Print the dependancy information to the data base.
+ */
+ prt_dpnd(db);
+ if (fclose(db) != 0)
+ err2("cannot close ", dbname);
+ #endif /* Rttx */
+ }
+
+#ifndef Rttx
+/*
+ * prt_impl - sort and print to the data base the enties from one
+ * of the operation tables.
+ */
+static void prt_impls(db, sect, tbl, num, sort_ary, cmp)
+FILE *db;
+char *sect;
+struct implement **tbl;
+int num;
+struct implement **sort_ary;
+int (*cmp)();
+ {
+ int i;
+ int j;
+ unsigned hashval;
+ struct implement *ip;
+
+ /*
+ * Each operation section begins with the section name.
+ */
+ fprintf(db, "%s\n\n", sect);
+
+ /*
+ * Sort the table entries before printing.
+ */
+ if (num > 0) {
+ i = 0;
+ for (hashval = 0; hashval < IHSize; ++hashval)
+ for (ip = tbl[hashval]; ip != NULL; ip = ip->blink)
+ sort_ary[i++] = ip;
+ qsort((char *)sort_ary, num, sizeof(struct implement *), cmp);
+ }
+
+ /*
+ * Output each entry to the data base.
+ */
+ for (i = 0; i < num; ++i) {
+ ip = sort_ary[i];
+
+ /*
+ * Operators have operator symbols.
+ */
+ if (ip->op != NULL)
+ fprintf(db, "%s\t", ip->op);
+
+ /*
+ * Print the operation name, the unique prefix used to generate
+ * C function names, and the number of parameters to the operation.
+ */
+ fprintf(db, "%s\t%c%c %d(", ip->name, ip->prefix[0], ip->prefix[1],
+ ip->nargs);
+
+ /*
+ * For each parameter, write and indication of whether a dereferenced
+ * value, 'd', and/or and undereferenced value, 'u', is needed.
+ */
+ for (j = 0; j < ip->nargs; ++j) {
+ if (j > 0)
+ fprintf(db, ",");
+ if (ip->arg_flgs[j] & RtParm)
+ fprintf(db, "u");
+ if (ip->arg_flgs[j] & DrfPrm)
+ fprintf(db, "d");
+ }
+
+ /*
+ * Indicate if the last parameter represents the tail of a
+ * variable length argument list.
+ */
+ if (ip->nargs > 0 && ip->arg_flgs[ip->nargs - 1] & VarPrm)
+ fprintf(db, "v");
+ fprintf(db, ")\t{");
+
+ /*
+ * Print the min and max result sequence length.
+ */
+ if (ip->min_result != NoRsltSeq) {
+ fprintf(db, "%ld,", ip->min_result);
+ if (ip->max_result == UnbndSeq)
+ fprintf(db, "*");
+ else
+ fprintf(db, "%ld", ip->max_result);
+ if (ip->resume)
+ fprintf(db, "+");
+ }
+ fprintf(db, "} ");
+
+ /*
+ * Print the return/suspend/fail/fall-through flag and an indication
+ * of whether the operation explicitly uses the result location
+ * (as opposed to an implicit use via return or suspend).
+ */
+ ret_flag(db, ip->ret_flag, 0);
+ if (ip->use_rslt)
+ fprintf(db, "t ");
+ else
+ fprintf(db, "f ");
+
+ /*
+ * Print the descriptive comment associated with the operation.
+ */
+ fprintf(db, "\n\"%s\"\n", ip->comment);
+
+ /*
+ * Print information about tended declarations from the declare
+ * statement. The number of tended variables is printed followed
+ * by an entry for each variable. Each entry consists of the
+ * type of the declaration
+ *
+ * struct descrip -> desc
+ * char * -> str
+ * struct b_xxx * -> blkptr b_xxx
+ * union block * -> blkptr *
+ *
+ * followed by the C code for the initializer (nil indicates none).
+ */
+ fprintf(db, "%d ", ip->ntnds);
+ for (j = 0; j < ip->ntnds; ++j) {
+ switch (ip->tnds[j].var_type) {
+ case TndDesc:
+ fprintf(db, "desc ");
+ break;
+ case TndStr:
+ fprintf(db, "str ");
+ break;
+ case TndBlk:
+ fprintf(db, "blkptr ");
+ if (ip->tnds[j].blk_name == NULL)
+ fprintf(db, "* ");
+ else
+ fprintf(db, "%s ", ip->tnds[j].blk_name);
+ break;
+ }
+ put_ilc(db, ip->tnds[j].init);
+ }
+
+ /*
+ * Print information about non-tended declarations from the declare
+ * statement. The number of variables is printed followed by an
+ * entry for each variable. Each entry consists of the variable
+ * name followed by the complete C code for the declaration.
+ */
+ fprintf(db, "\n%d ", ip->nvars);
+ for (j = 0; j < ip->nvars; ++j) {
+ fprintf(db, "%s ", ip->vars[j].name);
+ put_ilc(db, ip->vars[j].dcl);
+ }
+ fprintf(db, "\n");
+
+ /*
+ * Output the "executable" code (includes abstract code) for the
+ * operation.
+ */
+ put_inlin(db, ip->in_line);
+ fprintf(db, "\n$end\n\n"); /* end of operation entry */
+ }
+ fprintf(db, "$endsect\n\n"); /* end of section for operation type */
+ }
+
+/*
+ * put_inlin - put in-line code into the data base file. This is the
+ * code used by iconc to perform type infernence for the operation
+ * and to generate a tailored version of the operation.
+ */
+static void put_inlin(db, il)
+FILE *db;
+struct il_code *il;
+ {
+ int i;
+ int num_cases;
+ int indx;
+
+ /*
+ * RTL statements are handled by this function. Other functions
+ * are called for C code.
+ */
+ if (il == NULL) {
+ fprintf(db, "nil ");
+ return;
+ }
+
+ switch (il->il_type) {
+ case IL_Const:
+ /*
+ * Constant keyword.
+ */
+ fprintf(db, "const ");
+ put_typcd(db, il->u[0].n); /* type code */
+ fputs(il->u[1].s, db); fputc(' ', db); /* literal */
+ break;
+ case IL_If1:
+ /*
+ * if-then statment.
+ */
+ fprintf(db, "if1 ");
+ put_inlin(db, il->u[0].fld); /* condition */
+ fprintf(db, "\n");
+ put_inlin(db, il->u[1].fld); /* then clause */
+ break;
+ case IL_If2:
+ /*
+ * if-then-else statment.
+ */
+ fprintf(db, "if2 ");
+ put_inlin(db, il->u[0].fld); /* condition */
+ fprintf(db, "\n");
+ put_inlin(db, il->u[1].fld); /* then clause */
+ fprintf(db, "\n");
+ put_inlin(db, il->u[2].fld); /* else clause */
+ break;
+ case IL_Tcase1:
+ /*
+ * type_case statement with no default clause.
+ */
+ fprintf(db, "tcase1 ");
+ put_case(db, il);
+ break;
+ case IL_Tcase2:
+ /*
+ * type_case statement with a default clause.
+ */
+ fprintf(db, "tcase2 ");
+ indx = put_case(db, il);
+ fprintf(db, "\n");
+ put_inlin(db, il->u[indx].fld); /* default */
+ break;
+ case IL_Lcase:
+ /*
+ * len_case statement.
+ */
+ fprintf(db, "lcase ");
+ num_cases = il->u[0].n;
+ fprintf(db, "%d ", num_cases);
+ indx = 1;
+ for (i = 0; i < num_cases; ++i) {
+ fprintf(db, "\n%d ", il->u[indx++].n); /* selection number */
+ put_inlin(db, il->u[indx++].fld); /* action */
+ }
+ fprintf(db, "\n");
+ put_inlin(db, il->u[indx].fld); /* default */
+ break;
+ case IL_Acase:
+ /*
+ * arith_case statement.
+ */
+ fprintf(db, "acase ");
+ put_inlin(db, il->u[0].fld); /* first variable */
+ put_inlin(db, il->u[1].fld); /* second variable */
+ fprintf(db, "\n");
+ put_inlin(db, il->u[2].fld); /* C_integer action */
+ fprintf(db, "\n");
+ put_inlin(db, il->u[3].fld); /* integer action */
+ fprintf(db, "\n");
+ put_inlin(db, il->u[4].fld); /* C_double action */
+ break;
+ case IL_Err1:
+ /*
+ * runerr with no value argument.
+ */
+ fprintf(db, "runerr1 ");
+ fprintf(db, "%d ", il->u[0].n); /* error number */
+ break;
+ case IL_Err2:
+ /*
+ * runerr with a value argument.
+ */
+ fprintf(db, "runerr2 ");
+ fprintf(db, "%d ", il->u[0].n); /* error number */
+ put_inlin(db, il->u[1].fld); /* variable */
+ break;
+ case IL_Lst:
+ /*
+ * "glue" to string statements together.
+ */
+ fprintf(db, "lst ");
+ put_inlin(db, il->u[0].fld);
+ fprintf(db, "\n");
+ put_inlin(db, il->u[1].fld);
+ break;
+ case IL_Bang:
+ /*
+ * ! operator from type checking.
+ */
+ fprintf(db, "! ");
+ put_inlin(db, il->u[0].fld);
+ break;
+ case IL_And:
+ /*
+ * && operator from type checking.
+ */
+ fprintf(db, "&& ");
+ put_inlin(db, il->u[0].fld);
+ put_inlin(db, il->u[1].fld);
+ break;
+ case IL_Cnv1:
+ /*
+ * cnv:<dest-type>(<source>)
+ */
+ fprintf(db, "cnv1 ");
+ put_typcd(db, il->u[0].n); /* type code */
+ put_inlin(db, il->u[1].fld); /* source */
+ break;
+ case IL_Cnv2:
+ /*
+ * cnv:<dest-type>(<source>,<destination>)
+ */
+ fprintf(db, "cnv2 ");
+ put_typcd(db, il->u[0].n); /* type code */
+ put_inlin(db, il->u[1].fld); /* source */
+ put_ilc(db, il->u[2].c_cd); /* destination */
+ break;
+ case IL_Def1:
+ /*
+ * def:<dest-type>(<source>,<default-value>)
+ */
+ fprintf(db, "def1 ");
+ put_typcd(db, il->u[0].n); /* type code */
+ put_inlin(db, il->u[1].fld); /* source */
+ put_ilc(db, il->u[2].c_cd); /* default value */
+ break;
+ case IL_Def2:
+ /*
+ * def:<dest-type>(<source>,<default-value>,<destination>)
+ */
+ fprintf(db, "def2 ");
+ put_typcd(db, il->u[0].n); /* type code */
+ put_inlin(db, il->u[1].fld); /* source */
+ put_ilc(db, il->u[2].c_cd); /* default value */
+ put_ilc(db, il->u[3].c_cd); /* destination */
+ break;
+ case IL_Is:
+ /*
+ * is:<type-name>(<variable>)
+ */
+ fprintf(db, "is ");
+ put_typcd(db, il->u[0].n); /* type code */
+ put_inlin(db, il->u[1].fld); /* variable */
+ break;
+ case IL_Var:
+ /*
+ * A variable.
+ */
+ fprintf(db, "%d ", il->u[0].n); /* symbol table index */
+ break;
+ case IL_Subscr:
+ /*
+ * A subscripted variable.
+ */
+ fprintf(db, "[ ");
+ fprintf(db, "%d ", il->u[0].n); /* symbol table index */
+ fprintf(db, "%d ", il->u[1].n); /* subscripting index */
+ break;
+ case IL_Block:
+ /*
+ * A block of in-line code.
+ */
+ fprintf(db, "block ");
+ if (il->u[0].n)
+ fprintf(db, "t "); /* execution can fall through */
+ else
+ fprintf(db, "_ "); /* execution cannot fall through */
+ /*
+ * Output a symbol table of tended variables.
+ */
+ fprintf(db, "%d ", il->u[1].n); /* number of local tended */
+ for (i = 2; i - 2 < il->u[1].n; ++i)
+ switch (il->u[i].n) {
+ case TndDesc:
+ fprintf(db, "desc ");
+ break;
+ case TndStr:
+ fprintf(db, "str ");
+ break;
+ case TndBlk:
+ fprintf(db, "blkptr ");
+ break;
+ }
+ put_ilc(db, il->u[i].c_cd); /* body of block */
+ break;
+ case IL_Call:
+ /*
+ * A call to a body function.
+ */
+ fprintf(db, "call ");
+
+ /*
+ * Each body function has a 3rd prefix character to distingish
+ * it from other functions for the operation.
+ */
+ fprintf(db, "%c ", (char)il->u[1].n);
+
+ /*
+ * A body function that would only return one possible signal
+ * need return none. In which case, it can directly return a
+ * C integer or double directly rather than using a result
+ * descriptor location. Indicate what it does.
+ */
+ switch (il->u[2].n) {
+ case RetInt:
+ fprintf(db, "i "); /* directly return integer */
+ break;
+ case RetDbl:
+ fprintf(db, "d "); /* directly return double */
+ break;
+ case RetNoVal:
+ fprintf(db, "n "); /* return nothing directly */
+ break;
+ case RetSig:
+ fprintf(db, "s "); /* return a signal */
+ break;
+ }
+
+ /*
+ * Output the return/suspend/fail/fall-through flag.
+ */
+ ret_flag(db, il->u[3].n, 1);
+
+ /*
+ * Indicate whether the body function expects to have
+ * an explicit result location passed to it.
+ */
+ if (il->u[4].n)
+ fprintf(db, "t ");
+ else
+ fprintf(db, "f ");
+
+ fprintf(db, "%d ", il->u[5].n); /* num string bufs */
+ fprintf(db, "%d ", il->u[6].n); /* num cset bufs */
+ i = il->u[7].n;
+ fprintf(db, "%d ", i); /* num args */
+ indx = 8;
+ /*
+ * output prototype paramater declarations and actual arguments.
+ */
+ i *= 2;
+ while (i--)
+ put_ilc(db, il->u[indx++].c_cd);
+ break;
+ case IL_Abstr:
+ /*
+ * Abstract type computation.
+ */
+ fprintf(db, "abstr ");
+ put_inlin(db, il->u[0].fld); /* side effects */
+ put_inlin(db, il->u[1].fld); /* return type */
+ break;
+ case IL_VarTyp:
+ /*
+ * type(<parameter>)
+ */
+ fprintf(db, "vartyp ");
+ put_inlin(db, il->u[0].fld); /* variable */
+ break;
+ case IL_Store:
+ /*
+ * store[<type>]
+ */
+ fprintf(db, "store ");
+ put_inlin(db, il->u[0].fld); /* type to be "dereferenced "*/
+ break;
+ case IL_Compnt:
+ /*
+ * <type>.<component>
+ */
+ fprintf(db, ". ");
+ put_inlin(db, il->u[0].fld); /* type */
+ if (il->u[1].n == CM_Fields)
+ fprintf(db, "f "); /* special case record fields */
+ else
+ fprintf(db, "C%d ", (int)il->u[1].n); /* component table index */
+ break;
+ case IL_TpAsgn:
+ /*
+ * store[<variable-type>] = <value-type>
+ */
+ fprintf(db, "= ");
+ put_inlin(db, il->u[0].fld); /* variable type */
+ put_inlin(db, il->u[1].fld); /* value type */
+ break;
+ case IL_Union:
+ /*
+ * <type 1> ++ <type 2>
+ */
+ fprintf(db, "++ ");
+ put_inlin(db, il->u[0].fld);
+ put_inlin(db, il->u[1].fld);
+ break;
+ case IL_Inter:
+ /*
+ * <type 1> ** <type 2>
+ */
+ fprintf(db, "** ");
+ put_inlin(db, il->u[0].fld);
+ put_inlin(db, il->u[1].fld);
+ break;
+ case IL_New:
+ /*
+ * new <type-name>(<type 1> , ...)
+ */
+ fprintf(db, "new ");
+ put_typcd(db, il->u[0].n); /* type code */
+ i = il->u[1].n;
+ fprintf(db, "%d ", i); /* num args */
+ indx = 2;
+ while (i--)
+ put_inlin(db, il->u[indx++].fld);
+ break;
+ case IL_IcnTyp:
+ /*
+ * <type-name>
+ */
+ fprintf(db, "typ ");
+ put_typcd(db, il->u[0].n); /* type code */
+ break;
+ }
+ }
+
+/*
+ * put_case - put the cases of a type_case statement into the data base file.
+ */
+static int put_case(db, il)
+FILE *db;
+struct il_code *il;
+ {
+ int *typ_vect;
+ int i, j;
+ int num_cases;
+ int num_types;
+ int indx;
+
+ put_inlin(db, il->u[0].fld); /* expression being checked */
+ num_cases = il->u[1].n; /* number of cases */
+ fprintf(db, "%d ", num_cases);
+ indx = 2;
+ for (i = 0; i < num_cases; ++i) {
+ num_types = il->u[indx++].n; /* number of types in case */
+ fprintf(db, "\n%d ", num_types);
+ typ_vect = il->u[indx++].vect; /* vector of type codes */
+ for (j = 0; j < num_types; ++j)
+ put_typcd(db, typ_vect[j]); /* type code */
+ put_inlin(db, il->u[indx++].fld); /* action */
+ }
+ return indx;
+ }
+
+/*
+ * put_typcd - convert a numeric type code into an alpha type code and
+ * put it in the data base file.
+ */
+static void put_typcd(db, typcd)
+FILE *db;
+int typcd;
+ {
+ if (typcd >= 0)
+ fprintf(db, "T%d ", typcd);
+ else {
+ switch (typcd) {
+ case TypAny:
+ fprintf(db, "a "); /* any_value */
+ break;
+ case TypEmpty:
+ fprintf(db, "e "); /* empty_type */
+ break;
+ case TypVar:
+ fprintf(db, "v "); /* variable */
+ break;
+ case TypCInt:
+ fprintf(db, "ci "); /* C_integer */
+ break;
+ case TypCDbl:
+ fprintf(db, "cd "); /* C_double */
+ break;
+ case TypCStr:
+ fprintf(db, "cs "); /* C_string */
+ break;
+ case TypEInt:
+ fprintf(db, "ei "); /* (exact)integer) */
+ break;
+ case TypECInt:
+ fprintf(db, "eci "); /* (exact)C_integer */
+ break;
+ case TypTStr:
+ fprintf(db, "ts "); /* tmp_string */
+ break;
+ case TypTCset:
+ fprintf(db, "tc "); /* tmp_cset */
+ break;
+ case RetDesc:
+ fprintf(db, "d "); /* plain descriptor on return/suspend */
+ break;
+ case RetNVar:
+ fprintf(db, "nv "); /* named_var */
+ break;
+ case RetSVar:
+ fprintf(db, "sv "); /* struct_var */
+ break;
+ case RetNone:
+ fprintf(db, "rn "); /* preset result location on return/suspend */
+ break;
+ }
+ }
+ }
+
+/*
+ * put_ilc - put in-line C code in the data base file.
+ */
+static void put_ilc(db, ilc)
+FILE *db;
+struct il_c *ilc;
+ {
+ /*
+ * In-line C code is either "nil" or code bracketed by $c $e.
+ * The bracketed code consists of text for C code plus special
+ * constructs starting with $. Control structures have been
+ * translated into gotos in the form of special constructs
+ * (note that case statements are not supported in in-line code).
+ */
+ if (ilc == NULL) {
+ fprintf(db, "nil ");
+ return;
+ }
+ fprintf(db, "$c ");
+ while (ilc != NULL) {
+ switch(ilc->il_c_type) {
+ case ILC_Ref:
+ put_var(db, 'r', ilc); /* non-modifying reference to variable */
+ break;
+ case ILC_Mod:
+ put_var(db, 'm', ilc); /* modifying reference to variable */
+ break;
+ case ILC_Tend:
+ put_var(db, 't', ilc); /* variable declared tended */
+ break;
+ case ILC_SBuf:
+ fprintf(db, "$sb "); /* string buffer for tmp_string */
+ break;
+ case ILC_CBuf:
+ fprintf(db, "$cb "); /* cset buffer for tmp_cset */
+ break;
+ case ILC_Ret:
+ fprintf(db, "$ret "); /* return statement */
+ put_ret(db, ilc);
+ break;
+ case ILC_Susp:
+ fprintf(db, "$susp "); /* suspend statement */
+ put_ret(db, ilc);
+ break;
+ case ILC_Fail:
+ fprintf(db, "$fail "); /* fail statement */
+ break;
+ case ILC_EFail:
+ fprintf(db, "$efail "); /* errorfail statement */
+ break;
+ case ILC_Goto:
+ fprintf(db, "$goto %d ", ilc->n); /* goto label */
+ break;
+ case ILC_CGto:
+ fprintf(db, "$cgoto "); /* conditional goto */
+ put_ilc(db, ilc->code[0]); /* condition (with $c $e) */
+ fprintf(db, "%d ", ilc->n); /* label */
+ break;
+ case ILC_Lbl:
+ fprintf(db, "$lbl %d ", ilc->n); /* label */
+ break;
+ case ILC_LBrc:
+ fprintf(db, "${ "); /* start of C block with dcls */
+ break;
+ case ILC_RBrc:
+ fprintf(db, "$} "); /* end of C block with dcls */
+ break;
+ case ILC_Str:
+ fprintf(db, "%s", ilc->s); /* C code as plain text */
+ break;
+ }
+ ilc = ilc->next;
+ }
+ fprintf(db, " $e ");
+ }
+
+/*
+ * put_var - output in-line C code for a variable.
+ */
+static void put_var(db, code, ilc)
+FILE *db;
+int code;
+struct il_c *ilc;
+ {
+ fprintf(db, "$%c", code); /* 'r': non-mod ref, 'm': mod ref, 't': tended */
+ if (ilc->s != NULL)
+ fprintf(db, "%s", ilc->s); /* access into descriptor */
+ if (ilc->n == RsltIndx)
+ fprintf(db, "r "); /* this is "result" */
+ else
+ fprintf(db, "%d ", ilc->n); /* offset into a symbol table */
+ }
+
+/*
+ * ret_flag - put a return/suspend/fail/fall-through flag in the data base
+ * file.
+ */
+static void ret_flag(db, flag, may_fthru)
+FILE *db;
+int flag;
+int may_fthru;
+ {
+ if (flag & DoesFail)
+ fprintf(db, "f"); /* can fail */
+ else
+ fprintf(db, "_"); /* cannot fail */
+ if (flag & DoesRet)
+ fprintf(db, "r"); /* can return */
+ else
+ fprintf(db, "_"); /* cannot return */
+ if (flag & DoesSusp)
+ fprintf(db, "s"); /* can suspend */
+ else
+ fprintf(db, "_"); /* cannot suspend */
+ if (flag & DoesEFail)
+ fprintf(db, "e"); /* can do error conversion */
+ else
+ fprintf(db, "_"); /* cannot do error conversion */
+ if (may_fthru) /* body functions only: */
+ if (flag & DoesFThru)
+ fprintf(db, "t"); /* can fall through */
+ else
+ fprintf(db, "_"); /* cannot fall through */
+ fprintf(db, " ");
+ }
+
+/*
+ * put_ret - put the body of a return/suspend statement in the data base.
+ */
+static void put_ret(db, ilc)
+FILE *db;
+struct il_c *ilc;
+ {
+ int i;
+
+ /*
+ * Output the type of descriptor constructor on the return/suspend,
+ * then output the the number of arguments to the constructor, and
+ * the arguments themselves.
+ */
+ put_typcd(db, ilc->n);
+ for (i = 0; i < 3 && ilc->code[i] != NULL; ++i)
+ ;
+ fprintf(db, "%d ", i);
+ for (i = 0; i < 3 && ilc->code[i] != NULL; ++i)
+ put_ilc(db, ilc->code[i]);
+ }
+
+/*
+ * name_cmp - compare implementation structs by name; function used as
+ * an argument to qsort().
+ */
+static int name_cmp(p1, p2)
+char *p1;
+char *p2;
+ {
+ register struct implement *ip1;
+ register struct implement *ip2;
+
+ ip1 = *(struct implement **)p1;
+ ip2 = *(struct implement **)p2;
+ return strcmp(ip1->name, ip2->name);
+ }
+
+/*
+ * op_cmp - compare implementation structs by operator and number of args;
+ * function used as an argument to qsort().
+ */
+static int op_cmp(p1, p2)
+char *p1;
+char *p2;
+ {
+ register int cmp;
+ register struct implement *ip1;
+ register struct implement *ip2;
+
+ ip1 = *(struct implement **)p1;
+ ip2 = *(struct implement **)p2;
+
+ cmp = strcmp(ip1->op, ip2->op);
+ if (cmp == 0)
+ return ip1->nargs - ip2->nargs;
+ else
+ return cmp;
+ }
+
+/*
+ * prt_dpnd - print dependency information to the data base.
+ */
+static void prt_dpnd(db)
+FILE *db;
+ {
+ struct srcfile **sort_ary;
+ struct srcfile *sfile;
+ unsigned hashval;
+ int line_left;
+ int num;
+ int i;
+
+ fprintf(db, "\ndependencies\n\n"); /* start of dependency section */
+
+ /*
+ * sort the dependency information by source file name.
+ */
+ num = 0;
+ if (num_src > 0) {
+ sort_ary = alloc(num_src * sizeof(struct srcfile *));
+ for (hashval = 0; hashval < DHSize; ++hashval)
+ for (sfile = dhash[hashval]; sfile != NULL; sfile = sfile->next)
+ sort_ary[num++] = sfile;
+ qsort((char *)sort_ary, num, sizeof(struct srcfile *),
+ (int (*)())src_cmp);
+ }
+
+ /*
+ * For each source file with dependents, output the source file
+ * name followed by the list of dependent files. The list is
+ * terminated with "end".
+ */
+ for (i = 0; i < num; ++i) {
+ sfile = sort_ary[i];
+ if (sfile->dependents != NULL) {
+ fprintf(db, "%-12s ", sfile->name);
+ line_left = prt_c_fl(db, sfile->dependents, MaxLine - 14);
+ if (line_left - 4 < 0)
+ fprintf(db, "\n ");
+ fprintf(db, "$end\n");
+ }
+ }
+ fprintf(db, "\n$endsect\n"); /* end of dependency section */
+ if (num_src > 0)
+ free((char *)sort_ary);
+ }
+
+/*
+ * src_cmp - compare srcfile structs; function used as an argument to qsort().
+ */
+static int src_cmp(p1, p2)
+char *p1;
+char *p2;
+ {
+ register struct srcfile *sp1;
+ register struct srcfile *sp2;
+
+ sp1 = *(struct srcfile **)p1;
+ sp2 = *(struct srcfile **)p2;
+ return strcmp(sp1->name, sp2->name);
+ }
+
+/*
+ * prt_c_fl - print list of C files in reverse order.
+ */
+static int prt_c_fl(db, clst, line_left)
+FILE *db;
+struct cfile *clst;
+int line_left;
+ {
+ int len;
+
+ if (clst == NULL)
+ return line_left;
+ line_left = prt_c_fl(db, clst->next, line_left);
+
+ /*
+ * If this will exceed the line length, print a new-line and some
+ * leading white space.
+ */
+ len = strlen(clst->name) + 1;
+ if (line_left - len < 0) {
+ fprintf(db, "\n ");
+ line_left = MaxLine - 14;
+ }
+ fprintf(db, "%s ", clst->name);
+ return line_left - len;
+ }
+#endif /* Rttx */
+
+/*
+ * full_lst - print a full list of all files produced by translations
+ * as represented in the dependencies section of the data base.
+ */
+void full_lst(fname)
+char *fname;
+ {
+ unsigned hashval;
+ struct srcfile *sfile;
+ struct cfile *clst;
+ struct fileparts *fp;
+ FILE *f;
+
+ f = fopen(fname, "w");
+ if (f == NULL)
+ err2("cannot open ", fname);
+ for (hashval = 0; hashval < DHSize; ++hashval)
+ for (sfile = dhash[hashval]; sfile != NULL; sfile = sfile->next)
+ for (clst = sfile->dependents; clst != NULL; clst = clst->next) {
+ /*
+ * Remove the suffix from the name before printing.
+ */
+ fp = fparse(clst->name);
+ fprintf(f, "%s\n", fp->name);
+ }
+ if (fclose(f) != 0)
+ err2("cannot close ", fname);
+ }
+
+/*
+ * impl_fnc - find or create implementation struct for function currently
+ * being parsed.
+ */
+void impl_fnc(name)
+struct token *name;
+ {
+ /*
+ * Set the global operation type for later use. If this is a
+ * new function update the number of them.
+ */
+ op_type = TokFunction;
+ num_fnc = set_impl(name, bhash, num_fnc, fnc_pre);
+ }
+
+/*
+ * impl_key - find or create implementation struct for keyword currently
+ * being parsed.
+ */
+void impl_key(name)
+struct token *name;
+ {
+ /*
+ * Set the global operation type for later use. If this is a
+ * new keyword update the number of them.
+ */
+ op_type = Keyword;
+ num_key = set_impl(name, khash, num_key, key_pre);
+ }
+
+/*
+ * set_impl - lookup a function or keyword in a hash table and update the
+ * entry, creating the entry if needed.
+ */
+static int set_impl(name, tbl, num_impl, pre)
+struct token *name;
+struct implement **tbl;
+int num_impl;
+char *pre;
+ {
+ register struct implement *ptr;
+ char *name_s;
+ unsigned hashval;
+
+ /*
+ * we only need the operation name and not the entire token.
+ */
+ name_s = name->image;
+ free_t(name);
+
+ /*
+ * If the operation is not in the hash table, put it there.
+ */
+ if ((ptr = db_ilkup(name_s, tbl)) == NULL) {
+ ptr = NewStruct(implement);
+ hashval = IHasher(name_s);
+ ptr->blink = tbl[hashval];
+ ptr->oper_typ = ((op_type == TokFunction) ? 'F' : 'K');
+ nxt_pre(ptr->prefix, pre, 2); /* allocate a unique prefix */
+ ptr->name = name_s;
+ ptr->op = NULL;
+ tbl[hashval] = ptr;
+ ++num_impl;
+ }
+
+ cur_impl = ptr; /* put entry in global variable for later access */
+
+ /*
+ * initialize the entry based on global information set during parsing.
+ */
+ set_prms(ptr);
+ ptr->min_result = min_rs;
+ ptr->max_result = max_rs;
+ ptr->resume = rsm_rs;
+ ptr->ret_flag = 0;
+ if (comment == NULL)
+ ptr->comment = "";
+ else {
+ ptr->comment = comment->image;
+ free_t(comment);
+ comment = NULL;
+ }
+ ptr->ntnds = 0;
+ ptr->tnds = NULL;
+ ptr->nvars = 0;
+ ptr->vars = NULL;
+ ptr->in_line = NULL;
+ ptr->iconc_flgs = 0;
+ return num_impl;
+ }
+
+/*
+ * set_prms - set the parameter information of an implementation based on
+ * the params list constructed during parsing.
+ */
+static void set_prms(ptr)
+struct implement *ptr;
+ {
+ struct sym_entry *sym;
+ int nargs;
+ int i;
+
+ /*
+ * Create an array of parameter flags for the operation. The flag
+ * indicates the deref/underef and varargs status for each parameter.
+ */
+ if (params == NULL) {
+ ptr->nargs = 0;
+ ptr->arg_flgs = NULL;
+ }
+ else {
+ /*
+ * The parameters are in reverse order, so the number of the parameters
+ * can be determined by the number assigned to the first one on the
+ * list.
+ */
+ nargs = params->u.param_info.param_num + 1;
+ ptr->nargs = nargs;
+ ptr->arg_flgs = alloc(nargs * sizeof(int));
+ for (i = 0; i < nargs; ++i)
+ ptr->arg_flgs[i] = 0;
+ for (sym = params; sym != NULL; sym = sym->u.param_info.next)
+ ptr->arg_flgs[sym->u.param_info.param_num] |= sym->id_type;
+ }
+ }
+
+/*
+ * impl_op - find or create implementation struct for operator currently
+ * being parsed.
+ */
+void impl_op(op_sym, name)
+struct token *op_sym;
+struct token *name;
+ {
+ register struct implement *ptr;
+ char *op;
+ int nargs;
+ unsigned hashval;
+
+ /*
+ * The operator symbol is needed but not the entire token.
+ */
+ op = op_sym->image;
+ free_t(op_sym);
+
+ /*
+ * The parameters are in reverse order, so the number of the parameters
+ * can be determined by the number assigned to the first one on the
+ * list.
+ */
+ if (params == NULL)
+ nargs = 0;
+ else
+ nargs = params->u.param_info.param_num + 1;
+
+ /*
+ * Locate the operator in the hash table; it must match both the
+ * operator symbol and the number of arguments. If the operator is
+ * not there, create an entry.
+ */
+ hashval = IHasher(op);
+ ptr = ohash[hashval];
+ while (ptr != NULL && (ptr->op != op || ptr->nargs != nargs))
+ ptr = ptr->blink;
+ if (ptr == NULL) {
+ ptr = NewStruct(implement);
+ ptr->blink = ohash[hashval];
+ ptr->oper_typ = 'O';
+ nxt_pre(ptr->prefix, op_pre, 2); /* allocate a unique prefix */
+ ptr->op = op;
+ ohash[hashval] = ptr;
+ ++num_op;
+ }
+
+ /*
+ * Put the entry and operation type in global variables for
+ * later access.
+ */
+ cur_impl = ptr;
+ op_type = Operator;
+
+ /*
+ * initialize the entry based on global information set during parsing.
+ */
+ ptr->name = name->image;
+ free_t(name);
+ set_prms(ptr);
+ ptr->min_result = min_rs;
+ ptr->max_result = max_rs;
+ ptr->resume = rsm_rs;
+ ptr->ret_flag = 0;
+ if (comment == NULL)
+ ptr->comment = "";
+ else {
+ ptr->comment = comment->image;
+ free_t(comment);
+ comment = NULL;
+ }
+ ptr->ntnds = 0;
+ ptr->tnds = NULL;
+ ptr->nvars = 0;
+ ptr->vars = NULL;
+ ptr->in_line = NULL;
+ ptr->iconc_flgs = 0;
+ }
+
+/*
+ * set_r_seq - save result sequence information for updating the
+ * operation entry.
+ */
+void set_r_seq(min, max, resume)
+long min;
+long max;
+int resume;
+ {
+ if (min == UnbndSeq)
+ min = 0;
+ min_rs = min;
+ max_rs = max;
+ rsm_rs = resume;
+ }
+
diff --git a/src/rtt/rttgram.y b/src/rtt/rttgram.y
new file mode 100644
index 0000000..bf47752
--- /dev/null
+++ b/src/rtt/rttgram.y
@@ -0,0 +1,1101 @@
+/*
+ * Grammar for RTL. The C portion of the grammar is based on
+ * the ANSI Draft Standard - 3rd review.
+ */
+
+%{
+#include "rtt1.h"
+#define YYMAXDEPTH 250
+%}
+
+%union {
+ struct token *t;
+ struct node *n;
+ long i;
+ }
+
+%token <t> Identifier StrLit LStrLit FltConst DblConst LDblConst
+%token <t> CharConst LCharConst IntConst UIntConst LIntConst ULIntConst
+%token <t> Arrow Incr Decr LShft RShft Leq Geq Equal Neq
+%token <t> And Or MultAsgn DivAsgn ModAsgn PlusAsgn
+%token <t> MinusAsgn LShftAsgn RShftAsgn AndAsgn
+%token <t> XorAsgn OrAsgn Sizeof Intersect OpSym
+
+%token <t> Typedef Extern Static Auto Register Tended
+%token <t> Char Short Int Long Signed Unsigned Float Doubl Const Volatile
+%token <t> Void TypeDefName Struct Union Enum Ellipsis
+
+%token <t> Case Default If Else Switch While Do For Goto Continue Break Return
+
+%token <t> '%' '&' '(' ')' '*' '+' ',' '-' '.' '/' '{' '|' '}' '~' '[' ']'
+%token <t> '^' ':' ';' '<' '=' '>' '?' '!' '@' '\\'
+
+%token <t> Runerr Is Cnv Def Exact Empty_type IconType Component Variable
+%token <t> Any_value Named_var Struct_var C_Integer Arith_case
+%token <t> C_Double C_String Tmp_string Tmp_cset Body End Function Keyword
+%token <t> Operator Underef Declare Suspend Fail Inline Abstract Store
+%token <t> Type New All_fields Then Type_case Of Len_case Constant Errorfail
+
+%type <t> unary_op assign_op struct_or_union typedefname
+%type <t> identifier op_name key_const union attrb_name
+
+%type <n> any_ident storage_class_spec type_qual
+%type <n> primary_expr postfix_expr arg_expr_lst unary_expr cast_expr
+%type <n> multiplicative_expr additive_expr shift_expr relational_expr
+%type <n> equality_expr and_expr exclusive_or_expr inclusive_or_expr
+%type <n> logical_and_expr logical_or_expr conditional_expr assign_expr
+%type <n> expr opt_expr constant_expr opt_constant_expr dcltion
+%type <n> typ_dcltion_specs dcltion_specs type_ind type_storcl_tqual_lst
+%type <n> storcl_tqual_lst init_dcltor_lst no_tdn_init_dcltor_lst init_dcltor
+%type <n> no_tdn_init_dcltor type_spec stnd_type struct_or_union_spec
+%type <n> struct_dcltion_lst struct_dcltion struct_dcltion_specs struct_type_ind
+%type <n> struct_type_lst struct_dcltor_lst struct_dcltor
+%type <n> struct_no_tdn_dcltor_lst struct_no_tdn_dcltor enum_spec enumerator_lst
+%type <n> enumerator dcltor no_tdn_dcltor direct_dcltor no_tdn_direct_dcltor
+%type <n> pointer opt_pointer tqual_lst param_type_lst opt_param_type_lst
+%type <n> param_lst param_dcltion ident_lst type_tqual_lst type_name
+%type <n> abstract_dcltor direct_abstract_dcltor initializer initializer_lst
+%type <n> stmt labeled_stmt compound_stmt dcltion_lst opt_dcltion_lst stmt_lst
+%type <n> expr_stmt selection_stmt iteration_stmt jump_stmt parm_dcls_or_ids
+%type <n> func_head opt_stmt_lst local_dcls local_dcl
+%type <n> dest_type i_type_name opt_actions actions action ret_val detail_code
+%type <n> runerr variable checking_conversions label
+%type <n> type_check type_select_lst opt_default type_select selector_lst
+%type <n> c_opt_default c_type_select c_type_select_lst non_lbl_stmt
+%type <n> simple_check_conj simple_check len_select_lst len_select
+%type <n> type_computations side_effect_lst side_effect
+%type <n> type basic_type type_lst
+
+%type <i> opt_plus length
+
+/* Get rid of shift/reduce conflict on Else. Use precedence to force shift of
+ Else rather than reduction of if-cond-expr. This insures that the Else
+ is always paired with innermost If. Note, IfStmt is a dummy token. */
+%nonassoc IfStmt
+%nonassoc Else
+
+%start translation_unit
+%%
+
+primary_expr
+ : identifier {$$ = sym_node($1);}
+ | StrLit {$$ = node0(PrimryNd, $1);}
+ | LStrLit {$$ = node0(PrimryNd, $1);}
+ | FltConst {$$ = node0(PrimryNd, $1);}
+ | DblConst {$$ = node0(PrimryNd, $1);}
+ | LDblConst {$$ = node0(PrimryNd, $1);}
+ | CharConst {$$ = node0(PrimryNd, $1);}
+ | LCharConst {$$ = node0(PrimryNd, $1);}
+ | IntConst {$$ = node0(PrimryNd, $1);}
+ | UIntConst {$$ = node0(PrimryNd, $1);}
+ | LIntConst {$$ = node0(PrimryNd, $1);}
+ | ULIntConst {$$ = node0(PrimryNd, $1);}
+ | '(' expr ')' {$$ = node1(PrefxNd, $1, $2); free_t($3);}
+ ;
+
+postfix_expr
+ : primary_expr
+ | postfix_expr '[' expr ']' {$$ = node2(BinryNd, $2, $1, $3);
+ free_t($4);}
+ | postfix_expr '(' ')' {$$ = node2(BinryNd, $3, $1, NULL);
+ free_t($2);}
+ | postfix_expr '(' arg_expr_lst ')' {$$ = node2(BinryNd, $4, $1, $3);
+ free_t($2);}
+ | postfix_expr '.' any_ident {$$ = node2(BinryNd, $2, $1, $3);}
+ | postfix_expr Arrow any_ident {$$ = node2(BinryNd, $2, $1, $3);}
+ | postfix_expr Incr {$$ = node1(PstfxNd, $2, $1);}
+ | postfix_expr Decr {$$ = node1(PstfxNd, $2, $1);}
+ | Is ':' i_type_name '(' assign_expr ')'
+ {$$ = node2(BinryNd, $1, $3, $5); free_t($2); free_t($4); free_t($6);}
+ | Cnv ':' dest_type '(' assign_expr ',' assign_expr ')'
+ {$$ = node3(TrnryNd, $1, $3, $5, $7), free_t($2); free_t($4); free_t($6);
+ free_t($8);}
+ | Def ':' dest_type '(' assign_expr ',' assign_expr ',' assign_expr ')'
+ {$$ = node4(QuadNd, $1, $3, $5, $7, $9), free_t($2); free_t($4);
+ free_t($6); free_t($8); free_t($10);}
+ ;
+
+arg_expr_lst
+ : assign_expr
+ | arg_expr_lst ',' assign_expr {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+unary_expr
+ : postfix_expr
+ | Incr unary_expr {$$ = node1(PrefxNd, $1, $2);}
+ | Decr unary_expr {$$ = node1(PrefxNd, $1, $2);}
+ | unary_op cast_expr {$$ = node1(PrefxNd, $1, $2);}
+ | Sizeof unary_expr {$$ = node1(PrefxNd, $1, $2);}
+ | Sizeof '(' type_name ')' {$$ = node1(PrefxNd, $1, $3);
+ free_t($2); free_t($4);}
+ ;
+
+unary_op
+ : '&'
+ | '*'
+ | '+'
+ | '-'
+ | '~'
+ | '!'
+ ;
+
+cast_expr
+ : unary_expr
+ | '(' type_name ')' cast_expr {$$ = node2(BinryNd, $1, $2, $4); free_t($3);}
+ ;
+
+multiplicative_expr
+ : cast_expr
+ | multiplicative_expr '*' cast_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ | multiplicative_expr '/' cast_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ | multiplicative_expr '%' cast_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+additive_expr
+ : multiplicative_expr
+ | additive_expr '+' multiplicative_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ | additive_expr '-' multiplicative_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+shift_expr
+ : additive_expr
+ | shift_expr LShft additive_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ | shift_expr RShft additive_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+relational_expr
+ : shift_expr
+ | relational_expr '<' shift_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ | relational_expr '>' shift_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ | relational_expr Leq shift_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ | relational_expr Geq shift_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+equality_expr
+ : relational_expr
+ | equality_expr Equal relational_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ | equality_expr Neq relational_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+and_expr
+ : equality_expr
+ | and_expr '&' equality_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+exclusive_or_expr
+ : and_expr
+ | exclusive_or_expr '^' and_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+inclusive_or_expr
+ : exclusive_or_expr
+ | inclusive_or_expr '|' exclusive_or_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+logical_and_expr
+ : inclusive_or_expr
+ | logical_and_expr And inclusive_or_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+logical_or_expr
+ : logical_and_expr
+ | logical_or_expr Or logical_and_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+conditional_expr
+ : logical_or_expr
+ | logical_or_expr '?' expr ':' conditional_expr
+ {$$ = node3(TrnryNd, $2, $1, $3, $5);
+ free_t($4);}
+ ;
+
+assign_expr
+ : conditional_expr
+ | unary_expr assign_op assign_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+assign_op
+ : '='
+ | MultAsgn
+ | DivAsgn
+ | ModAsgn
+ | PlusAsgn
+ | MinusAsgn
+ | LShftAsgn
+ | RShftAsgn
+ | AndAsgn
+ | XorAsgn
+ | OrAsgn
+ ;
+
+expr
+ : assign_expr
+ | expr ',' assign_expr {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+opt_expr
+ : {$$ = NULL;}
+ | expr
+ ;
+
+constant_expr
+ : conditional_expr
+ ;
+
+opt_constant_expr
+ : {$$ = NULL;}
+ | constant_expr
+ ;
+
+dcltion
+ : typ_dcltion_specs ';' {$$ = node2(BinryNd, $2, $1, NULL);
+ dcl_stk->kind_dcl = OtherDcl;}
+ | typ_dcltion_specs init_dcltor_lst ';' {$$ = node2(BinryNd, $3, $1, $2);
+ dcl_stk->kind_dcl = OtherDcl;}
+ | storcl_tqual_lst no_tdn_init_dcltor_lst ';'
+ {$$ = node2(BinryNd, $3, $1, $2);
+ dcl_stk->kind_dcl = OtherDcl;}
+ ;
+
+typ_dcltion_specs
+ : type_ind
+ | storcl_tqual_lst type_ind {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+dcltion_specs
+ : typ_dcltion_specs
+ | storcl_tqual_lst
+ ;
+
+type_ind
+ : typedefname {$$ = node0(PrimryNd, $1);}
+ | typedefname storcl_tqual_lst
+ {$$ = node2(LstNd, NULL, node0(PrimryNd, $1), $2);}
+ | type_storcl_tqual_lst
+ ;
+
+type_storcl_tqual_lst
+ : stnd_type
+ | type_storcl_tqual_lst stnd_type {$$ = node2(LstNd, NULL, $1, $2);}
+ | type_storcl_tqual_lst storage_class_spec {$$ = node2(LstNd, NULL, $1, $2);}
+ | type_storcl_tqual_lst type_qual {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+storcl_tqual_lst
+ : storage_class_spec
+ | type_qual
+ | storcl_tqual_lst storage_class_spec {$$ = node2(LstNd, NULL, $1, $2);}
+ | storcl_tqual_lst type_qual {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+init_dcltor_lst
+ : init_dcltor
+ | init_dcltor_lst ',' init_dcltor {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+no_tdn_init_dcltor_lst
+ : no_tdn_init_dcltor
+ | no_tdn_init_dcltor_lst ',' no_tdn_init_dcltor
+ {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+init_dcltor
+ : dcltor {$$ = $1; id_def($1, NULL);}
+ | dcltor '=' initializer {$$ = node2(BinryNd, $2, $1, $3); id_def($1, $3);}
+ ;
+
+no_tdn_init_dcltor
+ : no_tdn_dcltor {$$ = $1; id_def($1, NULL);}
+ | no_tdn_dcltor '=' initializer
+ {$$ = node2(BinryNd, $2, $1, $3); id_def($1, $3);}
+ ;
+
+storage_class_spec
+ : Typedef {$$ = node0(PrimryNd, $1); dcl_stk->kind_dcl = IsTypedef;}
+ | Extern {$$ = node0(PrimryNd, $1);}
+ | Static {$$ = node0(PrimryNd, $1);}
+ | Auto {$$ = node0(PrimryNd, $1);}
+ | Register {$$ = node0(PrimryNd, $1);}
+ ;
+
+type_spec
+ : stnd_type
+ | typedefname {$$ = node0(PrimryNd, $1);}
+ ;
+
+stnd_type
+ : Void {$$ = node0(PrimryNd, $1);}
+ | Char {$$ = node0(PrimryNd, $1);}
+ | Short {$$ = node0(PrimryNd, $1);}
+ | Int {$$ = node0(PrimryNd, $1);}
+ | Long {$$ = node0(PrimryNd, $1);}
+ | Float {$$ = node0(PrimryNd, $1);}
+ | Doubl {$$ = node0(PrimryNd, $1);}
+ | Signed {$$ = node0(PrimryNd, $1);}
+ | Unsigned {$$ = node0(PrimryNd, $1);}
+ | struct_or_union_spec
+ | enum_spec
+ ;
+
+struct_or_union_spec
+ : struct_or_union any_ident '{' struct_dcltion_lst '}'
+ {$$ = node2(BinryNd, $1, $2, $4);
+ free_t($3); free_t($5);}
+ | struct_or_union '{' struct_dcltion_lst '}'
+ {$$ = node2(BinryNd, $1, NULL, $3);
+ free_t($2); free_t($4);}
+ | struct_or_union any_ident {$$ = node2(BinryNd, $1, $2, NULL);}
+ ;
+
+struct_or_union
+ : Struct
+ | Union
+ ;
+
+struct_dcltion_lst
+ : struct_dcltion
+ | struct_dcltion_lst struct_dcltion {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+struct_dcltion
+ : struct_dcltion_specs struct_dcltor_lst ';'
+ {$$ = node2(BinryNd, $3, $1, $2);}
+ | tqual_lst struct_no_tdn_dcltor_lst ';' {$$ = node2(BinryNd, $3, $1, $2);}
+ ;
+
+struct_dcltion_specs
+ : struct_type_ind
+ | tqual_lst struct_type_ind {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+struct_type_ind
+ : typedefname {$$ = node0(PrimryNd, $1);}
+ | typedefname tqual_lst {$$ = node2(LstNd, NULL, node0(PrimryNd, $1), $2);}
+ | struct_type_lst
+ ;
+
+struct_type_lst
+ : stnd_type
+ | struct_type_lst stnd_type {$$ = node2(LstNd, NULL, $1, $2);}
+ | struct_type_lst type_qual {$$ = node2(LstNd, NULL, $1, $2);} ;
+
+struct_dcltor_lst
+ : struct_dcltor
+ | struct_dcltor_lst ',' struct_dcltor {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+struct_dcltor
+ : dcltor {$$ = node2(StrDclNd, NULL, $1, NULL);
+ if (dcl_stk->parms_done) pop_cntxt();}
+ | ':' constant_expr {$$ = node2(StrDclNd, $1, NULL, $2);}
+ | dcltor ':' {if (dcl_stk->parms_done) pop_cntxt();} constant_expr
+ {$$ = node2(StrDclNd, $2, $1, $4);}
+ ;
+
+struct_no_tdn_dcltor_lst
+ : struct_no_tdn_dcltor
+ | struct_no_tdn_dcltor_lst ',' struct_no_tdn_dcltor
+ {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+struct_no_tdn_dcltor
+ : no_tdn_dcltor {$$ = node2(StrDclNd, NULL, $1, NULL);
+ if (dcl_stk->parms_done) pop_cntxt();}
+ | ':' constant_expr {$$ = node2(StrDclNd, $1, NULL, $2);}
+ | no_tdn_dcltor ':' {if (dcl_stk->parms_done) pop_cntxt();} constant_expr
+ {$$ = node2(StrDclNd, $2, $1, $4);}
+ ;
+
+enum_spec
+ : Enum {push_cntxt(0);} '{' enumerator_lst '}'
+ {$$ = node2(BinryNd, $1, NULL, $4); pop_cntxt(); free_t($3); free_t($5);}
+ | Enum any_ident {push_cntxt(0);} '{' enumerator_lst '}'
+ {$$ = node2(BinryNd, $1, $2, $5); pop_cntxt(); free_t($4); free_t($6);}
+ | Enum any_ident {$$ = node2(BinryNd, $1, $2, NULL);}
+ ;
+
+enumerator_lst
+ : enumerator
+ | enumerator_lst ',' enumerator {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+enumerator
+ : any_ident {$$ = $1; id_def($1, NULL);}
+ | any_ident '=' constant_expr
+ {$$ = node2(BinryNd, $2, $1, $3); id_def($1, $3);}
+ ;
+
+type_qual
+ : Const {$$ = node0(PrimryNd, $1);}
+ | Volatile {$$ = node0(PrimryNd, $1);}
+ ;
+
+
+dcltor
+ : opt_pointer direct_dcltor {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+no_tdn_dcltor
+ : opt_pointer no_tdn_direct_dcltor {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+direct_dcltor
+ : any_ident
+ | '(' dcltor ')' {$$ = node1(PrefxNd, $1, $2);
+ free_t($3);}
+ | direct_dcltor '[' opt_constant_expr ']' {$$ = node2(BinryNd, $2, $1, $3);
+ free_t($4);}
+ | direct_dcltor '(' {push_cntxt(1);} parm_dcls_or_ids ')'
+ {$$ = node2(BinryNd, $5, $1, $4);
+ if (dcl_stk->nest_lvl == 2)
+ dcl_stk->parms_done = 1;
+ else
+ pop_cntxt();
+ free_t($2);}
+ ;
+
+no_tdn_direct_dcltor
+ : identifier {$$ = node0(PrimryNd, $1);}
+ | '(' no_tdn_dcltor ')' {$$ = node1(PrefxNd, $1, $2);
+ free_t($3);}
+ | no_tdn_direct_dcltor '[' opt_constant_expr ']'
+ {$$ = node2(BinryNd, $2, $1, $3);
+ free_t($4);}
+ | no_tdn_direct_dcltor '(' {push_cntxt(1);} parm_dcls_or_ids ')'
+ {$$ = node2(BinryNd, $5, $1, $4);
+ if (dcl_stk->nest_lvl == 2)
+ dcl_stk->parms_done = 1;
+ else
+ pop_cntxt();
+ free_t($2);}
+ ;
+
+parm_dcls_or_ids
+ : opt_param_type_lst
+ | ident_lst
+ ;
+
+pointer
+ : '*' {$$ = node0(PrimryNd, $1);}
+ | '*' tqual_lst {$$ = node1(PreSpcNd, $1, $2);}
+ | '*' pointer {$$ = node1(PrefxNd, $1, $2);}
+ | '*' tqual_lst pointer {$$ = node1(PrefxNd, $1, node2(LstNd, NULL, $2,$3));}
+ ;
+
+opt_pointer
+ : {$$ = NULL;}
+ | pointer
+ ;
+
+tqual_lst
+ : type_qual
+ | tqual_lst type_qual {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+param_type_lst
+ : param_lst
+ | param_lst ',' Ellipsis {$$ = node2(CommaNd, $2, $1, node0(PrimryNd, $3));}
+ ;
+
+opt_param_type_lst
+ : {$$ = NULL;}
+ | param_type_lst
+ ;
+
+param_lst
+ : param_dcltion
+ | param_lst ',' param_dcltion {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+param_dcltion
+ : dcltion_specs no_tdn_dcltor {$$ = node2(LstNd, NULL, $1, $2);
+ id_def($2, NULL);}
+ | dcltion_specs
+ | dcltion_specs abstract_dcltor {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+ident_lst
+ : identifier {$$ = node0(PrimryNd, $1);}
+ | ident_lst ',' identifier {$$ = node2(CommaNd, $2, $1, node0(PrimryNd,$3));}
+ ;
+
+type_tqual_lst
+ : type_spec
+ | type_qual
+ | type_spec type_tqual_lst {$$ = node2(LstNd, NULL, $1, $2);}
+ | type_qual type_tqual_lst {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+type_name
+ : type_tqual_lst
+ | type_tqual_lst abstract_dcltor {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+abstract_dcltor
+ : pointer
+ | opt_pointer direct_abstract_dcltor {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+direct_abstract_dcltor
+ : '(' abstract_dcltor ')' {$$ = node1(PrefxNd, $1, $2);
+ free_t($3);}
+ | '[' opt_constant_expr ']'
+ {$$ = node2(BinryNd, $1, NULL, $2);
+ free_t($3);}
+ | direct_abstract_dcltor '[' opt_constant_expr ']'
+ {$$ = node2(BinryNd, $2, $1, $3);
+ free_t($4);}
+ | '(' {push_cntxt(1);} opt_param_type_lst ')'
+ {$$ = node2(BinryNd, $4, NULL, $3);
+ pop_cntxt();
+ free_t($1);}
+ | direct_abstract_dcltor '(' {push_cntxt(1);} opt_param_type_lst ')'
+ {$$ = node2(BinryNd, $5, $1, $4);
+ pop_cntxt();
+ free_t($2);}
+ ;
+
+initializer
+ : assign_expr
+ | '{' initializer_lst '}'
+ {$$ = node1(PrefxNd, $1, $2); free_t($3);}
+ | '{' initializer_lst ',' '}'
+ {$$ = node1(PrefxNd, $1, node2(CommaNd, $3, $2, NULL));
+ free_t($4);}
+ ;
+
+initializer_lst
+ : initializer
+ | initializer_lst ',' initializer {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+stmt
+ : labeled_stmt
+ | non_lbl_stmt
+ ;
+
+non_lbl_stmt
+ : {push_cntxt(1);} compound_stmt {$$ = $2; pop_cntxt();}
+ | expr_stmt
+ | selection_stmt
+ | iteration_stmt
+ | jump_stmt
+ | Runerr '(' assign_expr ')' ';'
+ {$$ = node2(BinryNd, $1, $3, NULL); free_t($2); free_t($4);}
+ | Runerr '(' assign_expr ',' assign_expr ')' ';'
+ {$$ = node2(BinryNd, $1, $3, $5); free_t($2); free_t($4); free_t($6);}
+ ;
+
+labeled_stmt
+ : label ':' stmt {$$ = node2(BinryNd, $2, $1, $3);}
+ | Case constant_expr ':' stmt {$$ = node2(BinryNd, $1, $2, $4); free_t($3);}
+ | Default ':' stmt {$$ = node1(PrefxNd, $1, $3); free_t($2);}
+ ;
+
+compound_stmt
+ : '{' opt_stmt_lst '}' {$$ = comp_nd($1, NULL, $2); free_t($3);}
+ | '{' local_dcls opt_stmt_lst '}' {$$ = comp_nd($1, $2, $3); free_t($4);}
+ ;
+
+dcltion_lst
+ : dcltion
+ | dcltion_lst dcltion {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+opt_dcltion_lst
+ : {$$ = NULL;}
+ | dcltion_lst
+ ;
+
+local_dcls
+ : local_dcl
+ | local_dcls local_dcl {$$ = ($2 == NULL ? $1 : node2(LstNd, NULL, $1, $2));}
+ ;
+
+local_dcl
+ : dcltion
+ | Tended tended_type init_dcltor_lst ';'
+ {$$ = NULL; free_t($1); free_t($4); dcl_stk->kind_dcl = OtherDcl;}
+ ;
+
+tended_type
+ : Char {tnd_char(); free_t($1);}
+ | Struct identifier {tnd_strct($2); free_t($1);}
+ | Struct TypeDefName {tnd_strct($2); free_t($1);}
+ | Union identifier {tnd_union($2); free_t($1);}
+ ;
+
+stmt_lst
+ : stmt
+ | stmt_lst stmt {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+opt_stmt_lst
+ : {$$ = NULL;}
+ | stmt_lst
+ ;
+expr_stmt
+ : opt_expr ';' {$$ = node1(PstfxNd, $2, $1);}
+ ;
+
+selection_stmt
+ : If '(' expr ')' stmt %prec IfStmt {$$ = node3(TrnryNd, $1, $3, $5,NULL);
+ free_t($2); free_t($4);}
+ | If '(' expr ')' stmt Else stmt {$$ = node3(TrnryNd, $1, $3, $5, $7);
+ free_t($2); free_t($4); free_t($6);}
+ | Switch '(' expr ')' stmt {$$ = node2(BinryNd, $1, $3, $5);
+ free_t($2); free_t($4);}
+ | Type_case expr Of '{' c_type_select_lst c_opt_default '}'
+ {$$ = node3(TrnryNd, $1, $2, $5, $6); free_t($3); free_t($4); free_t($7);}
+ ;
+
+c_type_select_lst
+ : c_type_select {$$ = node2(ConCatNd, NULL, NULL, $1);}
+ | c_type_select_lst c_type_select {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+c_type_select
+ : selector_lst non_lbl_stmt {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+c_opt_default
+ : {$$ = NULL;}
+ | Default ':' non_lbl_stmt {$$ = $3; free_t($1); free_t($2);}
+ ;
+
+iteration_stmt
+ : While '(' expr ')' stmt {$$ = node2(BinryNd, $1, $3, $5);
+ free_t($2); free_t($4);}
+ | Do stmt While '(' expr ')' ';' {$$ = node2(BinryNd, $1, $2, $5);
+ free_t($3); free_t($4); free_t($6);
+ free_t($7);}
+ | For '(' opt_expr ';' opt_expr ';' opt_expr ')' stmt
+ {$$ = node4(QuadNd, $1, $3, $5, $7, $9);
+ free_t($2); free_t($4); free_t($6);
+ free_t($8);}
+ ;
+
+jump_stmt
+ : Goto label';' {$$ = node1(PrefxNd, $1, $2); free_t($3);}
+ | Continue ';' {$$ = node0(PrimryNd, $1); free_t($2);}
+ | Break ';' {$$ = node0(PrimryNd, $1); free_t($2);}
+ | Return ret_val ';' {$$ = node1(PrefxNd, $1, $2); free_t($3);}
+ | Suspend ret_val ';' {$$ = node1(PrefxNd, $1, $2); free_t($3);}
+ | Fail ';' {$$ = node0(PrimryNd, $1); free_t($2);}
+ | Errorfail ';' {$$ = node0(PrimryNd, $1); free_t($2);}
+ ;
+
+translation_unit
+ :
+ | extrn_decltn_lst
+ ;
+
+extrn_decltn_lst
+ : external_dcltion
+ | extrn_decltn_lst external_dcltion
+ ;
+
+external_dcltion
+ : function_definition
+ | dcltion {dclout($1);}
+ | definition
+ ;
+
+function_definition
+ : func_head {func_def($1);} opt_dcltion_lst compound_stmt
+ {fncout($1, $3, $4);}
+ ;
+
+func_head
+ : no_tdn_dcltor {$$ = node2(LstNd, NULL, NULL, $1);}
+ | storcl_tqual_lst no_tdn_dcltor {$$ = node2(LstNd, NULL, $1, $2);}
+ | typ_dcltion_specs dcltor {$$ = node2(LstNd, NULL, $1, $2);}
+ ;
+
+any_ident
+ : identifier {$$ = node0(PrimryNd, $1);}
+ | typedefname {$$ = node0(PrimryNd, $1);}
+ ;
+
+label
+ : identifier {$$ = lbl($1);}
+ | typedefname {$$ = lbl($1);}
+ ;
+
+typedefname
+ : TypeDefName
+ | C_Integer /* hack to allow C_integer to be defined with typedef */
+ | C_Double /* for consistency with C_integer */
+ | C_String /* for consistency with C_integer */
+ ;
+
+/*
+ * The rest of the grammar implements the interface portion of the language.
+ */
+
+definition
+ : {strt_def();} description operation
+ ;
+
+operation
+ : fnc_oper op_declare actions End {defout($3); free_t($4);}
+ | keyword actions End {defout($2); free_t($3);}
+ | keyword Constant key_const End {keyconst($3); free_t($2); free_t($4);}
+ ;
+
+description
+ : {comment = NULL;}
+ | StrLit {comment = $1;}
+ ;
+
+fnc_oper
+ : Function '{' result_seq '}' op_name '(' opt_s_parm_lst ')'
+ {impl_fnc($5); free_t($1); free_t($2); free_t($4); free_t($6);
+ free_t($8);}
+ | Operator '{' result_seq {lex_state = OpHead;} '}' OpSym
+ {lex_state = DfltLex;} op_name '(' opt_s_parm_lst ')'
+ {impl_op($6, $8); free_t($1); free_t($2); free_t($5); free_t($9);
+ free_t($11);}
+
+keyword
+ : Keyword '{' result_seq '}' op_name
+ {impl_key($5); free_t($1); free_t($2); free_t($4);}
+ ;
+
+key_const
+ : StrLit
+ | CharConst
+ | DblConst
+ | IntConst
+ ;
+
+/*
+ * Allow as many special names to be identifiers as possible
+ */
+identifier
+ : Abstract
+ | All_fields
+ | Any_value
+ | Body
+ | Component
+ | Declare
+ | Empty_type
+ | End
+ | Exact
+ | IconType
+ | Identifier
+ | Inline
+ | Named_var
+ | New
+ | Of
+ | Store
+ | Struct_var
+ | Then
+ | Tmp_cset
+ | Tmp_string
+ | Type
+ | Underef
+ | Variable
+ ;
+
+/*
+ * an operation may be given any name.
+ */
+op_name
+ : identifier
+ | typedefname
+ | Auto
+ | Break
+ | Case
+ | Char
+ | Cnv
+ | Const
+ | Continue
+ | Def
+ | Default
+ | Do
+ | Doubl
+ | Else
+ | Enum
+ | Errorfail
+ | Extern
+ | Fail
+ | Float
+ | For
+ | Function
+ | Goto
+ | If
+ | Int
+ | Is
+ | Keyword
+ | Long
+ | Operator
+ | Register
+ | Return
+ | Runerr
+ | Short
+ | Signed
+ | Sizeof
+ | Static
+ | Struct
+ | Suspend
+ | Switch
+ | Tended
+ | Typedef
+ | Union
+ | Unsigned
+ | Void
+ | Volatile
+ | While
+ ;
+
+result_seq
+ : {set_r_seq(NoRsltSeq, NoRsltSeq, 0);}
+ | length opt_plus {set_r_seq($1, $1, (int)$2);}
+ | length ',' length opt_plus {set_r_seq($1, $3, (int)$4); free_t($2);}
+ ;
+
+length
+ : IntConst {$$ = ttol($1); free_t($1);}
+ | '*' {$$ = UnbndSeq; free_t($1);}
+ ;
+
+opt_plus
+ : {$$ = 0;}
+ | '+' {$$ = 1; free_t($1);}
+ ;
+
+opt_s_parm_lst
+ :
+ | s_parm_lst
+ | s_parm_lst '[' identifier ']' {var_args($3); free_t($2); free_t($4);}
+ ;
+
+s_parm_lst
+ : s_parm
+ | s_parm_lst ',' s_parm {free_t($2);}
+ ;
+
+s_parm
+ : identifier {s_prm_def(NULL, $1);}
+ | Underef identifier {s_prm_def($2, NULL); free_t($1);}
+ | Underef identifier Arrow identifier {s_prm_def($2, $4); free_t($1);
+ free_t($3);}
+ ;
+
+op_declare
+ : {}
+ | Declare '{' local_dcls '}' {d_lst_typ($3); free_t($1); free_t($2);
+ free_t($4);}
+ ;
+
+opt_actions
+ : {$$ = NULL;}
+ | actions
+ ;
+
+actions
+ : action
+ | actions action {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+action
+ : checking_conversions
+ | detail_code
+ | runerr
+ | '{' opt_actions '}' {$$ = node1(PrefxNd, $1, $2); free_t($3);}
+ | Abstract {lex_state = TypeComp;} '{' type_computations
+ {lex_state = DfltLex;} '}'
+ {$$ = $4; free_t($1); free_t($3); free_t($6);}
+ ;
+
+checking_conversions
+ : If type_check Then action %prec IfStmt
+ {$$ = node3(TrnryNd, $1, $2, $4, NULL); free_t($3);}
+ | If type_check Then action Else action
+ {$$ = node3(TrnryNd, $1, $2, $4, $6); free_t($3); free_t($5);}
+ | Type_case variable Of '{' type_select_lst opt_default '}'
+ {$$ = node3(TrnryNd, $1, $2, $5, $6); free_t($3); free_t($4); free_t($7);}
+ | Len_case identifier Of '{' len_select_lst Default ':' action '}'
+ {$$ = node3(TrnryNd, $1, sym_node($2), $5, $8); free_t($3), free_t($4);
+ free_t($6); free_t($7); free_t($9);}
+ | Arith_case '(' variable ',' variable ')' Of '{'
+ dest_type ':' action dest_type ':' action dest_type ':' action '}'
+ {$$ = arith_nd($1, $3, $5, $9, $11, $12, $14, $15, $17); free_t($2);
+ free_t($4), free_t($6); free_t($7); free_t($8); free_t($10);
+ free_t($13); free_t($16); free_t($18);}
+ ;
+
+type_select_lst
+ : type_select {$$ = node2(ConCatNd, NULL, NULL, $1);}
+ | type_select_lst type_select {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+type_select
+ : selector_lst action {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+opt_default
+ : {$$ = NULL;}
+ | Default ':' action {$$ = $3; free_t($1); free_t($2);}
+ ;
+
+selector_lst
+ : i_type_name ':' {$$ = node2(ConCatNd, NULL, NULL, $1);
+ free_t($2);}
+ | selector_lst i_type_name ':' {$$ = node2(ConCatNd, NULL, $1, $2);
+ free_t($3);}
+ ;
+
+len_select_lst
+ : len_select
+ | len_select_lst len_select {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+len_select
+ : IntConst ':' action {$$ = node1(PrefxNd, $1, $3); free_t($2);}
+ ;
+
+type_check
+ : simple_check_conj
+ | '!' simple_check {$$ = node1(PrefxNd, $1, $2);}
+ ;
+
+simple_check_conj
+ : simple_check
+ | simple_check_conj And simple_check {$$ = node2(BinryNd, $2, $1, $3);}
+ ;
+
+simple_check
+ : Is ':' i_type_name '(' variable ')'
+ {$$ = node2(BinryNd, $1, $3, $5); free_t($2); free_t($4); free_t($6);}
+ | Cnv ':' dest_type '(' variable ')'
+ {$$ = node3(TrnryNd, $1, $3, $5, NULL), dst_alloc($3, $5); free_t($2);
+ free_t($4); free_t($6);}
+ | Cnv ':' dest_type '(' variable ',' assign_expr ')'
+ {$$ = node3(TrnryNd, $1, $3, $5, $7), free_t($2); free_t($4); free_t($6);
+ free_t($8);}
+ | Def ':' dest_type '(' variable ',' assign_expr ')'
+ {$$ = node4(QuadNd, $1, $3, $5, $7, NULL), dst_alloc($3, $5); free_t($2);
+ free_t($4); free_t($6); free_t($8);}
+ | Def ':' dest_type '(' variable ',' assign_expr ',' assign_expr ')'
+ {$$ = node4(QuadNd, $1, $3, $5, $7, $9), free_t($2); free_t($4);
+ free_t($6); free_t($8); free_t($10);}
+ ;
+
+detail_code
+ : Body {push_cntxt(1);} compound_stmt
+ {$$ = node1(PrefxNd, $1, $3); pop_cntxt();}
+ | Inline {push_cntxt(1);} compound_stmt
+ {$$ = node1(PrefxNd, $1, $3); pop_cntxt();}
+ ;
+
+runerr
+ : Runerr '(' IntConst ')' opt_semi
+ {$$ = node2(BinryNd, $1, node0(PrimryNd, $3), NULL);
+ free_t($2); free_t($4);}
+ | Runerr '(' IntConst ',' variable ')' opt_semi
+ {$$ = node2(BinryNd, $1, node0(PrimryNd, $3), $5);
+ free_t($2); free_t($4); free_t($6);}
+ ;
+
+opt_semi
+ :
+ | ';' {free_t($1);}
+ ;
+
+variable
+ : identifier {$$ = sym_node($1);}
+ | identifier '[' IntConst ']' {$$ = node2(BinryNd, $2, sym_node($1),
+ node0(PrimryNd, $3));
+ free_t($4);}
+
+dest_type
+ : IconType {$$ = dest_node($1);}
+ | C_Integer {$$ = node0(PrimryNd, $1);}
+ | C_Double {$$ = node0(PrimryNd, $1);}
+ | C_String {$$ = node0(PrimryNd, $1);}
+ | Tmp_string {$$ = node0(PrimryNd, $1); ++n_tmp_str;}
+ | Tmp_cset {$$ = node0(PrimryNd, $1); ++n_tmp_cset;}
+ | '(' Exact ')' IconType {$$ = node0(ExactCnv, chk_exct($4)); free_t($1);
+ free_t($2); free_t($3);}
+ | '(' Exact ')' C_Integer {$$ = node0(ExactCnv, $4); free_t($1); free_t($2);
+ free_t($3);}
+ ;
+
+i_type_name
+ : Any_value {$$ = node0(PrimryNd, $1);}
+ | Empty_type {$$ = node0(PrimryNd, $1);}
+ | IconType {$$ = sym_node($1);}
+ | Variable {$$ = node0(PrimryNd, $1);}
+ ;
+
+ret_val
+ : opt_expr
+ | C_Integer assign_expr {$$ = node1(PrefxNd, $1, $2);}
+ | C_Double assign_expr {$$ = node1(PrefxNd, $1, $2);}
+ | C_String assign_expr {$$ = node1(PrefxNd, $1, $2);}
+ ;
+
+type_computations
+ : side_effect_lst Return type opt_semi {$$ = node2(AbstrNd, $2, $1, $3);}
+ | Return type opt_semi {$$ = node2(AbstrNd, $1, NULL, $2);}
+ | side_effect_lst {$$ = node2(AbstrNd, NULL, $1, NULL);}
+ ;
+
+side_effect_lst
+ : side_effect
+ | side_effect_lst side_effect {$$ = node2(ConCatNd, NULL, $1, $2);}
+ ;
+
+side_effect
+ : Store '[' type ']' '=' type opt_semi {$$ = node2(BinryNd, $5, $3, $6);
+ free_t($1); free_t($2); free_t($4);}
+ ;
+
+type
+ : basic_type
+ | type union basic_type {$$ = node2(BinryNd, $2, $1, $3);}
+ | type Intersect basic_type {$$ = node2(BinryNd, $2, $1, $3);}
+
+basic_type
+ : i_type_name {$$ = node1(IcnTypNd,
+ copy_t($1->tok), $1);}
+ | Type '(' variable ')' {$$ = node1(PrefxNd, $1, $3);
+ free_t($2); free_t($4);}
+ | New i_type_name '(' type_lst ')' {$$ = node2(BinryNd, $1, $2, $4);
+ free_t($3); free_t($5);}
+ | Store '[' type ']' {$$ = node1(PrefxNd, $1, $3);
+ free_t($2); free_t($4);}
+ | basic_type '.' attrb_name {$$ = node1(PstfxNd, $3, $1);
+ free_t($2);}
+ | '(' type ')' {$$ = $2; free_t($1); free_t($3);}
+ ;
+
+union
+ : Incr
+ ;
+
+type_lst
+ : type
+ | type_lst ',' type {$$ = node2(CommaNd, $2, $1, $3);}
+ ;
+
+attrb_name
+ : Component
+ | All_fields
+ ;
+
+%%
+
+/*
+ * xfree(p) -- used with free(p) macro to avoid compiler errors from
+ * miscast free calls generated by Yacc.
+ */
+static void xfree(p)
+char *p;
+{
+ free(p);
+}
+
+#define free(p) xfree((char*)p)
diff --git a/src/rtt/rttilc.c b/src/rtt/rttilc.c
new file mode 100644
index 0000000..70839ef
--- /dev/null
+++ b/src/rtt/rttilc.c
@@ -0,0 +1,1402 @@
+/*
+ * rttilc.c - routines to construct pieces of C code to put in the data base
+ * as in-line code.
+ *
+ * In-line C code is represented internally as a linked list of structures.
+ * The information contained in each structure depends on the type of code
+ * being represented. Some structures contain other fragments of C code.
+ * Code that does not require special processing is stored as strings. These
+ * strings are accumulated in a buffer until it is full or code that cannot
+ * be represented as a string must be produced. At that point, the string
+ * in placed in a structure and put on the list.
+ */
+#include "rtt.h"
+
+#ifndef Rttx
+
+/*
+ * prototypes for static functions.
+ */
+static void add_ptr (struct node *dcltor);
+static void alloc_ilc (int il_c_type);
+static void flush_str (void);
+static void ilc_chnl (struct token *t);
+static void ilc_cnv (struct node *cnv_typ, struct node *src,
+ struct node *dflt, struct node *dest);
+static void ilc_cgoto (int neg, struct node *cond, word lbl);
+static void ilc_goto (word lbl);
+static void ilc_lbl (word lbl);
+static void ilc_ret (struct token *t, int ilc_typ, struct node *n);
+static void ilc_str (char *s);
+static void ilc_tok (struct token *t);
+static void ilc_var (struct sym_entry *sym, int just_desc, int may_mod);
+static void ilc_walk (struct node *n, int may_mod, int const_cast);
+static void init_ilc (void);
+static void insrt_str (void);
+static void new_ilc (int il_c_type);
+static struct il_c *sep_ilc (char *s1,struct node *n,char *s2);
+
+#define SBufSz 256
+
+static char sbuf[SBufSz]; /* buffer for constructing fragments of code */
+static int nxt_char; /* next position in sbuf */
+static struct token *line_ref; /* "recent" token for comparing line number */
+static struct il_c ilc_base; /* base for list of in-line C code */
+static struct il_c *ilc_cur; /* current end of list of in-line C code */
+static int insert_nl; /* flag: new-line should be inserted in code */
+static word cont_lbl = 0; /* destination label for C continue statement */
+static word brk_lbl = 0; /* destination label for C break statement */
+
+/*
+ * inlin_c - Create a self-contained piece of in-line C code from a syntax
+ * sub-tree.
+ */
+struct il_c *inlin_c(n, may_mod)
+struct node *n;
+int may_mod;
+ {
+ init_ilc(); /* initialize code list and string buffer */
+ ilc_walk(n, may_mod, 0); /* translate the syntax sub-tree */
+ flush_str(); /* flush string buffer to code list */
+ return ilc_base.next;
+ }
+
+/*
+ * simpl_dcl - produce a simple declaration both in the output file and as
+ * in-line C code.
+ */
+struct il_c *simpl_dcl(tqual, addr_of, sym)
+char *tqual;
+int addr_of;
+struct sym_entry *sym;
+ {
+ init_ilc(); /* initialize code list and string buffer */
+ prt_str(tqual, 0);
+ ilc_str(tqual);
+ if (addr_of) {
+ prt_str("*", 0);
+ ilc_str("*");
+ }
+ prt_str(sym->image, 0);
+ ilc_str(sym->image);
+ prt_str(";", 0);
+ ForceNl();
+ flush_str(); /* flush string buffer to code list */
+ return ilc_base.next;
+ }
+
+/*
+ * parm_dcl - produce the declaration for a parameter to a body function.
+ * Print it in the output file and proceduce in-line C code for it.
+ */
+struct il_c *parm_dcl(addr_of, sym)
+int addr_of;
+struct sym_entry *sym;
+ {
+ init_ilc(); /* initialize code list and string buffer */
+
+ /*
+ * Produce type-qualifier list, but without non-type information.
+ */
+ just_type(sym->u.declare_var.tqual, 0, 1);
+ prt_str(" ", 0);
+ ilc_str(" ");
+
+ /*
+ * If the caller requested another level of indirection on the
+ * declaration add it.
+ */
+ if (addr_of)
+ add_ptr(sym->u.declare_var.dcltor);
+ else {
+ c_walk(sym->u.declare_var.dcltor, 0, 0);
+ ilc_walk(sym->u.declare_var.dcltor, 0, 0);
+ }
+ prt_str(";", 0);
+ ForceNl();
+ flush_str(); /* flush string buffer to code list */
+ return ilc_base.next;
+ }
+
+/*
+ * add_ptr - add another level of indirection to a declarator. Print it in
+ * the output file and proceduce in-line C code.
+ */
+static void add_ptr(dcltor)
+struct node *dcltor;
+ {
+ while (dcltor->nd_id == ConCatNd) {
+ c_walk(dcltor->u[0].child, IndentInc, 0);
+ ilc_walk(dcltor->u[0].child, 0, 0);
+ dcltor = dcltor->u[1].child;
+ }
+ switch (dcltor->nd_id) {
+ case PrimryNd:
+ /*
+ * We have reached the name, add a level of indirection.
+ */
+ prt_str("(*", IndentInc);
+ ilc_str("(*");
+ prt_str(dcltor->tok->image, IndentInc);
+ ilc_str(dcltor->tok->image);
+ prt_str(")", IndentInc);
+ ilc_str(")");
+ break;
+ case PrefxNd:
+ /*
+ * (...)
+ */
+ prt_str("(", IndentInc);
+ ilc_str("(");
+ add_ptr(dcltor->u[0].child);
+ prt_str(")", IndentInc);
+ ilc_str(")");
+ break;
+ case BinryNd:
+ if (dcltor->tok->tok_id == ')') {
+ /*
+ * Function declaration.
+ */
+ add_ptr(dcltor->u[0].child);
+ prt_str("(", IndentInc);
+ ilc_str("(");
+ c_walk(dcltor->u[1].child, IndentInc, 0);
+ ilc_walk(dcltor->u[1].child, 0, 0);
+ prt_str(")", IndentInc);
+ ilc_str(")");
+ }
+ else {
+ /*
+ * Array.
+ */
+ add_ptr(dcltor->u[0].child);
+ prt_str("[", IndentInc);
+ ilc_str("[");
+ c_walk(dcltor->u[1].child, IndentInc, 0);
+ ilc_walk(dcltor->u[1].child, 0, 0);
+ prt_str("]", IndentInc);
+ ilc_str("]");
+ }
+ }
+ }
+
+/*
+ * bdy_prm - produce the code that must be be supplied as the argument
+ * to the call of a body function.
+ */
+struct il_c *bdy_prm(addr_of, just_desc, sym, may_mod)
+int addr_of;
+int just_desc;
+struct sym_entry *sym;
+int may_mod;
+ {
+ init_ilc(); /* initialize code list and string buffer */
+ if (addr_of)
+ ilc_str("&("); /* call-by-reference parameter */
+ ilc_var(sym, just_desc, may_mod); /* variable to pass as argument */
+ if (addr_of)
+ ilc_str(")");
+ flush_str(); /* flush string buffer to code list */
+ return ilc_base.next;
+ }
+
+/*
+ * ilc_dcl - produce in-line code for a C declaration.
+ */
+struct il_c *ilc_dcl(tqual, dcltor, init)
+struct node *tqual;
+struct node *dcltor;
+struct node *init;
+ {
+ init_ilc(); /* initialize code list and string buffer */
+ ilc_walk(tqual, 0, 0);
+ ilc_str(" ");
+ ilc_walk(dcltor, 0, 0);
+ if (init != NULL) {
+ ilc_str(" = ");
+ ilc_walk(init, 0, 0);
+ }
+ ilc_str(";");
+ flush_str(); /* flush string buffer to code list */
+ return ilc_base.next;
+ }
+
+
+/*
+ * init_ilc - initialize the code list by pointing to ilc_base. Initialize
+ * the string buffer.
+ */
+static void init_ilc()
+ {
+ nxt_char = 0;
+ line_ref = NULL;
+ insert_nl = 0;
+ ilc_base.il_c_type = 0;
+ ilc_base.next = NULL;
+ ilc_cur = &ilc_base;
+ }
+
+
+/*
+ * - ilc_chnl - check for new-line.
+ */
+static void ilc_chnl(t)
+struct token *t;
+ {
+ /*
+ * See if this is a reasonable place to put a newline.
+ */
+ if (t->flag & LineChk) {
+ if (line_ref != NULL &&
+ (t->fname != line_ref->fname || t->line != line_ref->line))
+ insert_nl = 1;
+ line_ref = t;
+ }
+ }
+
+/*
+ * ilc_tok - convert a token to its string representation, quoting it
+ * if it is a string or character literal.
+ */
+static void ilc_tok(t)
+struct token *t;
+ {
+ char *s;
+
+ ilc_chnl(t);
+ s = t->image;
+ switch (t->tok_id) {
+ case StrLit:
+ ilc_str("\"");
+ ilc_str(s);
+ ilc_str("\"");
+ break;
+ case LStrLit:
+ ilc_str("L\"");
+ ilc_str(s);
+ ilc_str("\"");
+ break;
+ case CharConst:
+ ilc_str("'");
+ ilc_str(s);
+ ilc_str("'");
+ break;
+ case LCharConst:
+ ilc_str("L'");
+ ilc_str(s);
+ ilc_str("'");
+ break;
+ default:
+ ilc_str(s);
+ }
+ }
+
+/*
+ * ilc_str - append a string to the string buffer.
+ */
+static void ilc_str(s)
+char *s;
+ {
+ /*
+ * see if a new-line is needed before the string
+ */
+ if (insert_nl && (nxt_char == 0 || sbuf[nxt_char - 1] != '\n')) {
+ insert_nl = 0;
+ ilc_str("\n");
+ }
+
+ /*
+ * Put the string in the buffer. If the buffer is full, flush it
+ * to an element in the in-line code list.
+ */
+ while (*s != '\0') {
+ if (nxt_char >= SBufSz - 1)
+ insrt_str();
+ sbuf[nxt_char++] = *s++;
+ }
+ }
+
+/*
+ * insrt_str - insert the string in the buffer into the list of in-line
+ * code.
+ */
+static void insrt_str()
+ {
+ alloc_ilc(ILC_Str);
+ sbuf[nxt_char] = '\0';
+ ilc_cur->s = salloc(sbuf);
+ nxt_char = 0;
+ }
+
+/*
+ * flush_str - if the string buffer is not empty, flush it to the list
+ * of in-line code.
+ */
+static void flush_str()
+ {
+ if (insert_nl)
+ ilc_str("");
+ if (nxt_char != 0)
+ insrt_str();
+ }
+
+/*
+ * new_ilc - create a new element for the list of in-line C code. This
+ * is called for non-string elements. If necessary it flushes the
+ * string buffer to another element first.
+ */
+static void new_ilc(il_c_type)
+int il_c_type;
+ {
+ flush_str();
+ alloc_ilc(il_c_type);
+ }
+
+/*
+ * alloc_ilc - allocate a new element for the list of in-line C code
+ * and add it to the list.
+ */
+static void alloc_ilc(il_c_type)
+int il_c_type;
+ {
+ int i;
+ ilc_cur->next = NewStruct(il_c);
+ ilc_cur = ilc_cur->next;
+ ilc_cur->next = NULL;
+ ilc_cur->il_c_type = il_c_type;
+ for (i = 0; i < 3; ++i)
+ ilc_cur->code[i] = NULL;
+ ilc_cur->n = 0;
+ ilc_cur->s = NULL;
+ }
+
+/*
+ * sep_ilc - translate the syntax tree, n, (possibly surrounding it by
+ * strings) into a sub-list of in-line C code, remove the sub-list from
+ * the main list, and return it.
+ */
+static struct il_c *sep_ilc(s1, n, s2)
+char *s1;
+struct node *n;
+char *s2;
+ {
+ struct il_c *ilc;
+
+ ilc = ilc_cur; /* remember the starting point in the main list */
+ if (s1 != NULL)
+ ilc_str(s1);
+ ilc_walk(n, 0, 0);
+ if (s2 != NULL)
+ ilc_str(s2);
+ flush_str();
+
+ /*
+ * Reset the main list to its condition upon entry, and return the sublist
+ * created from s1, n, and s2.
+ */
+ ilc_cur = ilc;
+ ilc = ilc_cur->next;
+ ilc_cur->next = NULL;
+ return ilc;
+ }
+
+/*
+ * ilc_var - create in-line C code for a variable in the symbol table.
+ */
+static void ilc_var(sym, just_desc, may_mod)
+struct sym_entry *sym;
+int just_desc;
+int may_mod;
+ {
+ if (sym->il_indx >= 0) {
+ /*
+ * This symbol will be in symbol table iconc builds from the
+ * data base entry. iconc needs to know if this is a modifying
+ * reference so it can perform optimizations. This is indicated by
+ * may_mod. Some variables are implemented as the vword of a
+ * descriptor. Sometime the entire descriptor must be accessed.
+ * This is indicated by just_desc.
+ */
+ if (may_mod) {
+ new_ilc(ILC_Mod);
+ if (sym->id_type & DrfPrm)
+ sym->u.param_info.parm_mod |= 1;
+ }
+ else
+ new_ilc(ILC_Ref);
+ ilc_cur->n = sym->il_indx;
+ if (just_desc)
+ ilc_cur->s = "d";
+ }
+ else switch (sym->id_type) {
+ case TndDesc:
+ /*
+ * variable declared: tended struct descrip ...
+ */
+ new_ilc(ILC_Tend);
+ ilc_cur->n = sym->t_indx; /* index into tended variables */
+ break;
+ case TndStr:
+ /*
+ * variable declared: tended char *...
+ */
+ new_ilc(ILC_Tend);
+ ilc_cur->n = sym->t_indx; /* index into tended variables */
+ ilc_str(".vword.sptr"); /* get string pointer from vword union */
+ break;
+ case TndBlk:
+ /*
+ * If blk_name field is null, this variable was declared:
+ * tended union block *...
+ * otherwise it was declared:
+ * tended struct <blk_name> *...
+ */
+ if (sym->u.tnd_var.blk_name != NULL) {
+ /*
+ * Cast the "union block *" from the vword to the correct
+ * struct pointer. This cast can be used as an r-value or
+ * an l-value.
+ */
+ ilc_str("(*(struct ");
+ ilc_str(sym->u.tnd_var.blk_name);
+ ilc_str("**)&");
+ }
+ new_ilc(ILC_Tend);
+ ilc_cur->n = sym->t_indx; /* index into tended variables */
+ ilc_str(".vword.bptr"); /* get block pointer from vword union */
+ if (sym->u.tnd_var.blk_name != NULL)
+ ilc_str(")");
+ break;
+ case RsltLoc:
+ /*
+ * This is the special variable for the result of the operation.
+ * iconc needs to know if this is a modifying reference so it
+ * can perform optimizations.
+ */
+ if (may_mod)
+ new_ilc(ILC_Mod);
+ else
+ new_ilc(ILC_Ref);
+ ilc_cur->n = RsltIndx;
+ break;
+ default:
+ /*
+ * This is a variable with an ordinary declaration. Access it by
+ * its identifier.
+ */
+ ilc_str(sym->image);
+ }
+ }
+
+/*
+ * ilc_walk - walk the syntax tree for C code producing a list of "in-line"
+ * code. This function needs to know if the code is in a modifying context,
+ * such as the left-hand-side of an assignment.
+ */
+static void ilc_walk(n, may_mod, const_cast)
+struct node *n;
+int may_mod;
+int const_cast;
+ {
+ struct token *t;
+ struct node *n1;
+ struct node *n2;
+ struct sym_entry *sym;
+ word cont_sav;
+ word brk_sav;
+ word l1, l2;
+ int typcd;
+
+ if (n == NULL)
+ return;
+
+ t = n->tok;
+
+ switch (n->nd_id) {
+ case PrimryNd:
+ /*
+ * Primary expressions consisting of a single token.
+ */
+ switch (t->tok_id) {
+ case Fail:
+ /*
+ * fail statement. Note that this operaion can fail, output
+ * the corresponding "in-line" code, and make sure we have
+ * seen an abstract clause of some kind.
+ */
+ cur_impl->ret_flag |= DoesFail;
+ insert_nl = 1;
+ new_ilc(ILC_Fail);
+ insert_nl = 1;
+ line_ref = NULL;
+ chkabsret(t, SomeType);
+ break;
+ case Errorfail:
+ /*
+ * errorfail statement. Note that this operaion can do error
+ * conversion and output the corresponding "in-line" code.
+ */
+ cur_impl->ret_flag |= DoesEFail;
+ insert_nl = 1;
+ new_ilc(ILC_EFail);
+ insert_nl = 1;
+ line_ref = NULL;
+ break;
+ case Break:
+ /*
+ * iconc can only handle gotos for transfer of control in
+ * in-line code. A break label has been established for
+ * the current loop; transform the "break" into a goto.
+ */
+ ilc_goto(brk_lbl);
+ break;
+ case Continue:
+ /*
+ * iconc can only handle gotos for transfer of control in
+ * in-line code. A continue label has been established for
+ * the current loop; transform the "continue" into a goto.
+ */
+ ilc_goto(cont_lbl);
+ break;
+ default:
+ /*
+ * No special processing is needed for this primary
+ * expression, just output the image of the token.
+ */
+ ilc_tok(t);
+ }
+ break;
+ case PrefxNd:
+ /*
+ * Expressions with one operand that are introduced by a token.
+ * Note, "default :" does not appear here because switch
+ * statements are not allowed in in-line code.
+ */
+ switch (t->tok_id) {
+ case Sizeof:
+ /*
+ * sizeof(...)
+ */
+ ilc_tok(t);
+ ilc_str("(");
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str(")");
+ break;
+ case '{':
+ /*
+ * initializer: { ... }
+ */
+ ilc_tok(t);
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str("}");
+ break;
+ case Goto:
+ /*
+ * goto <label>;
+ */
+ ilc_goto(n->u[0].child->u[0].sym->u.lbl_num);
+ break;
+ case Return:
+ /*
+ * return <expression>;
+ * Indicate that this operation can return, then perform
+ * processing to categorize the kind of return statement
+ * and produce appropriate in-line code.
+ */
+ cur_impl->ret_flag |= DoesRet;
+ ilc_ret(t, ILC_Ret, n->u[0].child);
+ break;
+ case Suspend:
+ /*
+ * suspend <expression>;
+ * Indicate that this operation can suspend, then perform
+ * processing to categorize the kind of suspend statement
+ * and produce appropriate in-line code.
+ */
+ cur_impl->ret_flag |= DoesSusp;
+ ilc_ret(t, ILC_Susp, n->u[0].child);
+ break;
+ case '(':
+ /*
+ * ( ... )
+ */
+ ilc_tok(t);
+ ilc_walk(n->u[0].child, may_mod, const_cast);
+ ilc_str(")");
+ break;
+ case Incr:
+ case Decr:
+ /*
+ * The operand might be modified, otherwise nothing special
+ * is needed.
+ */
+ ilc_tok(t);
+ ilc_walk(n->u[0].child, 1, 0);
+ break;
+ case '&':
+ /*
+ * Unless the address is cast to a const pointer, this
+ * might be a modifiying reference.
+ */
+ ilc_tok(t);
+ if (const_cast)
+ ilc_walk(n->u[0].child, 0, 0);
+ else
+ ilc_walk(n->u[0].child, 1, 0);
+ break;
+ default:
+ /*
+ * Nothing special is needed, just output the image of
+ * the prefix operation followed by its operand.
+ */
+ ilc_tok(t);
+ ilc_walk(n->u[0].child, 0, 0);
+ }
+ break;
+ case PstfxNd:
+ /*
+ * postfix notation: ';', '++', and '--'. The later two
+ * modify their operands.
+ */
+ if (t->tok_id == ';')
+ ilc_walk(n->u[0].child, 0, 0);
+ else
+ ilc_walk(n->u[0].child, 1, 0);
+ ilc_tok(t);
+ break;
+ case PreSpcNd:
+ /*
+ * Prefix notation that needs a space after the expression;
+ * used for pointer/type qualifier lists.
+ */
+ ilc_tok(t);
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str(" ");
+ break;
+ case SymNd:
+ /*
+ * Identifier in symbol table. See if it start a new line. Note
+ * that we need to know whether this is a modifying reference.
+ */
+ ilc_chnl(n->tok);
+ ilc_var(n->u[0].sym, 0, may_mod);
+ break;
+ case BinryNd:
+ switch (t->tok_id) {
+ case '[':
+ /*
+ * Expression or declaration:
+ * <expr1> [ <expr2> ]
+ */
+ ilc_walk(n->u[0].child, may_mod, 0);
+ ilc_str("[");
+ ilc_walk(n->u[1].child, 0, 0);
+ ilc_str("]");
+ break;
+ case '(':
+ /*
+ * ( <type> ) expr
+ */
+ ilc_tok(t);
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str(")");
+ /*
+ * See if the is a const cast.
+ */
+ for (n1 = n->u[0].child; n1->nd_id == LstNd; n1 = n1->u[0].child)
+ ;
+ if (n1->nd_id == PrimryNd && n1->tok->tok_id == Const)
+ ilc_walk(n->u[1].child, 0, 1);
+ else
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ case ')':
+ /*
+ * Expression or declaration:
+ * <expr> ( <arg-list> )
+ */
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str("(");
+ ilc_walk(n->u[1].child, 0, 0);
+ ilc_tok(t);
+ break;
+ case Struct:
+ case Union:
+ case TokEnum:
+ /*
+ * <struct-union-enum> <identifier>
+ * <struct-union-enum> { <component-list> }
+ * <struct-union-enum> <identifier> { <component-list> }
+ */
+ ilc_tok(t);
+ ilc_str(" ");
+ ilc_walk(n->u[0].child, 0, 0);
+ if (n->u[1].child != NULL) {
+ ilc_str(" {");
+ ilc_walk(n->u[1].child, 0, 0);
+ ilc_str("}");
+ }
+ break;
+ case ';':
+ /*
+ * <type specifiers> <declarator> ;
+ */
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str(" ");
+ ilc_walk(n->u[1].child, 0, 0);
+ ilc_tok(t);
+ break;
+ case ':':
+ /*
+ * <label> : <statement>
+ */
+ ilc_lbl(n->u[0].child->u[0].sym->u.lbl_num);
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ case Switch:
+ errt1(t, "switch statement not supported in in-line code");
+ break;
+ case While:
+ /*
+ * Convert "while (c) s" into [conditional] gotos and labels.
+ * Establish labels for break and continue statements
+ * within s.
+ */
+ brk_sav = brk_lbl;
+ cont_sav = cont_lbl;
+ cont_lbl = lbl_num++;
+ brk_lbl = lbl_num++;
+ ilc_lbl(cont_lbl); /* L1: */
+ ilc_cgoto(1, n->u[0].child, brk_lbl); /* if (!(c)) goto L2; */
+ ilc_walk(n->u[1].child, 0, 0); /* s */
+ ilc_goto(cont_lbl); /* goto L1; */
+ ilc_lbl(brk_lbl); /* L2: */
+ brk_lbl = brk_sav;
+ cont_lbl = cont_sav;
+ break;
+ case Do:
+ /*
+ * Convert "do s while (c);" loop into a conditional goto and
+ * label. Establish labels for break and continue statements
+ * within s.
+ */
+ brk_sav = brk_lbl;
+ cont_sav = cont_lbl;
+ cont_lbl = lbl_num++;
+ brk_lbl = lbl_num++;
+ ilc_lbl(cont_lbl); /* L1: */
+ ilc_walk(n->u[0].child, 0, 0); /* s */
+ ilc_cgoto(0, n->u[1].child, cont_lbl); /* if (c) goto L1 */
+ ilc_lbl(brk_lbl);
+ brk_lbl = brk_sav;
+ cont_lbl = cont_sav;
+ break;
+ case '.':
+ /*
+ * <expr1> . <expr2>
+ */
+ ilc_walk(n->u[0].child, may_mod, 0);
+ ilc_tok(t);
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ case Arrow:
+ /*
+ * <expr1> -> <expr2>
+ */
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_tok(t);
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ case Runerr:
+ /*
+ * runerr ( <expr> ) ;
+ * runerr ( <expr> , <expr> ) ;
+ */
+ ilc_str("err_msg(");
+ ilc_walk(n->u[0].child, 0, 0);
+ if (n->u[1].child == NULL)
+ ilc_str(", NULL);");
+ else {
+ ilc_str(", &(");
+ ilc_walk(n->u[1].child, 0, 0);
+ ilc_str("));");
+ }
+ /*
+ * Handle error conversion.
+ */
+ cur_impl->ret_flag |= DoesEFail;
+ insert_nl = 1;
+ new_ilc(ILC_EFail);
+ insert_nl = 1;
+ break;
+ case Is:
+ /*
+ * is : <type-name> ( <expr> )
+ */
+ typcd = icn_typ(n->u[0].child);
+ n1 = n->u[1].child;
+ if (typcd == str_typ) {
+ ilc_str("(!((");
+ ilc_walk(n1, 0, 0);
+ ilc_str(").dword & F_Nqual))");
+ }
+ else if (typcd == Variable) {
+ ilc_str("(((");
+ ilc_walk(n1, 0, 0);
+ ilc_str(").dword & D_Var) == D_Var)");
+ }
+ else if (typcd == int_typ) {
+ ForceNl();
+ prt_str("#ifdef LargeInts", 0);
+ ForceNl();
+
+ ilc_str("(((");
+ ilc_walk(n1, 0, 0);
+ ilc_str(").dword == D_Integer) || ((");
+ ilc_walk(n1, 0, 0);
+ ilc_str(").dword == D_Lrgint))");
+
+ ForceNl();
+ prt_str("#else /* LargeInts */", 0);
+ ForceNl();
+
+ ilc_str("((");
+ ilc_walk(n1, 0, 0);
+ ilc_str(").dword == D_Integer)");
+
+ ForceNl();
+ prt_str("#endif /* LargeInts */", 0);
+ ForceNl();
+ }
+ else {
+ ilc_str("((");
+ ilc_walk(n1, 0, 0);
+ ilc_str(").dword == D_");
+ ilc_str(typ_name(typcd, n->u[0].child->tok));
+ ilc_str(")");
+ }
+ break;
+ case '=':
+ case MultAsgn:
+ case DivAsgn:
+ case ModAsgn:
+ case PlusAsgn:
+ case MinusAsgn:
+ case LShftAsgn:
+ case RShftAsgn:
+ case AndAsgn:
+ case XorAsgn:
+ case OrAsgn:
+ /*
+ * Assignment operation (or initialization or specification
+ * of enumeration value). Left-hand-side may be modified.
+ */
+ ilc_walk(n->u[0].child, 1, 0);
+ ilc_str(" ");
+ ilc_tok(t);
+ ilc_str(" ");
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ default:
+ /*
+ * Simple binary operator. Nothing special is needed,
+ * just put space around the operator.
+ */
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str(" ");
+ ilc_tok(t);
+ ilc_str(" ");
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ }
+ break;
+ case LstNd:
+ /*
+ * Consecutive expressions that need a space between them.
+ */
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str(" ");
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ case ConCatNd:
+ /*
+ * Consecutive expressions that don't need space between them.
+ */
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ case CommaNd:
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_tok(t);
+ ilc_str(" ");
+ ilc_walk(n->u[1].child, 0, 0);
+ break;
+ case StrDclNd:
+ /*
+ * struct field declarator. May be a bit field.
+ */
+ ilc_walk(n->u[0].child, 0, 0);
+ if (n->u[1].child != NULL) {
+ ilc_str(": ");
+ ilc_walk(n->u[1].child, 0, 0);
+ }
+ break;
+ case CompNd: {
+ /*
+ * Compound statement. May have declarations including tended
+ * declarations that are separated out.
+ */
+ struct node *dcls;
+
+ /*
+ * If the in-line code has declarations, the block must
+ * be surrounded by braces. Braces are special constructs
+ * because iconc must not delete one without the other
+ * during code optimization.
+ */
+ dcls = n->u[0].child;
+ if (dcls != NULL) {
+ insert_nl = 1;
+ new_ilc(ILC_LBrc);
+ insert_nl = 1;
+ line_ref = NULL;
+ ilc_walk(dcls, 0, 0);
+ }
+ /*
+ * we are in an inner block. tended locations may need to
+ * be set to values from declaration initializations.
+ */
+ for (sym = n->u[1].sym; sym!= NULL; sym = sym->u.tnd_var.next) {
+ if (sym->u.tnd_var.init != NULL) {
+ new_ilc(ILC_Tend);
+ ilc_cur->n = sym->t_indx;
+
+ /*
+ * See if the variable is just the vword of the descriptor.
+ */
+ switch (sym->id_type) {
+ case TndDesc:
+ ilc_str(" = ");
+ break;
+ case TndStr:
+ ilc_str(".vword.sptr = ");
+ break;
+ case TndBlk:
+ ilc_str(".vword.bptr = (union block *)");
+ break;
+ }
+ ilc_walk(sym->u.tnd_var.init, 0, 0); /* initial value */
+ ilc_str(";");
+ }
+ }
+
+ ilc_walk(n->u[2].child, 0, 0); /* body of compound statement */
+
+ if (dcls != NULL) {
+ insert_nl = 1;
+ new_ilc(ILC_RBrc); /* closing brace */
+ insert_nl = 1;
+ line_ref = NULL;
+ }
+ }
+ break;
+ case TrnryNd:
+ switch (t->tok_id) {
+ case '?':
+ /*
+ * <expr> ? <expr> : <expr>
+ */
+ ilc_walk(n->u[0].child, 0, 0);
+ ilc_str(" ");
+ ilc_tok(t);
+ ilc_str(" ");
+ ilc_walk(n->u[1].child, 0, 0);
+ ilc_str(" : ");
+ ilc_walk(n->u[2].child, 0, 0);
+ break;
+ case If:
+ /*
+ * Convert if statement into [conditional] gotos and labels.
+ */
+ n1 = n->u[1].child;
+ n2 = n->u[2].child;
+ l1 = lbl_num++;
+ if (n2 == NULL) { /* if (c) then s */
+ ilc_cgoto(1, n->u[0].child, l1); /* if (!(c)) goto L1; */
+ ilc_walk(n1, 0, 0); /* s */
+ ilc_lbl(l1); /* L1: */
+ }
+ else { /* if (c) then s1 else s2 */
+ ilc_cgoto(0, n->u[0].child, l1); /* if (c) goto L1; */
+ ilc_walk(n2, 0, 0); /* s2 */
+ l2 = lbl_num++;
+ ilc_goto(l2); /* goto L2; */
+ ilc_lbl(l1); /* L1: */
+ ilc_walk(n1, 0, 0); /* s1 */
+ ilc_lbl(l2); /* L2: */
+ }
+ break;
+ case Type_case:
+ errt1(t, "type case statement not supported in in-line code");
+ break;
+ case Cnv:
+ /*
+ * cnv : <type> ( <expr> , <expr> )
+ */
+ ilc_cnv(n->u[0].child, n->u[1].child, NULL, n->u[2].child);
+ break;
+ }
+ break;
+ case QuadNd:
+ switch (t->tok_id) {
+ case For:
+ /*
+ * convert "for (e1; e2; e3) s" into [conditional] gotos and
+ * labels.
+ */
+ brk_sav = brk_lbl;
+ cont_sav = cont_lbl;
+ l1 = lbl_num++;
+ cont_lbl = lbl_num++;
+ brk_lbl = lbl_num++;
+ ilc_walk(n->u[0].child, 0, 0); /* e1; */
+ ilc_str(";");
+ ilc_lbl(l1); /* L1: */
+ n2 = n->u[1].child;
+ if (n2 != NULL)
+ ilc_cgoto(1, n2, brk_lbl); /* if (!(e2)) goto L2; */
+ ilc_walk(n->u[3].child, 0, 0); /* s */
+ ilc_lbl(cont_lbl);
+ ilc_walk(n->u[2].child, 0, 0); /* e3; */
+ ilc_str(";");
+ ilc_goto(l1); /* goto L1 */
+ ilc_lbl(brk_lbl); /* L2: */
+ brk_lbl = brk_sav;
+ cont_lbl = cont_sav;
+ break;
+ case Def:
+ ilc_cnv(n->u[0].child, n->u[1].child, n->u[2].child,
+ n->u[3].child);
+ break;
+ }
+ break;
+ }
+ }
+
+/*
+ * ilc_cnv - produce code for a cnv: or def: statement.
+ */
+static void ilc_cnv(cnv_typ, src, dflt, dest)
+struct node *cnv_typ;
+struct node *src;
+struct node *dflt;
+struct node *dest;
+ {
+ int dflt_to_ptr;
+ int typcd;
+
+ /*
+ * Get the name of the conversion routine for the given type
+ * and determine whether the conversion routine needs a
+ * pointer to the default value (if there is one) rather
+ * the the value itself.
+ */
+ typcd = icn_typ(cnv_typ);
+ ilc_str(cnv_name(typcd, dflt, &dflt_to_ptr));
+ ilc_str("(");
+
+ /*
+ * If this is a conversion to a temporary string or cset, the
+ * conversion routine needs a temporary buffer in which to
+ * perform the conversion.
+ */
+ switch (typcd) {
+ case TypTStr:
+ new_ilc(ILC_SBuf);
+ ilc_str(", ");
+ break;
+ case TypTCset:
+ new_ilc(ILC_CBuf);
+ ilc_str(", ");
+ break;
+ }
+
+ /*
+ * Produce code for the source expression.
+ */
+ ilc_str("&(");
+ ilc_walk(src, 0, 0);
+ ilc_str("), ");
+
+ /*
+ * Produce code for the default expression, if there is one.
+ */
+ if (dflt != NULL) {
+ if (dflt_to_ptr)
+ ilc_str("&(");
+ ilc_walk(dflt, 0, 0);
+ if (dflt_to_ptr)
+ ilc_str("), ");
+ else
+ ilc_str(", ");
+ }
+
+ /*
+ * Produce code for the destination expression.
+ */
+ ilc_str("&(");
+ ilc_walk(dest, 1, 0);
+ ilc_str("))");
+ }
+
+/*
+ * ilc_ret - produce in-line code for suspend/return statement.
+ */
+static void ilc_ret(t, ilc_typ, n)
+struct token *t;
+int ilc_typ;
+struct node *n;
+ {
+ struct node *caller;
+ struct node *args;
+ int typcd;
+
+ insert_nl = 1;
+ line_ref = NULL;
+ new_ilc(ilc_typ);
+
+ if (n->nd_id == SymNd && n->u[0].sym->id_type == RsltLoc) {
+ /*
+ * return/suspend result;
+ */
+ ilc_cur->n = RetNone;
+ return;
+ }
+
+ if (n->nd_id == PrefxNd && n->tok != NULL) {
+ switch (n->tok->tok_id) {
+ case C_Integer:
+ /*
+ * return/suspend C_integer <expr>;
+ */
+ ilc_cur->n = TypCInt;
+ ilc_cur->code[0] = sep_ilc(NULL, n->u[0].child, NULL);
+ chkabsret(t, int_typ);
+ return;
+ case C_Double:
+ /*
+ * return/suspend C_double <expr>;
+ */
+ ilc_cur->n = TypCDbl;
+ ilc_cur->code[0] = sep_ilc(NULL, n->u[0].child, NULL);
+ chkabsret(t, real_typ);
+ return;
+ case C_String:
+ /*
+ * return/suspend C_string <expr>;
+ */
+ ilc_cur->n = TypCStr;
+ ilc_cur->code[0] = sep_ilc(NULL, n->u[0].child, NULL);
+ chkabsret(t, str_typ);
+ return;
+ }
+ }
+ else if (n->nd_id == BinryNd && n->tok->tok_id == ')') {
+ /*
+ * Return value is in form of function call, see if it is really
+ * a descriptor constructor.
+ */
+ caller = n->u[0].child;
+ args = n->u[1].child;
+ if (caller->nd_id == SymNd) {
+ switch (caller->tok->tok_id) {
+ case IconType:
+ typcd = caller->u[0].sym->u.typ_indx;
+ ilc_cur->n = typcd;
+ switch (icontypes[typcd].rtl_ret) {
+ case TRetBlkP:
+ case TRetDescP:
+ case TRetCharP:
+ case TRetCInt:
+ /*
+ * return/suspend <type>(<value>);
+ */
+ ilc_cur->code[0] = sep_ilc(NULL, args, NULL);
+ break;
+ case TRetSpcl:
+ if (typcd == str_typ) {
+ /*
+ * return/suspend string(<len>, <char-pntr>);
+ */
+ ilc_cur->code[0] = sep_ilc(NULL, args->u[0].child,NULL);
+ ilc_cur->code[1] = sep_ilc(NULL, args->u[1].child,NULL);
+ }
+ else if (typcd == stv_typ) {
+ /*
+ * return/suspend tvsubs(<desc-pntr>, <start>, <len>);
+ */
+ ilc_cur->n = stv_typ;
+ ilc_cur->code[0] = sep_ilc(NULL,
+ args->u[0].child->u[0].child, NULL);
+ ilc_cur->code[1] = sep_ilc(NULL,
+ args->u[0].child->u[1].child, NULL);
+ ilc_cur->code[2] = sep_ilc(NULL, args->u[1].child,
+ NULL);
+ chkabsret(t, stv_typ);
+ }
+ break;
+ }
+ chkabsret(t, typcd);
+ return;
+ case Named_var:
+ /*
+ * return/suspend named_var(<desc-pntr>);
+ */
+ ilc_cur->n = RetNVar;
+ ilc_cur->code[0] = sep_ilc(NULL, args, NULL);
+ chkabsret(t, TypVar);
+ return;
+ case Struct_var:
+ /*
+ * return/suspend struct_var(<desc-pntr>, <block_pntr>);
+ */
+ ilc_cur->n = RetSVar;
+ ilc_cur->code[0] = sep_ilc(NULL, args->u[0].child, NULL);
+ ilc_cur->code[1] = sep_ilc(NULL, args->u[1].child, NULL);
+ chkabsret(t, TypVar);
+ return;
+ }
+ }
+ }
+
+ /*
+ * If it is not one of the special returns, it is just a return of
+ * a descriptor.
+ */
+ ilc_cur->n = RetDesc;
+ ilc_cur->code[0] = sep_ilc(NULL, n, NULL);
+ chkabsret(t, SomeType);
+ }
+
+/*
+ * ilc_goto - produce in-line C code for a goto to a numbered label.
+ */
+static void ilc_goto(lbl)
+word lbl;
+ {
+ insert_nl = 1;
+ new_ilc(ILC_Goto);
+ ilc_cur->n = lbl;
+ insert_nl = 1;
+ line_ref = NULL;
+ }
+
+/*
+ * ilc_cgoto - produce in-line C code for a conditional goto to a numbered
+ * label. The condition may be negated.
+ */
+static void ilc_cgoto(neg, cond, lbl)
+int neg;
+struct node *cond;
+word lbl;
+ {
+ insert_nl = 1;
+ line_ref = NULL;
+ new_ilc(ILC_CGto);
+ if (neg)
+ ilc_cur->code[0] = sep_ilc("!(", cond, ")");
+ else
+ ilc_cur->code[0] = sep_ilc(NULL, cond, NULL);
+ ilc_cur->n = lbl;
+ insert_nl = 1;
+ line_ref = NULL;
+ }
+
+/*
+ * ilc_lbl - produce in-line C code for a numbered label.
+ */
+static void ilc_lbl(lbl)
+word lbl;
+ {
+ insert_nl = 1;
+ new_ilc(ILC_Lbl);
+ ilc_cur->n = lbl;
+ insert_nl = 1;
+ line_ref = NULL;
+ }
+#endif /* Rttx */
+
+/*
+ * chkabsret - make sure a previous abstract return statement
+ * was encountered and that it is consistent with this return,
+ * suspend, or fail.
+ */
+void chkabsret(tok, ret_typ)
+struct token *tok;
+int ret_typ;
+ {
+ if (abs_ret == NoAbstr)
+ errt2(tok, tok->image, " with no preceding abstract return");
+
+ /*
+ * We only check for type consistency when it is easy, otherwise
+ * we don't bother.
+ */
+ if (abs_ret == SomeType || ret_typ == SomeType || abs_ret == TypAny)
+ return;
+
+ /*
+ * Some return types match the generic "variable" type.
+ */
+ if (abs_ret == TypVar && ret_typ >= 0 && icontypes[ret_typ].deref != DrfNone)
+ return;
+
+ /*
+ * Otherwise the abstract return must match the real one.
+ */
+ if (abs_ret != ret_typ)
+ errt2(tok, tok->image, " is inconsistent with abstract return");
+ }
+
+/*
+ * just_type - strip non-type information from a type-qualifier list. Print
+ * it in the output file and if ilc is set, produce in-line C code.
+ */
+void just_type(typ, indent, ilc)
+struct node *typ;
+int indent;
+int ilc;
+ {
+ if (typ->nd_id == LstNd) {
+ /*
+ * Simple list of type-qualifier elements - concatenate them.
+ */
+ just_type(typ->u[0].child, indent, ilc);
+ just_type(typ->u[1].child, indent, ilc);
+ }
+ else if (typ->nd_id == PrimryNd) {
+ switch (typ->tok->tok_id) {
+ case Typedef:
+ case Extern:
+ case Static:
+ case Auto:
+ case TokRegister:
+ case Const:
+ case Volatile:
+ return; /* Don't output these declaration elements */
+ default:
+ c_walk(typ, indent, 0);
+ #ifndef Rttx
+ if (ilc)
+ ilc_walk(typ, 0, 0);
+ #endif /* Rttx */
+ }
+ }
+ else {
+ c_walk(typ, indent, 0);
+ #ifndef Rttx
+ if (ilc)
+ ilc_walk(typ, 0, 0);
+ #endif /* Rttx */
+ }
+ }
diff --git a/src/rtt/rttinlin.c b/src/rtt/rttinlin.c
new file mode 100644
index 0000000..660c604
--- /dev/null
+++ b/src/rtt/rttinlin.c
@@ -0,0 +1,1950 @@
+/*
+ * rttinlin.c contains routines which produce the in-line version of an
+ * operation and put it in the data base.
+ */
+#include "rtt.h"
+
+/*
+ * prototypes for static functions.
+ */
+static struct il_code *abstrcomp (struct node *n, int indx_stor,
+ int chng_stor, int escapes);
+static void abstrsnty (struct token *t, int typcd,
+ int indx_stor, int chng_stor);
+static int body_anlz (struct node *n, int *does_break,
+ int may_mod, int const_cast, int all);
+static struct il_code *body_fnc (struct node *n);
+static void chkrettyp (struct node *n);
+static void chng_ploc (int typcd, struct node *src);
+static void cnt_bufs (struct node *cnv_typ);
+static struct il_code *il_walk (struct node *n);
+static struct il_code *il_var (struct node *n);
+static int is_addr (struct node *dcltor, int modifier);
+static void lcl_tend (struct node *n);
+static int mrg_abstr (int sum, int typ);
+static int strct_typ (struct node *typ, int *is_reg);
+
+static int body_ret; /* RetInt, RetDbl, and/or RetOther for current body */
+static int ret_flag; /* DoesFail, DoesRet, and/or DoesSusp for current body */
+int fnc_ret; /* RetInt, RetDbl, RetNoVal, or RetSig for current func */
+
+#ifndef Rttx
+
+/*
+ * body_prms is a list of symbol table entries for identifiers that must
+ * be passed as parameters to the function implementing the current
+ * body statement. The id_type of an identifier may be changed in the
+ * symbol table while the body function is being produced; for example,
+ * a tended descriptor is accessed through a parameter that is a pointer
+ * to a descriptor, rather than being accessed as an element of a descriptor
+ * array in a struct.
+ */
+struct var_lst {
+ struct sym_entry *sym;
+ int id_type; /* saved value of id_type from sym */
+ struct var_lst *next;
+ };
+struct var_lst *body_prms;
+int n_bdy_prms; /* number of entries in body_prms list */
+int rslt_loc; /* flag: function passed addr of result descriptor */
+
+char prfx3; /* 3rd prefix char; used for unique body func names */
+
+/*
+ * in_line - place in the data base in-line code for an operation and
+ * produce C functions for body statements.
+ */
+void in_line(n)
+struct node *n;
+ {
+ struct sym_entry *sym;
+ int i;
+ int nvars;
+ int ntend;
+
+ prfx3 = ' '; /* reset 3rd prefix char for body functions */
+
+ /*
+ * Set up the local symbol table in the data base for the in-line code.
+ * This symbol table has an array of entries for the tended variables
+ * in the declare statement, if there is one. Determine how large the
+ * array must be and create it.
+ */
+ ntend = 0;
+ for (sym = dcl_stk->tended; sym != NULL; sym = sym->u.tnd_var.next)
+ ++ntend;
+ if (ntend == 0)
+ cur_impl->tnds = NULL;
+ else
+ cur_impl->tnds = alloc(ntend * sizeof(struct tend_var));
+ cur_impl->ntnds = ntend;
+ i = 0;
+
+ /*
+ * Go back through the declarations and fill in the array for the
+ * tended part of the data base symbol table. Array entries contain
+ * an indication of the type of tended declaration, the C code to
+ * initialize the variable if there is any, and, for block pointer
+ * declarations, the type of block. rtt's symbol table is updated to
+ * contain the variable's offset into the data base's symbol table.
+ * Note that parameters are considered part of the data base's symbol
+ * table when computing the offset and il_indx initially contains
+ * their number.
+ */
+ for (sym = dcl_stk->tended; sym != NULL; sym = sym->u.tnd_var.next) {
+ cur_impl->tnds[i].var_type = sym->id_type;
+ cur_impl->tnds[i].init = inlin_c(sym->u.tnd_var.init, 0);
+ cur_impl->tnds[i].blk_name = sym->u.tnd_var.blk_name;
+ sym->il_indx = il_indx++;
+ ++i;
+ }
+
+ /*
+ * The data base's symbol table also has entries for non-tended
+ * variables from the declare statement. Each entry has the
+ * identifier for the variable and the declaration (redundantly
+ * including the identifier). Once again the offset for the data
+ * base symbol table is stored in rtt's symbol table.
+ */
+ nvars = -il_indx; /* pre-subtract preceding number of entries */
+ for (sym = decl_lst; sym != NULL; sym = sym->u.declare_var.next)
+ sym->il_indx = il_indx++;
+ nvars += il_indx; /* compute number of entries in this part of table */
+ cur_impl->nvars = nvars;
+ if (nvars > 0) {
+ cur_impl->vars = alloc(nvars * sizeof(struct ord_var));
+ i = 0;
+ for (sym = decl_lst; sym != NULL; sym = sym->u.declare_var.next) {
+ cur_impl->vars[i].name = sym->image;
+ cur_impl->vars[i].dcl = ilc_dcl(sym->u.declare_var.tqual,
+ sym->u.declare_var.dcltor, sym->u.declare_var.init);
+ ++i;
+ }
+ }
+
+ abs_ret = NoAbstr; /* abstract clause not encountered yet */
+ cur_impl->in_line = il_walk(n); /* produce in-line code for operation */
+ }
+
+/*
+ * il_walk - walk the syntax tree producing in-line code.
+ */
+static struct il_code *il_walk(n)
+struct node *n;
+ {
+ struct token *t;
+ struct node *n1;
+ struct node *n2;
+ struct il_code *il;
+ struct il_code *il1;
+ struct sym_entry *sym;
+ struct init_tend *tnd;
+ int dummy_int;
+ int ntend;
+ int typcd;
+
+ if (n == NULL)
+ return NULL;
+
+ t = n->tok;
+
+ switch (n->nd_id) {
+ case PrefxNd:
+ switch (t->tok_id) {
+ case '{':
+ /*
+ * RTL code: { <actions> }
+ */
+ il = il_walk(n->u[0].child);
+ break;
+ case '!':
+ /*
+ * RTL type-checking and conversions: ! <simple-type-check>
+ */
+ il = new_il(IL_Bang, 1);
+ il->u[0].fld = il_walk(n->u[0].child);
+ break;
+ case Body:
+ /*
+ * RTL code: body { <c-code> }
+ */
+ il = body_fnc(n);
+ break;
+ case Inline:
+ /*
+ * RTL code: inline { <c-code> }
+ *
+ * An in-line code "block" in the data base starts off
+ * with an indication of whether execution falls through
+ * the code and a list of tended descriptors needed by the
+ * in-line C code. The list indicates the kind of tended
+ * descriptor. The list is determined by walking to the
+ * syntax tree for the C code; tend_lst points to its
+ * beginning. The last item in the block is the C code itself.
+ */
+ free_tend();
+ lcl_tend(n);
+ if (tend_lst == NULL)
+ ntend = 0;
+ else
+ ntend = tend_lst->t_indx + 1;
+ il = new_il(IL_Block, 3 + ntend);
+ /*
+ * Only need "fall through" info from body_anlz().
+ */
+ il->u[0].n = body_anlz(n->u[0].child, &dummy_int, 0, 0, 0);
+ il->u[1].n = ntend;
+ for (tnd = tend_lst; tnd != NULL; tnd = tnd->next)
+ il->u[2 + tnd->t_indx].n = tnd->init_typ;
+ il->u[ntend + 2].c_cd = inlin_c(n->u[0].child, 0);
+ if (!il->u[0].n)
+ clr_prmloc(); /* execution does not continue */
+ break;
+ }
+ break;
+ case BinryNd:
+ switch (t->tok_id) {
+ case Runerr:
+ /*
+ * RTL code: runerr( <message-number> )
+ * runerr( <message-number>, <descriptor> )
+ */
+ if (n->u[1].child == NULL)
+ il = new_il(IL_Err1, 1);
+ else {
+ il = new_il(IL_Err2, 2);
+ il->u[1].fld = il_var(n->u[1].child);
+ }
+ il->u[0].n = atol(n->u[0].child->tok->image);
+ /*
+ * Execution cannot continue on this execution path.
+ */
+ clr_prmloc();
+ break;
+ case And:
+ /*
+ * RTL type-checking and conversions:
+ * <type-check> && <type_check>
+ */
+ il = new_il(IL_And, 2);
+ il->u[0].fld = il_walk(n->u[0].child);
+ il->u[1].fld = il_walk(n->u[1].child);
+ break;
+ case Is:
+ /*
+ * RTL type-checking and conversions:
+ * is: <icon-type> ( <variable> )
+ */
+ il = new_il(IL_Is, 2);
+ il->u[0].n = icn_typ(n->u[0].child);
+ il->u[1].fld = il_var(n->u[1].child);
+ break;
+ }
+ break;
+ case ConCatNd:
+ /*
+ * "Glue" for two constructs.
+ */
+ il = new_il(IL_Lst, 2);
+ il->u[0].fld = il_walk(n->u[0].child);
+ il->u[1].fld = il_walk(n->u[1].child);
+ break;
+ case AbstrNd:
+ /*
+ * RTL code: abstract { <type-computations> }
+ *
+ * Remember the return statement if there is one. It is used for
+ * type checking when types are easily determined.
+ */
+ il = new_il(IL_Abstr, 2);
+ il->u[0].fld = abstrcomp(n->u[0].child, 0, 0, 0);
+ il1 = abstrcomp(n->u[1].child, 0, 0, 1);
+ il->u[1].fld = il1;
+ if (il1 != NULL) {
+ if (abs_ret != NoAbstr)
+ errt1(t,"only one abstract return may be on any execution path");
+ if (il1->il_type == IL_IcnTyp || il1->il_type == IL_New)
+ abs_ret = il1->u[0].n;
+ else
+ abs_ret = SomeType;
+ }
+ break;
+ case TrnryNd:
+ switch (t->tok_id) {
+ case If: {
+ /*
+ * RTL code for "if" statements:
+ * if <type-check> then <action>
+ * if <type-check> then <action> else <action>
+ *
+ * <type-check> may include parameter conversions that create
+ * new scoping. It is necessary to keep track of parameter
+ * types and locations along success and failure paths of
+ * these conversions. The "then" and "else" actions may
+ * also establish new scopes (if a parameter is used within
+ * a overlapping scopes that conflict, it has already been
+ * detected).
+ *
+ * The "then" and "else" actions may contain abstract return
+ * statements. The types of these must be "merged" in case
+ * type checking must be done on real return or suspend
+ * statements following the "if".
+ */
+ struct parminfo *then_prms = NULL;
+ struct parminfo *else_prms;
+ struct node *cond;
+ struct node *else_nd;
+ int sav_absret;
+ int new_absret;
+
+ /*
+ * Save the current parameter locations. These are in
+ * effect on the failure path of any type conversions
+ * in the condition of the "if". Also remember any
+ * information from abstract returns.
+ */
+ else_prms = new_prmloc();
+ sv_prmloc(else_prms);
+ sav_absret = new_absret = abs_ret;
+
+ cond = n->u[0].child;
+ else_nd = n->u[2].child;
+
+ if (else_nd == NULL)
+ il = new_il(IL_If1, 2);
+ else
+ il = new_il(IL_If2, 3);
+ il->u[0].fld = il_walk(cond);
+ /*
+ * If the condition is negated, the failure path is to the "then"
+ * and the success path is to the "else".
+ */
+ if (cond->nd_id == PrefxNd && cond->tok->tok_id == '!') {
+ then_prms = else_prms;
+ else_prms = new_prmloc();
+ sv_prmloc(else_prms);
+ ld_prmloc(then_prms);
+ }
+ il->u[1].fld = il_walk(n->u[1].child); /* then ... */
+ if (else_nd == NULL) {
+ mrg_prmloc(else_prms);
+ ld_prmloc(else_prms);
+ }
+ else {
+ if (then_prms == NULL)
+ then_prms = new_prmloc();
+ sv_prmloc(then_prms);
+ ld_prmloc(else_prms);
+ new_absret = mrg_abstr(new_absret, abs_ret);
+ abs_ret = sav_absret;
+ il->u[2].fld = il_walk(else_nd);
+ mrg_prmloc(then_prms);
+ ld_prmloc(then_prms);
+ }
+ abs_ret = mrg_abstr(new_absret, abs_ret);
+ if (then_prms != NULL)
+ free((char *)then_prms);
+ if (else_prms != NULL)
+ free((char *)else_prms);
+ }
+ break;
+ case Len_case: {
+ /*
+ * RTL code:
+ * len_case <variable> of {
+ * <integer>: <action>
+ * ...
+ * default: <action>
+ * }
+ */
+ struct parminfo *strt_prms;
+ struct parminfo *end_prms;
+ int n_cases;
+ int indx;
+ int sav_absret;
+ int new_absret;
+
+ /*
+ * A case may contain parameter conversions that create new
+ * scopes. Remember the parameter locations at the start
+ * of the len_case statement. Also remember information
+ * about abstract type returns.
+ */
+ strt_prms = new_prmloc();
+ sv_prmloc(strt_prms);
+ end_prms = new_prmloc();
+ sav_absret = new_absret = abs_ret;
+
+ /*
+ * Count the number of cases; there is at least one.
+ */
+ n_cases = 1;
+ for (n1 = n->u[1].child; n1->nd_id == ConCatNd;
+ n1 = n1->u[0].child)
+ ++n_cases;
+
+ /*
+ * The data base entry has one slot for the number of cases,
+ * one for the default clause, and two for each case. A
+ * case includes a selection integer and an action.
+ */
+ il = new_il(IL_Lcase, 2 + 2 * n_cases);
+ il->u[0].n = n_cases;
+
+ /*
+ * Go through the cases, adding them to the data base entry.
+ * Merge resulting parameter locations and information
+ * about abstract type returns, then restore the starting
+ * information for the next case.
+ */
+ indx = 2 * n_cases;
+ for (n1 = n->u[1].child; n1->nd_id == ConCatNd;
+ n1 = n1->u[0].child) {
+ il->u[indx--].fld = il_walk(n1->u[1].child->u[0].child);
+ il->u[indx--].n = atol(n1->u[1].child->tok->image);
+ mrg_prmloc(end_prms);
+ ld_prmloc(strt_prms);
+ new_absret = mrg_abstr(new_absret, abs_ret);
+ abs_ret = sav_absret;
+ }
+ /*
+ * Last case.
+ */
+ il->u[indx--].fld = il_walk(n1->u[0].child);
+ il->u[indx].n = atol(n1->tok->image);
+ mrg_prmloc(end_prms);
+ ld_prmloc(strt_prms);
+ new_absret = mrg_abstr(new_absret, abs_ret);
+ abs_ret = sav_absret;
+ /*
+ * Default clause.
+ */
+ il->u[1 + 2 * n_cases].fld = il_walk(n->u[2].child);
+ mrg_prmloc(end_prms);
+ ld_prmloc(end_prms);
+ abs_ret = mrg_abstr(new_absret, abs_ret);
+ if (strt_prms != NULL)
+ free((char *)strt_prms);
+ if (end_prms != NULL)
+ free((char *)end_prms);
+ }
+ break;
+ case Type_case: {
+ /*
+ * RTL code:
+ * type_case <variable> of {
+ * <icon_type> : ... <icon_type> : <action>
+ * ...
+ * }
+ *
+ * last clause may be: default: <action>
+ */
+ struct node *sel;
+ struct parminfo *strt_prms;
+ struct parminfo *end_prms;
+ int *typ_vect;
+ int n_case;
+ int n_typ;
+ int n_fld;
+ int sav_absret;
+ int new_absret;
+
+ /*
+ * A case may contain parameter conversions that create new
+ * scopes. Remember the parameter locations at the start
+ * of the type_case statement. Also remember information
+ * about abstract type returns.
+ */
+ strt_prms = new_prmloc();
+ sv_prmloc(strt_prms);
+ end_prms = new_prmloc();
+ sav_absret = new_absret = abs_ret;
+
+ /*
+ * Count the number of cases.
+ */
+ n_case = 0;
+ for (n1 = n->u[1].child; n1 != NULL; n1 = n1->u[0].child)
+ ++n_case;
+
+ /*
+ * The data base entry has one slot for the variable whose
+ * type is being tested, one for the number cases, three
+ * for each case, and, if there is default clause, one
+ * for it. Each case includes the number of types selected
+ * by the case, a vectors of those types, and the action
+ * for the case.
+ */
+ if (n->u[2].child == NULL) {
+ il = new_il(IL_Tcase1, 3 * n_case + 2);
+ il->u[0].fld = il_var(n->u[0].child);
+ }
+ else {
+ /*
+ * There is a default clause.
+ */
+ il = new_il(IL_Tcase2, 3 * n_case + 3);
+ il->u[0].fld = il_var(n->u[0].child);
+ il->u[3 * n_case + 2].fld = il_walk(n->u[2].child);
+ mrg_prmloc(end_prms);
+ ld_prmloc(strt_prms);
+ }
+ il->u[1].n = n_case;
+
+ /*
+ * Go through the cases, adding them to the data base entry.
+ * Merge resulting parameter locations and information
+ * about abstract type returns, then restore the starting
+ * information for the next case.
+ */
+ n_fld = 2;
+ for (n1 = n->u[1].child; n1 != NULL; n1 = n1->u[0].child) {
+ /*
+ * Determine the number types selected by the case and
+ * put the types in a vector.
+ */
+ sel = n1->u[1].child;
+ n_typ = 0;
+ for (n2 = sel->u[0].child; n2 != NULL; n2 = n2->u[0].child)
+ n_typ++;
+ il->u[n_fld++].n = n_typ;
+ typ_vect = alloc(n_typ * sizeof(int));
+ il->u[n_fld++].vect = typ_vect;
+ n_typ = 0;
+ for (n2 = sel->u[0].child; n2 != NULL; n2 = n2->u[0].child)
+ typ_vect[n_typ++] = icn_typ(n2->u[1].child);
+ /*
+ * Add code for the case to the data base entry.
+ */
+ new_absret = mrg_abstr(new_absret, abs_ret);
+ abs_ret = sav_absret;
+ il->u[n_fld++].fld = il_walk(sel->u[1].child);
+ mrg_prmloc(end_prms);
+ ld_prmloc(strt_prms);
+ }
+ ld_prmloc(end_prms);
+ abs_ret = mrg_abstr(new_absret, abs_ret);
+ if (strt_prms != NULL)
+ free((char *)strt_prms);
+ if (end_prms != NULL)
+ free((char *)end_prms);
+ }
+ break;
+ case Cnv: {
+ /*
+ * RTL code: cnv: <type> ( <source> )
+ * cnv: <type> ( <source> , <destination> )
+ */
+ struct node *typ;
+ struct node *src;
+ struct node *dst;
+
+ typ = n->u[0].child;
+ src = n->u[1].child;
+ dst = n->u[2].child;
+ typcd = icn_typ(typ);
+ if (src->nd_id == SymNd)
+ sym = src->u[0].sym;
+ else if (src->nd_id == BinryNd)
+ sym = src->u[0].child->u[0].sym; /* subscripted variable */
+ else
+ errt2(src->tok, "undeclared identifier: ", src->tok->image);
+ if (sym->u.param_info.parm_mod) {
+ fprintf(stderr, "%s: file %s, line %d, warning: ",
+ progname, src->tok->fname, src->tok->line);
+ fprintf(stderr, "%s may be modified\n", sym->image);
+ fprintf(stderr,
+ "\ticonc does not handle conversion of modified parameter\n");
+ }
+
+
+ if (dst == NULL) {
+ il = new_il(IL_Cnv1, 2);
+ il->u[0].n = typcd;
+ il->u[1].fld = il_var(src);
+ /*
+ * This "in-place" conversion may create a new scope for the
+ * source parameter.
+ */
+ chng_ploc(typcd, src);
+ sym->u.param_info.parm_mod |= 1;
+ }
+ else {
+ il = new_il(IL_Cnv2, 3);
+ il->u[0].n = typcd;
+ il->u[1].fld = il_var(src);
+ il->u[2].c_cd = inlin_c(dst, 1);
+ }
+ }
+ break;
+ case Arith_case: {
+ /*
+ * arith_case (<variable>, <variable>) of {
+ * C_integer: <statement>
+ * integer: <statement>
+ * C_double: <statement>
+ * }
+ *
+ * This construct does type conversions and provides
+ * alternate execution paths. It is necessary to keep
+ * track of parameter locations.
+ */
+ struct node *var1;
+ struct node *var2;
+ struct parminfo *strt_prms;
+ struct parminfo *end_prms;
+ int sav_absret;
+ int new_absret;
+
+ strt_prms = new_prmloc();
+ sv_prmloc(strt_prms);
+ end_prms = new_prmloc();
+ sav_absret = new_absret = abs_ret;
+
+ var1 = n->u[0].child;
+ var2 = n->u[1].child;
+ n1 = n->u[2].child; /* contains actions for the 3 cases */
+
+ /*
+ * The data base entry has a slot for each of the two variables
+ * and one for each of the three cases.
+ */
+ il = new_il(IL_Acase, 5);
+ il->u[0].fld = il_var(var1);
+ il->u[1].fld = il_var(var2);
+
+ /*
+ * The "in-place" conversions to C_integer creates new scopes.
+ */
+ chng_ploc(TypECInt, var1);
+ chng_ploc(TypECInt, var2);
+ il->u[2].fld = il_walk(n1->u[0].child);
+ mrg_prmloc(end_prms);
+ new_absret = mrg_abstr(new_absret, abs_ret);
+
+
+ /*
+ * Conversion to integer (applicable to large integers only).
+ */
+ ld_prmloc(strt_prms);
+ abs_ret = sav_absret;
+ il->u[3].fld = il_walk(n1->u[1].child);
+ mrg_prmloc(end_prms);
+ new_absret = mrg_abstr(new_absret, abs_ret);
+
+ /*
+ * The "in-place" conversions to C_double creates new scopes.
+ */
+ ld_prmloc(strt_prms);
+ abs_ret = sav_absret;
+ chng_ploc(TypCDbl, var1);
+ chng_ploc(TypCDbl, var2);
+ il->u[4].fld = il_walk(n1->u[2].child);
+ mrg_prmloc(end_prms);
+
+ ld_prmloc(end_prms);
+ abs_ret = mrg_abstr(new_absret, abs_ret);
+ free((char *)strt_prms);
+ free((char *)end_prms);
+ }
+ break;
+ }
+ break;
+ case QuadNd: {
+ /*
+ * RTL code: def: <type> ( <source> , <default>)
+ * def: <type> ( <source> , <default> , <destination> )
+ */
+ struct node *typ;
+ struct node *src;
+ struct node *dflt;
+ struct node *dst;
+
+ typ = n->u[0].child;
+ src = n->u[1].child;
+ dflt = n->u[2].child;
+ dst = n->u[3].child;
+ typcd = icn_typ(typ);
+ if (dst == NULL) {
+ il = new_il(IL_Def1, 3);
+ il->u[0].n = typcd;
+ il->u[1].fld = il_var(src);
+ il->u[2].c_cd = inlin_c(dflt, 0);
+ /*
+ * This "in-place" conversion may create a new scope for the
+ * source parameter.
+ */
+ chng_ploc(typcd, src);
+ }
+ else {
+ il = new_il(IL_Def2, 4);
+ il->u[0].n = typcd;
+ il->u[1].fld = il_var(src);
+ il->u[2].c_cd = inlin_c(dflt, 0);
+ il->u[3].c_cd = inlin_c(dst, 1);
+ }
+ }
+ break;
+ }
+ return il;
+ }
+
+/*
+ * il_var - produce in-line code in the data base for varibel references.
+ * These include both simple identifiers and subscripted identifiers.
+ */
+static struct il_code *il_var(n)
+struct node *n;
+ {
+ struct il_code *il;
+
+ if (n->nd_id == SymNd) {
+ il = new_il(IL_Var, 1);
+ il->u[0].n = n->u[0].sym->il_indx; /* offset into data base sym. tab. */
+ }
+ else if (n->nd_id == BinryNd) {
+ /*
+ * A subscripted variable.
+ */
+ il = new_il(IL_Subscr, 2);
+ il->u[0].n = n->u[0].child->u[0].sym->il_indx; /* sym. tab. offset */
+ il->u[1].n = atol(n->u[1].child->tok->image); /* subscript */
+ }
+ else
+ errt2(n->tok, "undeclared identifier: ", n->tok->image);
+ return il;
+ }
+
+/*
+ * abstrcomp - produce data base code for RTL abstract type computations.
+ * In the process, do a few sanity checks where they are easy to do.
+ */
+static struct il_code *abstrcomp(n, indx_stor, chng_stor, escapes)
+struct node *n;
+int indx_stor;
+int chng_stor;
+int escapes;
+ {
+ struct token *t;
+ struct il_code *il;
+ int typcd;
+ int cmpntcd;
+
+ if (n == NULL)
+ return NULL;
+
+ t = n->tok;
+
+ switch (n->nd_id) {
+ case PrefxNd:
+ switch (t->tok_id) {
+ case TokType:
+ /*
+ * type( <variable> )
+ */
+ il = new_il(IL_VarTyp, 1);
+ il->u[0].fld = il_var(n->u[0].child);
+ break;
+ case Store:
+ /*
+ * store[ <type> ]
+ */
+ il = new_il(IL_Store, 1);
+ il->u[0].fld = abstrcomp(n->u[0].child, 1, 0, 0);
+ break;
+ }
+ break;
+ case PstfxNd:
+ /*
+ * <type> . <attrb_name>
+ */
+ il = new_il(IL_Compnt, 2);
+ il->u[0].fld = abstrcomp(n->u[0].child, 0, 0, 0);
+ switch (t->tok_id) {
+ case Component:
+ cmpntcd = sym_lkup(t->image)->u.typ_indx;
+ il->u[1].n = cmpntcd;
+ if (escapes && !typecompnt[cmpntcd].var)
+ errt3(t, typecompnt[cmpntcd].id,
+ " component is an internal reference type.\n",
+ "\t\tuse store[<type>.<component>] to \"dereference\" it");
+ break;
+ case All_fields:
+ il->u[1].n = CM_Fields;
+ break;
+ }
+ break;
+ case IcnTypNd:
+ /*
+ * <icon-type>
+ */
+ il = new_il(IL_IcnTyp, 1);
+ typcd = icn_typ(n->u[0].child);
+ abstrsnty(t, typcd, indx_stor, chng_stor);
+ il->u[0].n = typcd;
+ break;
+ case BinryNd:
+ switch (t->tok_id) {
+ case '=':
+ /*
+ * store[ <type> ] = <type>
+ */
+ il = new_il(IL_TpAsgn, 2);
+ il->u[0].fld = abstrcomp(n->u[0].child, 1, 1, 0);
+ il->u[1].fld = abstrcomp(n->u[1].child, 0, 0, 1);
+ break;
+ case Incr: /* union */
+ /*
+ * <type> ++ <type>
+ */
+ il = new_il(IL_Union, 2);
+ il->u[0].fld = abstrcomp(n->u[0].child, indx_stor, chng_stor,
+ escapes);
+ il->u[1].fld = abstrcomp(n->u[1].child, indx_stor, chng_stor,
+ escapes);
+ break;
+ case Intersect:
+ /*
+ * <type> ** <type>
+ */
+ il = new_il(IL_Inter, 2);
+ il->u[0].fld = abstrcomp(n->u[0].child, indx_stor, chng_stor,
+ escapes);
+ il->u[1].fld = abstrcomp(n->u[1].child, indx_stor, chng_stor,
+ escapes);
+ break;
+ case New: {
+ /*
+ * new <icon-type> ( <type> , ... )
+ */
+ struct node *typ;
+ struct node *args;
+ int nargs;
+
+ typ = n->u[0].child;
+ args = n->u[1].child;
+
+ typcd = icn_typ(typ);
+ abstrsnty(typ->tok, typcd, indx_stor, chng_stor);
+
+ /*
+ * Determine the number of arguments expected for this
+ * structure type.
+ */
+ if (typcd >= 0)
+ nargs = icontypes[typcd].num_comps;
+ else
+ nargs = 0;
+ if (nargs == 0)
+ errt2(typ->tok,typ->tok->image," is not an aggregate type.");
+
+ /*
+ * Create the "new" construct for the data base with its type
+ * code and arguments.
+ */
+ il = new_il(IL_New, 2 + nargs);
+ il->u[0].n = typcd;
+ il->u[1].n = nargs;
+ while (nargs > 1) {
+ if (args->nd_id == CommaNd)
+ il->u[1 + nargs].fld = abstrcomp(args->u[1].child, 0,0,1);
+ else
+ errt2(typ->tok, "too few arguments for new",
+ typ->tok->image);
+ args = args->u[0].child;
+ --nargs;
+ }
+ if (args->nd_id == CommaNd)
+ errt2(typ->tok, "too many arguments for new",typ->tok->image);
+ il->u[2].fld = abstrcomp(args, 0, 0, 1);
+ }
+ break;
+ }
+ break;
+ case ConCatNd:
+ /*
+ * "Glue" for several side effects.
+ */
+ il = new_il(IL_Lst, 2);
+ il->u[0].fld = abstrcomp(n->u[0].child, 0, 0, 0);
+ il->u[1].fld = abstrcomp(n->u[1].child, 0, 0, 0);
+ break;
+ }
+ return il;
+ }
+
+/*
+ * abstrsnty - do some sanity checks on how this type is being used in
+ * an abstract type computation.
+ */
+static void abstrsnty(t, typcd, indx_stor, chng_stor)
+struct token *t;
+int typcd;
+int indx_stor;
+int chng_stor;
+ {
+ struct icon_type *itp;
+
+ if ((typcd < 0) || (!indx_stor))
+ return;
+
+ itp = &icontypes[typcd];
+
+ /*
+ * This type is being used to index the store; make sure this it
+ * is a variable.
+ */
+ if (itp->deref == DrfNone)
+ errt2(t, itp->id, " is not a variable type");
+
+ if (chng_stor && itp->deref == DrfCnst)
+ errt2(t, itp->id, " has an associated type that may not be changed");
+ }
+
+/*
+ * body_anlz - walk the syntax tree for the C code in a body statment,
+ * analyzing the code to determine the interface needed by the C function
+ * which will implement it. Also determine how many buffers are needed.
+ * The value returned indicates whether it is possible for execution
+ * to fall through the the code.
+ */
+static int body_anlz(n, does_break, may_mod, const_cast, all)
+struct node *n; /* subtree being analyzed */
+int *does_break; /* output flag: subtree contains "break;" */
+int may_mod; /* input flag: this subtree might be assigned to */
+int const_cast; /* input flag: expression is cast to (const ...) */
+int all; /* input flag: need all information about operation */
+ {
+ struct token *t;
+ struct node *n1, *n2, *n3;
+ struct sym_entry *sym;
+ struct var_lst *var_ref;
+ int break_chk = 0;
+ int fall_thru;
+ static int may_brnchto;
+
+ if (n == NULL)
+ return 1;
+
+ t = n->tok;
+
+ switch (n->nd_id) {
+ case PrimryNd:
+ switch (t->tok_id) {
+ case Fail:
+ if (all)
+ ret_flag |= DoesFail;
+ return 0;
+ case Errorfail:
+ if (all)
+ ret_flag |= DoesEFail;
+ return 0;
+ case Break:
+ *does_break = 1;
+ return 0;
+ default: /* do nothing special */
+ return 1;
+ }
+ case PrefxNd:
+ switch (t->tok_id) {
+ case Return:
+ if (all) {
+ ret_flag |= DoesRet;
+ chkrettyp(n->u[0].child); /* check for returning of C value */
+ }
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ return 0;
+ case Suspend:
+ if (all) {
+ ret_flag |= DoesSusp;
+ chkrettyp(n->u[0].child); /* check for returning of C value */
+ }
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ return 1;
+ case '(':
+ /*
+ * parenthesized expression: pass along may_mod and const_cast.
+ */
+ return body_anlz(n->u[0].child, does_break, may_mod, const_cast,
+ all);
+ case Incr: /* ++ */
+ case Decr: /* -- */
+ /*
+ * Operand may be modified.
+ */
+ body_anlz(n->u[0].child, does_break, 1, 0, all);
+ return 1;
+ case '&':
+ /*
+ * Unless the address is cast to a const pointer, this
+ * might be a modifiying reference.
+ */
+ if (const_cast)
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ else
+ body_anlz(n->u[0].child, does_break, 1, 0, all);
+ return 1;
+ case Default:
+ fall_thru = body_anlz(n->u[0].child, does_break, 0, 0, all);
+ may_brnchto = 1;
+ return fall_thru;
+ case Goto:
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ return 0;
+ default: /* unary operations the need nothing special */
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ return 1;
+ }
+ case PstfxNd:
+ if (t->tok_id == ';')
+ return body_anlz(n->u[0].child, does_break, 0, 0, all);
+ else {
+ /*
+ * C expressions: <expr> ++
+ * <expr> --
+ *
+ * modify operand
+ */
+ return body_anlz(n->u[0].child, does_break, 1, 0, all);
+ }
+ case PreSpcNd:
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ return 1;
+ case SymNd:
+ /*
+ * This is an identifier.
+ */
+ if (!all)
+ return 1;
+ sym = n->u[0].sym;
+ if (sym->id_type == RsltLoc) {
+ /*
+ * Note that this body code explicitly references the result
+ * location of the operation.
+ */
+ rslt_loc = 1;
+ }
+ else if (sym->nest_lvl == 2) {
+ /*
+ * This variable is local to the operation, but declared outside
+ * the body. It must passed as a parameter to the function.
+ * See if it is in the parameter list yet.
+ */
+ if (!(sym->id_type & PrmMark)) {
+ sym->id_type |= PrmMark;
+ var_ref = NewStruct(var_lst);
+ var_ref->sym = sym;
+ var_ref->next = body_prms;
+ body_prms = var_ref;
+ ++n_bdy_prms;
+ }
+
+ /*
+ * Note if the variable might be assigned to.
+ */
+ sym->may_mod |= may_mod;
+ }
+ return 1;
+ case BinryNd:
+ switch (t->tok_id) {
+ case '[': /* subscripting */
+ case '.':
+ /*
+ * Assignments will modify left operand.
+ */
+ body_anlz(n->u[0].child, does_break, may_mod, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ return 1;
+ case '(':
+ /*
+ * ( <type> ) expr
+ */
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ /*
+ * See if the is a const cast.
+ */
+ for (n1 = n->u[0].child; n1->nd_id == LstNd; n1 = n1->u[0].child)
+ ;
+ if (n1->nd_id == PrimryNd && n1->tok->tok_id == Const)
+ body_anlz(n->u[1].child, does_break, 0, 1, all);
+ else
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ return 1;
+ case ')':
+ /*
+ * function call or declaration: <expr> ( <expr-list> )
+ */
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ return call_ret(n->u[0].child);
+ case ':':
+ case Case:
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ fall_thru = body_anlz(n->u[1].child, does_break, 0, 0, all);
+ may_brnchto = 1;
+ return fall_thru;
+ case Switch:
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ fall_thru = body_anlz(n->u[1].child, &break_chk, 0, 0, all);
+ return fall_thru | break_chk;
+ case While: {
+ struct node *n0 = n->u[0].child;
+ body_anlz(n0, does_break, 0, 0, all);
+ body_anlz(n->u[1].child, &break_chk, 0, 0, all);
+ /*
+ * check for an infinite loop, while (1) ... :
+ * a condition consisting of an IntConst with image=="1"
+ * and no breaks in the body.
+ */
+ if (n0->nd_id == PrimryNd && n0->tok->tok_id == IntConst &&
+ !strcmp(n0->tok->image,"1") && !break_chk)
+ return 0;
+ return 1;
+ }
+ case Do:
+ /*
+ * Any "break;" statements in the body do not effect
+ * outer loops so pass along a new flag for does_break.
+ */
+ body_anlz(n->u[0].child, &break_chk, 0, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ return 1;
+ case Runerr:
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ if (all)
+ ret_flag |= DoesEFail; /* possibler error failure */
+ return 0;
+ case '=':
+ case MultAsgn: /* *= */
+ case DivAsgn: /* /= */
+ case ModAsgn: /* %= */
+ case PlusAsgn: /* += */
+ case MinusAsgn: /* -= */
+ case LShftAsgn: /* <<= */
+ case RShftAsgn: /* >>= */
+ case AndAsgn: /* &= */
+ case XorAsgn: /* ^= */
+ case OrAsgn: /* |= */
+ /*
+ * Left operand is modified.
+ */
+ body_anlz(n->u[0].child, does_break, 1, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ return 1;
+ default: /* binary operations that need nothing special */
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ return 1;
+ }
+ case LstNd:
+ case StrDclNd:
+ /*
+ * Some declaration code.
+ */
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ return 1;
+ case ConCatNd:
+ /*
+ * <some-code> <some-code>
+ */
+ if (body_anlz(n->u[0].child, does_break, 0, 0, all))
+ return body_anlz(n->u[1].child, does_break, 0, 0, all);
+ else {
+ /*
+ * Cannot directly reach the second piece of code, see if
+ * it is possible to branch into it.
+ */
+ may_brnchto = 0;
+ fall_thru = body_anlz(n->u[1].child, does_break, 0, 0, all);
+ return may_brnchto & fall_thru;
+ }
+ case CommaNd:
+ /*
+ * <expr> , <expr>
+ */
+ fall_thru = body_anlz(n->u[0].child, does_break, 0, 0, all);
+ return fall_thru & body_anlz(n->u[1].child, does_break, 0, 0, all);
+ case CompNd:
+ /*
+ * Compound statement, look only at executable code.
+ *
+ * First traverse declaration list looking for initializers.
+ */
+ n1 = n->u[0].child;
+ while (n1 != NULL) {
+ if (n1->nd_id == LstNd) {
+ n2 = n1->u[1].child;
+ n1 = n1->u[0].child;
+ }
+ else {
+ n2 = n1;
+ n1 = NULL;
+ }
+
+ /*
+ * Get declarator list from declaration and traverse it.
+ */
+ n2 = n2->u[1].child;
+ while (n2 != NULL) {
+ if (n2->nd_id == CommaNd) {
+ n3 = n2->u[1].child;
+ n2 = n2->u[0].child;
+ }
+ else {
+ n3 = n2;
+ n2 = NULL;
+ }
+ if (n3->nd_id == BinryNd && n3->tok->tok_id == '=')
+ body_anlz(n3->u[1].child, does_break, 0, 0, all);
+ }
+ }
+
+ /*
+ * Check initializers on tended declarations.
+ */
+ for (sym = n->u[1].sym; sym != NULL; sym = sym->u.tnd_var.next)
+ body_anlz(sym->u.tnd_var.init, does_break, 0, 0, all);
+
+ /*
+ * Do the statement list.
+ */
+ return body_anlz(n->u[2].child, does_break, 0, 0, all);
+ case TrnryNd:
+ switch (t->tok_id) {
+ case Cnv:
+ /*
+ * extended C code: cnv: <type> ( <source> )
+ * cnv: <type> ( <source> , <destination> )
+ *
+ * For some conversions, buffers may have to be allocated.
+ * An explicit destination must be marked as modified.
+ */
+ if (all)
+ cnt_bufs(n->u[0].child);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ body_anlz(n->u[2].child, does_break, 1, 0, all);
+ return 1;
+ case If:
+ /*
+ * Execution falls through an if statement if it falls
+ * through either branch. A null "else" branch always
+ * falls through.
+ */
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ return body_anlz(n->u[1].child, does_break, 0, 0, all) |
+ body_anlz(n->u[2].child, does_break, 0, 0, all);
+ case Type_case:
+ /*
+ * type_case <expr> of { <section-list> }
+ * type_case <expr> of { <section-list> <default-clause> }
+ */
+
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ /*
+ * Loop through the case clauses.
+ */
+ fall_thru = 0;
+ for (n1 = n->u[1].child; n1 != NULL; n1 = n1->u[0].child) {
+ n2 = n1->u[1].child->u[1].child;
+ fall_thru |= body_anlz(n2, does_break, 0, 0, all);
+ }
+ return fall_thru | body_anlz(n->u[2].child, does_break, 0, 0,
+ all);
+ default: /* nothing special is needed for these ternary nodes */
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ body_anlz(n->u[2].child, does_break, 0, 0, all);
+ return 1;
+ }
+ case QuadNd:
+ if (t->tok_id == Def) {
+ /*
+ * extended C code:
+ * def: <type> ( <source> , <default> )
+ * def: <type> ( <source> , <default> , <destination> )
+ *
+ * For some conversions, buffers may have to be allocated.
+ * An explicit destination must be marked as modified.
+ */
+ if (all)
+ cnt_bufs(n->u[0].child);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ body_anlz(n->u[2].child, does_break, 0, 0, all);
+ body_anlz(n->u[3].child, does_break, 1, 0, all);
+ return 1;
+ }
+ else { /* for */
+ /*
+ * Check for an infinite loop: for (<expr>; ; <expr> ) ...
+ *
+ * No ending condition and no breaks in the body.
+ */
+ body_anlz(n->u[0].child, does_break, 0, 0, all);
+ body_anlz(n->u[1].child, does_break, 0, 0, all);
+ body_anlz(n->u[2].child, does_break, 0, 0, all);
+ body_anlz(n->u[3].child, &break_chk, 0, 0, all);
+ if (n->u[1].child == NULL && !break_chk)
+ return 0;
+ else
+ return 1;
+ }
+ }
+ err1("rtt internal error detected in function body_anlz()");
+ /* NOTREACHED */
+ return 0; /* avoid gcc warning */
+ }
+
+/*
+ * lcl_tend - allocate any tended variables needed in this body or inline
+ * statement.
+ */
+static void lcl_tend(n)
+struct node *n;
+ {
+ struct sym_entry *sym;
+
+ if (n == NULL)
+ return;
+
+ /*
+ * Walk the syntax tree until a block with declarations is found.
+ */
+ switch (n->nd_id) {
+ case PrefxNd:
+ case PstfxNd:
+ case PreSpcNd:
+ lcl_tend(n->u[0].child);
+ break;
+ case BinryNd:
+ case LstNd:
+ case ConCatNd:
+ case CommaNd:
+ case StrDclNd:
+ lcl_tend(n->u[0].child);
+ lcl_tend(n->u[1].child);
+ break;
+ case CompNd:
+ /*
+ * Allocate the tended variables in this block, noting that the
+ * level of nesting in this C function is one less than in the
+ * operation as a whole. Then mark the tended slots as free for
+ * use in the next block.
+ */
+ for (sym = n->u[1].sym; sym != NULL; sym = sym->u.tnd_var.next) {
+ sym->t_indx = alloc_tnd(sym->id_type, sym->u.tnd_var.init,
+ sym->nest_lvl - 1);
+ }
+ lcl_tend(n->u[2].child);
+ sym = n->u[1].sym;
+ if (sym != NULL)
+ unuse(tend_lst, sym->nest_lvl - 1);
+ break;
+ case TrnryNd:
+ lcl_tend(n->u[0].child);
+ lcl_tend(n->u[1].child);
+ lcl_tend(n->u[2].child);
+ break;
+ case QuadNd:
+ lcl_tend(n->u[0].child);
+ lcl_tend(n->u[1].child);
+ lcl_tend(n->u[2].child);
+ lcl_tend(n->u[3].child);
+ break;
+ }
+ }
+
+/*
+ * chkrettyp - check type of return to see if it is a C integer or a
+ * C double and make note of what is found.
+ */
+static void chkrettyp(n)
+struct node *n;
+ {
+ if (n->nd_id == PrefxNd && n->tok != NULL) {
+ switch (n->tok->tok_id) {
+ case C_Integer:
+ body_ret |= RetInt;
+ return;
+ case C_Double:
+ body_ret |= RetDbl;
+ return;
+ }
+ }
+ body_ret |= RetOther;
+ }
+
+/*
+ * body_fnc - produce the function which implements a body statement.
+ */
+static struct il_code *body_fnc(n)
+struct node *n;
+ {
+ struct node *compound;
+ struct node *dcls;
+ struct node *stmts;
+ struct var_lst *var_ref;
+ struct sym_entry *sym;
+ struct il_code *il;
+ int fall_thru; /* flag: control can fall through end of body */
+ int num_sigs; /* number of different signals function may return */
+ int bprm_indx;
+ int first;
+ int is_reg;
+ int strct;
+ int addr;
+ int by_ref;
+ int just_desc;
+ int dummy_int;
+ char buf1[6];
+
+ char *cname;
+ char buf[MaxPath];
+
+ /*
+ * Figure out the next character to use as the 3rd prefix for the
+ * name of this body function.
+ */
+ if (prfx3 == ' ')
+ prfx3 = '0';
+ else if (prfx3 == '9')
+ prfx3 = 'a';
+ else if (prfx3 == 'z')
+ errt2(n->tok, "more than 26 body statements in", cur_impl->name);
+ else
+ ++prfx3;
+
+ /*
+ * Free any old body parameters and tended locations.
+ */
+ while (body_prms != NULL) {
+ var_ref = body_prms;
+ body_prms = body_prms->next;
+ free((char *)var_ref);
+ }
+ free_tend();
+
+ /*
+ * Locate the outer declarations and statements from the body clause.
+ */
+ compound = n->u[0].child;
+ dcls = compound->u[0].child;
+ stmts = compound->u[2].child;
+
+ /*
+ * Analyze the body code to determine what the function's interface
+ * needs. body_anlz() does the work after the counters and flags
+ * are initialized.
+ */
+ n_tmp_str = 0; /* number of temporary string buffers neeeded */
+ n_tmp_cset = 0; /* number of temporary cset buffers needed */
+ nxt_sbuf = 0; /* next string buffer index; used in code generation */
+ nxt_cbuf = 0; /* next cset buffer index; used in code generation */
+ n_bdy_prms = 0; /* number of variables needed as body function parameters */
+ body_ret = 0; /* flag: C values and/or non-C values returned */
+ ret_flag = 0; /* flag: return, suspend, fail, error fail */
+ rslt_loc = 0; /* flag: body code needs operations result location */
+ fall_thru = body_anlz(compound, &dummy_int, 0, 0, 1);
+ lcl_tend(n); /* allocate tended descriptors needed */
+
+
+ /*
+ * Use the letter indicating operation type along with body function
+ * prefixes to construct the name of the file to hold the C code.
+ */
+ sprintf(buf1, "%c_%c%c%c", lc_letter, prfx1, prfx2, prfx3);
+ cname = salloc(makename(buf, SourceDir, buf1, CSuffix));
+ if ((out_file = fopen(cname, "w")) == NULL)
+ err2("cannot open output file ", cname);
+ else
+ addrmlst(cname, out_file);
+
+ prologue(); /* output standard comments and preprocessor directives */
+
+ /*
+ * If the function produces a unique signal, the function need not actually
+ * return it, and we may be able to use the return value for something
+ * else. See if this is true.
+ */
+ num_sigs = 0;
+ if (ret_flag & DoesRet)
+ ++num_sigs;
+ if (ret_flag & (DoesFail | DoesEFail))
+ ++num_sigs;
+ if (ret_flag & DoesSusp)
+ num_sigs += 2; /* something > 1 (success cont. may return anything) */
+ if (fall_thru) {
+ ret_flag |= DoesFThru;
+ ++num_sigs;
+ }
+
+ if (num_sigs > 1)
+ fnc_ret = RetSig; /* Function must return a signal */
+ else {
+ /*
+ * If the body returns a C_integer or a C_double, we can make the
+ * function directly return the C value and the compiler can decide
+ * whether to construct a descriptor.
+ */
+ if (body_ret == RetInt || body_ret == RetDbl)
+ fnc_ret = body_ret;
+ else
+ fnc_ret = RetNoVal; /* Function returns nothing directly */
+ }
+
+ /*
+ * Decide whether the function needs to to be passed an explicit result
+ * location (the case where "result" is explicitly referenced is handled
+ * while analyzing the body). suspend always uses the result location.
+ * return uses the result location unless the function directly
+ * returns a C value.
+ */
+ if (ret_flag & DoesSusp)
+ rslt_loc = 1;
+ else if ((ret_flag & DoesRet) && (fnc_ret != RetInt && fnc_ret != RetDbl))
+ rslt_loc = 1;
+
+ /*
+ * The data base entry for the call to the body function has 8 slots
+ * for standard interface information and 2 slots for each parameter.
+ */
+ il = new_il(IL_Call, 8 + 2 * n_bdy_prms);
+ il->u[0].n = 0; /* reserved for internal use by compiler */
+ il->u[1].n = prfx3;
+ il->u[2].n = fnc_ret;
+ il->u[3].n = ret_flag;
+ il->u[4].n = rslt_loc;
+ il->u[5].n = 0; /* number of string buffers to pass in: set below */
+ il->u[6].n = 0; /* number of cset buffers to pass in: set below */
+ il->u[7].n = n_bdy_prms;
+ bprm_indx = 8;
+
+ /*
+ * Write the C function header for the body function.
+ */
+ switch (fnc_ret) {
+ case RetSig:
+ fprintf(out_file, "int ");
+ break;
+ case RetInt:
+ fprintf(out_file, "C_integer ");
+ break;
+ case RetDbl:
+ fprintf(out_file, "double ");
+ break;
+ case RetNoVal:
+ fprintf(out_file, "void ");
+ break;
+ }
+ fprintf(out_file, " %c%c%c%c_%s(", uc_letter, prfx1, prfx2, prfx3,
+ cur_impl->name);
+ fname = cname;
+ line = 7;
+
+ /*
+ * Write parameter list, first the parenthesized list of names. Start
+ * with names of RLT variables that must be passed in.
+ */
+ first = 1;
+ for (var_ref = body_prms; var_ref != NULL; var_ref = var_ref->next) {
+ sym = var_ref->sym;
+ sym->id_type &= ~PrmMark; /* unmark entry */
+ if (first)
+ first = 0;
+ else
+ prt_str(", ", IndentInc);
+ prt_str(sym->image, IndentInc);
+ }
+
+ if (fall_thru) {
+ /*
+ * We cannot allocate string and cset buffers locally, so any
+ * that are needed must be parameters.
+ */
+ if (n_tmp_str > 0) {
+ if (first)
+ first = 0;
+ else
+ prt_str(", ", IndentInc);
+ prt_str("r_sbuf", IndentInc);
+ }
+ if (n_tmp_cset > 0) {
+ if (first)
+ first = 0;
+ else
+ prt_str(", ", IndentInc);
+ prt_str("r_cbuf", IndentInc);
+ }
+ }
+
+ /*
+ * If the result location is needed it is passed as the next parameter.
+ */
+ if (rslt_loc) {
+ if (first)
+ first = 0;
+ else
+ prt_str(", ", IndentInc);
+ prt_str("r_rslt", IndentInc);
+ }
+
+ /*
+ * If a success continuation is needed, it goes last.
+ */
+ if (ret_flag & DoesSusp) {
+ if (!first)
+ prt_str(", ", IndentInc);
+ prt_str("r_s_cont", IndentInc);
+ }
+ prt_str(")", IndentInc);
+ ForceNl();
+
+ /*
+ * Go through the parameters to this function writing out declarations
+ * and filling in rest of data base entry. Start with RLT variables.
+ */
+ for (var_ref = body_prms; var_ref != NULL; var_ref = var_ref->next) {
+ /*
+ * Each parameters has two slots in the data base entry. One
+ * is the declaration for use by iconc in producing function
+ * prototypes. The other is the argument that must be passed as
+ * part of the call generated by iconc.
+ *
+ * Determine whether the parameter is passed by reference or by
+ * value (flag by_ref). Tended variables that refer to just the
+ * vword of a descriptor require special handling. They must
+ * be passed to the body function as a pointer to the entire
+ * descriptor and not just the vword. Within the function the
+ * parameter is then accessed as x->vword... This is indicated
+ * by the parameter flag just_desc.
+ */
+ sym = var_ref->sym;
+ var_ref->id_type = sym->id_type; /* save old id_type */
+ by_ref = 0;
+ just_desc = 0;
+ switch (sym->id_type) {
+ case TndDesc: /* tended struct descrip x */
+ by_ref = 1;
+ il->u[bprm_indx++].c_cd = simpl_dcl("dptr ", 0, sym);
+ break;
+ case TndStr: /* tended char *x */
+ case TndBlk: /* tended struct b_??? *x or tended union block *x */
+ by_ref = 1;
+ just_desc = 1;
+ il->u[bprm_indx++].c_cd = simpl_dcl("dptr ", 0, sym);
+ break;
+ case RtParm: /* undereferenced RTL parameter */
+ case DrfPrm: /* dereferenced RTL parameter */
+ switch (sym->u.param_info.cur_loc) {
+ case PrmTend: /* plain parameter: descriptor */
+ by_ref = 1;
+ il->u[bprm_indx++].c_cd = simpl_dcl("dptr ", 0, sym);
+ break;
+ case PrmCStr: /* parameter converted to a tended C string */
+ by_ref = 1;
+ just_desc = 1;
+ il->u[bprm_indx++].c_cd = simpl_dcl("dptr ", 0, sym);
+ break;
+ case PrmInt: /* parameter converted to a C integer */
+ sym->id_type = OtherDcl;
+ if (var_ref->sym->may_mod && fall_thru)
+ by_ref = 1;
+ il->u[bprm_indx++].c_cd = simpl_dcl("C_integer ", by_ref,
+ sym);
+ break;
+ case PrmDbl: /* parameter converted to a C double */
+ sym->id_type = OtherDcl;
+ if (var_ref->sym->may_mod && fall_thru)
+ by_ref = 1;
+ il->u[bprm_indx++].c_cd = simpl_dcl("double ", by_ref, sym);
+ break;
+ }
+ break;
+ case RtParm | VarPrm:
+ case DrfPrm | VarPrm:
+ /*
+ * Variable part of RTL parameter list: already descriptor pointer.
+ */
+ sym->id_type = OtherDcl;
+ il->u[bprm_indx++].c_cd = simpl_dcl("dptr ", 0, sym);
+ break;
+ case VArgLen:
+ /*
+ * Number of elements in variable part of RTL parameter list:
+ * integer but not a true variable.
+ */
+ sym->id_type = OtherDcl;
+ il->u[bprm_indx++].c_cd = simpl_dcl("int ", 0, sym);
+ break;
+ case OtherDcl:
+ is_reg = 0;
+ /*
+ * Pass by reference if it is a structure or union type (but
+ * not if it is a pointer to one) or if the variable is
+ * modified and it is possible to execute more code after the
+ * body. WARNING: crude assumptions are made for typedef
+ * types.
+ */
+ strct = strct_typ(sym->u.declare_var.tqual, &is_reg);
+ addr = is_addr(sym->u.declare_var.dcltor, '\0');
+ if ((strct && !addr) || (var_ref->sym->may_mod && fall_thru))
+ by_ref = 1;
+ if (is_reg && by_ref)
+ errt2(sym->u.declare_var.dcltor->u[1].child->tok, sym->image,
+ " may not be declared 'register'");
+
+ il->u[bprm_indx++].c_cd = parm_dcl(by_ref, sym);
+ break;
+ }
+
+ /*
+ * Determine what the iconc generated argument in a function
+ * call should look like.
+ */
+ il->u[bprm_indx++].c_cd = bdy_prm(by_ref, just_desc, sym,
+ var_ref->sym->may_mod);
+
+ /*
+ * If it a call-by-reference parameter, indicate that the level
+ * of indirection must be taken into account within the function
+ * body.
+ */
+ if (by_ref)
+ sym->id_type |= ByRef;
+ }
+
+ if (fall_thru) {
+ /*
+ * Write declarations for any needed buffer parameters.
+ */
+ if (n_tmp_str > 0) {
+ prt_str("char (*r_sbuf)[MaxCvtLen];", 0);
+ ForceNl();
+ }
+ if (n_tmp_cset > 0) {
+ prt_str("struct b_cset *r_cbuf;", 0);
+ ForceNl();
+ }
+ /*
+ * Indicate that buffers must be allocated by compiler and not
+ * within the function.
+ */
+ il->u[5].n = n_tmp_str;
+ il->u[6].n = n_tmp_cset;
+ n_tmp_str = 0;
+ n_tmp_cset = 0;
+ }
+
+ /*
+ * Write declarations for result location and success continuation
+ * parameters if they are needed.
+ */
+ if (rslt_loc) {
+ prt_str("dptr r_rslt;", 0);
+ ForceNl();
+ }
+ if (ret_flag & DoesSusp) {
+ prt_str("continuation r_s_cont;", 0);
+ ForceNl();
+ }
+
+ /*
+ * Output the code for the function including ordinary declaration,
+ * special declarations, and executable code.
+ */
+ prt_str("{", IndentInc);
+ ForceNl();
+ c_walk(dcls, IndentInc, 0);
+ spcl_dcls(NULL);
+ c_walk(stmts, IndentInc, 0);
+ ForceNl();
+ /*
+ * If it is possible for excution to fall through to the end of
+ * the body function, and it does so, return an A_FallThru signal.
+ */
+ if (fall_thru) {
+ if (tend_lst != NULL) {
+ prt_str("tend = tend->previous;", IndentInc);
+ ForceNl();
+ }
+ if (fnc_ret == RetSig) {
+ prt_str("return A_FallThru;", IndentInc);
+ ForceNl();
+ }
+ }
+ prt_str("}\n", IndentInc);
+ if (fclose(out_file) != 0)
+ err2("cannot close ", cname);
+ put_c_fl(cname, 1);
+
+ /*
+ * Restore the symbol table to its previous state. Note any parameters
+ * that were modified by the body code.
+ */
+ for (var_ref = body_prms; var_ref != NULL; var_ref = var_ref->next) {
+ sym = var_ref->sym;
+ sym->id_type = var_ref->id_type;
+ if (sym->id_type & DrfPrm)
+ sym->u.param_info.parm_mod |= sym->may_mod;
+ sym->may_mod = 0;
+ }
+
+ if (!fall_thru)
+ clr_prmloc();
+ return il;
+ }
+
+/*
+ * strct_typ - determine if the declaration may be for a structured type
+ * and look for register declarations.
+ */
+static int strct_typ(typ, is_reg)
+struct node *typ;
+int *is_reg;
+ {
+ if (typ->nd_id == LstNd) {
+ return strct_typ(typ->u[0].child, is_reg) |
+ strct_typ(typ->u[1].child, is_reg);
+ }
+ else if (typ->nd_id == PrimryNd) {
+ switch (typ->tok->tok_id) {
+ case Typedef:
+ case Extern:
+ errt2(typ->tok, "declare {...} should not contain ",
+ typ->tok->image);
+ case TokRegister:
+ *is_reg = 1;
+ return 0;
+ case TypeDefName:
+ if (strcmp(typ->tok->image, "word") == 0 ||
+ strcmp(typ->tok->image, "uword") == 0 ||
+ strcmp(typ->tok->image, "dptr") == 0)
+ return 0; /* assume non-structure type */
+ else
+ return 1; /* might be a structure (is not C_integer) */
+ default:
+ return 0;
+ }
+ }
+ else {
+ /*
+ * struct, union, or enum.
+ */
+ return 1;
+ }
+ }
+
+/*
+ * determine if the variable being declared evaluates to an address.
+ */
+static int is_addr(dcltor, modifier)
+struct node *dcltor;
+int modifier;
+ {
+ switch (dcltor->nd_id) {
+ case ConCatNd:
+ /*
+ * pointer?
+ */
+ if (dcltor->u[0].child != NULL)
+ modifier = '*';
+ return is_addr(dcltor->u[1].child, modifier);
+ case PrimryNd:
+ /*
+ * We have reached the name.
+ */
+ switch (modifier) {
+ case '\0':
+ return 0;
+ case '*':
+ case '[':
+ return 1;
+ case ')':
+ errt1(dcltor->tok,
+ "declare {...} should not contain a prototype");
+ }
+ case PrefxNd:
+ /*
+ * (...)
+ */
+ return is_addr(dcltor->u[0].child, modifier);
+ case BinryNd:
+ /*
+ * function or array.
+ */
+ return is_addr(dcltor->u[0].child, dcltor->tok->tok_id);
+ }
+ err1("rtt internal error detected in function is_addr()");
+ /* NOTREACHED */
+ return 0; /* avoid gcc warning */
+ }
+
+/*
+ * chgn_ploc - if this is an "in-place" conversion to a C value, change
+ * the "location" of the parameter being converted.
+ */
+static void chng_ploc(typcd, src)
+int typcd;
+struct node *src;
+ {
+ int loc;
+
+ /*
+ * Note, we know this is a valid conversion, because it got through
+ * pass 1.
+ */
+ loc = PrmTend;
+ switch (typcd) {
+ case TypCInt:
+ case TypECInt:
+ loc = PrmInt;
+ break;
+ case TypCDbl:
+ loc = PrmDbl;
+ break;
+ case TypCStr:
+ loc = PrmCStr;
+ break;
+ }
+ if (loc != PrmTend)
+ src->u[0].sym->u.param_info.cur_loc = loc;
+ }
+
+/*
+ * cnt_bufs - See if we need to allocate a string or cset buffer for
+ * this conversion.
+ */
+static void cnt_bufs(cnv_typ)
+struct node *cnv_typ;
+ {
+ if (cnv_typ->nd_id == PrimryNd)
+ switch (cnv_typ->tok->tok_id) {
+ case Tmp_string:
+ ++n_tmp_str;
+ break;
+ case Tmp_cset:
+ ++n_tmp_cset;
+ break;
+ }
+ }
+
+/*
+ * mrg_abstr - merge (join) types of abstract returns on two execution paths.
+ * The type lattice has three levels: NoAbstr is bottom, SomeType is top,
+ * and individual types form the middle level.
+ */
+static int mrg_abstr(sum, typ)
+int sum;
+int typ;
+ {
+ if (sum == NoAbstr)
+ return typ;
+ else if (typ == NoAbstr)
+ return sum;
+ else if (sum == typ)
+ return sum;
+ else
+ return SomeType;
+ }
+#endif /* Rttx */
diff --git a/src/rtt/rttlex.c b/src/rtt/rttlex.c
new file mode 100644
index 0000000..3e100bc
--- /dev/null
+++ b/src/rtt/rttlex.c
@@ -0,0 +1,356 @@
+/*
+ * This lexical analyzer uses the preprocessor to convert text into tokens.
+ * The lexical anayser discards white space, checks to see if identifiers
+ * are reserved words or typedef names, makes sure single characters
+ * are valid tokens, and converts preprocessor constants into the
+ * various C constants.
+ */
+#include "rtt.h"
+
+/*
+ * Prototype for static function.
+ */
+static int int_suffix (char *s);
+
+int lex_state = DfltLex;
+
+char *ident = "ident";
+
+/*
+ * Characters are used as token id's for single character tokens. The
+ * following table indicates which ones can be valid for RTL.
+ */
+
+#define GoodChar(c) ((c) < 127 && good_char[c])
+static int good_char[128] = {
+ 0 /* \000 */, 0 /* \001 */, 0 /* \002 */, 0 /* \003 */,
+ 0 /* \004 */, 0 /* \005 */, 0 /* \006 */, 0 /* \007 */,
+ 0 /* \b */, 0 /* \t */, 0 /* \n */, 0 /* \v */,
+ 0 /* \f */, 0 /* \r */, 0 /* \016 */, 0 /* \017 */,
+ 0 /* \020 */, 0 /* \021 */, 0 /* \022 */, 0 /* \023 */,
+ 0 /* \024 */, 0 /* \025 */, 0 /* \026 */, 0 /* \027 */,
+ 0 /* \030 */, 0 /* \031 */, 0 /* \032 */, 0 /* \e */,
+ 0 /* \034 */, 0 /* \035 */, 0 /* \036 */, 0 /* \037 */,
+ 0 /* */, 1 /* ! */, 0 /* \ */, 0 /* # */,
+ 0 /* $ */, 1 /* % */, 1 /* & */, 0 /* ' */,
+ 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
+ 1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
+ 0 /* 0 */, 0 /* 1 */, 0 /* 2 */, 0 /* 3 */,
+ 0 /* 4 */, 0 /* 5 */, 0 /* 6 */, 0 /* 7 */,
+ 0 /* 8 */, 0 /* 9 */, 1 /* : */, 1 /* ; */,
+ 1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
+ 0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
+ 0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
+ 0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
+ 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
+ 0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
+ 0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
+ 0 /* X */, 0 /* Y */, 0 /* Z */, 1 /* [ */,
+ 1 /* \\ */, 1 /* ] */, 1 /* ^ */, 0 /* _ */,
+ 0 /* ` */, 0 /* a */, 0 /* b */, 0 /* c */,
+ 0 /* d */, 0 /* e */, 0 /* f */, 0 /* g */,
+ 0 /* h */, 0 /* i */, 0 /* j */, 0 /* k */,
+ 0 /* l */, 0 /* m */, 0 /* n */, 0 /* o */,
+ 0 /* p */, 0 /* q */, 0 /* r */, 0 /* s */,
+ 0 /* t */, 0 /* u */, 0 /* v */, 0 /* w */,
+ 0 /* x */, 0 /* y */, 0 /* z */, 1 /* { */,
+ 1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* \d */
+ };
+
+/*
+ * init_lex - initialize lexical analyzer.
+ */
+void init_lex()
+ {
+ struct sym_entry *sym;
+ int i;
+ static int first_time = 1;
+
+ if (first_time) {
+ first_time = 0;
+ ident = spec_str(ident); /* install ident in string table */
+ /*
+ * install C keywords into the symbol table
+ */
+ sym_add(Auto, spec_str("auto"), OtherDcl, 0);
+ sym_add(Break, spec_str("break"), OtherDcl, 0);
+ sym_add(Case, spec_str("case"), OtherDcl, 0);
+ sym_add(TokChar, spec_str("char"), OtherDcl, 0);
+ sym_add(Const, spec_str("const"), OtherDcl, 0);
+ sym_add(Continue, spec_str("continue"), OtherDcl, 0);
+ sym_add(Default, spec_str("default"), OtherDcl, 0);
+ sym_add(Do, spec_str("do"), OtherDcl, 0);
+ sym_add(Doubl, spec_str("double"), OtherDcl, 0);
+ sym_add(Else, spec_str("else"), OtherDcl, 0);
+ sym_add(TokEnum, spec_str("enum"), OtherDcl, 0);
+ sym_add(Extern, spec_str("extern"), OtherDcl, 0);
+ sym_add(Float, spec_str("float"), OtherDcl, 0);
+ sym_add(For, spec_str("for"), OtherDcl, 0);
+ sym_add(Goto, spec_str("goto"), OtherDcl, 0);
+ sym_add(If, spec_str("if"), OtherDcl, 0);
+ sym_add(Int, spec_str("int"), OtherDcl, 0);
+ sym_add(TokLong, spec_str("long"), OtherDcl, 0);
+ sym_add(TokRegister, spec_str("register"), OtherDcl, 0);
+ sym_add(Return, spec_str("return"), OtherDcl, 0);
+ sym_add(TokShort, spec_str("short"), OtherDcl, 0);
+ sym_add(Signed, spec_str("signed"), OtherDcl, 0);
+ sym_add(Sizeof, spec_str("sizeof"), OtherDcl, 0);
+ sym_add(Static, spec_str("static"), OtherDcl, 0);
+ sym_add(Struct, spec_str("struct"), OtherDcl, 0);
+ sym_add(Switch, spec_str("switch"), OtherDcl, 0);
+ sym_add(Typedef, spec_str("typedef"), OtherDcl, 0);
+ sym_add(Union, spec_str("union"), OtherDcl, 0);
+ sym_add(Unsigned, spec_str("unsigned"), OtherDcl, 0);
+ sym_add(Void, spec_str("void"), OtherDcl, 0);
+ sym_add(Volatile, spec_str("volatile"), OtherDcl, 0);
+ sym_add(While, spec_str("while"), OtherDcl, 0);
+
+ /*
+ * Install keywords from run-time interface language.
+ */
+ sym_add(Abstract, spec_str("abstract"), OtherDcl, 0);
+ sym_add(All_fields, spec_str("all_fields"), OtherDcl, 0);
+ sym_add(Any_value, spec_str("any_value"), OtherDcl, 0);
+ sym_add(Arith_case, spec_str("arith_case"), OtherDcl, 0);
+ sym_add(Body, spec_str("body"), OtherDcl, 0);
+ sym_add(C_Double, spec_str("C_double"), OtherDcl, 0);
+ sym_add(C_Integer, spec_str("C_integer"), OtherDcl, 0);
+ sym_add(C_String, spec_str("C_string"), OtherDcl, 0);
+ sym_add(Cnv, spec_str("cnv"), OtherDcl, 0);
+ sym_add(Constant, spec_str("constant"), OtherDcl, 0);
+ sym_add(Declare, spec_str("declare"), OtherDcl, 0);
+ sym_add(Def, spec_str("def"), OtherDcl, 0);
+ sym_add(Empty_type, spec_str("empty_type"), OtherDcl, 0);
+ sym_add(End, spec_str("end"), OtherDcl, 0);
+ sym_add(Errorfail, spec_str("errorfail"), OtherDcl, 0);
+ sym_add(Exact, spec_str("exact"), OtherDcl, 0);
+ sym_add(Fail, spec_str("fail"), OtherDcl, 0);
+ sym_add(TokFunction, spec_str("function"), OtherDcl, 0);
+ sym_add(Inline, spec_str("inline"), OtherDcl, 0);
+ sym_add(Is, spec_str("is"), OtherDcl, 0);
+ sym_add(Keyword, spec_str("keyword"), OtherDcl, 0);
+ sym_add(Len_case, spec_str("len_case"), OtherDcl, 0);
+ sym_add(Named_var, spec_str("named_var"), OtherDcl, 0);
+ sym_add(New, spec_str("new"), OtherDcl, 0);
+ sym_add(Of, spec_str("of"), OtherDcl, 0);
+ sym_add(Operator, spec_str("operator"), OtherDcl, 0);
+ str_rslt = spec_str("result");
+ sym_add(Runerr, spec_str("runerr"), OtherDcl, 0);
+ sym_add(Store, spec_str("store"), OtherDcl, 0);
+ sym_add(Struct_var, spec_str("struct_var"), OtherDcl, 0);
+ sym_add(Suspend, spec_str("suspend"), OtherDcl, 0);
+ sym_add(Tended, spec_str("tended"), OtherDcl, 0);
+ sym_add(Then, spec_str("then"), OtherDcl, 0);
+ sym_add(Tmp_cset, spec_str("tmp_cset"), OtherDcl, 0);
+ sym_add(Tmp_string, spec_str("tmp_string"), OtherDcl, 0);
+ sym_add(TokType, spec_str("type"), OtherDcl, 0);
+ sym_add(Type_case, spec_str("type_case"), OtherDcl, 0);
+ sym_add(Underef, spec_str("underef"), OtherDcl, 0);
+ sym_add(Variable, spec_str("variable"), OtherDcl, 0);
+
+ for (i = 0; i < num_typs; ++i) {
+ icontypes[i].id = spec_str(icontypes[i].id);
+ sym = sym_add(IconType, icontypes[i].id, OtherDcl, 0);
+ sym->u.typ_indx = i;
+ }
+
+ for (i = 0; i < num_cmpnts; ++i) {
+ typecompnt[i].id = spec_str(typecompnt[i].id);
+ sym = sym_add(Component, typecompnt[i].id, OtherDcl, 0);
+ sym->u.typ_indx = i;
+ }
+ }
+ }
+
+/*
+ * int_suffix - we have reached the end of what seems to be an integer
+ * constant. check for a valid suffix.
+ */
+static int int_suffix(s)
+char *s;
+ {
+ int tok_id;
+
+ if (*s == 'u' || *s == 'U') {
+ ++s;
+ if (*s == 'l' || *s == 'L') {
+ ++s;
+ tok_id = ULIntConst; /* unsigned long */
+ }
+ else
+ tok_id = UIntConst; /* unsigned */
+ }
+ else if (*s == 'l' || *s == 'L') {
+ ++s;
+ if (*s == 'u' || *s == 'U') {
+ ++s;
+ tok_id = ULIntConst; /* unsigned long */
+ }
+ else
+ tok_id = LIntConst; /* long */
+ }
+ else
+ tok_id = IntConst; /* plain int */
+ if (*s != '\0')
+ errt2(yylval.t, "invalid integer constant: ", yylval.t->image);
+ return tok_id;
+ }
+
+/*
+ * yylex - lexical analyzer, called by yacc-generated parser.
+ */
+int yylex()
+ {
+ register char *s;
+ struct sym_entry *sym;
+ struct token *lk_ahead = NULL;
+ int is_float;
+ struct str_buf *sbuf;
+
+ /*
+ * See if the last call to yylex() left a token from looking ahead.
+ */
+ if (lk_ahead == NULL)
+ yylval.t = preproc();
+ else {
+ yylval.t = lk_ahead;
+ lk_ahead = NULL;
+ }
+
+ /*
+ * Skip white space, then check for end-of-input.
+ */
+ while (yylval.t != NULL && yylval.t->tok_id == WhiteSpace) {
+ free_t(yylval.t);
+ yylval.t = preproc();
+ }
+ if (yylval.t == NULL)
+ return 0;
+
+ /*
+ * The rtt recognizes ** as an operator in abstract type computations.
+ * The parsing context is indicated by lex_state.
+ */
+ if (lex_state == TypeComp && yylval.t->tok_id == '*') {
+ lk_ahead = preproc();
+ if (lk_ahead != NULL && lk_ahead->tok_id == '*') {
+ free_t(lk_ahead);
+ lk_ahead = NULL;
+ yylval.t->tok_id = Intersect;
+ yylval.t->image = spec_str("**");
+ }
+ }
+
+ /*
+ * Some tokens are passed along without change, but some need special
+ * processing: identifiers, numbers, PpKeep tokens, and single
+ * character tokens.
+ */
+ if (yylval.t->tok_id == Identifier) {
+ /*
+ * See if this is an identifier, a reserved word, or typedef name.
+ */
+ sym = sym_lkup(yylval.t->image);
+ if (sym != NULL)
+ yylval.t->tok_id = sym->tok_id;
+ }
+ else if (yylval.t->tok_id == PpNumber) {
+ /*
+ * Determine what kind of numeric constant this is.
+ */
+ s = yylval.t->image;
+ if (*s == '0' && (*++s == 'x' || *s == 'X')) {
+ /*
+ * Hex integer constant.
+ */
+ ++s;
+ while (isxdigit(*s))
+ ++s;
+ yylval.t->tok_id = int_suffix(s);
+ }
+ else {
+ is_float = 0;
+ while (isdigit(*s))
+ ++s;
+ if (*s == '.') {
+ is_float = 1;
+ ++s;
+ while (isdigit(*s))
+ ++s;
+ }
+ if (*s == 'e' || *s == 'E') {
+ is_float = 1;
+ ++s;
+ if (*s == '+' || *s == '-')
+ ++s;
+ while (isdigit(*s))
+ ++s;
+ }
+ if (is_float) {
+ switch (*s) {
+ case '\0':
+ yylval.t->tok_id = DblConst; /* double */
+ break;
+ case 'f': case 'F':
+ yylval.t->tok_id = FltConst; /* float */
+ break;
+ case 'l': case 'L':
+ yylval.t->tok_id = LDblConst; /* long double */
+ break;
+ default:
+ errt2(yylval.t, "invalid float constant: ", yylval.t->image);
+ }
+ }
+ else {
+ /*
+ * This appears to be an integer constant. If it starts
+ * with '0', it should be an octal constant.
+ */
+ if (yylval.t->image[0] == '0') {
+ s = yylval.t->image;
+ while (*s >= '0' && *s <= '7')
+ ++s;
+ }
+ yylval.t->tok_id = int_suffix(s);
+ }
+ }
+ }
+ else if (yylval.t->tok_id == PpKeep) {
+ /*
+ * This is a non-standard preprocessor directive that must be
+ * passed on to the output.
+ */
+ keepdir(yylval.t);
+ return yylex();
+ }
+ else if (lex_state == OpHead && yylval.t->tok_id != '}' &&
+ GoodChar((int)yylval.t->image[0])) {
+ /*
+ * This should be the operator symbol in the header of an operation
+ * declaration. Concatenate all operator symbols into one token
+ * of type OpSym.
+ */
+ sbuf = get_sbuf();
+ for (s = yylval.t->image; *s != '\0'; ++s)
+ AppChar(*sbuf, *s);
+ lk_ahead = preproc();
+ while (lk_ahead != NULL && GoodChar((int)lk_ahead->image[0])) {
+ for (s = lk_ahead->image; *s != '\0'; ++s)
+ AppChar(*sbuf, *s);
+ free_t(lk_ahead);
+ lk_ahead = preproc();
+ }
+ yylval.t->tok_id = OpSym;
+ yylval.t->image = str_install(sbuf);
+ rel_sbuf(sbuf);
+ }
+ else if (yylval.t->tok_id < 256) {
+ /*
+ * This is a one-character token, make sure it is valid.
+ */
+ if (!GoodChar(yylval.t->tok_id))
+ errt2(yylval.t, "invalid character: ", yylval.t->image);
+ }
+
+ return yylval.t->tok_id;
+ }
diff --git a/src/rtt/rttmain.c b/src/rtt/rttmain.c
new file mode 100644
index 0000000..2099c2f
--- /dev/null
+++ b/src/rtt/rttmain.c
@@ -0,0 +1,402 @@
+#include "rtt.h"
+
+/*
+ * prototypes for static functions.
+ */
+static void add_tdef (char *name);
+
+/*
+ * refpath is used to locate the standard include files for the Icon
+ * run-time system. If patchpath has been patched in the binary of rtt,
+ * the string that was patched in is used for refpath.
+ */
+char *refpath;
+char patchpath[MaxPath+18] = "%PatchStringHere->";
+
+static char *ostr = "+ECPD:I:U:d:cir:st:x";
+
+static char *options =
+ "[-E] [-C] [-P] [-Dname[=[text]]] [-Uname] [-Ipath] [-dfile]\n \
+[-rpath] [-tname] [-x] [files]";
+
+/*
+ * The relative path to grttin.h and rt.h depends on whether they are
+ * interpreted as relative to where rtt.exe is or where rtt.exe is
+ * invoked.
+ */
+ char *grttin_path = "../src/h/grttin.h";
+ char *rt_path = "../src/h/rt.h";
+
+/*
+ * Note: rtt presently does not process system include files. If this
+ * is needed, it may be necessary to add other options that set
+ * manifest constants in such include files. See pmain.c for the
+ * stand-alone preprocessor for examples of what's needed.
+ */
+
+char *progname = "rtt";
+char *compiler_def;
+FILE *out_file;
+char *inclname;
+int def_fnd;
+char *largeints = NULL;
+
+int iconx_flg = 0;
+int enable_out = 0;
+
+static char *curlst_nm = "rttcur.lst";
+static FILE *curlst;
+static char *cur_src;
+
+extern int line_cntrl;
+
+/*
+ * tdefnm is used to construct a list of identifiers that
+ * must be treated by rtt as typedef names.
+ */
+struct tdefnm {
+ char *name;
+ struct tdefnm *next;
+ };
+
+static char *dbname = "rt.db";
+static int pp_only = 0;
+static char *opt_lst;
+static char **opt_args;
+static char *in_header;
+static struct tdefnm *tdefnm_lst = NULL;
+
+/*
+ * getopt() variables
+ */
+extern int optind; /* index into parent argv vector */
+extern int optopt; /* character checked for validity */
+extern char *optarg; /* argument associated with option */
+
+int main(argc, argv)
+int argc;
+char **argv;
+ {
+ int c;
+ int nopts;
+ char buf[MaxPath]; /* file name construction buffer */
+ struct fileparts *fp;
+
+ /*
+ * See if the location of include files has been patched into the
+ * rtt executable.
+ */
+ if ((int)strlen(patchpath) > 18)
+ refpath = patchpath+18;
+ else
+ refpath = relfile(argv[0], "/../");
+
+ /*
+ * Initialize the string table and indicate that File must be treated
+ * as a typedef name.
+ */
+ init_str();
+ add_tdef("FILE");
+
+ /*
+ * By default, the spelling of white space in unimportant (it can
+ * only be significant with the -E option) and #line directives
+ * are required in the output.
+ */
+ whsp_image = NoSpelling;
+ line_cntrl = 1;
+
+ /*
+ * opt_lst and opt_args are the options and corresponding arguments
+ * that are passed along to the preprocessor initialization routine.
+ * Their number is at most the number of arguments to rtt.
+ */
+ opt_lst = alloc(argc);
+ opt_args = alloc(argc * sizeof (char *));
+ nopts = 0;
+
+ /*
+ * Process options.
+ */
+ while ((c = getopt(argc, argv, ostr)) != EOF)
+ switch (c) {
+ case 'E': /* run preprocessor only */
+ pp_only = 1;
+ if (whsp_image == NoSpelling)
+ whsp_image = NoComment;
+ break;
+ case 'C': /* retain spelling of white space, only effective with -E */
+ whsp_image = FullImage;
+ break;
+ case 'P': /* do not produce #line directives in output */
+ line_cntrl = 0;
+ break;
+ case 'd': /* -d name: name of data base */
+ dbname = optarg;
+ break;
+ case 'r': /* -r path: location of include files */
+ refpath = optarg;
+ break;
+ case 't': /* -t ident : treat ident as a typedef name */
+ add_tdef(optarg);
+ break;
+ case 'x': /* produce code for interpreter rather than compiler */
+ iconx_flg = 1;
+ break;
+
+ case 'D': /* define preprocessor symbol */
+ case 'I': /* path to search for preprocessor includes */
+ case 'U': /* undefine preprocessor symbol */
+ /*
+ * Save these options for the preprocessor initialization routine.
+ */
+ opt_lst[nopts] = c;
+ opt_args[nopts] = optarg;
+ ++nopts;
+ break;
+ default:
+ show_usage();
+ }
+
+ #ifdef Rttx
+ if (!iconx_flg) {
+ fprintf(stdout,
+ "rtt was compiled to only support the intepreter, use -x\n");
+ exit(EXIT_FAILURE);
+ }
+ #endif /* Rttx */
+
+ if (iconx_flg)
+ compiler_def = "#define COMPILER 0\n";
+ else
+ compiler_def = "#define COMPILER 1\n";
+ in_header = alloc(strlen(refpath) + strlen(grttin_path) + 1);
+ strcpy(in_header, refpath);
+ strcat(in_header, grttin_path);
+ inclname = alloc(strlen(refpath) + strlen(rt_path) + 1);
+ strcpy(inclname, refpath);
+ strcat(inclname, rt_path);
+
+ opt_lst[nopts] = '\0';
+
+ /*
+ * At least one file name must be given on the command line.
+ */
+ if (optind == argc)
+ show_usage();
+
+ /*
+ * When creating the compiler run-time system, rtt outputs a list
+ * of names of C files created, because most of the file names are
+ * not derived from the names of the input files.
+ */
+ if (!iconx_flg) {
+ curlst = fopen(curlst_nm, "w");
+ if (curlst == NULL)
+ err2("cannot open ", curlst_nm);
+ }
+
+ /*
+ * Unless the input is only being preprocessed, set up the in-memory data
+ * base (possibly loading it from a file).
+ */
+ if (!pp_only) {
+ fp = fparse(dbname);
+ if (*fp->ext == '\0')
+ dbname = salloc(makename(buf, SourceDir, dbname, DBSuffix));
+ else if (!smatch(fp->ext, DBSuffix))
+ err2("bad data base name:", dbname);
+ loaddb(dbname);
+ }
+
+ /*
+ * Scan file name arguments, and translate the files.
+ */
+ while (optind < argc) {
+ trans(argv[optind]);
+ optind++;
+ }
+
+ #ifndef Rttx
+ /*
+ * Unless the user just requested the preprocessor be run, we
+ * have created C files and updated the in-memory data base.
+ * If this is the compiler's run-time system, we must dump
+ * to data base to a file and create a list of all output files
+ * produced in all runs of rtt that created the data base.
+ */
+ if (!(pp_only || iconx_flg)) {
+ if (fclose(curlst) != 0)
+ err2("cannot close ", curlst_nm);
+ dumpdb(dbname);
+ full_lst("rttfull.lst");
+ }
+ #endif /* Rttx */
+
+ return EXIT_SUCCESS;
+ }
+
+/*
+ * trans - translate a source file.
+ */
+void trans(src_file)
+char *src_file;
+ {
+ char *cname;
+ char buf[MaxPath]; /* file name construction buffer */
+ char *buf_ptr;
+ char *s;
+ struct fileparts *fp;
+ struct tdefnm *td;
+ struct token *t;
+ static char *test_largeints = "#ifdef LargeInts\nyes\n#endif\n";
+ static int first_time = 1;
+
+ cur_src = src_file;
+
+ /*
+ * Read standard header file for preprocessor directives and
+ * typedefs, but don't write anything to output.
+ */
+ enable_out = 0;
+ init_preproc(in_header, opt_lst, opt_args);
+ str_src("<rtt initialization>", compiler_def, (int)strlen(compiler_def));
+ init_sym();
+ for (td = tdefnm_lst; td != NULL; td = td->next)
+ sym_add(TypeDefName, td->name, OtherDcl, 1);
+ init_lex();
+ yyparse();
+ if (first_time) {
+ first_time = 0;
+ /*
+ * Now that the standard include files have been processed, see if
+ * Largeints is defined and make sure it matches what's in the data base.
+ */
+ s = "NoLargeInts";
+ str_src("<rtt initialization>", test_largeints,
+ (int)strlen(test_largeints));
+ while ((t = preproc()) != NULL)
+ if (strcmp(t->image, "yes"))
+ s = "LargeInts";
+ if (largeints == NULL)
+ largeints = s;
+ else if (strcmp(largeints, s) != 0)
+ err2("header file definition of LargeInts/NoLargeInts does not match ",
+ dbname);
+ }
+ enable_out = 1;
+
+ /*
+ * Make sure we have a .r file or standard input.
+ */
+ if (strcmp(cur_src, "-") == 0) {
+ source("-"); /* tell preprocessor to read standard input */
+ cname = salloc(makename(buf, TargetDir, "stdin", CSuffix));
+ }
+ else {
+ fp = fparse(cur_src);
+ if (*fp->ext == '\0')
+ cur_src = salloc(makename(buf, SourceDir, cur_src, RttSuffix));
+ else if (!smatch(fp->ext, RttSuffix))
+ err2("unknown file suffix ", cur_src);
+ cur_src = spec_str(cur_src);
+
+ /*
+ * For the compiler, remove from the data base the list of
+ * files produced from this input file.
+ */
+ if (!iconx_flg)
+ clr_dpnd(cur_src);
+ source(cur_src); /* tell preprocessor to read source file */
+
+ /*
+ * For the interpreter prepend "x" to the file name for the .c file.
+ */
+ buf_ptr = buf;
+ if (iconx_flg)
+ *buf_ptr++ = 'x';
+ makename(buf_ptr, TargetDir, cur_src, CSuffix);
+ cname = salloc(buf);
+ }
+
+ if (pp_only)
+ output(stdout); /* invoke standard preprocessor output routine */
+ else {
+ /*
+ * For the compiler, non-RTL code is put in a file whose name
+ * is derived from input file name. The flag def_fnd indicates
+ * if anything interesting is put in the file.
+ */
+ def_fnd = 0;
+ if ((out_file = fopen(cname, "w")) == NULL)
+ err2("cannot open output file ", cname);
+ else
+ addrmlst(cname, out_file);
+ prologue(); /* output standard comments and preprocessor directives */
+ yyparse(); /* translate the input */
+ fprintf(out_file, "\n");
+ if (fclose(out_file) != 0)
+ err2("cannot close ", cname);
+
+ /*
+ * For the Compiler, note the name of the "primary" output file
+ * in the data base and list of created files.
+ */
+ if (!iconx_flg)
+ put_c_fl(cname, def_fnd);
+ }
+ }
+
+/*
+ * add_tdef - add identifier to list of typedef names.
+ */
+static void add_tdef(name)
+char *name;
+ {
+ struct tdefnm *td;
+
+ td = NewStruct(tdefnm);
+ td->name = spec_str(name);
+ td->next = tdefnm_lst;
+ tdefnm_lst = td;
+ }
+
+/*
+ * Add name of file to the output list, and if it contains "interesting"
+ * code, add it to the dependency list in the data base.
+ */
+void put_c_fl(fname, keep)
+char *fname;
+int keep;
+ {
+ struct fileparts *fp;
+
+ fp = fparse(fname);
+ fprintf(curlst, "%s\n", fp->name);
+ if (keep)
+ add_dpnd(src_lkup(cur_src), fname);
+ }
+
+/*
+ * Print an error message if called incorrectly.
+ */
+void show_usage()
+ {
+ fprintf(stderr, "usage: %s %s\n", progname, options);
+ exit(EXIT_FAILURE);
+ }
+
+/*
+ * yyerror - error routine called by yacc.
+ */
+void yyerror(s)
+char *s;
+ {
+ struct token *t;
+
+ t = yylval.t;
+ if (t == NULL)
+ err2(s, " at end of file");
+ else
+ errt1(t, s);
+ }
diff --git a/src/rtt/rttmisc.c b/src/rtt/rttmisc.c
new file mode 100644
index 0000000..822970f
--- /dev/null
+++ b/src/rtt/rttmisc.c
@@ -0,0 +1,114 @@
+#include "rtt.h"
+
+int n_tmp_str = 0;
+int n_tmp_cset = 0;
+struct sym_entry *params = NULL;
+
+/*
+ * clr_def - clear any information related to definitions.
+ */
+void clr_def()
+ {
+ struct sym_entry *sym;
+
+ n_tmp_str = 0;
+ n_tmp_cset = 0;
+ while (params != NULL) {
+ sym = params;
+ params = params->u.param_info.next;
+ free_sym(sym);
+ }
+ free_tend();
+ if (v_len != NULL)
+ free_sym(v_len);
+ v_len = NULL;
+ il_indx = 0;
+ lbl_num = 0;
+ abs_ret = SomeType;
+ }
+
+/*
+ * ttol - convert a token representing an integer constant into a long
+ * integer value.
+ */
+long ttol(t)
+struct token *t;
+{
+ register long i;
+ register char *s;
+ int base;
+
+ s = t->image;
+ i = 0;
+ base = 10;
+
+ if (*s == '0') {
+ base = 8;
+ ++s;
+ if (*s == 'x') {
+ base = 16;
+ ++s;
+ }
+ }
+ while (*s != '\0') {
+ i *= base;
+ if (*s >= '0' && *s <= '9')
+ i += *s++ - '0';
+ else if (*s >= 'a' && *s <= 'f')
+ i += *s++ - 'a' + 10;
+ else if (*s >= 'A' && *s <= 'F')
+ i += *s++ - 'A' + 10;
+ }
+ return i;
+ }
+
+struct token *chk_exct(tok)
+struct token *tok;
+ {
+ struct sym_entry *sym;
+
+ sym = sym_lkup(tok->image);
+ if (sym->u.typ_indx != int_typ)
+ errt2(tok, "exact conversions do not apply to ", tok->image);
+ return tok;
+ }
+
+/*
+ * icn_typ - convert a type node into a type code for the internal
+ * representation of the data base.
+ */
+int icn_typ(typ)
+struct node *typ;
+ {
+ switch (typ->nd_id) {
+ case PrimryNd:
+ switch (typ->tok->tok_id) {
+ case Any_value:
+ return TypAny;
+ case Empty_type:
+ return TypEmpty;
+ case Variable:
+ return TypVar;
+ case C_Integer:
+ return TypCInt;
+ case C_Double:
+ return TypCDbl;
+ case C_String:
+ return TypCStr;
+ case Tmp_string:
+ return TypTStr;
+ case Tmp_cset:
+ return TypTCset;
+ }
+
+ case SymNd:
+ return typ->u[0].sym->u.typ_indx;
+
+ default: /* must be exact conversion */
+ if (typ->tok->tok_id == C_Integer)
+ return TypECInt;
+ else /* integer */
+ return TypEInt;
+ }
+ }
+
diff --git a/src/rtt/rttnode.c b/src/rtt/rttnode.c
new file mode 100644
index 0000000..6064b7e
--- /dev/null
+++ b/src/rtt/rttnode.c
@@ -0,0 +1,264 @@
+#include "rtt.h"
+
+/*
+ * node0 - create a syntax tree leaf node.
+ */
+struct node *node0(id, tok)
+int id;
+struct token *tok;
+ {
+ struct node *n;
+
+ n = NewNode(0);
+ n->nd_id = id;
+ n->tok = tok;
+ return n;
+ }
+
+/*
+ * node1 - create a syntax tree node with one child.
+ */
+struct node *node1(id, tok, n1)
+int id;
+struct token *tok;
+struct node *n1;
+ {
+ struct node *n;
+
+ n = NewNode(1);
+ n->nd_id = id;
+ n->tok = tok;
+ n->u[0].child = n1;
+ return n;
+ }
+
+/*
+ * node2 - create a syntax tree node with two children.
+ */
+struct node *node2(id, tok, n1, n2)
+int id;
+struct token *tok;
+struct node *n1;
+struct node *n2;
+ {
+ struct node *n;
+
+ n = NewNode(2);
+ n->nd_id = id;
+ n->tok = tok;
+ n->u[0].child = n1;
+ n->u[1].child = n2;
+ return n;
+ }
+
+/*
+ * node3 - create a syntax tree node with three children.
+ */
+struct node *node3(id, tok, n1, n2, n3)
+int id;
+struct token *tok;
+struct node *n1;
+struct node *n2;
+struct node *n3;
+ {
+ struct node *n;
+
+ n = NewNode(3);
+ n->nd_id = id;
+ n->tok = tok;
+ n->u[0].child = n1;
+ n->u[1].child = n2;
+ n->u[2].child = n3;
+ return n;
+ }
+
+/*
+ * node4 - create a syntax tree node with four children.
+ */
+struct node *node4(id, tok, n1, n2, n3, n4)
+int id;
+struct token *tok;
+struct node *n1;
+struct node *n2;
+struct node *n3;
+struct node *n4;
+ {
+ struct node *n;
+
+ n = NewNode(4);
+ n->nd_id = id;
+ n->tok = tok;
+ n->u[0].child = n1;
+ n->u[1].child = n2;
+ n->u[2].child = n3;
+ n->u[3].child = n4;
+ return n;
+ }
+
+/*
+ * sym_node - create a syntax tree node for a variable. If the identifier
+ * is in the symbol table, create a node that references the entry,
+ * otherwise create a simple leaf node.
+ */
+struct node *sym_node(tok)
+struct token *tok;
+ {
+ struct sym_entry *sym;
+ struct node *n;
+
+ sym = sym_lkup(tok->image);
+ if (sym != NULL) {
+ n = NewNode(1);
+ n->nd_id = SymNd;
+ n->tok = tok;
+ n->u[0].sym = sym;
+ ++sym->ref_cnt;
+ /*
+ * If this is the result location of an operation, note that it
+ * is explicitly referenced.
+ */
+ if (sym->id_type == RsltLoc)
+ sym->u.referenced = 1;
+ return n;
+ }
+ else
+ return node0(PrimryNd, tok);
+ }
+
+/*
+ * comp_nd - create a node for a compound statement.
+ */
+struct node *comp_nd(tok, dcls, stmts)
+struct token *tok;
+struct node *dcls;
+struct node *stmts;
+ {
+ struct node *n;
+
+ n = NewNode(3);
+ n->nd_id = CompNd;
+ n->tok = tok;
+ n->u[0].child = dcls;
+ n->u[1].sym = dcl_stk->tended; /* tended declarations are not in dcls */
+ n->u[2].child = stmts;
+ return n;
+ }
+
+/*
+ * arith_nd - create a node for an arith_case statement.
+ */
+struct node *arith_nd(tok, p1, p2, c_int, ci_act, intgr, i_act, dbl, d_act)
+struct token *tok;
+struct node *p1;
+struct node *p2;
+struct node *c_int;
+struct node *ci_act;
+struct node *intgr;
+struct node *i_act;
+struct node *dbl;
+struct node *d_act;
+ {
+ struct node *n;
+
+ /*
+ * Insure the cases are what we expect.
+ */
+ if (c_int->tok->tok_id != C_Integer)
+ errt3(c_int->tok, "expected \"C_integer\", found \"", c_int->tok->image,
+ "\"");
+ if (intgr->tok->image != icontypes[int_typ].id)
+ errt3(intgr->tok, "expected \"integer\", found \"", intgr->tok->image,
+ "\"");
+ if (dbl->tok->tok_id != C_Double)
+ errt3(dbl->tok, "expected \"C_double\", found \"", dbl->tok->image,
+ "\"");
+
+ /*
+ * Indicate in the symbol table that the arguments are converted to C
+ * values.
+ */
+ dst_alloc(c_int, p1);
+ dst_alloc(c_int, p2);
+ dst_alloc(dbl, p1);
+ dst_alloc(dbl, p2);
+
+ free_tree(c_int);
+ free_tree(intgr);
+ free_tree(dbl);
+
+ n = node3(TrnryNd, NULL, ci_act, i_act, d_act);
+ return node3(TrnryNd, tok, p1, p2, n);
+ }
+
+struct node *dest_node(tok)
+struct token *tok;
+ {
+ struct node *n;
+ int typcd;
+
+ n = sym_node(tok);
+ typcd = n->u[0].sym->u.typ_indx;
+ if (typcd != int_typ && typcd != str_typ && typcd != cset_typ &&
+ typcd != real_typ)
+ errt2(tok, "cannot convert to ", tok->image);
+ return n;
+ }
+
+
+/*
+ * free_tree - free storage for a syntax tree.
+ */
+void free_tree(n)
+struct node *n;
+ {
+ struct sym_entry *sym, *sym1;
+
+ if (n == NULL)
+ return;
+
+ /*
+ * Free any subtrees and other referenced storage.
+ */
+ switch (n->nd_id) {
+ case SymNd:
+ free_sym(n->u[0].sym); /* Indicate one less reference to symbol */
+ break;
+
+ case CompNd:
+ /*
+ * Compound node. Free ordinary declarations, tended declarations,
+ * and executable code.
+ */
+ free_tree(n->u[0].child);
+ sym = n->u[1].sym;
+ while (sym != NULL) {
+ sym1 = sym;
+ sym = sym->u.tnd_var.next;
+ free_sym(sym1);
+ }
+ free_tree(n->u[2].child);
+ break;
+
+ case QuadNd:
+ free_tree(n->u[3].child);
+ /* fall thru to next case */
+ case TrnryNd:
+ free_tree(n->u[2].child);
+ /* fall thru to next case */
+ case AbstrNd: case BinryNd: case CommaNd: case ConCatNd: case LstNd:
+ case StrDclNd:
+ free_tree(n->u[1].child);
+ /* fall thru to next case */
+ case IcnTypNd: case PstfxNd: case PreSpcNd: case PrefxNd:
+ free_tree(n->u[0].child);
+ /* fall thru to next case */
+ case ExactCnv: case PrimryNd:
+ break;
+
+ default:
+ fprintf(stdout, "rtt internal error: unknown node type\n");
+ exit(EXIT_FAILURE);
+ }
+ free_t(n->tok); /* free token */
+ free((char *)n);
+ }
diff --git a/src/rtt/rttout.c b/src/rtt/rttout.c
new file mode 100644
index 0000000..14c71b7
--- /dev/null
+++ b/src/rtt/rttout.c
@@ -0,0 +1,3821 @@
+#include "rtt.h"
+
+#define NotId 0 /* declarator is not simple identifier */
+#define IsId 1 /* declarator is simple identifier */
+
+#define OrdFunc -1 /* indicates ordinary C function - non-token value */
+
+/*
+ * VArgAlwnc - allowance for the variable part of an argument list in the
+ * most general version of an operation. If it is too small, storage must
+ * be malloced. 3 was chosen because over 90 percent of all writes have
+ * 3 or fewer arguments. It is possible that 4 would be a better number,
+ * but 5 is probably overkill.
+ */
+#define VArgAlwnc 3
+
+/*
+ * Prototypes for static functions.
+ */
+static void cnv_fnc (struct token *t, int typcd,
+ struct node *src, struct node *dflt,
+ struct node *dest, int indent);
+static void chk_conj (struct node *n);
+static void chk_nl (int indent);
+static void chk_rsltblk (int indent);
+static void comp_def (struct node *n);
+static int does_call (struct node *expr);
+static void failure (int indent, int brace);
+static void interp_def (struct node *n);
+static int len_sel (struct node *sel,
+ struct parminfo *strt_prms,
+ struct parminfo *end_prms, int indent);
+static void line_dir (int nxt_line, char *new_fname);
+static int only_proto (struct node *n);
+static void parm_locs (struct sym_entry *op_params);
+static void parm_tnd (struct sym_entry *sym);
+static void prt_runerr (struct token *t, struct node *num,
+ struct node *val, int indent);
+static void prt_tok (struct token *t, int indent);
+static void prt_var (struct node *n, int indent);
+static int real_def (struct node *n);
+static int retval_dcltor (struct node *dcltor, int indent);
+static void ret_value (struct token *t, struct node *n,
+ int indent);
+static void ret_1_arg (struct token *t, struct node *args,
+ int typcd, char *vwrd_asgn, char *arg_rep,
+ int indent);
+static int rt_walk (struct node *n, int indent, int brace);
+static void spcl_start (struct sym_entry *op_params);
+static int tdef_or_extr (struct node *n);
+static void tend_ary (int n);
+static void tend_init (void);
+static void tnd_var (struct sym_entry *sym, char *strct_ptr, char *access, int indent);
+static void tok_line (struct token *t, int indent);
+static void typ_asrt (int typcd, struct node *desc,
+ struct token *tok, int indent);
+static int typ_case (struct node *var, struct node *slct_lst,
+ struct node *dflt,
+ int (*walk)(struct node *n, int xindent,
+ int brace), int maybe_var, int indent);
+static void untend (int indent);
+
+extern char *progname;
+
+int op_type = OrdFunc; /* type of operation */
+char lc_letter; /* f = function, o = operator, k = keyword */
+char uc_letter; /* F = function, O = operator, K = keyword */
+char prfx1; /* 1st char of unique prefix for operation */
+char prfx2; /* 2nd char of unique prefix for operation */
+char *fname = ""; /* current source file name */
+int line = 0; /* current source line number */
+int nxt_sbuf; /* next string buffer index */
+int nxt_cbuf; /* next cset buffer index */
+int abs_ret = SomeType; /* type from abstract return(s) */
+
+int nl = 0; /* flag indicating the a new-line should be output */
+static int no_nl = 0; /* flag to suppress line directives */
+
+static int ntend; /* number of tended descriptor needed */
+static char *tendstrct; /* expression to access struct of tended descriptors */
+static char *rslt_loc; /* expression to access result location */
+static int varargs = 0; /* flag: operation takes variable number of arguments */
+
+static int no_ret_val; /* function has return statement with no value */
+static struct node *fnc_head; /* header of function being "copied" to output */
+
+/*
+ * chk_nl - if a new-line is required, output it and indent the next line.
+ */
+static void chk_nl(indent)
+int indent;
+ {
+ int col;
+
+ if (nl) {
+ /*
+ * new-line required.
+ */
+ putc('\n', out_file);
+ ++line;
+ for (col = 0; col < indent; ++col)
+ putc(' ', out_file);
+ nl = 0;
+ }
+ }
+
+/*
+ * line_dir - Output a line directive.
+ */
+static void line_dir(nxt_line, new_fname)
+int nxt_line;
+char *new_fname;
+ {
+ char *s;
+
+ /*
+ * Make sure line directives are desired in the output. Normally,
+ * blank lines surround the directive for readability. However,`
+ * a preceding blank line is suppressed at the beginning of the
+ * output file. In addition, a blank line is suppressed after
+ * the directive if it would force the line number on the directive
+ * to be 0.
+ */
+ if (line_cntrl) {
+ fprintf(out_file, "\n");
+ if (line != 0)
+ fprintf(out_file, "\n");
+ if (nxt_line == 1)
+ fprintf(out_file, "#line %d \"", nxt_line);
+ else
+ fprintf(out_file, "#line %d \"", nxt_line - 1);
+ for (s = new_fname; *s != '\0'; ++s) {
+ if (*s == '"' || *s == '\\')
+ putc('\\', out_file);
+ putc(*s, out_file);
+ }
+ if (nxt_line == 1)
+ fprintf(out_file, "\"");
+ else
+ fprintf(out_file, "\"\n");
+ nl = 1;
+ --nxt_line;
+ }
+ else if ((nxt_line > line || fname != new_fname) && line != 0) {
+ /*
+ * Line directives are disabled, but we are in a situation where
+ * one or two new-lines are desirable.
+ */
+ if (nxt_line > line + 1 || fname != new_fname)
+ fprintf(out_file, "\n");
+ nl = 1;
+ --nxt_line;
+ }
+ line = nxt_line;
+ fname = new_fname;
+ }
+
+/*
+ * prt_str - print a string to the output file, possibly preceded by
+ * a new-line and indenting.
+ */
+void prt_str(s, indent)
+char *s;
+int indent;
+ {
+ chk_nl(indent);
+ fprintf(out_file, "%s", s);
+ }
+
+/*
+ * tok_line - determine if a line directive is needed to synchronize the
+ * output file name and line number with an input token.
+ */
+static void tok_line(t, indent)
+struct token *t;
+int indent;
+ {
+ int nxt_line;
+
+ /*
+ * Line directives may be suppressed at certain points during code
+ * output. This is done either by rtt itself using the no_nl flag, or
+ * for macros, by the preprocessor using a flag in the token.
+ */
+ if (no_nl)
+ return;
+ if (t->flag & LineChk) {
+ /*
+ * If blank lines can be used in place of a line directive and no
+ * more than 3 are needed, use them. If the line number and file
+ * name are correct, but we need a new-line, we must output a
+ * line directive so the line number is reset after the "new-line".
+ */
+ nxt_line = t->line;
+ if (fname != t->fname || line > nxt_line || line + 2 < nxt_line)
+ line_dir(nxt_line, t->fname);
+ else if (nl && line == nxt_line)
+ line_dir(nxt_line, t->fname);
+ else if (line != nxt_line) {
+ nl = 1;
+ --nxt_line;
+ while (line < nxt_line) { /* above condition limits # interactions */
+ putc('\n', out_file);
+ ++line;
+ }
+ }
+ }
+ chk_nl(indent);
+ }
+
+/*
+ * prt_tok - print a token.
+ */
+static void prt_tok(t, indent)
+struct token *t;
+int indent;
+ {
+ char *s;
+
+ tok_line(t, indent); /* synchronize file name and line number */
+
+ /*
+ * Most tokens contain a string of their exact image. However, string
+ * and character literals lack the surrounding quotes.
+ */
+ s = t->image;
+ switch (t->tok_id) {
+ case StrLit:
+ fprintf(out_file, "\"%s\"", s);
+ break;
+ case LStrLit:
+ fprintf(out_file, "L\"%s\"", s);
+ break;
+ case CharConst:
+ fprintf(out_file, "'%s'", s);
+ break;
+ case LCharConst:
+ fprintf(out_file, "L'%s'", s);
+ break;
+ default:
+ fprintf(out_file, "%s", s);
+ }
+ }
+
+/*
+ * untend - output code to removed the tended descriptors in this
+ * function from the global tended list.
+ */
+static void untend(indent)
+int indent;
+ {
+ ForceNl();
+ prt_str("tend = ", indent);
+ fprintf(out_file, "%s.previous;", tendstrct);
+ ForceNl();
+ /*
+ * For varargs operations, the tended structure might have been
+ * malloced. If so, it must be freed.
+ */
+ if (varargs) {
+ prt_str("if (r_tendp != (struct tend_desc *)&r_tend)", indent);
+ ForceNl();
+ prt_str("free((pointer)r_tendp);", 2 * indent);
+ }
+ }
+
+/*
+ * tnd_var - output an expression to accessed a tended variable.
+ */
+static void tnd_var(sym, strct_ptr, access, indent)
+struct sym_entry *sym;
+char *strct_ptr;
+char *access;
+int indent;
+ {
+ /*
+ * A variable that is a specific block pointer type must be cast
+ * to that pointer type in such a way that it can be used as either
+ * an lvalue or an rvalue: *(struct b_??? **)&???.vword.bptr
+ */
+ if (strct_ptr != NULL) {
+ prt_str("(*(struct ", indent);
+ prt_str(strct_ptr, indent);
+ prt_str("**)&", indent);
+ }
+
+ if (sym->id_type & ByRef) {
+ /*
+ * The tended variable is being accessed indirectly through
+ * a pointer (that is, it is accessed as the argument to a body
+ * function); dereference its identifier.
+ */
+ prt_str("(*", indent);
+ prt_str(sym->image, indent);
+ prt_str(")", indent);
+ }
+ else {
+ if (sym->t_indx >= 0) {
+ /*
+ * The variable is accessed directly as part of the tended structure.
+ */
+ prt_str(tendstrct, indent);
+ fprintf(out_file, ".d[%d]", sym->t_indx);
+ }
+ else {
+ /*
+ * This is a direct access to an operation parameter.
+ */
+ prt_str("r_args[", indent);
+ fprintf(out_file, "%d]", sym->u.param_info.param_num + 1);
+ }
+ }
+ prt_str(access, indent); /* access the vword for tended pointers */
+ if (strct_ptr != NULL)
+ prt_str(")", indent);
+ }
+
+/*
+ * prt_var - print a variable.
+ */
+static void prt_var(n, indent)
+struct node *n;
+int indent;
+ {
+ struct token *t;
+ struct sym_entry *sym;
+
+ t = n->tok;
+ tok_line(t, indent); /* synchronize file name and line nuber */
+ sym = n->u[0].sym;
+ switch (sym->id_type & ~ByRef) {
+ case TndDesc:
+ /*
+ * Simple tended descriptor.
+ */
+ tnd_var(sym, NULL, "", indent);
+ break;
+ case TndStr:
+ /*
+ * Tended character pointer.
+ */
+ tnd_var(sym, NULL, ".vword.sptr", indent);
+ break;
+ case TndBlk:
+ /*
+ * Tended block pointer.
+ */
+ tnd_var(sym, sym->u.tnd_var.blk_name, ".vword.bptr",
+ indent);
+ break;
+ case RtParm:
+ case DrfPrm:
+ switch (sym->u.param_info.cur_loc) {
+ case PrmTend:
+ /*
+ * Simple tended parameter.
+ */
+ tnd_var(sym, NULL, "", indent);
+ break;
+ case PrmCStr:
+ /*
+ * Parameter converted to a (tended) string.
+ */
+ tnd_var(sym, NULL, ".vword.sptr", indent);
+ break;
+ case PrmInt:
+ /*
+ * Parameter converted to a C integer.
+ */
+ chk_nl(indent);
+ fprintf(out_file, "r_i%d", sym->u.param_info.param_num);
+ break;
+ case PrmDbl:
+ /*
+ * Parameter converted to a C double.
+ */
+ chk_nl(indent);
+ fprintf(out_file, "r_d%d", sym->u.param_info.param_num);
+ break;
+ default:
+ errt2(t, "Conflicting conversions for: ", t->image);
+ }
+ break;
+ case RtParm | VarPrm:
+ case DrfPrm | VarPrm:
+ /*
+ * Parameter representing variable part of argument list.
+ */
+ prt_str("(&", indent);
+ if (sym->t_indx >= 0)
+ fprintf(out_file, "%s.d[%d])", tendstrct, sym->t_indx);
+ else
+ fprintf(out_file, "r_args[%d])", sym->u.param_info.param_num + 1);
+ break;
+ case VArgLen:
+ /*
+ * Length of variable part of argument list.
+ */
+ prt_str("(r_nargs - ", indent);
+ fprintf(out_file, "%d)", params->u.param_info.param_num);
+ break;
+ case RsltLoc:
+ /*
+ * "result" the result location of the operation.
+ */
+ prt_str(rslt_loc, indent);
+ break;
+ case Label:
+ /*
+ * Statement label.
+ */
+ prt_str(sym->image, indent);
+ break;
+ case OtherDcl:
+ /*
+ * Some other type of variable: accessed by identifier. If this
+ * is a body function, it may be passed by reference and need
+ * a level of pointer dereferencing.
+ */
+ if (sym->id_type & ByRef)
+ prt_str("(*",indent);
+ prt_str(sym->image, indent);
+ if (sym->id_type & ByRef)
+ prt_str(")",indent);
+ break;
+ }
+ }
+
+/*
+ * does_call - determine if an expression contains a function call by
+ * walking its syntax tree.
+ */
+static int does_call(expr)
+struct node *expr;
+ {
+ int n_subs;
+ int i;
+
+ if (expr == NULL)
+ return 0;
+ if (expr->nd_id == BinryNd && expr->tok->tok_id == ')')
+ return 1; /* found a function call */
+
+ switch (expr->nd_id) {
+ case ExactCnv: case PrimryNd: case SymNd:
+ n_subs = 0;
+ break;
+ case CompNd:
+ /*
+ * Check field 0 below, field 1 is not a subtree, check field 2 here.
+ */
+ n_subs = 1;
+ if (does_call(expr->u[2].child))
+ return 1;
+ break;
+ case IcnTypNd: case PstfxNd: case PreSpcNd: case PrefxNd:
+ n_subs = 1;
+ break;
+ case AbstrNd: case BinryNd: case CommaNd: case ConCatNd: case LstNd:
+ case StrDclNd:
+ n_subs = 2;
+ break;
+ case TrnryNd:
+ n_subs = 3;
+ break;
+ case QuadNd:
+ n_subs = 4;
+ break;
+ default:
+ fprintf(stdout, "rtt internal error: unknown node type\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < n_subs; ++i)
+ if (does_call(expr->u[i].child))
+ return 1;
+
+ return 0;
+ }
+
+/*
+ * prt_runerr - print code to implement runerr().
+ */
+static void prt_runerr(t, num, val, indent)
+struct token *t;
+struct node *num;
+struct node *val;
+int indent;
+ {
+ if (op_type == OrdFunc)
+ errt1(t, "'runerr' may not be used in an ordinary C function");
+
+ tok_line(t, indent); /* synchronize file name and line number */
+ prt_str("{", indent);
+ ForceNl();
+ prt_str("err_msg(", indent);
+ c_walk(num, indent, 0); /* error number */
+ if (val == NULL)
+ prt_str(", NULL);", indent); /* no offending value */
+ else {
+ prt_str(", &(", indent);
+ c_walk(val, indent, 0); /* offending value */
+ prt_str("));", indent);
+ }
+ /*
+ * Handle error conversion. Indicate that operation may fail because
+ * of error conversion and produce the necessary code.
+ */
+ cur_impl->ret_flag |= DoesEFail;
+ failure(indent, 1);
+ prt_str("}", indent);
+ ForceNl();
+ }
+
+/*
+ * typ_name - convert a type code to a string that can be used to
+ * output "T_" or "D_" type codes.
+ */
+char *typ_name(typcd, tok)
+int typcd;
+struct token *tok;
+ {
+ if (typcd == Empty_type)
+ errt1(tok, "it is meaningless to assert a type of empty_type");
+ else if (typcd == Any_value)
+ errt1(tok, "it is useless to assert a type of any_value");
+ else if (typcd < 0 || typcd == str_typ)
+ return NULL;
+ else
+ return icontypes[typcd].cap_id;
+ /*NOTREACHED*/
+ return 0; /* avoid gcc warning */
+ }
+
+/*
+ * Produce a C conditional expression to check a descriptor for a
+ * particular type.
+ */
+static void typ_asrt(typcd, desc, tok, indent)
+int typcd;
+struct node *desc;
+struct token *tok;
+int indent;
+ {
+ tok_line(tok, indent);
+
+ if (typcd == str_typ) {
+ /*
+ * Check dword for the absense of a "not qualifier" flag.
+ */
+ prt_str("(!((", indent);
+ c_walk(desc, indent, 0);
+ prt_str(").dword & F_Nqual))", indent);
+ }
+ else if (typcd == TypVar) {
+ /*
+ * Check dword for the presense of a "variable" flag.
+ */
+ prt_str("(((", indent);
+ c_walk(desc, indent, 0);
+ prt_str(").dword & D_Var) == D_Var)", indent);
+ }
+ else if (typcd == int_typ) {
+ /*
+ * If large integers are supported, an integer can be either
+ * an ordinary integer or a large integer.
+ */
+ ForceNl();
+ prt_str("#ifdef LargeInts", 0);
+ ForceNl();
+ prt_str("(((", indent);
+ c_walk(desc, indent, 0);
+ prt_str(").dword == D_Integer) || ((", indent);
+ c_walk(desc, indent, 0);
+ prt_str(").dword == D_Lrgint))", indent);
+ ForceNl();
+ prt_str("#else\t\t\t\t\t/* LargeInts */", 0);
+ ForceNl();
+ prt_str("((", indent);
+ c_walk(desc, indent, 0);
+ prt_str(").dword == D_Integer)", indent);
+ ForceNl();
+ prt_str("#endif\t\t\t\t\t/* LargeInts */", 0);
+ ForceNl();
+ }
+ else {
+ /*
+ * Check dword for a specific type code.
+ */
+ prt_str("((", indent);
+ c_walk(desc, indent, 0);
+ prt_str(").dword == D_", indent);
+ prt_str(typ_name(typcd, tok), indent);
+ prt_str(")", indent);
+ }
+ }
+
+/*
+ * retval_dcltor - convert the "declarator" part of function declaration
+ * into a declarator for the variable "r_retval" of the same type
+ * as the function result type, outputing the new declarator. This
+ * variable is a temporary location to store the result of the argument
+ * to a C return statement.
+ */
+static int retval_dcltor(dcltor, indent)
+struct node *dcltor;
+int indent;
+ {
+ int flag;
+
+ switch (dcltor->nd_id) {
+ case ConCatNd:
+ c_walk(dcltor->u[0].child, indent, 0);
+ retval_dcltor(dcltor->u[1].child, indent);
+ return NotId;
+ case PrimryNd:
+ /*
+ * We have reached the function name. Replace it with "r_retval"
+ * and tell caller we have found it.
+ */
+ prt_str("r_retval", indent);
+ return IsId;
+ case PrefxNd:
+ /*
+ * (...)
+ */
+ prt_str("(", indent);
+ flag = retval_dcltor(dcltor->u[0].child, indent);
+ prt_str(")", indent);
+ return flag;
+ case BinryNd:
+ if (dcltor->tok->tok_id == ')') {
+ /*
+ * Function declaration. If this is the declarator that actually
+ * defines the function being processed, discard the paramater
+ * list including parentheses.
+ */
+ if (retval_dcltor(dcltor->u[0].child, indent) == NotId) {
+ prt_str("(", indent);
+ c_walk(dcltor->u[1].child, indent, 0);
+ prt_str(")", indent);
+ }
+ }
+ else {
+ /*
+ * Array.
+ */
+ retval_dcltor(dcltor->u[0].child, indent);
+ prt_str("[", indent);
+ c_walk(dcltor->u[1].child, indent, 0);
+ prt_str("]", indent);
+ }
+ return NotId;
+ }
+ err1("rtt internal error detected in function retval_dcltor()");
+ /*NOTREACHED*/
+ return 0; /* avoid gcc warning */
+ }
+
+/*
+ * cnv_fnc - produce code to handle RTT cnv: and def: constructs.
+ */
+static void cnv_fnc(t, typcd, src, dflt, dest, indent)
+struct token *t;
+int typcd;
+struct node *src;
+struct node *dflt;
+struct node *dest;
+int indent;
+ {
+ int dflt_to_ptr;
+ int loc;
+ int is_cstr;
+
+ if (src->nd_id == SymNd && src->u[0].sym->id_type & VarPrm)
+ errt1(t, "converting entire variable part of param list not supported");
+
+ tok_line(t, indent); /* synchronize file name and line number */
+
+ /*
+ * Initial assumptions: result of conversion is a tended location
+ * and is not tended C string.
+ */
+ loc = PrmTend;
+ is_cstr = 0;
+
+ /*
+ * Print the name of the conversion function. If it is a conversion
+ * with a default value, determine (through dflt_to_prt) if the
+ * default value is passed by-reference instead of by-value.
+ */
+ prt_str(cnv_name(typcd, dflt, &dflt_to_ptr), indent);
+ prt_str("(", indent);
+
+ /*
+ * Determine what parameter scope, if any, is established by this
+ * conversion. If the conversion needs a buffer, allocate it and
+ * put it in the argument list.
+ */
+ switch (typcd) {
+ case TypCInt:
+ case TypECInt:
+ loc = PrmInt;
+ break;
+ case TypCDbl:
+ loc = PrmDbl;
+ break;
+ case TypCStr:
+ is_cstr = 1;
+ break;
+ case TypTStr:
+ fprintf(out_file, "r_sbuf[%d], ", nxt_sbuf++);
+ break;
+ case TypTCset:
+ fprintf(out_file, "&r_cbuf[%d], ", nxt_cbuf++);
+ break;
+ }
+
+ /*
+ * Output source of conversion.
+ */
+ prt_str("&(", indent);
+ c_walk(src, indent, 0);
+ prt_str("), ", indent);
+
+ /*
+ * If there is a default value, output it, taking its address if necessary.
+ */
+ if (dflt != NULL) {
+ if (dflt_to_ptr)
+ prt_str("&(", indent);
+ c_walk(dflt, indent, 0);
+ if (dflt_to_ptr)
+ prt_str("), ", indent);
+ else
+ prt_str(", ", indent);
+ }
+
+ /*
+ * Output the destination of the conversion. This may or may not be
+ * the same as the source.
+ */
+ prt_str("&(", indent);
+ if (dest == NULL) {
+ /*
+ * Convert "in place", changing the location of a paramater if needed.
+ */
+ if (src->nd_id == SymNd && src->u[0].sym->id_type & (RtParm | DrfPrm)) {
+ if (src->u[0].sym->id_type & DrfPrm)
+ src->u[0].sym->u.param_info.cur_loc = loc;
+ else
+ errt1(t, "only dereferenced parameter can be converted in-place");
+ }
+ else if ((loc != PrmTend) | is_cstr)
+ errt1(t,
+ "only ordinary parameters can be converted in-place to C values");
+ c_walk(src, indent, 0);
+ if (is_cstr) {
+ /*
+ * The parameter must be accessed as a tended C string, but only
+ * now, after the "destination" code has been produced as a full
+ * descriptor.
+ */
+ src->u[0].sym->u.param_info.cur_loc = PrmCStr;
+ }
+ }
+ else {
+ /*
+ * Convert to an explicit destination.
+ */
+ if (is_cstr) {
+ /*
+ * Access the destination as a full descriptor even though it
+ * must be declared as a tended C string.
+ */
+ if (dest->nd_id != SymNd || (dest->u[0].sym->id_type != TndStr &&
+ dest->u[0].sym->id_type != TndDesc))
+ errt1(t,
+ "dest. of C_string conv. must be tended descriptor or char *");
+ tnd_var(dest->u[0].sym, NULL, "", indent);
+ }
+ else
+ c_walk(dest, indent, 0);
+ }
+ prt_str("))", indent);
+ }
+
+/*
+ * cnv_name - produce name of conversion routine. Warning, name is
+ * constructed in a static buffer. Also determine if a default
+ * must be passed "by reference".
+ */
+char *cnv_name(typcd, dflt, dflt_to_ptr)
+int typcd;
+struct node *dflt;
+int *dflt_to_ptr;
+ {
+ static char buf[15];
+ int by_ref;
+
+ /*
+ * The names of simple conversion and defaulting conversions have
+ * the same suffixes, but different prefixes.
+ */
+ if (dflt == NULL)
+ strcpy(buf , "cnv_");
+ else
+ strcpy(buf, "def_");
+
+ by_ref = 0;
+ switch (typcd) {
+ case TypCInt:
+ strcat(buf, "c_int");
+ break;
+ case TypCDbl:
+ strcat(buf, "c_dbl");
+ break;
+ case TypCStr:
+ strcat(buf, "c_str");
+ break;
+ case TypTStr:
+ strcat(buf, "tstr");
+ by_ref = 1;
+ break;
+ case TypTCset:
+ strcat(buf, "tcset");
+ by_ref = 1;
+ break;
+ case TypEInt:
+ strcat(buf, "eint");
+ break;
+ case TypECInt:
+ strcat(buf, "ec_int");
+ break;
+ default:
+ if (typcd == cset_typ) {
+ strcat(buf, "cset");
+ by_ref = 1;
+ }
+ else if (typcd == int_typ)
+ strcat(buf, "int");
+ else if (typcd == real_typ)
+ strcat(buf, "real");
+ else if (typcd == str_typ) {
+ strcat(buf, "str");
+ by_ref = 1;
+ }
+ }
+ if (dflt_to_ptr != NULL)
+ *dflt_to_ptr = by_ref;
+ return buf;
+ }
+
+/*
+ * ret_value - produce code to set the result location of an operation
+ * using the expression on a return or suspend.
+ */
+static void ret_value(t, n, indent)
+struct token *t;
+struct node *n;
+int indent;
+ {
+ struct node *caller;
+ struct node *args;
+ int typcd;
+
+ if (n == NULL)
+ errt1(t, "there is no default return value for run-time operations");
+
+ if (n->nd_id == SymNd && n->u[0].sym->id_type == RsltLoc) {
+ /*
+ * return/suspend result;
+ *
+ * result already where it needs to be.
+ */
+ return;
+ }
+
+ if (n->nd_id == PrefxNd && n->tok != NULL) {
+ switch (n->tok->tok_id) {
+ case C_Integer:
+ /*
+ * return/suspend C_integer <expr>;
+ */
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.integr = ", indent);
+ c_walk(n->u[0].child, indent + IndentInc, 0);
+ prt_str(";", indent);
+ ForceNl();
+ prt_str(rslt_loc, indent);
+ prt_str(".dword = D_Integer;", indent);
+ chkabsret(t, int_typ); /* compare return with abstract return */
+ return;
+ case C_Double:
+ /*
+ * return/suspend C_double <expr>;
+ */
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.bptr = (union block *)alcreal(", indent);
+ c_walk(n->u[0].child, indent + IndentInc, 0);
+ prt_str(");", indent + IndentInc);
+ ForceNl();
+ prt_str(rslt_loc, indent);
+ prt_str(".dword = D_Real;", indent);
+ /*
+ * The allocation of the real block may fail.
+ */
+ chk_rsltblk(indent);
+ chkabsret(t, real_typ); /* compare return with abstract return */
+ return;
+ case C_String:
+ /*
+ * return/suspend C_string <expr>;
+ */
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.sptr = ", indent);
+ c_walk(n->u[0].child, indent + IndentInc, 0);
+ prt_str(";", indent);
+ ForceNl();
+ prt_str(rslt_loc, indent);
+ prt_str(".dword = strlen(", indent);
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.sptr);", indent);
+ chkabsret(t, str_typ); /* compare return with abstract return */
+ return;
+ }
+ }
+ else if (n->nd_id == BinryNd && n->tok->tok_id == ')') {
+ /*
+ * Return value is in form of function call, see if it is really
+ * a descriptor constructor.
+ */
+ caller = n->u[0].child;
+ args = n->u[1].child;
+ if (caller->nd_id == SymNd) {
+ switch (caller->tok->tok_id) {
+ case IconType:
+ typcd = caller->u[0].sym->u.typ_indx;
+ switch (icontypes[typcd].rtl_ret) {
+ case TRetBlkP:
+ /*
+ * return/suspend <type>(<block-pntr>);
+ */
+ ret_1_arg(t, args, typcd, ".vword.bptr = (union block *)",
+ "(bp)", indent);
+ break;
+ case TRetDescP:
+ /*
+ * return/suspend <type>(<desc-pntr>);
+ */
+ ret_1_arg(t, args, typcd, ".vword.descptr = (dptr)",
+ "(dp)", indent);
+ break;
+ case TRetCharP:
+ /*
+ * return/suspend <type>(<char-pntr>);
+ */
+ ret_1_arg(t, args, typcd, ".vword.sptr = (char *)",
+ "(s)", indent);
+ break;
+ case TRetCInt:
+ /*
+ * return/suspend <type>(<integer>);
+ */
+ ret_1_arg(t, args, typcd, ".vword.integr = (word)",
+ "(i)", indent);
+ break;
+ case TRetSpcl:
+ if (typcd == str_typ) {
+ /*
+ * return/suspend string(<len>, <char-pntr>);
+ */
+ if (args == NULL || args->nd_id != CommaNd ||
+ args->u[0].child->nd_id == CommaNd)
+ errt1(t, "wrong no. of args for string(n, s)");
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.sptr = ", indent);
+ c_walk(args->u[1].child, indent + IndentInc, 0);
+ prt_str(";", indent);
+ ForceNl();
+ prt_str(rslt_loc, indent);
+ prt_str(".dword = ", indent);
+ c_walk(args->u[0].child, indent + IndentInc, 0);
+ prt_str(";", indent);
+ }
+ else if (typcd == stv_typ) {
+ /*
+ * return/suspend tvsubs(<desc-pntr>, <start>, <len>);
+ */
+ if (args == NULL || args->nd_id != CommaNd ||
+ args->u[0].child->nd_id != CommaNd ||
+ args->u[0].child->u[0].child->nd_id == CommaNd)
+ errt1(t, "wrong no. of args for tvsubs(dp, i, j)");
+ no_nl = 1;
+ prt_str("SubStr(&", indent);
+ prt_str(rslt_loc, indent);
+ prt_str(", ", indent);
+ c_walk(args->u[0].child->u[0].child, indent + IndentInc,
+ 0);
+ prt_str(", ", indent + IndentInc);
+ c_walk(args->u[1].child, indent + IndentInc, 0);
+ prt_str(", ", indent + IndentInc);
+ c_walk(args->u[0].child->u[1].child, indent + IndentInc,
+ 0);
+ prt_str(");", indent + IndentInc);
+ no_nl = 0;
+ /*
+ * The allocation of the substring trapped variable
+ * block may fail.
+ */
+ chk_rsltblk(indent);
+ chkabsret(t, stv_typ); /* compare to abstract return */
+ }
+ break;
+ }
+ chkabsret(t, typcd); /* compare return with abstract return */
+ return;
+ case Named_var:
+ /*
+ * return/suspend named_var(<desc-pntr>);
+ */
+ if (args == NULL || args->nd_id == CommaNd)
+ errt1(t, "wrong no. of args for named_var(dp)");
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.descptr = ", indent);
+ c_walk(args, indent + IndentInc, 0);
+ prt_str(";", indent);
+ ForceNl();
+ prt_str(rslt_loc, indent);
+ prt_str(".dword = D_Var;", indent);
+ chkabsret(t, TypVar); /* compare return with abstract return */
+ return;
+ case Struct_var:
+ /*
+ * return/suspend struct_var(<desc-pntr>, <block_pntr>);
+ */
+ if (args == NULL || args->nd_id != CommaNd ||
+ args->u[0].child->nd_id == CommaNd)
+ errt1(t, "wrong no. of args for struct_var(dp, bp)");
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.descptr = (dptr)", indent);
+ c_walk(args->u[1].child, indent + IndentInc, 0);
+ prt_str(";", indent);
+ ForceNl();
+ prt_str(rslt_loc, indent);
+ prt_str(".dword = D_Var + ((word *)", indent);
+ c_walk(args->u[0].child, indent + IndentInc, 0);
+ prt_str(" - (word *)", indent+IndentInc);
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.descptr);", indent+IndentInc);
+ ForceNl();
+ chkabsret(t, TypVar); /* compare return with abstract return */
+ return;
+ }
+ }
+ }
+
+ /*
+ * If it is not one of the special returns, it is just a return of
+ * a descriptor.
+ */
+ prt_str(rslt_loc, indent);
+ prt_str(" = ", indent);
+ c_walk(n, indent + IndentInc, 0);
+ prt_str(";", indent);
+ chkabsret(t, SomeType); /* check for preceding abstract return */
+ }
+
+/*
+ * ret_1_arg - produce code for a special return/suspend with one argument.
+ */
+static void ret_1_arg(t, args, typcd, vwrd_asgn, arg_rep, indent)
+struct token *t;
+struct node *args;
+int typcd;
+char *vwrd_asgn;
+char *arg_rep;
+int indent;
+ {
+ if (args == NULL || args->nd_id == CommaNd)
+ errt3(t, "wrong no. of args for", icontypes[typcd].id, arg_rep);
+
+ /*
+ * Assignment to vword of result descriptor.
+ */
+ prt_str(rslt_loc, indent);
+ prt_str(vwrd_asgn, indent);
+ c_walk(args, indent + IndentInc, 0);
+ prt_str(";", indent);
+ ForceNl();
+
+ /*
+ * Assignment to dword of result descriptor.
+ */
+ prt_str(rslt_loc, indent);
+ prt_str(".dword = D_", indent);
+ prt_str(icontypes[typcd].cap_id, indent);
+ prt_str(";", indent);
+ }
+
+/*
+ * chk_rsltblk - the result value contains an allocated block, make sure
+ * the allocation succeeded.
+ */
+static void chk_rsltblk(indent)
+int indent;
+ {
+ ForceNl();
+ prt_str("if (", indent);
+ prt_str(rslt_loc, indent);
+ prt_str(".vword.bptr == NULL) {", indent);
+ ForceNl();
+ prt_str("err_msg(307, NULL);", indent + IndentInc);
+ ForceNl();
+ /*
+ * Handle error conversion. Indicate that operation may fail because
+ * of error conversion and produce the necessary code.
+ */
+ cur_impl->ret_flag |= DoesEFail;
+ failure(indent + IndentInc, 1);
+ prt_str("}", indent + IndentInc);
+ ForceNl();
+ }
+
+/*
+ * failure - produce code for fail or efail.
+ */
+static void failure(indent, brace)
+int indent;
+int brace;
+ {
+ /*
+ * If there are tended variables, they must be removed from the tended
+ * list. The C function may or may not return an explicit signal.
+ */
+ ForceNl();
+ if (ntend != 0) {
+ if (!brace)
+ prt_str("{", indent);
+ untend(indent);
+ ForceNl();
+ if (fnc_ret == RetSig)
+ prt_str("return A_Resume;", indent);
+ else
+ prt_str("return;", indent);
+ if (!brace) {
+ ForceNl();
+ prt_str("}", indent);
+ }
+ }
+ else
+ if (fnc_ret == RetSig)
+ prt_str("return A_Resume;", indent);
+ else
+ prt_str("return;", indent);
+ ForceNl();
+ }
+
+/*
+ * c_walk - walk the syntax tree for extended C code and output the
+ * corresponding ordinary C. Return and indication of whether execution
+ * falls through the code.
+ */
+int c_walk(n, indent, brace)
+struct node *n;
+int indent;
+int brace;
+ {
+ struct token *t;
+ struct node *n1;
+ struct sym_entry *sym;
+ int fall_thru;
+ int save_break;
+ static int does_break = 0;
+ static int may_brnchto; /* may reach end of code by branching into middle */
+
+ if (n == NULL)
+ return 1;
+
+ t = n->tok;
+
+ switch (n->nd_id) {
+ case PrimryNd:
+ switch (t->tok_id) {
+ case Fail:
+ if (op_type == OrdFunc)
+ errt1(t, "'fail' may not be used in an ordinary C function");
+ cur_impl->ret_flag |= DoesFail;
+ failure(indent, brace);
+ chkabsret(t, SomeType); /* check preceding abstract return */
+ return 0;
+ case Errorfail:
+ if (op_type == OrdFunc)
+ errt1(t,
+ "'errorfail' may not be used in an ordinary C function");
+ cur_impl->ret_flag |= DoesEFail;
+ failure(indent, brace);
+ return 0;
+ case Break:
+ prt_tok(t, indent);
+ prt_str(";", indent);
+ does_break = 1;
+ return 0;
+ default:
+ /*
+ * Other "primary" expressions are just their token image,
+ * possibly followed by a semicolon.
+ */
+ prt_tok(t, indent);
+ if (t->tok_id == Continue)
+ prt_str(";", indent);
+ return 1;
+ }
+ case PrefxNd:
+ switch (t->tok_id) {
+ case Sizeof:
+ prt_tok(t, indent); /* sizeof */
+ prt_str("(", indent);
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(")", indent);
+ return 1;
+ case '{':
+ /*
+ * Initializer list.
+ */
+ prt_tok(t, indent + IndentInc); /* { */
+ c_walk(n->u[0].child, indent + IndentInc, 0);
+ prt_str("}", indent + IndentInc);
+ return 1;
+ case Default:
+ prt_tok(t, indent - IndentInc); /* default (un-indented) */
+ prt_str(": ", indent - IndentInc);
+ fall_thru = c_walk(n->u[0].child, indent, 0);
+ may_brnchto = 1;
+ return fall_thru;
+ case Goto:
+ prt_tok(t, indent); /* goto */
+ prt_str(" ", indent);
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(";", indent);
+ return 0;
+ case Return:
+ if (n->u[0].child != NULL)
+ no_ret_val = 0; /* note that return statement has no value */
+
+ if (op_type == OrdFunc || fnc_ret == RetInt ||
+ fnc_ret == RetDbl) {
+ /*
+ * ordinary C return: ignore C_integer, C_double, and
+ * C_string qualifiers on return expression (the first
+ * two may legally occur when fnc_ret is RetInt or RetDbl).
+ */
+ n1 = n->u[0].child;
+ if (n1 != NULL && n1->nd_id == PrefxNd && n1->tok != NULL) {
+ switch (n1->tok->tok_id) {
+ case C_Integer:
+ case C_Double:
+ case C_String:
+ n1 = n1->u[0].child;
+ }
+ }
+ if (ntend != 0) {
+ /*
+ * There are tended variables that must be removed from
+ * the tended list.
+ */
+ if (!brace)
+ prt_str("{", indent);
+ if (does_call(n1)) {
+ /*
+ * The return expression contains a function call;
+ * the variables must remain tended while it is
+ * computed, so compute it into a temporary variable
+ * named r_retval.Output a declaration for r_retval;
+ * its type must match the return type of the C
+ * function.
+ */
+ ForceNl();
+ prt_str("register ", indent);
+ if (op_type == OrdFunc) {
+ no_nl = 1;
+ just_type(fnc_head->u[0].child, indent, 0);
+ prt_str(" ", indent);
+ retval_dcltor(fnc_head->u[1].child, indent);
+ prt_str(";", indent);
+ no_nl = 0;
+ }
+ else if (fnc_ret == RetInt)
+ prt_str("C_integer r_retval;", indent);
+ else /* fnc_ret == RetDbl */
+ prt_str("double r_retval;", indent);
+ ForceNl();
+
+ /*
+ * Output code to compute the return value, untend
+ * the variable, then return the value.
+ */
+ prt_str("r_retval = ", indent);
+ c_walk(n1, indent + IndentInc, 0);
+ prt_str(";", indent);
+ untend(indent);
+ ForceNl();
+ prt_str("return r_retval;", indent);
+ }
+ else {
+ /*
+ * It is safe to untend the variables and return
+ * the result value directly with a return
+ * statement.
+ */
+ untend(indent);
+ ForceNl();
+ prt_tok(t, indent); /* return */
+ prt_str(" ", indent);
+ c_walk(n1, indent, 0);
+ prt_str(";", indent);
+ }
+ if (!brace) {
+ ForceNl();
+ prt_str("}", indent);
+ }
+ ForceNl();
+ }
+ else {
+ /*
+ * There are no tended variable, just output the
+ * return expression.
+ */
+ prt_tok(t, indent); /* return */
+ prt_str(" ", indent);
+ c_walk(n1, indent, 0);
+ prt_str(";", indent);
+ }
+
+ /*
+ * If this is a body function, check the return against
+ * preceding abstract returns.
+ */
+ if (fnc_ret == RetInt)
+ chkabsret(n->tok, int_typ);
+ else if (fnc_ret == RetDbl)
+ chkabsret(n->tok, real_typ);
+ }
+ else {
+ /*
+ * Return from Icon operation. Indicate that the operation
+ * returns, compute the value into the result location,
+ * untend variables if necessary, and return a signal
+ * if the function requires one.
+ */
+ cur_impl->ret_flag |= DoesRet;
+ ForceNl();
+ if (!brace) {
+ prt_str("{", indent);
+ ForceNl();
+ }
+ ret_value(t, n->u[0].child, indent);
+ if (ntend != 0)
+ untend(indent);
+ ForceNl();
+ if (fnc_ret == RetSig)
+ prt_str("return A_Continue;", indent);
+ else if (fnc_ret == RetNoVal)
+ prt_str("return;", indent);
+ ForceNl();
+ if (!brace) {
+ prt_str("}", indent);
+ ForceNl();
+ }
+ }
+ return 0;
+ case Suspend:
+ if (op_type == OrdFunc)
+ errt1(t, "'suspend' may not be used in an ordinary C function"
+ );
+ cur_impl->ret_flag |= DoesSusp; /* note suspension */
+ ForceNl();
+ if (!brace) {
+ prt_str("{", indent);
+ ForceNl();
+ }
+ prt_str("register int signal;", indent + IndentInc);
+ ForceNl();
+ ret_value(t, n->u[0].child, indent);
+ ForceNl();
+ /*
+ * The operator suspends by calling the success continuation
+ * if there is one or just returns if there is none. For
+ * the interpreter, interp() is the success continuation.
+ * A non-A_Resume signal from the success continuation must
+ * returned to the caller. If there are tended variables
+ * they must be removed from the tended list before a signal
+ * is returned.
+ */
+ if (iconx_flg) {
+ #ifdef EventMon
+ switch (op_type) {
+ case TokFunction:
+ prt_str(
+ "if ((signal = interp(G_Fsusp, r_args)) != A_Resume) {",
+ indent);
+ break;
+ case Operator:
+ case Keyword:
+ prt_str(
+ "if ((signal = interp(G_Osusp, r_args)) != A_Resume) {",
+ indent);
+ break;
+ default:
+ prt_str(
+ "if ((signal = interp(G_Csusp, r_args)) != A_Resume) {",
+ indent);
+ }
+ #else /* EventMon */
+ prt_str(
+ "if ((signal = interp(G_Csusp, r_args)) != A_Resume) {",
+ indent);
+ #endif /* EventMon */
+ }
+ else {
+ prt_str("if (r_s_cont == (continuation)NULL) {", indent);
+ if (ntend != 0)
+ untend(indent + IndentInc);
+ ForceNl();
+ prt_str("return A_Continue;", indent + IndentInc);
+ ForceNl();
+ prt_str("}", indent + IndentInc);
+ ForceNl();
+ prt_str("else if ((signal = (*r_s_cont)()) != A_Resume) {",
+ indent);
+ }
+ ForceNl();
+ if (ntend != 0)
+ untend(indent + IndentInc);
+ ForceNl();
+ prt_str("return signal;", indent + IndentInc);
+ ForceNl();
+ prt_str("}", indent + IndentInc);
+ if (!brace) {
+ prt_str("}", indent);
+ ForceNl();
+ }
+ return 1;
+ case '(':
+ /*
+ * Parenthesized expression.
+ */
+ prt_tok(t, indent); /* ( */
+ fall_thru = c_walk(n->u[0].child, indent, 0);
+ prt_str(")", indent);
+ return fall_thru;
+ default:
+ /*
+ * All other prefix expressions are printed as the token
+ * image of the operation followed by the operand.
+ */
+ prt_tok(t, indent);
+ c_walk(n->u[0].child, indent, 0);
+ return 1;
+ }
+ case PstfxNd:
+ /*
+ * All postfix expressions are printed as the operand followed
+ * by the token image of the operation.
+ */
+ fall_thru = c_walk(n->u[0].child, indent, 0);
+ prt_tok(t, indent);
+ return fall_thru;
+ case PreSpcNd:
+ /*
+ * This prefix expression (pointer indication in a declaration) needs
+ * a space after it.
+ */
+ prt_tok(t, indent);
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(" ", indent);
+ return 1;
+ case SymNd:
+ /*
+ * Identifier.
+ */
+ prt_var(n, indent);
+ return 1;
+ case BinryNd:
+ switch (t->tok_id) {
+ case '[':
+ /*
+ * subscripting expression or declaration: <expr> [ <expr> ]
+ */
+ n1 = n->u[0].child;
+ c_walk(n->u[0].child, indent, 0);
+ prt_str("[", indent);
+ c_walk(n->u[1].child, indent, 0);
+ prt_str("]", indent);
+ return 1;
+ case '(':
+ /*
+ * cast: ( <type> ) <expr>
+ */
+ prt_tok(t, indent); /* ) */
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(")", indent);
+ c_walk(n->u[1].child, indent, 0);
+ return 1;
+ case ')':
+ /*
+ * function call or declaration: <expr> ( <expr-list> )
+ */
+ c_walk(n->u[0].child, indent, 0);
+ prt_str("(", indent);
+ c_walk(n->u[1].child, indent, 0);
+ prt_tok(t, indent); /* ) */
+ return call_ret(n->u[0].child);
+ case Struct:
+ case Union:
+ /*
+ * struct/union <ident>
+ * struct/union <opt-ident> { <field-list> }
+ */
+ prt_tok(t, indent); /* struct or union */
+ prt_str(" ", indent);
+ c_walk(n->u[0].child, indent, 0);
+ if (n->u[1].child != NULL) {
+ /*
+ * Field declaration list.
+ */
+ prt_str(" {", indent);
+ c_walk(n->u[1].child, indent + IndentInc, 0);
+ ForceNl();
+ prt_str("}", indent);
+ }
+ return 1;
+ case TokEnum:
+ /*
+ * enum <ident>
+ * enum <opt-ident> { <enum-list> }
+ */
+ prt_tok(t, indent); /* enum */
+ prt_str(" ", indent);
+ c_walk(n->u[0].child, indent, 0);
+ if (n->u[1].child != NULL) {
+ /*
+ * enumerator list.
+ */
+ prt_str(" {", indent);
+ c_walk(n->u[1].child, indent + IndentInc, 0);
+ prt_str("}", indent);
+ }
+ return 1;
+ case ';':
+ /*
+ * <type-specs> <declarator> ;
+ */
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(" ", indent);
+ c_walk(n->u[1].child, indent, 0);
+ prt_tok(t, indent); /* ; */
+ return 1;
+ case ':':
+ /*
+ * <label> : <statement>
+ */
+ c_walk(n->u[0].child, indent, 0);
+ prt_tok(t, indent); /* : */
+ prt_str(" ", indent);
+ fall_thru = c_walk(n->u[1].child, indent, 0);
+ may_brnchto = 1;
+ return fall_thru;
+ case Case:
+ /*
+ * case <expr> : <statement>
+ */
+ prt_tok(t, indent - IndentInc); /* case (un-indented) */
+ prt_str(" ", indent);
+ c_walk(n->u[0].child, indent - IndentInc, 0);
+ prt_str(": ", indent - IndentInc);
+ fall_thru = c_walk(n->u[1].child, indent, 0);
+ may_brnchto = 1;
+ return fall_thru;
+ case Switch:
+ /*
+ * switch ( <expr> ) <statement>
+ *
+ * <statement> is double indented so that case and default
+ * statements can be un-indented and come out indented 1
+ * with respect to the switch. Statements that are not
+ * "labeled" with case or default are indented one more
+ * than those that are labeled.
+ */
+ prt_tok(t, indent); /* switch */
+ prt_str(" (", indent);
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(")", indent);
+ prt_str(" ", indent);
+ save_break = does_break;
+ fall_thru = c_walk(n->u[1].child, indent + 2 * IndentInc, 0);
+ fall_thru |= does_break;
+ does_break = save_break;
+ return fall_thru;
+ case While: {
+ struct node *n0;
+ /*
+ * While ( <expr> ) <statement>
+ */
+ n0 = n->u[0].child;
+ prt_tok(t, indent); /* while */
+ prt_str(" (", indent);
+ c_walk(n0, indent, 0);
+ prt_str(")", indent);
+ prt_str(" ", indent);
+ save_break = does_break;
+ c_walk(n->u[1].child, indent + IndentInc, 0);
+ /*
+ * check for an infinite loop, while (1) ... :
+ * a condition consisting of an IntConst with image=="1"
+ * and no breaks in the body.
+ */
+ if (n0->nd_id == PrimryNd && n0->tok->tok_id == IntConst &&
+ !strcmp(n0->tok->image,"1") && !does_break)
+ fall_thru = 0;
+ else
+ fall_thru = 1;
+ does_break = save_break;
+ return fall_thru;
+ }
+ case Do:
+ /*
+ * do <statement> <while> ( <expr> )
+ */
+ prt_tok(t, indent); /* do */
+ prt_str(" ", indent);
+ c_walk(n->u[0].child, indent + IndentInc, 0);
+ ForceNl();
+ prt_str("while (", indent);
+ save_break = does_break;
+ c_walk(n->u[1].child, indent, 0);
+ does_break = save_break;
+ prt_str(");", indent);
+ return 1;
+ case '.':
+ case Arrow:
+ /*
+ * Field access: <expr> . <expr> and <expr> -> <expr>
+ */
+ c_walk(n->u[0].child, indent, 0);
+ prt_tok(t, indent); /* . or -> */
+ c_walk(n->u[1].child, indent, 0);
+ return 1;
+ case Runerr:
+ /*
+ * runerr ( <error-number> )
+ * runerr ( <error-number> , <offending-value> )
+ */
+ prt_runerr(t, n->u[0].child, n->u[1].child, indent);
+ return 0;
+ case Is:
+ /*
+ * is : <type> ( <expr> )
+ */
+ typ_asrt(icn_typ(n->u[0].child), n->u[1].child,
+ n->u[0].child->tok, indent);
+ return 1;
+ default:
+ /*
+ * All other binary expressions are infix notation and
+ * are printed with spaces around the operator.
+ */
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(" ", indent);
+ prt_tok(t, indent);
+ prt_str(" ", indent);
+ c_walk(n->u[1].child, indent, 0);
+ return 1;
+ }
+ case LstNd:
+ /*
+ * <declaration-part> <declaration-part>
+ *
+ * Need space between parts
+ */
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(" ", indent);
+ c_walk(n->u[1].child, indent, 0);
+ return 1;
+ case ConCatNd:
+ /*
+ * <some-code> <some-code>
+ *
+ * Various lists of code parts that do not need space between them.
+ */
+ if (c_walk(n->u[0].child, indent, 0))
+ return c_walk(n->u[1].child, indent, 0);
+ else {
+ /*
+ * Cannot directly reach the second piece of code, see if
+ * it is possible to branch into it.
+ */
+ may_brnchto = 0;
+ fall_thru = c_walk(n->u[1].child, indent, 0);
+ return may_brnchto & fall_thru;
+ }
+ case CommaNd:
+ /*
+ * <expr> , <expr>
+ */
+ c_walk(n->u[0].child, indent, 0);
+ prt_tok(t, indent);
+ prt_str(" ", indent);
+ return c_walk(n->u[1].child, indent, 0);
+ case StrDclNd:
+ /*
+ * Structure field declaration. Bit field declarations have
+ * a semicolon and a field width.
+ */
+ c_walk(n->u[0].child, indent, 0);
+ if (n->u[1].child != NULL) {
+ prt_str(": ", indent);
+ c_walk(n->u[1].child, indent, 0);
+ }
+ return 1;
+ case CompNd:
+ /*
+ * Compound statement.
+ */
+ if (brace)
+ tok_line(t, indent); /* just synch. file name and line number */
+ else
+ prt_tok(t, indent); /* { */
+ c_walk(n->u[0].child, indent, 0);
+ /*
+ * we are in an inner block. tended locations may need to
+ * be set to values from declaration initializations.
+ */
+ for (sym = n->u[1].sym; sym!= NULL; sym = sym->u.tnd_var.next) {
+ if (sym->u.tnd_var.init != NULL) {
+ prt_str(tendstrct, IndentInc);
+ fprintf(out_file, ".d[%d]", sym->t_indx);
+ switch (sym->id_type) {
+ case TndDesc:
+ prt_str(" = ", IndentInc);
+ break;
+ case TndStr:
+ prt_str(".vword.sptr = ", IndentInc);
+ break;
+ case TndBlk:
+ prt_str(".vword.bptr = (union block *)",
+ IndentInc);
+ break;
+ }
+ c_walk(sym->u.tnd_var.init, 2 * IndentInc, 0);
+ prt_str(";", 2 * IndentInc);
+ ForceNl();
+ }
+ }
+ /*
+ * If there are no declarations, suppress braces that
+ * may be required for a one-statement body; we already
+ * have a set.
+ */
+ if (n->u[0].child == NULL && n->u[1].sym == NULL)
+ fall_thru = c_walk(n->u[2].child, indent, 1);
+ else
+ fall_thru = c_walk(n->u[2].child, indent, 0);
+ if (!brace) {
+ ForceNl();
+ prt_str("}", indent);
+ }
+ return fall_thru;
+ case TrnryNd:
+ switch (t->tok_id) {
+ case '?':
+ /*
+ * <expr> ? <expr> : <expr>
+ */
+ c_walk(n->u[0].child, indent, 0);
+ prt_str(" ", indent);
+ prt_tok(t, indent); /* ? */
+ prt_str(" ", indent);
+ c_walk(n->u[1].child, indent, 0);
+ prt_str(" : ", indent);
+ c_walk(n->u[2].child, indent, 0);
+ return 1;
+ case If:
+ /*
+ * if ( <expr> ) <statement>
+ * if ( <expr> ) <statement> else <statement>
+ */
+ prt_tok(t, indent); /* if */
+ prt_str(" (", indent);
+ c_walk(n->u[0].child, indent + IndentInc, 0);
+ prt_str(") ", indent);
+ fall_thru = c_walk(n->u[1].child, indent + IndentInc, 0);
+ n1 = n->u[2].child;
+ if (n1 == NULL)
+ fall_thru = 1;
+ else {
+ /*
+ * There is an else statement. Don't indent an
+ * "else if"
+ */
+ ForceNl();
+ prt_str("else ", indent);
+ if (n1->nd_id == TrnryNd && n1->tok->tok_id == If)
+ fall_thru |= c_walk(n1, indent, 0);
+ else
+ fall_thru |= c_walk(n1, indent + IndentInc, 0);
+ }
+ return fall_thru;
+ case Type_case:
+ /*
+ * type_case <expr> of { <section-list> }
+ * type_case <expr> of { <section-list> <default-clause> }
+ */
+ return typ_case(n->u[0].child, n->u[1].child, n->u[2].child,
+ c_walk, 1, indent);
+ case Cnv:
+ /*
+ * cnv : <type> ( <source> , <destination> )
+ */
+ cnv_fnc(t, icn_typ(n->u[0].child), n->u[1].child, NULL,
+ n->u[2].child,
+ indent);
+ return 1;
+ }
+ case QuadNd:
+ switch (t->tok_id) {
+ case For:
+ /*
+ * for ( <expr> ; <expr> ; <expr> ) <statement>
+ */
+ prt_tok(t, indent); /* for */
+ prt_str(" (", indent);
+ c_walk(n->u[0].child, indent, 0);
+ prt_str("; ", indent);
+ c_walk(n->u[1].child, indent, 0);
+ prt_str("; ", indent);
+ c_walk(n->u[2].child, indent, 0);
+ prt_str(") ", indent);
+ save_break = does_break;
+ c_walk(n->u[3].child, indent + IndentInc, 0);
+ if (n->u[1].child == NULL && !does_break)
+ fall_thru = 0;
+ else
+ fall_thru = 1;
+ does_break = save_break;
+ return fall_thru;
+ case Def:
+ /*
+ * def : <type> ( <source> , <default> , <destination> )
+ */
+ cnv_fnc(t, icn_typ(n->u[0].child), n->u[1].child, n->u[2].child,
+ n->u[3].child, indent);
+ return 1;
+ }
+ }
+ /*NOTREACHED*/
+ return 0; /* avoid gcc warning */
+ }
+
+/*
+ * call_ret - decide whether a function being called might return.
+ */
+int call_ret(n)
+struct node *n;
+ {
+ /*
+ * Assume functions return except for c_exit(), fatalerr(), and syserr().
+ */
+ if (n->tok != NULL &&
+ (strcmp("c_exit", n->tok->image) == 0 ||
+ strcmp("fatalerr", n->tok->image) == 0 ||
+ strcmp("syserr", n->tok->image) == 0))
+ return 0;
+ else
+ return 1;
+ }
+
+/*
+ * new_prmloc - allocate an array large enough to hold a flag for every
+ * parameter of the current operation. This flag indicates where
+ * the parameter is in terms of scopes created by conversions.
+ */
+struct parminfo *new_prmloc()
+ {
+ struct parminfo *parminfo;
+ int nparams;
+ int i;
+
+ if (params == NULL)
+ return NULL;
+ nparams = params->u.param_info.param_num + 1;
+ parminfo = alloc(nparams * sizeof(struct parminfo));
+ for (i = 0; i < nparams; ++i) {
+ parminfo[i].cur_loc = 0;
+ parminfo [i].parm_mod = 0;
+ }
+ return parminfo;
+ }
+
+/*
+ * ld_prmloc - load parameter location information that has been
+ * saved in an arrary into the symbol table.
+ */
+void ld_prmloc(parminfo)
+struct parminfo *parminfo;
+ {
+ struct sym_entry *sym;
+ int param_num;
+
+ for (sym = params; sym != NULL; sym = sym->u.param_info.next) {
+ param_num = sym->u.param_info.param_num;
+ if (sym->id_type & DrfPrm) {
+ sym->u.param_info.cur_loc = parminfo[param_num].cur_loc;
+ sym->u.param_info.parm_mod = parminfo[param_num].parm_mod;
+ }
+ }
+ }
+
+/*
+ * sv_prmloc - save parameter location information from the the symbol table
+ * into an array.
+ */
+void sv_prmloc(parminfo)
+struct parminfo *parminfo;
+ {
+ struct sym_entry *sym;
+ int param_num;
+
+ for (sym = params; sym != NULL; sym = sym->u.param_info.next) {
+ param_num = sym->u.param_info.param_num;
+ if (sym->id_type & DrfPrm) {
+ parminfo[param_num].cur_loc = sym->u.param_info.cur_loc;
+ parminfo[param_num].parm_mod = sym->u.param_info.parm_mod;
+ }
+ }
+ }
+
+/*
+ * mrg_prmloc - merge parameter location information in the symbol table
+ * with other information already saved in an array. This may result
+ * in conflicting location information, but conflicts are only detected
+ * when a parameter is actually used.
+ */
+void mrg_prmloc(parminfo)
+struct parminfo *parminfo;
+ {
+ struct sym_entry *sym;
+ int param_num;
+
+ for (sym = params; sym != NULL; sym = sym->u.param_info.next) {
+ param_num = sym->u.param_info.param_num;
+ if (sym->id_type & DrfPrm) {
+ parminfo[param_num].cur_loc |= sym->u.param_info.cur_loc;
+ parminfo[param_num].parm_mod |= sym->u.param_info.parm_mod;
+ }
+ }
+ }
+
+/*
+ * clr_prmloc - indicate that this execution path contributes nothing
+ * to the location of parameters.
+ */
+void clr_prmloc()
+ {
+ struct sym_entry *sym;
+
+ for (sym = params; sym != NULL; sym = sym->u.param_info.next) {
+ if (sym->id_type & DrfPrm) {
+ sym->u.param_info.cur_loc = 0;
+ sym->u.param_info.parm_mod = 0;
+ }
+ }
+ }
+
+/*
+ * typ_case - translate a type_case statement into C. This is called
+ * while walking a syntax tree of either RTL code or C code; the parameter
+ * "walk" is a function used to process the subtrees within the type_case
+ * statement.
+ */
+static int typ_case(var, slct_lst, dflt, walk, maybe_var, indent)
+struct node *var;
+struct node *slct_lst;
+struct node *dflt;
+int (*walk)(struct node *n, int xindent, int brace);
+int maybe_var;
+int indent;
+ {
+ struct node *lst;
+ struct node *select;
+ struct node *slctor;
+ struct parminfo *strt_prms;
+ struct parminfo *end_prms;
+ int remaining;
+ int first;
+ int fnd_slctrs;
+ int maybe_str = 1;
+ int dflt_lbl;
+ int typcd;
+ int fall_thru;
+ char *s;
+
+ /*
+ * This statement involves multiple paths that may establish new
+ * scopes for parameters. Remember the starting scope information
+ * and initialize an array in which to compute the final information.
+ */
+ strt_prms = new_prmloc();
+ sv_prmloc(strt_prms);
+ end_prms = new_prmloc();
+
+ /*
+ * First look for cases that must be checked with "if" statements.
+ * These include string qualifiers and variables.
+ */
+ remaining = 0; /* number of cases skipped in first pass */
+ first = 1; /* next case to be output is the first */
+ if (dflt == NULL)
+ fall_thru = 1;
+ else
+ fall_thru = 0;
+ for (lst = slct_lst; lst != NULL; lst = lst->u[0].child) {
+ select = lst->u[1].child;
+ fnd_slctrs = 0; /* flag: found type selections for clause for this pass */
+ /*
+ * A selection clause may include several types.
+ */
+ for (slctor = select->u[0].child; slctor != NULL; slctor =
+ slctor->u[0].child) {
+ typcd = icn_typ(slctor->u[1].child);
+ if(typ_name(typcd, slctor->u[1].child->tok) == NULL) {
+ /*
+ * This type must be checked with the "if". Is this the
+ * first condition checked for this clause? Is this the
+ * first clause output?
+ */
+ if (fnd_slctrs)
+ prt_str(" || ", indent);
+ else {
+ if (first)
+ first = 0;
+ else {
+ ForceNl();
+ prt_str("else ", indent);
+ }
+ prt_str("if (", indent);
+ fnd_slctrs = 1;
+ }
+
+ /*
+ * Output type check
+ */
+ typ_asrt(typcd, var, slctor->u[1].child->tok, indent + IndentInc);
+
+ if (typcd == str_typ)
+ maybe_str = 0; /* string has been taken care of */
+ else if (typcd == Variable)
+ maybe_var = 0; /* variable has been taken care of */
+ }
+ else
+ ++remaining;
+ }
+ if (fnd_slctrs) {
+ /*
+ * We have found and output type selections for this clause;
+ * output the body of the clause. Remember any changes to
+ * paramter locations caused by type conversions within the
+ * clause.
+ */
+ prt_str(") {", indent + IndentInc);
+ ForceNl();
+ if ((*walk)(select->u[1].child, indent + IndentInc, 1)) {
+ fall_thru |= 1;
+ mrg_prmloc(end_prms);
+ }
+ prt_str("}", indent + IndentInc);
+ ForceNl();
+ ld_prmloc(strt_prms);
+ }
+ }
+ /*
+ * The rest of the cases can be checked with a "switch" statement, look
+ * for them..
+ */
+ if (remaining == 0) {
+ if (dflt != NULL) {
+ /*
+ * There are no cases to handle with a switch statement, but there
+ * is a default clause; handle it with an "else".
+ */
+ prt_str("else {", indent);
+ ForceNl();
+ fall_thru |= (*walk)(dflt, indent + IndentInc, 1);
+ ForceNl();
+ prt_str("}", indent + IndentInc);
+ ForceNl();
+ }
+ }
+ else {
+ /*
+ * If an "if" statement was output, the "switch" must be in its "else"
+ * clause.
+ */
+ if (!first)
+ prt_str("else ", indent);
+
+ /*
+ * A switch statement cannot handle types that are not simple type
+ * codes. If these have not taken care of, output code to check them.
+ * This will either branch around the switch statement or into
+ * its default clause.
+ */
+ if (maybe_str || maybe_var) {
+ dflt_lbl = lbl_num++; /* allocate a label number */
+ prt_str("{", indent);
+ ForceNl();
+ prt_str("if (((", indent);
+ c_walk(var, indent + IndentInc, 0);
+ prt_str(").dword & D_Typecode) != D_Typecode) ", indent);
+ ForceNl();
+ prt_str("goto L", indent + IndentInc);
+ fprintf(out_file, "%d; /* default */ ", dflt_lbl);
+ ForceNl();
+ }
+
+ no_nl = 1; /* suppress #line directives */
+ prt_str("switch (Type(", indent);
+ c_walk(var, indent + IndentInc, 0);
+ prt_str(")) {", indent + IndentInc);
+ no_nl = 0;
+ ForceNl();
+
+ /*
+ * Loop through the case clauses producing code for them.
+ */
+ for (lst = slct_lst; lst != NULL; lst = lst->u[0].child) {
+ select = lst->u[1].child;
+ fnd_slctrs = 0;
+ /*
+ * A selection clause may include several types.
+ */
+ for (slctor = select->u[0].child; slctor != NULL; slctor =
+ slctor->u[0].child) {
+ typcd = icn_typ(slctor->u[1].child);
+ s = typ_name(typcd, slctor->u[1].child->tok);
+ if (s != NULL) {
+ /*
+ * A type selection has been found that can be checked
+ * in the switch statement. Note that large integers
+ * require special handling.
+ */
+ fnd_slctrs = 1;
+
+ if (typcd == int_typ) {
+ ForceNl();
+ prt_str("#ifdef LargeInts", 0);
+ ForceNl();
+ prt_str("case T_Lrgint: ", indent + IndentInc);
+ ForceNl();
+ prt_str("#endif /* LargeInts */", 0);
+ ForceNl();
+ }
+
+ prt_str("case T_", indent + IndentInc);
+ prt_str(s, indent + IndentInc);
+ prt_str(": ", indent + IndentInc);
+ }
+ }
+ if (fnd_slctrs) {
+ /*
+ * We have found and output type selections for this clause;
+ * output the body of the clause. Remember any changes to
+ * paramter locations caused by type conversions within the
+ * clause.
+ */
+ ForceNl();
+ if ((*walk)(select->u[1].child, indent + 2 * IndentInc, 0)) {
+ fall_thru |= 1;
+ ForceNl();
+ prt_str("break;", indent + 2 * IndentInc);
+ mrg_prmloc(end_prms);
+ }
+ ForceNl();
+ ld_prmloc(strt_prms);
+ }
+ }
+ if (dflt != NULL) {
+ /*
+ * This type_case statement has a default clause. If there is
+ * a branch into this clause, output the label. Remember any
+ * changes to paramter locations caused by type conversions
+ * within the clause.
+ */
+ ForceNl();
+ prt_str("default:", indent + 1 * IndentInc);
+ ForceNl();
+ if (maybe_str || maybe_var) {
+ prt_str("L", 0);
+ fprintf(out_file, "%d: ; /* default */", dflt_lbl);
+ ForceNl();
+ }
+ if ((*walk)(dflt, indent + 2 * IndentInc, 0)) {
+ fall_thru |= 1;
+ mrg_prmloc(end_prms);
+ }
+ ForceNl();
+ ld_prmloc(strt_prms);
+ }
+ prt_str("}", indent + IndentInc);
+
+ if (maybe_str || maybe_var) {
+ if (dflt == NULL) {
+ /*
+ * There is a branch around the switch statement. Output
+ * the label.
+ */
+ ForceNl();
+ prt_str("L", 0);
+ fprintf(out_file, "%d: ; /* default */", dflt_lbl);
+ }
+ ForceNl();
+ prt_str("}", indent + IndentInc);
+ }
+ ForceNl();
+ }
+
+ /*
+ * Put ending parameter locations into effect.
+ */
+ mrg_prmloc(end_prms);
+ ld_prmloc(end_prms);
+ if (strt_prms != NULL)
+ free(strt_prms);
+ if (end_prms != NULL)
+ free(end_prms);
+ return fall_thru;
+ }
+
+/*
+ * chk_conj - see if the left argument of a conjunction is an in-place
+ * conversion of a parameter other than a conversion to C_integer or
+ * C_double. If so issue a warning.
+ */
+static void chk_conj(n)
+struct node *n;
+ {
+ struct node *cnv_type;
+ struct node *src;
+ struct node *dest;
+ int typcd;
+
+ if (n->nd_id == BinryNd && n->tok->tok_id == And)
+ n = n->u[1].child;
+
+ switch (n->nd_id) {
+ case TrnryNd:
+ /*
+ * Must be Cnv.
+ */
+ cnv_type = n->u[0].child;
+ src = n->u[1].child;
+ dest = n->u[2].child;
+ break;
+ case QuadNd:
+ /*
+ * Must be Def.
+ */
+ cnv_type = n->u[0].child;
+ src = n->u[1].child;
+ dest = n->u[3].child;
+ break;
+ default:
+ return; /* not a conversion */
+ }
+
+ /*
+ * A conversion has been found. See if it meets the criteria for
+ * issuing a warning.
+ */
+
+ if (src->nd_id != SymNd || !(src->u[0].sym->id_type & DrfPrm))
+ return; /* not a dereferenced parameter */
+
+ typcd = icn_typ(cnv_type);
+ switch (typcd) {
+ case TypCInt:
+ case TypCDbl:
+ case TypECInt:
+ return;
+ }
+
+ if (dest != NULL)
+ return; /* not an in-place convertion */
+
+ fprintf(stderr,
+ "%s: file %s, line %d, warning: in-place conversion may or may not be\n",
+ progname, cnv_type->tok->fname, cnv_type->tok->line);
+ fprintf(stderr, "\tundone on subsequent failure.\n");
+ }
+
+/*
+ * len_sel - translate a clause form a len_case statement into a C case
+ * clause. Return an indication of whether execution falls through the
+ * clause.
+ */
+static int len_sel(sel, strt_prms, end_prms, indent)
+struct node *sel;
+struct parminfo *strt_prms;
+struct parminfo *end_prms;
+int indent;
+ {
+ int fall_thru;
+
+ prt_str("case ", indent);
+ prt_tok(sel->tok, indent + IndentInc); /* integer selection */
+ prt_str(":", indent + IndentInc);
+ fall_thru = rt_walk(sel->u[0].child, indent + IndentInc, 0);/* clause body */
+ ForceNl();
+
+ if (fall_thru) {
+ prt_str("break;", indent + IndentInc);
+ ForceNl();
+ /*
+ * Remember any changes to paramter locations caused by type conversions
+ * within the clause.
+ */
+ mrg_prmloc(end_prms);
+ }
+
+ ld_prmloc(strt_prms);
+ return fall_thru;
+ }
+
+/*
+ * rt_walk - walk the part of the syntax tree containing rtt code, producing
+ * code for the most-general version of the routine.
+ */
+static int rt_walk(n, indent, brace)
+struct node *n;
+int indent;
+int brace;
+ {
+ struct token *t, *t1;
+ struct node *n1, *errnum;
+ int fall_thru;
+
+ if (n == NULL)
+ return 1;
+
+ t = n->tok;
+
+ switch (n->nd_id) {
+ case PrefxNd:
+ switch (t->tok_id) {
+ case '{':
+ /*
+ * RTL code: { <actions> }
+ */
+ if (brace)
+ tok_line(t, indent); /* just synch file name and line num */
+ else
+ prt_tok(t, indent); /* { */
+ fall_thru = rt_walk(n->u[0].child, indent, 1);
+ if (!brace)
+ prt_str("}", indent);
+ return fall_thru;
+ case '!':
+ /*
+ * RTL type-checking and conversions: ! <simple-type-check>
+ */
+ prt_tok(t, indent);
+ rt_walk(n->u[0].child, indent, 0);
+ return 1;
+ case Body:
+ case Inline:
+ /*
+ * RTL code: body { <c-code> }
+ * inline { <c-code> }
+ */
+ fall_thru = c_walk(n->u[0].child, indent, brace);
+ if (!fall_thru)
+ clr_prmloc();
+ return fall_thru;
+ }
+ break;
+ case BinryNd:
+ switch (t->tok_id) {
+ case Runerr:
+ /*
+ * RTL code: runerr( <message-number> )
+ * runerr( <message-number>, <descriptor> )
+ */
+ prt_runerr(t, n->u[0].child, n->u[1].child, indent);
+
+ /*
+ * Execution cannot continue on this execution path.
+ */
+ clr_prmloc();
+ return 0;
+ case And:
+ /*
+ * RTL type-checking and conversions:
+ * <type-check> && <type_check>
+ */
+ chk_conj(n->u[0].child); /* is a warning needed? */
+ rt_walk(n->u[0].child, indent, 0);
+ prt_str(" ", indent);
+ prt_tok(t, indent); /* && */
+ prt_str(" ", indent);
+ rt_walk(n->u[1].child, indent, 0);
+ return 1;
+ case Is:
+ /*
+ * RTL type-checking and conversions:
+ * is: <icon-type> ( <variable> )
+ */
+ typ_asrt(icn_typ(n->u[0].child), n->u[1].child,
+ n->u[0].child->tok, indent);
+ return 1;
+ }
+ break;
+ case ConCatNd:
+ /*
+ * "Glue" for two constructs.
+ */
+ fall_thru = rt_walk(n->u[0].child, indent, 0);
+ return fall_thru & rt_walk(n->u[1].child, indent, 0);
+ case AbstrNd:
+ /*
+ * Ignore abstract type computations while producing C code
+ * for library routines.
+ */
+ return 1;
+ case TrnryNd:
+ switch (t->tok_id) {
+ case If: {
+ /*
+ * RTL code for "if" statements:
+ * if <type-check> then <action>
+ * if <type-check> then <action> else <action>
+ *
+ * <type-check> may include parameter conversions that create
+ * new scoping. It is necessary to keep track of paramter
+ * types and locations along success and failure paths of
+ * these conversions. The "then" and "else" actions may
+ * also establish new scopes.
+ */
+ struct parminfo *then_prms = NULL;
+ struct parminfo *else_prms;
+
+ /*
+ * Save the current parameter locations. These are in
+ * effect on the failure path of any type conversions
+ * in the condition of the "if".
+ */
+ else_prms = new_prmloc();
+ sv_prmloc(else_prms);
+
+ prt_tok(t, indent); /* if */
+ prt_str(" (", indent);
+ n1 = n->u[0].child;
+ rt_walk(n1, indent + IndentInc, 0); /* type check */
+ prt_str(") {", indent);
+
+ /*
+ * If the condition is negated, the failure path is to the "then"
+ * and the success path is to the "else".
+ */
+ if (n1->nd_id == PrefxNd && n1->tok->tok_id == '!') {
+ then_prms = else_prms;
+ else_prms = new_prmloc();
+ sv_prmloc(else_prms);
+ ld_prmloc(then_prms);
+ }
+
+ /*
+ * Then Clause.
+ */
+ fall_thru = rt_walk(n->u[1].child, indent + IndentInc, 1);
+ ForceNl();
+ prt_str("}", indent + IndentInc);
+
+ /*
+ * Determine if there is an else clause and merge parameter
+ * location information from the alternate paths through
+ * the statement.
+ */
+ n1 = n->u[2].child;
+ if (n1 == NULL) {
+ if (fall_thru)
+ mrg_prmloc(else_prms);
+ ld_prmloc(else_prms);
+ fall_thru = 1;
+ }
+ else {
+ if (then_prms == NULL)
+ then_prms = new_prmloc();
+ if (fall_thru)
+ sv_prmloc(then_prms);
+ ld_prmloc(else_prms);
+ ForceNl();
+ prt_str("else {", indent);
+ if (rt_walk(n1, indent + IndentInc, 1)) { /* else clause */
+ fall_thru = 1;
+ mrg_prmloc(then_prms);
+ }
+ ForceNl();
+ prt_str("}", indent + IndentInc);
+ ld_prmloc(then_prms);
+ }
+ ForceNl();
+ if (then_prms != NULL)
+ free(then_prms);
+ if (else_prms != NULL)
+ free(else_prms);
+ }
+ return fall_thru;
+ case Len_case: {
+ /*
+ * RTL code:
+ * len_case <variable> of {
+ * <integer>: <action>
+ * ...
+ * default: <action>
+ * }
+ */
+ struct parminfo *strt_prms;
+ struct parminfo *end_prms;
+
+ /*
+ * A case may contain parameter conversions that create new
+ * scopes. Remember the parameter locations at the start
+ * of the len_case statement.
+ */
+ strt_prms = new_prmloc();
+ sv_prmloc(strt_prms);
+ end_prms = new_prmloc();
+
+ n1 = n->u[0].child;
+ if (!(n1->u[0].sym->id_type & VArgLen))
+ errt1(t, "len_case must select on length of vararg");
+ /*
+ * The len_case statement is implemented as a C switch
+ * statement.
+ */
+ prt_str("switch (", indent);
+ prt_var(n1, indent);
+ prt_str(") {", indent);
+ ForceNl();
+ fall_thru = 0;
+ for (n1 = n->u[1].child; n1->nd_id == ConCatNd;
+ n1 = n1->u[0].child)
+ fall_thru |= len_sel(n1->u[1].child, strt_prms, end_prms,
+ indent + IndentInc);
+ fall_thru |= len_sel(n1, strt_prms, end_prms,
+ indent + IndentInc);
+
+ /*
+ * Handle default clause.
+ */
+ prt_str("default:", indent + IndentInc);
+ ForceNl();
+ fall_thru |= rt_walk(n->u[2].child, indent + 2 * IndentInc, 0);
+ ForceNl();
+ prt_str("}", indent + IndentInc);
+ ForceNl();
+
+ /*
+ * Put into effect the location of parameters at the end
+ * of the len_case statement.
+ */
+ mrg_prmloc(end_prms);
+ ld_prmloc(end_prms);
+ if (strt_prms != NULL)
+ free(strt_prms);
+ if (end_prms != NULL)
+ free(end_prms);
+ }
+ return fall_thru;
+ case Type_case: {
+ /*
+ * RTL code:
+ * type_case <variable> of {
+ * <icon_type> : ... <icon_type> : <action>
+ * ...
+ * }
+ *
+ * last clause may be: default: <action>
+ */
+ int maybe_var;
+ struct node *var;
+ struct sym_entry *sym;
+
+ /*
+ * If we can determine that the value being checked is
+ * not a variable reference, we don't have to produce code
+ * to check for that possibility.
+ */
+ maybe_var = 1;
+ var = n->u[0].child;
+ if (var->nd_id == SymNd) {
+ sym = var->u[0].sym;
+ switch(sym->id_type) {
+ case DrfPrm:
+ case OtherDcl:
+ case TndDesc:
+ case TndStr:
+ case RsltLoc:
+ if (sym->nest_lvl > 1) {
+ /*
+ * The thing being tested is either a
+ * dereferenced parameter or a local
+ * descriptor which could only have been
+ * set by a conversion which does not
+ * produce a variable reference.
+ */
+ maybe_var = 0;
+ }
+ }
+ }
+ return typ_case(var, n->u[1].child, n->u[2].child, rt_walk,
+ maybe_var, indent);
+ }
+ case Cnv:
+ /*
+ * RTL code: cnv: <type> ( <source> )
+ * cnv: <type> ( <source> , <destination> )
+ */
+ cnv_fnc(t, icn_typ(n->u[0].child), n->u[1].child, NULL,
+ n->u[2].child, indent);
+ return 1;
+ case Arith_case: {
+ /*
+ * arith_case (<variable>, <variable>) of {
+ * C_integer: <statement>
+ * integer: <statement>
+ * C_double: <statement>
+ * }
+ *
+ * This construct does type conversions and provides
+ * alternate execution paths. It is necessary to keep
+ * track of parameter locations.
+ */
+ struct parminfo *strt_prms;
+ struct parminfo *end_prms;
+ struct parminfo *tmp_prms;
+
+ strt_prms = new_prmloc();
+ sv_prmloc(strt_prms);
+ end_prms = new_prmloc();
+ tmp_prms = new_prmloc();
+
+ fall_thru = 0;
+
+ n1 = n->u[2].child; /* contains actions for the 3 cases */
+
+ /*
+ * Set up an error number node for use in runerr().
+ */
+ t1 = copy_t(t);
+ t1->tok_id = IntConst;
+ t1->image = "102";
+ errnum = node0(PrimryNd, t1);
+
+ /*
+ * Try converting both arguments to a C_integer.
+ */
+ tok_line(t, indent);
+ prt_str("if (", indent);
+ cnv_fnc(t, TypECInt, n->u[0].child, NULL, NULL, indent);
+ prt_str(" && ", indent);
+ cnv_fnc(t, TypECInt, n->u[1].child, NULL, NULL, indent);
+ prt_str(") ", indent);
+ ForceNl();
+ if (rt_walk(n1->u[0].child, indent + IndentInc, 0)) {
+ fall_thru |= 1;
+ mrg_prmloc(end_prms);
+ }
+ ForceNl();
+
+ /*
+ * Try converting both arguments to an integer.
+ */
+ prt_str("#ifdef LargeInts", 0);
+ ForceNl();
+ ld_prmloc(strt_prms);
+ tok_line(t, indent);
+ prt_str("else if (", indent);
+ cnv_fnc(t, TypEInt, n->u[0].child, NULL, NULL, indent);
+ prt_str(" && ", indent);
+ cnv_fnc(t, TypEInt, n->u[1].child, NULL, NULL, indent);
+ prt_str(") ", indent);
+ ForceNl();
+ if (rt_walk(n1->u[1].child, indent + IndentInc, 0)) {
+ fall_thru |= 1;
+ mrg_prmloc(end_prms);
+ }
+ ForceNl();
+ prt_str("#endif\t\t\t\t\t/* LargeInts */", 0);
+ ForceNl();
+
+ /*
+ * Try converting both arguments to a C_double
+ */
+ ld_prmloc(strt_prms);
+ prt_str("else {", indent);
+ ForceNl();
+ tok_line(t, indent + IndentInc);
+ prt_str("if (!", indent + IndentInc);
+ cnv_fnc(t, TypCDbl, n->u[0].child, NULL, NULL,
+ indent + IndentInc);
+ prt_str(")", indent + IndentInc);
+ ForceNl();
+ sv_prmloc(tmp_prms); /* use original parm locs for error */
+ ld_prmloc(strt_prms);
+ prt_runerr(t, errnum, n->u[0].child, indent + 2 * IndentInc);
+ ld_prmloc(tmp_prms);
+ tok_line(t, indent + IndentInc);
+ prt_str("if (!", indent + IndentInc);
+ cnv_fnc(t, TypCDbl, n->u[1].child, NULL, NULL,
+ indent + IndentInc);
+ prt_str(") ", indent + IndentInc);
+ ForceNl();
+ sv_prmloc(tmp_prms); /* use original parm locs for error */
+ ld_prmloc(strt_prms);
+ prt_runerr(t, errnum, n->u[1].child, indent + 2 * IndentInc);
+ ld_prmloc(tmp_prms);
+ if (rt_walk(n1->u[2].child, indent + IndentInc, 0)) {
+ fall_thru |= 1;
+ mrg_prmloc(end_prms);
+ }
+ ForceNl();
+ prt_str("}", indent + IndentInc);
+ ForceNl();
+
+ ld_prmloc(end_prms);
+ free(strt_prms);
+ free(end_prms);
+ free(tmp_prms);
+ free_tree(errnum);
+ return fall_thru;
+ }
+ }
+ case QuadNd:
+ /*
+ * RTL code: def: <type> ( <source> , <default>)
+ * def: <type> ( <source> , <default> , <destination> )
+ */
+ cnv_fnc(t, icn_typ(n->u[0].child), n->u[1].child, n->u[2].child,
+ n->u[3].child, indent);
+ return 1;
+ }
+ /*NOTREACHED*/
+ return 0; /* avoid gcc warning */
+ }
+
+/*
+ * spcl_dcls - print special declarations for tended variables, parameter
+ * conversions, and buffers.
+ */
+void spcl_dcls(op_params)
+struct sym_entry *op_params; /* operation parameters or NULL */
+ {
+ register struct sym_entry *sym;
+ struct sym_entry *sym1;
+
+ /*
+ * Output declarations for buffers and locations to hold conversions
+ * to C values.
+ */
+ spcl_start(op_params);
+
+ /*
+ * Determine if this operation takes a variable number of arguments.
+ * Use that information in deciding how large a tended array to
+ * declare.
+ */
+ varargs = (op_params != NULL && op_params->id_type & VarPrm);
+ if (varargs)
+ tend_ary(ntend + VArgAlwnc - 1);
+ else
+ tend_ary(ntend);
+
+ if (varargs) {
+ /*
+ * This operation takes a variable number of arguments. A declaration
+ * for a tended array has been made that will usually hold them, but
+ * sometimes it is necessary to malloc() a tended array at run
+ * time. Produce code to check for this.
+ */
+ cur_impl->ret_flag |= DoesEFail; /* error conversion from allocation */
+ prt_str("struct tend_desc *r_tendp;", IndentInc);
+ ForceNl();
+ prt_str("int r_n;\n", IndentInc);
+ ++line;
+ ForceNl();
+ prt_str("if (r_nargs <= ", IndentInc);
+ fprintf(out_file, "%d)", op_params->u.param_info.param_num + VArgAlwnc);
+ ForceNl();
+ prt_str("r_tendp = (struct tend_desc *)&r_tend;", 2 * IndentInc);
+ ForceNl();
+ prt_str("else {", IndentInc);
+ ForceNl();
+ prt_str(
+ "r_tendp = (struct tend_desc *)malloc((sizeof(struct tend_desc)",
+ 2 * IndentInc);
+ ForceNl();
+ prt_str("", 3 * IndentInc);
+ fprintf(out_file, "+ (r_nargs + %d) * sizeof(struct descrip)));",
+ ntend - 2 - op_params->u.param_info.param_num);
+ ForceNl();
+ prt_str("if (r_tendp == NULL) {", 2 * IndentInc);
+ ForceNl();
+ prt_str("err_msg(305, NULL);", 3 * IndentInc);
+ ForceNl();
+ prt_str("return A_Resume;", 3 * IndentInc);
+ ForceNl();
+ prt_str("}", 3 * IndentInc);
+ ForceNl();
+ prt_str("}", 2 * IndentInc);
+ ForceNl();
+ tendstrct = "(*r_tendp)";
+ }
+ else
+ tendstrct = "r_tend";
+
+ /*
+ * Produce code to initialize the tended array. These are for tended
+ * declarations and parameters.
+ */
+ tend_init(); /* initializations for tended declarations. */
+ if (varargs) {
+ /*
+ * This operation takes a variable number of arguments. Produce code
+ * to dereference or copy this into its portion of the tended
+ * array.
+ */
+ prt_str("for (r_n = ", IndentInc);
+ fprintf(out_file, "%d; r_n < r_nargs; ++r_n)",
+ op_params->u.param_info.param_num);
+ ForceNl();
+ if (op_params->id_type & DrfPrm) {
+ prt_str("deref(&r_args[r_n], &", IndentInc * 2);
+ fprintf(out_file, "%s.d[r_n + %d]);", tendstrct, ntend - 1 -
+ op_params->u.param_info.param_num);
+ }
+ else {
+ prt_str(tendstrct, IndentInc * 2);
+ fprintf(out_file, ".d[r_n + %d] = r_args[r_n];", ntend - 1 -
+ op_params->u.param_info.param_num);
+ }
+ ForceNl();
+ sym = op_params->u.param_info.next;
+ }
+ else
+ sym = op_params; /* no variable part of arg list */
+
+ /*
+ * Go through the fixed part of the parameter list, producing code
+ * to copy/dereference parameters into the tended array.
+ */
+ while (sym != NULL) {
+ /*
+ * A there may be identifiers for dereferenced and/or undereferenced
+ * versions of a paramater. If there are both, sym1 references the
+ * second identifier.
+ */
+ sym1 = sym->u.param_info.next;
+ if (sym1 != NULL && sym->u.param_info.param_num !=
+ sym1->u.param_info.param_num)
+ sym1 = NULL; /* the next entry is not for the same parameter */
+
+ /*
+ * If there are not enough arguments to supply a value for this
+ * parameter, set it to the null value.
+ */
+ prt_str("if (", IndentInc);
+ fprintf(out_file, "r_nargs > %d) {", sym->u.param_info.param_num);
+ ForceNl();
+ parm_tnd(sym);
+ if (sym1 != NULL) {
+ ForceNl();
+ parm_tnd(sym1);
+ }
+ ForceNl();
+ prt_str("} else {", IndentInc);
+ ForceNl();
+ prt_str(tendstrct, IndentInc * 2);
+ fprintf(out_file, ".d[%d].dword = D_Null;", sym->t_indx);
+ if (sym1 != NULL) {
+ ForceNl();
+ prt_str(tendstrct, IndentInc * 2);
+ fprintf(out_file, ".d[%d].dword = D_Null;", sym1->t_indx);
+ }
+ ForceNl();
+ prt_str("}", 2 * IndentInc);
+ ForceNl();
+ if (sym1 == NULL)
+ sym = sym->u.param_info.next;
+ else
+ sym = sym1->u.param_info.next;
+ }
+
+ /*
+ * Finish setting up the tended array structure and link it into the tended
+ * list.
+ */
+ if (ntend != 0) {
+ prt_str(tendstrct, IndentInc);
+ if (varargs)
+ fprintf(out_file, ".num = %d + Max(r_nargs - %d, 0);", ntend - 1,
+ op_params->u.param_info.param_num);
+ else
+ fprintf(out_file, ".num = %d;", ntend);
+ ForceNl();
+ prt_str(tendstrct, IndentInc);
+ prt_str(".previous = tend;", IndentInc);
+ ForceNl();
+ prt_str("tend = (struct tend_desc *)&", IndentInc);
+ fprintf(out_file, "%s;", tendstrct);
+ ForceNl();
+ }
+ }
+
+/*
+ * spcl_start - do initial work for outputing special declarations. Output
+ * declarations for buffers and locations to hold conversions to C values.
+ * Determine what tended locations are needed for parameters.
+ */
+static void spcl_start(op_params)
+struct sym_entry *op_params;
+ {
+ ForceNl();
+ if (n_tmp_str > 0) {
+ prt_str("char r_sbuf[", IndentInc);
+ fprintf(out_file, "%d][MaxCvtLen];", n_tmp_str);
+ ForceNl();
+ }
+ if (n_tmp_cset > 0) {
+ prt_str("struct b_cset r_cbuf[", IndentInc);
+ fprintf(out_file, "%d];", n_tmp_cset);
+ ForceNl();
+ }
+ if (tend_lst == NULL)
+ ntend = 0;
+ else
+ ntend = tend_lst->t_indx + 1;
+ parm_locs(op_params); /* see what parameter conversion there are */
+ }
+
+/*
+ * tend_ary - write struct containing array of tended descriptors.
+ */
+static void tend_ary(n)
+int n;
+ {
+ if (n == 0)
+ return;
+ prt_str("struct {", IndentInc);
+ ForceNl();
+ prt_str("struct tend_desc *previous;", 2 * IndentInc);
+ ForceNl();
+ prt_str("int num;", 2 * IndentInc);
+ ForceNl();
+ prt_str("struct descrip d[", 2 * IndentInc);
+ fprintf(out_file, "%d];", n);
+ ForceNl();
+ prt_str("} r_tend;\n", 2 * IndentInc);
+ ++line;
+ ForceNl();
+ }
+
+/*
+ * tend_init - produce code to initialize entries in the tended array
+ * corresponding to tended declarations. Default initializations are
+ * supplied when there is none in the declaration.
+ */
+static void tend_init()
+ {
+ register struct init_tend *tnd;
+
+ for (tnd = tend_lst; tnd != NULL; tnd = tnd->next) {
+ switch (tnd->init_typ) {
+ case TndDesc:
+ /*
+ * Simple tended declaration.
+ */
+ prt_str(tendstrct, IndentInc);
+ if (tnd->init == NULL)
+ fprintf(out_file, ".d[%d].dword = D_Null;", tnd->t_indx);
+ else {
+ fprintf(out_file, ".d[%d] = ", tnd->t_indx);
+ c_walk(tnd->init, 2 * IndentInc, 0);
+ prt_str(";", 2 * IndentInc);
+ }
+ break;
+ case TndStr:
+ /*
+ * Tended character pointer.
+ */
+ prt_str(tendstrct, IndentInc);
+ if (tnd->init == NULL)
+ fprintf(out_file, ".d[%d] = emptystr;", tnd->t_indx);
+ else {
+ fprintf(out_file, ".d[%d].dword = 0;", tnd->t_indx);
+ ForceNl();
+ prt_str(tendstrct, IndentInc);
+ fprintf(out_file, ".d[%d].vword.sptr = ", tnd->t_indx);
+ c_walk(tnd->init, 2 * IndentInc, 0);
+ prt_str(";", 2 * IndentInc);
+ }
+ break;
+ case TndBlk:
+ /*
+ * A tended block pointer of some kind.
+ */
+ prt_str(tendstrct, IndentInc);
+ if (tnd->init == NULL)
+ fprintf(out_file, ".d[%d] = nullptr;", tnd->t_indx);
+ else {
+ fprintf(out_file, ".d[%d].dword = F_Ptr | F_Nqual;",tnd->t_indx);
+ ForceNl();
+ prt_str(tendstrct, IndentInc);
+ fprintf(out_file, ".d[%d].vword.bptr = (union block *)",
+ tnd->t_indx);
+ c_walk(tnd->init, 2 * IndentInc, 0);
+ prt_str(";", 2 * IndentInc);
+ }
+ break;
+ }
+ ForceNl();
+ }
+ }
+
+/*
+ * parm_tnd - produce code to put a parameter in its tended location.
+ */
+static void parm_tnd(sym)
+struct sym_entry *sym;
+ {
+ /*
+ * A parameter may either be dereferenced into its tended location
+ * or copied.
+ */
+ if (sym->id_type & DrfPrm) {
+ prt_str("deref(&r_args[", IndentInc * 2);
+ fprintf(out_file, "%d], &%s.d[%d]);", sym->u.param_info.param_num,
+ tendstrct, sym->t_indx);
+ }
+ else {
+ prt_str(tendstrct, IndentInc * 2);
+ fprintf(out_file, ".d[%d] = r_args[%d];", sym->t_indx,
+ sym->u.param_info.param_num);
+ }
+ }
+
+/*
+ * parm_locs - determine what locations are needed to hold parameters and
+ * their conversions. Produce declarations for the C_integer and C_double
+ * locations.
+ */
+static void parm_locs(op_params)
+struct sym_entry *op_params;
+ {
+ struct sym_entry *next_parm;
+
+ /*
+ * Parameters are stored in reverse order: Recurse down the list
+ * and perform processing on the way back.
+ */
+ if (op_params == NULL)
+ return;
+ next_parm = op_params->u.param_info.next;
+ parm_locs(next_parm);
+
+ /*
+ * For interpreter routines, extra tended descriptors are only needed
+ * when both dereferenced and undereferenced values are requested.
+ */
+ if (iconx_flg && (next_parm == NULL ||
+ op_params->u.param_info.param_num != next_parm->u.param_info.param_num))
+ op_params->t_indx = -1;
+ else
+ op_params->t_indx = ntend++;
+ if (op_params->u.param_info.non_tend & PrmInt) {
+ prt_str("C_integer r_i", IndentInc);
+ fprintf(out_file, "%d;", op_params->u.param_info.param_num);
+ ForceNl();
+ }
+ if (op_params->u.param_info.non_tend & PrmDbl) {
+ prt_str("double r_d", IndentInc);
+ fprintf(out_file, "%d;", op_params->u.param_info.param_num);
+ ForceNl();
+ }
+ }
+
+/*
+ * real_def - see if a declaration really defines storage.
+ */
+static int real_def(n)
+struct node *n;
+ {
+ struct node *dcl_lst;
+
+ dcl_lst = n->u[1].child;
+ /*
+ * If no variables are being defined this must be a tag declaration.
+ */
+ if (dcl_lst == NULL)
+ return 0;
+
+ if (only_proto(dcl_lst))
+ return 0;
+
+ if (tdef_or_extr(n->u[0].child))
+ return 0;
+
+ return 1;
+ }
+
+/*
+ * only_proto - see if this declarator list contains only function prototypes.
+ */
+static int only_proto(n)
+struct node *n;
+ {
+ switch (n->nd_id) {
+ case CommaNd:
+ return only_proto(n->u[0].child) & only_proto(n->u[1].child);
+ case ConCatNd:
+ /*
+ * Optional pointer.
+ */
+ return only_proto(n->u[1].child);
+ case BinryNd:
+ switch (n->tok->tok_id) {
+ case '=':
+ return only_proto(n->u[0].child);
+ case '[':
+ /*
+ * At this point, assume array declarator is not part of
+ * prototype.
+ */
+ return 0;
+ case ')':
+ /*
+ * Prototype (or forward declaration).
+ */
+ return 1;
+ }
+ case PrefxNd:
+ /*
+ * Parenthesized.
+ */
+ return only_proto(n->u[0].child);
+ case PrimryNd:
+ /*
+ * At this point, assume it is not a prototype.
+ */
+ return 0;
+ }
+ err1("rtt internal error detected in function only_proto()");
+ /*NOTREACHED*/
+ return 0; /* avoid gcc warning */
+ }
+
+/*
+ * tdef_or_extr - see if this is a typedef or extern.
+ */
+static int tdef_or_extr(n)
+struct node *n;
+ {
+ switch (n->nd_id) {
+ case LstNd:
+ return tdef_or_extr(n->u[0].child) | tdef_or_extr(n->u[1].child);
+ case BinryNd:
+ /*
+ * struct, union, or enum.
+ */
+ return 0;
+ case PrimryNd:
+ if (n->tok->tok_id == Extern || n->tok->tok_id == Typedef)
+ return 1;
+ else
+ return 0;
+ }
+ err1("rtt internal error detected in function tdef_or_extr()");
+ /*NOTREACHED*/
+ return 0; /* avoid gcc warning */
+ }
+
+/*
+ * dclout - output an ordinary global C declaration.
+ */
+void dclout(n)
+struct node *n;
+ {
+ if (!enable_out)
+ return; /* output disabled */
+ if (real_def(n))
+ def_fnd = 1; /* this declaration defines a run-time object */
+ c_walk(n, 0, 0);
+ free_tree(n);
+ }
+
+/*
+ * fncout - output code for a C function.
+ */
+void fncout(head, prm_dcl, block)
+struct node *head;
+struct node *prm_dcl;
+struct node *block;
+ {
+ if (!enable_out)
+ return; /* output disabled */
+
+ def_fnd = 1; /* this declaration defines a run-time object */
+
+ nxt_sbuf = 0; /* clear number of string buffers */
+ nxt_cbuf = 0; /* clear number of cset buffers */
+
+ /*
+ * Output the function header and the parameter declarations.
+ */
+ fnc_head = head;
+ c_walk(head, 0, 0);
+ prt_str(" ", 0);
+ c_walk(prm_dcl, 0, 0);
+ prt_str(" ", 0);
+
+ /*
+ * Handle outer block.
+ */
+ prt_tok(block->tok, IndentInc); /* { */
+ c_walk(block->u[0].child, IndentInc, 0); /* non-tended declarations */
+ spcl_dcls(NULL); /* tended declarations */
+ no_ret_val = 1;
+ c_walk(block->u[2].child, IndentInc, 0); /* statement list */
+ if (ntend != 0 && no_ret_val) {
+ /*
+ * This function contains no return statements with values, assume
+ * that the programmer is using the implicit return at the end
+ * of the function and update the tending of descriptors.
+ */
+ untend(IndentInc);
+ }
+ ForceNl();
+ prt_str("}", IndentInc);
+ ForceNl();
+
+ /*
+ * free storage.
+ */
+ free_tree(head);
+ free_tree(prm_dcl);
+ free_tree(block);
+ pop_cntxt();
+ clr_def();
+ }
+
+/*
+ * defout - output operation definitions (except for constant keywords)
+ */
+void defout(n)
+struct node *n;
+ {
+ struct sym_entry *sym, *sym1;
+
+ if (!enable_out)
+ return; /* output disabled */
+
+ nxt_sbuf = 0;
+ nxt_cbuf = 0;
+
+ /*
+ * Somewhat different code is produced for the interpreter and compiler.
+ */
+ if (iconx_flg)
+ interp_def(n);
+ else
+ comp_def(n);
+
+ free_tree(n);
+ /*
+ * The declarations for the declare statement are not associated with
+ * any compound statement and must be freed here.
+ */
+ sym = dcl_stk->tended;
+ while (sym != NULL) {
+ sym1 = sym;
+ sym = sym->u.tnd_var.next;
+ free_sym(sym1);
+ }
+ while (decl_lst != NULL) {
+ sym1 = decl_lst;
+ decl_lst = decl_lst->u.declare_var.next;
+ free_sym(sym1);
+ }
+ op_type = OrdFunc;
+ pop_cntxt();
+ clr_def();
+ }
+
+/*
+ * comp_def - output code for the compiler for operation definitions.
+ */
+static void comp_def(n)
+struct node *n;
+ {
+ #ifdef Rttx
+ fprintf(stdout,
+ "rtt was compiled to only support the interpreter, use -x\n");
+ exit(EXIT_FAILURE);
+ #else /* Rttx */
+ struct sym_entry *sym;
+ struct node *n1;
+ FILE *f_save;
+
+ char buf1[5];
+ char buf[MaxPath];
+ char *cname;
+ long min_result;
+ long max_result;
+ int ret_flag;
+ int resume;
+ char *name;
+ char *s;
+
+ f_save = out_file;
+
+ /*
+ * Note if the result location is explicitly referenced and note
+ * how it is accessed in the generated code.
+ */
+ cur_impl->use_rslt = sym_lkup(str_rslt)->u.referenced;
+ rslt_loc = "(*r_rslt)";
+
+ /*
+ * In several contexts, letters are used to distinguish kinds of operations.
+ */
+ switch (op_type) {
+ case TokFunction:
+ lc_letter = 'f';
+ uc_letter = 'F';
+ break;
+ case Keyword:
+ lc_letter = 'k';
+ uc_letter = 'K';
+ break;
+ case Operator:
+ lc_letter = 'o';
+ uc_letter = 'O';
+ }
+ prfx1 = cur_impl->prefix[0];
+ prfx2 = cur_impl->prefix[1];
+
+ if (op_type != Keyword) {
+ /*
+ * First pass through the operation: produce most general routine.
+ */
+ fnc_ret = RetSig; /* most general routine always returns a signal */
+
+ /*
+ * Compute the file name in which to output the function.
+ */
+ sprintf(buf1, "%c_%c%c", lc_letter, prfx1, prfx2);
+ cname = salloc(makename(buf, SourceDir, buf1, CSuffix));
+ if ((out_file = fopen(cname, "w")) == NULL)
+ err2("cannot open output file", cname);
+ else
+ addrmlst(cname, out_file);
+
+ prologue(); /* output standard comments and preprocessor directives */
+
+ /*
+ * Output function header that corresponds to standard calling
+ * convensions. The function name is constructed from the letter
+ * for the operation type, the prefix that makes the function
+ * name unique, and the name of the operation.
+ */
+ fprintf(out_file, "int %c%c%c_%s(r_nargs, r_args, r_rslt, r_s_cont)\n",
+ uc_letter, prfx1, prfx2, cur_impl->name);
+ fprintf(out_file, "int r_nargs;\n");
+ fprintf(out_file, "dptr r_args;\n");
+ fprintf(out_file, "dptr r_rslt;\n");
+ fprintf(out_file, "continuation r_s_cont;");
+ fname = cname;
+ line = 12;
+ ForceNl();
+ prt_str("{", IndentInc);
+ ForceNl();
+
+ /*
+ * Output ordinary declarations from declare clause.
+ */
+ for (sym = decl_lst; sym != NULL; sym = sym->u.declare_var.next) {
+ c_walk(sym->u.declare_var.tqual, IndentInc, 0);
+ prt_str(" ", IndentInc);
+ c_walk(sym->u.declare_var.dcltor, IndentInc, 0);
+ if ((n1 = sym->u.declare_var.init) != NULL) {
+ prt_str(" = ", IndentInc);
+ c_walk(n1, IndentInc, 0);
+ }
+ prt_str(";", IndentInc);
+ }
+
+ /*
+ * Output code for special declarations along with code to initial
+ * them. This includes buffers and tended locations for parameters
+ * and tended variables.
+ */
+ spcl_dcls(params);
+
+ if (rt_walk(n, IndentInc, 0)) { /* body of operation */
+ if (n->nd_id == ConCatNd)
+ s = n->u[1].child->tok->fname;
+ else
+ s = n->tok->fname;
+ fprintf(stderr, "%s: file %s, warning: ", progname, s);
+ fprintf(stderr, "execution may fall off end of operation \"%s\"\n",
+ cur_impl->name);
+ }
+
+ ForceNl();
+ prt_str("}\n", IndentInc);
+ if (fclose(out_file) != 0)
+ err2("cannot close ", cname);
+ put_c_fl(cname, 1); /* note name of output file for operation */
+ }
+
+ /*
+ * Second pass through operation: produce in-line code and special purpose
+ * routines.
+ */
+ for (sym = params; sym != NULL; sym = sym->u.param_info.next)
+ if (sym->id_type & DrfPrm)
+ sym->u.param_info.cur_loc = PrmTend; /* reset location of parameter */
+ in_line(n);
+
+ /*
+ * Insure that the fail/return/suspend statements are consistent
+ * with the result sequence indicated.
+ */
+ min_result = cur_impl->min_result;
+ max_result = cur_impl->max_result;
+ ret_flag = cur_impl->ret_flag;
+ resume = cur_impl->resume;
+ name = cur_impl->name;
+ if (min_result == NoRsltSeq && ret_flag & (DoesFail|DoesRet|DoesSusp))
+ err2(name,
+ ": result sequence of {}, but fail, return, or suspend present");
+ if (min_result != NoRsltSeq && ret_flag == 0)
+ err2(name,
+ ": result sequence indicated, no fail, return, or suspend present");
+ if (max_result != NoRsltSeq) {
+ if (max_result == 0 && ret_flag & (DoesRet|DoesSusp))
+ err2(name,
+ ": result sequence of 0 length, but return or suspend present");
+ if (max_result != 0 && !(ret_flag & (DoesRet | DoesSusp)))
+ err2(name,
+ ": result sequence length > 0, but no return or suspend present");
+ if ((max_result == UnbndSeq || max_result > 1 || resume) &&
+ !(ret_flag & DoesSusp))
+ err2(name,
+ ": result sequence indicates suspension, but no suspend present");
+ if ((max_result != UnbndSeq && max_result <= 1 && !resume) &&
+ ret_flag & DoesSusp)
+ err2(name,
+ ": result sequence indicates no suspension, but suspend present");
+ }
+ if (min_result != NoRsltSeq && max_result != UnbndSeq &&
+ min_result > max_result)
+ err2(name, ": minimum result sequence length greater than maximum");
+
+ out_file = f_save;
+#endif /* Rttx */
+ }
+
+/*
+ * interp_def - output code for the interpreter for operation definitions.
+ */
+static void interp_def(n)
+struct node *n;
+ {
+ struct sym_entry *sym;
+ struct node *n1;
+ int nparms;
+ int has_underef;
+ char letter;
+ char *name;
+ char *s;
+
+ /*
+ * Note how result location is accessed in generated code.
+ */
+ rslt_loc = "r_args[0]";
+
+ /*
+ * Determine if the operation has any undereferenced parameters.
+ */
+ has_underef = 0;
+ for (sym = params; sym != NULL; sym = sym->u.param_info.next)
+ if (sym->id_type & RtParm) {
+ has_underef = 1;
+ break;
+ }
+
+ /*
+ * Determine the nuber of parameters. A negative value is used
+ * to indicate an operation that takes a variable number of
+ * arguments.
+ */
+ if (params == NULL)
+ nparms = 0;
+ else {
+ nparms = params->u.param_info.param_num + 1;
+ if (params->id_type & VarPrm)
+ nparms = -nparms;
+ }
+
+ fnc_ret = RetSig; /* interpreter routine always returns a signal */
+ name = cur_impl->name;
+
+ /*
+ * Determine what letter is used to prefix the operation name.
+ */
+ switch (op_type) {
+ case TokFunction:
+ letter = 'Z';
+ break;
+ case Keyword:
+ letter = 'K';
+ break;
+ case Operator:
+ letter = 'O';
+ }
+
+ fprintf(out_file, "\n");
+ if (op_type != Keyword) {
+ /*
+ * Output prototype. Operations taking a variable number of arguments
+ * have an extra parameter: the number of arguments.
+ */
+ fprintf(out_file, "int %c%s (", letter, name);
+ if (params != NULL && (params->id_type & VarPrm))
+ fprintf(out_file, "int r_nargs, ");
+ fprintf(out_file, "dptr r_args);\n");
+ ++line;
+
+ /*
+ * Output procedure block.
+ */
+ switch (op_type) {
+ case TokFunction:
+ fprintf(out_file, "FncBlock(%s, %d, %d)\n\n", name, nparms,
+ (has_underef ? -1 : 0));
+ ++line;
+ break;
+ case Operator:
+ if (strcmp(cur_impl->op,"\\") == 0)
+ fprintf(out_file, "OpBlock(%s, %d, \"%s\", 0)\n\n", name, nparms,
+ "\\\\");
+ else
+ fprintf(out_file, "OpBlock(%s, %d, \"%s\", 0)\n\n", name, nparms,
+ cur_impl->op);
+ ++line;
+ }
+ }
+
+ /*
+ * Output function header. Operations taking a variable number of arguments
+ * have an extra parameter: the number of arguments.
+ */
+ fprintf(out_file, "int %c%s(", letter, name);
+ if (params != NULL && (params->id_type & VarPrm))
+ fprintf(out_file, "r_nargs, ");
+ fprintf(out_file, "r_args)\n");
+ ++line;
+ if (params != NULL && (params->id_type & VarPrm)) {
+ fprintf(out_file, "int r_nargs;\n");
+ ++line;
+ }
+ fprintf(out_file, "dptr r_args;");
+ ++line;
+ ForceNl();
+ prt_str("{", IndentInc);
+
+ /*
+ * Output ordinary declarations from the declare clause.
+ */
+ ForceNl();
+ for (sym = decl_lst; sym != NULL; sym = sym->u.declare_var.next) {
+ c_walk(sym->u.declare_var.tqual, IndentInc, 0);
+ prt_str(" ", IndentInc);
+ c_walk(sym->u.declare_var.dcltor, IndentInc, 0);
+ if ((n1 = sym->u.declare_var.init) != NULL) {
+ prt_str(" = ", IndentInc);
+ c_walk(n1, IndentInc, 0);
+ }
+ prt_str(";", IndentInc);
+ }
+
+ /*
+ * Output special declarations and initial processing.
+ */
+ tendstrct = "r_tend";
+ spcl_start(params);
+ tend_ary(ntend);
+ if (has_underef && params != NULL && params->id_type == (VarPrm | DrfPrm))
+ prt_str("int r_n;\n", IndentInc);
+ tend_init();
+
+ /*
+ * See which parameters need to be dereferenced. If all are dereferenced,
+ * it is done by before the routine is called.
+ */
+ if (has_underef) {
+ sym = params;
+ if (sym != NULL && sym->id_type & VarPrm) {
+ if (sym->id_type & DrfPrm) {
+ /*
+ * There is a variable part of the parameter list and it
+ * must be dereferenced.
+ */
+ prt_str("for (r_n = ", IndentInc);
+ fprintf(out_file, "%d; r_n <= r_nargs; ++r_n)",
+ sym->u.param_info.param_num + 1);
+ ForceNl();
+ prt_str("Deref(r_args[r_n]);", IndentInc * 2);
+ ForceNl();
+ }
+ sym = sym->u.param_info.next;
+ }
+
+ /*
+ * Produce code to dereference any fixed parameters that need to be.
+ */
+ while (sym != NULL) {
+ if (sym->id_type & DrfPrm) {
+ /*
+ * Tended index of -1 indicates that the parameter can be
+ * dereferened in-place (this is the usual case).
+ */
+ if (sym->t_indx == -1) {
+ prt_str("Deref(r_args[", IndentInc * 2);
+ fprintf(out_file, "%d]);", sym->u.param_info.param_num + 1);
+ }
+ else {
+ prt_str("deref(&r_args[", IndentInc * 2);
+ fprintf(out_file, "%d], &r_tend.d[%d]);",
+ sym->u.param_info.param_num + 1, sym->t_indx);
+ }
+ }
+ ForceNl();
+ sym = sym->u.param_info.next;
+ }
+ }
+
+ /*
+ * Finish setting up the tended array structure and link it into the tended
+ * list.
+ */
+ if (ntend != 0) {
+ prt_str("r_tend.num = ", IndentInc);
+ fprintf(out_file, "%d;", ntend);
+ ForceNl();
+ prt_str("r_tend.previous = tend;", IndentInc);
+ ForceNl();
+ prt_str("tend = (struct tend_desc *)&r_tend;", IndentInc);
+ ForceNl();
+ }
+
+ if (rt_walk(n, IndentInc, 0)) { /* body of operation */
+ if (n->nd_id == ConCatNd)
+ s = n->u[1].child->tok->fname;
+ else
+ s = n->tok->fname;
+ fprintf(stderr, "%s: file %s, warning: ", progname, s);
+ fprintf(stderr, "execution may fall off end of operation \"%s\"\n",
+ cur_impl->name);
+ }
+ ForceNl();
+ prt_str("}\n", IndentInc);
+ }
+
+/*
+ * keyconst - produce code for a constant keyword.
+ */
+void keyconst(t)
+struct token *t;
+ {
+ struct il_code *il;
+ int n;
+
+ if (iconx_flg) {
+ /*
+ * For the interpreter, output a C function implementing the keyword.
+ */
+ rslt_loc = "r_args[0]"; /* result location */
+
+ fprintf(out_file, "\n");
+ fprintf(out_file, "int K%s(r_args)\n", cur_impl->name);
+ fprintf(out_file, "dptr r_args;");
+ line += 2;
+ ForceNl();
+ prt_str("{", IndentInc);
+ ForceNl();
+ switch (t->tok_id) {
+ case StrLit:
+ prt_str(rslt_loc, IndentInc);
+ prt_str(".vword.sptr = \"", IndentInc);
+ n = prt_i_str(out_file, t->image, (int)strlen(t->image));
+ prt_str("\";", IndentInc);
+ ForceNl();
+ prt_str(rslt_loc, IndentInc);
+ fprintf(out_file, ".dword = %d;", n);
+ break;
+ case CharConst:
+ prt_str("static struct b_cset cset_blk = ", IndentInc);
+ cset_init(out_file, bitvect(t->image, (int)strlen(t->image)));
+ ForceNl();
+ prt_str(rslt_loc, IndentInc);
+ prt_str(".dword = D_Cset;", IndentInc);
+ ForceNl();
+ prt_str(rslt_loc, IndentInc);
+ prt_str(".vword.bptr = (union block *)&cset_blk;", IndentInc);
+ break;
+ case DblConst:
+ prt_str("static struct b_real real_blk = {T_Real, ", IndentInc);
+ fprintf(out_file, "%s};", t->image);
+ ForceNl();
+ prt_str(rslt_loc, IndentInc);
+ prt_str(".dword = D_Real;", IndentInc);
+ ForceNl();
+ prt_str(rslt_loc, IndentInc);
+ prt_str(".vword.bptr = (union block *)&real_blk;", IndentInc);
+ break;
+ case IntConst:
+ prt_str(rslt_loc, IndentInc);
+ prt_str(".dword = D_Integer;", IndentInc);
+ ForceNl();
+ prt_str(rslt_loc, IndentInc);
+ prt_str(".vword.integr = ", IndentInc);
+ prt_str(t->image, IndentInc);
+ prt_str(";", IndentInc);
+ break;
+ }
+ ForceNl();
+ prt_str("return A_Continue;", IndentInc);
+ ForceNl();
+ prt_str("}\n", IndentInc);
+ ++line;
+ ForceNl();
+ }
+ else {
+ /*
+ * For the compiler, make an entry in the data base for the keyword.
+ */
+ cur_impl->use_rslt = 0;
+
+ il = new_il(IL_Const, 2);
+ switch (t->tok_id) {
+ case StrLit:
+ il->u[0].n = str_typ;
+ il->u[1].s = alloc(strlen(t->image) + 3);
+ sprintf(il->u[1].s, "\"%s\"", t->image);
+ break;
+ case CharConst:
+ il->u[0].n = cset_typ;
+ il->u[1].s = alloc(strlen(t->image) + 3);
+ sprintf(il->u[1].s, "'%s'", t->image);
+ break;
+ case DblConst:
+ il->u[0].n = real_typ;
+ il->u[1].s = t->image;
+ break;
+ case IntConst:
+ il->u[0].n = int_typ;
+ il->u[1].s = t->image;
+ break;
+ }
+ cur_impl->in_line = il;
+ }
+
+ /*
+ * Reset the translator and free storage.
+ */
+ op_type = OrdFunc;
+ free_t(t);
+ pop_cntxt();
+ clr_def();
+ }
+
+/*
+ * keepdir - A preprocessor directive to be kept has been encountered.
+ * If it is #passthru, print just the body of the directive, otherwise
+ * print the whole thing.
+ */
+void keepdir(t)
+struct token *t;
+ {
+ char *s;
+
+ tok_line(t, 0);
+ s = t->image;
+ if (strncmp(s, "#passthru", 9) == 0)
+ s = s + 10;
+ fprintf(out_file, "%s\n", s);
+ line += 1;
+ }
+
+/*
+ * prologue - print standard comments and preprocessor directives at the
+ * start of an output file.
+ */
+void prologue()
+ {
+ id_comment(out_file);
+ fprintf(out_file, "%s", compiler_def);
+ fprintf(out_file, "#include \"%s\"\n\n", inclname);
+ }
diff --git a/src/rtt/rttparse.c b/src/rtt/rttparse.c
new file mode 100644
index 0000000..9f18ec1
--- /dev/null
+++ b/src/rtt/rttparse.c
@@ -0,0 +1,2992 @@
+
+# line 7 "rttgram.y"
+#include "rtt1.h"
+#define YYMAXDEPTH 250
+
+# line 11 "rttgram.y"
+typedef union {
+ struct token *t;
+ struct node *n;
+ long i;
+ } YYSTYPE;
+# define Identifier 257
+# define StrLit 258
+# define LStrLit 259
+# define FltConst 260
+# define DblConst 261
+# define LDblConst 262
+# define CharConst 263
+# define LCharConst 264
+# define IntConst 265
+# define UIntConst 266
+# define LIntConst 267
+# define ULIntConst 268
+# define Arrow 269
+# define Incr 270
+# define Decr 271
+# define LShft 272
+# define RShft 273
+# define Leq 274
+# define Geq 275
+# define TokEqual 276
+# define Neq 277
+# define And 278
+# define Or 279
+# define MultAsgn 280
+# define DivAsgn 281
+# define ModAsgn 282
+# define PlusAsgn 283
+# define MinusAsgn 284
+# define LShftAsgn 285
+# define RShftAsgn 286
+# define AndAsgn 287
+# define XorAsgn 288
+# define OrAsgn 289
+# define Sizeof 290
+# define Intersect 291
+# define OpSym 292
+# define Typedef 293
+# define Extern 294
+# define Static 295
+# define Auto 296
+# define TokRegister 297
+# define Tended 298
+# define TokChar 299
+# define TokShort 300
+# define Int 301
+# define TokLong 302
+# define Signed 303
+# define Unsigned 304
+# define Float 305
+# define Doubl 306
+# define Const 307
+# define Volatile 308
+# define Void 309
+# define TypeDefName 310
+# define Struct 311
+# define Union 312
+# define TokEnum 313
+# define Ellipsis 314
+# define Case 315
+# define Default 316
+# define If 317
+# define Else 318
+# define Switch 319
+# define While 320
+# define Do 321
+# define For 322
+# define Goto 323
+# define Continue 324
+# define Break 325
+# define Return 326
+# define Runerr 327
+# define Is 328
+# define Cnv 329
+# define Def 330
+# define Exact 331
+# define Empty_type 332
+# define IconType 333
+# define Component 334
+# define Variable 335
+# define Any_value 336
+# define Named_var 337
+# define Struct_var 338
+# define C_Integer 339
+# define Arith_case 340
+# define C_Double 341
+# define C_String 342
+# define Tmp_string 343
+# define Tmp_cset 344
+# define Body 345
+# define End 346
+# define TokFunction 347
+# define Keyword 348
+# define Operator 349
+# define Underef 350
+# define Declare 351
+# define Suspend 352
+# define Fail 353
+# define Inline 354
+# define Abstract 355
+# define Store 356
+# define TokType 357
+# define New 358
+# define All_fields 359
+# define Then 360
+# define Type_case 361
+# define Of 362
+# define Len_case 363
+# define Constant 364
+# define Errorfail 365
+# define IfStmt 366
+#define yyclearin yychar = -1
+#define yyerrok yyerrflag = 0
+extern int yychar;
+extern int yyerrflag;
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 150
+#endif
+YYSTYPE yylval, yyval;
+# define YYERRCODE 256
+
+# line 1089 "rttgram.y"
+
+
+/*
+ * xfree(p) -- used with free(p) macro to avoid compiler errors from
+ * miscast free calls generated by Yacc.
+ */
+static void xfree(p)
+char *p;
+{
+ free(p);
+}
+
+#define free(p) xfree((char*)p)
+int yyexca[] ={
+-1, 0,
+ 0, 279,
+ 258, 299,
+ 347, 299,
+ 348, 299,
+ 349, 299,
+ -2, 193,
+-1, 1,
+ 0, -1,
+ -2, 0,
+-1, 2,
+ 0, 280,
+ 258, 299,
+ 347, 299,
+ 348, 299,
+ 349, 299,
+ -2, 193,
+-1, 51,
+ 44, 113,
+ 59, 113,
+ -2, 290,
+-1, 58,
+ 44, 115,
+ 59, 115,
+ -2, 289,
+-1, 100,
+ 123, 166,
+ -2, 168,
+-1, 138,
+ 125, 257,
+ 59, 86,
+ -2, 230,
+-1, 238,
+ 125, 257,
+ 59, 86,
+ -2, 230,
+-1, 239,
+ 125, 258,
+ 59, 86,
+ -2, 230,
+-1, 255,
+ 58, 293,
+ -2, 1,
+-1, 256,
+ 58, 294,
+ -2, 98,
+-1, 262,
+ 59, 86,
+ -2, 230,
+-1, 308,
+ 41, 212,
+ -2, 193,
+-1, 371,
+ 41, 204,
+ 44, 204,
+ -2, 193,
+-1, 396,
+ 59, 86,
+ -2, 230,
+-1, 398,
+ 59, 86,
+ -2, 230,
+-1, 452,
+ 41, 214,
+ 44, 214,
+ -2, 194,
+-1, 516,
+ 59, 86,
+ -2, 230,
+-1, 545,
+ 40, 193,
+ 91, 193,
+ -2, 219,
+-1, 617,
+ 293, 219,
+ 294, 219,
+ 295, 219,
+ 296, 219,
+ 297, 219,
+ 299, 219,
+ 300, 219,
+ 301, 219,
+ 302, 219,
+ 303, 219,
+ 304, 219,
+ 305, 219,
+ 306, 219,
+ 307, 219,
+ 308, 219,
+ 309, 219,
+ 310, 219,
+ 311, 219,
+ 312, 219,
+ 313, 219,
+ 41, 219,
+ 339, 219,
+ 341, 219,
+ 342, 219,
+ -2, 193,
+-1, 624,
+ 59, 86,
+ -2, 230,
+-1, 625,
+ 59, 86,
+ -2, 230,
+-1, 627,
+ 59, 86,
+ -2, 230,
+-1, 677,
+ 59, 86,
+ -2, 230,
+-1, 725,
+ 59, 86,
+ -2, 230,
+-1, 730,
+ 58, 453,
+ -2, 317,
+-1, 731,
+ 58, 454,
+ -2, 321,
+-1, 732,
+ 58, 455,
+ -2, 324,
+-1, 733,
+ 58, 456,
+ -2, 337,
+-1, 771,
+ 59, 86,
+ -2, 230,
+-1, 792,
+ 59, 86,
+ -2, 230,
+ };
+# define YYNPROD 481
+# define YYLAST 3082
+int yyact[]={
+
+ 166, 644, 439, 665, 196, 272, 241, 718, 245, 720,
+ 565, 350, 645, 16, 676, 257, 63, 657, 105, 9,
+ 662, 9, 646, 492, 365, 212, 552, 370, 104, 8,
+ 358, 8, 11, 658, 240, 88, 186, 50, 143, 234,
+ 222, 346, 58, 638, 97, 97, 227, 761, 271, 213,
+ 420, 486, 140, 484, 97, 147, 745, 98, 98, 12,
+ 478, 51, 642, 551, 193, 13, 475, 98, 728, 55,
+ 118, 120, 119, 541, 146, 56, 683, 25, 238, 709,
+ 523, 746, 684, 90, 436, 437, 364, 438, 435, 137,
+ 725, 652, 553, 553, 345, 436, 437, 123, 438, 435,
+ 436, 437, 179, 438, 435, 347, 348, 349, 666, 93,
+ 132, 663, 23, 24, 144, 18, 19, 20, 21, 22,
+ 144, 33, 34, 35, 36, 39, 40, 37, 38, 23,
+ 24, 32, 308, 45, 46, 44, 97, 307, 141, 255,
+ 132, 132, 185, 181, 132, 180, 141, 182, 393, 98,
+ 670, 144, 256, 191, 56, 165, 301, 780, 751, 15,
+ 394, 395, 713, 228, 189, 55, 696, 184, 53, 479,
+ 124, 56, 288, 789, 154, 663, 446, 215, 650, 317,
+ 560, 318, 223, 246, 274, 315, 316, 695, 490, 298,
+ 321, 322, 312, 61, 183, 336, 214, 237, 338, 334,
+ 337, 131, 339, 412, 351, 352, 295, 297, 215, 299,
+ 820, 360, 800, 328, 127, 200, 31, 368, 770, 18,
+ 19, 20, 21, 22, 756, 691, 612, 306, 233, 384,
+ 510, 128, 132, 23, 24, 373, 422, 97, 496, 255,
+ 255, 491, 476, 215, 305, 372, 390, 384, 387, 786,
+ 98, 626, 256, 391, 561, 559, 138, 235, 477, 130,
+ 332, 313, 214, 255, 53, 409, 236, 53, 211, 406,
+ 210, 53, 750, 389, 378, 88, 391, 209, 391, 382,
+ 215, 423, 135, 413, 413, 215, 126, 59, 802, 53,
+ 738, 92, 97, 97, 200, 420, 429, 397, 690, 214,
+ 660, 95, 100, 215, 214, 98, 98, 447, 357, 404,
+ 509, 110, 471, 363, 312, 637, 700, 421, 651, 696,
+ 765, 485, 214, 312, 312, 434, 781, 385, 383, 114,
+ 368, 108, 226, 545, 696, 696, 334, 425, 426, 399,
+ 695, 218, 772, 215, 535, 306, 334, 768, 373, 306,
+ 666, 188, 451, 735, 351, 695, 695, 215, 372, 220,
+ 194, 215, 468, 469, 470, 487, 636, 764, 521, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 546, 97, 452, 480, 287, 347,
+ 348, 349, 230, 319, 320, 512, 514, 255, 98, 255,
+ 52, 190, 187, 515, 500, 517, 518, 671, 448, 202,
+ 391, 474, 391, 228, 31, 501, 472, 503, 629, 208,
+ 527, 528, 529, 524, 507, 122, 531, 505, 144, 223,
+ 511, 49, 205, 55, 359, 508, 388, 206, 432, 56,
+ 530, 215, 454, 455, 488, 489, 207, 201, 408, 452,
+ 220, 519, 520, 203, 522, 204, 195, 433, 457, 456,
+ 214, 533, 424, 458, 459, 386, 466, 467, 453, 440,
+ 436, 437, 417, 438, 435, 441, 121, 442, 443, 444,
+ 445, 23, 24, 554, 526, 557, 558, 543, 202, 464,
+ 465, 525, 566, 419, 649, 647, 648, 566, 208, 614,
+ 418, 696, 411, 63, 556, 567, 215, 613, 142, 389,
+ 567, 205, 460, 461, 462, 463, 206, 255, 373, 361,
+ 362, 555, 695, 621, 611, 207, 201, 616, 372, 410,
+ 391, 502, 203, 420, 204, 401, 53, 818, 290, 242,
+ 5, 31, 5, 631, 291, 632, 633, 534, 635, 430,
+ 431, 107, 53, 331, 618, 380, 619, 229, 376, 31,
+ 215, 341, 215, 351, 815, 351, 620, 810, 113, 107,
+ 379, 771, 640, 375, 664, 224, 667, 643, 759, 214,
+ 758, 214, 659, 112, 106, 757, 715, 712, 103, 289,
+ 215, 516, 483, 482, 481, 398, 396, 381, 377, 304,
+ 303, 164, 215, 302, 697, 775, 159, 327, 178, 630,
+ 160, 161, 325, 162, 323, 798, 324, 326, 799, 794,
+ 755, 214, 795, 452, 753, 255, 255, 754, 255, 672,
+ 734, 673, 674, 420, 678, 669, 685, 627, 391, 391,
+ 420, 391, 139, 625, 692, 680, 420, 682, 693, 659,
+ 123, 562, 701, 702, 351, 351, 351, 703, 373, 499,
+ 677, 498, 686, 710, 689, 704, 705, 706, 372, 721,
+ 624, 699, 622, 420, 708, 623, 420, 679, 494, 659,
+ 563, 711, 714, 564, 536, 812, 729, 537, 736, 31,
+ 727, 737, 215, 811, 163, 452, 741, 806, 659, 351,
+ 711, 790, 749, 494, 493, 453, 373, 742, 743, 677,
+ 747, 214, 739, 797, 449, 792, 372, 420, 777, 776,
+ 760, 762, 774, 766, 566, 763, 255, 752, 740, 724,
+ 717, 716, 769, 688, 767, 681, 634, 567, 547, 391,
+ 538, 497, 450, 330, 217, 748, 698, 668, 655, 654,
+ 779, 773, 653, 628, 542, 540, 539, 407, 405, 403,
+ 782, 783, 784, 402, 785, 787, 721, 292, 293, 294,
+ 400, 356, 353, 314, 355, 788, 3, 502, 354, 47,
+ 791, 793, 641, 796, 342, 719, 723, 495, 117, 801,
+ 803, 721, 192, 255, 116, 115, 60, 807, 804, 805,
+ 808, 10, 48, 6, 4, 809, 391, 2, 392, 249,
+ 687, 639, 216, 329, 136, 813, 814, 99, 506, 817,
+ 816, 200, 504, 819, 1, 75, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 778, 150, 151,
+ 550, 164, 549, 661, 344, 675, 159, 726, 178, 707,
+ 160, 161, 656, 162, 343, 197, 199, 198, 153, 340,
+ 7, 18, 19, 20, 21, 22, 243, 33, 34, 35,
+ 36, 39, 40, 37, 38, 23, 24, 32, 26, 45,
+ 46, 44, 253, 247, 248, 258, 252, 259, 261, 262,
+ 263, 264, 265, 266, 267, 254, 156, 157, 158, 73,
+ 71, 74, 69, 87, 67, 77, 81, 27, 75, 28,
+ 29, 84, 83, 68, 72, 251, 250, 239, 86, 70,
+ 268, 269, 76, 65, 80, 85, 78, 66, 82, 260,
+ 79, 101, 102, 270, 163, 244, 273, 544, 366, 369,
+ 367, 599, 62, 109, 605, 582, 600, 568, 594, 604,
+ 571, 597, 589, 592, 598, 607, 584, 578, 573, 609,
+ 608, 26, 601, 606, 580, 42, 570, 576, 588, 579,
+ 603, 610, 577, 585, 587, 574, 569, 595, 596, 590,
+ 572, 575, 73, 71, 74, 69, 87, 67, 77, 81,
+ 27, 225, 28, 29, 84, 83, 68, 72, 586, 591,
+ 593, 86, 70, 602, 583, 76, 65, 80, 85, 78,
+ 66, 82, 164, 79, 221, 202, 581, 159, 133, 178,
+ 129, 160, 161, 41, 162, 208, 309, 54, 17, 371,
+ 436, 437, 276, 438, 435, 148, 428, 149, 205, 155,
+ 744, 694, 335, 206, 43, 275, 152, 0, 0, 0,
+ 0, 0, 207, 201, 0, 0, 111, 0, 0, 203,
+ 0, 204, 0, 0, 0, 75, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 0, 150, 151,
+ 33, 34, 35, 36, 39, 40, 37, 38, 23, 24,
+ 32, 0, 45, 46, 44, 0, 0, 0, 153, 0,
+ 0, 0, 0, 0, 0, 163, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 26, 75,
+ 0, 0, 0, 247, 248, 258, 0, 259, 261, 262,
+ 263, 264, 265, 266, 267, 254, 156, 157, 158, 73,
+ 71, 74, 69, 87, 67, 77, 81, 27, 0, 28,
+ 29, 84, 83, 68, 72, 0, 0, 0, 86, 70,
+ 268, 269, 76, 65, 80, 85, 78, 66, 82, 260,
+ 79, 164, 26, 270, 0, 0, 159, 0, 178, 0,
+ 160, 161, 0, 162, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 73, 71, 74, 69, 87, 67, 77,
+ 81, 27, 0, 28, 29, 84, 83, 68, 72, 0,
+ 0, 0, 86, 70, 0, 0, 76, 65, 80, 85,
+ 78, 66, 82, 0, 79, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 75, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 0, 150,
+ 151, 277, 278, 279, 280, 281, 282, 283, 284, 285,
+ 286, 0, 0, 0, 163, 0, 0, 0, 0, 153,
+ 0, 0, 0, 75, 0, 0, 0, 0, 33, 34,
+ 35, 36, 39, 40, 37, 38, 23, 24, 32, 26,
+ 45, 46, 44, 164, 0, 0, 0, 0, 159, 0,
+ 178, 0, 160, 161, 0, 162, 0, 156, 157, 158,
+ 73, 71, 74, 69, 87, 67, 77, 81, 27, 0,
+ 28, 29, 84, 83, 68, 72, 26, 0, 0, 86,
+ 70, 0, 0, 76, 65, 80, 85, 78, 66, 82,
+ 0, 79, 0, 0, 0, 0, 0, 73, 71, 74,
+ 69, 87, 67, 77, 81, 27, 0, 28, 29, 84,
+ 83, 68, 72, 0, 0, 0, 86, 70, 0, 0,
+ 76, 65, 80, 85, 78, 66, 82, 0, 79, 0,
+ 0, 0, 0, 0, 0, 0, 163, 0, 0, 0,
+ 0, 0, 0, 0, 0, 75, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 0, 150, 151,
+ 0, 164, 0, 0, 0, 0, 159, 0, 178, 0,
+ 160, 161, 0, 162, 0, 0, 0, 0, 153, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 258, 0, 259, 261, 262,
+ 263, 264, 265, 266, 267, 254, 156, 157, 158, 73,
+ 71, 74, 69, 87, 67, 77, 81, 0, 0, 0,
+ 0, 84, 83, 68, 72, 0, 0, 0, 86, 70,
+ 268, 269, 76, 65, 80, 85, 78, 66, 82, 260,
+ 79, 0, 0, 270, 163, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 75, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 0,
+ 150, 151, 0, 0, 164, 0, 0, 0, 0, 159,
+ 0, 178, 0, 160, 161, 0, 162, 0, 0, 0,
+ 153, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 258, 0, 259,
+ 261, 262, 263, 264, 265, 266, 267, 254, 156, 157,
+ 158, 73, 731, 732, 69, 733, 730, 77, 81, 0,
+ 0, 0, 0, 84, 83, 68, 72, 0, 0, 0,
+ 86, 70, 268, 269, 76, 65, 80, 85, 78, 66,
+ 82, 260, 79, 0, 145, 270, 532, 163, 0, 0,
+ 0, 0, 0, 0, 0, 75, 167, 168, 169, 170,
+ 171, 172, 173, 174, 175, 176, 177, 0, 150, 151,
+ 164, 0, 0, 0, 0, 159, 0, 178, 427, 160,
+ 161, 0, 162, 0, 0, 0, 0, 0, 153, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 164, 0, 0, 0, 0,
+ 159, 0, 178, 0, 160, 161, 0, 162, 0, 0,
+ 0, 0, 0, 0, 0, 0, 156, 157, 158, 73,
+ 71, 74, 69, 87, 67, 77, 81, 414, 374, 415,
+ 416, 84, 83, 68, 72, 0, 0, 0, 86, 70,
+ 0, 0, 76, 65, 80, 85, 78, 66, 82, 0,
+ 79, 0, 0, 163, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 75, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 0, 150, 151, 0, 0, 145, 0, 0, 163, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 153, 0, 164, 0, 0, 0, 0, 159, 0,
+ 178, 0, 160, 161, 0, 162, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 156,
+ 157, 158, 73, 71, 74, 69, 87, 67, 77, 81,
+ 0, 0, 0, 0, 84, 83, 68, 72, 0, 0,
+ 0, 86, 70, 0, 0, 76, 65, 80, 85, 78,
+ 66, 82, 0, 79, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 75, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 163, 150, 151, 0,
+ 0, 0, 33, 34, 35, 36, 39, 40, 37, 38,
+ 23, 24, 32, 26, 45, 46, 44, 153, 0, 75,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+ 177, 0, 150, 151, 0, 0, 0, 0, 0, 0,
+ 0, 0, 27, 0, 28, 29, 0, 0, 0, 0,
+ 0, 0, 153, 0, 0, 156, 157, 158, 73, 71,
+ 74, 69, 87, 67, 77, 81, 0, 0, 0, 0,
+ 84, 83, 68, 72, 0, 0, 0, 86, 70, 0,
+ 0, 76, 65, 80, 85, 78, 66, 82, 0, 79,
+ 156, 157, 158, 73, 71, 74, 69, 87, 67, 77,
+ 81, 0, 0, 0, 0, 84, 83, 68, 72, 0,
+ 0, 0, 86, 70, 0, 0, 76, 65, 80, 85,
+ 78, 66, 82, 0, 79, 0, 0, 75, 167, 168,
+ 169, 170, 171, 172, 173, 174, 175, 176, 177, 0,
+ 150, 151, 164, 0, 0, 0, 0, 159, 0, 300,
+ 0, 160, 161, 0, 162, 0, 0, 0, 0, 0,
+ 153, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 164, 0, 0,
+ 0, 0, 159, 0, 296, 0, 160, 161, 0, 162,
+ 0, 0, 0, 0, 0, 0, 0, 0, 156, 157,
+ 158, 73, 71, 74, 69, 87, 67, 77, 81, 75,
+ 219, 0, 0, 84, 83, 68, 72, 0, 0, 0,
+ 86, 70, 0, 0, 76, 65, 80, 85, 78, 66,
+ 82, 0, 79, 0, 0, 163, 0, 0, 0, 0,
+ 0, 75, 0, 0, 0, 18, 19, 20, 21, 22,
+ 0, 33, 34, 35, 36, 39, 40, 37, 38, 23,
+ 24, 32, 26, 45, 46, 44, 0, 0, 0, 0,
+ 163, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 73, 71, 74, 69, 87, 67, 77,
+ 81, 27, 0, 28, 29, 84, 83, 68, 72, 0,
+ 0, 0, 86, 70, 0, 0, 76, 65, 80, 85,
+ 78, 66, 82, 617, 79, 73, 71, 74, 69, 87,
+ 67, 77, 81, 0, 0, 0, 0, 84, 83, 68,
+ 72, 0, 0, 0, 722, 70, 0, 0, 76, 65,
+ 80, 85, 78, 66, 82, 0, 79, 0, 0, 96,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 546, 0, 75, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 0, 150,
+ 151, 0, 0, 0, 33, 34, 35, 36, 39, 40,
+ 37, 38, 23, 24, 32, 26, 45, 46, 44, 153,
+ 0, 75, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 0, 150, 151, 0, 0, 14, 0,
+ 0, 0, 0, 0, 27, 0, 28, 29, 57, 64,
+ 0, 0, 0, 0, 153, 0, 91, 156, 157, 158,
+ 73, 71, 74, 69, 87, 67, 77, 81, 0, 0,
+ 94, 0, 84, 83, 68, 72, 0, 0, 0, 86,
+ 70, 0, 0, 76, 65, 80, 85, 78, 66, 82,
+ 0, 79, 156, 157, 158, 73, 71, 74, 69, 87,
+ 67, 77, 81, 75, 0, 0, 0, 84, 83, 68,
+ 72, 0, 0, 0, 86, 70, 0, 0, 76, 65,
+ 80, 85, 78, 66, 82, 0, 79, 57, 0, 0,
+ 0, 125, 0, 0, 0, 94, 0, 0, 0, 0,
+ 0, 0, 0, 0, 57, 0, 0, 0, 0, 0,
+ 75, 0, 0, 0, 0, 0, 26, 0, 0, 0,
+ 0, 0, 0, 0, 0, 94, 94, 0, 0, 125,
+ 0, 94, 232, 0, 0, 0, 0, 73, 71, 74,
+ 69, 87, 67, 77, 81, 27, 0, 28, 29, 84,
+ 83, 68, 72, 0, 0, 0, 86, 70, 0, 0,
+ 76, 65, 80, 85, 78, 66, 82, 75, 79, 0,
+ 200, 0, 0, 200, 0, 0, 0, 310, 0, 0,
+ 0, 0, 0, 0, 73, 71, 74, 69, 87, 67,
+ 77, 81, 0, 0, 0, 0, 84, 83, 68, 72,
+ 0, 0, 0, 86, 70, 0, 0, 76, 65, 80,
+ 85, 78, 66, 82, 0, 79, 0, 94, 0, 0,
+ 513, 0, 0, 0, 0, 0, 75, 0, 0, 125,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 73, 71, 74, 69, 87, 67, 77, 81, 548,
+ 0, 0, 0, 84, 83, 68, 72, 0, 75, 31,
+ 86, 70, 0, 0, 76, 65, 80, 85, 78, 66,
+ 82, 0, 79, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 310,
+ 73, 71, 74, 69, 87, 67, 77, 81, 310, 310,
+ 0, 0, 84, 83, 68, 72, 0, 0, 0, 86,
+ 70, 0, 0, 76, 65, 80, 85, 78, 66, 82,
+ 0, 79, 73, 71, 74, 69, 87, 67, 77, 81,
+ 0, 0, 0, 0, 84, 83, 68, 72, 0, 0,
+ 0, 86, 70, 31, 0, 76, 65, 80, 85, 78,
+ 66, 82, 0, 79, 202, 0, 0, 202, 0, 229,
+ 0, 0, 57, 0, 208, 0, 0, 208, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 205, 0, 0,
+ 205, 0, 206, 473, 0, 206, 333, 0, 0, 0,
+ 0, 207, 201, 0, 207, 201, 0, 0, 203, 0,
+ 204, 203, 0, 204, 0, 0, 0, 18, 19, 20,
+ 21, 22, 243, 33, 34, 35, 36, 39, 40, 37,
+ 38, 23, 24, 32, 26, 45, 46, 44, 18, 19,
+ 20, 21, 22, 0, 33, 34, 35, 36, 39, 40,
+ 37, 38, 23, 24, 32, 26, 45, 46, 44, 615,
+ 30, 0, 0, 27, 0, 28, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 89, 0,
+ 0, 0, 0, 0, 27, 0, 28, 29, 18, 19,
+ 20, 21, 22, 243, 33, 34, 35, 36, 39, 40,
+ 37, 38, 23, 24, 32, 26, 45, 46, 44, 0,
+ 18, 19, 20, 21, 22, 0, 33, 34, 35, 36,
+ 39, 40, 37, 38, 23, 24, 32, 26, 45, 46,
+ 44, 0, 0, 0, 27, 0, 28, 29, 0, 0,
+ 0, 33, 34, 35, 36, 39, 40, 37, 38, 23,
+ 24, 32, 26, 45, 46, 44, 27, 134, 28, 29,
+ 18, 19, 20, 21, 22, 0, 33, 34, 35, 36,
+ 39, 40, 37, 38, 23, 24, 32, 26, 45, 46,
+ 44, 27, 0, 28, 29, 0, 0, 134, 134, 0,
+ 0, 134, 0, 0, 231, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 27, 0, 28, 29,
+ 33, 34, 35, 36, 39, 40, 37, 38, 23, 24,
+ 32, 26, 45, 46, 44, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 311,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 27, 0, 28, 29, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 134,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 311, 0, 0, 0, 0, 0, 0, 0, 0,
+ 311, 311 };
+int yypact[]={
+
+ 2527, -1000, 2527, -1000, -1000, -1000, -1000, -1000, 372, 2527,
+ -65, -1000, -1000, -1000, -1000, 2279, -74, -178, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, 174, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, 2116, 862, -1000, -1000, -1000, 2577, -1000,
+ 525, 270, -1000, 1016, 524, -1000, -1000, -1000, 268, -1000,
+ -277, -1000, 385, -1000, 647, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -74, -1000,
+ -1000, -1000, 174, -1000, -1000, 163, 2552, -1000, -1000, 159,
+ -1000, 133, 2577, -1000, 372, 2527, -1000, 647, 1652, 311,
+ -1000, 647, -1000, 647, 1652, -1000, -287, 92, 154, 147,
+ 145, 1760, -1000, 703, -1000, -1000, 2552, 1975, -1000, 517,
+ 2621, -1000, -195, 781, -1000, 862, 143, -1000, 568, -1000,
+ 270, 268, -1000, -1000, -1000, 1652, -1000, 971, 109, 498,
+ 2034, 2034, 1760, 1999, -122, -1000, 545, 542, 541, -1000,
+ -1000, -1000, -1000, -1000, -1000, 120, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 979, 167,
+ 735, -91, 119, -82, 571, 570, -1000, 1760, -1000, 702,
+ -1000, -1000, 171, 137, 2360, -63, -1000, -1000, -1000, -1000,
+ 171, -1000, 61, 2311, 2311, 732, -1000, -1000, 731, 169,
+ 169, 169, 220, -1000, -1000, -1000, 1842, -1000, 1593, -1000,
+ -1000, 514, -1000, 540, 1760, 511, -1000, -1000, 539, 1760,
+ -195, -1000, -1000, 203, -1000, 266, 862, 123, 568, 808,
+ -1000, -1000, -1000, -151, -1000, -1000, 538, 1760, 537, 133,
+ -1000, -1000, -1000, -1000, 730, -1000, -74, 476, 723, 719,
+ 1760, 718, 808, 717, 862, 470, 443, 1378, 1378, 441,
+ 434, 632, -1000, 192, -1000, 1760, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1760, 1760, 1760,
+ 1617, 862, 862, -1000, -1000, -1000, 1760, -1000, -1000, -1000,
+ 979, 1760, -232, 136, 136, 1760, 673, 701, 647, 2552,
+ 2552, -1000, -1000, 1760, 1760, 1760, 1760, 1760, 1760, 1760,
+ 1760, 1760, 1760, 1760, 1760, 1760, 1760, 1760, 219, 1842,
+ -1000, 2357, 2505, -1000, -1000, -280, -1000, -1000, -1000, -1000,
+ 117, 171, 135, -300, -109, -223, -1000, 536, 535, 534,
+ -309, 230, -311, 2311, 133, 133, -77, 116, 660, -1000,
+ -1000, -1000, 113, -1000, 700, -1000, 617, -1000, -1000, 615,
+ -1000, 647, -1000, 2577, -1000, -1000, 517, -1000, -1000, -1000,
+ 499, -1000, -1000, -1000, 862, 1760, 185, -1000, 105, -1000,
+ -1000, -1000, 647, -1000, 2220, 2311, 808, 533, 808, -1000,
+ 1760, -1000, 1760, 1760, 6, 1760, -240, 1760, 432, -1000,
+ -1000, -1000, 425, -1000, 1760, 1760, 1760, 381, -1000, -1000,
+ 1760, -1000, 1501, -1000, -122, 489, 251, -1000, 643, -1000,
+ -1000, -1000, 699, 120, 716, -1000, -1000, -1000, -1000, 715,
+ -1000, -1000, -1000, -1000, -1000, -1000, -258, 714, 167, -1000,
+ 1760, -1000, -1000, 293, -1000, -1000, 735, -91, 119, 119,
+ -82, -82, -82, -82, 571, 571, 570, 570, -1000, -1000,
+ -1000, -1000, 697, -1000, 2434, -1000, -1000, -263, 171, -223,
+ -1000, -232, 136, 136, 132, -85, 131, 607, -1000, -1000,
+ 639, 651, -1000, 169, -1000, 101, 651, -1000, 2311, 2455,
+ -1000, -1000, 2163, -1000, 1760, -1000, 1760, -1000, -1000, -1000,
+ -1000, 507, -1000, -1000, -1000, -1000, 808, -1000, 631, 629,
+ 602, 128, 596, 713, 359, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, 1760, -1000, -1000, 1760, -1000, 1760,
+ 1760, 695, 1760, -1000, 275, 647, 1760, -1000, -1000, -1000,
+ -264, 138, -1000, 227, -227, -1000, 712, 709, 708, -232,
+ 207, -90, 2311, 291, 2311, 707, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+ -1000, 635, -142, -1000, -1000, -1000, -1000, 647, -1000, -1000,
+ -1000, -1000, 348, 1760, 808, 808, -232, 808, 1760, 1760,
+ -1000, -1000, 694, 603, -257, 592, 1760, -1000, 692, 2577,
+ 205, 100, 138, -1000, 49, 558, -1000, 706, -232, 225,
+ 138, 138, 171, 2311, 2311, 2311, -237, -1000, 698, 529,
+ -1000, -154, -1000, 528, 690, -1000, -1000, 689, 1874, -1000,
+ -1000, -1000, 688, -228, -1000, -248, -1000, 1260, -1000, 589,
+ 294, -1000, 1760, -1000, -1000, 1760, 197, 2577, -1000, 687,
+ -1000, -1000, 49, -1000, 138, 138, -1000, -278, 2311, 705,
+ 138, 231, 65, -1000, 686, 583, 576, 99, -1000, 527,
+ -1000, 522, -1000, 520, -1000, 171, -315, 291, 684, 276,
+ -1000, -1000, 2311, 651, 288, 808, 93, -1000, 513, -1000,
+ -1000, -1000, -1000, -1000, 283, 1760, 681, 561, -1000, 678,
+ -1000, -1000, 558, 558, -1000, -1000, -1000, 677, 138, 64,
+ -1000, 265, -1000, -1000, 1760, 1760, -1000, 171, -1000, 171,
+ -1000, 126, -1000, -1000, 2311, 1874, -96, 661, -1000, -1000,
+ -1000, 1138, -1000, 674, -1000, 1760, -1000, -1000, 578, -104,
+ -1000, 138, 672, 574, -1000, 87, 136, 195, -1000, 2311,
+ 1874, -1000, 808, 656, -1000, 138, 49, -1000, -1000, 1760,
+ -1000, 509, -1000, -1000, 652, -1000, -1000, -104, -1000, 644,
+ 171, -1000, -1000, 136, 506, 171, 136, 479, 171, 85,
+ -1000 };
+int yypgo[]={
+
+ 0, 1046, 1045, 1044, 13, 0, 10, 1042, 1041, 1040,
+ 257, 65, 2308, 1039, 1037, 1036, 55, 36, 142, 167,
+ 194, 147, 143, 145, 102, 155, 174, 1035, 74, 5,
+ 48, 15, 49, 25, 539, 28, 1029, 59, 1028, 18,
+ 37, 1027, 400, 287, 1026, 2770, 1023, 214, 231, 1020,
+ 201, 1018, 1014, 40, 991, 46, 965, 228, 39, 52,
+ 32, 943, 942, 77, 159, 259, 940, 24, 939, 27,
+ 938, 132, 137, 43, 937, 38, 936, 6, 935, 89,
+ 932, 931, 917, 916, 915, 886, 882, 86, 860, 197,
+ 78, 34, 2, 22, 859, 360, 4, 203, 857, 856,
+ 11, 855, 183, 854, 852, 849, 17, 33, 847, 14,
+ 845, 8, 844, 41, 843, 20, 842, 840, 26, 1,
+ 12, 837, 23, 30, 824, 822, 818, 817, 814, 813,
+ 812, 811, 810, 809, 808, 807, 776, 804, 803, 802,
+ 801, 796, 795, 794, 792, 788, 308, 7, 787, 786,
+ 785, 9, 784, 782, 778, 774, 3 };
+int yyr1[]={
+
+ 0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 15, 15, 16, 16, 16,
+ 16, 16, 16, 1, 1, 1, 1, 1, 1, 17,
+ 17, 18, 18, 18, 18, 19, 19, 19, 20, 20,
+ 20, 21, 21, 21, 21, 21, 22, 22, 22, 23,
+ 23, 24, 24, 25, 25, 26, 26, 27, 27, 28,
+ 28, 29, 29, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 30, 30, 31, 31, 32, 33,
+ 33, 34, 34, 34, 35, 35, 36, 36, 37, 37,
+ 37, 38, 38, 38, 38, 39, 39, 39, 39, 40,
+ 40, 41, 41, 42, 42, 43, 43, 11, 11, 11,
+ 11, 11, 44, 44, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 46, 46, 46, 3, 3,
+ 47, 47, 48, 48, 49, 49, 50, 50, 50, 51,
+ 51, 51, 52, 52, 53, 53, 125, 53, 54, 54,
+ 55, 55, 126, 55, 127, 56, 128, 56, 56, 57,
+ 57, 58, 58, 12, 12, 59, 60, 61, 61, 61,
+ 129, 61, 62, 62, 62, 130, 62, 87, 87, 63,
+ 63, 63, 63, 64, 64, 65, 65, 66, 66, 67,
+ 67, 68, 68, 69, 69, 69, 70, 70, 71, 71,
+ 71, 71, 72, 72, 73, 73, 74, 74, 74, 131,
+ 74, 132, 74, 75, 75, 75, 76, 76, 77, 77,
+ 133, 111, 111, 111, 111, 111, 111, 111, 78, 78,
+ 78, 79, 79, 80, 80, 81, 81, 90, 90, 91,
+ 91, 134, 134, 134, 134, 82, 82, 89, 89, 83,
+ 84, 84, 84, 84, 110, 110, 109, 108, 108, 85,
+ 85, 85, 86, 86, 86, 86, 86, 86, 86, 124,
+ 124, 135, 135, 136, 136, 136, 139, 137, 88, 88,
+ 88, 10, 10, 102, 102, 4, 4, 4, 4, 140,
+ 138, 142, 142, 142, 141, 141, 143, 148, 149, 143,
+ 145, 7, 7, 7, 7, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 146, 146, 146, 123, 123, 122, 122,
+ 147, 147, 147, 150, 150, 151, 151, 151, 144, 144,
+ 94, 94, 95, 95, 96, 96, 96, 96, 152, 153,
+ 96, 101, 101, 101, 101, 101, 104, 104, 106, 105,
+ 105, 107, 107, 114, 114, 115, 103, 103, 112, 112,
+ 113, 113, 113, 113, 113, 154, 98, 155, 98, 99,
+ 99, 156, 156, 100, 100, 92, 92, 92, 92, 92,
+ 92, 92, 92, 93, 93, 93, 93, 97, 97, 97,
+ 97, 116, 116, 116, 117, 117, 118, 119, 119, 119,
+ 120, 120, 120, 120, 120, 120, 8, 121, 121, 9,
+ 9 };
+int yyr2[]={
+
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 7, 2, 9, 7, 9, 7, 7,
+ 5, 5, 13, 17, 21, 2, 7, 2, 5, 5,
+ 5, 5, 9, 2, 2, 2, 2, 2, 2, 2,
+ 9, 2, 7, 7, 7, 2, 7, 7, 2, 7,
+ 7, 2, 7, 7, 7, 7, 2, 7, 7, 2,
+ 7, 2, 7, 2, 7, 2, 7, 2, 7, 2,
+ 11, 2, 7, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 7, 1, 2, 2, 1,
+ 2, 5, 7, 7, 2, 5, 2, 2, 3, 5,
+ 2, 2, 5, 5, 5, 2, 2, 5, 5, 2,
+ 7, 2, 7, 3, 7, 3, 7, 3, 3, 3,
+ 3, 3, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 2, 2, 11, 9, 5, 2, 2,
+ 2, 5, 7, 7, 2, 5, 3, 5, 2, 2,
+ 5, 5, 2, 7, 3, 5, 1, 9, 2, 7,
+ 3, 5, 1, 9, 1, 11, 1, 13, 5, 2,
+ 7, 3, 7, 3, 3, 5, 5, 2, 7, 9,
+ 1, 11, 3, 7, 9, 1, 11, 2, 2, 3,
+ 5, 5, 7, 1, 2, 2, 5, 2, 7, 1,
+ 2, 2, 7, 5, 2, 5, 3, 7, 2, 2,
+ 5, 5, 2, 5, 2, 5, 7, 7, 9, 1,
+ 9, 1, 11, 2, 7, 9, 2, 7, 2, 2,
+ 1, 5, 2, 2, 2, 2, 11, 15, 7, 9,
+ 7, 7, 9, 2, 5, 1, 2, 2, 5, 2,
+ 9, 3, 5, 5, 5, 2, 5, 1, 2, 5,
+ 11, 15, 11, 15, 3, 5, 5, 1, 7, 11,
+ 15, 19, 7, 5, 5, 7, 7, 5, 5, 0,
+ 2, 2, 4, 2, 3, 2, 1, 9, 3, 5,
+ 5, 3, 3, 3, 3, 2, 2, 2, 2, 1,
+ 6, 9, 7, 9, 1, 3, 17, 1, 1, 23,
+ 11, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 5, 9, 3, 3, 1, 3,
+ 0, 2, 9, 2, 7, 3, 5, 9, 1, 9,
+ 1, 2, 2, 5, 2, 2, 2, 7, 1, 1,
+ 13, 9, 13, 15, 19, 37, 3, 5, 5, 1,
+ 7, 5, 7, 2, 5, 7, 2, 5, 2, 7,
+ 13, 13, 17, 17, 21, 1, 7, 1, 7, 11,
+ 15, 0, 3, 3, 9, 3, 3, 3, 3, 3,
+ 3, 9, 9, 3, 3, 3, 3, 2, 5, 5,
+ 5, 9, 7, 3, 2, 5, 15, 2, 7, 7,
+ 3, 9, 11, 9, 7, 7, 2, 2, 7, 2,
+ 2 };
+int yychk[]={
+
+ -1000, -124, -135, -136, -137, -34, -138, -88, -35, -39,
+ -140, -60, -37, -11, -12, -64, -4, -38, 293, 294,
+ 295, 296, 297, 307, 308, -63, 310, 339, 341, 342,
+ -45, 42, 309, 299, 300, 301, 302, 305, 306, 303,
+ 304, -46, -56, -3, 313, 311, 312, -136, -139, 59,
+ -40, -59, -42, -64, -41, -37, -11, -12, -60, -43,
+ -141, 258, -62, -5, 40, 355, 359, 336, 345, 334,
+ 351, 332, 346, 331, 333, 257, 354, 337, 358, 362,
+ 356, 338, 360, 344, 343, 357, 350, 335, -39, -45,
+ -11, -12, -65, -63, -12, -10, 123, -5, -4, -127,
+ -10, -81, -80, -34, -35, -39, 59, 44, 61, -61,
+ -10, 40, 59, 44, 61, -142, -143, -145, 347, 349,
+ 348, 91, 40, -60, -63, -12, 123, -47, -48, -49,
+ -65, -50, -4, -51, -45, 123, -128, -79, 123, -34,
+ -59, -60, -42, -75, -29, 123, -28, -16, -27, -14,
+ 270, 271, -1, 290, -26, -13, 328, 329, 330, 38,
+ 42, 43, 45, 126, 33, -25, -5, 258, 259, 260,
+ 261, 262, 263, 264, 265, 266, 267, 268, 40, -24,
+ -23, -22, -21, -20, -19, -18, -17, 91, 40, -59,
+ -43, -75, -144, 351, -95, 364, -96, -101, -98, -99,
+ 123, 355, 317, 361, 363, 340, 345, 354, 327, 123,
+ 123, 123, -33, -32, -28, -16, -130, 41, -47, 125,
+ -48, -52, -53, -59, 58, -54, -50, -55, -60, 58,
+ -65, -45, -12, -57, -58, -10, 123, -89, -90, -82,
+ -91, -77, -34, 298, -78, -111, -102, 315, 316, -133,
+ -83, -84, -85, -86, 327, -5, -4, -31, 317, 319,
+ 361, 320, 321, 322, 323, 324, 325, 326, 352, 353,
+ 365, -30, -29, -76, -75, -2, 61, 280, 281, 282,
+ 283, 284, 285, 286, 287, 288, 289, 279, 63, 91,
+ 40, 46, 269, 270, 271, -16, 40, -16, -17, -16,
+ 40, 278, 58, 58, 58, 124, -30, -72, -71, -44,
+ -12, -45, -4, 94, 38, 276, 277, 60, 62, 274,
+ 275, 272, 273, 43, 45, 42, 47, 37, -33, -129,
+ 41, -95, 123, 346, -96, -7, 258, 263, 261, 265,
+ -94, -95, -152, -103, -112, 33, -113, 328, 329, 330,
+ -100, -5, -5, 40, -154, -155, 40, -146, -123, 265,
+ 42, -146, -146, 93, -87, -67, -70, -66, -5, -68,
+ -69, -36, -35, -39, 125, 59, 44, 58, -32, 59,
+ 44, 58, -32, 125, 44, 61, -57, 125, -89, -91,
+ -77, -4, -134, 299, 311, 312, 58, -32, 58, -79,
+ 40, 59, 40, 40, -30, 40, -77, 40, -102, -5,
+ 59, 59, -97, -31, 339, 341, 342, -97, 59, 59,
+ 44, 125, 44, -29, -26, -30, -30, 41, -15, -29,
+ -10, -10, -72, -25, -93, 336, 332, 333, 335, -92,
+ 333, 339, 341, 342, 343, 344, 40, -92, -24, 41,
+ 41, -73, -63, -64, -71, -71, -23, -22, -21, -21,
+ -20, -20, -20, -20, -19, -19, -18, -18, -17, -17,
+ -17, 93, -87, 346, -90, 346, 125, 123, 360, 278,
+ -113, 58, 58, 58, 362, 91, 362, -100, -79, -79,
+ 265, 125, -122, 44, 43, -148, 125, 41, 44, 44,
+ -60, -73, -64, -53, -125, -55, -126, -58, -32, 125,
+ 125, -40, -5, 310, -5, -77, 58, -77, -29, -30,
+ -30, 362, -30, 320, -31, 59, 59, -29, -29, -29,
+ 59, -29, 125, -75, 58, 93, 41, 44, 41, 40,
+ 40, 331, 40, -17, -74, 40, 91, 41, 125, -116,
+ -117, 326, -118, 356, -96, -113, -93, -92, -92, 123,
+ 265, 123, 44, 41, 44, -6, -5, -4, 296, 325,
+ 315, 299, 329, 307, 324, 330, 316, 321, 306, 318,
+ 313, 365, 294, 353, 305, 322, 347, 323, 317, 301,
+ 328, 348, 302, 349, 297, 326, 327, 300, 303, 290,
+ 295, 311, 352, 319, 298, 293, 312, 304, 309, 308,
+ 320, -123, 125, -6, -5, 314, -69, 40, -32, -32,
+ 59, -77, 41, 44, 41, 41, 123, 41, 40, 59,
+ -28, -29, -29, -29, 41, -29, 91, 40, -73, -131,
+ -33, -153, 326, -118, -119, -120, -93, 357, 358, 356,
+ 40, 91, 318, 40, 40, 40, -104, -106, -107, -93,
+ 93, -114, -115, 265, -100, -156, 59, -100, 40, -122,
+ 292, 59, -29, -77, -77, -110, -109, -107, -77, -30,
+ -31, 41, 44, 333, 339, 44, -33, -132, 41, -67,
+ 93, 125, -119, -156, -8, 291, 270, 46, 40, -93,
+ 91, -119, -119, -96, -100, -100, -100, -105, -106, 316,
+ -96, -93, 58, 316, -115, 58, 41, 41, -147, -150,
+ -151, -5, 350, -149, 41, 318, -108, -109, 316, -111,
+ 336, 332, 333, 335, 41, 59, -29, -29, 93, -67,
+ 41, -156, -120, -120, -9, 334, 359, -100, 40, -119,
+ 41, 93, 41, 41, 44, 44, 125, 58, 58, 58,
+ -96, 362, -156, 41, 91, 44, -5, -6, 59, -77,
+ 125, 58, 59, -31, 41, 44, 41, 41, -121, -119,
+ 93, 61, -29, -29, -96, -96, 123, -5, -151, 269,
+ 40, -111, 41, -29, 41, 44, -119, 41, 41, 44,
+ 125, -92, 93, -5, -147, -77, 41, -119, -156, -29,
+ 58, 41, 41, -96, -92, 58, -96, -92, 58, -96,
+ 125 };
+int yydef[]={
+
+ -2, -2, -2, 281, 283, 284, 285, 286, 193, 193,
+ 304, 288, 94, 105, 106, 0, 98, 100, 117, 118,
+ 119, 120, 121, 173, 174, 194, 295, 296, 297, 298,
+ 101, 189, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 0, 164, 138, 139, 282, 245, 91,
+ 0, -2, 109, 0, 0, 95, 107, 108, -2, 111,
+ 0, 305, 176, 182, 193, 315, 316, 317, 318, 319,
+ 320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, 333, 334, 335, 336, 337, 99, 102,
+ 103, 104, 190, 191, 195, 137, 0, 291, 292, 0,
+ -2, 0, 246, 243, 193, 193, 92, 193, 0, 175,
+ 177, 193, 93, 193, 0, 300, 398, 0, 0, 0,
+ 0, 89, 185, 0, 192, 196, 0, 0, 140, 193,
+ 193, 144, 146, 148, 149, 0, 0, 287, -2, 244,
+ 113, 115, 110, 114, 223, 0, 71, 39, 69, 27,
+ 0, 0, 0, 0, 67, 14, 0, 0, 0, 33,
+ 34, 35, 36, 37, 38, 65, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 0, 63,
+ 61, 59, 56, 51, 48, 45, 41, 89, 180, 0,
+ 112, 116, 0, 0, 0, 0, 402, 404, 405, 406,
+ 400, 408, 0, 0, 0, 0, 435, 437, 0, 383,
+ 383, 383, 0, 90, 88, 39, 199, 183, 0, 136,
+ 141, 0, 152, 154, 0, 0, 145, 158, 160, 0,
+ 147, 150, 151, 0, 169, 171, 0, 0, -2, -2,
+ 247, 255, 249, 0, 228, 229, 0, 0, 0, 0,
+ 232, 233, 234, 235, 0, -2, -2, 0, 0, 0,
+ 0, 0, -2, 0, 0, 0, 0, 86, 86, 0,
+ 0, 87, 84, 0, 226, 0, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 0, 0, 0,
+ 0, 0, 0, 20, 21, 28, 0, 29, 30, 31,
+ 0, 0, 0, 0, 0, 0, 0, 0, -2, 208,
+ 209, 122, 123, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 199,
+ 178, 0, 0, 302, 403, 0, 311, 312, 313, 314,
+ 0, 401, 0, 0, 426, 0, 428, 0, 0, 0,
+ 0, 443, 0, 0, 0, 0, 0, 0, 388, 386,
+ 387, 307, 0, 184, 0, 187, 188, 200, 206, 197,
+ 201, -2, 96, 97, 135, 142, 193, 156, 155, 143,
+ 193, 162, 161, 165, 0, 0, 0, 241, 0, 248,
+ 256, 294, 193, 251, 0, 0, -2, 0, -2, 231,
+ 0, 259, 0, 0, 0, 0, 0, 86, 0, 293,
+ 273, 274, 0, 457, 0, 0, 0, 0, 277, 278,
+ 0, 224, 0, 72, 68, 0, 0, 16, 0, 25,
+ 18, 19, 0, 66, 0, 453, 454, 455, 456, 0,
+ 445, 446, 447, 448, 449, 450, 0, 0, 64, 13,
+ 0, 213, -2, 0, 210, 211, 62, 60, 57, 58,
+ 52, 53, 54, 55, 49, 50, 46, 47, 42, 43,
+ 44, 179, 0, 301, 0, 303, 407, 0, 0, 0,
+ 427, 0, 0, 0, 0, 0, 0, 0, 436, 438,
+ 0, 0, 384, 0, 389, 0, 0, 186, 0, 0,
+ 203, 205, 0, 153, 0, 159, 0, 170, 172, 167,
+ 242, 0, 252, 253, 254, 238, -2, 240, 0, 0,
+ 0, 0, 0, 0, 0, 272, 275, 458, 459, 460,
+ 276, 85, 225, 227, 0, 15, 17, 0, 32, 0,
+ 0, 0, 0, 40, 215, -2, 89, 181, 399, 409,
+ 463, 0, 464, 0, 411, 429, 0, 0, 0, 0,
+ 0, 0, 0, 441, 0, 0, 338, 339, 340, 341,
+ 342, 343, 344, 345, 346, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 358, 359, 360, 361,
+ 362, 363, 364, 365, 366, 367, 368, 369, 370, 371,
+ 372, 373, 374, 375, 376, 377, 378, 379, 380, 381,
+ 382, 388, 0, 310, 207, 198, 202, -2, 157, 163,
+ 250, 239, 0, 0, -2, -2, 0, -2, 0, 86,
+ 70, 26, 0, 0, 0, 0, 89, 221, 0, 199,
+ 0, 0, 0, 465, 441, 467, 470, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 419, 416, 0, 0,
+ 444, 0, 423, 0, 0, 439, 442, 0, 390, 385,
+ 308, 236, 0, 260, 262, 267, 264, -2, 269, 0,
+ 0, 22, 0, 451, 452, 0, 0, 199, 216, 0,
+ 217, 410, 441, 462, 0, 0, 476, 0, 0, 0,
+ 0, 0, 0, 412, 0, 0, 0, 0, 417, 0,
+ 418, 0, 421, 0, 424, 0, 0, 441, 0, 391,
+ 393, 395, 336, 0, 0, -2, 0, 265, 0, 266,
+ -2, -2, -2, -2, 0, 86, 0, 0, 218, 0,
+ 220, 461, 468, 469, 474, 479, 480, 0, 0, 0,
+ 475, 0, 430, 431, 0, 0, 413, 0, 422, 0,
+ 425, 0, 440, 306, 0, 0, 396, 0, 237, 261,
+ 263, -2, 270, 0, 23, 0, 222, 471, 0, 477,
+ 473, 0, 0, 0, 420, 0, 0, 0, 394, 0,
+ 390, 268, -2, 0, 472, 0, 441, 432, 433, 0,
+ 414, 0, 392, 397, 0, 271, 24, 478, 466, 0,
+ 0, 309, 434, 0, 0, 0, 0, 0, 0, 0,
+ 415 };
+typedef struct { char *t_name; int t_val; } yytoktype;
+#ifndef YYDEBUG
+# define YYDEBUG 0 /* don't allow debugging */
+#endif
+
+#if YYDEBUG
+
+yytoktype yytoks[] =
+{
+ "Identifier", 257,
+ "StrLit", 258,
+ "LStrLit", 259,
+ "FltConst", 260,
+ "DblConst", 261,
+ "LDblConst", 262,
+ "CharConst", 263,
+ "LCharConst", 264,
+ "IntConst", 265,
+ "UIntConst", 266,
+ "LIntConst", 267,
+ "ULIntConst", 268,
+ "Arrow", 269,
+ "Incr", 270,
+ "Decr", 271,
+ "LShft", 272,
+ "RShft", 273,
+ "Leq", 274,
+ "Geq", 275,
+ "Equal", 276,
+ "Neq", 277,
+ "And", 278,
+ "Or", 279,
+ "MultAsgn", 280,
+ "DivAsgn", 281,
+ "ModAsgn", 282,
+ "PlusAsgn", 283,
+ "MinusAsgn", 284,
+ "LShftAsgn", 285,
+ "RShftAsgn", 286,
+ "AndAsgn", 287,
+ "XorAsgn", 288,
+ "OrAsgn", 289,
+ "Sizeof", 290,
+ "Intersect", 291,
+ "OpSym", 292,
+ "Typedef", 293,
+ "Extern", 294,
+ "Static", 295,
+ "Auto", 296,
+ "Register", 297,
+ "Tended", 298,
+ "Char", 299,
+ "Short", 300,
+ "Int", 301,
+ "Long", 302,
+ "Signed", 303,
+ "Unsigned", 304,
+ "Float", 305,
+ "Doubl", 306,
+ "Const", 307,
+ "Volatile", 308,
+ "Void", 309,
+ "TypeDefName", 310,
+ "Struct", 311,
+ "Union", 312,
+ "Enum", 313,
+ "Ellipsis", 314,
+ "Case", 315,
+ "Default", 316,
+ "If", 317,
+ "Else", 318,
+ "Switch", 319,
+ "While", 320,
+ "Do", 321,
+ "For", 322,
+ "Goto", 323,
+ "Continue", 324,
+ "Break", 325,
+ "Return", 326,
+ "%", 37,
+ "&", 38,
+ "(", 40,
+ ")", 41,
+ "*", 42,
+ "+", 43,
+ ",", 44,
+ "-", 45,
+ ".", 46,
+ "/", 47,
+ "{", 123,
+ "|", 124,
+ "}", 125,
+ "~", 126,
+ "[", 91,
+ "]", 93,
+ "^", 94,
+ ":", 58,
+ ";", 59,
+ "<", 60,
+ "=", 61,
+ ">", 62,
+ "?", 63,
+ "!", 33,
+ "@", 64,
+ "\\", 92,
+ "Runerr", 327,
+ "Is", 328,
+ "Cnv", 329,
+ "Def", 330,
+ "Exact", 331,
+ "Empty_type", 332,
+ "IconType", 333,
+ "Component", 334,
+ "Variable", 335,
+ "Any_value", 336,
+ "Named_var", 337,
+ "Struct_var", 338,
+ "C_Integer", 339,
+ "Arith_case", 340,
+ "C_Double", 341,
+ "C_String", 342,
+ "Tmp_string", 343,
+ "Tmp_cset", 344,
+ "Body", 345,
+ "End", 346,
+ "Function", 347,
+ "Keyword", 348,
+ "Operator", 349,
+ "Underef", 350,
+ "Declare", 351,
+ "Suspend", 352,
+ "Fail", 353,
+ "Inline", 354,
+ "Abstract", 355,
+ "Store", 356,
+ "Type", 357,
+ "New", 358,
+ "All_fields", 359,
+ "Then", 360,
+ "Type_case", 361,
+ "Of", 362,
+ "Len_case", 363,
+ "Constant", 364,
+ "Errorfail", 365,
+ "IfStmt", 366,
+ "-unknown-", -1 /* ends search */
+};
+
+char * yyreds[] =
+{
+ "-no such reduction-",
+ "primary_expr : identifier",
+ "primary_expr : StrLit",
+ "primary_expr : LStrLit",
+ "primary_expr : FltConst",
+ "primary_expr : DblConst",
+ "primary_expr : LDblConst",
+ "primary_expr : CharConst",
+ "primary_expr : LCharConst",
+ "primary_expr : IntConst",
+ "primary_expr : UIntConst",
+ "primary_expr : LIntConst",
+ "primary_expr : ULIntConst",
+ "primary_expr : '(' expr ')'",
+ "postfix_expr : primary_expr",
+ "postfix_expr : postfix_expr '[' expr ']'",
+ "postfix_expr : postfix_expr '(' ')'",
+ "postfix_expr : postfix_expr '(' arg_expr_lst ')'",
+ "postfix_expr : postfix_expr '.' any_ident",
+ "postfix_expr : postfix_expr Arrow any_ident",
+ "postfix_expr : postfix_expr Incr",
+ "postfix_expr : postfix_expr Decr",
+ "postfix_expr : Is ':' i_type_name '(' assign_expr ')'",
+ "postfix_expr : Cnv ':' dest_type '(' assign_expr ',' assign_expr ')'",
+ "postfix_expr : Def ':' dest_type '(' assign_expr ',' assign_expr ',' assign_expr ')'",
+ "arg_expr_lst : assign_expr",
+ "arg_expr_lst : arg_expr_lst ',' assign_expr",
+ "unary_expr : postfix_expr",
+ "unary_expr : Incr unary_expr",
+ "unary_expr : Decr unary_expr",
+ "unary_expr : unary_op cast_expr",
+ "unary_expr : Sizeof unary_expr",
+ "unary_expr : Sizeof '(' type_name ')'",
+ "unary_op : '&'",
+ "unary_op : '*'",
+ "unary_op : '+'",
+ "unary_op : '-'",
+ "unary_op : '~'",
+ "unary_op : '!'",
+ "cast_expr : unary_expr",
+ "cast_expr : '(' type_name ')' cast_expr",
+ "multiplicative_expr : cast_expr",
+ "multiplicative_expr : multiplicative_expr '*' cast_expr",
+ "multiplicative_expr : multiplicative_expr '/' cast_expr",
+ "multiplicative_expr : multiplicative_expr '%' cast_expr",
+ "additive_expr : multiplicative_expr",
+ "additive_expr : additive_expr '+' multiplicative_expr",
+ "additive_expr : additive_expr '-' multiplicative_expr",
+ "shift_expr : additive_expr",
+ "shift_expr : shift_expr LShft additive_expr",
+ "shift_expr : shift_expr RShft additive_expr",
+ "relational_expr : shift_expr",
+ "relational_expr : relational_expr '<' shift_expr",
+ "relational_expr : relational_expr '>' shift_expr",
+ "relational_expr : relational_expr Leq shift_expr",
+ "relational_expr : relational_expr Geq shift_expr",
+ "equality_expr : relational_expr",
+ "equality_expr : equality_expr Equal relational_expr",
+ "equality_expr : equality_expr Neq relational_expr",
+ "and_expr : equality_expr",
+ "and_expr : and_expr '&' equality_expr",
+ "exclusive_or_expr : and_expr",
+ "exclusive_or_expr : exclusive_or_expr '^' and_expr",
+ "inclusive_or_expr : exclusive_or_expr",
+ "inclusive_or_expr : inclusive_or_expr '|' exclusive_or_expr",
+ "logical_and_expr : inclusive_or_expr",
+ "logical_and_expr : logical_and_expr And inclusive_or_expr",
+ "logical_or_expr : logical_and_expr",
+ "logical_or_expr : logical_or_expr Or logical_and_expr",
+ "conditional_expr : logical_or_expr",
+ "conditional_expr : logical_or_expr '?' expr ':' conditional_expr",
+ "assign_expr : conditional_expr",
+ "assign_expr : unary_expr assign_op assign_expr",
+ "assign_op : '='",
+ "assign_op : MultAsgn",
+ "assign_op : DivAsgn",
+ "assign_op : ModAsgn",
+ "assign_op : PlusAsgn",
+ "assign_op : MinusAsgn",
+ "assign_op : LShftAsgn",
+ "assign_op : RShftAsgn",
+ "assign_op : AndAsgn",
+ "assign_op : XorAsgn",
+ "assign_op : OrAsgn",
+ "expr : assign_expr",
+ "expr : expr ',' assign_expr",
+ "opt_expr : /* empty */",
+ "opt_expr : expr",
+ "constant_expr : conditional_expr",
+ "opt_constant_expr : /* empty */",
+ "opt_constant_expr : constant_expr",
+ "dcltion : typ_dcltion_specs ';'",
+ "dcltion : typ_dcltion_specs init_dcltor_lst ';'",
+ "dcltion : storcl_tqual_lst no_tdn_init_dcltor_lst ';'",
+ "typ_dcltion_specs : type_ind",
+ "typ_dcltion_specs : storcl_tqual_lst type_ind",
+ "dcltion_specs : typ_dcltion_specs",
+ "dcltion_specs : storcl_tqual_lst",
+ "type_ind : typedefname",
+ "type_ind : typedefname storcl_tqual_lst",
+ "type_ind : type_storcl_tqual_lst",
+ "type_storcl_tqual_lst : stnd_type",
+ "type_storcl_tqual_lst : type_storcl_tqual_lst stnd_type",
+ "type_storcl_tqual_lst : type_storcl_tqual_lst storage_class_spec",
+ "type_storcl_tqual_lst : type_storcl_tqual_lst type_qual",
+ "storcl_tqual_lst : storage_class_spec",
+ "storcl_tqual_lst : type_qual",
+ "storcl_tqual_lst : storcl_tqual_lst storage_class_spec",
+ "storcl_tqual_lst : storcl_tqual_lst type_qual",
+ "init_dcltor_lst : init_dcltor",
+ "init_dcltor_lst : init_dcltor_lst ',' init_dcltor",
+ "no_tdn_init_dcltor_lst : no_tdn_init_dcltor",
+ "no_tdn_init_dcltor_lst : no_tdn_init_dcltor_lst ',' no_tdn_init_dcltor",
+ "init_dcltor : dcltor",
+ "init_dcltor : dcltor '=' initializer",
+ "no_tdn_init_dcltor : no_tdn_dcltor",
+ "no_tdn_init_dcltor : no_tdn_dcltor '=' initializer",
+ "storage_class_spec : Typedef",
+ "storage_class_spec : Extern",
+ "storage_class_spec : Static",
+ "storage_class_spec : Auto",
+ "storage_class_spec : Register",
+ "type_spec : stnd_type",
+ "type_spec : typedefname",
+ "stnd_type : Void",
+ "stnd_type : Char",
+ "stnd_type : Short",
+ "stnd_type : Int",
+ "stnd_type : Long",
+ "stnd_type : Float",
+ "stnd_type : Doubl",
+ "stnd_type : Signed",
+ "stnd_type : Unsigned",
+ "stnd_type : struct_or_union_spec",
+ "stnd_type : enum_spec",
+ "struct_or_union_spec : struct_or_union any_ident '{' struct_dcltion_lst '}'",
+ "struct_or_union_spec : struct_or_union '{' struct_dcltion_lst '}'",
+ "struct_or_union_spec : struct_or_union any_ident",
+ "struct_or_union : Struct",
+ "struct_or_union : Union",
+ "struct_dcltion_lst : struct_dcltion",
+ "struct_dcltion_lst : struct_dcltion_lst struct_dcltion",
+ "struct_dcltion : struct_dcltion_specs struct_dcltor_lst ';'",
+ "struct_dcltion : tqual_lst struct_no_tdn_dcltor_lst ';'",
+ "struct_dcltion_specs : struct_type_ind",
+ "struct_dcltion_specs : tqual_lst struct_type_ind",
+ "struct_type_ind : typedefname",
+ "struct_type_ind : typedefname tqual_lst",
+ "struct_type_ind : struct_type_lst",
+ "struct_type_lst : stnd_type",
+ "struct_type_lst : struct_type_lst stnd_type",
+ "struct_type_lst : struct_type_lst type_qual",
+ "struct_dcltor_lst : struct_dcltor",
+ "struct_dcltor_lst : struct_dcltor_lst ',' struct_dcltor",
+ "struct_dcltor : dcltor",
+ "struct_dcltor : ':' constant_expr",
+ "struct_dcltor : dcltor ':'",
+ "struct_dcltor : dcltor ':' constant_expr",
+ "struct_no_tdn_dcltor_lst : struct_no_tdn_dcltor",
+ "struct_no_tdn_dcltor_lst : struct_no_tdn_dcltor_lst ',' struct_no_tdn_dcltor",
+ "struct_no_tdn_dcltor : no_tdn_dcltor",
+ "struct_no_tdn_dcltor : ':' constant_expr",
+ "struct_no_tdn_dcltor : no_tdn_dcltor ':'",
+ "struct_no_tdn_dcltor : no_tdn_dcltor ':' constant_expr",
+ "enum_spec : Enum",
+ "enum_spec : Enum '{' enumerator_lst '}'",
+ "enum_spec : Enum any_ident",
+ "enum_spec : Enum any_ident '{' enumerator_lst '}'",
+ "enum_spec : Enum any_ident",
+ "enumerator_lst : enumerator",
+ "enumerator_lst : enumerator_lst ',' enumerator",
+ "enumerator : any_ident",
+ "enumerator : any_ident '=' constant_expr",
+ "type_qual : Const",
+ "type_qual : Volatile",
+ "dcltor : opt_pointer direct_dcltor",
+ "no_tdn_dcltor : opt_pointer no_tdn_direct_dcltor",
+ "direct_dcltor : any_ident",
+ "direct_dcltor : '(' dcltor ')'",
+ "direct_dcltor : direct_dcltor '[' opt_constant_expr ']'",
+ "direct_dcltor : direct_dcltor '('",
+ "direct_dcltor : direct_dcltor '(' parm_dcls_or_ids ')'",
+ "no_tdn_direct_dcltor : identifier",
+ "no_tdn_direct_dcltor : '(' no_tdn_dcltor ')'",
+ "no_tdn_direct_dcltor : no_tdn_direct_dcltor '[' opt_constant_expr ']'",
+ "no_tdn_direct_dcltor : no_tdn_direct_dcltor '('",
+ "no_tdn_direct_dcltor : no_tdn_direct_dcltor '(' parm_dcls_or_ids ')'",
+ "parm_dcls_or_ids : opt_param_type_lst",
+ "parm_dcls_or_ids : ident_lst",
+ "pointer : '*'",
+ "pointer : '*' tqual_lst",
+ "pointer : '*' pointer",
+ "pointer : '*' tqual_lst pointer",
+ "opt_pointer : /* empty */",
+ "opt_pointer : pointer",
+ "tqual_lst : type_qual",
+ "tqual_lst : tqual_lst type_qual",
+ "param_type_lst : param_lst",
+ "param_type_lst : param_lst ',' Ellipsis",
+ "opt_param_type_lst : /* empty */",
+ "opt_param_type_lst : param_type_lst",
+ "param_lst : param_dcltion",
+ "param_lst : param_lst ',' param_dcltion",
+ "param_dcltion : dcltion_specs no_tdn_dcltor",
+ "param_dcltion : dcltion_specs",
+ "param_dcltion : dcltion_specs abstract_dcltor",
+ "ident_lst : identifier",
+ "ident_lst : ident_lst ',' identifier",
+ "type_tqual_lst : type_spec",
+ "type_tqual_lst : type_qual",
+ "type_tqual_lst : type_spec type_tqual_lst",
+ "type_tqual_lst : type_qual type_tqual_lst",
+ "type_name : type_tqual_lst",
+ "type_name : type_tqual_lst abstract_dcltor",
+ "abstract_dcltor : pointer",
+ "abstract_dcltor : opt_pointer direct_abstract_dcltor",
+ "direct_abstract_dcltor : '(' abstract_dcltor ')'",
+ "direct_abstract_dcltor : '[' opt_constant_expr ']'",
+ "direct_abstract_dcltor : direct_abstract_dcltor '[' opt_constant_expr ']'",
+ "direct_abstract_dcltor : '('",
+ "direct_abstract_dcltor : '(' opt_param_type_lst ')'",
+ "direct_abstract_dcltor : direct_abstract_dcltor '('",
+ "direct_abstract_dcltor : direct_abstract_dcltor '(' opt_param_type_lst ')'",
+ "initializer : assign_expr",
+ "initializer : '{' initializer_lst '}'",
+ "initializer : '{' initializer_lst ',' '}'",
+ "initializer_lst : initializer",
+ "initializer_lst : initializer_lst ',' initializer",
+ "stmt : labeled_stmt",
+ "stmt : non_lbl_stmt",
+ "non_lbl_stmt : /* empty */",
+ "non_lbl_stmt : compound_stmt",
+ "non_lbl_stmt : expr_stmt",
+ "non_lbl_stmt : selection_stmt",
+ "non_lbl_stmt : iteration_stmt",
+ "non_lbl_stmt : jump_stmt",
+ "non_lbl_stmt : Runerr '(' assign_expr ')' ';'",
+ "non_lbl_stmt : Runerr '(' assign_expr ',' assign_expr ')' ';'",
+ "labeled_stmt : label ':' stmt",
+ "labeled_stmt : Case constant_expr ':' stmt",
+ "labeled_stmt : Default ':' stmt",
+ "compound_stmt : '{' opt_stmt_lst '}'",
+ "compound_stmt : '{' local_dcls opt_stmt_lst '}'",
+ "dcltion_lst : dcltion",
+ "dcltion_lst : dcltion_lst dcltion",
+ "opt_dcltion_lst : /* empty */",
+ "opt_dcltion_lst : dcltion_lst",
+ "local_dcls : local_dcl",
+ "local_dcls : local_dcls local_dcl",
+ "local_dcl : dcltion",
+ "local_dcl : Tended tended_type init_dcltor_lst ';'",
+ "tended_type : Char",
+ "tended_type : Struct identifier",
+ "tended_type : Struct TypeDefName",
+ "tended_type : Union identifier",
+ "stmt_lst : stmt",
+ "stmt_lst : stmt_lst stmt",
+ "opt_stmt_lst : /* empty */",
+ "opt_stmt_lst : stmt_lst",
+ "expr_stmt : opt_expr ';'",
+ "selection_stmt : If '(' expr ')' stmt",
+ "selection_stmt : If '(' expr ')' stmt Else stmt",
+ "selection_stmt : Switch '(' expr ')' stmt",
+ "selection_stmt : Type_case expr Of '{' c_type_select_lst c_opt_default '}'",
+ "c_type_select_lst : c_type_select",
+ "c_type_select_lst : c_type_select_lst c_type_select",
+ "c_type_select : selector_lst non_lbl_stmt",
+ "c_opt_default : /* empty */",
+ "c_opt_default : Default ':' non_lbl_stmt",
+ "iteration_stmt : While '(' expr ')' stmt",
+ "iteration_stmt : Do stmt While '(' expr ')' ';'",
+ "iteration_stmt : For '(' opt_expr ';' opt_expr ';' opt_expr ')' stmt",
+ "jump_stmt : Goto label ';'",
+ "jump_stmt : Continue ';'",
+ "jump_stmt : Break ';'",
+ "jump_stmt : Return ret_val ';'",
+ "jump_stmt : Suspend ret_val ';'",
+ "jump_stmt : Fail ';'",
+ "jump_stmt : Errorfail ';'",
+ "translation_unit : /* empty */",
+ "translation_unit : extrn_decltn_lst",
+ "extrn_decltn_lst : external_dcltion",
+ "extrn_decltn_lst : extrn_decltn_lst external_dcltion",
+ "external_dcltion : function_definition",
+ "external_dcltion : dcltion",
+ "external_dcltion : definition",
+ "function_definition : func_head",
+ "function_definition : func_head opt_dcltion_lst compound_stmt",
+ "func_head : no_tdn_dcltor",
+ "func_head : storcl_tqual_lst no_tdn_dcltor",
+ "func_head : typ_dcltion_specs dcltor",
+ "any_ident : identifier",
+ "any_ident : typedefname",
+ "label : identifier",
+ "label : typedefname",
+ "typedefname : TypeDefName",
+ "typedefname : C_Integer",
+ "typedefname : C_Double",
+ "typedefname : C_String",
+ "definition : /* empty */",
+ "definition : description operation",
+ "operation : fnc_oper op_declare actions End",
+ "operation : keyword actions End",
+ "operation : keyword Constant key_const End",
+ "description : /* empty */",
+ "description : StrLit",
+ "fnc_oper : Function '{' result_seq '}' op_name '(' opt_s_parm_lst ')'",
+ "fnc_oper : Operator '{' result_seq",
+ "fnc_oper : Operator '{' result_seq '}' OpSym",
+ "fnc_oper : Operator '{' result_seq '}' OpSym op_name '(' opt_s_parm_lst ')'",
+ "keyword : Keyword '{' result_seq '}' op_name",
+ "key_const : StrLit",
+ "key_const : CharConst",
+ "key_const : DblConst",
+ "key_const : IntConst",
+ "identifier : Abstract",
+ "identifier : All_fields",
+ "identifier : Any_value",
+ "identifier : Body",
+ "identifier : Component",
+ "identifier : Declare",
+ "identifier : Empty_type",
+ "identifier : End",
+ "identifier : Exact",
+ "identifier : IconType",
+ "identifier : Identifier",
+ "identifier : Inline",
+ "identifier : Named_var",
+ "identifier : New",
+ "identifier : Of",
+ "identifier : Store",
+ "identifier : Struct_var",
+ "identifier : Then",
+ "identifier : Tmp_cset",
+ "identifier : Tmp_string",
+ "identifier : TokType",
+ "identifier : Underef",
+ "identifier : Variable",
+ "op_name : identifier",
+ "op_name : typedefname",
+ "op_name : Auto",
+ "op_name : Break",
+ "op_name : Case",
+ "op_name : Char",
+ "op_name : Cnv",
+ "op_name : Const",
+ "op_name : Continue",
+ "op_name : Def",
+ "op_name : Default",
+ "op_name : Do",
+ "op_name : Doubl",
+ "op_name : Else",
+ "op_name : Enum",
+ "op_name : Errorfail",
+ "op_name : Extern",
+ "op_name : Fail",
+ "op_name : Float",
+ "op_name : For",
+ "op_name : Function",
+ "op_name : Goto",
+ "op_name : If",
+ "op_name : Int",
+ "op_name : Is",
+ "op_name : Keyword",
+ "op_name : Long",
+ "op_name : Operator",
+ "op_name : Register",
+ "op_name : Return",
+ "op_name : Runerr",
+ "op_name : Short",
+ "op_name : Signed",
+ "op_name : Sizeof",
+ "op_name : Static",
+ "op_name : Struct",
+ "op_name : Suspend",
+ "op_name : Switch",
+ "op_name : Tended",
+ "op_name : Typedef",
+ "op_name : Union",
+ "op_name : Unsigned",
+ "op_name : Void",
+ "op_name : Volatile",
+ "op_name : While",
+ "result_seq : /* empty */",
+ "result_seq : length opt_plus",
+ "result_seq : length ',' length opt_plus",
+ "length : IntConst",
+ "length : '*'",
+ "opt_plus : /* empty */",
+ "opt_plus : '+'",
+ "opt_s_parm_lst : /* empty */",
+ "opt_s_parm_lst : s_parm_lst",
+ "opt_s_parm_lst : s_parm_lst '[' identifier ']'",
+ "s_parm_lst : s_parm",
+ "s_parm_lst : s_parm_lst ',' s_parm",
+ "s_parm : identifier",
+ "s_parm : Underef identifier",
+ "s_parm : Underef identifier Arrow identifier",
+ "op_declare : /* empty */",
+ "op_declare : Declare '{' local_dcls '}'",
+ "opt_actions : /* empty */",
+ "opt_actions : actions",
+ "actions : action",
+ "actions : actions action",
+ "action : checking_conversions",
+ "action : detail_code",
+ "action : runerr",
+ "action : '{' opt_actions '}'",
+ "action : Abstract",
+ "action : Abstract '{' type_computations",
+ "action : Abstract '{' type_computations '}'",
+ "checking_conversions : If type_check Then action",
+ "checking_conversions : If type_check Then action Else action",
+ "checking_conversions : Type_case variable Of '{' type_select_lst opt_default '}'",
+ "checking_conversions : Len_case identifier Of '{' len_select_lst Default ':' action '}'",
+ "checking_conversions : Arith_case '(' variable ',' variable ')' Of '{' dest_type ':' action dest_type ':' action dest_type ':' action '}'",
+ "type_select_lst : type_select",
+ "type_select_lst : type_select_lst type_select",
+ "type_select : selector_lst action",
+ "opt_default : /* empty */",
+ "opt_default : Default ':' action",
+ "selector_lst : i_type_name ':'",
+ "selector_lst : selector_lst i_type_name ':'",
+ "len_select_lst : len_select",
+ "len_select_lst : len_select_lst len_select",
+ "len_select : IntConst ':' action",
+ "type_check : simple_check_conj",
+ "type_check : '!' simple_check",
+ "simple_check_conj : simple_check",
+ "simple_check_conj : simple_check_conj And simple_check",
+ "simple_check : Is ':' i_type_name '(' variable ')'",
+ "simple_check : Cnv ':' dest_type '(' variable ')'",
+ "simple_check : Cnv ':' dest_type '(' variable ',' assign_expr ')'",
+ "simple_check : Def ':' dest_type '(' variable ',' assign_expr ')'",
+ "simple_check : Def ':' dest_type '(' variable ',' assign_expr ',' assign_expr ')'",
+ "detail_code : Body",
+ "detail_code : Body compound_stmt",
+ "detail_code : Inline",
+ "detail_code : Inline compound_stmt",
+ "runerr : Runerr '(' IntConst ')' opt_semi",
+ "runerr : Runerr '(' IntConst ',' variable ')' opt_semi",
+ "opt_semi : /* empty */",
+ "opt_semi : ';'",
+ "variable : identifier",
+ "variable : identifier '[' IntConst ']'",
+ "dest_type : IconType",
+ "dest_type : C_Integer",
+ "dest_type : C_Double",
+ "dest_type : C_String",
+ "dest_type : Tmp_string",
+ "dest_type : Tmp_cset",
+ "dest_type : '(' Exact ')' IconType",
+ "dest_type : '(' Exact ')' C_Integer",
+ "i_type_name : Any_value",
+ "i_type_name : Empty_type",
+ "i_type_name : IconType",
+ "i_type_name : Variable",
+ "ret_val : opt_expr",
+ "ret_val : C_Integer assign_expr",
+ "ret_val : C_Double assign_expr",
+ "ret_val : C_String assign_expr",
+ "type_computations : side_effect_lst Return type opt_semi",
+ "type_computations : Return type opt_semi",
+ "type_computations : side_effect_lst",
+ "side_effect_lst : side_effect",
+ "side_effect_lst : side_effect_lst side_effect",
+ "side_effect : Store '[' type ']' '=' type opt_semi",
+ "type : basic_type",
+ "type : type union basic_type",
+ "type : type Intersect basic_type",
+ "basic_type : i_type_name",
+ "basic_type : TokType '(' variable ')'",
+ "basic_type : New i_type_name '(' type_lst ')'",
+ "basic_type : Store '[' type ']'",
+ "basic_type : basic_type '.' attrb_name",
+ "basic_type : '(' type ')'",
+ "union : Incr",
+ "type_lst : type",
+ "type_lst : type_lst ',' type",
+ "attrb_name : Component",
+ "attrb_name : All_fields",
+};
+#endif /* YYDEBUG */
+#line 1 "/usr/lib/yaccpar"
+/* @(#)yaccpar 1.10 89/04/04 SMI; from S5R3 1.10 */
+
+/*
+** Skeleton parser driver for yacc output
+*/
+
+/*
+** yacc user known macros and defines
+*/
+#define YYERROR goto yyerrlab
+#define YYACCEPT { free(yys); free(yyv); return(0); }
+#define YYABORT { free(yys); free(yyv); return(1); }
+#define YYBACKUP( newtoken, newvalue )\
+{\
+ if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\
+ {\
+ yyerror( "syntax error - cannot backup" );\
+ goto yyerrlab;\
+ }\
+ yychar = newtoken;\
+ yystate = *yyps;\
+ yylval = newvalue;\
+ goto yynewstate;\
+}
+#define YYRECOVERING() (!!yyerrflag)
+#ifndef YYDEBUG
+# define YYDEBUG 1 /* make debugging available */
+#endif
+
+/*
+** user known globals
+*/
+int yydebug; /* set to 1 to get debugging */
+
+/*
+** driver internal defines
+*/
+#define YYFLAG (-1000)
+
+/*
+** static variables used by the parser
+*/
+static YYSTYPE *yyv; /* value stack */
+static int *yys; /* state stack */
+
+static YYSTYPE *yypv; /* top of value stack */
+static int *yyps; /* top of state stack */
+
+static int yystate; /* current state */
+static int yytmp; /* extra var (lasts between blocks) */
+
+int yynerrs; /* number of errors */
+
+int yyerrflag; /* error recovery flag */
+int yychar; /* current input token number */
+
+
+/*
+** yyparse - return 0 if worked, 1 if syntax error not recovered from
+*/
+int
+yyparse()
+{
+ register YYSTYPE *yypvt; /* top of value stack for $vars */
+ unsigned yymaxdepth = YYMAXDEPTH;
+
+ /*
+ ** Initialize externals - yyparse may be called more than once
+ */
+ yyv = (YYSTYPE*)malloc(yymaxdepth*sizeof(YYSTYPE));
+ yys = (int*)malloc(yymaxdepth*sizeof(int));
+ if (!yyv || !yys)
+ {
+ yyerror( "out of memory" );
+ return(1);
+ }
+ yypv = &yyv[-1];
+ yyps = &yys[-1];
+ yystate = 0;
+ yytmp = 0;
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = -1;
+
+ goto yystack;
+ {
+ register YYSTYPE *yy_pv; /* top of value stack */
+ register int *yy_ps; /* top of state stack */
+ register int yy_state; /* current state */
+ register int yy_n; /* internal state number info */
+
+ /*
+ ** get globals into registers.
+ ** branch to here only if YYBACKUP was called.
+ */
+ yynewstate:
+ yy_pv = yypv;
+ yy_ps = yyps;
+ yy_state = yystate;
+ goto yy_newstate;
+
+ /*
+ ** get globals into registers.
+ ** either we just started, or we just finished a reduction
+ */
+ yystack:
+ yy_pv = yypv;
+ yy_ps = yyps;
+ yy_state = yystate;
+
+ /*
+ ** top of for (;;) loop while no reductions done
+ */
+ yy_stack:
+ /*
+ ** put a state and value onto the stacks
+ */
+#if YYDEBUG
+ /*
+ ** if debugging, look up token value in list of value vs.
+ ** name pairs. 0 and negative (-1) are special values.
+ ** Note: linear search is used since time is not a real
+ ** consideration while debugging.
+ */
+ if ( yydebug )
+ {
+ register int yy_i;
+
+ (void)printf( "State %d, token ", yy_state );
+ if ( yychar == 0 )
+ (void)printf( "end-of-file\n" );
+ else if ( yychar < 0 )
+ (void)printf( "-none-\n" );
+ else
+ {
+ for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
+ yy_i++ )
+ {
+ if ( yytoks[yy_i].t_val == yychar )
+ break;
+ }
+ (void)printf( "%s\n", yytoks[yy_i].t_name );
+ }
+ }
+#endif /* YYDEBUG */
+ if ( ++yy_ps >= &yys[ yymaxdepth ] ) /* room on stack? */
+ {
+ /*
+ ** reallocate and recover. Note that pointers
+ ** have to be reset, or bad things will happen
+ */
+ int yyps_index = (yy_ps - yys);
+ int yypv_index = (yy_pv - yyv);
+ int yypvt_index = (yypvt - yyv);
+ yymaxdepth += YYMAXDEPTH;
+ yyv = (YYSTYPE*)realloc((char*)yyv,
+ yymaxdepth * sizeof(YYSTYPE));
+ yys = (int*)realloc((char*)yys,
+ yymaxdepth * sizeof(int));
+ if (!yyv || !yys)
+ {
+ yyerror( "yacc stack overflow" );
+ return(1);
+ }
+ yy_ps = yys + yyps_index;
+ yy_pv = yyv + yypv_index;
+ yypvt = yyv + yypvt_index;
+ }
+ *yy_ps = yy_state;
+ *++yy_pv = yyval;
+
+ /*
+ ** we have a new state - find out what to do
+ */
+ yy_newstate:
+ if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG )
+ goto yydefault; /* simple state */
+#if YYDEBUG
+ /*
+ ** if debugging, need to mark whether new token grabbed
+ */
+ yytmp = yychar < 0;
+#endif
+ if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
+ yychar = 0; /* reached EOF */
+#if YYDEBUG
+ if ( yydebug && yytmp )
+ {
+ register int yy_i;
+
+ (void)printf( "Received token " );
+ if ( yychar == 0 )
+ (void)printf( "end-of-file\n" );
+ else if ( yychar < 0 )
+ (void)printf( "-none-\n" );
+ else
+ {
+ for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
+ yy_i++ )
+ {
+ if ( yytoks[yy_i].t_val == yychar )
+ break;
+ }
+ (void)printf( "%s\n", yytoks[yy_i].t_name );
+ }
+ }
+#endif /* YYDEBUG */
+ if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) )
+ goto yydefault;
+ if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar ) /*valid shift*/
+ {
+ yychar = -1;
+ yyval = yylval;
+ yy_state = yy_n;
+ if ( yyerrflag > 0 )
+ yyerrflag--;
+ goto yy_stack;
+ }
+
+ yydefault:
+ if ( ( yy_n = yydef[ yy_state ] ) == -2 )
+ {
+#if YYDEBUG
+ yytmp = yychar < 0;
+#endif
+ if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
+ yychar = 0; /* reached EOF */
+#if YYDEBUG
+ if ( yydebug && yytmp )
+ {
+ register int yy_i;
+
+ (void)printf( "Received token " );
+ if ( yychar == 0 )
+ (void)printf( "end-of-file\n" );
+ else if ( yychar < 0 )
+ (void)printf( "-none-\n" );
+ else
+ {
+ for ( yy_i = 0;
+ yytoks[yy_i].t_val >= 0;
+ yy_i++ )
+ {
+ if ( yytoks[yy_i].t_val
+ == yychar )
+ {
+ break;
+ }
+ }
+ (void)printf( "%s\n", yytoks[yy_i].t_name );
+ }
+ }
+#endif /* YYDEBUG */
+ /*
+ ** look through exception table
+ */
+ {
+ register int *yyxi = yyexca;
+
+ while ( ( *yyxi != -1 ) ||
+ ( yyxi[1] != yy_state ) )
+ {
+ yyxi += 2;
+ }
+ while ( ( *(yyxi += 2) >= 0 ) &&
+ ( *yyxi != yychar ) )
+ ;
+ if ( ( yy_n = yyxi[1] ) < 0 )
+ YYACCEPT;
+ }
+ }
+
+ /*
+ ** check for syntax error
+ */
+ if ( yy_n == 0 ) /* have an error */
+ {
+ /* no worry about speed here! */
+ switch ( yyerrflag )
+ {
+ case 0: /* new error */
+ yyerror( "syntax error" );
+ goto skip_init;
+ yyerrlab:
+ /*
+ ** get globals into registers.
+ ** we have a user generated syntax type error
+ */
+ yy_pv = yypv;
+ yy_ps = yyps;
+ yy_state = yystate;
+ yynerrs++;
+ skip_init:
+ case 1:
+ case 2: /* incompletely recovered error */
+ /* try again... */
+ yyerrflag = 3;
+ /*
+ ** find state where "error" is a legal
+ ** shift action
+ */
+ while ( yy_ps >= yys )
+ {
+ yy_n = yypact[ *yy_ps ] + YYERRCODE;
+ if ( yy_n >= 0 && yy_n < YYLAST &&
+ yychk[yyact[yy_n]] == YYERRCODE) {
+ /*
+ ** simulate shift of "error"
+ */
+ yy_state = yyact[ yy_n ];
+ goto yy_stack;
+ }
+ /*
+ ** current state has no shift on
+ ** "error", pop stack
+ */
+#if YYDEBUG
+# define _POP_ "Error recovery pops state %d, uncovers state %d\n"
+ if ( yydebug )
+ (void)printf( _POP_, *yy_ps,
+ yy_ps[-1] );
+# undef _POP_
+#endif
+ yy_ps--;
+ yy_pv--;
+ }
+ /*
+ ** there is no state on stack with "error" as
+ ** a valid shift. give up.
+ */
+ YYABORT;
+ case 3: /* no shift yet; eat a token */
+#if YYDEBUG
+ /*
+ ** if debugging, look up token in list of
+ ** pairs. 0 and negative shouldn't occur,
+ ** but since timing doesn't matter when
+ ** debugging, it doesn't hurt to leave the
+ ** tests here.
+ */
+ if ( yydebug )
+ {
+ register int yy_i;
+
+ (void)printf( "Error recovery discards " );
+ if ( yychar == 0 )
+ (void)printf( "token end-of-file\n" );
+ else if ( yychar < 0 )
+ (void)printf( "token -none-\n" );
+ else
+ {
+ for ( yy_i = 0;
+ yytoks[yy_i].t_val >= 0;
+ yy_i++ )
+ {
+ if ( yytoks[yy_i].t_val
+ == yychar )
+ {
+ break;
+ }
+ }
+ (void)printf( "token %s\n",
+ yytoks[yy_i].t_name );
+ }
+ }
+#endif /* YYDEBUG */
+ if ( yychar == 0 ) /* reached EOF. quit */
+ YYABORT;
+ yychar = -1;
+ goto yy_newstate;
+ }
+ }/* end if ( yy_n == 0 ) */
+ /*
+ ** reduction by production yy_n
+ ** put stack tops, etc. so things right after switch
+ */
+#if YYDEBUG
+ /*
+ ** if debugging, print the string that is the user's
+ ** specification of the reduction which is just about
+ ** to be done.
+ */
+ if ( yydebug )
+ (void)printf( "Reduce by (%d) \"%s\"\n",
+ yy_n, yyreds[ yy_n ] );
+#endif
+ yytmp = yy_n; /* value to switch over */
+ yypvt = yy_pv; /* $vars top of value stack */
+ /*
+ ** Look in goto table for next state
+ ** Sorry about using yy_state here as temporary
+ ** register variable, but why not, if it works...
+ ** If yyr2[ yy_n ] doesn't have the low order bit
+ ** set, then there is no action to be done for
+ ** this reduction. So, no saving & unsaving of
+ ** registers done. The only difference between the
+ ** code just after the if and the body of the if is
+ ** the goto yy_stack in the body. This way the test
+ ** can be made before the choice of what to do is needed.
+ */
+ {
+ /* length of production doubled with extra bit */
+ register int yy_len = yyr2[ yy_n ];
+
+ if ( !( yy_len & 01 ) )
+ {
+ yy_len >>= 1;
+ yyval = ( yy_pv -= yy_len )[1]; /* $$ = $1 */
+ yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
+ *( yy_ps -= yy_len ) + 1;
+ if ( yy_state >= YYLAST ||
+ yychk[ yy_state =
+ yyact[ yy_state ] ] != -yy_n )
+ {
+ yy_state = yyact[ yypgo[ yy_n ] ];
+ }
+ goto yy_stack;
+ }
+ yy_len >>= 1;
+ yyval = ( yy_pv -= yy_len )[1]; /* $$ = $1 */
+ yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
+ *( yy_ps -= yy_len ) + 1;
+ if ( yy_state >= YYLAST ||
+ yychk[ yy_state = yyact[ yy_state ] ] != -yy_n )
+ {
+ yy_state = yyact[ yypgo[ yy_n ] ];
+ }
+ }
+ /* save until reenter driver code */
+ yystate = yy_state;
+ yyps = yy_ps;
+ yypv = yy_pv;
+ }
+ /*
+ ** code supplied by user is placed in this switch
+ */
+ switch( yytmp )
+ {
+
+case 1:
+# line 81 "rttgram.y"
+{yyval.n = sym_node(yypvt[-0].t);} break;
+case 2:
+# line 82 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 3:
+# line 83 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 4:
+# line 84 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 5:
+# line 85 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 6:
+# line 86 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 7:
+# line 87 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 8:
+# line 88 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 9:
+# line 89 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 10:
+# line 90 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 11:
+# line 91 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 12:
+# line 92 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 13:
+# line 93 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 15:
+# line 98 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-2].t, yypvt[-3].n, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 16:
+# line 100 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-2].n, NULL);
+ free_t(yypvt[-1].t);} break;
+case 17:
+# line 102 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-3].n, yypvt[-1].n);
+ free_t(yypvt[-2].t);} break;
+case 18:
+# line 104 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 19:
+# line 105 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 20:
+# line 106 "rttgram.y"
+{yyval.n = node1(PstfxNd, yypvt[-0].t, yypvt[-1].n);} break;
+case 21:
+# line 107 "rttgram.y"
+{yyval.n = node1(PstfxNd, yypvt[-0].t, yypvt[-1].n);} break;
+case 22:
+# line 109 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-5].t, yypvt[-3].n, yypvt[-1].n); free_t(yypvt[-4].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 23:
+# line 111 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-7].t, yypvt[-5].n, yypvt[-3].n, yypvt[-1].n), free_t(yypvt[-6].t); free_t(yypvt[-4].t); free_t(yypvt[-2].t);
+ free_t(yypvt[-0].t);} break;
+case 24:
+# line 114 "rttgram.y"
+{yyval.n = node4(QuadNd, yypvt[-9].t, yypvt[-7].n, yypvt[-5].n, yypvt[-3].n, yypvt[-1].n), free_t(yypvt[-8].t); free_t(yypvt[-6].t);
+ free_t(yypvt[-4].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 26:
+# line 120 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 28:
+# line 125 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 29:
+# line 126 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 30:
+# line 127 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 31:
+# line 128 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 32:
+# line 129 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-3].t, yypvt[-1].n);
+ free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 40:
+# line 144 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-3].t, yypvt[-2].n, yypvt[-0].n); free_t(yypvt[-1].t);} break;
+case 42:
+# line 149 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 43:
+# line 150 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 44:
+# line 151 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 46:
+# line 156 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 47:
+# line 157 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 49:
+# line 162 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 50:
+# line 163 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 52:
+# line 168 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 53:
+# line 169 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 54:
+# line 170 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 55:
+# line 171 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 57:
+# line 176 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 58:
+# line 177 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 60:
+# line 182 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 62:
+# line 187 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 64:
+# line 192 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 66:
+# line 197 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 68:
+# line 202 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 70:
+# line 208 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-3].t, yypvt[-4].n, yypvt[-2].n, yypvt[-0].n);
+ free_t(yypvt[-1].t);} break;
+case 72:
+# line 214 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 85:
+# line 233 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 86:
+# line 237 "rttgram.y"
+{yyval.n = NULL;} break;
+case 89:
+# line 246 "rttgram.y"
+{yyval.n = NULL;} break;
+case 91:
+# line 251 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-1].n, NULL);
+ dcl_stk->kind_dcl = OtherDcl;} break;
+case 92:
+# line 253 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-2].n, yypvt[-1].n);
+ dcl_stk->kind_dcl = OtherDcl;} break;
+case 93:
+# line 256 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-2].n, yypvt[-1].n);
+ dcl_stk->kind_dcl = OtherDcl;} break;
+case 95:
+# line 262 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 98:
+# line 271 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 99:
+# line 273 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, node0(PrimryNd, yypvt[-1].t), yypvt[-0].n);} break;
+case 102:
+# line 279 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 103:
+# line 280 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 104:
+# line 281 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 107:
+# line 287 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 108:
+# line 288 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 110:
+# line 293 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 112:
+# line 299 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 113:
+# line 303 "rttgram.y"
+{yyval.n = yypvt[-0].n; id_def(yypvt[-0].n, NULL);} break;
+case 114:
+# line 304 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n); id_def(yypvt[-2].n, yypvt[-0].n);} break;
+case 115:
+# line 308 "rttgram.y"
+{yyval.n = yypvt[-0].n; id_def(yypvt[-0].n, NULL);} break;
+case 116:
+# line 310 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n); id_def(yypvt[-2].n, yypvt[-0].n);} break;
+case 117:
+# line 314 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t); dcl_stk->kind_dcl = IsTypedef;} break;
+case 118:
+# line 315 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 119:
+# line 316 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 120:
+# line 317 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 121:
+# line 318 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 123:
+# line 323 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 124:
+# line 327 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 125:
+# line 328 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 126:
+# line 329 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 127:
+# line 330 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 128:
+# line 331 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 129:
+# line 332 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 130:
+# line 333 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 131:
+# line 334 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 132:
+# line 335 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 135:
+# line 342 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-4].t, yypvt[-3].n, yypvt[-1].n);
+ free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 136:
+# line 345 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-3].t, NULL, yypvt[-1].n);
+ free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 137:
+# line 347 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-0].n, NULL);} break;
+case 141:
+# line 357 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 142:
+# line 362 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-2].n, yypvt[-1].n);} break;
+case 143:
+# line 363 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-2].n, yypvt[-1].n);} break;
+case 145:
+# line 368 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 146:
+# line 372 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 147:
+# line 373 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, node0(PrimryNd, yypvt[-1].t), yypvt[-0].n);} break;
+case 150:
+# line 379 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 151:
+# line 380 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 153:
+# line 384 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 154:
+# line 388 "rttgram.y"
+{yyval.n = node2(StrDclNd, NULL, yypvt[-0].n, NULL);
+ if (dcl_stk->parms_done) pop_cntxt();} break;
+case 155:
+# line 390 "rttgram.y"
+{yyval.n = node2(StrDclNd, yypvt[-1].t, NULL, yypvt[-0].n);} break;
+case 156:
+# line 391 "rttgram.y"
+{if (dcl_stk->parms_done) pop_cntxt();} break;
+case 157:
+# line 392 "rttgram.y"
+{yyval.n = node2(StrDclNd, yypvt[-2].t, yypvt[-3].n, yypvt[-0].n);} break;
+case 159:
+# line 398 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 160:
+# line 402 "rttgram.y"
+{yyval.n = node2(StrDclNd, NULL, yypvt[-0].n, NULL);
+ if (dcl_stk->parms_done) pop_cntxt();} break;
+case 161:
+# line 404 "rttgram.y"
+{yyval.n = node2(StrDclNd, yypvt[-1].t, NULL, yypvt[-0].n);} break;
+case 162:
+# line 405 "rttgram.y"
+{if (dcl_stk->parms_done) pop_cntxt();} break;
+case 163:
+# line 406 "rttgram.y"
+{yyval.n = node2(StrDclNd, yypvt[-2].t, yypvt[-3].n, yypvt[-0].n);} break;
+case 164:
+# line 410 "rttgram.y"
+{push_cntxt(0);} break;
+case 165:
+# line 411 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-4].t, NULL, yypvt[-1].n); pop_cntxt(); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 166:
+# line 412 "rttgram.y"
+{push_cntxt(0);} break;
+case 167:
+# line 413 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-5].t, yypvt[-4].n, yypvt[-1].n); pop_cntxt(); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 168:
+# line 414 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-0].n, NULL);} break;
+case 170:
+# line 419 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 171:
+# line 423 "rttgram.y"
+{yyval.n = yypvt[-0].n; id_def(yypvt[-0].n, NULL);} break;
+case 172:
+# line 425 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n); id_def(yypvt[-2].n, yypvt[-0].n);} break;
+case 173:
+# line 429 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 174:
+# line 430 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 175:
+# line 435 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 176:
+# line 439 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 178:
+# line 444 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 179:
+# line 446 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-2].t, yypvt[-3].n, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 180:
+# line 448 "rttgram.y"
+{push_cntxt(1);} break;
+case 181:
+# line 449 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-4].n, yypvt[-1].n);
+ if (dcl_stk->nest_lvl == 2)
+ dcl_stk->parms_done = 1;
+ else
+ pop_cntxt();
+ free_t(yypvt[-3].t);} break;
+case 182:
+# line 458 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 183:
+# line 459 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 184:
+# line 462 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-2].t, yypvt[-3].n, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 185:
+# line 464 "rttgram.y"
+{push_cntxt(1);} break;
+case 186:
+# line 465 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-4].n, yypvt[-1].n);
+ if (dcl_stk->nest_lvl == 2)
+ dcl_stk->parms_done = 1;
+ else
+ pop_cntxt();
+ free_t(yypvt[-3].t);} break;
+case 189:
+# line 479 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 190:
+# line 480 "rttgram.y"
+{yyval.n = node1(PreSpcNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 191:
+# line 481 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 192:
+# line 482 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, node2(LstNd, NULL, yypvt[-1].n,yypvt[-0].n));} break;
+case 193:
+# line 486 "rttgram.y"
+{yyval.n = NULL;} break;
+case 196:
+# line 492 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 198:
+# line 497 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, node0(PrimryNd, yypvt[-0].t));} break;
+case 199:
+# line 501 "rttgram.y"
+{yyval.n = NULL;} break;
+case 202:
+# line 507 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 203:
+# line 511 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);
+ id_def(yypvt[-0].n, NULL);} break;
+case 205:
+# line 514 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 206:
+# line 518 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 207:
+# line 519 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, node0(PrimryNd,yypvt[-0].t));} break;
+case 210:
+# line 525 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 211:
+# line 526 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 213:
+# line 531 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 215:
+# line 536 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 216:
+# line 540 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 217:
+# line 543 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-2].t, NULL, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 218:
+# line 546 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-2].t, yypvt[-3].n, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 219:
+# line 548 "rttgram.y"
+{push_cntxt(1);} break;
+case 220:
+# line 549 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, NULL, yypvt[-1].n);
+ pop_cntxt();
+ free_t(yypvt[-3].t);} break;
+case 221:
+# line 552 "rttgram.y"
+{push_cntxt(1);} break;
+case 222:
+# line 553 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-0].t, yypvt[-4].n, yypvt[-1].n);
+ pop_cntxt();
+ free_t(yypvt[-3].t);} break;
+case 224:
+# line 561 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 225:
+# line 563 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-3].t, node2(CommaNd, yypvt[-1].t, yypvt[-2].n, NULL));
+ free_t(yypvt[-0].t);} break;
+case 227:
+# line 569 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 230:
+# line 578 "rttgram.y"
+{push_cntxt(1);} break;
+case 231:
+# line 578 "rttgram.y"
+{yyval.n = yypvt[-0].n; pop_cntxt();} break;
+case 236:
+# line 584 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-4].t, yypvt[-2].n, NULL); free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 237:
+# line 586 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-6].t, yypvt[-4].n, yypvt[-2].n); free_t(yypvt[-5].t); free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 238:
+# line 590 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 239:
+# line 591 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-3].t, yypvt[-2].n, yypvt[-0].n); free_t(yypvt[-1].t);} break;
+case 240:
+# line 592 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-0].n); free_t(yypvt[-1].t);} break;
+case 241:
+# line 596 "rttgram.y"
+{yyval.n = comp_nd(yypvt[-2].t, NULL, yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 242:
+# line 597 "rttgram.y"
+{yyval.n = comp_nd(yypvt[-3].t, yypvt[-2].n, yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 244:
+# line 602 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 245:
+# line 606 "rttgram.y"
+{yyval.n = NULL;} break;
+case 248:
+# line 612 "rttgram.y"
+{yyval.n = (yypvt[-0].n == NULL ? yypvt[-1].n : node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n));} break;
+case 250:
+# line 618 "rttgram.y"
+{yyval.n = NULL; free_t(yypvt[-3].t); free_t(yypvt[-0].t); dcl_stk->kind_dcl = OtherDcl;} break;
+case 251:
+# line 622 "rttgram.y"
+{tnd_char(); free_t(yypvt[-0].t);} break;
+case 252:
+# line 623 "rttgram.y"
+{tnd_strct(yypvt[-0].t); free_t(yypvt[-1].t);} break;
+case 253:
+# line 624 "rttgram.y"
+{tnd_strct(yypvt[-0].t); free_t(yypvt[-1].t);} break;
+case 254:
+# line 625 "rttgram.y"
+{tnd_union(yypvt[-0].t); free_t(yypvt[-1].t);} break;
+case 256:
+# line 630 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 257:
+# line 634 "rttgram.y"
+{yyval.n = NULL;} break;
+case 259:
+# line 638 "rttgram.y"
+{yyval.n = node1(PstfxNd, yypvt[-0].t, yypvt[-1].n);} break;
+case 260:
+# line 642 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-4].t, yypvt[-2].n, yypvt[-0].n,NULL);
+ free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 261:
+# line 644 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-6].t, yypvt[-4].n, yypvt[-2].n, yypvt[-0].n);
+ free_t(yypvt[-5].t); free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 262:
+# line 646 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-4].t, yypvt[-2].n, yypvt[-0].n);
+ free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 263:
+# line 649 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-6].t, yypvt[-5].n, yypvt[-2].n, yypvt[-1].n); free_t(yypvt[-4].t); free_t(yypvt[-3].t); free_t(yypvt[-0].t);} break;
+case 264:
+# line 653 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, NULL, yypvt[-0].n);} break;
+case 265:
+# line 654 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 266:
+# line 658 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 267:
+# line 662 "rttgram.y"
+{yyval.n = NULL;} break;
+case 268:
+# line 663 "rttgram.y"
+{yyval.n = yypvt[-0].n; free_t(yypvt[-2].t); free_t(yypvt[-1].t);} break;
+case 269:
+# line 667 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-4].t, yypvt[-2].n, yypvt[-0].n);
+ free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 270:
+# line 669 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-6].t, yypvt[-5].n, yypvt[-2].n);
+ free_t(yypvt[-4].t); free_t(yypvt[-3].t); free_t(yypvt[-1].t);
+ free_t(yypvt[-0].t);} break;
+case 271:
+# line 673 "rttgram.y"
+{yyval.n = node4(QuadNd, yypvt[-8].t, yypvt[-6].n, yypvt[-4].n, yypvt[-2].n, yypvt[-0].n);
+ free_t(yypvt[-7].t); free_t(yypvt[-5].t); free_t(yypvt[-3].t);
+ free_t(yypvt[-1].t);} break;
+case 272:
+# line 679 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 273:
+# line 680 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-1].t); free_t(yypvt[-0].t);} break;
+case 274:
+# line 681 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-1].t); free_t(yypvt[-0].t);} break;
+case 275:
+# line 682 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 276:
+# line 683 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 277:
+# line 684 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-1].t); free_t(yypvt[-0].t);} break;
+case 278:
+# line 685 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-1].t); free_t(yypvt[-0].t);} break;
+case 284:
+# line 700 "rttgram.y"
+{dclout(yypvt[-0].n);} break;
+case 286:
+# line 705 "rttgram.y"
+{func_def(yypvt[-0].n);} break;
+case 287:
+# line 706 "rttgram.y"
+{fncout(yypvt[-3].n, yypvt[-1].n, yypvt[-0].n);} break;
+case 288:
+# line 710 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, NULL, yypvt[-0].n);} break;
+case 289:
+# line 711 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 290:
+# line 712 "rttgram.y"
+{yyval.n = node2(LstNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 291:
+# line 716 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 292:
+# line 717 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 293:
+# line 721 "rttgram.y"
+{yyval.n = lbl(yypvt[-0].t);} break;
+case 294:
+# line 722 "rttgram.y"
+{yyval.n = lbl(yypvt[-0].t);} break;
+case 299:
+# line 737 "rttgram.y"
+{strt_def();} break;
+case 301:
+# line 741 "rttgram.y"
+{defout(yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 302:
+# line 742 "rttgram.y"
+{defout(yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 303:
+# line 743 "rttgram.y"
+{keyconst(yypvt[-1].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 304:
+# line 747 "rttgram.y"
+{comment = NULL;} break;
+case 305:
+# line 748 "rttgram.y"
+{comment = yypvt[-0].t;} break;
+case 306:
+# line 753 "rttgram.y"
+{impl_fnc(yypvt[-3].t); free_t(yypvt[-7].t); free_t(yypvt[-6].t); free_t(yypvt[-4].t); free_t(yypvt[-2].t);
+ free_t(yypvt[-0].t);} break;
+case 307:
+# line 755 "rttgram.y"
+{lex_state = OpHead;} break;
+case 308:
+# line 756 "rttgram.y"
+{lex_state = DfltLex;} break;
+case 309:
+# line 757 "rttgram.y"
+{impl_op(yypvt[-5].t, yypvt[-3].t); free_t(yypvt[-10].t); free_t(yypvt[-9].t); free_t(yypvt[-6].t); free_t(yypvt[-2].t);
+ free_t(yypvt[-0].t);} break;
+case 310:
+# line 762 "rttgram.y"
+{impl_key(yypvt[-0].t); free_t(yypvt[-4].t); free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 383:
+# line 853 "rttgram.y"
+{set_r_seq(NoRsltSeq, NoRsltSeq, 0);} break;
+case 384:
+# line 854 "rttgram.y"
+{set_r_seq(yypvt[-1].i, yypvt[-1].i, (int)yypvt[-0].i);} break;
+case 385:
+# line 855 "rttgram.y"
+{set_r_seq(yypvt[-3].i, yypvt[-1].i, (int)yypvt[-0].i); free_t(yypvt[-2].t);} break;
+case 386:
+# line 859 "rttgram.y"
+{yyval.i = ttol(yypvt[-0].t); free_t(yypvt[-0].t);} break;
+case 387:
+# line 860 "rttgram.y"
+{yyval.i = UnbndSeq; free_t(yypvt[-0].t);} break;
+case 388:
+# line 864 "rttgram.y"
+{yyval.i = 0;} break;
+case 389:
+# line 865 "rttgram.y"
+{yyval.i = 1; free_t(yypvt[-0].t);} break;
+case 392:
+# line 871 "rttgram.y"
+{var_args(yypvt[-1].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 394:
+# line 876 "rttgram.y"
+{free_t(yypvt[-1].t);} break;
+case 395:
+# line 880 "rttgram.y"
+{s_prm_def(NULL, yypvt[-0].t);} break;
+case 396:
+# line 881 "rttgram.y"
+{s_prm_def(yypvt[-0].t, NULL); free_t(yypvt[-1].t);} break;
+case 397:
+# line 882 "rttgram.y"
+{s_prm_def(yypvt[-2].t, yypvt[-0].t); free_t(yypvt[-3].t);
+ free_t(yypvt[-1].t);} break;
+case 398:
+# line 887 "rttgram.y"
+{} break;
+case 399:
+# line 888 "rttgram.y"
+{d_lst_typ(yypvt[-1].n); free_t(yypvt[-3].t); free_t(yypvt[-2].t);
+ free_t(yypvt[-0].t);} break;
+case 400:
+# line 893 "rttgram.y"
+{yyval.n = NULL;} break;
+case 403:
+# line 899 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 407:
+# line 906 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-1].n); free_t(yypvt[-0].t);} break;
+case 408:
+# line 907 "rttgram.y"
+{lex_state = TypeComp;} break;
+case 409:
+# line 908 "rttgram.y"
+{lex_state = DfltLex;} break;
+case 410:
+# line 909 "rttgram.y"
+{yyval.n = yypvt[-2].n; free_t(yypvt[-5].t); free_t(yypvt[-3].t); free_t(yypvt[-0].t);} break;
+case 411:
+# line 914 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-3].t, yypvt[-2].n, yypvt[-0].n, NULL); free_t(yypvt[-1].t);} break;
+case 412:
+# line 916 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-5].t, yypvt[-4].n, yypvt[-2].n, yypvt[-0].n); free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 413:
+# line 918 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-6].t, yypvt[-5].n, yypvt[-2].n, yypvt[-1].n); free_t(yypvt[-4].t); free_t(yypvt[-3].t); free_t(yypvt[-0].t);} break;
+case 414:
+# line 920 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-8].t, sym_node(yypvt[-7].t), yypvt[-4].n, yypvt[-1].n); free_t(yypvt[-6].t), free_t(yypvt[-5].t);
+ free_t(yypvt[-3].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 415:
+# line 924 "rttgram.y"
+{yyval.n = arith_nd(yypvt[-17].t, yypvt[-15].n, yypvt[-13].n, yypvt[-9].n, yypvt[-7].n, yypvt[-6].n, yypvt[-4].n, yypvt[-3].n, yypvt[-1].n); free_t(yypvt[-16].t);
+ free_t(yypvt[-14].t), free_t(yypvt[-12].t); free_t(yypvt[-11].t); free_t(yypvt[-10].t); free_t(yypvt[-8].t);
+ free_t(yypvt[-5].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 416:
+# line 930 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, NULL, yypvt[-0].n);} break;
+case 417:
+# line 931 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 418:
+# line 935 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 419:
+# line 939 "rttgram.y"
+{yyval.n = NULL;} break;
+case 420:
+# line 940 "rttgram.y"
+{yyval.n = yypvt[-0].n; free_t(yypvt[-2].t); free_t(yypvt[-1].t);} break;
+case 421:
+# line 944 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, NULL, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 422:
+# line 946 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-2].n, yypvt[-1].n);
+ free_t(yypvt[-0].t);} break;
+case 424:
+# line 952 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 425:
+# line 956 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-0].n); free_t(yypvt[-1].t);} break;
+case 427:
+# line 961 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 429:
+# line 966 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 430:
+# line 971 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-5].t, yypvt[-3].n, yypvt[-1].n); free_t(yypvt[-4].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 431:
+# line 973 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-5].t, yypvt[-3].n, yypvt[-1].n, NULL), dst_alloc(yypvt[-3].n, yypvt[-1].n); free_t(yypvt[-4].t);
+ free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 432:
+# line 976 "rttgram.y"
+{yyval.n = node3(TrnryNd, yypvt[-7].t, yypvt[-5].n, yypvt[-3].n, yypvt[-1].n), free_t(yypvt[-6].t); free_t(yypvt[-4].t); free_t(yypvt[-2].t);
+ free_t(yypvt[-0].t);} break;
+case 433:
+# line 979 "rttgram.y"
+{yyval.n = node4(QuadNd, yypvt[-7].t, yypvt[-5].n, yypvt[-3].n, yypvt[-1].n, NULL), dst_alloc(yypvt[-5].n, yypvt[-3].n); free_t(yypvt[-6].t);
+ free_t(yypvt[-4].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 434:
+# line 982 "rttgram.y"
+{yyval.n = node4(QuadNd, yypvt[-9].t, yypvt[-7].n, yypvt[-5].n, yypvt[-3].n, yypvt[-1].n), free_t(yypvt[-8].t); free_t(yypvt[-6].t);
+ free_t(yypvt[-4].t); free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 435:
+# line 987 "rttgram.y"
+{push_cntxt(1);} break;
+case 436:
+# line 988 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-0].n); pop_cntxt();} break;
+case 437:
+# line 989 "rttgram.y"
+{push_cntxt(1);} break;
+case 438:
+# line 990 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-2].t, yypvt[-0].n); pop_cntxt();} break;
+case 439:
+# line 995 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-4].t, node0(PrimryNd, yypvt[-2].t), NULL);
+ free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 440:
+# line 998 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-6].t, node0(PrimryNd, yypvt[-4].t), yypvt[-2].n);
+ free_t(yypvt[-5].t); free_t(yypvt[-3].t); free_t(yypvt[-1].t);} break;
+case 442:
+# line 1004 "rttgram.y"
+{free_t(yypvt[-0].t);} break;
+case 443:
+# line 1008 "rttgram.y"
+{yyval.n = sym_node(yypvt[-0].t);} break;
+case 444:
+# line 1009 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-2].t, sym_node(yypvt[-3].t),
+ node0(PrimryNd, yypvt[-1].t));
+ free_t(yypvt[-0].t);} break;
+case 445:
+# line 1014 "rttgram.y"
+{yyval.n = dest_node(yypvt[-0].t);} break;
+case 446:
+# line 1015 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 447:
+# line 1016 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 448:
+# line 1017 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 449:
+# line 1018 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t); ++n_tmp_str;} break;
+case 450:
+# line 1019 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t); ++n_tmp_cset;} break;
+case 451:
+# line 1020 "rttgram.y"
+{yyval.n = node0(ExactCnv, chk_exct(yypvt[-0].t)); free_t(yypvt[-3].t);
+ free_t(yypvt[-2].t); free_t(yypvt[-1].t);} break;
+case 452:
+# line 1022 "rttgram.y"
+{yyval.n = node0(ExactCnv, yypvt[-0].t); free_t(yypvt[-3].t); free_t(yypvt[-2].t);
+ free_t(yypvt[-1].t);} break;
+case 453:
+# line 1027 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 454:
+# line 1028 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 455:
+# line 1029 "rttgram.y"
+{yyval.n = sym_node(yypvt[-0].t);} break;
+case 456:
+# line 1030 "rttgram.y"
+{yyval.n = node0(PrimryNd, yypvt[-0].t);} break;
+case 458:
+# line 1035 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 459:
+# line 1036 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 460:
+# line 1037 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-1].t, yypvt[-0].n);} break;
+case 461:
+# line 1041 "rttgram.y"
+{yyval.n = node2(AbstrNd, yypvt[-2].t, yypvt[-3].n, yypvt[-1].n);} break;
+case 462:
+# line 1042 "rttgram.y"
+{yyval.n = node2(AbstrNd, yypvt[-2].t, NULL, yypvt[-1].n);} break;
+case 463:
+# line 1043 "rttgram.y"
+{yyval.n = node2(AbstrNd, NULL, yypvt[-0].n, NULL);} break;
+case 465:
+# line 1048 "rttgram.y"
+{yyval.n = node2(ConCatNd, NULL, yypvt[-1].n, yypvt[-0].n);} break;
+case 466:
+# line 1052 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-2].t, yypvt[-4].n, yypvt[-1].n);
+ free_t(yypvt[-6].t); free_t(yypvt[-5].t); free_t(yypvt[-3].t);} break;
+case 468:
+# line 1058 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 469:
+# line 1059 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+case 470:
+# line 1062 "rttgram.y"
+{yyval.n = node1(IcnTypNd,
+ copy_t(yypvt[-0].n->tok), yypvt[-0].n);} break;
+case 471:
+# line 1064 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-3].t, yypvt[-1].n);
+ free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 472:
+# line 1066 "rttgram.y"
+{yyval.n = node2(BinryNd, yypvt[-4].t, yypvt[-3].n, yypvt[-1].n);
+ free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 473:
+# line 1068 "rttgram.y"
+{yyval.n = node1(PrefxNd, yypvt[-3].t, yypvt[-1].n);
+ free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 474:
+# line 1070 "rttgram.y"
+{yyval.n = node1(PstfxNd, yypvt[-0].t, yypvt[-2].n);
+ free_t(yypvt[-1].t);} break;
+case 475:
+# line 1072 "rttgram.y"
+{yyval.n = yypvt[-1].n; free_t(yypvt[-2].t); free_t(yypvt[-0].t);} break;
+case 478:
+# line 1081 "rttgram.y"
+{yyval.n = node2(CommaNd, yypvt[-1].t, yypvt[-2].n, yypvt[-0].n);} break;
+ }
+ goto yystack; /* reset registers in driver code */
+}
diff --git a/src/rtt/rttproto.h b/src/rtt/rttproto.h
new file mode 100644
index 0000000..315286b
--- /dev/null
+++ b/src/rtt/rttproto.h
@@ -0,0 +1,92 @@
+void add_dpnd (struct srcfile *sfile, char *objname);
+int alloc_tnd (int typ, struct node *init, int lvl);
+struct node *arith_nd (struct token *tok, struct node *p1,
+ struct node *p2, struct node *c_int,
+ struct node *ci_act, struct node *intgr,
+ struct node *i_act, struct node *dbl,
+ struct node *d_act);
+struct il_c *bdy_prm (int addr_of, int just_desc, struct sym_entry *sym, int may_mod);
+int c_walk (struct node *n, int indent, int brace);
+int call_ret (struct node *n);
+struct token *chk_exct (struct token *tok);
+void chkabsret (struct token *tok, int ret_typ);
+void clr_def (void);
+void clr_dpnd (char *srcname);
+void clr_prmloc (void);
+struct token *cnv_to_id (struct token *t);
+char *cnv_name (int typcd, struct node *dflt, int *dflt_to_ptr);
+struct node *comp_nd (struct token *tok, struct node *dcls,
+ struct node *stmts);
+int creat_obj (void);
+void d_lst_typ (struct node *dcls);
+void dclout (struct node *n);
+struct node *dest_node (struct token *tok);
+void dst_alloc (struct node *cnv_typ, struct node *var);
+void dumpdb (char *dbname);
+void fncout (struct node *head, struct node *prm_dcl,
+ struct node *block);
+void force_nl (int indent);
+void free_sym (struct sym_entry *sym);
+void free_tree (struct node *n);
+void free_tend (void);
+void full_lst (char *fname);
+void func_def (struct node *dcltor);
+void id_def (struct node *dcltor, struct node *x);
+void keepdir (struct token *s);
+int icn_typ (struct node *n);
+struct il_c *ilc_dcl (struct node *tqual, struct node *dcltor,
+ struct node *init);
+void impl_fnc (struct token *name);
+void impl_key (struct token *name);
+void impl_op (struct token *op_sym, struct token *name);
+void init_lex (void);
+void init_sym (void);
+struct il_c *inlin_c (struct node *n, int may_mod);
+void in_line (struct node *n);
+void just_type (struct node *typ, int indent, int ilc);
+void keyconst (struct token *t);
+struct node *lbl (struct token *t);
+void ld_prmloc (struct parminfo *parminfo);
+void loaddb (char *db);
+void mrg_prmloc (struct parminfo *parminfo);
+struct parminfo *new_prmloc (void);
+struct node *node0 (int id, struct token *tok);
+struct node *node1 (int id, struct token *tok, struct node *n1);
+struct node *node2 (int id, struct token *tok, struct node *n1,
+ struct node *n2);
+struct node *node3 (int id, struct token *tok, struct node *n1,
+ struct node *n2, struct node *n3);
+struct node *node4 (int id, struct token *tok, struct node *n1,
+ struct node *n2, struct node *n3,
+ struct node *n4);
+struct il_c *parm_dcl (int addr_of, struct sym_entry *sym);
+void pop_cntxt (void);
+void pop_lvl (void);
+void prologue (void);
+void prt_str (char *s, int indent);
+void ptout (struct token * x);
+void push_cntxt (int lvl_incr);
+void push_lvl (void);
+void put_c_fl (char *fname, int keep);
+void defout (struct node *n);
+void set_r_seq (long min, long max, int resume);
+struct il_c *simpl_dcl (char *tqual, int addr_of, struct sym_entry *sym);
+void spcl_dcls (struct sym_entry *op_params);
+struct srcfile *src_lkup (char *srcname);
+void strt_def (void);
+void sv_prmloc (struct parminfo *parminfo);
+struct sym_entry *sym_add (int tok_id, char *image, int id_type, int nest_lvl);
+struct sym_entry *sym_lkup (char *image);
+struct node *sym_node (struct token *tok);
+void s_prm_def (struct token *u_ident, struct token *d_ident);
+void tnd_char (void);
+void tnd_strct (struct token *t);
+void tnd_union (struct token *t);
+void trans (char *src_file);
+long ttol (struct token *t);
+char *typ_name (int typ, struct token *tok);
+void unuse (struct init_tend *t_lst, int lvl);
+void var_args (struct token *ident);
+void yyerror (char *s);
+int yylex (void);
+int yyparse (void);
diff --git a/src/rtt/rttsym.c b/src/rtt/rttsym.c
new file mode 100644
index 0000000..9e1901b
--- /dev/null
+++ b/src/rtt/rttsym.c
@@ -0,0 +1,722 @@
+/*
+ * rttsym.c contains symbol table routines.
+ */
+#include "rtt.h"
+
+#define HashSize 149
+
+/*
+ * Prototype for static function.
+ */
+static void add_def (struct node *dcltor);
+static void add_s_prm (struct token *ident, int param_num, int flags);
+static void dcl_typ (struct node *dcl);
+static void dcltor_typ (struct node *dcltor, struct node *tqual);
+
+word lbl_num = 0; /* next unused label number */
+struct lvl_entry *dcl_stk; /* stack of declaration contexts */
+
+char *str_rslt; /* string "result" in string table */
+struct init_tend *tend_lst = NULL; /* list of tended descriptors */
+struct sym_entry *decl_lst = NULL; /* declarations from "declare {...}" */
+struct sym_entry *v_len = NULL; /* entry for length of varargs */
+int il_indx = 0; /* data base symbol table index */
+
+static struct sym_entry *sym_tbl[HashSize]; /* symbol table */
+
+/*
+ * The following strings are put in the string table and used for
+ * recognizing valid tended declarations.
+ */
+static char *block = "block";
+static char *descrip = "descrip";
+
+/*
+ * init_sym - initialize symbol table.
+ */
+void init_sym()
+ {
+ static int first_time = 1;
+ int hash_val;
+ register struct sym_entry *sym;
+ int i;
+
+ /*
+ * Initialize the symbol table and declaration stack. When called for
+ * the first time, put strings in string table.
+ */
+ if (first_time) {
+ first_time = 0;
+ for (i = 0; i < HashSize; ++i)
+ sym_tbl[i] = NULL;
+ dcl_stk = NewStruct(lvl_entry);
+ dcl_stk->nest_lvl = 1;
+ dcl_stk->next = NULL;
+ block = spec_str(block);
+ descrip = spec_str(descrip);
+ }
+ else {
+ for (hash_val = 0; hash_val < HashSize; ++ hash_val) {
+ for (sym = sym_tbl[hash_val]; sym != NULL &&
+ sym->nest_lvl > 0; sym = sym_tbl[hash_val]) {
+ sym_tbl[hash_val] = sym->next;
+ free((char *)sym);
+ }
+ }
+ }
+ dcl_stk->kind_dcl = OtherDcl;
+ dcl_stk->parms_done = 0;
+ }
+
+/*
+ * sym_lkup - look up a string in the symbol table. Return NULL If it is not
+ * there.
+ */
+struct sym_entry *sym_lkup(image)
+char *image;
+ {
+ register struct sym_entry *sym;
+
+ for (sym = sym_tbl[(unsigned int)(unsigned long)image % HashSize];
+ sym != NULL;
+ sym = sym->next)
+ if (sym->image == image)
+ return sym;
+ return NULL;
+ }
+
+/*
+ * sym_add - add a symbol to the symbol table. For some types of entries
+ * it is illegal to redefine them. In that case, NULL is returned otherwise
+ * the entry is returned.
+ */
+struct sym_entry *sym_add(tok_id, image, id_type, nest_lvl)
+int tok_id;
+char *image;
+int id_type;
+int nest_lvl;
+ {
+ register struct sym_entry **symp;
+ register struct sym_entry *sym;
+
+ symp = &sym_tbl[(unsigned int)(unsigned long)image % HashSize];
+ while (*symp != NULL && (*symp)->nest_lvl > nest_lvl)
+ symp = &((*symp)->next);
+ while (*symp != NULL && (*symp)->nest_lvl == nest_lvl) {
+ if ((*symp)->image == image) {
+ /*
+ * Redeclaration:
+ *
+ * An explicit typedef may be given for a built-in typedef
+ * name. A label appears in multiply gotos and as a label
+ * on a statement. Assume a global redeclaration is for an
+ * extern. Return the entry for these situations but don't
+ * try too hard to detect errors. If actual errors are not
+ * caught here, the C compiler will find them.
+ */
+ if (tok_id == TypeDefName && ((*symp)->tok_id == C_Integer ||
+ (*symp)->tok_id == TypeDefName))
+ return *symp;
+ if (id_type == Label && (*symp)->id_type == Label)
+ return *symp;
+ if ((*symp)->nest_lvl == 1)
+ return *symp;
+ return NULL; /* illegal redeclarations */
+ }
+ symp = &((*symp)->next);
+ }
+
+ /*
+ * No entry exists for the symbol, create one, fill in its fields, and add
+ * it to the table.
+ */
+ sym = NewStruct(sym_entry);
+ sym->tok_id = tok_id;
+ sym->image = image;
+ sym->id_type = id_type;
+ sym->nest_lvl = nest_lvl;
+ sym->ref_cnt = 1;
+ sym->il_indx = -1;
+ sym->may_mod = 0;
+ if (id_type == Label)
+ sym->u.lbl_num = lbl_num++;
+ sym->next = *symp;
+ *symp = sym;
+
+ return sym; /* success */
+ }
+
+/*
+ * lbl - make sure the label is in the symbol table and return a node
+ * referencing the symbol table entry.
+ */
+struct node *lbl(t)
+struct token *t;
+ {
+ struct sym_entry *sym;
+ struct node *n;
+
+ sym = sym_add(Identifier, t->image, Label, 2);
+ if (sym == NULL)
+ errt2(t, "conflicting definitions for ", t->image);
+ n = sym_node(t);
+ if (n->u[0].sym != sym)
+ errt2(t, "conflicting definitions for ", t->image);
+ return n;
+ }
+
+/*
+ * push_cntxt - push a level of declaration context (this may or may not
+ * be level of declaration nesting).
+ */
+void push_cntxt(lvl_incr)
+int lvl_incr;
+ {
+ struct lvl_entry *entry;
+
+ entry = NewStruct(lvl_entry);
+ entry->nest_lvl = dcl_stk->nest_lvl + lvl_incr;
+ entry->kind_dcl = OtherDcl;
+ entry->parms_done = 0;
+ entry->tended = NULL;
+ entry->next = dcl_stk;
+ dcl_stk = entry;
+ }
+
+/*
+ * pop_cntxt - end a level of declaration context
+ */
+void pop_cntxt()
+ {
+ int hash_val;
+ int old_lvl;
+ int new_lvl;
+ register struct sym_entry *sym;
+ struct lvl_entry *entry;
+
+ /*
+ * Move the top entry of the stack to the free list.
+ */
+ old_lvl = dcl_stk->nest_lvl;
+ entry = dcl_stk;
+ dcl_stk = dcl_stk->next;
+ free((char *)entry);
+
+ /*
+ * If this pop reduced the declaration nesting level, remove obsolete
+ * entries from the symbol table.
+ */
+ new_lvl = dcl_stk->nest_lvl;
+ if (old_lvl > new_lvl) {
+ for (hash_val = 0; hash_val < HashSize; ++ hash_val) {
+ for (sym = sym_tbl[hash_val]; sym != NULL &&
+ sym->nest_lvl > new_lvl; sym = sym_tbl[hash_val]) {
+ sym_tbl[hash_val] = sym->next;
+ free_sym(sym);
+ }
+ }
+ unuse(tend_lst, old_lvl);
+ }
+ }
+
+/*
+ * unuse - mark tended slots in at the given level of declarations nesting
+ * as being no longer in use, and leave the slots available for reuse
+ * for declarations that occur in pararallel compound statements.
+ */
+void unuse(t_lst, lvl)
+struct init_tend *t_lst;
+int lvl;
+ {
+ while (t_lst != NULL) {
+ if (t_lst->nest_lvl >= lvl)
+ t_lst->in_use = 0;
+ t_lst = t_lst->next;
+ }
+ }
+
+/*
+ * free_sym - remove a reference to a symbol table entry and free storage
+ * related to it if no references remain.
+ */
+void free_sym(sym)
+struct sym_entry *sym;
+ {
+ if (--sym->ref_cnt <= 0) {
+ switch (sym->id_type) {
+ case TndDesc:
+ case TndStr:
+ case TndBlk:
+ free_tree(sym->u.tnd_var.init); /* initializer expression */
+ }
+ free((char *)sym);
+ }
+ }
+
+/*
+ * alloc_tnd - allocated a slot in a tended array for a variable and return
+ * its index.
+ */
+int alloc_tnd(typ, init, lvl)
+int typ;
+struct node *init;
+int lvl;
+ {
+ register struct init_tend *tnd;
+
+ if (lvl > 2) {
+ /*
+ * This declaration occurs in an inner compound statement. There
+ * may be slots created for parallel compound statement, but were
+ * freed and can be reused here.
+ */
+ tnd = tend_lst;
+ while (tnd != NULL && (tnd->in_use || tnd->init_typ != typ))
+ tnd = tnd->next;
+ if (tnd != NULL) {
+ tnd->in_use = 1;
+ tnd->nest_lvl = lvl;
+ return tnd->t_indx;
+ }
+ }
+
+ /*
+ * Allocate a new tended slot, compute its index in the array, and
+ * set initialization and other information.
+ */
+ tnd = NewStruct(init_tend);
+
+ if (tend_lst == NULL)
+ tnd->t_indx = 0;
+ else
+ tnd->t_indx = tend_lst->t_indx + 1;
+ tnd->init_typ = typ;
+ /*
+ * The initialization from the declaration will only be used to
+ * set up the tended location if the declaration is in the outermost
+ * "block". Otherwise a generic initialization will be done during
+ * the set up and the one from the declaration will be put off until
+ * the block is entered.
+ */
+ if (lvl == 2)
+ tnd->init = init;
+ else
+ tnd->init = NULL;
+ tnd->in_use = 1;
+ tnd->nest_lvl = lvl;
+ tnd->next = tend_lst;
+ tend_lst = tnd;
+ return tnd->t_indx;
+ }
+
+/*
+ * free_tend - put the list of tended descriptors on the free list.
+ */
+void free_tend()
+ {
+ register struct init_tend *tnd, *tnd1;
+
+ for (tnd = tend_lst; tnd != NULL; tnd = tnd1) {
+ tnd1 = tnd->next;
+ free((char *)tnd);
+ }
+ tend_lst = NULL;
+ }
+
+/*
+ * dst_alloc - the conversion of a parameter is encountered during
+ * parsing; make sure a place is allocated to act as the destination.
+ */
+void dst_alloc(cnv_typ, var)
+struct node *cnv_typ;
+struct node *var;
+ {
+ struct sym_entry *sym;
+
+ if (var->nd_id == SymNd) {
+ sym = var->u[0].sym;
+ if (sym->id_type & DrfPrm) {
+ switch (cnv_typ->tok->tok_id) {
+ case C_Integer:
+ sym->u.param_info.non_tend |= PrmInt;
+ break;
+ case C_Double:
+ sym->u.param_info.non_tend |= PrmDbl;
+ break;
+ }
+ }
+ }
+ }
+
+/*
+ * strt_def - the start of an operation definition is encountered during
+ * parsing; establish an new declaration context and make "result"
+ * a special identifier.
+ */
+void strt_def()
+ {
+ struct sym_entry *sym;
+
+ push_cntxt(1);
+ sym = sym_add(Identifier, str_rslt, RsltLoc, dcl_stk->nest_lvl);
+ sym->u.referenced = 0;
+ }
+
+/*
+ * add_def - update the symbol table for the given declarator.
+ */
+static void add_def(dcltor)
+struct node *dcltor;
+ {
+ struct sym_entry *sym;
+ struct token *t;
+ int tok_id;
+
+ /*
+ * find the identifier within the declarator.
+ */
+ for (;;) {
+ switch (dcltor->nd_id) {
+ case BinryNd:
+ /* ')' or '[' */
+ dcltor = dcltor->u[0].child;
+ break;
+ case ConCatNd:
+ /* pointer direct-declarator */
+ dcltor = dcltor->u[1].child;
+ break;
+ case PrefxNd:
+ /* ( ... ) */
+ dcltor = dcltor->u[0].child;
+ break;
+ case PrimryNd:
+ t = dcltor->tok;
+ if (t->tok_id == Identifier || t->tok_id == TypeDefName) {
+ /*
+ * We have found the identifier, add an entry to the
+ * symbol table based on information in the declaration
+ * context.
+ */
+ if (dcl_stk->kind_dcl == IsTypedef)
+ tok_id = TypeDefName;
+ else
+ tok_id = Identifier;
+ sym = sym_add(tok_id, t->image, OtherDcl, dcl_stk->nest_lvl);
+ if (sym == NULL)
+ errt2(t, "redefinition of ", t->image);
+ }
+ return;
+ default:
+ return;
+ }
+ }
+ }
+
+/*
+ * id_def - a declarator has been parsed. Determine what to do with it
+ * based on information put in the declaration context while parsing
+ * the "storage class type qualifier list".
+ */
+void id_def(dcltor, init)
+struct node *dcltor;
+struct node *init;
+ {
+ struct node *chld0, *chld1;
+ struct sym_entry *sym;
+
+ if (dcl_stk->parms_done)
+ pop_cntxt();
+
+ /*
+ * Look in the declaration context (the top of the declaration stack)
+ * to see if this is a tended declaration.
+ */
+ switch (dcl_stk->kind_dcl) {
+ case TndDesc:
+ case TndStr:
+ case TndBlk:
+ /*
+ * Tended variables are either simple identifiers or pointers to
+ * simple identifiers.
+ */
+ chld0 = dcltor->u[0].child;
+ chld1 = dcltor->u[1].child;
+ if (chld1->nd_id != PrimryNd || (chld1->tok->tok_id != Identifier &&
+ chld1->tok->tok_id != TypeDefName))
+ errt1(chld1->tok, "unsupported tended declaration");
+ if (dcl_stk->kind_dcl == TndDesc) {
+ /*
+ * Declared as full tended descriptor - must not be a pointer.
+ */
+ if (chld0 != NULL)
+ errt1(chld1->tok, "unsupported tended declaration");
+ }
+ else {
+ /*
+ * Must be a tended pointer.
+ */
+ if (chld0 == NULL || chld0->nd_id != PrimryNd)
+ errt1(chld1->tok, "unsupported tended declaration");
+ }
+
+ /*
+ * This is a legal tended declaration, make a symbol table entry
+ * for it and allocated a tended slot. Add the symbol table
+ * entry to the list of tended variables in this context.
+ */
+ sym = sym_add(Identifier, chld1->tok->image, dcl_stk->kind_dcl,
+ dcl_stk->nest_lvl);
+ if (sym == NULL)
+ errt2(chld1->tok, "redefinition of ", chld1->tok->image);
+ sym->u.tnd_var.blk_name = dcl_stk->blk_name;
+ sym->u.tnd_var.init = init;
+ sym->t_indx = alloc_tnd(dcl_stk->kind_dcl, init, dcl_stk->nest_lvl);
+ sym->u.tnd_var.next = dcl_stk->tended;
+ dcl_stk->tended = sym;
+ ++sym->ref_cnt;
+ return;
+ default:
+ add_def(dcltor); /* ordinary declaration */
+ }
+ }
+
+/*
+ * func_def - a function header has been parsed. Add the identifier for
+ * the function to the symbol table.
+ */
+void func_def(head)
+struct node *head;
+ {
+ /*
+ * If this is really a function header, the current declaration
+ * context indicates that a parameter list has been completed.
+ * Parameter lists at other than at nesting level 2 are part of
+ * nested declaration information and do not show up here. The
+ * function parameters must remain in the symbol table, so the
+ * context is just updated, not popped.
+ */
+ if (!dcl_stk->parms_done)
+ yyerror("invalid declaration");
+ dcl_stk->parms_done = 0;
+ if (dcl_stk->next->kind_dcl == IsTypedef)
+ yyerror("a typedef may not be a function definition");
+ add_def(head->u[1].child);
+ }
+
+/*
+ * s_prm_def - add symbol table entries for a parameter to an operation.
+ * Undereferenced and/or dereferenced versions of the parameter may be
+ * specified.
+ */
+void s_prm_def(u_ident, d_ident)
+struct token *u_ident;
+struct token *d_ident;
+ {
+ int param_num;
+
+ if (params == NULL)
+ param_num = 0;
+ else
+ param_num = params->u.param_info.param_num + 1;
+ if (u_ident != NULL)
+ add_s_prm(u_ident, param_num, RtParm);
+ if (d_ident != NULL)
+ add_s_prm(d_ident, param_num, DrfPrm);
+ }
+
+/*
+ * add_s_prm - add a symbol table entry for either a dereferenced or
+ * undereferenced version of a parameter. Put it on the current
+ * list of parameters.
+ */
+static void add_s_prm(ident, param_num, flags)
+struct token *ident;
+int param_num;
+int flags;
+ {
+ struct sym_entry *sym;
+
+ sym = sym_add(Identifier, ident->image, flags, dcl_stk->nest_lvl);
+ if (sym == NULL)
+ errt2(ident, "redefinition of ", ident->image);
+ sym->u.param_info.param_num = param_num;
+ sym->u.param_info.non_tend = 0;
+ sym->u.param_info.cur_loc = PrmTend;
+ sym->u.param_info.parm_mod = 0;
+ sym->u.param_info.next = params;
+ sym->il_indx = il_indx++;
+ params = sym;
+ ++sym->ref_cnt;
+ }
+
+/*
+ * var_args - a variable length parameter list for an operation is parsed.
+ */
+void var_args(ident)
+struct token *ident;
+ {
+ struct sym_entry *sym;
+
+ /*
+ * The last parameter processed represents the variable part of the list;
+ * update the symbol table entry. It may be dereferenced or undereferenced
+ * but not both.
+ */
+ sym = params->u.param_info.next;
+ if (sym != NULL && sym->u.param_info.param_num ==
+ params->u.param_info.param_num)
+ errt1(ident, "only one version of variable parameter list allowed");
+ params->id_type |= VarPrm;
+
+ /*
+ * Add the identifier for the length of the variable part of the list
+ * to the symbol table.
+ */
+ sym = sym_add(Identifier, ident->image, VArgLen, dcl_stk->nest_lvl);
+ if (sym == NULL)
+ errt2(ident, "redefinition of ", ident->image);
+ sym->il_indx = il_indx++;
+ v_len = sym;
+ ++v_len->ref_cnt;
+ }
+
+/*
+ * d_lst_typ - the end of a "declare {...}" is encountered. Go through a
+ * declaration list adding storage class, type qualifier, declarator
+ * and initializer information to the symbol table entry for each
+ * identifier. Add the entry onto the list associated with the "declare"
+ */
+void d_lst_typ(dcls)
+struct node *dcls;
+ {
+ if (dcls == NULL)
+ return;
+ for ( ; dcls != NULL && dcls->nd_id == LstNd; dcls = dcls->u[0].child)
+ dcl_typ(dcls->u[1].child);
+ dcl_typ(dcls);
+ }
+
+/*
+ * dcl_typ - go through the declarators of a declaration adding the storage
+ * class, type qualifier, declarator, and initializer information to the
+ * symbol table entry of each identifier. Add the entry onto the list
+ * associated with the current "declare {...}".
+ */
+static void dcl_typ(dcl)
+struct node *dcl;
+ {
+ struct node *tqual;
+ struct node *dcltors;
+
+ if (dcl == NULL)
+ return;
+ tqual = dcl->u[0].child;
+ for (dcltors = dcl->u[1].child; dcltors->nd_id == CommaNd;
+ dcltors = dcltors->u[0].child)
+ dcltor_typ(dcltors->u[1].child, tqual);
+ dcltor_typ(dcltors, tqual);
+ }
+
+/*
+ * dcltor_typ- find the identifier in the [initialized] declarator and add
+ * the storage class, type qualifer, declarator, and initialization
+ * information to its symbol table entry. Add the entry onto the list
+ * associated with the current "declare {...}".
+ */
+static void dcltor_typ(dcltor, tqual)
+struct node *dcltor;
+struct node *tqual;
+ {
+ struct sym_entry *sym;
+ struct node *part_dcltor;
+ struct node *init = NULL;
+ struct token *t;
+
+ if (dcltor->nd_id == BinryNd && dcltor->tok->tok_id == '=') {
+ init = dcltor->u[1].child;
+ dcltor = dcltor->u[0].child;
+ }
+ part_dcltor = dcltor;
+ for (;;) {
+ switch (part_dcltor->nd_id) {
+ case BinryNd:
+ /* ')' or '[' */
+ part_dcltor = part_dcltor->u[0].child;
+ break;
+ case ConCatNd:
+ /* pointer direct-declarator */
+ part_dcltor = part_dcltor->u[1].child;
+ break;
+ case PrefxNd:
+ /* ( ... ) */
+ part_dcltor = part_dcltor->u[0].child;
+ break;
+ case PrimryNd:
+ t = part_dcltor->tok;
+ if (t->tok_id == Identifier || t->tok_id == TypeDefName) {
+ /*
+ * The identifier has been found, update its symbol table
+ * entry.
+ */
+ sym = sym_lkup(t->image);
+ sym->u.declare_var.tqual = tqual;
+ sym->u.declare_var.dcltor = dcltor;
+ sym->u.declare_var.init = init;
+ ++sym->ref_cnt;
+ sym->u.declare_var.next = decl_lst;
+ decl_lst = sym;
+ }
+ return;
+ default:
+ return;
+ }
+ }
+ }
+
+/*
+ * tnd_char - indicate in the current declaration context that a tended
+ * character (pointer?) declaration has been found.
+ */
+void tnd_char()
+ {
+ dcl_stk->kind_dcl = TndStr;
+ dcl_stk->blk_name = NULL;
+ }
+
+/*
+ * tnd_strct - indicate in the current declaration context that a tended
+ * struct declaration has been found and indicate the struct type.
+ */
+void tnd_strct(t)
+struct token *t;
+ {
+ char *strct_nm;
+
+ strct_nm = t->image;
+ free_t(t);
+
+ if (strct_nm == descrip) {
+ dcl_stk->kind_dcl = TndDesc;
+ dcl_stk->blk_name = NULL;
+ return;
+ }
+ dcl_stk->kind_dcl = TndBlk;
+ dcl_stk->blk_name = strct_nm;
+ }
+
+/*
+ * tnd_strct - indicate in the current declaration context that a tended
+ * union (pointer?) declaration has been found.
+ */
+void tnd_union(t)
+struct token *t;
+ {
+ /*
+ * Only union block pointers may be tended.
+ */
+ if (t->image != block)
+ yyerror("unsupported tended type");
+ free_t(t);
+ dcl_stk->kind_dcl = TndBlk;
+ dcl_stk->blk_name = NULL;
+ }