parag@hpsdeb.sde.hp.com (Parag Patel) (05/19/91)
Submitted-by: Parag Patel <parag@hpsdeb.sde.hp.com> Posting-number: Volume 19, Issue 91 Archive-name: wacco/part04 ---- Cut Here and feed the following to sh ---- #!/bin/sh # This is part 04 of wacco # ============= wacco.w ============== if test -f 'wacco.w' -a X"$1" != X"-c"; then echo 'x - skipping wacco.w (File already exists)' else echo 'x - extracting wacco.w (Text)' sed 's/^X//' << 'SHAR_EOF' > 'wacco.w' && { // Copyright (c) 1991 by Parag Patel. All Rights Reserved. static const char rcs_id[] = "$Header: wacco.w,v 1.13 91/02/22 16:04:36 hmgr Exp $"; X #undef YYTEXT_DECL #define YYTEXT_DECL char yytext[] X #include "defs.h" X struct nodedat { X symbol *sym; X union X { X symnode *node; X char *alias; X }; X nodedat *prev; X nodedat() { sym = NULL; node = NULL; prev = NULL; } }; X } X program X : directives { $code = NULL; } code { startcode = $code; } statlist X ; X directives X : DIRECTIVE X { X int argc; X char **argv = strsep(yytext, " \t", TRUE, &argc); X getoptions(argc, argv); X } X | [] X ; X statlist X : statement { $code = NULL; } code { addnonterm($code); } statlist X | [] X ; X statement<symbol*> X : ID X { X $$ = addsymbol(yytext); X if ($$->type == TERMINAL) X (void)addnonterm($$); X if (startsymbol == NULL) X { X startsymbol = $$; X $$->usecount += 2; X } X } X idtype X { X if ($$->rettype != NULL && $idtype != NULL && X strcmp($$->rettype, $idtype) != 0) X scanerr("Two types defined for %s", $$->name); X X if ($$->rettype == NULL) X $$->rettype = $idtype; X else X delete $idtype; X } X (<boolean> EXPORT { $$ = TRUE; } | [] { $$ = FALSE; }) X { X if ($_) X { X exportedname = $$->export = TRUE; X $$->usecount += 2; X } X } X resyncset ':' X { X $$->list = $resyncset; X nodedat end; X end.sym = $concatlist.sym = $orlist.sym = $$; X $concatlist.prev = $orlist.prev = &end; X } X concatlist X { X symnode *node = $$->node; X if (node != NULL) X { X while (node->or != NULL) X node = node->or; X node->or = $concatlist.node; X } X else X node = $$->node = $concatlist.node; X } X orlist X { X if (node == NULL) X $$->node = $orlist.node; X else if (node->or == NULL) X node->or = $orlist.node; X else X node->or->or = $orlist.node; X } X ';' X ; X idtype<char*> X : '<' { $$ = readtype(); } X | [] { $$ = NULL; } X ; X concatlist<nodedat> X : { X $code = $exprlist.sym = $$.sym; X $exprlist.prev = $$.prev; X } X code exprlist X { X if ($code == NULL) X $$.node = $exprlist.node; X else X { X $$.node = new symnode; X $$.node->sym = $code; X $$.node->next = $exprlist.node; X } X } X | [] X ; X orlist<nodedat> X : { X $concatlist.sym = $orlist.sym = $$.sym; X $concatlist.prev = $orlist.prev = $$.prev; X } X '|' concatlist orlist X { X $$.node = $concatlist.node; X if ($$.node == NULL) X $$.node = $orlist.node; X else X $$.node->or = $orlist.node; X } X | [] X ; X X exprlist<nodedat> X : { X $expression.sym = $code = $exprlist.sym = $$.sym; X $expression.prev = $exprlist.prev = $$.prev; X } X expression resyncset code exprlist X { X $$.node = new symnode; X $$.node->sym = $expression.sym; X $$.node->alias = $expression.alias; X $$.node->next = $exprlist.node; X $$.node->list = $resyncset; X if ($code != NULL) X { X $$.node->next = new symnode; X $$.node->next->sym = $code; X $$.node->next->next = $exprlist.node; X } X } X | [] X ; X resyncset<resynclist*> X : '[' resynclist ']' { $$ = $resynclist; } X | [] { $$ = NULL; } X ; X resynclist<resynclist*> X : resyncitem (',' resynclist { $$=$resynclist; } | [] { $$ = NULL; }) X { X $$ = $resyncitem; X $$->next = $_; X } X ; X resyncitem<resynclist*> X : settype=first resyncid settype=follow X { X $$ = $resyncid; X $$->first = $first == 0 && $follow == 0 ? 1 : $first; X $$->follow = $follow; X } X ; X settype X : '+' { $$ = 1; } X | '-' { $$ = -1; } X | [] { $$ = 0; } X ; X resyncid<resynclist*> X : ID { $$ = new resynclist(yytext); } X | NULLSYM { $$ = new resynclist(NULL); } X | STRING { $$ = new resynclist(yytext); } X | CHARACTER { $$ = new resynclist(yytext); } X | '#' count { $$ = new resynclist(NULL); X $$->paren = $count == 0 ? 1 : $count; } X ; X count X : INT { $$ = atoi(yytext); } X | '*' { $$ = -1; } X | [] { $$ = 0; } X ; X alias<char*> X : '=' (ID { $$ = yytext; } | INT { $$ = yytext; }) X { $$ = strdup($_); } X | [] { $$ = NULL; } X ; X expression<nodedat> X : ID { $$.sym = addsymbol(yytext); $$.sym->usecount++; } X alias { $$.alias = $alias; } X | NULLSYM { $$.sym = getsymbol(EMPTY); } X | '#' count alias X { X nodedat *p = $$.prev; X for (int i = 0; p != NULL && ($count < 0 || i < $count); i++) X { X $$.sym = p->sym; X p = p->prev; X } X if ($count > 0 && i < $count) X scanerr("not that many parentheses"); X $$.sym->usecount++; X $$.alias = $alias; X } X | STRING X { X $$.sym = addsymbol(yytext); X $$.sym->lexstr = $$.sym->name; X gotlexstr = TRUE; X } X | CHARACTER X { X $$.sym = addsymbol(yytext); X if ($$.sym->lexstr == NULL) X { X char *s = strdup(yytext); X s[0] = s[strlen(s) - 1] = '"'; X $$.sym->lexstr = s; X } X } X | '(' idtype X { X char *type = $$.sym->rettype; X char *name = $$.sym->realname; X static int num = 1; X X addnonterm($$.sym = addsymbol(strbldf("_P%d", num++))); X $$.sym->type = NONTERMINAL; X $$.sym->rettype = $idtype == NULL ? type : $idtype; X $$.sym->realname = name; X $$.sym->usecount++; X X $concatlist.sym = $orlist.sym = $$.sym; X $concatlist.prev = $orlist.prev = &$$; X } X concatlist orlist ')' alias X { X $$.sym->node = $concatlist.node; X if ($$.sym->node == NULL) X $$.sym->node = $orlist.node; X else X $$.sym->node->or = $orlist.node; X $$.alias = $alias; X } X ; X code<symbol*> X : { X int rettype = 0; X int line = currline(); X } X (<char*> X '{' { $$ = readcode(rettype); } X | BLOCKCODE { $$ = readblockcode(rettype); } X ) X { X if ($$ != NULL) X $$->usedret = rettype; X X $$ = new symbol; X $$->name = "<code>"; X $$->type = CODE; X $$->code = $_; X $$->line = line; X } X | [] { $$ = NULL; } X ; SHAR_EOF chmod 0444 wacco.w || echo 'restore of wacco.w failed' Wc_c="`wc -c < 'wacco.w'`" test 5585 -eq "$Wc_c" || echo 'wacco.w: original size 5585, current size' "$Wc_c" fi # ============= defs.h ============== if test -f 'defs.h' -a X"$1" != X"-c"; then echo 'x - skipping defs.h (File already exists)' else echo 'x - extracting defs.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'defs.h' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. // $Header: defs.h,v 1.15 91/05/17 16:29:55 hmgr Exp $ X #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <malloc.h> X #include "boolean.h" #include "darray.h" #include "table.h" #include "bitset.h" X inline char *strdup(const char *s) X { return s == NULL ? NULL : strcpy((char*)malloc(strlen(s) + 1), s); } inline char *strnew(size_t len) { return (char*)malloc(len + 1); } #if FREE_TAKES_CHAR inline void strfree(const char *s) { if (s != NULL) free((char *)s); } #else inline void strfree(const char *s) { if (s != NULL) free((const void *)s); } #endif X // for large switch statements #define Case break;case #define Default break;default X X const TERMINAL = 1; const NONTERMINAL = 2; const CODE = 3; X const END = 0; const EMPTY = 1; const START = 2; X X #define RET_NONE 0x00 #define RET_VALUE 0x01 #define RET_CODE 0x02 X X struct symbol; struct symnode; struct resynclist; X struct Set { X Bitset *set; X int id; X X Set(Bitset *s = NULL) { set = s; } X operator Bitset*() { return set; } X boolean operator==(Bitset *b) { return *set == *b; }; }; X struct symbol { X char *name; X int id; X int parserid; X int type; X X char *rettype; X union X { X char *lexstr; X char *realname; X }; X char *code; X X union X { X int usedret; X boolean lexdef; X int line; X }; X X int usecount; X char toempty; X char export; X char mkstruct; X X Bitset *first; X Bitset *follow; X union X { X Set *resync; X resynclist *list; X }; X X symnode *node; X X symbol(const char *n = NULL); X operator char *() { return name; } X boolean operator==(const char *k) { return strcmp(name, k) == 0; } }; X struct symnode { X symbol *sym; X char *alias; X symnode *next; X symnode *or; X union X { X Set *resync; X resynclist *list; X }; X X symnode(); }; X struct resynclist { X char *name; X char first; X char follow; X char paren; X resynclist *next; X X resynclist(char *); X ~resynclist() { delete name; } }; X X declare_table(Settab, Setiter, Set, Bitset*); extern Settab settab; X extern boolean optimize; extern boolean dumpcode; extern boolean statonly; extern boolean docompare; extern boolean casesensitive; extern boolean dargstyle; extern boolean genlineinfo; extern char *headername; extern char *scannername; extern char *parsername; extern void getoptions(int argc, char *argv[]); extern FILE *makefile(char *fname); extern void cmpandmv(char *file); extern boolean exportedname; X extern int numsymbols(void); extern symbol *getsymbol(int); extern int numterms(void); extern int numnonterms(void); extern symbol *getterm(int); extern symbol *getnonterm(int); extern symbol *addsymbol(const char *); extern void addterm(symbol *); extern void addnonterm(symbol *); extern symbol *findsymbol(const char *); extern void initsym(void); extern symbol *startsymbol; extern symbol *startcode; X extern "C" { X extern int w_input(void); X extern int w_unput(int chr); } X extern boolean gotlexstr; extern void readccomment(void); extern char *readtype(void); extern char *readcode(int &); extern char *readblockcode(int &); extern char *getword(void); X extern void buildsets(void); extern void check(void); extern void gencode(char *infile); X extern void quit(char *fmt, ...); extern int error(char *fmt, ...); X extern char **strsep(const char *str, const char *sep, X boolean whsp = TRUE, int *num = NULL); extern const char *strbldf(const char *fmt, ...); X declare_array(charbuf, char); declare_array(charvec, char*); SHAR_EOF chmod 0444 defs.h || echo 'restore of defs.h failed' Wc_c="`wc -c < 'defs.h'`" test 3575 -eq "$Wc_c" || echo 'defs.h: original size 3575, current size' "$Wc_c" fi # ============= toks.h ============== if test -f 'toks.h' -a X"$1" != X"-c"; then echo 'x - skipping toks.h (File already exists)' else echo 'x - extracting toks.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'toks.h' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. // $Header: toks.h,v 1.9 91/02/22 16:04:47 hmgr Exp $ X #ifndef _T_O_K_E_N_S_ #define _T_O_K_E_N_S_ X #ifndef NULL #include <stdio.h> #endif X #define RETOK 1 #define RETERR 0 X enum tokenids { X EOI = 0, X _EMPTY = 256, /* nothing uses this yet */ X DIRECTIVE = 257, X ID, X EXPORT, X NULLSYM, X STRING, X CHARACTER, X INT, X BLOCKCODE, }; X #ifdef __cplusplus extern "C" { extern int yylex(); extern int yylook(); extern int w_input(); extern int w_unput(int); extern void w_output(int); } #else extern int yylex(); extern int yylook(); extern int w_input(); extern int w_unput(); extern void w_output(); #endif X extern int w_numerrors; #ifdef __cplusplus extern "C" { extern int w_scanerr(const char *, ...); extern void w_flusherrs(); extern void w_closefile(); extern int w_openfile(char *); extern FILE *w_getfile(); extern void w_setfile(FILE *); extern int w_currcol(); extern int w_currline(); extern char *w_getcurrline(); extern int w_gettoken(); extern int w_nexttoken(); extern void w_skiptoken(); extern char *w_tokenname(int); } #else extern int w_scanerr(); extern void w_flusherrs(); extern void w_closefile(); extern int w_openfile(); extern FILE *w_getfile(); extern void w_setfile(); extern int w_currcol(); extern int w_currline(); extern char *w_getcurrline(); extern int w_gettoken(); extern int w_nexttoken(); extern void w_skiptoken(); extern char *w_tokenname(); #endif X #ifdef __cplusplus extern "C" { int program(); } #else extern int program(); #endif X X #endif /* _T_O_K_E_N_S_ */ SHAR_EOF chmod 0444 toks.h || echo 'restore of toks.h failed' Wc_c="`wc -c < 'toks.h'`" test 1555 -eq "$Wc_c" || echo 'toks.h: original size 1555, current size' "$Wc_c" fi # ============= boolean.h ============== if test -f 'boolean.h' -a X"$1" != X"-c"; then echo 'x - skipping boolean.h (File already exists)' else echo 'x - extracting boolean.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'boolean.h' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. // $Header: boolean.h,v 1.3 91/02/22 16:04:53 hmgr Exp $ X typedef int boolean; const boolean FALSE = 0; const boolean TRUE = 1; SHAR_EOF chmod 0444 boolean.h || echo 'restore of boolean.h failed' Wc_c="`wc -c < 'boolean.h'`" test 188 -eq "$Wc_c" || echo 'boolean.h: original size 188, current size' "$Wc_c" fi # ============= bitset.h ============== if test -f 'bitset.h' -a X"$1" != X"-c"; then echo 'x - skipping bitset.h (File already exists)' else echo 'x - extracting bitset.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'bitset.h' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. // $Header: bitset.h,v 1.3 91/02/22 16:04:57 hmgr Exp $ X #define __B_S_BIT(n) ((long)(1L << (n & 0x1F))) #define __B_S_ELT(n) (n >> 5) X // a set of ints (esp. enums) - also an array of bits class Bitset { X int num; X long *elts; X X friend class Bitsetiter; X X void bumpsize(int); // grow the Bitset X // inline for speed X void BUMPSIZE(int largest) { if (num < largest) bumpsize(largest); } X public: X Bitset(int, int,...); // new element list X Bitset(int); // new size X Bitset(Bitset const &); // new Bitset X Bitset() { elts = new long; num = 0; elts[0] = 0L; } X ~Bitset() { delete elts; } // destructor X X Bitset& operator=(Bitset const &); // dup X X Bitset& add(int); // add to X Bitset& remove(int); // delete from X Bitset& operator+=(int e) { return add(e); } X Bitset& operator-=(int e) { return remove(e); } X X int size() const; // number of elements in Bitset X int card() const { return size(); } // for clarity? X boolean isin(int bit) const X { return bit >= 0 && bit <= num && X (elts[__B_S_ELT(bit)] & __B_S_BIT(bit)); } X void clear(); // clear the set X unsigned long hash() const; // return a hash number for this set X X Bitset& operator|=(Bitset const &); // union with X Bitset& operator&=(Bitset const &); // intersect with X Bitset& operator-=(Bitset const &); // difference from X Bitset& operator^=(Bitset const &); // symmetric difference from X Bitset& operator~(); // complement self X X int get(int elt) const X { return (elt >= 0 && elt <= num && X (elts[__B_S_ELT(elt)] & __B_S_BIT(elt))) ? 1 : 0; } X int operator[](int elt) const { return get(elt); } X X // equality testing: X boolean operator==(Bitset const &s) const; X boolean operator!=(Bitset const &s) const { return !(s == *this); } X // subset and superset: X boolean operator<=(Bitset const &s) const; X boolean operator>=(Bitset const &s) const { return s <= *this; } X // proper subset and proper superset: X boolean operator<(Bitset const &s) const X { return *this != s && *this <= s; } X boolean operator>(Bitset const &s) const { return s < *this; } }; X // iterator over a Bitset class Bitsetiter { X int elt, len; X int *arr; X public: X Bitsetiter(Bitset const &); // creator - iterate over a set X ~Bitsetiter() { delete arr; } X // get next element in set X int operator()() { return elt >= len ? elt = 0, -1 : arr[elt++]; } }; X #undef __B_S_ELT #undef __B_S_BIT SHAR_EOF chmod 0444 bitset.h || echo 'restore of bitset.h failed' Wc_c="`wc -c < 'bitset.h'`" test 2537 -eq "$Wc_c" || echo 'bitset.h: original size 2537, current size' "$Wc_c" fi # ============= darray.h ============== if test -f 'darray.h' -a X"$1" != X"-c"; then echo 'x - skipping darray.h (File already exists)' else echo 'x - extracting darray.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'darray.h' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. // $Header: darray.h,v 1.3 91/02/22 16:05:04 hmgr Exp $ X // Handle simple dynamic arrays of arbitrary type and range. // They are automatically grown to fit any array-like reference. // by Parag Patel X X // this is used to create an ARRAY of a TYPE #define declare_array(ARRAY, TYPE) \ class ARRAY \ { \ X long len; \ X long max; \ X TYPE *arr; \ X TYPE &bumpsize(long); \ public: \ X ARRAY() { arr = 0; max = len = 0; } \ X ARRAY(long siz) \ X { arr = 0; max = len = 0; if (siz > 0) bumpsize(siz-1); } \ X ARRAY(const ARRAY &); \ X ~ARRAY() { delete[max] arr; } \ X ARRAY &operator=(const ARRAY &); \ X long size() const { return len; } \ X void reset(long l = 0) { bumpsize(l); len = l; } \ X TYPE &operator[](long e) \ X { if (e < len) return arr[e]; else return bumpsize(e); } \ X TYPE *getarr() { return arr; } \ }; X X // this implements an ARRAY of a TYPE #define implement_array(ARRAY, TYPE) \ TYPE &ARRAY::bumpsize(long elt) \ { \ X if (elt < 0) \ X elt = 0; \ X if (elt >= max) \ X { \ X long omax = max; \ X if (max <= 0) \ X max = 1; \ X TYPE *narr = new TYPE[max = elt + (max > 1024 ? 1024 : max)]; \ X for (long i = 0; i < len; i++) \ X narr[i] = arr[i]; \ X delete[omax] arr; \ X arr = narr; \ X } \ X if (elt >= len) \ X len = elt + 1; \ X return arr[elt]; \ } \ ARRAY &ARRAY::operator=(const ARRAY &a) \ { \ X if (&a == this) \ X return *this; \ X if (a.len > len) \ X bumpsize(a.len); \ X len = a.len; \ X for (long i = 0; i < len; i++) \ X arr[i] = a.arr[i]; \ X return *this; \ } \ ARRAY::ARRAY(const ARRAY &t) \ { \ X arr = 0; \ X max = len = 0; \ X *this = t; \ } SHAR_EOF chmod 0444 darray.h || echo 'restore of darray.h failed' Wc_c="`wc -c < 'darray.h'`" test 1624 -eq "$Wc_c" || echo 'darray.h: original size 1624, current size' "$Wc_c" fi # ============= table.h ============== if test -f 'table.h' -a X"$1" != X"-c"; then echo 'x - skipping table.h (File already exists)' else echo 'x - extracting table.h (Text)' sed 's/^X//' << 'SHAR_EOF' > 'table.h' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. // $Header: table.h,v 1.5 91/05/17 16:30:00 hmgr Exp $ X #ifndef GENERICH #include <generic.h> #endif X #include <stddef.h> X #define table_node(table) name2(table,node) #define table_key(table) name2(table,key) X typedef unsigned TABLE_BUMP(unsigned); extern unsigned table_bump(unsigned); X X #define declare_table(table,iterator,symbol,key) \ typedef key table_key(table); \ struct table_node(table) \ { \ X table_node(table) *next; \ X symbol sym; \ X table_node(table)(key k, table_node(table) *tail) \ X : sym(k) { next = tail; } \ X table_node(table)(symbol &s, table_node(table) *tail) \ X : sym(s) { next = tail; } \ }; \ class table \ { \ X unsigned hash_size; \ X unsigned threshold; \ X unsigned numnode; \ X table_node(table) **vec; \ X table_node(table) *curr; \ X friend class iterator; \ X unsigned (*bump)(unsigned); \ X void resize(unsigned =0); \ X void delnode(table_node(table) **); \ X boolean insertsym(symbol&); \ public: \ X table(unsigned hs =0, TABLE_BUMP *bump_function =NULL); \ X table(table&); \ X ~table(); \ X boolean find(key); \ X boolean insert(key); \ X boolean remove(key); \ X boolean operator+=(key k) { return insert(k); } \ X boolean operator-=(key k) { return remove(k); } \ X boolean operator==(key k) { return find(k); } \ X boolean operator!=(key k) { return !find(k); } \ X symbol &operator[](key); \ X symbol &get(); \ X symbol &operator()(); \ X symbol &operator*(); \ X symbol *operator->(); \ X table& clear(); \ X table& operator=(table&); \ X boolean operator==(table&); \ X table& operator+=(table&); \ X table& operator-=(table&); \ X table& operator&=(table&); \ X unsigned size(); \ }; \ class iterator \ { \ X table *parent; \ X table_node(table) *curr; \ X unsigned index; \ X void transfer(table *); \ X friend class table; \ public: \ X iterator(); \ X iterator(table &); \ X ~iterator(); \ X table &operator=(table &); \ X boolean operator==(iterator &); \ X boolean operator!=(iterator &); \ X operator boolean(); \ X symbol &get(); \ X symbol &operator()(); \ X symbol &operator*(); \ X symbol *operator->(); \ X symbol &operator++(); \ X void remove(); \ }; \ inline symbol &table::operator[](key k) \ { \ X void(insert(k)); \ X return curr->sym; \ } \ inline symbol &table::get() \ { \ X if (curr != NULL) \ X return curr->sym; \ X else \ X return *(symbol *)NULL; \ } \ inline symbol &table::operator()() { return get(); } \ inline symbol &table::operator*() { return get(); } \ inline symbol *table::operator->() { return &get(); } \ inline unsigned table::size() \ { \ X return numnode; \ } \ inline iterator::iterator() \ { \ X parent = NULL; \ X curr = NULL; \ } \ inline iterator::iterator(table &t) \ { \ X parent = NULL; \ X this->transfer(&t); \ } \ inline iterator::~iterator() \ { \ X this->transfer(NULL); \ } \ inline table &iterator::operator=(table &t) \ { \ X this->transfer(&t); \ X return t; \ } \ inline boolean iterator::operator==(iterator &i) \ { \ X return (curr == i.curr); \ } \ inline boolean iterator::operator!=(iterator &i) \ { \ X return (curr != i.curr); \ } \ inline iterator::operator boolean() \ { \ X return (curr != NULL); \ } \ inline symbol &iterator::get() \ { \ X if (curr != NULL) \ X return curr->sym; \ X else \ X return *(symbol *)NULL; \ } \ inline symbol &iterator::operator()() { return get(); } \ inline symbol &iterator::operator*() { return get(); } \ inline symbol *iterator::operator->() { return &get(); } \ X X X #define implement_table(table,iterator,symbol,key,hash_func) \ table::table(unsigned hs, TABLE_BUMP *bump_function) \ { \ X hash_size = 0; \ X numnode = 0; \ X vec = NULL; \ X curr = NULL; \ X bump = (bump_function == NULL) ? &table_bump : bump_function; \ X resize(hs); \ } \ table::table(table& h) \ { \ X hash_size = 0; \ X numnode = 0; \ X vec = NULL; \ X curr = NULL; \ X bump = h.bump; \ X resize(h.hash_size); \ X *this = h; \ } \ table::~table() \ { \ X clear(); \ X delete vec; \ } \ boolean table::find(key k) \ { \ X register table_node(table) *p = vec[hash_func(k) % hash_size]; \ X for (; p != NULL; p = p->next) \ X if (p->sym == k) \ X { \ X curr = p; \ X return TRUE; \ X } \ X curr = NULL; \ X return FALSE; \ } \ boolean table::insert(key k) \ { \ X if (numnode >= threshold) \ X resize(); \ X register table_node(table) **q = vec + hash_func(k) % hash_size; \ X register table_node(table) *p = *q; \ X for (; p != NULL; p = p->next) \ X if (p->sym == k) \ X { \ X curr = p; \ X return FALSE; \ X } \ X curr = *q = new table_node(table)(k, *q); \ X numnode++; \ X return TRUE; \ } \ boolean table::insertsym(symbol &s) \ { \ X if (numnode >= threshold) \ X resize(); \ X register table_node(table) **q = vec + \ X hash_func((table_key(table))s) % hash_size; \ X register table_node(table) *p = *q; \ X for (; p != NULL; p = p->next) \ X if (p->sym == (table_key(table))s) \ X { \ X curr = p; \ X return FALSE; \ X } \ X curr = *q = new table_node(table)(s, *q); \ X numnode++; \ X return TRUE; \ } \ boolean table::remove(key k) \ { \ X register table_node(table) **p = vec + hash_func(k) % hash_size; \ X curr = NULL; \ X for (; (*p) != NULL; p = &((**p).next)) \ X if ((**p).sym == k) \ X { \ X delnode(p); \ X return TRUE; \ X } \ X return FALSE; \ } \ void table::delnode(table_node(table) **p) \ { \ X table_node(table) *next = (**p).next; \ X delete *p; \ X *p = next; \ X --numnode; \ } \ void table::resize(unsigned hs) \ { \ X register table_node(table) **pos, **endpos; \ X table_node(table) *chain = NULL; \ X unsigned new_hash_size = (hs == 0) ? bump(hash_size) : hs; \ X if (new_hash_size == 0) \ X new_hash_size = 1; \ X if (new_hash_size <= hash_size) \ X return; \ X if (vec != NULL) \ X { \ X pos = vec; \ X endpos = pos + hash_size; \ X for (; pos < endpos; pos++) \ X { \ X table_node(table) *p = *pos; \ X if (p != NULL) \ X { \ X while (p->next != NULL) \ X p = p->next; \ X p->next = chain; \ X chain = *pos; \ X } \ X } \ X } \ X hash_size = new_hash_size; \ X threshold = hash_size + (hash_size >> 2); \ X delete vec; \ X pos = vec = new table_node(table) *[hash_size]; \ X endpos = pos + hash_size; \ X while (pos < endpos) \ X *(pos++) = NULL; \ X while (chain != NULL) \ X { \ X table_node(table) *entry = chain; \ X chain = entry->next; \ X pos = vec + \ X hash_func((table_key(table))entry->sym) \ X % hash_size; \ X entry->next = *pos; \ X *pos = entry; \ X } \ } \ table& table::clear() \ { \ X for (int i = 0; i < hash_size; i++) \ X { \ X table_node(table) *p = vec[i]; \ X while (p != NULL) \ X { \ X table_node(table) *next = p->next; \ X delete p; \ X p = next; \ X } \ X vec[i] = NULL; \ X } \ X numnode = 0; \ X curr = NULL; \ X return *this; \ } \ table& table::operator=(table& h) \ { \ X if (this == &h) \ X return *this; \ X clear(); \ X for (iterator i = h; i; i++) \ X insertsym(i()); \ X return *this; \ } \ boolean table::operator==(table& h) \ { \ X if (this == &h) \ X return TRUE; \ X if (size() != h.size()) \ X return FALSE; \ X for (iterator i = h; i; i++) \ X if (!find((table_key(table))i())) \ X return FALSE; \ X return TRUE; \ } \ table& table::operator+=(table& h) \ { \ X if (this == &h) \ X return *this; \ X for (iterator i = h; i; i++) \ X insert((table_key(table))i()); \ X return *this; \ } \ table& table::operator-=(table& h) \ { \ X if (this == &h) \ X return clear(); \ X for (iterator i = h; i; i++) \ X remove((table_key(table))i()); \ X return *this; \ } \ table& table::operator&=(table& h) \ { \ X if (this == &h) \ X return *this; \ X for (iterator i = *this; i; ) \ X if (h.find((table_key(table))i())) \ X i++; \ X else \ X i.remove(); \ X return *this; \ } \ symbol &iterator::operator++() \ { \ X if (curr != NULL) \ X { \ X table_node(table) *prev = curr; \ X for (curr = curr->next; \ X curr == NULL && ++index < parent->hash_size; \ X curr = parent->vec[index]) \ X ; \ X return prev->sym; \ X } \ X else \ X { \ X return *(symbol *)NULL; \ X } \ } \ void iterator::remove() \ { \ X if (curr != NULL) \ X { \ X register table_node(table) **p = parent->vec + index; \ X for (; (*p) != curr; p = &((**p).next)) \ X ; \ X parent->delnode(p); \ X } \ } \ void iterator::transfer(table *newparent) \ { \ X if ((parent = newparent) != NULL) \ X { \ X for (index = 0, curr = parent->vec[0]; \ X curr == NULL && ++index < parent->hash_size; \ X curr = parent->vec[index]) \ X ; \ X } \ X else \ X curr = NULL; \ } SHAR_EOF chmod 0444 table.h || echo 'restore of table.h failed' Wc_c="`wc -c < 'table.h'`" test 8290 -eq "$Wc_c" || echo 'table.h: original size 8290, current size' "$Wc_c" fi # ============= bitset.C ============== if test -f 'bitset.C' -a X"$1" != X"-c"; then echo 'x - skipping bitset.C (File already exists)' else echo 'x - extracting bitset.C (Text)' sed 's/^X//' << 'SHAR_EOF' > 'bitset.C' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. // $Header: bitset.C,v 1.3 91/02/22 16:05:27 hmgr Exp $ X // A set of ints (or an array of bits) is implemented by matching // each element in the set with its corresponding bit position in // a word of infinite size. The word is implemented as an array // of "long" that is grown in size as necessary. Thus this set of // ints is not limited in size, like most Pascal implementations. // // By Parag Patel X #include <stdio.h> #include <stdarg.h> #include "boolean.h" #include "bitset.h" X X // the following are machine-dependant - change them if necessary // sizeof long == 32 bits == 2**5 --> 5, therefore ... const int NUM = 32; const int SHIFT = 5; const int MASK = 0x1F; const long EMPTY = 0; X X // generic minimum function static inline int MIN(int i1, int i2) { X return i1 < i2 ? i1 : i2; } X // this determines which particular "long" in the array has this element static inline int ELT(int e) { X return e >> SHIFT; } X // this gets the bit position in a "long" for this set element static inline long BIT(int e) { X return ((long)(1L << (e & MASK))); } X // this adds an element to an array of longs static inline void ADD(long *elts, int e) { X elts[ELT(e)] |= BIT(e); } X X // return a new set of elts - clear it static long *newelts(int largest) { X register long *elts = new long[ELT(largest) + 1]; X X for (register int i = ELT(largest); i >= 0; i--) X elts[i] = EMPTY; X return elts; } X // bump the size of a set void Bitset::bumpsize(int largest) { X if (largest <= num) X return; X X // only re-allocate our array if we are out of ELTs X if (ELT(largest) != ELT(num)) X { X register long *ne = newelts(largest); X for (register int i = ELT(num); i >= 0; i--) X ne[i] = elts[i]; X delete elts; X elts = ne; X } X num = largest; } X // various constructors: X // construct a set from a list of elements Bitset::Bitset(int e1, int e2 ...) { X // if the first element is < 0, we ignore the rest X if (e1 < 0) X { X elts = new long; X num = 0; X elts[0] = 0L; X return; X } X X // the largest element in our list for determining the initial X // Bitset size X register int largest = e1 > e2 ? e1 : e2; X va_list ap; X register int t; X X // if we have more than 3 elements, we need to use varargs X if (e2 >= 0) X { X // find the largest element to be put in the set X va_start(ap, e2); X while ((t = va_arg(ap, int)) >= 0) X if (t > largest) X largest = t; X va_end(ap); X } X X // allocate the space for this set X elts = newelts(num = largest); X X // add all the elements to the set X ADD(elts, e1); X if (e2 >= 0) X { X ADD(elts, e2); X va_start(ap, e2); X while ((t = va_arg(ap, int)) >= 0) X ADD(elts, t); X va_end(ap); X } } X // make a new set of the specified size Bitset::Bitset(int size) { X if (size <= 1) X size = 1; X elts = newelts(num = size - 1); } X // dup a set Bitset::Bitset(const Bitset &s) { X elts = newelts(num = s.num); X for (register int i = ELT(s.num); i >= 0; i--) X elts[i] = s.elts[i]; } X // assign a set to a set - also a dup Bitset &Bitset::operator=(const Bitset &s) { X register int i, t; X X BUMPSIZE(s.num); X for (i = t = ELT(s.num); i >= 0; i--) X elts[i] = s.elts[i]; X for (i = ELT(num); i > t; i--) X elts[i] = EMPTY; X return *this; } X X // add an element to a set Bitset &Bitset::add(int elt) { X if (elt < 0) X return *this; X BUMPSIZE(elt); X elts[ELT(elt)] |= BIT(elt); X return *this; } X // delete an element from a set Bitset &Bitset::remove(int elt) { X if (elt < 0) X return *this; X elts[ELT(elt)] &= ~BIT(elt); X return *this; } X // union with set Bitset &Bitset::operator|=(const Bitset &s) { X BUMPSIZE(s.num); X for (register int i = ELT(s.num); i >= 0; i--) X elts[i] |= s.elts[i]; X return *this; } X // intersect with set Bitset &Bitset::operator&=(const Bitset &s) { X register int t = ELT(s.num); X X BUMPSIZE(s.num); X for (register int i = ELT(num); i >= 0; i--) X elts[i] &= i <= t ? s.elts[i] : EMPTY; X return *this; } X // difference from set Bitset &Bitset::operator-=(const Bitset &s) { X for (register int i = MIN(ELT(num), ELT(s.num)); i >= 0; i--) X elts[i] &= ~s.elts[i]; X return *this; } X // symmetric difference (xor) from set Bitset &Bitset::operator^=(const Bitset &s) { X BUMPSIZE(s.num); X for (register int i = ELT(s.num); i >= 0; i--) X elts[i] ^= s.elts[i]; X return *this; } X // complement set Bitset &Bitset::operator~() { X register int i = ELT(num); X X elts[i] = ((BIT(num) << 1) - 1) & ~elts[i]; X for (i--; i >= 0; i--) X elts[i] = ~elts[i]; X return *this; } X // is set a subset of s? boolean Bitset::operator<=(const Bitset &s) const { X register int i = MIN(num, s.num); X X for (i = ELT(i); i >= 0; i--) X if ((elts[i] & s.elts[i]) != elts[i]) X return FALSE; X if (num <= s.num) X return TRUE; X X register int t = ELT(s.num); X for (i = ELT(num); i > t; i--) X if (elts[i]) X return FALSE; X return TRUE; } X // is set same as s? boolean Bitset::operator==(const Bitset &s) const { X register int i = MIN(num, s.num); X X for (i = ELT(i); i >= 0; i--) X if (elts[i] != s.elts[i]) X return FALSE; X if (num == s.num) X return TRUE; X X register int t; X if (num < s.num) X { X for (t = ELT(num), i = ELT(s.num); i > t; i--) X if (s.elts[i]) X return FALSE; X } X else X { X for (t = ELT(s.num), i = ELT(num); i > t; i--) X if (elts[i]) X return FALSE; X } X return TRUE; } X X // return the number of elements in the set (cardinality) int Bitset::size() const { X register int n = 0; X X for (register int i = ELT(num); i >= 0; i--) X for (register long m = 1; m; m <<= 1) X if (elts[i] & m) X n++; X return n; } X // clear the set of all elements void Bitset::clear() { X for (register int i = ELT(num); i >= 0; i--) X elts[i] = EMPTY; } X // return a hash number for this set unsigned long Bitset::hash() const { X register int i = ELT(num); X X // skip over null elements in array to make X // hash value independent of size X while (i >= 0 && elts[i] == 0) X i--; X X // now we can hash safely... X register unsigned long h = 0; X for (; i >= 0; i--) X { X // "+" moves around the bits a lot better than "^" X h += elts[i]; X // rotate "h" left by 3 bits, just to mix things up X h = (h << 3) | (h >> (NUM - 3)); X } X X return h; } X X X // set iterator class: X // creator Bitsetiter::Bitsetiter(const Bitset &s) { X int i, e; X int num = 0; X X arr = new int[len = s.size()]; X int t = ELT(s.num); X for (e = 0, i = 0; i <= t; i++) X for (long m = 1; m; e++, m <<= 1) X if (s.elts[i] & m) X arr[num++] = e; X elt = 0; } SHAR_EOF chmod 0444 bitset.C || echo 'restore of bitset.C failed' Wc_c="`wc -c < 'bitset.C'`" test 6447 -eq "$Wc_c" || echo 'bitset.C: original size 6447, current size' "$Wc_c" fi # ============= tgram.w ============== if test -f 'tgram.w' -a X"$1" != X"-c"; then echo 'x - skipping tgram.w (File already exists)' else echo 'x - extracting tgram.w (Text)' sed 's/^X//' << 'SHAR_EOF' > 'tgram.w' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. // $Header: tgram.w,v 1.5 91/02/22 16:05:33 hmgr Exp $ X { #include <stdio.h> } X program X : "program" ID '(' idlist ')' semi X declarations subprogdecls compoundstat '.' X ; X semi X : ';'[semi+] X ; X idlist X : ID (',' ID | []) X ; X declarations X : "var" (decllist | semi) X | [] X ; X decllist X : idlist ':' type semi (decllist | []) X ; X type X : "integer" X | "array" '[' INT ".." INT ']' "of" "integer" X ; X subprogdecls X : subproghead declarations subprogdecls X compoundstat semi subprogdecls X | [] X ; X subproghead X : "function" ID arguments ':' "integer" semi X | "procedure" ID arguments semi X ; X arguments X : '(' paramlist ')' X | [] X ; X paramlist X : idlist ':' type (semi paramlist | []) X ; X compoundstat X : "begin" statlist "end"[+semi+] X ; X statlist X : statement semi statlist X | [] X ; X statement X : ID assignment X | compoundstat X | "if" expression "then" statement ("else" statement | []) X | "while" expression "do" statement X | "for" varref ":=" expression ("to" | "downto") X expression "do" statement X ; X assignment X : '[' expression ']' ":=" expression X | '(' exprlist ')' X | ":=" expression X | [] X ; X varref X : ID ('[' expression ']' | []) X ; X exprlist X : expression (',' exprlist | []) X ; X expression X : term (('+'|'-') expression | []) X ; X term X : expr (('*'|'/') term | []) X ; X expr X : ID ('(' exprlist ')' | '[' expression ']' [')'] | []) X | INT X | '(' expression ')' X | "not" expression X | ('+'|'-') expression X ; X { X int main() X { X w_setfile(stdin); X X if (!program()) X return 1; X X return 0; X } } X $$ X D [0-9] L [A-Za-z_$] X %% X $ID {L}({L}|{D})* $INT {D}+ X [ \t\v\n\f] ; . { w_scanerr("Illegal character %d (%c)", yytext[0], yytext[0]); } SHAR_EOF chmod 0444 tgram.w || echo 'restore of tgram.w failed' Wc_c="`wc -c < 'tgram.w'`" test 1739 -eq "$Wc_c" || echo 'tgram.w: original size 1739, current size' "$Wc_c" fi # ============= tgram.good ============== if test -f 'tgram.good' -a X"$1" != X"-c"; then echo 'x - skipping tgram.good (File already exists)' else echo 'x - extracting tgram.good (Text)' sed 's/^X//' << 'SHAR_EOF' > 'tgram.good' && program test(input); X var X x, a: integer; X ara: array [1..10] of integer; X procedure try(a:integer); X var u,v:integer; X begin X if not a then try:=u+3 else try:=a; X end; X begin X while a do X begin X x := a-1; X a:=5*a; X end; end. SHAR_EOF chmod 0444 tgram.good || echo 'restore of tgram.good failed' Wc_c="`wc -c < 'tgram.good'`" test 229 -eq "$Wc_c" || echo 'tgram.good: original size 229, current size' "$Wc_c" fi # ============= tgram.bad ============== if test -f 'tgram.bad' -a X"$1" != X"-c"; then echo 'x - skipping tgram.bad (File already exists)' else echo 'x - extracting tgram.bad (Text)' sed 's/^X//' << 'SHAR_EOF' > 'tgram.bad' && program test(input); X var X x a: integer; X ara: array [1...10] of integer; X procedure try(a:integer):result integer; X u,v:integer; X begin if not not a try:=u+ else try:=a; X end X end X begin X while not x a do X x = a-1; X a2:=5**a; X x:= ara[3]*(ara[x+x) X end end SHAR_EOF chmod 0444 tgram.bad || echo 'restore of tgram.bad failed' Wc_c="`wc -c < 'tgram.bad'`" test 261 -eq "$Wc_c" || echo 'tgram.bad: original size 261, current size' "$Wc_c" fi # ============= main.C ============== if test -f 'main.C' -a X"$1" != X"-c"; then echo 'x - skipping main.C (File already exists)' else echo 'x - extracting main.C (Text)' sed 's/^X//' << 'SHAR_EOF' > 'main.C' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. static const char rcs_id[] = "$Header: main.C,v 1.22 91/02/22 16:05:39 hmgr Exp $"; X #include "version.C" X #include "defs.h" #include "toks.h" #include <osfcn.h> #include <stdarg.h> X #ifdef BSD #include <sys/wait.h> #endif X // externs for getopt() extern char *optarg; extern int optind; X // These vars are modified from the command line boolean optimize = TRUE; boolean dumpcode = TRUE; boolean statonly = FALSE; boolean docompare = TRUE; boolean casesensitive = FALSE; boolean dargstyle = TRUE; boolean genlineinfo = TRUE; char *headername = "tokens.h"; char *scannername = "scanner.l"; char *parsername = "parser.C"; X // just other globals here boolean exportedname = FALSE; X implement_array(charbuf, char); implement_array(charvec, char*); X X static charbuf buf; static charvec vec; X #define issep(c) (strchr(sep, (c)) != NULL) #define notsep(c) (strchr(sep, (c)) == NULL) X char **strsep(const char *str, const char *sep, int whsp, int *retnum) { X buf.reset(strlen(str) + 1); X register char *s = buf.getarr(); X strcpy(s, str); X X register int num = 0; X while (*s != '\0') X { X if (whsp) // skip leading separators? X while (*s != '\0' && issep(*s)) X s++; X X vec[num++] = s; X X // find next separator X while (*s != '\0' && notsep(*s)) X s++; X if (*s != '\0') X *s++ = '\0'; X } X X vec[num] = NULL; X X if (retnum != NULL) X *retnum = num; X X return &vec[0]; } X const char * strbldf(const char *format, ...) { X static char buff[4][1024]; X static int curr = 0; X if (++curr > 3) X curr = 0; X X va_list ap; X va_start(ap, format); X vsprintf(buff[curr], (char*)format, ap); X va_end(ap); X return buff[curr]; } X X int error(char *fmt, ...) { X va_list ap; X X w_numerrors++; X va_start(ap, fmt); X vfprintf(stderr, fmt, ap); X fprintf(stderr, ".\n"); X va_end(ap); X return RETERR; } X void quit(char *fmt, ...) { X va_list ap; X X va_start(ap, fmt); X vfprintf(stderr, fmt, ap); X fprintf(stderr, "!\n"); X va_end(ap); X exit(1); } X X static unsigned prime[] = { X 11, X 23, X 47, X 97, X 197, X 397, X 797, X 1597, X 3203, X 6421, X 12853, X 25717, X 51437, X 102877, X 205759, X 411527, X 823117, X 1646237, X 3292489, X 6584983, X 13169977, X 26339969, X 52679969, X 105359939, X 210719881, X 421439783, X 842879579 }; const N = sizeof prime/sizeof *prime; X unsigned table_bump(unsigned hs) { X if (hs < prime[N - 2]) X for (int i = 0; i < N; i++) X if (prime[i] > 2 * hs) X return prime[i]; X X return prime[N - 1]; } X X static void dumpset(Bitset &set) { X Bitsetiter si(set); X symbol *s; X int id; X X printf("("); X while ((id = si()) >= 0) X { X if (id == END || id == EMPTY) X continue; X s = getsymbol(id); X printf(" %s", s->name); X } X if (set.isin(EMPTY)) X printf(" []"); X else if (set.isin(END)) X printf(" $"); X printf(" )\n"); } X static void dump(void) { X symbol *sym; X symnode *n1, *n2; X int i; X char *s; X X for (i = START; i < numsymbols(); i++) X { X sym = getsymbol(i); X if (sym->type == NONTERMINAL) X { X if (sym->lexstr == NULL) X printf("%s", sym->name); X else X printf("%s (%s)", sym->lexstr, sym->name); X if (sym->rettype != NULL) X printf("<%s>", sym->rettype); X printf(" use=%d usedret=%d", sym->usecount, sym->usedret); X if (sym->toempty) X printf(" ==> []"); X printf("\n"); X s = "\t:"; X for (n1 = sym->node; n1 != NULL; n1 = n1->or) X { X for (n2 = n1; n2 != NULL; n2 = n2->next) X { X if (n2->sym->type == CODE) X printf("%s {%s}\n", s, n2->sym->code); X else X { X printf("%s %s[%d] = ", s, n2->sym->name, X n2->resync->id); X dumpset(*n2->resync->set); X } X s = "\t "; X } X s = "\t|"; X } X printf("\t;\n"); X } X else if (sym->type == TERMINAL) X { X printf("[%s]", sym->name); X if (sym->lexstr != NULL) X printf(" == %s", sym->lexstr); X printf("\n"); X } X else X { X printf("%s == {%s}\n", sym->name, sym->code); X continue; X } X X printf("FIRST(%s) = ", sym->name); X dumpset(*sym->first); X X printf("FOLLOW(%s) = ", sym->name); X dumpset(*sym->follow); X X if (sym->resync != NULL) X { X printf("SKIP-SET(%s[%d]) = ", sym->name, sym->resync->id); X dumpset(*sym->resync->set); X } X X printf("\n"); X } } X X static char *tmpname = ".wacco.tmp"; X FILE *makefile(char *fname) { X if (docompare) X fname = tmpname; X FILE *fp = fopen(fname, "w"); X if (fp == NULL) X quit("Cannot open %s for writing!", fname); X return fp; } X void cmpandmv(char *file) { X if (!docompare) X return; X #ifdef BSD X int pid = fork(); #else X pid_t pid = fork(); #endif X if (pid == 0) X { X execlp("cmp", "cmp", "-s", file, tmpname, NULL); X exit(-1); X } X #ifdef BSD X union wait stat; X int w; #else X int stat; X pid_t w; #endif X do X w = wait(&stat); X while (w != pid && w >= 0); X #ifdef BSD X if (stat.w_termsig == 0 && stat.w_retcode == 0) X return; #else X if (stat == 0) X return; #endif X X unlink(file); X if (link(tmpname, file) < 0) X quit("Cannot link %s to %s", tmpname, file); X unlink(tmpname); } X X void getoptions(int argc, char *argv[]) { X int opt; X X while ((opt = getopt(argc, argv, "dciah:s:p:OCL")) != EOF) X switch (opt) X { X Case 'd': X statonly = TRUE; X X Case 'c': X docompare = FALSE; X X Case 'i': X casesensitive = TRUE; X X Case 'a': X dargstyle = FALSE; X X Case 'h': X headername = strdup(optarg); X X Case 's': X scannername = strdup(optarg); X X Case 'p': X parsername = strdup(optarg); X X Case 'O': X optimize = FALSE; X X Case 'C': X dumpcode = FALSE; X X Case 'L': X genlineinfo = FALSE; X X Default: X quit( "Usage: %s [-dlciOCL] [-h header] [-p parser] [-s scanner] [file]", argv[0]); X } } X X int main(int argc, char *argv[]) { X getoptions(argc, argv); X X initsym(); X X char *infile = NULL; X FILE *fp = stdin; X if (optind < argc) X { X fp = fopen(infile = argv[optind], "r"); X if (fp == NULL) X quit("Cannot open file %s for reading", argv[optind]); X } X w_setfile(fp); X X if (!program()) X return 1; X X if (startsymbol == NULL && !exportedname) X quit("No start symbol defined"); X X buildsets(); X check(); X X if (w_numerrors > 0) X quit("Not generating any w_output files"); X X if (statonly) X { X dump(); X return 0; X } X X gencode(infile); X if (docompare) X unlink(tmpname); X return 0; } SHAR_EOF chmod 0444 main.C || echo 'restore of main.C failed' Wc_c="`wc -c < 'main.C'`" test 6362 -eq "$Wc_c" || echo 'main.C: original size 6362, current size' "$Wc_c" fi # ============= sym.C ============== if test -f 'sym.C' -a X"$1" != X"-c"; then echo 'x - skipping sym.C (File already exists)' else echo 'x - extracting sym.C (Text)' sed 's/^X//' << 'SHAR_EOF' > 'sym.C' && // Copyright (c) 1991 by Parag Patel. All Rights Reserved. static const char rcs_id[] = "$Header: sym.C,v 1.14 91/02/22 16:06:42 hmgr Exp $"; X #include "defs.h" #ifdef BSD # define BITSPERBYTE 8 # define BITS(type) (BITSPERBYTE * (int)sizeof(type)) #else # include <values.h> #endif X inline static unsigned sethash(Bitset *key) { X return key->hash(); } X // This is from the "dragon" Compilers book. // It is much better than the above but somewhat slower. // static unsigned strhash(register const char *p) { X register unsigned h = 0; X register g; X while (*p != '\0') X { X h = (h << 4) + (unsigned)*p++; X if (g = h & (0xF << BITS(unsigned) - 4)) X { X h ^= g >> BITS(unsigned) - 4; X h ^= g; X } X } X return h; } X X typedef Bitset *Bitsetptr; implement_table(Settab, Setiter, Set, Bitsetptr, sethash); Settab settab; X X typedef const char *charptr; declare_table(symtab, symiter, symbol, charptr); implement_table(symtab, symiter, symbol, charptr, strhash); X typedef symbol *symptr; declare_array(symptrarr,symptr); implement_array(symptrarr, symptr); X symbol *startsymbol = NULL; symbol *startcode = NULL; X static symtab symlist; static symptrarr symids, nonterms, terms; X X symbol::symbol(const char *n) { X name = strdup(n); X type = TERMINAL; X X rettype = NULL; X lexstr = NULL; // realname X code = NULL; X X usedret = 0; // lexdef, line X X toempty = FALSE; X usecount = 0; X export = FALSE; X mkstruct = FALSE; X X first = new Bitset; X follow = new Bitset; X resync = NULL; // list X X node = NULL; } X X symnode::symnode() { X sym = NULL; X alias = NULL; X next = NULL; X or = NULL; X resync = NULL; // list } X resynclist::resynclist(char *n) { X if (n == NULL) X name = NULL; X else X name = strdup(n); X first = follow = 0; X paren = 0; X next = NULL; } X X int numsymbols() { X return symlist.size(); } X symbol * getsymbol(int id) { X if (id < 0 || id >= symids.size()) X return NULL; X return symids[id]; } X int numterms() { X return terms.size(); } X int numnonterms() { X return nonterms.size(); } X symbol * getterm(int id) { X if (id < 0 || id >= terms.size()) X return NULL; X return terms[id]; } X symbol * getnonterm(int id) { X if (id < 0 || id >= nonterms.size()) X return NULL; X return nonterms[id]; } X X symbol * addsymbol(const char *name) { X if (!symlist.insert(name)) X return &symlist(); X X symbol & s = symlist(); X static int idnum = 0; X s.id = idnum; X symids[idnum++] = &s; X s.first = new Bitset; X s.follow = new Bitset; X return &s; } X void addterm(symbol *s) { X if (s == NULL) X return; X X terms[s->parserid = (int)terms.size()] = s; } X void addnonterm(symbol *s) { X if (s == NULL) X return; X X nonterms[s->parserid = (int)nonterms.size()] = s; X s->parserid = -1 - s->parserid; X if (s->type == TERMINAL) X { X s->type = NONTERMINAL; X s->realname = s->name; X } } X symbol * findsymbol(const char *name) { X if (symlist.find(name)) X return &symlist(); X return NULL; } X void initsym() { X symbol *s; X X s = addsymbol("$ END"); // id == 0 == END X s = addsymbol("[]"); // id == 1 == EMPTY } SHAR_EOF chmod 0444 sym.C || echo 'restore of sym.C failed' Wc_c="`wc -c < 'sym.C'`" test 3130 -eq "$Wc_c" || echo 'sym.C: original size 3130, current size' "$Wc_c" fi true || echo 'restore of parse.C failed' echo End of part 4, continue with part 5 exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.