xref: /onnv-gate/usr/src/lib/libsqlite/tool/lemon.c (revision 4520:7dbeadedd7fe)
1*4520Snw141292 
2*4520Snw141292 #pragma ident	"%Z%%M%	%I%	%E% SMI"
3*4520Snw141292 
4*4520Snw141292 /*
5*4520Snw141292 ** This file contains all sources (including headers) to the LEMON
6*4520Snw141292 ** LALR(1) parser generator.  The sources have been combined into a
7*4520Snw141292 ** single file to make it easy to include LEMON in the source tree
8*4520Snw141292 ** and Makefile of another program.
9*4520Snw141292 **
10*4520Snw141292 ** The author of this program disclaims copyright.
11*4520Snw141292 */
12*4520Snw141292 #include <stdio.h>
13*4520Snw141292 #include <stdarg.h>
14*4520Snw141292 #include <string.h>
15*4520Snw141292 #include <ctype.h>
16*4520Snw141292 #include <stdlib.h>
17*4520Snw141292 
18*4520Snw141292 #ifndef __WIN32__
19*4520Snw141292 #   if defined(_WIN32) || defined(WIN32)
20*4520Snw141292 #	define __WIN32__
21*4520Snw141292 #   endif
22*4520Snw141292 #endif
23*4520Snw141292 
24*4520Snw141292 /* #define PRIVATE static */
25*4520Snw141292 #define PRIVATE
26*4520Snw141292 
27*4520Snw141292 #ifdef TEST
28*4520Snw141292 #define MAXRHS 5       /* Set low to exercise exception code */
29*4520Snw141292 #else
30*4520Snw141292 #define MAXRHS 1000
31*4520Snw141292 #endif
32*4520Snw141292 
33*4520Snw141292 char *msort();
34*4520Snw141292 extern void *malloc();
35*4520Snw141292 
36*4520Snw141292 /******** From the file "action.h" *************************************/
37*4520Snw141292 struct action *Action_new();
38*4520Snw141292 struct action *Action_sort();
39*4520Snw141292 
40*4520Snw141292 /********* From the file "assert.h" ************************************/
41*4520Snw141292 void myassert();
42*4520Snw141292 #ifndef NDEBUG
43*4520Snw141292 #  define assert(X) if(!(X))myassert(__FILE__,__LINE__)
44*4520Snw141292 #else
45*4520Snw141292 #  define assert(X)
46*4520Snw141292 #endif
47*4520Snw141292 
48*4520Snw141292 /********** From the file "build.h" ************************************/
49*4520Snw141292 void FindRulePrecedences();
50*4520Snw141292 void FindFirstSets();
51*4520Snw141292 void FindStates();
52*4520Snw141292 void FindLinks();
53*4520Snw141292 void FindFollowSets();
54*4520Snw141292 void FindActions();
55*4520Snw141292 
56*4520Snw141292 /********* From the file "configlist.h" *********************************/
57*4520Snw141292 void Configlist_init(/* void */);
58*4520Snw141292 struct config *Configlist_add(/* struct rule *, int */);
59*4520Snw141292 struct config *Configlist_addbasis(/* struct rule *, int */);
60*4520Snw141292 void Configlist_closure(/* void */);
61*4520Snw141292 void Configlist_sort(/* void */);
62*4520Snw141292 void Configlist_sortbasis(/* void */);
63*4520Snw141292 struct config *Configlist_return(/* void */);
64*4520Snw141292 struct config *Configlist_basis(/* void */);
65*4520Snw141292 void Configlist_eat(/* struct config * */);
66*4520Snw141292 void Configlist_reset(/* void */);
67*4520Snw141292 
68*4520Snw141292 /********* From the file "error.h" ***************************************/
69*4520Snw141292 void ErrorMsg(const char *, int,const char *, ...);
70*4520Snw141292 
71*4520Snw141292 /****** From the file "option.h" ******************************************/
72*4520Snw141292 struct s_options {
73*4520Snw141292   enum { OPT_FLAG=1,  OPT_INT,  OPT_DBL,  OPT_STR,
74*4520Snw141292          OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type;
75*4520Snw141292   char *label;
76*4520Snw141292   char *arg;
77*4520Snw141292   char *message;
78*4520Snw141292 };
79*4520Snw141292 int    OptInit(/* char**,struct s_options*,FILE* */);
80*4520Snw141292 int    OptNArgs(/* void */);
81*4520Snw141292 char  *OptArg(/* int */);
82*4520Snw141292 void   OptErr(/* int */);
83*4520Snw141292 void   OptPrint(/* void */);
84*4520Snw141292 
85*4520Snw141292 /******** From the file "parse.h" *****************************************/
86*4520Snw141292 void Parse(/* struct lemon *lemp */);
87*4520Snw141292 
88*4520Snw141292 /********* From the file "plink.h" ***************************************/
89*4520Snw141292 struct plink *Plink_new(/* void */);
90*4520Snw141292 void Plink_add(/* struct plink **, struct config * */);
91*4520Snw141292 void Plink_copy(/* struct plink **, struct plink * */);
92*4520Snw141292 void Plink_delete(/* struct plink * */);
93*4520Snw141292 
94*4520Snw141292 /********** From the file "report.h" *************************************/
95*4520Snw141292 void Reprint(/* struct lemon * */);
96*4520Snw141292 void ReportOutput(/* struct lemon * */);
97*4520Snw141292 void ReportTable(/* struct lemon * */);
98*4520Snw141292 void ReportHeader(/* struct lemon * */);
99*4520Snw141292 void CompressTables(/* struct lemon * */);
100*4520Snw141292 
101*4520Snw141292 /********** From the file "set.h" ****************************************/
102*4520Snw141292 void  SetSize(/* int N */);             /* All sets will be of size N */
103*4520Snw141292 char *SetNew(/* void */);               /* A new set for element 0..N */
104*4520Snw141292 void  SetFree(/* char* */);             /* Deallocate a set */
105*4520Snw141292 
106*4520Snw141292 int SetAdd(/* char*,int */);            /* Add element to a set */
107*4520Snw141292 int SetUnion(/* char *A,char *B */);    /* A <- A U B, thru element N */
108*4520Snw141292 
109*4520Snw141292 #define SetFind(X,Y) (X[Y])       /* True if Y is in set X */
110*4520Snw141292 
111*4520Snw141292 /********** From the file "struct.h" *************************************/
112*4520Snw141292 /*
113*4520Snw141292 ** Principal data structures for the LEMON parser generator.
114*4520Snw141292 */
115*4520Snw141292 
116*4520Snw141292 typedef enum {B_FALSE=0, B_TRUE} Boolean;
117*4520Snw141292 
118*4520Snw141292 /* Symbols (terminals and nonterminals) of the grammar are stored
119*4520Snw141292 ** in the following: */
120*4520Snw141292 struct symbol {
121*4520Snw141292   char *name;              /* Name of the symbol */
122*4520Snw141292   int index;               /* Index number for this symbol */
123*4520Snw141292   enum {
124*4520Snw141292     TERMINAL,
125*4520Snw141292     NONTERMINAL
126*4520Snw141292   } type;                  /* Symbols are all either TERMINALS or NTs */
127*4520Snw141292   struct rule *rule;       /* Linked list of rules of this (if an NT) */
128*4520Snw141292   struct symbol *fallback; /* fallback token in case this token doesn't parse */
129*4520Snw141292   int prec;                /* Precedence if defined (-1 otherwise) */
130*4520Snw141292   enum e_assoc {
131*4520Snw141292     LEFT,
132*4520Snw141292     RIGHT,
133*4520Snw141292     NONE,
134*4520Snw141292     UNK
135*4520Snw141292   } assoc;                 /* Associativity if predecence is defined */
136*4520Snw141292   char *firstset;          /* First-set for all rules of this symbol */
137*4520Snw141292   Boolean lambda;          /* True if NT and can generate an empty string */
138*4520Snw141292   char *destructor;        /* Code which executes whenever this symbol is
139*4520Snw141292                            ** popped from the stack during error processing */
140*4520Snw141292   int destructorln;        /* Line number of destructor code */
141*4520Snw141292   char *datatype;          /* The data type of information held by this
142*4520Snw141292                            ** object. Only used if type==NONTERMINAL */
143*4520Snw141292   int dtnum;               /* The data type number.  In the parser, the value
144*4520Snw141292                            ** stack is a union.  The .yy%d element of this
145*4520Snw141292                            ** union is the correct data type for this object */
146*4520Snw141292 };
147*4520Snw141292 
148*4520Snw141292 /* Each production rule in the grammar is stored in the following
149*4520Snw141292 ** structure.  */
150*4520Snw141292 struct rule {
151*4520Snw141292   struct symbol *lhs;      /* Left-hand side of the rule */
152*4520Snw141292   char *lhsalias;          /* Alias for the LHS (NULL if none) */
153*4520Snw141292   int ruleline;            /* Line number for the rule */
154*4520Snw141292   int nrhs;                /* Number of RHS symbols */
155*4520Snw141292   struct symbol **rhs;     /* The RHS symbols */
156*4520Snw141292   char **rhsalias;         /* An alias for each RHS symbol (NULL if none) */
157*4520Snw141292   int line;                /* Line number at which code begins */
158*4520Snw141292   char *code;              /* The code executed when this rule is reduced */
159*4520Snw141292   struct symbol *precsym;  /* Precedence symbol for this rule */
160*4520Snw141292   int index;               /* An index number for this rule */
161*4520Snw141292   Boolean canReduce;       /* True if this rule is ever reduced */
162*4520Snw141292   struct rule *nextlhs;    /* Next rule with the same LHS */
163*4520Snw141292   struct rule *next;       /* Next rule in the global list */
164*4520Snw141292 };
165*4520Snw141292 
166*4520Snw141292 /* A configuration is a production rule of the grammar together with
167*4520Snw141292 ** a mark (dot) showing how much of that rule has been processed so far.
168*4520Snw141292 ** Configurations also contain a follow-set which is a list of terminal
169*4520Snw141292 ** symbols which are allowed to immediately follow the end of the rule.
170*4520Snw141292 ** Every configuration is recorded as an instance of the following: */
171*4520Snw141292 struct config {
172*4520Snw141292   struct rule *rp;         /* The rule upon which the configuration is based */
173*4520Snw141292   int dot;                 /* The parse point */
174*4520Snw141292   char *fws;               /* Follow-set for this configuration only */
175*4520Snw141292   struct plink *fplp;      /* Follow-set forward propagation links */
176*4520Snw141292   struct plink *bplp;      /* Follow-set backwards propagation links */
177*4520Snw141292   struct state *stp;       /* Pointer to state which contains this */
178*4520Snw141292   enum {
179*4520Snw141292     COMPLETE,              /* The status is used during followset and */
180*4520Snw141292     INCOMPLETE             /*    shift computations */
181*4520Snw141292   } status;
182*4520Snw141292   struct config *next;     /* Next configuration in the state */
183*4520Snw141292   struct config *bp;       /* The next basis configuration */
184*4520Snw141292 };
185*4520Snw141292 
186*4520Snw141292 /* Every shift or reduce operation is stored as one of the following */
187*4520Snw141292 struct action {
188*4520Snw141292   struct symbol *sp;       /* The look-ahead symbol */
189*4520Snw141292   enum e_action {
190*4520Snw141292     SHIFT,
191*4520Snw141292     ACCEPT,
192*4520Snw141292     REDUCE,
193*4520Snw141292     ERROR,
194*4520Snw141292     CONFLICT,                /* Was a reduce, but part of a conflict */
195*4520Snw141292     SH_RESOLVED,             /* Was a shift.  Precedence resolved conflict */
196*4520Snw141292     RD_RESOLVED,             /* Was reduce.  Precedence resolved conflict */
197*4520Snw141292     NOT_USED                 /* Deleted by compression */
198*4520Snw141292   } type;
199*4520Snw141292   union {
200*4520Snw141292     struct state *stp;     /* The new state, if a shift */
201*4520Snw141292     struct rule *rp;       /* The rule, if a reduce */
202*4520Snw141292   } x;
203*4520Snw141292   struct action *next;     /* Next action for this state */
204*4520Snw141292   struct action *collide;  /* Next action with the same hash */
205*4520Snw141292 };
206*4520Snw141292 
207*4520Snw141292 /* Each state of the generated parser's finite state machine
208*4520Snw141292 ** is encoded as an instance of the following structure. */
209*4520Snw141292 struct state {
210*4520Snw141292   struct config *bp;       /* The basis configurations for this state */
211*4520Snw141292   struct config *cfp;      /* All configurations in this set */
212*4520Snw141292   int index;               /* Sequencial number for this state */
213*4520Snw141292   struct action *ap;       /* Array of actions for this state */
214*4520Snw141292   int nTknAct, nNtAct;     /* Number of actions on terminals and nonterminals */
215*4520Snw141292   int iTknOfst, iNtOfst;   /* yy_action[] offset for terminals and nonterms */
216*4520Snw141292   int iDflt;               /* Default action */
217*4520Snw141292 };
218*4520Snw141292 #define NO_OFFSET (-2147483647)
219*4520Snw141292 
220*4520Snw141292 /* A followset propagation link indicates that the contents of one
221*4520Snw141292 ** configuration followset should be propagated to another whenever
222*4520Snw141292 ** the first changes. */
223*4520Snw141292 struct plink {
224*4520Snw141292   struct config *cfp;      /* The configuration to which linked */
225*4520Snw141292   struct plink *next;      /* The next propagate link */
226*4520Snw141292 };
227*4520Snw141292 
228*4520Snw141292 /* The state vector for the entire parser generator is recorded as
229*4520Snw141292 ** follows.  (LEMON uses no global variables and makes little use of
230*4520Snw141292 ** static variables.  Fields in the following structure can be thought
231*4520Snw141292 ** of as begin global variables in the program.) */
232*4520Snw141292 struct lemon {
233*4520Snw141292   struct state **sorted;   /* Table of states sorted by state number */
234*4520Snw141292   struct rule *rule;       /* List of all rules */
235*4520Snw141292   int nstate;              /* Number of states */
236*4520Snw141292   int nrule;               /* Number of rules */
237*4520Snw141292   int nsymbol;             /* Number of terminal and nonterminal symbols */
238*4520Snw141292   int nterminal;           /* Number of terminal symbols */
239*4520Snw141292   struct symbol **symbols; /* Sorted array of pointers to symbols */
240*4520Snw141292   int errorcnt;            /* Number of errors */
241*4520Snw141292   struct symbol *errsym;   /* The error symbol */
242*4520Snw141292   char *name;              /* Name of the generated parser */
243*4520Snw141292   char *arg;               /* Declaration of the 3th argument to parser */
244*4520Snw141292   char *tokentype;         /* Type of terminal symbols in the parser stack */
245*4520Snw141292   char *vartype;           /* The default type of non-terminal symbols */
246*4520Snw141292   char *start;             /* Name of the start symbol for the grammar */
247*4520Snw141292   char *stacksize;         /* Size of the parser stack */
248*4520Snw141292   char *include;           /* Code to put at the start of the C file */
249*4520Snw141292   int  includeln;          /* Line number for start of include code */
250*4520Snw141292   char *error;             /* Code to execute when an error is seen */
251*4520Snw141292   int  errorln;            /* Line number for start of error code */
252*4520Snw141292   char *overflow;          /* Code to execute on a stack overflow */
253*4520Snw141292   int  overflowln;         /* Line number for start of overflow code */
254*4520Snw141292   char *failure;           /* Code to execute on parser failure */
255*4520Snw141292   int  failureln;          /* Line number for start of failure code */
256*4520Snw141292   char *accept;            /* Code to execute when the parser excepts */
257*4520Snw141292   int  acceptln;           /* Line number for the start of accept code */
258*4520Snw141292   char *extracode;         /* Code appended to the generated file */
259*4520Snw141292   int  extracodeln;        /* Line number for the start of the extra code */
260*4520Snw141292   char *tokendest;         /* Code to execute to destroy token data */
261*4520Snw141292   int  tokendestln;        /* Line number for token destroyer code */
262*4520Snw141292   char *vardest;           /* Code for the default non-terminal destructor */
263*4520Snw141292   int  vardestln;          /* Line number for default non-term destructor code*/
264*4520Snw141292   char *filename;          /* Name of the input file */
265*4520Snw141292   char *outname;           /* Name of the current output file */
266*4520Snw141292   char *tokenprefix;       /* A prefix added to token names in the .h file */
267*4520Snw141292   int nconflict;           /* Number of parsing conflicts */
268*4520Snw141292   int tablesize;           /* Size of the parse tables */
269*4520Snw141292   int basisflag;           /* Print only basis configurations */
270*4520Snw141292   int has_fallback;        /* True if any %fallback is seen in the grammer */
271*4520Snw141292   char *argv0;             /* Name of the program */
272*4520Snw141292 };
273*4520Snw141292 
274*4520Snw141292 #define MemoryCheck(X) if((X)==0){ \
275*4520Snw141292   extern void memory_error(); \
276*4520Snw141292   memory_error(); \
277*4520Snw141292 }
278*4520Snw141292 
279*4520Snw141292 /**************** From the file "table.h" *********************************/
280*4520Snw141292 /*
281*4520Snw141292 ** All code in this file has been automatically generated
282*4520Snw141292 ** from a specification in the file
283*4520Snw141292 **              "table.q"
284*4520Snw141292 ** by the associative array code building program "aagen".
285*4520Snw141292 ** Do not edit this file!  Instead, edit the specification
286*4520Snw141292 ** file, then rerun aagen.
287*4520Snw141292 */
288*4520Snw141292 /*
289*4520Snw141292 ** Code for processing tables in the LEMON parser generator.
290*4520Snw141292 */
291*4520Snw141292 
292*4520Snw141292 /* Routines for handling a strings */
293*4520Snw141292 
294*4520Snw141292 char *Strsafe();
295*4520Snw141292 
296*4520Snw141292 void Strsafe_init(/* void */);
297*4520Snw141292 int Strsafe_insert(/* char * */);
298*4520Snw141292 char *Strsafe_find(/* char * */);
299*4520Snw141292 
300*4520Snw141292 /* Routines for handling symbols of the grammar */
301*4520Snw141292 
302*4520Snw141292 struct symbol *Symbol_new();
303*4520Snw141292 int Symbolcmpp(/* struct symbol **, struct symbol ** */);
304*4520Snw141292 void Symbol_init(/* void */);
305*4520Snw141292 int Symbol_insert(/* struct symbol *, char * */);
306*4520Snw141292 struct symbol *Symbol_find(/* char * */);
307*4520Snw141292 struct symbol *Symbol_Nth(/* int */);
308*4520Snw141292 int Symbol_count(/*  */);
309*4520Snw141292 struct symbol **Symbol_arrayof(/*  */);
310*4520Snw141292 
311*4520Snw141292 /* Routines to manage the state table */
312*4520Snw141292 
313*4520Snw141292 int Configcmp(/* struct config *, struct config * */);
314*4520Snw141292 struct state *State_new();
315*4520Snw141292 void State_init(/* void */);
316*4520Snw141292 int State_insert(/* struct state *, struct config * */);
317*4520Snw141292 struct state *State_find(/* struct config * */);
318*4520Snw141292 struct state **State_arrayof(/*  */);
319*4520Snw141292 
320*4520Snw141292 /* Routines used for efficiency in Configlist_add */
321*4520Snw141292 
322*4520Snw141292 void Configtable_init(/* void */);
323*4520Snw141292 int Configtable_insert(/* struct config * */);
324*4520Snw141292 struct config *Configtable_find(/* struct config * */);
325*4520Snw141292 void Configtable_clear(/* int(*)(struct config *) */);
326*4520Snw141292 /****************** From the file "action.c" *******************************/
327*4520Snw141292 /*
328*4520Snw141292 ** Routines processing parser actions in the LEMON parser generator.
329*4520Snw141292 */
330*4520Snw141292 
331*4520Snw141292 /* Allocate a new parser action */
Action_new()332*4520Snw141292 struct action *Action_new(){
333*4520Snw141292   static struct action *freelist = 0;
334*4520Snw141292   struct action *new;
335*4520Snw141292 
336*4520Snw141292   if( freelist==0 ){
337*4520Snw141292     int i;
338*4520Snw141292     int amt = 100;
339*4520Snw141292     freelist = (struct action *)malloc( sizeof(struct action)*amt );
340*4520Snw141292     if( freelist==0 ){
341*4520Snw141292       fprintf(stderr,"Unable to allocate memory for a new parser action.");
342*4520Snw141292       exit(1);
343*4520Snw141292     }
344*4520Snw141292     for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
345*4520Snw141292     freelist[amt-1].next = 0;
346*4520Snw141292   }
347*4520Snw141292   new = freelist;
348*4520Snw141292   freelist = freelist->next;
349*4520Snw141292   return new;
350*4520Snw141292 }
351*4520Snw141292 
352*4520Snw141292 /* Compare two actions */
actioncmp(ap1,ap2)353*4520Snw141292 static int actioncmp(ap1,ap2)
354*4520Snw141292 struct action *ap1;
355*4520Snw141292 struct action *ap2;
356*4520Snw141292 {
357*4520Snw141292   int rc;
358*4520Snw141292   rc = ap1->sp->index - ap2->sp->index;
359*4520Snw141292   if( rc==0 ) rc = (int)ap1->type - (int)ap2->type;
360*4520Snw141292   if( rc==0 ){
361*4520Snw141292     assert( ap1->type==REDUCE || ap1->type==RD_RESOLVED || ap1->type==CONFLICT);
362*4520Snw141292     assert( ap2->type==REDUCE || ap2->type==RD_RESOLVED || ap2->type==CONFLICT);
363*4520Snw141292     rc = ap1->x.rp->index - ap2->x.rp->index;
364*4520Snw141292   }
365*4520Snw141292   return rc;
366*4520Snw141292 }
367*4520Snw141292 
368*4520Snw141292 /* Sort parser actions */
Action_sort(ap)369*4520Snw141292 struct action *Action_sort(ap)
370*4520Snw141292 struct action *ap;
371*4520Snw141292 {
372*4520Snw141292   ap = (struct action *)msort((char *)ap,(char **)&ap->next,actioncmp);
373*4520Snw141292   return ap;
374*4520Snw141292 }
375*4520Snw141292 
Action_add(app,type,sp,arg)376*4520Snw141292 void Action_add(app,type,sp,arg)
377*4520Snw141292 struct action **app;
378*4520Snw141292 enum e_action type;
379*4520Snw141292 struct symbol *sp;
380*4520Snw141292 char *arg;
381*4520Snw141292 {
382*4520Snw141292   struct action *new;
383*4520Snw141292   new = Action_new();
384*4520Snw141292   new->next = *app;
385*4520Snw141292   *app = new;
386*4520Snw141292   new->type = type;
387*4520Snw141292   new->sp = sp;
388*4520Snw141292   if( type==SHIFT ){
389*4520Snw141292     new->x.stp = (struct state *)arg;
390*4520Snw141292   }else{
391*4520Snw141292     new->x.rp = (struct rule *)arg;
392*4520Snw141292   }
393*4520Snw141292 }
394*4520Snw141292 /********************** New code to implement the "acttab" module ***********/
395*4520Snw141292 /*
396*4520Snw141292 ** This module implements routines use to construct the yy_action[] table.
397*4520Snw141292 */
398*4520Snw141292 
399*4520Snw141292 /*
400*4520Snw141292 ** The state of the yy_action table under construction is an instance of
401*4520Snw141292 ** the following structure
402*4520Snw141292 */
403*4520Snw141292 typedef struct acttab acttab;
404*4520Snw141292 struct acttab {
405*4520Snw141292   int nAction;                 /* Number of used slots in aAction[] */
406*4520Snw141292   int nActionAlloc;            /* Slots allocated for aAction[] */
407*4520Snw141292   struct {
408*4520Snw141292     int lookahead;             /* Value of the lookahead token */
409*4520Snw141292     int action;                /* Action to take on the given lookahead */
410*4520Snw141292   } *aAction,                  /* The yy_action[] table under construction */
411*4520Snw141292     *aLookahead;               /* A single new transaction set */
412*4520Snw141292   int mnLookahead;             /* Minimum aLookahead[].lookahead */
413*4520Snw141292   int mnAction;                /* Action associated with mnLookahead */
414*4520Snw141292   int mxLookahead;             /* Maximum aLookahead[].lookahead */
415*4520Snw141292   int nLookahead;              /* Used slots in aLookahead[] */
416*4520Snw141292   int nLookaheadAlloc;         /* Slots allocated in aLookahead[] */
417*4520Snw141292 };
418*4520Snw141292 
419*4520Snw141292 /* Return the number of entries in the yy_action table */
420*4520Snw141292 #define acttab_size(X) ((X)->nAction)
421*4520Snw141292 
422*4520Snw141292 /* The value for the N-th entry in yy_action */
423*4520Snw141292 #define acttab_yyaction(X,N)  ((X)->aAction[N].action)
424*4520Snw141292 
425*4520Snw141292 /* The value for the N-th entry in yy_lookahead */
426*4520Snw141292 #define acttab_yylookahead(X,N)  ((X)->aAction[N].lookahead)
427*4520Snw141292 
428*4520Snw141292 /* Free all memory associated with the given acttab */
acttab_free(acttab * p)429*4520Snw141292 void acttab_free(acttab *p){
430*4520Snw141292   free( p->aAction );
431*4520Snw141292   free( p->aLookahead );
432*4520Snw141292   free( p );
433*4520Snw141292 }
434*4520Snw141292 
435*4520Snw141292 /* Allocate a new acttab structure */
acttab_alloc(void)436*4520Snw141292 acttab *acttab_alloc(void){
437*4520Snw141292   acttab *p = malloc( sizeof(*p) );
438*4520Snw141292   if( p==0 ){
439*4520Snw141292     fprintf(stderr,"Unable to allocate memory for a new acttab.");
440*4520Snw141292     exit(1);
441*4520Snw141292   }
442*4520Snw141292   memset(p, 0, sizeof(*p));
443*4520Snw141292   return p;
444*4520Snw141292 }
445*4520Snw141292 
446*4520Snw141292 /* Add a new action to the current transaction set
447*4520Snw141292 */
acttab_action(acttab * p,int lookahead,int action)448*4520Snw141292 void acttab_action(acttab *p, int lookahead, int action){
449*4520Snw141292   if( p->nLookahead>=p->nLookaheadAlloc ){
450*4520Snw141292     p->nLookaheadAlloc += 25;
451*4520Snw141292     p->aLookahead = realloc( p->aLookahead,
452*4520Snw141292                              sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
453*4520Snw141292     if( p->aLookahead==0 ){
454*4520Snw141292       fprintf(stderr,"malloc failed\n");
455*4520Snw141292       exit(1);
456*4520Snw141292     }
457*4520Snw141292   }
458*4520Snw141292   if( p->nLookahead==0 ){
459*4520Snw141292     p->mxLookahead = lookahead;
460*4520Snw141292     p->mnLookahead = lookahead;
461*4520Snw141292     p->mnAction = action;
462*4520Snw141292   }else{
463*4520Snw141292     if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
464*4520Snw141292     if( p->mnLookahead>lookahead ){
465*4520Snw141292       p->mnLookahead = lookahead;
466*4520Snw141292       p->mnAction = action;
467*4520Snw141292     }
468*4520Snw141292   }
469*4520Snw141292   p->aLookahead[p->nLookahead].lookahead = lookahead;
470*4520Snw141292   p->aLookahead[p->nLookahead].action = action;
471*4520Snw141292   p->nLookahead++;
472*4520Snw141292 }
473*4520Snw141292 
474*4520Snw141292 /*
475*4520Snw141292 ** Add the transaction set built up with prior calls to acttab_action()
476*4520Snw141292 ** into the current action table.  Then reset the transaction set back
477*4520Snw141292 ** to an empty set in preparation for a new round of acttab_action() calls.
478*4520Snw141292 **
479*4520Snw141292 ** Return the offset into the action table of the new transaction.
480*4520Snw141292 */
acttab_insert(acttab * p)481*4520Snw141292 int acttab_insert(acttab *p){
482*4520Snw141292   int i, j, k, n;
483*4520Snw141292   assert( p->nLookahead>0 );
484*4520Snw141292 
485*4520Snw141292   /* Make sure we have enough space to hold the expanded action table
486*4520Snw141292   ** in the worst case.  The worst case occurs if the transaction set
487*4520Snw141292   ** must be appended to the current action table
488*4520Snw141292   */
489*4520Snw141292   n = p->mxLookahead + 1;
490*4520Snw141292   if( p->nAction + n >= p->nActionAlloc ){
491*4520Snw141292     int oldAlloc = p->nActionAlloc;
492*4520Snw141292     p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
493*4520Snw141292     p->aAction = realloc( p->aAction,
494*4520Snw141292                           sizeof(p->aAction[0])*p->nActionAlloc);
495*4520Snw141292     if( p->aAction==0 ){
496*4520Snw141292       fprintf(stderr,"malloc failed\n");
497*4520Snw141292       exit(1);
498*4520Snw141292     }
499*4520Snw141292     for(i=oldAlloc; i<p->nActionAlloc; i++){
500*4520Snw141292       p->aAction[i].lookahead = -1;
501*4520Snw141292       p->aAction[i].action = -1;
502*4520Snw141292     }
503*4520Snw141292   }
504*4520Snw141292 
505*4520Snw141292   /* Scan the existing action table looking for an offset where we can
506*4520Snw141292   ** insert the current transaction set.  Fall out of the loop when that
507*4520Snw141292   ** offset is found.  In the worst case, we fall out of the loop when
508*4520Snw141292   ** i reaches p->nAction, which means we append the new transaction set.
509*4520Snw141292   **
510*4520Snw141292   ** i is the index in p->aAction[] where p->mnLookahead is inserted.
511*4520Snw141292   */
512*4520Snw141292   for(i=0; i<p->nAction+p->mnLookahead; i++){
513*4520Snw141292     if( p->aAction[i].lookahead<0 ){
514*4520Snw141292       for(j=0; j<p->nLookahead; j++){
515*4520Snw141292         k = p->aLookahead[j].lookahead - p->mnLookahead + i;
516*4520Snw141292         if( k<0 ) break;
517*4520Snw141292         if( p->aAction[k].lookahead>=0 ) break;
518*4520Snw141292       }
519*4520Snw141292       if( j<p->nLookahead ) continue;
520*4520Snw141292       for(j=0; j<p->nAction; j++){
521*4520Snw141292         if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
522*4520Snw141292       }
523*4520Snw141292       if( j==p->nAction ){
524*4520Snw141292         break;  /* Fits in empty slots */
525*4520Snw141292       }
526*4520Snw141292     }else if( p->aAction[i].lookahead==p->mnLookahead ){
527*4520Snw141292       if( p->aAction[i].action!=p->mnAction ) continue;
528*4520Snw141292       for(j=0; j<p->nLookahead; j++){
529*4520Snw141292         k = p->aLookahead[j].lookahead - p->mnLookahead + i;
530*4520Snw141292         if( k<0 || k>=p->nAction ) break;
531*4520Snw141292         if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
532*4520Snw141292         if( p->aLookahead[j].action!=p->aAction[k].action ) break;
533*4520Snw141292       }
534*4520Snw141292       if( j<p->nLookahead ) continue;
535*4520Snw141292       n = 0;
536*4520Snw141292       for(j=0; j<p->nAction; j++){
537*4520Snw141292         if( p->aAction[j].lookahead<0 ) continue;
538*4520Snw141292         if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
539*4520Snw141292       }
540*4520Snw141292       if( n==p->nLookahead ){
541*4520Snw141292         break;  /* Same as a prior transaction set */
542*4520Snw141292       }
543*4520Snw141292     }
544*4520Snw141292   }
545*4520Snw141292   /* Insert transaction set at index i. */
546*4520Snw141292   for(j=0; j<p->nLookahead; j++){
547*4520Snw141292     k = p->aLookahead[j].lookahead - p->mnLookahead + i;
548*4520Snw141292     p->aAction[k] = p->aLookahead[j];
549*4520Snw141292     if( k>=p->nAction ) p->nAction = k+1;
550*4520Snw141292   }
551*4520Snw141292   p->nLookahead = 0;
552*4520Snw141292 
553*4520Snw141292   /* Return the offset that is added to the lookahead in order to get the
554*4520Snw141292   ** index into yy_action of the action */
555*4520Snw141292   return i - p->mnLookahead;
556*4520Snw141292 }
557*4520Snw141292 
558*4520Snw141292 /********************** From the file "assert.c" ****************************/
559*4520Snw141292 /*
560*4520Snw141292 ** A more efficient way of handling assertions.
561*4520Snw141292 */
myassert(file,line)562*4520Snw141292 void myassert(file,line)
563*4520Snw141292 char *file;
564*4520Snw141292 int line;
565*4520Snw141292 {
566*4520Snw141292   fprintf(stderr,"Assertion failed on line %d of file \"%s\"\n",line,file);
567*4520Snw141292   exit(1);
568*4520Snw141292 }
569*4520Snw141292 /********************** From the file "build.c" *****************************/
570*4520Snw141292 /*
571*4520Snw141292 ** Routines to construction the finite state machine for the LEMON
572*4520Snw141292 ** parser generator.
573*4520Snw141292 */
574*4520Snw141292 
575*4520Snw141292 /* Find a precedence symbol of every rule in the grammar.
576*4520Snw141292 **
577*4520Snw141292 ** Those rules which have a precedence symbol coded in the input
578*4520Snw141292 ** grammar using the "[symbol]" construct will already have the
579*4520Snw141292 ** rp->precsym field filled.  Other rules take as their precedence
580*4520Snw141292 ** symbol the first RHS symbol with a defined precedence.  If there
581*4520Snw141292 ** are not RHS symbols with a defined precedence, the precedence
582*4520Snw141292 ** symbol field is left blank.
583*4520Snw141292 */
FindRulePrecedences(xp)584*4520Snw141292 void FindRulePrecedences(xp)
585*4520Snw141292 struct lemon *xp;
586*4520Snw141292 {
587*4520Snw141292   struct rule *rp;
588*4520Snw141292   for(rp=xp->rule; rp; rp=rp->next){
589*4520Snw141292     if( rp->precsym==0 ){
590*4520Snw141292       int i;
591*4520Snw141292       for(i=0; i<rp->nrhs; i++){
592*4520Snw141292         if( rp->rhs[i]->prec>=0 ){
593*4520Snw141292           rp->precsym = rp->rhs[i];
594*4520Snw141292           break;
595*4520Snw141292 	}
596*4520Snw141292       }
597*4520Snw141292     }
598*4520Snw141292   }
599*4520Snw141292   return;
600*4520Snw141292 }
601*4520Snw141292 
602*4520Snw141292 /* Find all nonterminals which will generate the empty string.
603*4520Snw141292 ** Then go back and compute the first sets of every nonterminal.
604*4520Snw141292 ** The first set is the set of all terminal symbols which can begin
605*4520Snw141292 ** a string generated by that nonterminal.
606*4520Snw141292 */
FindFirstSets(lemp)607*4520Snw141292 void FindFirstSets(lemp)
608*4520Snw141292 struct lemon *lemp;
609*4520Snw141292 {
610*4520Snw141292   int i;
611*4520Snw141292   struct rule *rp;
612*4520Snw141292   int progress;
613*4520Snw141292 
614*4520Snw141292   for(i=0; i<lemp->nsymbol; i++){
615*4520Snw141292     lemp->symbols[i]->lambda = B_FALSE;
616*4520Snw141292   }
617*4520Snw141292   for(i=lemp->nterminal; i<lemp->nsymbol; i++){
618*4520Snw141292     lemp->symbols[i]->firstset = SetNew();
619*4520Snw141292   }
620*4520Snw141292 
621*4520Snw141292   /* First compute all lambdas */
622*4520Snw141292   do{
623*4520Snw141292     progress = 0;
624*4520Snw141292     for(rp=lemp->rule; rp; rp=rp->next){
625*4520Snw141292       if( rp->lhs->lambda ) continue;
626*4520Snw141292       for(i=0; i<rp->nrhs; i++){
627*4520Snw141292          if( rp->rhs[i]->lambda==B_FALSE ) break;
628*4520Snw141292       }
629*4520Snw141292       if( i==rp->nrhs ){
630*4520Snw141292         rp->lhs->lambda = B_TRUE;
631*4520Snw141292         progress = 1;
632*4520Snw141292       }
633*4520Snw141292     }
634*4520Snw141292   }while( progress );
635*4520Snw141292 
636*4520Snw141292   /* Now compute all first sets */
637*4520Snw141292   do{
638*4520Snw141292     struct symbol *s1, *s2;
639*4520Snw141292     progress = 0;
640*4520Snw141292     for(rp=lemp->rule; rp; rp=rp->next){
641*4520Snw141292       s1 = rp->lhs;
642*4520Snw141292       for(i=0; i<rp->nrhs; i++){
643*4520Snw141292         s2 = rp->rhs[i];
644*4520Snw141292         if( s2->type==TERMINAL ){
645*4520Snw141292           progress += SetAdd(s1->firstset,s2->index);
646*4520Snw141292           break;
647*4520Snw141292 	}else if( s1==s2 ){
648*4520Snw141292           if( s1->lambda==B_FALSE ) break;
649*4520Snw141292 	}else{
650*4520Snw141292           progress += SetUnion(s1->firstset,s2->firstset);
651*4520Snw141292           if( s2->lambda==B_FALSE ) break;
652*4520Snw141292 	}
653*4520Snw141292       }
654*4520Snw141292     }
655*4520Snw141292   }while( progress );
656*4520Snw141292   return;
657*4520Snw141292 }
658*4520Snw141292 
659*4520Snw141292 /* Compute all LR(0) states for the grammar.  Links
660*4520Snw141292 ** are added to between some states so that the LR(1) follow sets
661*4520Snw141292 ** can be computed later.
662*4520Snw141292 */
663*4520Snw141292 PRIVATE struct state *getstate(/* struct lemon * */);  /* forward reference */
FindStates(lemp)664*4520Snw141292 void FindStates(lemp)
665*4520Snw141292 struct lemon *lemp;
666*4520Snw141292 {
667*4520Snw141292   struct symbol *sp;
668*4520Snw141292   struct rule *rp;
669*4520Snw141292 
670*4520Snw141292   Configlist_init();
671*4520Snw141292 
672*4520Snw141292   /* Find the start symbol */
673*4520Snw141292   if( lemp->start ){
674*4520Snw141292     sp = Symbol_find(lemp->start);
675*4520Snw141292     if( sp==0 ){
676*4520Snw141292       ErrorMsg(lemp->filename,0,
677*4520Snw141292 "The specified start symbol \"%s\" is not \
678*4520Snw141292 in a nonterminal of the grammar.  \"%s\" will be used as the start \
679*4520Snw141292 symbol instead.",lemp->start,lemp->rule->lhs->name);
680*4520Snw141292       lemp->errorcnt++;
681*4520Snw141292       sp = lemp->rule->lhs;
682*4520Snw141292     }
683*4520Snw141292   }else{
684*4520Snw141292     sp = lemp->rule->lhs;
685*4520Snw141292   }
686*4520Snw141292 
687*4520Snw141292   /* Make sure the start symbol doesn't occur on the right-hand side of
688*4520Snw141292   ** any rule.  Report an error if it does.  (YACC would generate a new
689*4520Snw141292   ** start symbol in this case.) */
690*4520Snw141292   for(rp=lemp->rule; rp; rp=rp->next){
691*4520Snw141292     int i;
692*4520Snw141292     for(i=0; i<rp->nrhs; i++){
693*4520Snw141292       if( rp->rhs[i]==sp ){
694*4520Snw141292         ErrorMsg(lemp->filename,0,
695*4520Snw141292 "The start symbol \"%s\" occurs on the \
696*4520Snw141292 right-hand side of a rule. This will result in a parser which \
697*4520Snw141292 does not work properly.",sp->name);
698*4520Snw141292         lemp->errorcnt++;
699*4520Snw141292       }
700*4520Snw141292     }
701*4520Snw141292   }
702*4520Snw141292 
703*4520Snw141292   /* The basis configuration set for the first state
704*4520Snw141292   ** is all rules which have the start symbol as their
705*4520Snw141292   ** left-hand side */
706*4520Snw141292   for(rp=sp->rule; rp; rp=rp->nextlhs){
707*4520Snw141292     struct config *newcfp;
708*4520Snw141292     newcfp = Configlist_addbasis(rp,0);
709*4520Snw141292     SetAdd(newcfp->fws,0);
710*4520Snw141292   }
711*4520Snw141292 
712*4520Snw141292   /* Compute the first state.  All other states will be
713*4520Snw141292   ** computed automatically during the computation of the first one.
714*4520Snw141292   ** The returned pointer to the first state is not used. */
715*4520Snw141292   (void)getstate(lemp);
716*4520Snw141292   return;
717*4520Snw141292 }
718*4520Snw141292 
719*4520Snw141292 /* Return a pointer to a state which is described by the configuration
720*4520Snw141292 ** list which has been built from calls to Configlist_add.
721*4520Snw141292 */
722*4520Snw141292 PRIVATE void buildshifts(/* struct lemon *, struct state * */); /* Forwd ref */
getstate(lemp)723*4520Snw141292 PRIVATE struct state *getstate(lemp)
724*4520Snw141292 struct lemon *lemp;
725*4520Snw141292 {
726*4520Snw141292   struct config *cfp, *bp;
727*4520Snw141292   struct state *stp;
728*4520Snw141292 
729*4520Snw141292   /* Extract the sorted basis of the new state.  The basis was constructed
730*4520Snw141292   ** by prior calls to "Configlist_addbasis()". */
731*4520Snw141292   Configlist_sortbasis();
732*4520Snw141292   bp = Configlist_basis();
733*4520Snw141292 
734*4520Snw141292   /* Get a state with the same basis */
735*4520Snw141292   stp = State_find(bp);
736*4520Snw141292   if( stp ){
737*4520Snw141292     /* A state with the same basis already exists!  Copy all the follow-set
738*4520Snw141292     ** propagation links from the state under construction into the
739*4520Snw141292     ** preexisting state, then return a pointer to the preexisting state */
740*4520Snw141292     struct config *x, *y;
741*4520Snw141292     for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
742*4520Snw141292       Plink_copy(&y->bplp,x->bplp);
743*4520Snw141292       Plink_delete(x->fplp);
744*4520Snw141292       x->fplp = x->bplp = 0;
745*4520Snw141292     }
746*4520Snw141292     cfp = Configlist_return();
747*4520Snw141292     Configlist_eat(cfp);
748*4520Snw141292   }else{
749*4520Snw141292     /* This really is a new state.  Construct all the details */
750*4520Snw141292     Configlist_closure(lemp);    /* Compute the configuration closure */
751*4520Snw141292     Configlist_sort();           /* Sort the configuration closure */
752*4520Snw141292     cfp = Configlist_return();   /* Get a pointer to the config list */
753*4520Snw141292     stp = State_new();           /* A new state structure */
754*4520Snw141292     MemoryCheck(stp);
755*4520Snw141292     stp->bp = bp;                /* Remember the configuration basis */
756*4520Snw141292     stp->cfp = cfp;              /* Remember the configuration closure */
757*4520Snw141292     stp->index = lemp->nstate++; /* Every state gets a sequence number */
758*4520Snw141292     stp->ap = 0;                 /* No actions, yet. */
759*4520Snw141292     State_insert(stp,stp->bp);   /* Add to the state table */
760*4520Snw141292     buildshifts(lemp,stp);       /* Recursively compute successor states */
761*4520Snw141292   }
762*4520Snw141292   return stp;
763*4520Snw141292 }
764*4520Snw141292 
765*4520Snw141292 /* Construct all successor states to the given state.  A "successor"
766*4520Snw141292 ** state is any state which can be reached by a shift action.
767*4520Snw141292 */
buildshifts(lemp,stp)768*4520Snw141292 PRIVATE void buildshifts(lemp,stp)
769*4520Snw141292 struct lemon *lemp;
770*4520Snw141292 struct state *stp;     /* The state from which successors are computed */
771*4520Snw141292 {
772*4520Snw141292   struct config *cfp;  /* For looping thru the config closure of "stp" */
773*4520Snw141292   struct config *bcfp; /* For the inner loop on config closure of "stp" */
774*4520Snw141292   struct config *new;  /* */
775*4520Snw141292   struct symbol *sp;   /* Symbol following the dot in configuration "cfp" */
776*4520Snw141292   struct symbol *bsp;  /* Symbol following the dot in configuration "bcfp" */
777*4520Snw141292   struct state *newstp; /* A pointer to a successor state */
778*4520Snw141292 
779*4520Snw141292   /* Each configuration becomes complete after it contibutes to a successor
780*4520Snw141292   ** state.  Initially, all configurations are incomplete */
781*4520Snw141292   for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
782*4520Snw141292 
783*4520Snw141292   /* Loop through all configurations of the state "stp" */
784*4520Snw141292   for(cfp=stp->cfp; cfp; cfp=cfp->next){
785*4520Snw141292     if( cfp->status==COMPLETE ) continue;    /* Already used by inner loop */
786*4520Snw141292     if( cfp->dot>=cfp->rp->nrhs ) continue;  /* Can't shift this config */
787*4520Snw141292     Configlist_reset();                      /* Reset the new config set */
788*4520Snw141292     sp = cfp->rp->rhs[cfp->dot];             /* Symbol after the dot */
789*4520Snw141292 
790*4520Snw141292     /* For every configuration in the state "stp" which has the symbol "sp"
791*4520Snw141292     ** following its dot, add the same configuration to the basis set under
792*4520Snw141292     ** construction but with the dot shifted one symbol to the right. */
793*4520Snw141292     for(bcfp=cfp; bcfp; bcfp=bcfp->next){
794*4520Snw141292       if( bcfp->status==COMPLETE ) continue;    /* Already used */
795*4520Snw141292       if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
796*4520Snw141292       bsp = bcfp->rp->rhs[bcfp->dot];           /* Get symbol after dot */
797*4520Snw141292       if( bsp!=sp ) continue;                   /* Must be same as for "cfp" */
798*4520Snw141292       bcfp->status = COMPLETE;                  /* Mark this config as used */
799*4520Snw141292       new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
800*4520Snw141292       Plink_add(&new->bplp,bcfp);
801*4520Snw141292     }
802*4520Snw141292 
803*4520Snw141292     /* Get a pointer to the state described by the basis configuration set
804*4520Snw141292     ** constructed in the preceding loop */
805*4520Snw141292     newstp = getstate(lemp);
806*4520Snw141292 
807*4520Snw141292     /* The state "newstp" is reached from the state "stp" by a shift action
808*4520Snw141292     ** on the symbol "sp" */
809*4520Snw141292     Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
810*4520Snw141292   }
811*4520Snw141292 }
812*4520Snw141292 
813*4520Snw141292 /*
814*4520Snw141292 ** Construct the propagation links
815*4520Snw141292 */
FindLinks(lemp)816*4520Snw141292 void FindLinks(lemp)
817*4520Snw141292 struct lemon *lemp;
818*4520Snw141292 {
819*4520Snw141292   int i;
820*4520Snw141292   struct config *cfp, *other;
821*4520Snw141292   struct state *stp;
822*4520Snw141292   struct plink *plp;
823*4520Snw141292 
824*4520Snw141292   /* Housekeeping detail:
825*4520Snw141292   ** Add to every propagate link a pointer back to the state to
826*4520Snw141292   ** which the link is attached. */
827*4520Snw141292   for(i=0; i<lemp->nstate; i++){
828*4520Snw141292     stp = lemp->sorted[i];
829*4520Snw141292     for(cfp=stp->cfp; cfp; cfp=cfp->next){
830*4520Snw141292       cfp->stp = stp;
831*4520Snw141292     }
832*4520Snw141292   }
833*4520Snw141292 
834*4520Snw141292   /* Convert all backlinks into forward links.  Only the forward
835*4520Snw141292   ** links are used in the follow-set computation. */
836*4520Snw141292   for(i=0; i<lemp->nstate; i++){
837*4520Snw141292     stp = lemp->sorted[i];
838*4520Snw141292     for(cfp=stp->cfp; cfp; cfp=cfp->next){
839*4520Snw141292       for(plp=cfp->bplp; plp; plp=plp->next){
840*4520Snw141292         other = plp->cfp;
841*4520Snw141292         Plink_add(&other->fplp,cfp);
842*4520Snw141292       }
843*4520Snw141292     }
844*4520Snw141292   }
845*4520Snw141292 }
846*4520Snw141292 
847*4520Snw141292 /* Compute all followsets.
848*4520Snw141292 **
849*4520Snw141292 ** A followset is the set of all symbols which can come immediately
850*4520Snw141292 ** after a configuration.
851*4520Snw141292 */
FindFollowSets(lemp)852*4520Snw141292 void FindFollowSets(lemp)
853*4520Snw141292 struct lemon *lemp;
854*4520Snw141292 {
855*4520Snw141292   int i;
856*4520Snw141292   struct config *cfp;
857*4520Snw141292   struct plink *plp;
858*4520Snw141292   int progress;
859*4520Snw141292   int change;
860*4520Snw141292 
861*4520Snw141292   for(i=0; i<lemp->nstate; i++){
862*4520Snw141292     for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
863*4520Snw141292       cfp->status = INCOMPLETE;
864*4520Snw141292     }
865*4520Snw141292   }
866*4520Snw141292 
867*4520Snw141292   do{
868*4520Snw141292     progress = 0;
869*4520Snw141292     for(i=0; i<lemp->nstate; i++){
870*4520Snw141292       for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
871*4520Snw141292         if( cfp->status==COMPLETE ) continue;
872*4520Snw141292         for(plp=cfp->fplp; plp; plp=plp->next){
873*4520Snw141292           change = SetUnion(plp->cfp->fws,cfp->fws);
874*4520Snw141292           if( change ){
875*4520Snw141292             plp->cfp->status = INCOMPLETE;
876*4520Snw141292             progress = 1;
877*4520Snw141292 	  }
878*4520Snw141292 	}
879*4520Snw141292         cfp->status = COMPLETE;
880*4520Snw141292       }
881*4520Snw141292     }
882*4520Snw141292   }while( progress );
883*4520Snw141292 }
884*4520Snw141292 
885*4520Snw141292 static int resolve_conflict();
886*4520Snw141292 
887*4520Snw141292 /* Compute the reduce actions, and resolve conflicts.
888*4520Snw141292 */
FindActions(lemp)889*4520Snw141292 void FindActions(lemp)
890*4520Snw141292 struct lemon *lemp;
891*4520Snw141292 {
892*4520Snw141292   int i,j;
893*4520Snw141292   struct config *cfp;
894*4520Snw141292   struct state *stp;
895*4520Snw141292   struct symbol *sp;
896*4520Snw141292   struct rule *rp;
897*4520Snw141292 
898*4520Snw141292   /* Add all of the reduce actions
899*4520Snw141292   ** A reduce action is added for each element of the followset of
900*4520Snw141292   ** a configuration which has its dot at the extreme right.
901*4520Snw141292   */
902*4520Snw141292   for(i=0; i<lemp->nstate; i++){   /* Loop over all states */
903*4520Snw141292     stp = lemp->sorted[i];
904*4520Snw141292     for(cfp=stp->cfp; cfp; cfp=cfp->next){  /* Loop over all configurations */
905*4520Snw141292       if( cfp->rp->nrhs==cfp->dot ){        /* Is dot at extreme right? */
906*4520Snw141292         for(j=0; j<lemp->nterminal; j++){
907*4520Snw141292           if( SetFind(cfp->fws,j) ){
908*4520Snw141292             /* Add a reduce action to the state "stp" which will reduce by the
909*4520Snw141292             ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
910*4520Snw141292             Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
911*4520Snw141292           }
912*4520Snw141292 	}
913*4520Snw141292       }
914*4520Snw141292     }
915*4520Snw141292   }
916*4520Snw141292 
917*4520Snw141292   /* Add the accepting token */
918*4520Snw141292   if( lemp->start ){
919*4520Snw141292     sp = Symbol_find(lemp->start);
920*4520Snw141292     if( sp==0 ) sp = lemp->rule->lhs;
921*4520Snw141292   }else{
922*4520Snw141292     sp = lemp->rule->lhs;
923*4520Snw141292   }
924*4520Snw141292   /* Add to the first state (which is always the starting state of the
925*4520Snw141292   ** finite state machine) an action to ACCEPT if the lookahead is the
926*4520Snw141292   ** start nonterminal.  */
927*4520Snw141292   Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
928*4520Snw141292 
929*4520Snw141292   /* Resolve conflicts */
930*4520Snw141292   for(i=0; i<lemp->nstate; i++){
931*4520Snw141292     struct action *ap, *nap;
932*4520Snw141292     struct state *stp;
933*4520Snw141292     stp = lemp->sorted[i];
934*4520Snw141292     assert( stp->ap );
935*4520Snw141292     stp->ap = Action_sort(stp->ap);
936*4520Snw141292     for(ap=stp->ap; ap && ap->next; ap=ap->next){
937*4520Snw141292       for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
938*4520Snw141292          /* The two actions "ap" and "nap" have the same lookahead.
939*4520Snw141292          ** Figure out which one should be used */
940*4520Snw141292          lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym);
941*4520Snw141292       }
942*4520Snw141292     }
943*4520Snw141292   }
944*4520Snw141292 
945*4520Snw141292   /* Report an error for each rule that can never be reduced. */
946*4520Snw141292   for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = B_FALSE;
947*4520Snw141292   for(i=0; i<lemp->nstate; i++){
948*4520Snw141292     struct action *ap;
949*4520Snw141292     for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
950*4520Snw141292       if( ap->type==REDUCE ) ap->x.rp->canReduce = B_TRUE;
951*4520Snw141292     }
952*4520Snw141292   }
953*4520Snw141292   for(rp=lemp->rule; rp; rp=rp->next){
954*4520Snw141292     if( rp->canReduce ) continue;
955*4520Snw141292     ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
956*4520Snw141292     lemp->errorcnt++;
957*4520Snw141292   }
958*4520Snw141292 }
959*4520Snw141292 
960*4520Snw141292 /* Resolve a conflict between the two given actions.  If the
961*4520Snw141292 ** conflict can't be resolve, return non-zero.
962*4520Snw141292 **
963*4520Snw141292 ** NO LONGER TRUE:
964*4520Snw141292 **   To resolve a conflict, first look to see if either action
965*4520Snw141292 **   is on an error rule.  In that case, take the action which
966*4520Snw141292 **   is not associated with the error rule.  If neither or both
967*4520Snw141292 **   actions are associated with an error rule, then try to
968*4520Snw141292 **   use precedence to resolve the conflict.
969*4520Snw141292 **
970*4520Snw141292 ** If either action is a SHIFT, then it must be apx.  This
971*4520Snw141292 ** function won't work if apx->type==REDUCE and apy->type==SHIFT.
972*4520Snw141292 */
resolve_conflict(apx,apy,errsym)973*4520Snw141292 static int resolve_conflict(apx,apy,errsym)
974*4520Snw141292 struct action *apx;
975*4520Snw141292 struct action *apy;
976*4520Snw141292 struct symbol *errsym;   /* The error symbol (if defined.  NULL otherwise) */
977*4520Snw141292 {
978*4520Snw141292   struct symbol *spx, *spy;
979*4520Snw141292   int errcnt = 0;
980*4520Snw141292   assert( apx->sp==apy->sp );  /* Otherwise there would be no conflict */
981*4520Snw141292   if( apx->type==SHIFT && apy->type==REDUCE ){
982*4520Snw141292     spx = apx->sp;
983*4520Snw141292     spy = apy->x.rp->precsym;
984*4520Snw141292     if( spy==0 || spx->prec<0 || spy->prec<0 ){
985*4520Snw141292       /* Not enough precedence information. */
986*4520Snw141292       apy->type = CONFLICT;
987*4520Snw141292       errcnt++;
988*4520Snw141292     }else if( spx->prec>spy->prec ){    /* Lower precedence wins */
989*4520Snw141292       apy->type = RD_RESOLVED;
990*4520Snw141292     }else if( spx->prec<spy->prec ){
991*4520Snw141292       apx->type = SH_RESOLVED;
992*4520Snw141292     }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
993*4520Snw141292       apy->type = RD_RESOLVED;                             /* associativity */
994*4520Snw141292     }else if( spx->prec==spy->prec && spx->assoc==LEFT ){  /* to break tie */
995*4520Snw141292       apx->type = SH_RESOLVED;
996*4520Snw141292     }else{
997*4520Snw141292       assert( spx->prec==spy->prec && spx->assoc==NONE );
998*4520Snw141292       apy->type = CONFLICT;
999*4520Snw141292       errcnt++;
1000*4520Snw141292     }
1001*4520Snw141292   }else if( apx->type==REDUCE && apy->type==REDUCE ){
1002*4520Snw141292     spx = apx->x.rp->precsym;
1003*4520Snw141292     spy = apy->x.rp->precsym;
1004*4520Snw141292     if( spx==0 || spy==0 || spx->prec<0 ||
1005*4520Snw141292     spy->prec<0 || spx->prec==spy->prec ){
1006*4520Snw141292       apy->type = CONFLICT;
1007*4520Snw141292       errcnt++;
1008*4520Snw141292     }else if( spx->prec>spy->prec ){
1009*4520Snw141292       apy->type = RD_RESOLVED;
1010*4520Snw141292     }else if( spx->prec<spy->prec ){
1011*4520Snw141292       apx->type = RD_RESOLVED;
1012*4520Snw141292     }
1013*4520Snw141292   }else{
1014*4520Snw141292     assert(
1015*4520Snw141292       apx->type==SH_RESOLVED ||
1016*4520Snw141292       apx->type==RD_RESOLVED ||
1017*4520Snw141292       apx->type==CONFLICT ||
1018*4520Snw141292       apy->type==SH_RESOLVED ||
1019*4520Snw141292       apy->type==RD_RESOLVED ||
1020*4520Snw141292       apy->type==CONFLICT
1021*4520Snw141292     );
1022*4520Snw141292     /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
1023*4520Snw141292     ** REDUCEs on the list.  If we reach this point it must be because
1024*4520Snw141292     ** the parser conflict had already been resolved. */
1025*4520Snw141292   }
1026*4520Snw141292   return errcnt;
1027*4520Snw141292 }
1028*4520Snw141292 /********************* From the file "configlist.c" *************************/
1029*4520Snw141292 /*
1030*4520Snw141292 ** Routines to processing a configuration list and building a state
1031*4520Snw141292 ** in the LEMON parser generator.
1032*4520Snw141292 */
1033*4520Snw141292 
1034*4520Snw141292 static struct config *freelist = 0;      /* List of free configurations */
1035*4520Snw141292 static struct config *current = 0;       /* Top of list of configurations */
1036*4520Snw141292 static struct config **currentend = 0;   /* Last on list of configs */
1037*4520Snw141292 static struct config *basis = 0;         /* Top of list of basis configs */
1038*4520Snw141292 static struct config **basisend = 0;     /* End of list of basis configs */
1039*4520Snw141292 
1040*4520Snw141292 /* Return a pointer to a new configuration */
newconfig()1041*4520Snw141292 PRIVATE struct config *newconfig(){
1042*4520Snw141292   struct config *new;
1043*4520Snw141292   if( freelist==0 ){
1044*4520Snw141292     int i;
1045*4520Snw141292     int amt = 3;
1046*4520Snw141292     freelist = (struct config *)malloc( sizeof(struct config)*amt );
1047*4520Snw141292     if( freelist==0 ){
1048*4520Snw141292       fprintf(stderr,"Unable to allocate memory for a new configuration.");
1049*4520Snw141292       exit(1);
1050*4520Snw141292     }
1051*4520Snw141292     for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
1052*4520Snw141292     freelist[amt-1].next = 0;
1053*4520Snw141292   }
1054*4520Snw141292   new = freelist;
1055*4520Snw141292   freelist = freelist->next;
1056*4520Snw141292   return new;
1057*4520Snw141292 }
1058*4520Snw141292 
1059*4520Snw141292 /* The configuration "old" is no longer used */
deleteconfig(old)1060*4520Snw141292 PRIVATE void deleteconfig(old)
1061*4520Snw141292 struct config *old;
1062*4520Snw141292 {
1063*4520Snw141292   old->next = freelist;
1064*4520Snw141292   freelist = old;
1065*4520Snw141292 }
1066*4520Snw141292 
1067*4520Snw141292 /* Initialized the configuration list builder */
Configlist_init()1068*4520Snw141292 void Configlist_init(){
1069*4520Snw141292   current = 0;
1070*4520Snw141292   currentend = &current;
1071*4520Snw141292   basis = 0;
1072*4520Snw141292   basisend = &basis;
1073*4520Snw141292   Configtable_init();
1074*4520Snw141292   return;
1075*4520Snw141292 }
1076*4520Snw141292 
1077*4520Snw141292 /* Initialized the configuration list builder */
Configlist_reset()1078*4520Snw141292 void Configlist_reset(){
1079*4520Snw141292   current = 0;
1080*4520Snw141292   currentend = &current;
1081*4520Snw141292   basis = 0;
1082*4520Snw141292   basisend = &basis;
1083*4520Snw141292   Configtable_clear(0);
1084*4520Snw141292   return;
1085*4520Snw141292 }
1086*4520Snw141292 
1087*4520Snw141292 /* Add another configuration to the configuration list */
Configlist_add(rp,dot)1088*4520Snw141292 struct config *Configlist_add(rp,dot)
1089*4520Snw141292 struct rule *rp;    /* The rule */
1090*4520Snw141292 int dot;            /* Index into the RHS of the rule where the dot goes */
1091*4520Snw141292 {
1092*4520Snw141292   struct config *cfp, model;
1093*4520Snw141292 
1094*4520Snw141292   assert( currentend!=0 );
1095*4520Snw141292   model.rp = rp;
1096*4520Snw141292   model.dot = dot;
1097*4520Snw141292   cfp = Configtable_find(&model);
1098*4520Snw141292   if( cfp==0 ){
1099*4520Snw141292     cfp = newconfig();
1100*4520Snw141292     cfp->rp = rp;
1101*4520Snw141292     cfp->dot = dot;
1102*4520Snw141292     cfp->fws = SetNew();
1103*4520Snw141292     cfp->stp = 0;
1104*4520Snw141292     cfp->fplp = cfp->bplp = 0;
1105*4520Snw141292     cfp->next = 0;
1106*4520Snw141292     cfp->bp = 0;
1107*4520Snw141292     *currentend = cfp;
1108*4520Snw141292     currentend = &cfp->next;
1109*4520Snw141292     Configtable_insert(cfp);
1110*4520Snw141292   }
1111*4520Snw141292   return cfp;
1112*4520Snw141292 }
1113*4520Snw141292 
1114*4520Snw141292 /* Add a basis configuration to the configuration list */
Configlist_addbasis(rp,dot)1115*4520Snw141292 struct config *Configlist_addbasis(rp,dot)
1116*4520Snw141292 struct rule *rp;
1117*4520Snw141292 int dot;
1118*4520Snw141292 {
1119*4520Snw141292   struct config *cfp, model;
1120*4520Snw141292 
1121*4520Snw141292   assert( basisend!=0 );
1122*4520Snw141292   assert( currentend!=0 );
1123*4520Snw141292   model.rp = rp;
1124*4520Snw141292   model.dot = dot;
1125*4520Snw141292   cfp = Configtable_find(&model);
1126*4520Snw141292   if( cfp==0 ){
1127*4520Snw141292     cfp = newconfig();
1128*4520Snw141292     cfp->rp = rp;
1129*4520Snw141292     cfp->dot = dot;
1130*4520Snw141292     cfp->fws = SetNew();
1131*4520Snw141292     cfp->stp = 0;
1132*4520Snw141292     cfp->fplp = cfp->bplp = 0;
1133*4520Snw141292     cfp->next = 0;
1134*4520Snw141292     cfp->bp = 0;
1135*4520Snw141292     *currentend = cfp;
1136*4520Snw141292     currentend = &cfp->next;
1137*4520Snw141292     *basisend = cfp;
1138*4520Snw141292     basisend = &cfp->bp;
1139*4520Snw141292     Configtable_insert(cfp);
1140*4520Snw141292   }
1141*4520Snw141292   return cfp;
1142*4520Snw141292 }
1143*4520Snw141292 
1144*4520Snw141292 /* Compute the closure of the configuration list */
Configlist_closure(lemp)1145*4520Snw141292 void Configlist_closure(lemp)
1146*4520Snw141292 struct lemon *lemp;
1147*4520Snw141292 {
1148*4520Snw141292   struct config *cfp, *newcfp;
1149*4520Snw141292   struct rule *rp, *newrp;
1150*4520Snw141292   struct symbol *sp, *xsp;
1151*4520Snw141292   int i, dot;
1152*4520Snw141292 
1153*4520Snw141292   assert( currentend!=0 );
1154*4520Snw141292   for(cfp=current; cfp; cfp=cfp->next){
1155*4520Snw141292     rp = cfp->rp;
1156*4520Snw141292     dot = cfp->dot;
1157*4520Snw141292     if( dot>=rp->nrhs ) continue;
1158*4520Snw141292     sp = rp->rhs[dot];
1159*4520Snw141292     if( sp->type==NONTERMINAL ){
1160*4520Snw141292       if( sp->rule==0 && sp!=lemp->errsym ){
1161*4520Snw141292         ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
1162*4520Snw141292           sp->name);
1163*4520Snw141292         lemp->errorcnt++;
1164*4520Snw141292       }
1165*4520Snw141292       for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
1166*4520Snw141292         newcfp = Configlist_add(newrp,0);
1167*4520Snw141292         for(i=dot+1; i<rp->nrhs; i++){
1168*4520Snw141292           xsp = rp->rhs[i];
1169*4520Snw141292           if( xsp->type==TERMINAL ){
1170*4520Snw141292             SetAdd(newcfp->fws,xsp->index);
1171*4520Snw141292             break;
1172*4520Snw141292 	  }else{
1173*4520Snw141292             SetUnion(newcfp->fws,xsp->firstset);
1174*4520Snw141292             if( xsp->lambda==B_FALSE ) break;
1175*4520Snw141292 	  }
1176*4520Snw141292 	}
1177*4520Snw141292         if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
1178*4520Snw141292       }
1179*4520Snw141292     }
1180*4520Snw141292   }
1181*4520Snw141292   return;
1182*4520Snw141292 }
1183*4520Snw141292 
1184*4520Snw141292 /* Sort the configuration list */
Configlist_sort()1185*4520Snw141292 void Configlist_sort(){
1186*4520Snw141292   current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp);
1187*4520Snw141292   currentend = 0;
1188*4520Snw141292   return;
1189*4520Snw141292 }
1190*4520Snw141292 
1191*4520Snw141292 /* Sort the basis configuration list */
Configlist_sortbasis()1192*4520Snw141292 void Configlist_sortbasis(){
1193*4520Snw141292   basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp);
1194*4520Snw141292   basisend = 0;
1195*4520Snw141292   return;
1196*4520Snw141292 }
1197*4520Snw141292 
1198*4520Snw141292 /* Return a pointer to the head of the configuration list and
1199*4520Snw141292 ** reset the list */
Configlist_return()1200*4520Snw141292 struct config *Configlist_return(){
1201*4520Snw141292   struct config *old;
1202*4520Snw141292   old = current;
1203*4520Snw141292   current = 0;
1204*4520Snw141292   currentend = 0;
1205*4520Snw141292   return old;
1206*4520Snw141292 }
1207*4520Snw141292 
1208*4520Snw141292 /* Return a pointer to the head of the configuration list and
1209*4520Snw141292 ** reset the list */
Configlist_basis()1210*4520Snw141292 struct config *Configlist_basis(){
1211*4520Snw141292   struct config *old;
1212*4520Snw141292   old = basis;
1213*4520Snw141292   basis = 0;
1214*4520Snw141292   basisend = 0;
1215*4520Snw141292   return old;
1216*4520Snw141292 }
1217*4520Snw141292 
1218*4520Snw141292 /* Free all elements of the given configuration list */
Configlist_eat(cfp)1219*4520Snw141292 void Configlist_eat(cfp)
1220*4520Snw141292 struct config *cfp;
1221*4520Snw141292 {
1222*4520Snw141292   struct config *nextcfp;
1223*4520Snw141292   for(; cfp; cfp=nextcfp){
1224*4520Snw141292     nextcfp = cfp->next;
1225*4520Snw141292     assert( cfp->fplp==0 );
1226*4520Snw141292     assert( cfp->bplp==0 );
1227*4520Snw141292     if( cfp->fws ) SetFree(cfp->fws);
1228*4520Snw141292     deleteconfig(cfp);
1229*4520Snw141292   }
1230*4520Snw141292   return;
1231*4520Snw141292 }
1232*4520Snw141292 /***************** From the file "error.c" *********************************/
1233*4520Snw141292 /*
1234*4520Snw141292 ** Code for printing error message.
1235*4520Snw141292 */
1236*4520Snw141292 
1237*4520Snw141292 /* Find a good place to break "msg" so that its length is at least "min"
1238*4520Snw141292 ** but no more than "max".  Make the point as close to max as possible.
1239*4520Snw141292 */
findbreak(msg,min,max)1240*4520Snw141292 static int findbreak(msg,min,max)
1241*4520Snw141292 char *msg;
1242*4520Snw141292 int min;
1243*4520Snw141292 int max;
1244*4520Snw141292 {
1245*4520Snw141292   int i,spot;
1246*4520Snw141292   char c;
1247*4520Snw141292   for(i=spot=min; i<=max; i++){
1248*4520Snw141292     c = msg[i];
1249*4520Snw141292     if( c=='\t' ) msg[i] = ' ';
1250*4520Snw141292     if( c=='\n' ){ msg[i] = ' '; spot = i; break; }
1251*4520Snw141292     if( c==0 ){ spot = i; break; }
1252*4520Snw141292     if( c=='-' && i<max-1 ) spot = i+1;
1253*4520Snw141292     if( c==' ' ) spot = i;
1254*4520Snw141292   }
1255*4520Snw141292   return spot;
1256*4520Snw141292 }
1257*4520Snw141292 
1258*4520Snw141292 /*
1259*4520Snw141292 ** The error message is split across multiple lines if necessary.  The
1260*4520Snw141292 ** splits occur at a space, if there is a space available near the end
1261*4520Snw141292 ** of the line.
1262*4520Snw141292 */
1263*4520Snw141292 #define ERRMSGSIZE  10000 /* Hope this is big enough.  No way to error check */
1264*4520Snw141292 #define LINEWIDTH      79 /* Max width of any output line */
1265*4520Snw141292 #define PREFIXLIMIT    30 /* Max width of the prefix on each line */
ErrorMsg(const char * filename,int lineno,const char * format,...)1266*4520Snw141292 void ErrorMsg(const char *filename, int lineno, const char *format, ...){
1267*4520Snw141292   char errmsg[ERRMSGSIZE];
1268*4520Snw141292   char prefix[PREFIXLIMIT+10];
1269*4520Snw141292   int errmsgsize;
1270*4520Snw141292   int prefixsize;
1271*4520Snw141292   int availablewidth;
1272*4520Snw141292   va_list ap;
1273*4520Snw141292   int end, restart, base;
1274*4520Snw141292 
1275*4520Snw141292   va_start(ap, format);
1276*4520Snw141292   /* Prepare a prefix to be prepended to every output line */
1277*4520Snw141292   if( lineno>0 ){
1278*4520Snw141292     sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno);
1279*4520Snw141292   }else{
1280*4520Snw141292     sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename);
1281*4520Snw141292   }
1282*4520Snw141292   prefixsize = strlen(prefix);
1283*4520Snw141292   availablewidth = LINEWIDTH - prefixsize;
1284*4520Snw141292 
1285*4520Snw141292   /* Generate the error message */
1286*4520Snw141292   vsprintf(errmsg,format,ap);
1287*4520Snw141292   va_end(ap);
1288*4520Snw141292   errmsgsize = strlen(errmsg);
1289*4520Snw141292   /* Remove trailing '\n's from the error message. */
1290*4520Snw141292   while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){
1291*4520Snw141292      errmsg[--errmsgsize] = 0;
1292*4520Snw141292   }
1293*4520Snw141292 
1294*4520Snw141292   /* Print the error message */
1295*4520Snw141292   base = 0;
1296*4520Snw141292   while( errmsg[base]!=0 ){
1297*4520Snw141292     end = restart = findbreak(&errmsg[base],0,availablewidth);
1298*4520Snw141292     restart += base;
1299*4520Snw141292     while( errmsg[restart]==' ' ) restart++;
1300*4520Snw141292     fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]);
1301*4520Snw141292     base = restart;
1302*4520Snw141292   }
1303*4520Snw141292 }
1304*4520Snw141292 /**************** From the file "main.c" ************************************/
1305*4520Snw141292 /*
1306*4520Snw141292 ** Main program file for the LEMON parser generator.
1307*4520Snw141292 */
1308*4520Snw141292 
1309*4520Snw141292 /* Report an out-of-memory condition and abort.  This function
1310*4520Snw141292 ** is used mostly by the "MemoryCheck" macro in struct.h
1311*4520Snw141292 */
memory_error()1312*4520Snw141292 void memory_error(){
1313*4520Snw141292   fprintf(stderr,"Out of memory.  Aborting...\n");
1314*4520Snw141292   exit(1);
1315*4520Snw141292 }
1316*4520Snw141292 
1317*4520Snw141292 
1318*4520Snw141292 /* The main program.  Parse the command line and do it... */
main(argc,argv)1319*4520Snw141292 int main(argc,argv)
1320*4520Snw141292 int argc;
1321*4520Snw141292 char **argv;
1322*4520Snw141292 {
1323*4520Snw141292   static int version = 0;
1324*4520Snw141292   static int rpflag = 0;
1325*4520Snw141292   static int basisflag = 0;
1326*4520Snw141292   static int compress = 0;
1327*4520Snw141292   static int quiet = 0;
1328*4520Snw141292   static int statistics = 0;
1329*4520Snw141292   static int mhflag = 0;
1330*4520Snw141292   static struct s_options options[] = {
1331*4520Snw141292     {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
1332*4520Snw141292     {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
1333*4520Snw141292     {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
1334*4520Snw141292     {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"},
1335*4520Snw141292     {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
1336*4520Snw141292     {OPT_FLAG, "s", (char*)&statistics, "Print parser stats to standard output."},
1337*4520Snw141292     {OPT_FLAG, "x", (char*)&version, "Print the version number."},
1338*4520Snw141292     {OPT_FLAG,0,0,0}
1339*4520Snw141292   };
1340*4520Snw141292   int i;
1341*4520Snw141292   struct lemon lem;
1342*4520Snw141292 
1343*4520Snw141292   OptInit(argv,options,stderr);
1344*4520Snw141292   if( version ){
1345*4520Snw141292      printf("Lemon version 1.0\n");
1346*4520Snw141292      exit(0);
1347*4520Snw141292   }
1348*4520Snw141292   if( OptNArgs()!=1 ){
1349*4520Snw141292     fprintf(stderr,"Exactly one filename argument is required.\n");
1350*4520Snw141292     exit(1);
1351*4520Snw141292   }
1352*4520Snw141292   lem.errorcnt = 0;
1353*4520Snw141292 
1354*4520Snw141292   /* Initialize the machine */
1355*4520Snw141292   Strsafe_init();
1356*4520Snw141292   Symbol_init();
1357*4520Snw141292   State_init();
1358*4520Snw141292   lem.argv0 = argv[0];
1359*4520Snw141292   lem.filename = OptArg(0);
1360*4520Snw141292   lem.basisflag = basisflag;
1361*4520Snw141292   lem.has_fallback = 0;
1362*4520Snw141292   lem.nconflict = 0;
1363*4520Snw141292   lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
1364*4520Snw141292   lem.vartype = 0;
1365*4520Snw141292   lem.stacksize = 0;
1366*4520Snw141292   lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
1367*4520Snw141292      lem.tokenprefix = lem.outname = lem.extracode = 0;
1368*4520Snw141292   lem.vardest = 0;
1369*4520Snw141292   lem.tablesize = 0;
1370*4520Snw141292   Symbol_new("$");
1371*4520Snw141292   lem.errsym = Symbol_new("error");
1372*4520Snw141292 
1373*4520Snw141292   /* Parse the input file */
1374*4520Snw141292   Parse(&lem);
1375*4520Snw141292   if( lem.errorcnt ) exit(lem.errorcnt);
1376*4520Snw141292   if( lem.rule==0 ){
1377*4520Snw141292     fprintf(stderr,"Empty grammar.\n");
1378*4520Snw141292     exit(1);
1379*4520Snw141292   }
1380*4520Snw141292 
1381*4520Snw141292   /* Count and index the symbols of the grammar */
1382*4520Snw141292   lem.nsymbol = Symbol_count();
1383*4520Snw141292   Symbol_new("{default}");
1384*4520Snw141292   lem.symbols = Symbol_arrayof();
1385*4520Snw141292   for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
1386*4520Snw141292   qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
1387*4520Snw141292         (int(*)())Symbolcmpp);
1388*4520Snw141292   for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
1389*4520Snw141292   for(i=1; isupper(lem.symbols[i]->name[0]); i++);
1390*4520Snw141292   lem.nterminal = i;
1391*4520Snw141292 
1392*4520Snw141292   /* Generate a reprint of the grammar, if requested on the command line */
1393*4520Snw141292   if( rpflag ){
1394*4520Snw141292     Reprint(&lem);
1395*4520Snw141292   }else{
1396*4520Snw141292     /* Initialize the size for all follow and first sets */
1397*4520Snw141292     SetSize(lem.nterminal);
1398*4520Snw141292 
1399*4520Snw141292     /* Find the precedence for every production rule (that has one) */
1400*4520Snw141292     FindRulePrecedences(&lem);
1401*4520Snw141292 
1402*4520Snw141292     /* Compute the lambda-nonterminals and the first-sets for every
1403*4520Snw141292     ** nonterminal */
1404*4520Snw141292     FindFirstSets(&lem);
1405*4520Snw141292 
1406*4520Snw141292     /* Compute all LR(0) states.  Also record follow-set propagation
1407*4520Snw141292     ** links so that the follow-set can be computed later */
1408*4520Snw141292     lem.nstate = 0;
1409*4520Snw141292     FindStates(&lem);
1410*4520Snw141292     lem.sorted = State_arrayof();
1411*4520Snw141292 
1412*4520Snw141292     /* Tie up loose ends on the propagation links */
1413*4520Snw141292     FindLinks(&lem);
1414*4520Snw141292 
1415*4520Snw141292     /* Compute the follow set of every reducible configuration */
1416*4520Snw141292     FindFollowSets(&lem);
1417*4520Snw141292 
1418*4520Snw141292     /* Compute the action tables */
1419*4520Snw141292     FindActions(&lem);
1420*4520Snw141292 
1421*4520Snw141292     /* Compress the action tables */
1422*4520Snw141292     if( compress==0 ) CompressTables(&lem);
1423*4520Snw141292 
1424*4520Snw141292     /* Generate a report of the parser generated.  (the "y.output" file) */
1425*4520Snw141292     if( !quiet ) ReportOutput(&lem);
1426*4520Snw141292 
1427*4520Snw141292     /* Generate the source code for the parser */
1428*4520Snw141292     ReportTable(&lem, mhflag);
1429*4520Snw141292 
1430*4520Snw141292     /* Produce a header file for use by the scanner.  (This step is
1431*4520Snw141292     ** omitted if the "-m" option is used because makeheaders will
1432*4520Snw141292     ** generate the file for us.) */
1433*4520Snw141292     if( !mhflag ) ReportHeader(&lem);
1434*4520Snw141292   }
1435*4520Snw141292   if( statistics ){
1436*4520Snw141292     printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
1437*4520Snw141292       lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
1438*4520Snw141292     printf("                   %d states, %d parser table entries, %d conflicts\n",
1439*4520Snw141292       lem.nstate, lem.tablesize, lem.nconflict);
1440*4520Snw141292   }
1441*4520Snw141292   if( lem.nconflict ){
1442*4520Snw141292     fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
1443*4520Snw141292   }
1444*4520Snw141292   exit(lem.errorcnt + lem.nconflict);
1445*4520Snw141292   return (lem.errorcnt + lem.nconflict);
1446*4520Snw141292 }
1447*4520Snw141292 /******************** From the file "msort.c" *******************************/
1448*4520Snw141292 /*
1449*4520Snw141292 ** A generic merge-sort program.
1450*4520Snw141292 **
1451*4520Snw141292 ** USAGE:
1452*4520Snw141292 ** Let "ptr" be a pointer to some structure which is at the head of
1453*4520Snw141292 ** a null-terminated list.  Then to sort the list call:
1454*4520Snw141292 **
1455*4520Snw141292 **     ptr = msort(ptr,&(ptr->next),cmpfnc);
1456*4520Snw141292 **
1457*4520Snw141292 ** In the above, "cmpfnc" is a pointer to a function which compares
1458*4520Snw141292 ** two instances of the structure and returns an integer, as in
1459*4520Snw141292 ** strcmp.  The second argument is a pointer to the pointer to the
1460*4520Snw141292 ** second element of the linked list.  This address is used to compute
1461*4520Snw141292 ** the offset to the "next" field within the structure.  The offset to
1462*4520Snw141292 ** the "next" field must be constant for all structures in the list.
1463*4520Snw141292 **
1464*4520Snw141292 ** The function returns a new pointer which is the head of the list
1465*4520Snw141292 ** after sorting.
1466*4520Snw141292 **
1467*4520Snw141292 ** ALGORITHM:
1468*4520Snw141292 ** Merge-sort.
1469*4520Snw141292 */
1470*4520Snw141292 
1471*4520Snw141292 /*
1472*4520Snw141292 ** Return a pointer to the next structure in the linked list.
1473*4520Snw141292 */
1474*4520Snw141292 #define NEXT(A) (*(char**)(((unsigned long)A)+offset))
1475*4520Snw141292 
1476*4520Snw141292 /*
1477*4520Snw141292 ** Inputs:
1478*4520Snw141292 **   a:       A sorted, null-terminated linked list.  (May be null).
1479*4520Snw141292 **   b:       A sorted, null-terminated linked list.  (May be null).
1480*4520Snw141292 **   cmp:     A pointer to the comparison function.
1481*4520Snw141292 **   offset:  Offset in the structure to the "next" field.
1482*4520Snw141292 **
1483*4520Snw141292 ** Return Value:
1484*4520Snw141292 **   A pointer to the head of a sorted list containing the elements
1485*4520Snw141292 **   of both a and b.
1486*4520Snw141292 **
1487*4520Snw141292 ** Side effects:
1488*4520Snw141292 **   The "next" pointers for elements in the lists a and b are
1489*4520Snw141292 **   changed.
1490*4520Snw141292 */
merge(a,b,cmp,offset)1491*4520Snw141292 static char *merge(a,b,cmp,offset)
1492*4520Snw141292 char *a;
1493*4520Snw141292 char *b;
1494*4520Snw141292 int (*cmp)();
1495*4520Snw141292 int offset;
1496*4520Snw141292 {
1497*4520Snw141292   char *ptr, *head;
1498*4520Snw141292 
1499*4520Snw141292   if( a==0 ){
1500*4520Snw141292     head = b;
1501*4520Snw141292   }else if( b==0 ){
1502*4520Snw141292     head = a;
1503*4520Snw141292   }else{
1504*4520Snw141292     if( (*cmp)(a,b)<0 ){
1505*4520Snw141292       ptr = a;
1506*4520Snw141292       a = NEXT(a);
1507*4520Snw141292     }else{
1508*4520Snw141292       ptr = b;
1509*4520Snw141292       b = NEXT(b);
1510*4520Snw141292     }
1511*4520Snw141292     head = ptr;
1512*4520Snw141292     while( a && b ){
1513*4520Snw141292       if( (*cmp)(a,b)<0 ){
1514*4520Snw141292         NEXT(ptr) = a;
1515*4520Snw141292         ptr = a;
1516*4520Snw141292         a = NEXT(a);
1517*4520Snw141292       }else{
1518*4520Snw141292         NEXT(ptr) = b;
1519*4520Snw141292         ptr = b;
1520*4520Snw141292         b = NEXT(b);
1521*4520Snw141292       }
1522*4520Snw141292     }
1523*4520Snw141292     if( a ) NEXT(ptr) = a;
1524*4520Snw141292     else    NEXT(ptr) = b;
1525*4520Snw141292   }
1526*4520Snw141292   return head;
1527*4520Snw141292 }
1528*4520Snw141292 
1529*4520Snw141292 /*
1530*4520Snw141292 ** Inputs:
1531*4520Snw141292 **   list:      Pointer to a singly-linked list of structures.
1532*4520Snw141292 **   next:      Pointer to pointer to the second element of the list.
1533*4520Snw141292 **   cmp:       A comparison function.
1534*4520Snw141292 **
1535*4520Snw141292 ** Return Value:
1536*4520Snw141292 **   A pointer to the head of a sorted list containing the elements
1537*4520Snw141292 **   orginally in list.
1538*4520Snw141292 **
1539*4520Snw141292 ** Side effects:
1540*4520Snw141292 **   The "next" pointers for elements in list are changed.
1541*4520Snw141292 */
1542*4520Snw141292 #define LISTSIZE 30
msort(list,next,cmp)1543*4520Snw141292 char *msort(list,next,cmp)
1544*4520Snw141292 char *list;
1545*4520Snw141292 char **next;
1546*4520Snw141292 int (*cmp)();
1547*4520Snw141292 {
1548*4520Snw141292   unsigned long offset;
1549*4520Snw141292   char *ep;
1550*4520Snw141292   char *set[LISTSIZE];
1551*4520Snw141292   int i;
1552*4520Snw141292   offset = (unsigned long)next - (unsigned long)list;
1553*4520Snw141292   for(i=0; i<LISTSIZE; i++) set[i] = 0;
1554*4520Snw141292   while( list ){
1555*4520Snw141292     ep = list;
1556*4520Snw141292     list = NEXT(list);
1557*4520Snw141292     NEXT(ep) = 0;
1558*4520Snw141292     for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
1559*4520Snw141292       ep = merge(ep,set[i],cmp,offset);
1560*4520Snw141292       set[i] = 0;
1561*4520Snw141292     }
1562*4520Snw141292     set[i] = ep;
1563*4520Snw141292   }
1564*4520Snw141292   ep = 0;
1565*4520Snw141292   for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset);
1566*4520Snw141292   return ep;
1567*4520Snw141292 }
1568*4520Snw141292 /************************ From the file "option.c" **************************/
1569*4520Snw141292 static char **argv;
1570*4520Snw141292 static struct s_options *op;
1571*4520Snw141292 static FILE *errstream;
1572*4520Snw141292 
1573*4520Snw141292 #define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
1574*4520Snw141292 
1575*4520Snw141292 /*
1576*4520Snw141292 ** Print the command line with a carrot pointing to the k-th character
1577*4520Snw141292 ** of the n-th field.
1578*4520Snw141292 */
errline(n,k,err)1579*4520Snw141292 static void errline(n,k,err)
1580*4520Snw141292 int n;
1581*4520Snw141292 int k;
1582*4520Snw141292 FILE *err;
1583*4520Snw141292 {
1584*4520Snw141292   int spcnt, i;
1585*4520Snw141292   spcnt = 0;
1586*4520Snw141292   if( argv[0] ) fprintf(err,"%s",argv[0]);
1587*4520Snw141292   spcnt = strlen(argv[0]) + 1;
1588*4520Snw141292   for(i=1; i<n && argv[i]; i++){
1589*4520Snw141292     fprintf(err," %s",argv[i]);
1590*4520Snw141292     spcnt += strlen(argv[i]+1);
1591*4520Snw141292   }
1592*4520Snw141292   spcnt += k;
1593*4520Snw141292   for(; argv[i]; i++) fprintf(err," %s",argv[i]);
1594*4520Snw141292   if( spcnt<20 ){
1595*4520Snw141292     fprintf(err,"\n%*s^-- here\n",spcnt,"");
1596*4520Snw141292   }else{
1597*4520Snw141292     fprintf(err,"\n%*shere --^\n",spcnt-7,"");
1598*4520Snw141292   }
1599*4520Snw141292 }
1600*4520Snw141292 
1601*4520Snw141292 /*
1602*4520Snw141292 ** Return the index of the N-th non-switch argument.  Return -1
1603*4520Snw141292 ** if N is out of range.
1604*4520Snw141292 */
argindex(n)1605*4520Snw141292 static int argindex(n)
1606*4520Snw141292 int n;
1607*4520Snw141292 {
1608*4520Snw141292   int i;
1609*4520Snw141292   int dashdash = 0;
1610*4520Snw141292   if( argv!=0 && *argv!=0 ){
1611*4520Snw141292     for(i=1; argv[i]; i++){
1612*4520Snw141292       if( dashdash || !ISOPT(argv[i]) ){
1613*4520Snw141292         if( n==0 ) return i;
1614*4520Snw141292         n--;
1615*4520Snw141292       }
1616*4520Snw141292       if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1617*4520Snw141292     }
1618*4520Snw141292   }
1619*4520Snw141292   return -1;
1620*4520Snw141292 }
1621*4520Snw141292 
1622*4520Snw141292 static char emsg[] = "Command line syntax error: ";
1623*4520Snw141292 
1624*4520Snw141292 /*
1625*4520Snw141292 ** Process a flag command line argument.
1626*4520Snw141292 */
handleflags(i,err)1627*4520Snw141292 static int handleflags(i,err)
1628*4520Snw141292 int i;
1629*4520Snw141292 FILE *err;
1630*4520Snw141292 {
1631*4520Snw141292   int v;
1632*4520Snw141292   int errcnt = 0;
1633*4520Snw141292   int j;
1634*4520Snw141292   for(j=0; op[j].label; j++){
1635*4520Snw141292     if( strcmp(&argv[i][1],op[j].label)==0 ) break;
1636*4520Snw141292   }
1637*4520Snw141292   v = argv[i][0]=='-' ? 1 : 0;
1638*4520Snw141292   if( op[j].label==0 ){
1639*4520Snw141292     if( err ){
1640*4520Snw141292       fprintf(err,"%sundefined option.\n",emsg);
1641*4520Snw141292       errline(i,1,err);
1642*4520Snw141292     }
1643*4520Snw141292     errcnt++;
1644*4520Snw141292   }else if( op[j].type==OPT_FLAG ){
1645*4520Snw141292     *((int*)op[j].arg) = v;
1646*4520Snw141292   }else if( op[j].type==OPT_FFLAG ){
1647*4520Snw141292     (*(void(*)())(op[j].arg))(v);
1648*4520Snw141292   }else{
1649*4520Snw141292     if( err ){
1650*4520Snw141292       fprintf(err,"%smissing argument on switch.\n",emsg);
1651*4520Snw141292       errline(i,1,err);
1652*4520Snw141292     }
1653*4520Snw141292     errcnt++;
1654*4520Snw141292   }
1655*4520Snw141292   return errcnt;
1656*4520Snw141292 }
1657*4520Snw141292 
1658*4520Snw141292 /*
1659*4520Snw141292 ** Process a command line switch which has an argument.
1660*4520Snw141292 */
handleswitch(i,err)1661*4520Snw141292 static int handleswitch(i,err)
1662*4520Snw141292 int i;
1663*4520Snw141292 FILE *err;
1664*4520Snw141292 {
1665*4520Snw141292   int lv = 0;
1666*4520Snw141292   double dv = 0.0;
1667*4520Snw141292   char *sv = 0, *end;
1668*4520Snw141292   char *cp;
1669*4520Snw141292   int j;
1670*4520Snw141292   int errcnt = 0;
1671*4520Snw141292   cp = strchr(argv[i],'=');
1672*4520Snw141292   *cp = 0;
1673*4520Snw141292   for(j=0; op[j].label; j++){
1674*4520Snw141292     if( strcmp(argv[i],op[j].label)==0 ) break;
1675*4520Snw141292   }
1676*4520Snw141292   *cp = '=';
1677*4520Snw141292   if( op[j].label==0 ){
1678*4520Snw141292     if( err ){
1679*4520Snw141292       fprintf(err,"%sundefined option.\n",emsg);
1680*4520Snw141292       errline(i,0,err);
1681*4520Snw141292     }
1682*4520Snw141292     errcnt++;
1683*4520Snw141292   }else{
1684*4520Snw141292     cp++;
1685*4520Snw141292     switch( op[j].type ){
1686*4520Snw141292       case OPT_FLAG:
1687*4520Snw141292       case OPT_FFLAG:
1688*4520Snw141292         if( err ){
1689*4520Snw141292           fprintf(err,"%soption requires an argument.\n",emsg);
1690*4520Snw141292           errline(i,0,err);
1691*4520Snw141292         }
1692*4520Snw141292         errcnt++;
1693*4520Snw141292         break;
1694*4520Snw141292       case OPT_DBL:
1695*4520Snw141292       case OPT_FDBL:
1696*4520Snw141292         dv = strtod(cp,&end);
1697*4520Snw141292         if( *end ){
1698*4520Snw141292           if( err ){
1699*4520Snw141292             fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
1700*4520Snw141292             errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
1701*4520Snw141292           }
1702*4520Snw141292           errcnt++;
1703*4520Snw141292         }
1704*4520Snw141292         break;
1705*4520Snw141292       case OPT_INT:
1706*4520Snw141292       case OPT_FINT:
1707*4520Snw141292         lv = strtol(cp,&end,0);
1708*4520Snw141292         if( *end ){
1709*4520Snw141292           if( err ){
1710*4520Snw141292             fprintf(err,"%sillegal character in integer argument.\n",emsg);
1711*4520Snw141292             errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
1712*4520Snw141292           }
1713*4520Snw141292           errcnt++;
1714*4520Snw141292         }
1715*4520Snw141292         break;
1716*4520Snw141292       case OPT_STR:
1717*4520Snw141292       case OPT_FSTR:
1718*4520Snw141292         sv = cp;
1719*4520Snw141292         break;
1720*4520Snw141292     }
1721*4520Snw141292     switch( op[j].type ){
1722*4520Snw141292       case OPT_FLAG:
1723*4520Snw141292       case OPT_FFLAG:
1724*4520Snw141292         break;
1725*4520Snw141292       case OPT_DBL:
1726*4520Snw141292         *(double*)(op[j].arg) = dv;
1727*4520Snw141292         break;
1728*4520Snw141292       case OPT_FDBL:
1729*4520Snw141292         (*(void(*)())(op[j].arg))(dv);
1730*4520Snw141292         break;
1731*4520Snw141292       case OPT_INT:
1732*4520Snw141292         *(int*)(op[j].arg) = lv;
1733*4520Snw141292         break;
1734*4520Snw141292       case OPT_FINT:
1735*4520Snw141292         (*(void(*)())(op[j].arg))((int)lv);
1736*4520Snw141292         break;
1737*4520Snw141292       case OPT_STR:
1738*4520Snw141292         *(char**)(op[j].arg) = sv;
1739*4520Snw141292         break;
1740*4520Snw141292       case OPT_FSTR:
1741*4520Snw141292         (*(void(*)())(op[j].arg))(sv);
1742*4520Snw141292         break;
1743*4520Snw141292     }
1744*4520Snw141292   }
1745*4520Snw141292   return errcnt;
1746*4520Snw141292 }
1747*4520Snw141292 
OptInit(a,o,err)1748*4520Snw141292 int OptInit(a,o,err)
1749*4520Snw141292 char **a;
1750*4520Snw141292 struct s_options *o;
1751*4520Snw141292 FILE *err;
1752*4520Snw141292 {
1753*4520Snw141292   int errcnt = 0;
1754*4520Snw141292   argv = a;
1755*4520Snw141292   op = o;
1756*4520Snw141292   errstream = err;
1757*4520Snw141292   if( argv && *argv && op ){
1758*4520Snw141292     int i;
1759*4520Snw141292     for(i=1; argv[i]; i++){
1760*4520Snw141292       if( argv[i][0]=='+' || argv[i][0]=='-' ){
1761*4520Snw141292         errcnt += handleflags(i,err);
1762*4520Snw141292       }else if( strchr(argv[i],'=') ){
1763*4520Snw141292         errcnt += handleswitch(i,err);
1764*4520Snw141292       }
1765*4520Snw141292     }
1766*4520Snw141292   }
1767*4520Snw141292   if( errcnt>0 ){
1768*4520Snw141292     fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
1769*4520Snw141292     OptPrint();
1770*4520Snw141292     exit(1);
1771*4520Snw141292   }
1772*4520Snw141292   return 0;
1773*4520Snw141292 }
1774*4520Snw141292 
OptNArgs()1775*4520Snw141292 int OptNArgs(){
1776*4520Snw141292   int cnt = 0;
1777*4520Snw141292   int dashdash = 0;
1778*4520Snw141292   int i;
1779*4520Snw141292   if( argv!=0 && argv[0]!=0 ){
1780*4520Snw141292     for(i=1; argv[i]; i++){
1781*4520Snw141292       if( dashdash || !ISOPT(argv[i]) ) cnt++;
1782*4520Snw141292       if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1783*4520Snw141292     }
1784*4520Snw141292   }
1785*4520Snw141292   return cnt;
1786*4520Snw141292 }
1787*4520Snw141292 
OptArg(n)1788*4520Snw141292 char *OptArg(n)
1789*4520Snw141292 int n;
1790*4520Snw141292 {
1791*4520Snw141292   int i;
1792*4520Snw141292   i = argindex(n);
1793*4520Snw141292   return i>=0 ? argv[i] : 0;
1794*4520Snw141292 }
1795*4520Snw141292 
OptErr(n)1796*4520Snw141292 void OptErr(n)
1797*4520Snw141292 int n;
1798*4520Snw141292 {
1799*4520Snw141292   int i;
1800*4520Snw141292   i = argindex(n);
1801*4520Snw141292   if( i>=0 ) errline(i,0,errstream);
1802*4520Snw141292 }
1803*4520Snw141292 
OptPrint()1804*4520Snw141292 void OptPrint(){
1805*4520Snw141292   int i;
1806*4520Snw141292   int max, len;
1807*4520Snw141292   max = 0;
1808*4520Snw141292   for(i=0; op[i].label; i++){
1809*4520Snw141292     len = strlen(op[i].label) + 1;
1810*4520Snw141292     switch( op[i].type ){
1811*4520Snw141292       case OPT_FLAG:
1812*4520Snw141292       case OPT_FFLAG:
1813*4520Snw141292         break;
1814*4520Snw141292       case OPT_INT:
1815*4520Snw141292       case OPT_FINT:
1816*4520Snw141292         len += 9;       /* length of "<integer>" */
1817*4520Snw141292         break;
1818*4520Snw141292       case OPT_DBL:
1819*4520Snw141292       case OPT_FDBL:
1820*4520Snw141292         len += 6;       /* length of "<real>" */
1821*4520Snw141292         break;
1822*4520Snw141292       case OPT_STR:
1823*4520Snw141292       case OPT_FSTR:
1824*4520Snw141292         len += 8;       /* length of "<string>" */
1825*4520Snw141292         break;
1826*4520Snw141292     }
1827*4520Snw141292     if( len>max ) max = len;
1828*4520Snw141292   }
1829*4520Snw141292   for(i=0; op[i].label; i++){
1830*4520Snw141292     switch( op[i].type ){
1831*4520Snw141292       case OPT_FLAG:
1832*4520Snw141292       case OPT_FFLAG:
1833*4520Snw141292         fprintf(errstream,"  -%-*s  %s\n",max,op[i].label,op[i].message);
1834*4520Snw141292         break;
1835*4520Snw141292       case OPT_INT:
1836*4520Snw141292       case OPT_FINT:
1837*4520Snw141292         fprintf(errstream,"  %s=<integer>%*s  %s\n",op[i].label,
1838*4520Snw141292           (int)(max-strlen(op[i].label)-9),"",op[i].message);
1839*4520Snw141292         break;
1840*4520Snw141292       case OPT_DBL:
1841*4520Snw141292       case OPT_FDBL:
1842*4520Snw141292         fprintf(errstream,"  %s=<real>%*s  %s\n",op[i].label,
1843*4520Snw141292           (int)(max-strlen(op[i].label)-6),"",op[i].message);
1844*4520Snw141292         break;
1845*4520Snw141292       case OPT_STR:
1846*4520Snw141292       case OPT_FSTR:
1847*4520Snw141292         fprintf(errstream,"  %s=<string>%*s  %s\n",op[i].label,
1848*4520Snw141292           (int)(max-strlen(op[i].label)-8),"",op[i].message);
1849*4520Snw141292         break;
1850*4520Snw141292     }
1851*4520Snw141292   }
1852*4520Snw141292 }
1853*4520Snw141292 /*********************** From the file "parse.c" ****************************/
1854*4520Snw141292 /*
1855*4520Snw141292 ** Input file parser for the LEMON parser generator.
1856*4520Snw141292 */
1857*4520Snw141292 
1858*4520Snw141292 /* The state of the parser */
1859*4520Snw141292 struct pstate {
1860*4520Snw141292   char *filename;       /* Name of the input file */
1861*4520Snw141292   int tokenlineno;      /* Linenumber at which current token starts */
1862*4520Snw141292   int errorcnt;         /* Number of errors so far */
1863*4520Snw141292   char *tokenstart;     /* Text of current token */
1864*4520Snw141292   struct lemon *gp;     /* Global state vector */
1865*4520Snw141292   enum e_state {
1866*4520Snw141292     INITIALIZE,
1867*4520Snw141292     WAITING_FOR_DECL_OR_RULE,
1868*4520Snw141292     WAITING_FOR_DECL_KEYWORD,
1869*4520Snw141292     WAITING_FOR_DECL_ARG,
1870*4520Snw141292     WAITING_FOR_PRECEDENCE_SYMBOL,
1871*4520Snw141292     WAITING_FOR_ARROW,
1872*4520Snw141292     IN_RHS,
1873*4520Snw141292     LHS_ALIAS_1,
1874*4520Snw141292     LHS_ALIAS_2,
1875*4520Snw141292     LHS_ALIAS_3,
1876*4520Snw141292     RHS_ALIAS_1,
1877*4520Snw141292     RHS_ALIAS_2,
1878*4520Snw141292     PRECEDENCE_MARK_1,
1879*4520Snw141292     PRECEDENCE_MARK_2,
1880*4520Snw141292     RESYNC_AFTER_RULE_ERROR,
1881*4520Snw141292     RESYNC_AFTER_DECL_ERROR,
1882*4520Snw141292     WAITING_FOR_DESTRUCTOR_SYMBOL,
1883*4520Snw141292     WAITING_FOR_DATATYPE_SYMBOL,
1884*4520Snw141292     WAITING_FOR_FALLBACK_ID
1885*4520Snw141292   } state;                   /* The state of the parser */
1886*4520Snw141292   struct symbol *fallback;   /* The fallback token */
1887*4520Snw141292   struct symbol *lhs;        /* Left-hand side of current rule */
1888*4520Snw141292   char *lhsalias;            /* Alias for the LHS */
1889*4520Snw141292   int nrhs;                  /* Number of right-hand side symbols seen */
1890*4520Snw141292   struct symbol *rhs[MAXRHS];  /* RHS symbols */
1891*4520Snw141292   char *alias[MAXRHS];       /* Aliases for each RHS symbol (or NULL) */
1892*4520Snw141292   struct rule *prevrule;     /* Previous rule parsed */
1893*4520Snw141292   char *declkeyword;         /* Keyword of a declaration */
1894*4520Snw141292   char **declargslot;        /* Where the declaration argument should be put */
1895*4520Snw141292   int *decllnslot;           /* Where the declaration linenumber is put */
1896*4520Snw141292   enum e_assoc declassoc;    /* Assign this association to decl arguments */
1897*4520Snw141292   int preccounter;           /* Assign this precedence to decl arguments */
1898*4520Snw141292   struct rule *firstrule;    /* Pointer to first rule in the grammar */
1899*4520Snw141292   struct rule *lastrule;     /* Pointer to the most recently parsed rule */
1900*4520Snw141292 };
1901*4520Snw141292 
1902*4520Snw141292 /* Parse a single token */
parseonetoken(psp)1903*4520Snw141292 static void parseonetoken(psp)
1904*4520Snw141292 struct pstate *psp;
1905*4520Snw141292 {
1906*4520Snw141292   char *x;
1907*4520Snw141292   x = Strsafe(psp->tokenstart);     /* Save the token permanently */
1908*4520Snw141292 #if 0
1909*4520Snw141292   printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
1910*4520Snw141292     x,psp->state);
1911*4520Snw141292 #endif
1912*4520Snw141292   switch( psp->state ){
1913*4520Snw141292     case INITIALIZE:
1914*4520Snw141292       psp->prevrule = 0;
1915*4520Snw141292       psp->preccounter = 0;
1916*4520Snw141292       psp->firstrule = psp->lastrule = 0;
1917*4520Snw141292       psp->gp->nrule = 0;
1918*4520Snw141292       /* Fall thru to next case */
1919*4520Snw141292     case WAITING_FOR_DECL_OR_RULE:
1920*4520Snw141292       if( x[0]=='%' ){
1921*4520Snw141292         psp->state = WAITING_FOR_DECL_KEYWORD;
1922*4520Snw141292       }else if( islower(x[0]) ){
1923*4520Snw141292         psp->lhs = Symbol_new(x);
1924*4520Snw141292         psp->nrhs = 0;
1925*4520Snw141292         psp->lhsalias = 0;
1926*4520Snw141292         psp->state = WAITING_FOR_ARROW;
1927*4520Snw141292       }else if( x[0]=='{' ){
1928*4520Snw141292         if( psp->prevrule==0 ){
1929*4520Snw141292           ErrorMsg(psp->filename,psp->tokenlineno,
1930*4520Snw141292 "There is not prior rule opon which to attach the code \
1931*4520Snw141292 fragment which begins on this line.");
1932*4520Snw141292           psp->errorcnt++;
1933*4520Snw141292 	}else if( psp->prevrule->code!=0 ){
1934*4520Snw141292           ErrorMsg(psp->filename,psp->tokenlineno,
1935*4520Snw141292 "Code fragment beginning on this line is not the first \
1936*4520Snw141292 to follow the previous rule.");
1937*4520Snw141292           psp->errorcnt++;
1938*4520Snw141292         }else{
1939*4520Snw141292           psp->prevrule->line = psp->tokenlineno;
1940*4520Snw141292           psp->prevrule->code = &x[1];
1941*4520Snw141292 	}
1942*4520Snw141292       }else if( x[0]=='[' ){
1943*4520Snw141292         psp->state = PRECEDENCE_MARK_1;
1944*4520Snw141292       }else{
1945*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
1946*4520Snw141292           "Token \"%s\" should be either \"%%\" or a nonterminal name.",
1947*4520Snw141292           x);
1948*4520Snw141292         psp->errorcnt++;
1949*4520Snw141292       }
1950*4520Snw141292       break;
1951*4520Snw141292     case PRECEDENCE_MARK_1:
1952*4520Snw141292       if( !isupper(x[0]) ){
1953*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
1954*4520Snw141292           "The precedence symbol must be a terminal.");
1955*4520Snw141292         psp->errorcnt++;
1956*4520Snw141292       }else if( psp->prevrule==0 ){
1957*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
1958*4520Snw141292           "There is no prior rule to assign precedence \"[%s]\".",x);
1959*4520Snw141292         psp->errorcnt++;
1960*4520Snw141292       }else if( psp->prevrule->precsym!=0 ){
1961*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
1962*4520Snw141292 "Precedence mark on this line is not the first \
1963*4520Snw141292 to follow the previous rule.");
1964*4520Snw141292         psp->errorcnt++;
1965*4520Snw141292       }else{
1966*4520Snw141292         psp->prevrule->precsym = Symbol_new(x);
1967*4520Snw141292       }
1968*4520Snw141292       psp->state = PRECEDENCE_MARK_2;
1969*4520Snw141292       break;
1970*4520Snw141292     case PRECEDENCE_MARK_2:
1971*4520Snw141292       if( x[0]!=']' ){
1972*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
1973*4520Snw141292           "Missing \"]\" on precedence mark.");
1974*4520Snw141292         psp->errorcnt++;
1975*4520Snw141292       }
1976*4520Snw141292       psp->state = WAITING_FOR_DECL_OR_RULE;
1977*4520Snw141292       break;
1978*4520Snw141292     case WAITING_FOR_ARROW:
1979*4520Snw141292       if( x[0]==':' && x[1]==':' && x[2]=='=' ){
1980*4520Snw141292         psp->state = IN_RHS;
1981*4520Snw141292       }else if( x[0]=='(' ){
1982*4520Snw141292         psp->state = LHS_ALIAS_1;
1983*4520Snw141292       }else{
1984*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
1985*4520Snw141292           "Expected to see a \":\" following the LHS symbol \"%s\".",
1986*4520Snw141292           psp->lhs->name);
1987*4520Snw141292         psp->errorcnt++;
1988*4520Snw141292         psp->state = RESYNC_AFTER_RULE_ERROR;
1989*4520Snw141292       }
1990*4520Snw141292       break;
1991*4520Snw141292     case LHS_ALIAS_1:
1992*4520Snw141292       if( isalpha(x[0]) ){
1993*4520Snw141292         psp->lhsalias = x;
1994*4520Snw141292         psp->state = LHS_ALIAS_2;
1995*4520Snw141292       }else{
1996*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
1997*4520Snw141292           "\"%s\" is not a valid alias for the LHS \"%s\"\n",
1998*4520Snw141292           x,psp->lhs->name);
1999*4520Snw141292         psp->errorcnt++;
2000*4520Snw141292         psp->state = RESYNC_AFTER_RULE_ERROR;
2001*4520Snw141292       }
2002*4520Snw141292       break;
2003*4520Snw141292     case LHS_ALIAS_2:
2004*4520Snw141292       if( x[0]==')' ){
2005*4520Snw141292         psp->state = LHS_ALIAS_3;
2006*4520Snw141292       }else{
2007*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2008*4520Snw141292           "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
2009*4520Snw141292         psp->errorcnt++;
2010*4520Snw141292         psp->state = RESYNC_AFTER_RULE_ERROR;
2011*4520Snw141292       }
2012*4520Snw141292       break;
2013*4520Snw141292     case LHS_ALIAS_3:
2014*4520Snw141292       if( x[0]==':' && x[1]==':' && x[2]=='=' ){
2015*4520Snw141292         psp->state = IN_RHS;
2016*4520Snw141292       }else{
2017*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2018*4520Snw141292           "Missing \"->\" following: \"%s(%s)\".",
2019*4520Snw141292            psp->lhs->name,psp->lhsalias);
2020*4520Snw141292         psp->errorcnt++;
2021*4520Snw141292         psp->state = RESYNC_AFTER_RULE_ERROR;
2022*4520Snw141292       }
2023*4520Snw141292       break;
2024*4520Snw141292     case IN_RHS:
2025*4520Snw141292       if( x[0]=='.' ){
2026*4520Snw141292         struct rule *rp;
2027*4520Snw141292         rp = (struct rule *)malloc( sizeof(struct rule) +
2028*4520Snw141292              sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
2029*4520Snw141292         if( rp==0 ){
2030*4520Snw141292           ErrorMsg(psp->filename,psp->tokenlineno,
2031*4520Snw141292             "Can't allocate enough memory for this rule.");
2032*4520Snw141292           psp->errorcnt++;
2033*4520Snw141292           psp->prevrule = 0;
2034*4520Snw141292 	}else{
2035*4520Snw141292           int i;
2036*4520Snw141292           rp->ruleline = psp->tokenlineno;
2037*4520Snw141292           rp->rhs = (struct symbol**)&rp[1];
2038*4520Snw141292           rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]);
2039*4520Snw141292           for(i=0; i<psp->nrhs; i++){
2040*4520Snw141292             rp->rhs[i] = psp->rhs[i];
2041*4520Snw141292             rp->rhsalias[i] = psp->alias[i];
2042*4520Snw141292 	  }
2043*4520Snw141292           rp->lhs = psp->lhs;
2044*4520Snw141292           rp->lhsalias = psp->lhsalias;
2045*4520Snw141292           rp->nrhs = psp->nrhs;
2046*4520Snw141292           rp->code = 0;
2047*4520Snw141292           rp->precsym = 0;
2048*4520Snw141292           rp->index = psp->gp->nrule++;
2049*4520Snw141292           rp->nextlhs = rp->lhs->rule;
2050*4520Snw141292           rp->lhs->rule = rp;
2051*4520Snw141292           rp->next = 0;
2052*4520Snw141292           if( psp->firstrule==0 ){
2053*4520Snw141292             psp->firstrule = psp->lastrule = rp;
2054*4520Snw141292 	  }else{
2055*4520Snw141292             psp->lastrule->next = rp;
2056*4520Snw141292             psp->lastrule = rp;
2057*4520Snw141292 	  }
2058*4520Snw141292           psp->prevrule = rp;
2059*4520Snw141292 	}
2060*4520Snw141292         psp->state = WAITING_FOR_DECL_OR_RULE;
2061*4520Snw141292       }else if( isalpha(x[0]) ){
2062*4520Snw141292         if( psp->nrhs>=MAXRHS ){
2063*4520Snw141292           ErrorMsg(psp->filename,psp->tokenlineno,
2064*4520Snw141292             "Too many symbol on RHS or rule beginning at \"%s\".",
2065*4520Snw141292             x);
2066*4520Snw141292           psp->errorcnt++;
2067*4520Snw141292           psp->state = RESYNC_AFTER_RULE_ERROR;
2068*4520Snw141292 	}else{
2069*4520Snw141292           psp->rhs[psp->nrhs] = Symbol_new(x);
2070*4520Snw141292           psp->alias[psp->nrhs] = 0;
2071*4520Snw141292           psp->nrhs++;
2072*4520Snw141292 	}
2073*4520Snw141292       }else if( x[0]=='(' && psp->nrhs>0 ){
2074*4520Snw141292         psp->state = RHS_ALIAS_1;
2075*4520Snw141292       }else{
2076*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2077*4520Snw141292           "Illegal character on RHS of rule: \"%s\".",x);
2078*4520Snw141292         psp->errorcnt++;
2079*4520Snw141292         psp->state = RESYNC_AFTER_RULE_ERROR;
2080*4520Snw141292       }
2081*4520Snw141292       break;
2082*4520Snw141292     case RHS_ALIAS_1:
2083*4520Snw141292       if( isalpha(x[0]) ){
2084*4520Snw141292         psp->alias[psp->nrhs-1] = x;
2085*4520Snw141292         psp->state = RHS_ALIAS_2;
2086*4520Snw141292       }else{
2087*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2088*4520Snw141292           "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
2089*4520Snw141292           x,psp->rhs[psp->nrhs-1]->name);
2090*4520Snw141292         psp->errorcnt++;
2091*4520Snw141292         psp->state = RESYNC_AFTER_RULE_ERROR;
2092*4520Snw141292       }
2093*4520Snw141292       break;
2094*4520Snw141292     case RHS_ALIAS_2:
2095*4520Snw141292       if( x[0]==')' ){
2096*4520Snw141292         psp->state = IN_RHS;
2097*4520Snw141292       }else{
2098*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2099*4520Snw141292           "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
2100*4520Snw141292         psp->errorcnt++;
2101*4520Snw141292         psp->state = RESYNC_AFTER_RULE_ERROR;
2102*4520Snw141292       }
2103*4520Snw141292       break;
2104*4520Snw141292     case WAITING_FOR_DECL_KEYWORD:
2105*4520Snw141292       if( isalpha(x[0]) ){
2106*4520Snw141292         psp->declkeyword = x;
2107*4520Snw141292         psp->declargslot = 0;
2108*4520Snw141292         psp->decllnslot = 0;
2109*4520Snw141292         psp->state = WAITING_FOR_DECL_ARG;
2110*4520Snw141292         if( strcmp(x,"name")==0 ){
2111*4520Snw141292           psp->declargslot = &(psp->gp->name);
2112*4520Snw141292 	}else if( strcmp(x,"include")==0 ){
2113*4520Snw141292           psp->declargslot = &(psp->gp->include);
2114*4520Snw141292           psp->decllnslot = &psp->gp->includeln;
2115*4520Snw141292 	}else if( strcmp(x,"code")==0 ){
2116*4520Snw141292           psp->declargslot = &(psp->gp->extracode);
2117*4520Snw141292           psp->decllnslot = &psp->gp->extracodeln;
2118*4520Snw141292 	}else if( strcmp(x,"token_destructor")==0 ){
2119*4520Snw141292           psp->declargslot = &psp->gp->tokendest;
2120*4520Snw141292           psp->decllnslot = &psp->gp->tokendestln;
2121*4520Snw141292 	}else if( strcmp(x,"default_destructor")==0 ){
2122*4520Snw141292           psp->declargslot = &psp->gp->vardest;
2123*4520Snw141292           psp->decllnslot = &psp->gp->vardestln;
2124*4520Snw141292 	}else if( strcmp(x,"token_prefix")==0 ){
2125*4520Snw141292           psp->declargslot = &psp->gp->tokenprefix;
2126*4520Snw141292 	}else if( strcmp(x,"syntax_error")==0 ){
2127*4520Snw141292           psp->declargslot = &(psp->gp->error);
2128*4520Snw141292           psp->decllnslot = &psp->gp->errorln;
2129*4520Snw141292 	}else if( strcmp(x,"parse_accept")==0 ){
2130*4520Snw141292           psp->declargslot = &(psp->gp->accept);
2131*4520Snw141292           psp->decllnslot = &psp->gp->acceptln;
2132*4520Snw141292 	}else if( strcmp(x,"parse_failure")==0 ){
2133*4520Snw141292           psp->declargslot = &(psp->gp->failure);
2134*4520Snw141292           psp->decllnslot = &psp->gp->failureln;
2135*4520Snw141292 	}else if( strcmp(x,"stack_overflow")==0 ){
2136*4520Snw141292           psp->declargslot = &(psp->gp->overflow);
2137*4520Snw141292           psp->decllnslot = &psp->gp->overflowln;
2138*4520Snw141292         }else if( strcmp(x,"extra_argument")==0 ){
2139*4520Snw141292           psp->declargslot = &(psp->gp->arg);
2140*4520Snw141292         }else if( strcmp(x,"token_type")==0 ){
2141*4520Snw141292           psp->declargslot = &(psp->gp->tokentype);
2142*4520Snw141292         }else if( strcmp(x,"default_type")==0 ){
2143*4520Snw141292           psp->declargslot = &(psp->gp->vartype);
2144*4520Snw141292         }else if( strcmp(x,"stack_size")==0 ){
2145*4520Snw141292           psp->declargslot = &(psp->gp->stacksize);
2146*4520Snw141292         }else if( strcmp(x,"start_symbol")==0 ){
2147*4520Snw141292           psp->declargslot = &(psp->gp->start);
2148*4520Snw141292         }else if( strcmp(x,"left")==0 ){
2149*4520Snw141292           psp->preccounter++;
2150*4520Snw141292           psp->declassoc = LEFT;
2151*4520Snw141292           psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2152*4520Snw141292         }else if( strcmp(x,"right")==0 ){
2153*4520Snw141292           psp->preccounter++;
2154*4520Snw141292           psp->declassoc = RIGHT;
2155*4520Snw141292           psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2156*4520Snw141292         }else if( strcmp(x,"nonassoc")==0 ){
2157*4520Snw141292           psp->preccounter++;
2158*4520Snw141292           psp->declassoc = NONE;
2159*4520Snw141292           psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2160*4520Snw141292 	}else if( strcmp(x,"destructor")==0 ){
2161*4520Snw141292           psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
2162*4520Snw141292 	}else if( strcmp(x,"type")==0 ){
2163*4520Snw141292           psp->state = WAITING_FOR_DATATYPE_SYMBOL;
2164*4520Snw141292         }else if( strcmp(x,"fallback")==0 ){
2165*4520Snw141292           psp->fallback = 0;
2166*4520Snw141292           psp->state = WAITING_FOR_FALLBACK_ID;
2167*4520Snw141292         }else{
2168*4520Snw141292           ErrorMsg(psp->filename,psp->tokenlineno,
2169*4520Snw141292             "Unknown declaration keyword: \"%%%s\".",x);
2170*4520Snw141292           psp->errorcnt++;
2171*4520Snw141292           psp->state = RESYNC_AFTER_DECL_ERROR;
2172*4520Snw141292 	}
2173*4520Snw141292       }else{
2174*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2175*4520Snw141292           "Illegal declaration keyword: \"%s\".",x);
2176*4520Snw141292         psp->errorcnt++;
2177*4520Snw141292         psp->state = RESYNC_AFTER_DECL_ERROR;
2178*4520Snw141292       }
2179*4520Snw141292       break;
2180*4520Snw141292     case WAITING_FOR_DESTRUCTOR_SYMBOL:
2181*4520Snw141292       if( !isalpha(x[0]) ){
2182*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2183*4520Snw141292           "Symbol name missing after %destructor keyword");
2184*4520Snw141292         psp->errorcnt++;
2185*4520Snw141292         psp->state = RESYNC_AFTER_DECL_ERROR;
2186*4520Snw141292       }else{
2187*4520Snw141292         struct symbol *sp = Symbol_new(x);
2188*4520Snw141292         psp->declargslot = &sp->destructor;
2189*4520Snw141292         psp->decllnslot = &sp->destructorln;
2190*4520Snw141292         psp->state = WAITING_FOR_DECL_ARG;
2191*4520Snw141292       }
2192*4520Snw141292       break;
2193*4520Snw141292     case WAITING_FOR_DATATYPE_SYMBOL:
2194*4520Snw141292       if( !isalpha(x[0]) ){
2195*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2196*4520Snw141292           "Symbol name missing after %destructor keyword");
2197*4520Snw141292         psp->errorcnt++;
2198*4520Snw141292         psp->state = RESYNC_AFTER_DECL_ERROR;
2199*4520Snw141292       }else{
2200*4520Snw141292         struct symbol *sp = Symbol_new(x);
2201*4520Snw141292         psp->declargslot = &sp->datatype;
2202*4520Snw141292         psp->decllnslot = 0;
2203*4520Snw141292         psp->state = WAITING_FOR_DECL_ARG;
2204*4520Snw141292       }
2205*4520Snw141292       break;
2206*4520Snw141292     case WAITING_FOR_PRECEDENCE_SYMBOL:
2207*4520Snw141292       if( x[0]=='.' ){
2208*4520Snw141292         psp->state = WAITING_FOR_DECL_OR_RULE;
2209*4520Snw141292       }else if( isupper(x[0]) ){
2210*4520Snw141292         struct symbol *sp;
2211*4520Snw141292         sp = Symbol_new(x);
2212*4520Snw141292         if( sp->prec>=0 ){
2213*4520Snw141292           ErrorMsg(psp->filename,psp->tokenlineno,
2214*4520Snw141292             "Symbol \"%s\" has already be given a precedence.",x);
2215*4520Snw141292           psp->errorcnt++;
2216*4520Snw141292 	}else{
2217*4520Snw141292           sp->prec = psp->preccounter;
2218*4520Snw141292           sp->assoc = psp->declassoc;
2219*4520Snw141292 	}
2220*4520Snw141292       }else{
2221*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2222*4520Snw141292           "Can't assign a precedence to \"%s\".",x);
2223*4520Snw141292         psp->errorcnt++;
2224*4520Snw141292       }
2225*4520Snw141292       break;
2226*4520Snw141292     case WAITING_FOR_DECL_ARG:
2227*4520Snw141292       if( (x[0]=='{' || x[0]=='\"' || isalnum(x[0])) ){
2228*4520Snw141292         if( *(psp->declargslot)!=0 ){
2229*4520Snw141292           ErrorMsg(psp->filename,psp->tokenlineno,
2230*4520Snw141292             "The argument \"%s\" to declaration \"%%%s\" is not the first.",
2231*4520Snw141292             x[0]=='\"' ? &x[1] : x,psp->declkeyword);
2232*4520Snw141292           psp->errorcnt++;
2233*4520Snw141292           psp->state = RESYNC_AFTER_DECL_ERROR;
2234*4520Snw141292 	}else{
2235*4520Snw141292           *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x;
2236*4520Snw141292           if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno;
2237*4520Snw141292           psp->state = WAITING_FOR_DECL_OR_RULE;
2238*4520Snw141292 	}
2239*4520Snw141292       }else{
2240*4520Snw141292         ErrorMsg(psp->filename,psp->tokenlineno,
2241*4520Snw141292           "Illegal argument to %%%s: %s",psp->declkeyword,x);
2242*4520Snw141292         psp->errorcnt++;
2243*4520Snw141292         psp->state = RESYNC_AFTER_DECL_ERROR;
2244*4520Snw141292       }
2245*4520Snw141292       break;
2246*4520Snw141292     case WAITING_FOR_FALLBACK_ID:
2247*4520Snw141292       if( x[0]=='.' ){
2248*4520Snw141292         psp->state = WAITING_FOR_DECL_OR_RULE;
2249*4520Snw141292       }else if( !isupper(x[0]) ){
2250*4520Snw141292         ErrorMsg(psp->filename, psp->tokenlineno,
2251*4520Snw141292           "%%fallback argument \"%s\" should be a token", x);
2252*4520Snw141292         psp->errorcnt++;
2253*4520Snw141292       }else{
2254*4520Snw141292         struct symbol *sp = Symbol_new(x);
2255*4520Snw141292         if( psp->fallback==0 ){
2256*4520Snw141292           psp->fallback = sp;
2257*4520Snw141292         }else if( sp->fallback ){
2258*4520Snw141292           ErrorMsg(psp->filename, psp->tokenlineno,
2259*4520Snw141292             "More than one fallback assigned to token %s", x);
2260*4520Snw141292           psp->errorcnt++;
2261*4520Snw141292         }else{
2262*4520Snw141292           sp->fallback = psp->fallback;
2263*4520Snw141292           psp->gp->has_fallback = 1;
2264*4520Snw141292         }
2265*4520Snw141292       }
2266*4520Snw141292       break;
2267*4520Snw141292     case RESYNC_AFTER_RULE_ERROR:
2268*4520Snw141292 /*      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2269*4520Snw141292 **      break; */
2270*4520Snw141292     case RESYNC_AFTER_DECL_ERROR:
2271*4520Snw141292       if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2272*4520Snw141292       if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
2273*4520Snw141292       break;
2274*4520Snw141292   }
2275*4520Snw141292 }
2276*4520Snw141292 
2277*4520Snw141292 /* In spite of its name, this function is really a scanner.  It read
2278*4520Snw141292 ** in the entire input file (all at once) then tokenizes it.  Each
2279*4520Snw141292 ** token is passed to the function "parseonetoken" which builds all
2280*4520Snw141292 ** the appropriate data structures in the global state vector "gp".
2281*4520Snw141292 */
Parse(gp)2282*4520Snw141292 void Parse(gp)
2283*4520Snw141292 struct lemon *gp;
2284*4520Snw141292 {
2285*4520Snw141292   struct pstate ps;
2286*4520Snw141292   FILE *fp;
2287*4520Snw141292   char *filebuf;
2288*4520Snw141292   int filesize;
2289*4520Snw141292   int lineno;
2290*4520Snw141292   int c;
2291*4520Snw141292   char *cp, *nextcp;
2292*4520Snw141292   int startline = 0;
2293*4520Snw141292 
2294*4520Snw141292   ps.gp = gp;
2295*4520Snw141292   ps.filename = gp->filename;
2296*4520Snw141292   ps.errorcnt = 0;
2297*4520Snw141292   ps.state = INITIALIZE;
2298*4520Snw141292 
2299*4520Snw141292   /* Begin by reading the input file */
2300*4520Snw141292   fp = fopen(ps.filename,"rb");
2301*4520Snw141292   if( fp==0 ){
2302*4520Snw141292     ErrorMsg(ps.filename,0,"Can't open this file for reading.");
2303*4520Snw141292     gp->errorcnt++;
2304*4520Snw141292     return;
2305*4520Snw141292   }
2306*4520Snw141292   fseek(fp,0,2);
2307*4520Snw141292   filesize = ftell(fp);
2308*4520Snw141292   rewind(fp);
2309*4520Snw141292   filebuf = (char *)malloc( filesize+1 );
2310*4520Snw141292   if( filebuf==0 ){
2311*4520Snw141292     ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.",
2312*4520Snw141292       filesize+1);
2313*4520Snw141292     gp->errorcnt++;
2314*4520Snw141292     return;
2315*4520Snw141292   }
2316*4520Snw141292   if( fread(filebuf,1,filesize,fp)!=filesize ){
2317*4520Snw141292     ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
2318*4520Snw141292       filesize);
2319*4520Snw141292     free(filebuf);
2320*4520Snw141292     gp->errorcnt++;
2321*4520Snw141292     return;
2322*4520Snw141292   }
2323*4520Snw141292   fclose(fp);
2324*4520Snw141292   filebuf[filesize] = 0;
2325*4520Snw141292 
2326*4520Snw141292   /* Now scan the text of the input file */
2327*4520Snw141292   lineno = 1;
2328*4520Snw141292   for(cp=filebuf; (c= *cp)!=0; ){
2329*4520Snw141292     if( c=='\n' ) lineno++;              /* Keep track of the line number */
2330*4520Snw141292     if( isspace(c) ){ cp++; continue; }  /* Skip all white space */
2331*4520Snw141292     if( c=='/' && cp[1]=='/' ){          /* Skip C++ style comments */
2332*4520Snw141292       cp+=2;
2333*4520Snw141292       while( (c= *cp)!=0 && c!='\n' ) cp++;
2334*4520Snw141292       continue;
2335*4520Snw141292     }
2336*4520Snw141292     if( c=='/' && cp[1]=='*' ){          /* Skip C style comments */
2337*4520Snw141292       cp+=2;
2338*4520Snw141292       while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
2339*4520Snw141292         if( c=='\n' ) lineno++;
2340*4520Snw141292         cp++;
2341*4520Snw141292       }
2342*4520Snw141292       if( c ) cp++;
2343*4520Snw141292       continue;
2344*4520Snw141292     }
2345*4520Snw141292     ps.tokenstart = cp;                /* Mark the beginning of the token */
2346*4520Snw141292     ps.tokenlineno = lineno;           /* Linenumber on which token begins */
2347*4520Snw141292     if( c=='\"' ){                     /* String literals */
2348*4520Snw141292       cp++;
2349*4520Snw141292       while( (c= *cp)!=0 && c!='\"' ){
2350*4520Snw141292         if( c=='\n' ) lineno++;
2351*4520Snw141292         cp++;
2352*4520Snw141292       }
2353*4520Snw141292       if( c==0 ){
2354*4520Snw141292         ErrorMsg(ps.filename,startline,
2355*4520Snw141292 "String starting on this line is not terminated before the end of the file.");
2356*4520Snw141292         ps.errorcnt++;
2357*4520Snw141292         nextcp = cp;
2358*4520Snw141292       }else{
2359*4520Snw141292         nextcp = cp+1;
2360*4520Snw141292       }
2361*4520Snw141292     }else if( c=='{' ){               /* A block of C code */
2362*4520Snw141292       int level;
2363*4520Snw141292       cp++;
2364*4520Snw141292       for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
2365*4520Snw141292         if( c=='\n' ) lineno++;
2366*4520Snw141292         else if( c=='{' ) level++;
2367*4520Snw141292         else if( c=='}' ) level--;
2368*4520Snw141292         else if( c=='/' && cp[1]=='*' ){  /* Skip comments */
2369*4520Snw141292           int prevc;
2370*4520Snw141292           cp = &cp[2];
2371*4520Snw141292           prevc = 0;
2372*4520Snw141292           while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
2373*4520Snw141292             if( c=='\n' ) lineno++;
2374*4520Snw141292             prevc = c;
2375*4520Snw141292             cp++;
2376*4520Snw141292 	  }
2377*4520Snw141292 	}else if( c=='/' && cp[1]=='/' ){  /* Skip C++ style comments too */
2378*4520Snw141292           cp = &cp[2];
2379*4520Snw141292           while( (c= *cp)!=0 && c!='\n' ) cp++;
2380*4520Snw141292           if( c ) lineno++;
2381*4520Snw141292 	}else if( c=='\'' || c=='\"' ){    /* String a character literals */
2382*4520Snw141292           int startchar, prevc;
2383*4520Snw141292           startchar = c;
2384*4520Snw141292           prevc = 0;
2385*4520Snw141292           for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
2386*4520Snw141292             if( c=='\n' ) lineno++;
2387*4520Snw141292             if( prevc=='\\' ) prevc = 0;
2388*4520Snw141292             else              prevc = c;
2389*4520Snw141292 	  }
2390*4520Snw141292 	}
2391*4520Snw141292       }
2392*4520Snw141292       if( c==0 ){
2393*4520Snw141292         ErrorMsg(ps.filename,ps.tokenlineno,
2394*4520Snw141292 "C code starting on this line is not terminated before the end of the file.");
2395*4520Snw141292         ps.errorcnt++;
2396*4520Snw141292         nextcp = cp;
2397*4520Snw141292       }else{
2398*4520Snw141292         nextcp = cp+1;
2399*4520Snw141292       }
2400*4520Snw141292     }else if( isalnum(c) ){          /* Identifiers */
2401*4520Snw141292       while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
2402*4520Snw141292       nextcp = cp;
2403*4520Snw141292     }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
2404*4520Snw141292       cp += 3;
2405*4520Snw141292       nextcp = cp;
2406*4520Snw141292     }else{                          /* All other (one character) operators */
2407*4520Snw141292       cp++;
2408*4520Snw141292       nextcp = cp;
2409*4520Snw141292     }
2410*4520Snw141292     c = *cp;
2411*4520Snw141292     *cp = 0;                        /* Null terminate the token */
2412*4520Snw141292     parseonetoken(&ps);             /* Parse the token */
2413*4520Snw141292     *cp = c;                        /* Restore the buffer */
2414*4520Snw141292     cp = nextcp;
2415*4520Snw141292   }
2416*4520Snw141292   free(filebuf);                    /* Release the buffer after parsing */
2417*4520Snw141292   gp->rule = ps.firstrule;
2418*4520Snw141292   gp->errorcnt = ps.errorcnt;
2419*4520Snw141292 }
2420*4520Snw141292 /*************************** From the file "plink.c" *********************/
2421*4520Snw141292 /*
2422*4520Snw141292 ** Routines processing configuration follow-set propagation links
2423*4520Snw141292 ** in the LEMON parser generator.
2424*4520Snw141292 */
2425*4520Snw141292 static struct plink *plink_freelist = 0;
2426*4520Snw141292 
2427*4520Snw141292 /* Allocate a new plink */
Plink_new()2428*4520Snw141292 struct plink *Plink_new(){
2429*4520Snw141292   struct plink *new;
2430*4520Snw141292 
2431*4520Snw141292   if( plink_freelist==0 ){
2432*4520Snw141292     int i;
2433*4520Snw141292     int amt = 100;
2434*4520Snw141292     plink_freelist = (struct plink *)malloc( sizeof(struct plink)*amt );
2435*4520Snw141292     if( plink_freelist==0 ){
2436*4520Snw141292       fprintf(stderr,
2437*4520Snw141292       "Unable to allocate memory for a new follow-set propagation link.\n");
2438*4520Snw141292       exit(1);
2439*4520Snw141292     }
2440*4520Snw141292     for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
2441*4520Snw141292     plink_freelist[amt-1].next = 0;
2442*4520Snw141292   }
2443*4520Snw141292   new = plink_freelist;
2444*4520Snw141292   plink_freelist = plink_freelist->next;
2445*4520Snw141292   return new;
2446*4520Snw141292 }
2447*4520Snw141292 
2448*4520Snw141292 /* Add a plink to a plink list */
Plink_add(plpp,cfp)2449*4520Snw141292 void Plink_add(plpp,cfp)
2450*4520Snw141292 struct plink **plpp;
2451*4520Snw141292 struct config *cfp;
2452*4520Snw141292 {
2453*4520Snw141292   struct plink *new;
2454*4520Snw141292   new = Plink_new();
2455*4520Snw141292   new->next = *plpp;
2456*4520Snw141292   *plpp = new;
2457*4520Snw141292   new->cfp = cfp;
2458*4520Snw141292 }
2459*4520Snw141292 
2460*4520Snw141292 /* Transfer every plink on the list "from" to the list "to" */
Plink_copy(to,from)2461*4520Snw141292 void Plink_copy(to,from)
2462*4520Snw141292 struct plink **to;
2463*4520Snw141292 struct plink *from;
2464*4520Snw141292 {
2465*4520Snw141292   struct plink *nextpl;
2466*4520Snw141292   while( from ){
2467*4520Snw141292     nextpl = from->next;
2468*4520Snw141292     from->next = *to;
2469*4520Snw141292     *to = from;
2470*4520Snw141292     from = nextpl;
2471*4520Snw141292   }
2472*4520Snw141292 }
2473*4520Snw141292 
2474*4520Snw141292 /* Delete every plink on the list */
Plink_delete(plp)2475*4520Snw141292 void Plink_delete(plp)
2476*4520Snw141292 struct plink *plp;
2477*4520Snw141292 {
2478*4520Snw141292   struct plink *nextpl;
2479*4520Snw141292 
2480*4520Snw141292   while( plp ){
2481*4520Snw141292     nextpl = plp->next;
2482*4520Snw141292     plp->next = plink_freelist;
2483*4520Snw141292     plink_freelist = plp;
2484*4520Snw141292     plp = nextpl;
2485*4520Snw141292   }
2486*4520Snw141292 }
2487*4520Snw141292 /*********************** From the file "report.c" **************************/
2488*4520Snw141292 /*
2489*4520Snw141292 ** Procedures for generating reports and tables in the LEMON parser generator.
2490*4520Snw141292 */
2491*4520Snw141292 
2492*4520Snw141292 /* Generate a filename with the given suffix.  Space to hold the
2493*4520Snw141292 ** name comes from malloc() and must be freed by the calling
2494*4520Snw141292 ** function.
2495*4520Snw141292 */
file_makename(lemp,suffix)2496*4520Snw141292 PRIVATE char *file_makename(lemp,suffix)
2497*4520Snw141292 struct lemon *lemp;
2498*4520Snw141292 char *suffix;
2499*4520Snw141292 {
2500*4520Snw141292   char *name;
2501*4520Snw141292   char *cp;
2502*4520Snw141292 
2503*4520Snw141292   name = malloc( strlen(lemp->filename) + strlen(suffix) + 5 );
2504*4520Snw141292   if( name==0 ){
2505*4520Snw141292     fprintf(stderr,"Can't allocate space for a filename.\n");
2506*4520Snw141292     exit(1);
2507*4520Snw141292   }
2508*4520Snw141292   strcpy(name,lemp->filename);
2509*4520Snw141292   cp = strrchr(name,'.');
2510*4520Snw141292   if( cp ) *cp = 0;
2511*4520Snw141292   strcat(name,suffix);
2512*4520Snw141292   return name;
2513*4520Snw141292 }
2514*4520Snw141292 
2515*4520Snw141292 /* Open a file with a name based on the name of the input file,
2516*4520Snw141292 ** but with a different (specified) suffix, and return a pointer
2517*4520Snw141292 ** to the stream */
file_open(lemp,suffix,mode)2518*4520Snw141292 PRIVATE FILE *file_open(lemp,suffix,mode)
2519*4520Snw141292 struct lemon *lemp;
2520*4520Snw141292 char *suffix;
2521*4520Snw141292 char *mode;
2522*4520Snw141292 {
2523*4520Snw141292   FILE *fp;
2524*4520Snw141292 
2525*4520Snw141292   if( lemp->outname ) free(lemp->outname);
2526*4520Snw141292   lemp->outname = file_makename(lemp, suffix);
2527*4520Snw141292   fp = fopen(lemp->outname,mode);
2528*4520Snw141292   if( fp==0 && *mode=='w' ){
2529*4520Snw141292     fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
2530*4520Snw141292     lemp->errorcnt++;
2531*4520Snw141292     return 0;
2532*4520Snw141292   }
2533*4520Snw141292   return fp;
2534*4520Snw141292 }
2535*4520Snw141292 
2536*4520Snw141292 /* Duplicate the input file without comments and without actions
2537*4520Snw141292 ** on rules */
Reprint(lemp)2538*4520Snw141292 void Reprint(lemp)
2539*4520Snw141292 struct lemon *lemp;
2540*4520Snw141292 {
2541*4520Snw141292   struct rule *rp;
2542*4520Snw141292   struct symbol *sp;
2543*4520Snw141292   int i, j, maxlen, len, ncolumns, skip;
2544*4520Snw141292   printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
2545*4520Snw141292   maxlen = 10;
2546*4520Snw141292   for(i=0; i<lemp->nsymbol; i++){
2547*4520Snw141292     sp = lemp->symbols[i];
2548*4520Snw141292     len = strlen(sp->name);
2549*4520Snw141292     if( len>maxlen ) maxlen = len;
2550*4520Snw141292   }
2551*4520Snw141292   ncolumns = 76/(maxlen+5);
2552*4520Snw141292   if( ncolumns<1 ) ncolumns = 1;
2553*4520Snw141292   skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
2554*4520Snw141292   for(i=0; i<skip; i++){
2555*4520Snw141292     printf("//");
2556*4520Snw141292     for(j=i; j<lemp->nsymbol; j+=skip){
2557*4520Snw141292       sp = lemp->symbols[j];
2558*4520Snw141292       assert( sp->index==j );
2559*4520Snw141292       printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
2560*4520Snw141292     }
2561*4520Snw141292     printf("\n");
2562*4520Snw141292   }
2563*4520Snw141292   for(rp=lemp->rule; rp; rp=rp->next){
2564*4520Snw141292     printf("%s",rp->lhs->name);
2565*4520Snw141292 /*    if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
2566*4520Snw141292     printf(" ::=");
2567*4520Snw141292     for(i=0; i<rp->nrhs; i++){
2568*4520Snw141292       printf(" %s",rp->rhs[i]->name);
2569*4520Snw141292 /*      if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
2570*4520Snw141292     }
2571*4520Snw141292     printf(".");
2572*4520Snw141292     if( rp->precsym ) printf(" [%s]",rp->precsym->name);
2573*4520Snw141292 /*    if( rp->code ) printf("\n    %s",rp->code); */
2574*4520Snw141292     printf("\n");
2575*4520Snw141292   }
2576*4520Snw141292 }
2577*4520Snw141292 
ConfigPrint(fp,cfp)2578*4520Snw141292 void ConfigPrint(fp,cfp)
2579*4520Snw141292 FILE *fp;
2580*4520Snw141292 struct config *cfp;
2581*4520Snw141292 {
2582*4520Snw141292   struct rule *rp;
2583*4520Snw141292   int i;
2584*4520Snw141292   rp = cfp->rp;
2585*4520Snw141292   fprintf(fp,"%s ::=",rp->lhs->name);
2586*4520Snw141292   for(i=0; i<=rp->nrhs; i++){
2587*4520Snw141292     if( i==cfp->dot ) fprintf(fp," *");
2588*4520Snw141292     if( i==rp->nrhs ) break;
2589*4520Snw141292     fprintf(fp," %s",rp->rhs[i]->name);
2590*4520Snw141292   }
2591*4520Snw141292 }
2592*4520Snw141292 
2593*4520Snw141292 /* #define TEST */
2594*4520Snw141292 #ifdef TEST
2595*4520Snw141292 /* Print a set */
SetPrint(out,set,lemp)2596*4520Snw141292 PRIVATE void SetPrint(out,set,lemp)
2597*4520Snw141292 FILE *out;
2598*4520Snw141292 char *set;
2599*4520Snw141292 struct lemon *lemp;
2600*4520Snw141292 {
2601*4520Snw141292   int i;
2602*4520Snw141292   char *spacer;
2603*4520Snw141292   spacer = "";
2604*4520Snw141292   fprintf(out,"%12s[","");
2605*4520Snw141292   for(i=0; i<lemp->nterminal; i++){
2606*4520Snw141292     if( SetFind(set,i) ){
2607*4520Snw141292       fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
2608*4520Snw141292       spacer = " ";
2609*4520Snw141292     }
2610*4520Snw141292   }
2611*4520Snw141292   fprintf(out,"]\n");
2612*4520Snw141292 }
2613*4520Snw141292 
2614*4520Snw141292 /* Print a plink chain */
PlinkPrint(out,plp,tag)2615*4520Snw141292 PRIVATE void PlinkPrint(out,plp,tag)
2616*4520Snw141292 FILE *out;
2617*4520Snw141292 struct plink *plp;
2618*4520Snw141292 char *tag;
2619*4520Snw141292 {
2620*4520Snw141292   while( plp ){
2621*4520Snw141292     fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->index);
2622*4520Snw141292     ConfigPrint(out,plp->cfp);
2623*4520Snw141292     fprintf(out,"\n");
2624*4520Snw141292     plp = plp->next;
2625*4520Snw141292   }
2626*4520Snw141292 }
2627*4520Snw141292 #endif
2628*4520Snw141292 
2629*4520Snw141292 /* Print an action to the given file descriptor.  Return FALSE if
2630*4520Snw141292 ** nothing was actually printed.
2631*4520Snw141292 */
PrintAction(struct action * ap,FILE * fp,int indent)2632*4520Snw141292 int PrintAction(struct action *ap, FILE *fp, int indent){
2633*4520Snw141292   int result = 1;
2634*4520Snw141292   switch( ap->type ){
2635*4520Snw141292     case SHIFT:
2636*4520Snw141292       fprintf(fp,"%*s shift  %d",indent,ap->sp->name,ap->x.stp->index);
2637*4520Snw141292       break;
2638*4520Snw141292     case REDUCE:
2639*4520Snw141292       fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
2640*4520Snw141292       break;
2641*4520Snw141292     case ACCEPT:
2642*4520Snw141292       fprintf(fp,"%*s accept",indent,ap->sp->name);
2643*4520Snw141292       break;
2644*4520Snw141292     case ERROR:
2645*4520Snw141292       fprintf(fp,"%*s error",indent,ap->sp->name);
2646*4520Snw141292       break;
2647*4520Snw141292     case CONFLICT:
2648*4520Snw141292       fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
2649*4520Snw141292         indent,ap->sp->name,ap->x.rp->index);
2650*4520Snw141292       break;
2651*4520Snw141292     case SH_RESOLVED:
2652*4520Snw141292     case RD_RESOLVED:
2653*4520Snw141292     case NOT_USED:
2654*4520Snw141292       result = 0;
2655*4520Snw141292       break;
2656*4520Snw141292   }
2657*4520Snw141292   return result;
2658*4520Snw141292 }
2659*4520Snw141292 
2660*4520Snw141292 /* Generate the "y.output" log file */
ReportOutput(lemp)2661*4520Snw141292 void ReportOutput(lemp)
2662*4520Snw141292 struct lemon *lemp;
2663*4520Snw141292 {
2664*4520Snw141292   int i;
2665*4520Snw141292   struct state *stp;
2666*4520Snw141292   struct config *cfp;
2667*4520Snw141292   struct action *ap;
2668*4520Snw141292   FILE *fp;
2669*4520Snw141292 
2670*4520Snw141292   fp = file_open(lemp,".out","w");
2671*4520Snw141292   if( fp==0 ) return;
2672*4520Snw141292   fprintf(fp," \b");
2673*4520Snw141292   for(i=0; i<lemp->nstate; i++){
2674*4520Snw141292     stp = lemp->sorted[i];
2675*4520Snw141292     fprintf(fp,"State %d:\n",stp->index);
2676*4520Snw141292     if( lemp->basisflag ) cfp=stp->bp;
2677*4520Snw141292     else                  cfp=stp->cfp;
2678*4520Snw141292     while( cfp ){
2679*4520Snw141292       char buf[20];
2680*4520Snw141292       if( cfp->dot==cfp->rp->nrhs ){
2681*4520Snw141292         sprintf(buf,"(%d)",cfp->rp->index);
2682*4520Snw141292         fprintf(fp,"    %5s ",buf);
2683*4520Snw141292       }else{
2684*4520Snw141292         fprintf(fp,"          ");
2685*4520Snw141292       }
2686*4520Snw141292       ConfigPrint(fp,cfp);
2687*4520Snw141292       fprintf(fp,"\n");
2688*4520Snw141292 #ifdef TEST
2689*4520Snw141292       SetPrint(fp,cfp->fws,lemp);
2690*4520Snw141292       PlinkPrint(fp,cfp->fplp,"To  ");
2691*4520Snw141292       PlinkPrint(fp,cfp->bplp,"From");
2692*4520Snw141292 #endif
2693*4520Snw141292       if( lemp->basisflag ) cfp=cfp->bp;
2694*4520Snw141292       else                  cfp=cfp->next;
2695*4520Snw141292     }
2696*4520Snw141292     fprintf(fp,"\n");
2697*4520Snw141292     for(ap=stp->ap; ap; ap=ap->next){
2698*4520Snw141292       if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
2699*4520Snw141292     }
2700*4520Snw141292     fprintf(fp,"\n");
2701*4520Snw141292   }
2702*4520Snw141292   fclose(fp);
2703*4520Snw141292   return;
2704*4520Snw141292 }
2705*4520Snw141292 
2706*4520Snw141292 /* Search for the file "name" which is in the same directory as
2707*4520Snw141292 ** the exacutable */
pathsearch(argv0,name,modemask)2708*4520Snw141292 PRIVATE char *pathsearch(argv0,name,modemask)
2709*4520Snw141292 char *argv0;
2710*4520Snw141292 char *name;
2711*4520Snw141292 int modemask;
2712*4520Snw141292 {
2713*4520Snw141292   char *pathlist;
2714*4520Snw141292   char *path,*cp;
2715*4520Snw141292   char c;
2716*4520Snw141292   extern int access();
2717*4520Snw141292 
2718*4520Snw141292 #ifdef __WIN32__
2719*4520Snw141292   cp = strrchr(argv0,'\\');
2720*4520Snw141292 #else
2721*4520Snw141292   cp = strrchr(argv0,'/');
2722*4520Snw141292 #endif
2723*4520Snw141292   if( cp ){
2724*4520Snw141292     c = *cp;
2725*4520Snw141292     *cp = 0;
2726*4520Snw141292     path = (char *)malloc( strlen(argv0) + strlen(name) + 2 );
2727*4520Snw141292     if( path ) sprintf(path,"%s/%s",argv0,name);
2728*4520Snw141292     *cp = c;
2729*4520Snw141292   }else{
2730*4520Snw141292     extern char *getenv();
2731*4520Snw141292     pathlist = getenv("PATH");
2732*4520Snw141292     if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
2733*4520Snw141292     path = (char *)malloc( strlen(pathlist)+strlen(name)+2 );
2734*4520Snw141292     if( path!=0 ){
2735*4520Snw141292       while( *pathlist ){
2736*4520Snw141292         cp = strchr(pathlist,':');
2737*4520Snw141292         if( cp==0 ) cp = &pathlist[strlen(pathlist)];
2738*4520Snw141292         c = *cp;
2739*4520Snw141292         *cp = 0;
2740*4520Snw141292         sprintf(path,"%s/%s",pathlist,name);
2741*4520Snw141292         *cp = c;
2742*4520Snw141292         if( c==0 ) pathlist = "";
2743*4520Snw141292         else pathlist = &cp[1];
2744*4520Snw141292         if( access(path,modemask)==0 ) break;
2745*4520Snw141292       }
2746*4520Snw141292     }
2747*4520Snw141292   }
2748*4520Snw141292   return path;
2749*4520Snw141292 }
2750*4520Snw141292 
2751*4520Snw141292 /* Given an action, compute the integer value for that action
2752*4520Snw141292 ** which is to be put in the action table of the generated machine.
2753*4520Snw141292 ** Return negative if no action should be generated.
2754*4520Snw141292 */
compute_action(lemp,ap)2755*4520Snw141292 PRIVATE int compute_action(lemp,ap)
2756*4520Snw141292 struct lemon *lemp;
2757*4520Snw141292 struct action *ap;
2758*4520Snw141292 {
2759*4520Snw141292   int act;
2760*4520Snw141292   switch( ap->type ){
2761*4520Snw141292     case SHIFT:  act = ap->x.stp->index;               break;
2762*4520Snw141292     case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
2763*4520Snw141292     case ERROR:  act = lemp->nstate + lemp->nrule;     break;
2764*4520Snw141292     case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
2765*4520Snw141292     default:     act = -1; break;
2766*4520Snw141292   }
2767*4520Snw141292   return act;
2768*4520Snw141292 }
2769*4520Snw141292 
2770*4520Snw141292 #define LINESIZE 1000
2771*4520Snw141292 /* The next cluster of routines are for reading the template file
2772*4520Snw141292 ** and writing the results to the generated parser */
2773*4520Snw141292 /* The first function transfers data from "in" to "out" until
2774*4520Snw141292 ** a line is seen which begins with "%%".  The line number is
2775*4520Snw141292 ** tracked.
2776*4520Snw141292 **
2777*4520Snw141292 ** if name!=0, then any word that begin with "Parse" is changed to
2778*4520Snw141292 ** begin with *name instead.
2779*4520Snw141292 */
tplt_xfer(name,in,out,lineno)2780*4520Snw141292 PRIVATE void tplt_xfer(name,in,out,lineno)
2781*4520Snw141292 char *name;
2782*4520Snw141292 FILE *in;
2783*4520Snw141292 FILE *out;
2784*4520Snw141292 int *lineno;
2785*4520Snw141292 {
2786*4520Snw141292   int i, iStart;
2787*4520Snw141292   char line[LINESIZE];
2788*4520Snw141292   while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
2789*4520Snw141292     (*lineno)++;
2790*4520Snw141292     iStart = 0;
2791*4520Snw141292     if( name ){
2792*4520Snw141292       for(i=0; line[i]; i++){
2793*4520Snw141292         if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
2794*4520Snw141292           && (i==0 || !isalpha(line[i-1]))
2795*4520Snw141292         ){
2796*4520Snw141292           if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
2797*4520Snw141292           fprintf(out,"%s",name);
2798*4520Snw141292           i += 4;
2799*4520Snw141292           iStart = i+1;
2800*4520Snw141292         }
2801*4520Snw141292       }
2802*4520Snw141292     }
2803*4520Snw141292     fprintf(out,"%s",&line[iStart]);
2804*4520Snw141292   }
2805*4520Snw141292 }
2806*4520Snw141292 
2807*4520Snw141292 /* The next function finds the template file and opens it, returning
2808*4520Snw141292 ** a pointer to the opened file. */
tplt_open(lemp)2809*4520Snw141292 PRIVATE FILE *tplt_open(lemp)
2810*4520Snw141292 struct lemon *lemp;
2811*4520Snw141292 {
2812*4520Snw141292   static char templatename[] = "lempar.c";
2813*4520Snw141292   char buf[1000];
2814*4520Snw141292   FILE *in;
2815*4520Snw141292   char *tpltname;
2816*4520Snw141292   char *cp;
2817*4520Snw141292 
2818*4520Snw141292   cp = strrchr(lemp->filename,'.');
2819*4520Snw141292   if( cp ){
2820*4520Snw141292     sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
2821*4520Snw141292   }else{
2822*4520Snw141292     sprintf(buf,"%s.lt",lemp->filename);
2823*4520Snw141292   }
2824*4520Snw141292   if( access(buf,004)==0 ){
2825*4520Snw141292     tpltname = buf;
2826*4520Snw141292   }else if( access(templatename,004)==0 ){
2827*4520Snw141292     tpltname = templatename;
2828*4520Snw141292   }else{
2829*4520Snw141292     tpltname = pathsearch(lemp->argv0,templatename,0);
2830*4520Snw141292   }
2831*4520Snw141292   if( tpltname==0 ){
2832*4520Snw141292     fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
2833*4520Snw141292     templatename);
2834*4520Snw141292     lemp->errorcnt++;
2835*4520Snw141292     return 0;
2836*4520Snw141292   }
2837*4520Snw141292   in = fopen(tpltname,"r");
2838*4520Snw141292   if( in==0 ){
2839*4520Snw141292     fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
2840*4520Snw141292     lemp->errorcnt++;
2841*4520Snw141292     return 0;
2842*4520Snw141292   }
2843*4520Snw141292   return in;
2844*4520Snw141292 }
2845*4520Snw141292 
2846*4520Snw141292 /* Print a string to the file and keep the linenumber up to date */
tplt_print(out,lemp,str,strln,lineno)2847*4520Snw141292 PRIVATE void tplt_print(out,lemp,str,strln,lineno)
2848*4520Snw141292 FILE *out;
2849*4520Snw141292 struct lemon *lemp;
2850*4520Snw141292 char *str;
2851*4520Snw141292 int strln;
2852*4520Snw141292 int *lineno;
2853*4520Snw141292 {
2854*4520Snw141292   if( str==0 ) return;
2855*4520Snw141292   fprintf(out,"#line %d \"%s\"\n",strln,lemp->filename); (*lineno)++;
2856*4520Snw141292   while( *str ){
2857*4520Snw141292     if( *str=='\n' ) (*lineno)++;
2858*4520Snw141292     putc(*str,out);
2859*4520Snw141292     str++;
2860*4520Snw141292   }
2861*4520Snw141292   fprintf(out,"\n#line %d \"%s\"\n",*lineno+2,lemp->outname); (*lineno)+=2;
2862*4520Snw141292   return;
2863*4520Snw141292 }
2864*4520Snw141292 
2865*4520Snw141292 /*
2866*4520Snw141292 ** The following routine emits code for the destructor for the
2867*4520Snw141292 ** symbol sp
2868*4520Snw141292 */
emit_destructor_code(out,sp,lemp,lineno)2869*4520Snw141292 void emit_destructor_code(out,sp,lemp,lineno)
2870*4520Snw141292 FILE *out;
2871*4520Snw141292 struct symbol *sp;
2872*4520Snw141292 struct lemon *lemp;
2873*4520Snw141292 int *lineno;
2874*4520Snw141292 {
2875*4520Snw141292  char *cp = 0;
2876*4520Snw141292 
2877*4520Snw141292  int linecnt = 0;
2878*4520Snw141292  if( sp->type==TERMINAL ){
2879*4520Snw141292    cp = lemp->tokendest;
2880*4520Snw141292    if( cp==0 ) return;
2881*4520Snw141292    fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
2882*4520Snw141292  }else if( sp->destructor ){
2883*4520Snw141292    cp = sp->destructor;
2884*4520Snw141292    fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
2885*4520Snw141292  }else if( lemp->vardest ){
2886*4520Snw141292    cp = lemp->vardest;
2887*4520Snw141292    if( cp==0 ) return;
2888*4520Snw141292    fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
2889*4520Snw141292  }else{
2890*4520Snw141292    assert( 0 );  /* Cannot happen */
2891*4520Snw141292  }
2892*4520Snw141292  for(; *cp; cp++){
2893*4520Snw141292    if( *cp=='$' && cp[1]=='$' ){
2894*4520Snw141292      fprintf(out,"(yypminor->yy%d)",sp->dtnum);
2895*4520Snw141292      cp++;
2896*4520Snw141292      continue;
2897*4520Snw141292    }
2898*4520Snw141292    if( *cp=='\n' ) linecnt++;
2899*4520Snw141292    fputc(*cp,out);
2900*4520Snw141292  }
2901*4520Snw141292  (*lineno) += 3 + linecnt;
2902*4520Snw141292  fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
2903*4520Snw141292  return;
2904*4520Snw141292 }
2905*4520Snw141292 
2906*4520Snw141292 /*
2907*4520Snw141292 ** Return TRUE (non-zero) if the given symbol has a destructor.
2908*4520Snw141292 */
has_destructor(sp,lemp)2909*4520Snw141292 int has_destructor(sp, lemp)
2910*4520Snw141292 struct symbol *sp;
2911*4520Snw141292 struct lemon *lemp;
2912*4520Snw141292 {
2913*4520Snw141292   int ret;
2914*4520Snw141292   if( sp->type==TERMINAL ){
2915*4520Snw141292     ret = lemp->tokendest!=0;
2916*4520Snw141292   }else{
2917*4520Snw141292     ret = lemp->vardest!=0 || sp->destructor!=0;
2918*4520Snw141292   }
2919*4520Snw141292   return ret;
2920*4520Snw141292 }
2921*4520Snw141292 
2922*4520Snw141292 /*
2923*4520Snw141292 ** Generate code which executes when the rule "rp" is reduced.  Write
2924*4520Snw141292 ** the code to "out".  Make sure lineno stays up-to-date.
2925*4520Snw141292 */
emit_code(out,rp,lemp,lineno)2926*4520Snw141292 PRIVATE void emit_code(out,rp,lemp,lineno)
2927*4520Snw141292 FILE *out;
2928*4520Snw141292 struct rule *rp;
2929*4520Snw141292 struct lemon *lemp;
2930*4520Snw141292 int *lineno;
2931*4520Snw141292 {
2932*4520Snw141292  char *cp, *xp;
2933*4520Snw141292  int linecnt = 0;
2934*4520Snw141292  int i;
2935*4520Snw141292  char lhsused = 0;    /* True if the LHS element has been used */
2936*4520Snw141292  char used[MAXRHS];   /* True for each RHS element which is used */
2937*4520Snw141292 
2938*4520Snw141292  for(i=0; i<rp->nrhs; i++) used[i] = 0;
2939*4520Snw141292  lhsused = 0;
2940*4520Snw141292 
2941*4520Snw141292  /* Generate code to do the reduce action */
2942*4520Snw141292  if( rp->code ){
2943*4520Snw141292    fprintf(out,"#line %d \"%s\"\n{",rp->line,lemp->filename);
2944*4520Snw141292    for(cp=rp->code; *cp; cp++){
2945*4520Snw141292      if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
2946*4520Snw141292        char saved;
2947*4520Snw141292        for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
2948*4520Snw141292        saved = *xp;
2949*4520Snw141292        *xp = 0;
2950*4520Snw141292        if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
2951*4520Snw141292          fprintf(out,"yygotominor.yy%d",rp->lhs->dtnum);
2952*4520Snw141292          cp = xp;
2953*4520Snw141292          lhsused = 1;
2954*4520Snw141292        }else{
2955*4520Snw141292          for(i=0; i<rp->nrhs; i++){
2956*4520Snw141292            if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
2957*4520Snw141292              fprintf(out,"yymsp[%d].minor.yy%d",i-rp->nrhs+1,rp->rhs[i]->dtnum);
2958*4520Snw141292              cp = xp;
2959*4520Snw141292              used[i] = 1;
2960*4520Snw141292              break;
2961*4520Snw141292            }
2962*4520Snw141292          }
2963*4520Snw141292        }
2964*4520Snw141292        *xp = saved;
2965*4520Snw141292      }
2966*4520Snw141292      if( *cp=='\n' ) linecnt++;
2967*4520Snw141292      fputc(*cp,out);
2968*4520Snw141292    } /* End loop */
2969*4520Snw141292    (*lineno) += 3 + linecnt;
2970*4520Snw141292    fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
2971*4520Snw141292  } /* End if( rp->code ) */
2972*4520Snw141292 
2973*4520Snw141292  /* Check to make sure the LHS has been used */
2974*4520Snw141292  if( rp->lhsalias && !lhsused ){
2975*4520Snw141292    ErrorMsg(lemp->filename,rp->ruleline,
2976*4520Snw141292      "Label \"%s\" for \"%s(%s)\" is never used.",
2977*4520Snw141292        rp->lhsalias,rp->lhs->name,rp->lhsalias);
2978*4520Snw141292    lemp->errorcnt++;
2979*4520Snw141292  }
2980*4520Snw141292 
2981*4520Snw141292  /* Generate destructor code for RHS symbols which are not used in the
2982*4520Snw141292  ** reduce code */
2983*4520Snw141292  for(i=0; i<rp->nrhs; i++){
2984*4520Snw141292    if( rp->rhsalias[i] && !used[i] ){
2985*4520Snw141292      ErrorMsg(lemp->filename,rp->ruleline,
2986*4520Snw141292        "Label %s for \"%s(%s)\" is never used.",
2987*4520Snw141292        rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
2988*4520Snw141292      lemp->errorcnt++;
2989*4520Snw141292    }else if( rp->rhsalias[i]==0 ){
2990*4520Snw141292      if( has_destructor(rp->rhs[i],lemp) ){
2991*4520Snw141292        fprintf(out,"  yy_destructor(%d,&yymsp[%d].minor);\n",
2992*4520Snw141292           rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++;
2993*4520Snw141292      }else{
2994*4520Snw141292        fprintf(out,"        /* No destructor defined for %s */\n",
2995*4520Snw141292         rp->rhs[i]->name);
2996*4520Snw141292         (*lineno)++;
2997*4520Snw141292      }
2998*4520Snw141292    }
2999*4520Snw141292  }
3000*4520Snw141292  return;
3001*4520Snw141292 }
3002*4520Snw141292 
3003*4520Snw141292 /*
3004*4520Snw141292 ** Print the definition of the union used for the parser's data stack.
3005*4520Snw141292 ** This union contains fields for every possible data type for tokens
3006*4520Snw141292 ** and nonterminals.  In the process of computing and printing this
3007*4520Snw141292 ** union, also set the ".dtnum" field of every terminal and nonterminal
3008*4520Snw141292 ** symbol.
3009*4520Snw141292 */
print_stack_union(out,lemp,plineno,mhflag)3010*4520Snw141292 void print_stack_union(out,lemp,plineno,mhflag)
3011*4520Snw141292 FILE *out;                  /* The output stream */
3012*4520Snw141292 struct lemon *lemp;         /* The main info structure for this parser */
3013*4520Snw141292 int *plineno;               /* Pointer to the line number */
3014*4520Snw141292 int mhflag;                 /* True if generating makeheaders output */
3015*4520Snw141292 {
3016*4520Snw141292   int lineno = *plineno;    /* The line number of the output */
3017*4520Snw141292   char **types;             /* A hash table of datatypes */
3018*4520Snw141292   int arraysize;            /* Size of the "types" array */
3019*4520Snw141292   int maxdtlength;          /* Maximum length of any ".datatype" field. */
3020*4520Snw141292   char *stddt;              /* Standardized name for a datatype */
3021*4520Snw141292   int i,j;                  /* Loop counters */
3022*4520Snw141292   int hash;                 /* For hashing the name of a type */
3023*4520Snw141292   char *name;               /* Name of the parser */
3024*4520Snw141292 
3025*4520Snw141292   /* Allocate and initialize types[] and allocate stddt[] */
3026*4520Snw141292   arraysize = lemp->nsymbol * 2;
3027*4520Snw141292   types = (char**)malloc( arraysize * sizeof(char*) );
3028*4520Snw141292   for(i=0; i<arraysize; i++) types[i] = 0;
3029*4520Snw141292   maxdtlength = 0;
3030*4520Snw141292   if( lemp->vartype ){
3031*4520Snw141292     maxdtlength = strlen(lemp->vartype);
3032*4520Snw141292   }
3033*4520Snw141292   for(i=0; i<lemp->nsymbol; i++){
3034*4520Snw141292     int len;
3035*4520Snw141292     struct symbol *sp = lemp->symbols[i];
3036*4520Snw141292     if( sp->datatype==0 ) continue;
3037*4520Snw141292     len = strlen(sp->datatype);
3038*4520Snw141292     if( len>maxdtlength ) maxdtlength = len;
3039*4520Snw141292   }
3040*4520Snw141292   stddt = (char*)malloc( maxdtlength*2 + 1 );
3041*4520Snw141292   if( types==0 || stddt==0 ){
3042*4520Snw141292     fprintf(stderr,"Out of memory.\n");
3043*4520Snw141292     exit(1);
3044*4520Snw141292   }
3045*4520Snw141292 
3046*4520Snw141292   /* Build a hash table of datatypes. The ".dtnum" field of each symbol
3047*4520Snw141292   ** is filled in with the hash index plus 1.  A ".dtnum" value of 0 is
3048*4520Snw141292   ** used for terminal symbols.  If there is no %default_type defined then
3049*4520Snw141292   ** 0 is also used as the .dtnum value for nonterminals which do not specify
3050*4520Snw141292   ** a datatype using the %type directive.
3051*4520Snw141292   */
3052*4520Snw141292   for(i=0; i<lemp->nsymbol; i++){
3053*4520Snw141292     struct symbol *sp = lemp->symbols[i];
3054*4520Snw141292     char *cp;
3055*4520Snw141292     if( sp==lemp->errsym ){
3056*4520Snw141292       sp->dtnum = arraysize+1;
3057*4520Snw141292       continue;
3058*4520Snw141292     }
3059*4520Snw141292     if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
3060*4520Snw141292       sp->dtnum = 0;
3061*4520Snw141292       continue;
3062*4520Snw141292     }
3063*4520Snw141292     cp = sp->datatype;
3064*4520Snw141292     if( cp==0 ) cp = lemp->vartype;
3065*4520Snw141292     j = 0;
3066*4520Snw141292     while( isspace(*cp) ) cp++;
3067*4520Snw141292     while( *cp ) stddt[j++] = *cp++;
3068*4520Snw141292     while( j>0 && isspace(stddt[j-1]) ) j--;
3069*4520Snw141292     stddt[j] = 0;
3070*4520Snw141292     hash = 0;
3071*4520Snw141292     for(j=0; stddt[j]; j++){
3072*4520Snw141292       hash = hash*53 + stddt[j];
3073*4520Snw141292     }
3074*4520Snw141292     hash = (hash & 0x7fffffff)%arraysize;
3075*4520Snw141292     while( types[hash] ){
3076*4520Snw141292       if( strcmp(types[hash],stddt)==0 ){
3077*4520Snw141292         sp->dtnum = hash + 1;
3078*4520Snw141292         break;
3079*4520Snw141292       }
3080*4520Snw141292       hash++;
3081*4520Snw141292       if( hash>=arraysize ) hash = 0;
3082*4520Snw141292     }
3083*4520Snw141292     if( types[hash]==0 ){
3084*4520Snw141292       sp->dtnum = hash + 1;
3085*4520Snw141292       types[hash] = (char*)malloc( strlen(stddt)+1 );
3086*4520Snw141292       if( types[hash]==0 ){
3087*4520Snw141292         fprintf(stderr,"Out of memory.\n");
3088*4520Snw141292         exit(1);
3089*4520Snw141292       }
3090*4520Snw141292       strcpy(types[hash],stddt);
3091*4520Snw141292     }
3092*4520Snw141292   }
3093*4520Snw141292 
3094*4520Snw141292   /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
3095*4520Snw141292   name = lemp->name ? lemp->name : "Parse";
3096*4520Snw141292   lineno = *plineno;
3097*4520Snw141292   if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
3098*4520Snw141292   fprintf(out,"#define %sTOKENTYPE %s\n",name,
3099*4520Snw141292     lemp->tokentype?lemp->tokentype:"void*");  lineno++;
3100*4520Snw141292   if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
3101*4520Snw141292   fprintf(out,"typedef union {\n"); lineno++;
3102*4520Snw141292   fprintf(out,"  %sTOKENTYPE yy0;\n",name); lineno++;
3103*4520Snw141292   for(i=0; i<arraysize; i++){
3104*4520Snw141292     if( types[i]==0 ) continue;
3105*4520Snw141292     fprintf(out,"  %s yy%d;\n",types[i],i+1); lineno++;
3106*4520Snw141292     free(types[i]);
3107*4520Snw141292   }
3108*4520Snw141292   fprintf(out,"  int yy%d;\n",lemp->errsym->dtnum); lineno++;
3109*4520Snw141292   free(stddt);
3110*4520Snw141292   free(types);
3111*4520Snw141292   fprintf(out,"} YYMINORTYPE;\n"); lineno++;
3112*4520Snw141292   *plineno = lineno;
3113*4520Snw141292 }
3114*4520Snw141292 
3115*4520Snw141292 /*
3116*4520Snw141292 ** Return the name of a C datatype able to represent values between
3117*4520Snw141292 ** lwr and upr, inclusive.
3118*4520Snw141292 */
minimum_size_type(int lwr,int upr)3119*4520Snw141292 static const char *minimum_size_type(int lwr, int upr){
3120*4520Snw141292   if( lwr>=0 ){
3121*4520Snw141292     if( upr<=255 ){
3122*4520Snw141292       return "unsigned char";
3123*4520Snw141292     }else if( upr<65535 ){
3124*4520Snw141292       return "unsigned short int";
3125*4520Snw141292     }else{
3126*4520Snw141292       return "unsigned int";
3127*4520Snw141292     }
3128*4520Snw141292   }else if( lwr>=-127 && upr<=127 ){
3129*4520Snw141292     return "signed char";
3130*4520Snw141292   }else if( lwr>=-32767 && upr<32767 ){
3131*4520Snw141292     return "short";
3132*4520Snw141292   }else{
3133*4520Snw141292     return "int";
3134*4520Snw141292   }
3135*4520Snw141292 }
3136*4520Snw141292 
3137*4520Snw141292 /*
3138*4520Snw141292 ** Each state contains a set of token transaction and a set of
3139*4520Snw141292 ** nonterminal transactions.  Each of these sets makes an instance
3140*4520Snw141292 ** of the following structure.  An array of these structures is used
3141*4520Snw141292 ** to order the creation of entries in the yy_action[] table.
3142*4520Snw141292 */
3143*4520Snw141292 struct axset {
3144*4520Snw141292   struct state *stp;   /* A pointer to a state */
3145*4520Snw141292   int isTkn;           /* True to use tokens.  False for non-terminals */
3146*4520Snw141292   int nAction;         /* Number of actions */
3147*4520Snw141292 };
3148*4520Snw141292 
3149*4520Snw141292 /*
3150*4520Snw141292 ** Compare to axset structures for sorting purposes
3151*4520Snw141292 */
axset_compare(const void * a,const void * b)3152*4520Snw141292 static int axset_compare(const void *a, const void *b){
3153*4520Snw141292   struct axset *p1 = (struct axset*)a;
3154*4520Snw141292   struct axset *p2 = (struct axset*)b;
3155*4520Snw141292   return p2->nAction - p1->nAction;
3156*4520Snw141292 }
3157*4520Snw141292 
3158*4520Snw141292 /* Generate C source code for the parser */
ReportTable(lemp,mhflag)3159*4520Snw141292 void ReportTable(lemp, mhflag)
3160*4520Snw141292 struct lemon *lemp;
3161*4520Snw141292 int mhflag;     /* Output in makeheaders format if true */
3162*4520Snw141292 {
3163*4520Snw141292   FILE *out, *in;
3164*4520Snw141292   char line[LINESIZE];
3165*4520Snw141292   int  lineno;
3166*4520Snw141292   struct state *stp;
3167*4520Snw141292   struct action *ap;
3168*4520Snw141292   struct rule *rp;
3169*4520Snw141292   struct acttab *pActtab;
3170*4520Snw141292   int i, j, n;
3171*4520Snw141292   char *name;
3172*4520Snw141292   int mnTknOfst, mxTknOfst;
3173*4520Snw141292   int mnNtOfst, mxNtOfst;
3174*4520Snw141292   struct axset *ax;
3175*4520Snw141292 
3176*4520Snw141292   in = tplt_open(lemp);
3177*4520Snw141292   if( in==0 ) return;
3178*4520Snw141292   out = file_open(lemp,".c","w");
3179*4520Snw141292   if( out==0 ){
3180*4520Snw141292     fclose(in);
3181*4520Snw141292     return;
3182*4520Snw141292   }
3183*4520Snw141292   lineno = 1;
3184*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3185*4520Snw141292 
3186*4520Snw141292   /* Generate the include code, if any */
3187*4520Snw141292   tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno);
3188*4520Snw141292   if( mhflag ){
3189*4520Snw141292     char *name = file_makename(lemp, ".h");
3190*4520Snw141292     fprintf(out,"#include \"%s\"\n", name); lineno++;
3191*4520Snw141292     free(name);
3192*4520Snw141292   }
3193*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3194*4520Snw141292 
3195*4520Snw141292   /* Generate #defines for all tokens */
3196*4520Snw141292   if( mhflag ){
3197*4520Snw141292     char *prefix;
3198*4520Snw141292     fprintf(out,"#if INTERFACE\n"); lineno++;
3199*4520Snw141292     if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3200*4520Snw141292     else                    prefix = "";
3201*4520Snw141292     for(i=1; i<lemp->nterminal; i++){
3202*4520Snw141292       fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3203*4520Snw141292       lineno++;
3204*4520Snw141292     }
3205*4520Snw141292     fprintf(out,"#endif\n"); lineno++;
3206*4520Snw141292   }
3207*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3208*4520Snw141292 
3209*4520Snw141292   /* Generate the defines */
3210*4520Snw141292   fprintf(out,"/* \001 */\n");
3211*4520Snw141292   fprintf(out,"#define YYCODETYPE %s\n",
3212*4520Snw141292     minimum_size_type(0, lemp->nsymbol+5)); lineno++;
3213*4520Snw141292   fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1);  lineno++;
3214*4520Snw141292   fprintf(out,"#define YYACTIONTYPE %s\n",
3215*4520Snw141292     minimum_size_type(0, lemp->nstate+lemp->nrule+5));  lineno++;
3216*4520Snw141292   print_stack_union(out,lemp,&lineno,mhflag);
3217*4520Snw141292   if( lemp->stacksize ){
3218*4520Snw141292     if( atoi(lemp->stacksize)<=0 ){
3219*4520Snw141292       ErrorMsg(lemp->filename,0,
3220*4520Snw141292 "Illegal stack size: [%s].  The stack size should be an integer constant.",
3221*4520Snw141292         lemp->stacksize);
3222*4520Snw141292       lemp->errorcnt++;
3223*4520Snw141292       lemp->stacksize = "100";
3224*4520Snw141292     }
3225*4520Snw141292     fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize);  lineno++;
3226*4520Snw141292   }else{
3227*4520Snw141292     fprintf(out,"#define YYSTACKDEPTH 100\n");  lineno++;
3228*4520Snw141292   }
3229*4520Snw141292   if( mhflag ){
3230*4520Snw141292     fprintf(out,"#if INTERFACE\n"); lineno++;
3231*4520Snw141292   }
3232*4520Snw141292   name = lemp->name ? lemp->name : "Parse";
3233*4520Snw141292   if( lemp->arg && lemp->arg[0] ){
3234*4520Snw141292     int i;
3235*4520Snw141292     i = strlen(lemp->arg);
3236*4520Snw141292     while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
3237*4520Snw141292     while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
3238*4520Snw141292     fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg);  lineno++;
3239*4520Snw141292     fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg);  lineno++;
3240*4520Snw141292     fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
3241*4520Snw141292                  name,lemp->arg,&lemp->arg[i]);  lineno++;
3242*4520Snw141292     fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
3243*4520Snw141292                  name,&lemp->arg[i],&lemp->arg[i]);  lineno++;
3244*4520Snw141292   }else{
3245*4520Snw141292     fprintf(out,"#define %sARG_SDECL\n",name);  lineno++;
3246*4520Snw141292     fprintf(out,"#define %sARG_PDECL\n",name);  lineno++;
3247*4520Snw141292     fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
3248*4520Snw141292     fprintf(out,"#define %sARG_STORE\n",name); lineno++;
3249*4520Snw141292   }
3250*4520Snw141292   if( mhflag ){
3251*4520Snw141292     fprintf(out,"#endif\n"); lineno++;
3252*4520Snw141292   }
3253*4520Snw141292   fprintf(out,"#define YYNSTATE %d\n",lemp->nstate);  lineno++;
3254*4520Snw141292   fprintf(out,"#define YYNRULE %d\n",lemp->nrule);  lineno++;
3255*4520Snw141292   fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index);  lineno++;
3256*4520Snw141292   fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum);  lineno++;
3257*4520Snw141292   if( lemp->has_fallback ){
3258*4520Snw141292     fprintf(out,"#define YYFALLBACK 1\n");  lineno++;
3259*4520Snw141292   }
3260*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3261*4520Snw141292 
3262*4520Snw141292   /* Generate the action table and its associates:
3263*4520Snw141292   **
3264*4520Snw141292   **  yy_action[]        A single table containing all actions.
3265*4520Snw141292   **  yy_lookahead[]     A table containing the lookahead for each entry in
3266*4520Snw141292   **                     yy_action.  Used to detect hash collisions.
3267*4520Snw141292   **  yy_shift_ofst[]    For each state, the offset into yy_action for
3268*4520Snw141292   **                     shifting terminals.
3269*4520Snw141292   **  yy_reduce_ofst[]   For each state, the offset into yy_action for
3270*4520Snw141292   **                     shifting non-terminals after a reduce.
3271*4520Snw141292   **  yy_default[]       Default action for each state.
3272*4520Snw141292   */
3273*4520Snw141292 
3274*4520Snw141292   /* Compute the actions on all states and count them up */
3275*4520Snw141292   ax = malloc( sizeof(ax[0])*lemp->nstate*2 );
3276*4520Snw141292   if( ax==0 ){
3277*4520Snw141292     fprintf(stderr,"malloc failed\n");
3278*4520Snw141292     exit(1);
3279*4520Snw141292   }
3280*4520Snw141292   for(i=0; i<lemp->nstate; i++){
3281*4520Snw141292     stp = lemp->sorted[i];
3282*4520Snw141292     stp->nTknAct = stp->nNtAct = 0;
3283*4520Snw141292     stp->iDflt = lemp->nstate + lemp->nrule;
3284*4520Snw141292     stp->iTknOfst = NO_OFFSET;
3285*4520Snw141292     stp->iNtOfst = NO_OFFSET;
3286*4520Snw141292     for(ap=stp->ap; ap; ap=ap->next){
3287*4520Snw141292       if( compute_action(lemp,ap)>=0 ){
3288*4520Snw141292         if( ap->sp->index<lemp->nterminal ){
3289*4520Snw141292           stp->nTknAct++;
3290*4520Snw141292         }else if( ap->sp->index<lemp->nsymbol ){
3291*4520Snw141292           stp->nNtAct++;
3292*4520Snw141292         }else{
3293*4520Snw141292           stp->iDflt = compute_action(lemp, ap);
3294*4520Snw141292         }
3295*4520Snw141292       }
3296*4520Snw141292     }
3297*4520Snw141292     ax[i*2].stp = stp;
3298*4520Snw141292     ax[i*2].isTkn = 1;
3299*4520Snw141292     ax[i*2].nAction = stp->nTknAct;
3300*4520Snw141292     ax[i*2+1].stp = stp;
3301*4520Snw141292     ax[i*2+1].isTkn = 0;
3302*4520Snw141292     ax[i*2+1].nAction = stp->nNtAct;
3303*4520Snw141292   }
3304*4520Snw141292   mxTknOfst = mnTknOfst = 0;
3305*4520Snw141292   mxNtOfst = mnNtOfst = 0;
3306*4520Snw141292 
3307*4520Snw141292   /* Compute the action table.  In order to try to keep the size of the
3308*4520Snw141292   ** action table to a minimum, the heuristic of placing the largest action
3309*4520Snw141292   ** sets first is used.
3310*4520Snw141292   */
3311*4520Snw141292   qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare);
3312*4520Snw141292   pActtab = acttab_alloc();
3313*4520Snw141292   for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){
3314*4520Snw141292     stp = ax[i].stp;
3315*4520Snw141292     if( ax[i].isTkn ){
3316*4520Snw141292       for(ap=stp->ap; ap; ap=ap->next){
3317*4520Snw141292         int action;
3318*4520Snw141292         if( ap->sp->index>=lemp->nterminal ) continue;
3319*4520Snw141292         action = compute_action(lemp, ap);
3320*4520Snw141292         if( action<0 ) continue;
3321*4520Snw141292         acttab_action(pActtab, ap->sp->index, action);
3322*4520Snw141292       }
3323*4520Snw141292       stp->iTknOfst = acttab_insert(pActtab);
3324*4520Snw141292       if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
3325*4520Snw141292       if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
3326*4520Snw141292     }else{
3327*4520Snw141292       for(ap=stp->ap; ap; ap=ap->next){
3328*4520Snw141292         int action;
3329*4520Snw141292         if( ap->sp->index<lemp->nterminal ) continue;
3330*4520Snw141292         if( ap->sp->index==lemp->nsymbol ) continue;
3331*4520Snw141292         action = compute_action(lemp, ap);
3332*4520Snw141292         if( action<0 ) continue;
3333*4520Snw141292         acttab_action(pActtab, ap->sp->index, action);
3334*4520Snw141292       }
3335*4520Snw141292       stp->iNtOfst = acttab_insert(pActtab);
3336*4520Snw141292       if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
3337*4520Snw141292       if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
3338*4520Snw141292     }
3339*4520Snw141292   }
3340*4520Snw141292   free(ax);
3341*4520Snw141292 
3342*4520Snw141292   /* Output the yy_action table */
3343*4520Snw141292   fprintf(out,"static YYACTIONTYPE yy_action[] = {\n"); lineno++;
3344*4520Snw141292   n = acttab_size(pActtab);
3345*4520Snw141292   for(i=j=0; i<n; i++){
3346*4520Snw141292     int action = acttab_yyaction(pActtab, i);
3347*4520Snw141292     if( action<0 ) action = lemp->nsymbol + lemp->nrule + 2;
3348*4520Snw141292     if( j==0 ) fprintf(out," /* %5d */ ", i);
3349*4520Snw141292     fprintf(out, " %4d,", action);
3350*4520Snw141292     if( j==9 || i==n-1 ){
3351*4520Snw141292       fprintf(out, "\n"); lineno++;
3352*4520Snw141292       j = 0;
3353*4520Snw141292     }else{
3354*4520Snw141292       j++;
3355*4520Snw141292     }
3356*4520Snw141292   }
3357*4520Snw141292   fprintf(out, "};\n"); lineno++;
3358*4520Snw141292 
3359*4520Snw141292   /* Output the yy_lookahead table */
3360*4520Snw141292   fprintf(out,"static YYCODETYPE yy_lookahead[] = {\n"); lineno++;
3361*4520Snw141292   for(i=j=0; i<n; i++){
3362*4520Snw141292     int la = acttab_yylookahead(pActtab, i);
3363*4520Snw141292     if( la<0 ) la = lemp->nsymbol;
3364*4520Snw141292     if( j==0 ) fprintf(out," /* %5d */ ", i);
3365*4520Snw141292     fprintf(out, " %4d,", la);
3366*4520Snw141292     if( j==9 || i==n-1 ){
3367*4520Snw141292       fprintf(out, "\n"); lineno++;
3368*4520Snw141292       j = 0;
3369*4520Snw141292     }else{
3370*4520Snw141292       j++;
3371*4520Snw141292     }
3372*4520Snw141292   }
3373*4520Snw141292   fprintf(out, "};\n"); lineno++;
3374*4520Snw141292 
3375*4520Snw141292   /* Output the yy_shift_ofst[] table */
3376*4520Snw141292   fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
3377*4520Snw141292   fprintf(out, "static %s yy_shift_ofst[] = {\n",
3378*4520Snw141292           minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
3379*4520Snw141292   n = lemp->nstate;
3380*4520Snw141292   for(i=j=0; i<n; i++){
3381*4520Snw141292     int ofst;
3382*4520Snw141292     stp = lemp->sorted[i];
3383*4520Snw141292     ofst = stp->iTknOfst;
3384*4520Snw141292     if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
3385*4520Snw141292     if( j==0 ) fprintf(out," /* %5d */ ", i);
3386*4520Snw141292     fprintf(out, " %4d,", ofst);
3387*4520Snw141292     if( j==9 || i==n-1 ){
3388*4520Snw141292       fprintf(out, "\n"); lineno++;
3389*4520Snw141292       j = 0;
3390*4520Snw141292     }else{
3391*4520Snw141292       j++;
3392*4520Snw141292     }
3393*4520Snw141292   }
3394*4520Snw141292   fprintf(out, "};\n"); lineno++;
3395*4520Snw141292 
3396*4520Snw141292   /* Output the yy_reduce_ofst[] table */
3397*4520Snw141292   fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
3398*4520Snw141292   fprintf(out, "static %s yy_reduce_ofst[] = {\n",
3399*4520Snw141292           minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
3400*4520Snw141292   n = lemp->nstate;
3401*4520Snw141292   for(i=j=0; i<n; i++){
3402*4520Snw141292     int ofst;
3403*4520Snw141292     stp = lemp->sorted[i];
3404*4520Snw141292     ofst = stp->iNtOfst;
3405*4520Snw141292     if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
3406*4520Snw141292     if( j==0 ) fprintf(out," /* %5d */ ", i);
3407*4520Snw141292     fprintf(out, " %4d,", ofst);
3408*4520Snw141292     if( j==9 || i==n-1 ){
3409*4520Snw141292       fprintf(out, "\n"); lineno++;
3410*4520Snw141292       j = 0;
3411*4520Snw141292     }else{
3412*4520Snw141292       j++;
3413*4520Snw141292     }
3414*4520Snw141292   }
3415*4520Snw141292   fprintf(out, "};\n"); lineno++;
3416*4520Snw141292 
3417*4520Snw141292   /* Output the default action table */
3418*4520Snw141292   fprintf(out, "static YYACTIONTYPE yy_default[] = {\n"); lineno++;
3419*4520Snw141292   n = lemp->nstate;
3420*4520Snw141292   for(i=j=0; i<n; i++){
3421*4520Snw141292     stp = lemp->sorted[i];
3422*4520Snw141292     if( j==0 ) fprintf(out," /* %5d */ ", i);
3423*4520Snw141292     fprintf(out, " %4d,", stp->iDflt);
3424*4520Snw141292     if( j==9 || i==n-1 ){
3425*4520Snw141292       fprintf(out, "\n"); lineno++;
3426*4520Snw141292       j = 0;
3427*4520Snw141292     }else{
3428*4520Snw141292       j++;
3429*4520Snw141292     }
3430*4520Snw141292   }
3431*4520Snw141292   fprintf(out, "};\n"); lineno++;
3432*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3433*4520Snw141292 
3434*4520Snw141292   /* Generate the table of fallback tokens.
3435*4520Snw141292   */
3436*4520Snw141292   if( lemp->has_fallback ){
3437*4520Snw141292     for(i=0; i<lemp->nterminal; i++){
3438*4520Snw141292       struct symbol *p = lemp->symbols[i];
3439*4520Snw141292       if( p->fallback==0 ){
3440*4520Snw141292         fprintf(out, "    0,  /* %10s => nothing */\n", p->name);
3441*4520Snw141292       }else{
3442*4520Snw141292         fprintf(out, "  %3d,  /* %10s => %s */\n", p->fallback->index,
3443*4520Snw141292           p->name, p->fallback->name);
3444*4520Snw141292       }
3445*4520Snw141292       lineno++;
3446*4520Snw141292     }
3447*4520Snw141292   }
3448*4520Snw141292   tplt_xfer(lemp->name, in, out, &lineno);
3449*4520Snw141292 
3450*4520Snw141292   /* Generate a table containing the symbolic name of every symbol
3451*4520Snw141292   */
3452*4520Snw141292   for(i=0; i<lemp->nsymbol; i++){
3453*4520Snw141292     sprintf(line,"\"%s\",",lemp->symbols[i]->name);
3454*4520Snw141292     fprintf(out,"  %-15s",line);
3455*4520Snw141292     if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
3456*4520Snw141292   }
3457*4520Snw141292   if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
3458*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3459*4520Snw141292 
3460*4520Snw141292   /* Generate a table containing a text string that describes every
3461*4520Snw141292   ** rule in the rule set of the grammer.  This information is used
3462*4520Snw141292   ** when tracing REDUCE actions.
3463*4520Snw141292   */
3464*4520Snw141292   for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
3465*4520Snw141292     assert( rp->index==i );
3466*4520Snw141292     fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
3467*4520Snw141292     for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name);
3468*4520Snw141292     fprintf(out,"\",\n"); lineno++;
3469*4520Snw141292   }
3470*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3471*4520Snw141292 
3472*4520Snw141292   /* Generate code which executes every time a symbol is popped from
3473*4520Snw141292   ** the stack while processing errors or while destroying the parser.
3474*4520Snw141292   ** (In other words, generate the %destructor actions)
3475*4520Snw141292   */
3476*4520Snw141292   if( lemp->tokendest ){
3477*4520Snw141292     for(i=0; i<lemp->nsymbol; i++){
3478*4520Snw141292       struct symbol *sp = lemp->symbols[i];
3479*4520Snw141292       if( sp==0 || sp->type!=TERMINAL ) continue;
3480*4520Snw141292       fprintf(out,"    case %d:\n",sp->index); lineno++;
3481*4520Snw141292     }
3482*4520Snw141292     for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
3483*4520Snw141292     if( i<lemp->nsymbol ){
3484*4520Snw141292       emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3485*4520Snw141292       fprintf(out,"      break;\n"); lineno++;
3486*4520Snw141292     }
3487*4520Snw141292   }
3488*4520Snw141292   for(i=0; i<lemp->nsymbol; i++){
3489*4520Snw141292     struct symbol *sp = lemp->symbols[i];
3490*4520Snw141292     if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
3491*4520Snw141292     fprintf(out,"    case %d:\n",sp->index); lineno++;
3492*4520Snw141292     emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3493*4520Snw141292     fprintf(out,"      break;\n"); lineno++;
3494*4520Snw141292   }
3495*4520Snw141292   if( lemp->vardest ){
3496*4520Snw141292     struct symbol *dflt_sp = 0;
3497*4520Snw141292     for(i=0; i<lemp->nsymbol; i++){
3498*4520Snw141292       struct symbol *sp = lemp->symbols[i];
3499*4520Snw141292       if( sp==0 || sp->type==TERMINAL ||
3500*4520Snw141292           sp->index<=0 || sp->destructor!=0 ) continue;
3501*4520Snw141292       fprintf(out,"    case %d:\n",sp->index); lineno++;
3502*4520Snw141292       dflt_sp = sp;
3503*4520Snw141292     }
3504*4520Snw141292     if( dflt_sp!=0 ){
3505*4520Snw141292       emit_destructor_code(out,dflt_sp,lemp,&lineno);
3506*4520Snw141292       fprintf(out,"      break;\n"); lineno++;
3507*4520Snw141292     }
3508*4520Snw141292   }
3509*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3510*4520Snw141292 
3511*4520Snw141292   /* Generate code which executes whenever the parser stack overflows */
3512*4520Snw141292   tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
3513*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3514*4520Snw141292 
3515*4520Snw141292   /* Generate the table of rule information
3516*4520Snw141292   **
3517*4520Snw141292   ** Note: This code depends on the fact that rules are number
3518*4520Snw141292   ** sequentually beginning with 0.
3519*4520Snw141292   */
3520*4520Snw141292   for(rp=lemp->rule; rp; rp=rp->next){
3521*4520Snw141292     fprintf(out,"  { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
3522*4520Snw141292   }
3523*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3524*4520Snw141292 
3525*4520Snw141292   /* Generate code which execution during each REDUCE action */
3526*4520Snw141292   for(rp=lemp->rule; rp; rp=rp->next){
3527*4520Snw141292     fprintf(out,"      case %d:\n",rp->index); lineno++;
3528*4520Snw141292     emit_code(out,rp,lemp,&lineno);
3529*4520Snw141292     fprintf(out,"        break;\n"); lineno++;
3530*4520Snw141292   }
3531*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3532*4520Snw141292 
3533*4520Snw141292   /* Generate code which executes if a parse fails */
3534*4520Snw141292   tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);
3535*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3536*4520Snw141292 
3537*4520Snw141292   /* Generate code which executes when a syntax error occurs */
3538*4520Snw141292   tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno);
3539*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3540*4520Snw141292 
3541*4520Snw141292   /* Generate code which executes when the parser accepts its input */
3542*4520Snw141292   tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno);
3543*4520Snw141292   tplt_xfer(lemp->name,in,out,&lineno);
3544*4520Snw141292 
3545*4520Snw141292   /* Append any addition code the user desires */
3546*4520Snw141292   tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno);
3547*4520Snw141292 
3548*4520Snw141292   fclose(in);
3549*4520Snw141292   fclose(out);
3550*4520Snw141292   return;
3551*4520Snw141292 }
3552*4520Snw141292 
3553*4520Snw141292 /* Generate a header file for the parser */
ReportHeader(lemp)3554*4520Snw141292 void ReportHeader(lemp)
3555*4520Snw141292 struct lemon *lemp;
3556*4520Snw141292 {
3557*4520Snw141292   FILE *out, *in;
3558*4520Snw141292   char *prefix;
3559*4520Snw141292   char line[LINESIZE];
3560*4520Snw141292   char pattern[LINESIZE];
3561*4520Snw141292   int i;
3562*4520Snw141292 
3563*4520Snw141292   if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3564*4520Snw141292   else                    prefix = "";
3565*4520Snw141292   in = file_open(lemp,".h","r");
3566*4520Snw141292   if( in ){
3567*4520Snw141292     for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
3568*4520Snw141292       sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3569*4520Snw141292       if( strcmp(line,pattern) ) break;
3570*4520Snw141292     }
3571*4520Snw141292     fclose(in);
3572*4520Snw141292     if( i==lemp->nterminal ){
3573*4520Snw141292       /* No change in the file.  Don't rewrite it. */
3574*4520Snw141292       return;
3575*4520Snw141292     }
3576*4520Snw141292   }
3577*4520Snw141292   out = file_open(lemp,".h","w");
3578*4520Snw141292   if( out ){
3579*4520Snw141292     for(i=1; i<lemp->nterminal; i++){
3580*4520Snw141292       fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3581*4520Snw141292     }
3582*4520Snw141292     fclose(out);
3583*4520Snw141292   }
3584*4520Snw141292   return;
3585*4520Snw141292 }
3586*4520Snw141292 
3587*4520Snw141292 /* Reduce the size of the action tables, if possible, by making use
3588*4520Snw141292 ** of defaults.
3589*4520Snw141292 **
3590*4520Snw141292 ** In this version, we take the most frequent REDUCE action and make
3591*4520Snw141292 ** it the default.  Only default a reduce if there are more than one.
3592*4520Snw141292 */
CompressTables(lemp)3593*4520Snw141292 void CompressTables(lemp)
3594*4520Snw141292 struct lemon *lemp;
3595*4520Snw141292 {
3596*4520Snw141292   struct state *stp;
3597*4520Snw141292   struct action *ap, *ap2;
3598*4520Snw141292   struct rule *rp, *rp2, *rbest;
3599*4520Snw141292   int nbest, n;
3600*4520Snw141292   int i;
3601*4520Snw141292 
3602*4520Snw141292   for(i=0; i<lemp->nstate; i++){
3603*4520Snw141292     stp = lemp->sorted[i];
3604*4520Snw141292     nbest = 0;
3605*4520Snw141292     rbest = 0;
3606*4520Snw141292 
3607*4520Snw141292     for(ap=stp->ap; ap; ap=ap->next){
3608*4520Snw141292       if( ap->type!=REDUCE ) continue;
3609*4520Snw141292       rp = ap->x.rp;
3610*4520Snw141292       if( rp==rbest ) continue;
3611*4520Snw141292       n = 1;
3612*4520Snw141292       for(ap2=ap->next; ap2; ap2=ap2->next){
3613*4520Snw141292         if( ap2->type!=REDUCE ) continue;
3614*4520Snw141292         rp2 = ap2->x.rp;
3615*4520Snw141292         if( rp2==rbest ) continue;
3616*4520Snw141292         if( rp2==rp ) n++;
3617*4520Snw141292       }
3618*4520Snw141292       if( n>nbest ){
3619*4520Snw141292         nbest = n;
3620*4520Snw141292         rbest = rp;
3621*4520Snw141292       }
3622*4520Snw141292     }
3623*4520Snw141292 
3624*4520Snw141292     /* Do not make a default if the number of rules to default
3625*4520Snw141292     ** is not at least 2 */
3626*4520Snw141292     if( nbest<2 ) continue;
3627*4520Snw141292 
3628*4520Snw141292 
3629*4520Snw141292     /* Combine matching REDUCE actions into a single default */
3630*4520Snw141292     for(ap=stp->ap; ap; ap=ap->next){
3631*4520Snw141292       if( ap->type==REDUCE && ap->x.rp==rbest ) break;
3632*4520Snw141292     }
3633*4520Snw141292     assert( ap );
3634*4520Snw141292     ap->sp = Symbol_new("{default}");
3635*4520Snw141292     for(ap=ap->next; ap; ap=ap->next){
3636*4520Snw141292       if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
3637*4520Snw141292     }
3638*4520Snw141292     stp->ap = Action_sort(stp->ap);
3639*4520Snw141292   }
3640*4520Snw141292 }
3641*4520Snw141292 
3642*4520Snw141292 /***************** From the file "set.c" ************************************/
3643*4520Snw141292 /*
3644*4520Snw141292 ** Set manipulation routines for the LEMON parser generator.
3645*4520Snw141292 */
3646*4520Snw141292 
3647*4520Snw141292 static int size = 0;
3648*4520Snw141292 
3649*4520Snw141292 /* Set the set size */
SetSize(n)3650*4520Snw141292 void SetSize(n)
3651*4520Snw141292 int n;
3652*4520Snw141292 {
3653*4520Snw141292   size = n+1;
3654*4520Snw141292 }
3655*4520Snw141292 
3656*4520Snw141292 /* Allocate a new set */
SetNew()3657*4520Snw141292 char *SetNew(){
3658*4520Snw141292   char *s;
3659*4520Snw141292   int i;
3660*4520Snw141292   s = (char*)malloc( size );
3661*4520Snw141292   if( s==0 ){
3662*4520Snw141292     extern void memory_error();
3663*4520Snw141292     memory_error();
3664*4520Snw141292   }
3665*4520Snw141292   for(i=0; i<size; i++) s[i] = 0;
3666*4520Snw141292   return s;
3667*4520Snw141292 }
3668*4520Snw141292 
3669*4520Snw141292 /* Deallocate a set */
SetFree(s)3670*4520Snw141292 void SetFree(s)
3671*4520Snw141292 char *s;
3672*4520Snw141292 {
3673*4520Snw141292   free(s);
3674*4520Snw141292 }
3675*4520Snw141292 
3676*4520Snw141292 /* Add a new element to the set.  Return TRUE if the element was added
3677*4520Snw141292 ** and FALSE if it was already there. */
SetAdd(s,e)3678*4520Snw141292 int SetAdd(s,e)
3679*4520Snw141292 char *s;
3680*4520Snw141292 int e;
3681*4520Snw141292 {
3682*4520Snw141292   int rv;
3683*4520Snw141292   rv = s[e];
3684*4520Snw141292   s[e] = 1;
3685*4520Snw141292   return !rv;
3686*4520Snw141292 }
3687*4520Snw141292 
3688*4520Snw141292 /* Add every element of s2 to s1.  Return TRUE if s1 changes. */
SetUnion(s1,s2)3689*4520Snw141292 int SetUnion(s1,s2)
3690*4520Snw141292 char *s1;
3691*4520Snw141292 char *s2;
3692*4520Snw141292 {
3693*4520Snw141292   int i, progress;
3694*4520Snw141292   progress = 0;
3695*4520Snw141292   for(i=0; i<size; i++){
3696*4520Snw141292     if( s2[i]==0 ) continue;
3697*4520Snw141292     if( s1[i]==0 ){
3698*4520Snw141292       progress = 1;
3699*4520Snw141292       s1[i] = 1;
3700*4520Snw141292     }
3701*4520Snw141292   }
3702*4520Snw141292   return progress;
3703*4520Snw141292 }
3704*4520Snw141292 /********************** From the file "table.c" ****************************/
3705*4520Snw141292 /*
3706*4520Snw141292 ** All code in this file has been automatically generated
3707*4520Snw141292 ** from a specification in the file
3708*4520Snw141292 **              "table.q"
3709*4520Snw141292 ** by the associative array code building program "aagen".
3710*4520Snw141292 ** Do not edit this file!  Instead, edit the specification
3711*4520Snw141292 ** file, then rerun aagen.
3712*4520Snw141292 */
3713*4520Snw141292 /*
3714*4520Snw141292 ** Code for processing tables in the LEMON parser generator.
3715*4520Snw141292 */
3716*4520Snw141292 
strhash(x)3717*4520Snw141292 PRIVATE int strhash(x)
3718*4520Snw141292 char *x;
3719*4520Snw141292 {
3720*4520Snw141292   int h = 0;
3721*4520Snw141292   while( *x) h = h*13 + *(x++);
3722*4520Snw141292   return h;
3723*4520Snw141292 }
3724*4520Snw141292 
3725*4520Snw141292 /* Works like strdup, sort of.  Save a string in malloced memory, but
3726*4520Snw141292 ** keep strings in a table so that the same string is not in more
3727*4520Snw141292 ** than one place.
3728*4520Snw141292 */
Strsafe(y)3729*4520Snw141292 char *Strsafe(y)
3730*4520Snw141292 char *y;
3731*4520Snw141292 {
3732*4520Snw141292   char *z;
3733*4520Snw141292 
3734*4520Snw141292   z = Strsafe_find(y);
3735*4520Snw141292   if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
3736*4520Snw141292     strcpy(z,y);
3737*4520Snw141292     Strsafe_insert(z);
3738*4520Snw141292   }
3739*4520Snw141292   MemoryCheck(z);
3740*4520Snw141292   return z;
3741*4520Snw141292 }
3742*4520Snw141292 
3743*4520Snw141292 /* There is one instance of the following structure for each
3744*4520Snw141292 ** associative array of type "x1".
3745*4520Snw141292 */
3746*4520Snw141292 struct s_x1 {
3747*4520Snw141292   int size;               /* The number of available slots. */
3748*4520Snw141292                           /*   Must be a power of 2 greater than or */
3749*4520Snw141292                           /*   equal to 1 */
3750*4520Snw141292   int count;              /* Number of currently slots filled */
3751*4520Snw141292   struct s_x1node *tbl;  /* The data stored here */
3752*4520Snw141292   struct s_x1node **ht;  /* Hash table for lookups */
3753*4520Snw141292 };
3754*4520Snw141292 
3755*4520Snw141292 /* There is one instance of this structure for every data element
3756*4520Snw141292 ** in an associative array of type "x1".
3757*4520Snw141292 */
3758*4520Snw141292 typedef struct s_x1node {
3759*4520Snw141292   char *data;                  /* The data */
3760*4520Snw141292   struct s_x1node *next;   /* Next entry with the same hash */
3761*4520Snw141292   struct s_x1node **from;  /* Previous link */
3762*4520Snw141292 } x1node;
3763*4520Snw141292 
3764*4520Snw141292 /* There is only one instance of the array, which is the following */
3765*4520Snw141292 static struct s_x1 *x1a;
3766*4520Snw141292 
3767*4520Snw141292 /* Allocate a new associative array */
Strsafe_init()3768*4520Snw141292 void Strsafe_init(){
3769*4520Snw141292   if( x1a ) return;
3770*4520Snw141292   x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
3771*4520Snw141292   if( x1a ){
3772*4520Snw141292     x1a->size = 1024;
3773*4520Snw141292     x1a->count = 0;
3774*4520Snw141292     x1a->tbl = (x1node*)malloc(
3775*4520Snw141292       (sizeof(x1node) + sizeof(x1node*))*1024 );
3776*4520Snw141292     if( x1a->tbl==0 ){
3777*4520Snw141292       free(x1a);
3778*4520Snw141292       x1a = 0;
3779*4520Snw141292     }else{
3780*4520Snw141292       int i;
3781*4520Snw141292       x1a->ht = (x1node**)&(x1a->tbl[1024]);
3782*4520Snw141292       for(i=0; i<1024; i++) x1a->ht[i] = 0;
3783*4520Snw141292     }
3784*4520Snw141292   }
3785*4520Snw141292 }
3786*4520Snw141292 /* Insert a new record into the array.  Return TRUE if successful.
3787*4520Snw141292 ** Prior data with the same key is NOT overwritten */
Strsafe_insert(data)3788*4520Snw141292 int Strsafe_insert(data)
3789*4520Snw141292 char *data;
3790*4520Snw141292 {
3791*4520Snw141292   x1node *np;
3792*4520Snw141292   int h;
3793*4520Snw141292   int ph;
3794*4520Snw141292 
3795*4520Snw141292   if( x1a==0 ) return 0;
3796*4520Snw141292   ph = strhash(data);
3797*4520Snw141292   h = ph & (x1a->size-1);
3798*4520Snw141292   np = x1a->ht[h];
3799*4520Snw141292   while( np ){
3800*4520Snw141292     if( strcmp(np->data,data)==0 ){
3801*4520Snw141292       /* An existing entry with the same key is found. */
3802*4520Snw141292       /* Fail because overwrite is not allows. */
3803*4520Snw141292       return 0;
3804*4520Snw141292     }
3805*4520Snw141292     np = np->next;
3806*4520Snw141292   }
3807*4520Snw141292   if( x1a->count>=x1a->size ){
3808*4520Snw141292     /* Need to make the hash table bigger */
3809*4520Snw141292     int i,size;
3810*4520Snw141292     struct s_x1 array;
3811*4520Snw141292     array.size = size = x1a->size*2;
3812*4520Snw141292     array.count = x1a->count;
3813*4520Snw141292     array.tbl = (x1node*)malloc(
3814*4520Snw141292       (sizeof(x1node) + sizeof(x1node*))*size );
3815*4520Snw141292     if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
3816*4520Snw141292     array.ht = (x1node**)&(array.tbl[size]);
3817*4520Snw141292     for(i=0; i<size; i++) array.ht[i] = 0;
3818*4520Snw141292     for(i=0; i<x1a->count; i++){
3819*4520Snw141292       x1node *oldnp, *newnp;
3820*4520Snw141292       oldnp = &(x1a->tbl[i]);
3821*4520Snw141292       h = strhash(oldnp->data) & (size-1);
3822*4520Snw141292       newnp = &(array.tbl[i]);
3823*4520Snw141292       if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3824*4520Snw141292       newnp->next = array.ht[h];
3825*4520Snw141292       newnp->data = oldnp->data;
3826*4520Snw141292       newnp->from = &(array.ht[h]);
3827*4520Snw141292       array.ht[h] = newnp;
3828*4520Snw141292     }
3829*4520Snw141292     free(x1a->tbl);
3830*4520Snw141292     *x1a = array;
3831*4520Snw141292   }
3832*4520Snw141292   /* Insert the new data */
3833*4520Snw141292   h = ph & (x1a->size-1);
3834*4520Snw141292   np = &(x1a->tbl[x1a->count++]);
3835*4520Snw141292   np->data = data;
3836*4520Snw141292   if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
3837*4520Snw141292   np->next = x1a->ht[h];
3838*4520Snw141292   x1a->ht[h] = np;
3839*4520Snw141292   np->from = &(x1a->ht[h]);
3840*4520Snw141292   return 1;
3841*4520Snw141292 }
3842*4520Snw141292 
3843*4520Snw141292 /* Return a pointer to data assigned to the given key.  Return NULL
3844*4520Snw141292 ** if no such key. */
Strsafe_find(key)3845*4520Snw141292 char *Strsafe_find(key)
3846*4520Snw141292 char *key;
3847*4520Snw141292 {
3848*4520Snw141292   int h;
3849*4520Snw141292   x1node *np;
3850*4520Snw141292 
3851*4520Snw141292   if( x1a==0 ) return 0;
3852*4520Snw141292   h = strhash(key) & (x1a->size-1);
3853*4520Snw141292   np = x1a->ht[h];
3854*4520Snw141292   while( np ){
3855*4520Snw141292     if( strcmp(np->data,key)==0 ) break;
3856*4520Snw141292     np = np->next;
3857*4520Snw141292   }
3858*4520Snw141292   return np ? np->data : 0;
3859*4520Snw141292 }
3860*4520Snw141292 
3861*4520Snw141292 /* Return a pointer to the (terminal or nonterminal) symbol "x".
3862*4520Snw141292 ** Create a new symbol if this is the first time "x" has been seen.
3863*4520Snw141292 */
Symbol_new(x)3864*4520Snw141292 struct symbol *Symbol_new(x)
3865*4520Snw141292 char *x;
3866*4520Snw141292 {
3867*4520Snw141292   struct symbol *sp;
3868*4520Snw141292 
3869*4520Snw141292   sp = Symbol_find(x);
3870*4520Snw141292   if( sp==0 ){
3871*4520Snw141292     sp = (struct symbol *)malloc( sizeof(struct symbol) );
3872*4520Snw141292     MemoryCheck(sp);
3873*4520Snw141292     sp->name = Strsafe(x);
3874*4520Snw141292     sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
3875*4520Snw141292     sp->rule = 0;
3876*4520Snw141292     sp->fallback = 0;
3877*4520Snw141292     sp->prec = -1;
3878*4520Snw141292     sp->assoc = UNK;
3879*4520Snw141292     sp->firstset = 0;
3880*4520Snw141292     sp->lambda = B_FALSE;
3881*4520Snw141292     sp->destructor = 0;
3882*4520Snw141292     sp->datatype = 0;
3883*4520Snw141292     Symbol_insert(sp,sp->name);
3884*4520Snw141292   }
3885*4520Snw141292   return sp;
3886*4520Snw141292 }
3887*4520Snw141292 
3888*4520Snw141292 /* Compare two symbols for working purposes
3889*4520Snw141292 **
3890*4520Snw141292 ** Symbols that begin with upper case letters (terminals or tokens)
3891*4520Snw141292 ** must sort before symbols that begin with lower case letters
3892*4520Snw141292 ** (non-terminals).  Other than that, the order does not matter.
3893*4520Snw141292 **
3894*4520Snw141292 ** We find experimentally that leaving the symbols in their original
3895*4520Snw141292 ** order (the order they appeared in the grammar file) gives the
3896*4520Snw141292 ** smallest parser tables in SQLite.
3897*4520Snw141292 */
Symbolcmpp(struct symbol ** a,struct symbol ** b)3898*4520Snw141292 int Symbolcmpp(struct symbol **a, struct symbol **b){
3899*4520Snw141292   int i1 = (**a).index + 10000000*((**a).name[0]>'Z');
3900*4520Snw141292   int i2 = (**b).index + 10000000*((**b).name[0]>'Z');
3901*4520Snw141292   return i1-i2;
3902*4520Snw141292 }
3903*4520Snw141292 
3904*4520Snw141292 /* There is one instance of the following structure for each
3905*4520Snw141292 ** associative array of type "x2".
3906*4520Snw141292 */
3907*4520Snw141292 struct s_x2 {
3908*4520Snw141292   int size;               /* The number of available slots. */
3909*4520Snw141292                           /*   Must be a power of 2 greater than or */
3910*4520Snw141292                           /*   equal to 1 */
3911*4520Snw141292   int count;              /* Number of currently slots filled */
3912*4520Snw141292   struct s_x2node *tbl;  /* The data stored here */
3913*4520Snw141292   struct s_x2node **ht;  /* Hash table for lookups */
3914*4520Snw141292 };
3915*4520Snw141292 
3916*4520Snw141292 /* There is one instance of this structure for every data element
3917*4520Snw141292 ** in an associative array of type "x2".
3918*4520Snw141292 */
3919*4520Snw141292 typedef struct s_x2node {
3920*4520Snw141292   struct symbol *data;                  /* The data */
3921*4520Snw141292   char *key;                   /* The key */
3922*4520Snw141292   struct s_x2node *next;   /* Next entry with the same hash */
3923*4520Snw141292   struct s_x2node **from;  /* Previous link */
3924*4520Snw141292 } x2node;
3925*4520Snw141292 
3926*4520Snw141292 /* There is only one instance of the array, which is the following */
3927*4520Snw141292 static struct s_x2 *x2a;
3928*4520Snw141292 
3929*4520Snw141292 /* Allocate a new associative array */
Symbol_init()3930*4520Snw141292 void Symbol_init(){
3931*4520Snw141292   if( x2a ) return;
3932*4520Snw141292   x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
3933*4520Snw141292   if( x2a ){
3934*4520Snw141292     x2a->size = 128;
3935*4520Snw141292     x2a->count = 0;
3936*4520Snw141292     x2a->tbl = (x2node*)malloc(
3937*4520Snw141292       (sizeof(x2node) + sizeof(x2node*))*128 );
3938*4520Snw141292     if( x2a->tbl==0 ){
3939*4520Snw141292       free(x2a);
3940*4520Snw141292       x2a = 0;
3941*4520Snw141292     }else{
3942*4520Snw141292       int i;
3943*4520Snw141292       x2a->ht = (x2node**)&(x2a->tbl[128]);
3944*4520Snw141292       for(i=0; i<128; i++) x2a->ht[i] = 0;
3945*4520Snw141292     }
3946*4520Snw141292   }
3947*4520Snw141292 }
3948*4520Snw141292 /* Insert a new record into the array.  Return TRUE if successful.
3949*4520Snw141292 ** Prior data with the same key is NOT overwritten */
Symbol_insert(data,key)3950*4520Snw141292 int Symbol_insert(data,key)
3951*4520Snw141292 struct symbol *data;
3952*4520Snw141292 char *key;
3953*4520Snw141292 {
3954*4520Snw141292   x2node *np;
3955*4520Snw141292   int h;
3956*4520Snw141292   int ph;
3957*4520Snw141292 
3958*4520Snw141292   if( x2a==0 ) return 0;
3959*4520Snw141292   ph = strhash(key);
3960*4520Snw141292   h = ph & (x2a->size-1);
3961*4520Snw141292   np = x2a->ht[h];
3962*4520Snw141292   while( np ){
3963*4520Snw141292     if( strcmp(np->key,key)==0 ){
3964*4520Snw141292       /* An existing entry with the same key is found. */
3965*4520Snw141292       /* Fail because overwrite is not allows. */
3966*4520Snw141292       return 0;
3967*4520Snw141292     }
3968*4520Snw141292     np = np->next;
3969*4520Snw141292   }
3970*4520Snw141292   if( x2a->count>=x2a->size ){
3971*4520Snw141292     /* Need to make the hash table bigger */
3972*4520Snw141292     int i,size;
3973*4520Snw141292     struct s_x2 array;
3974*4520Snw141292     array.size = size = x2a->size*2;
3975*4520Snw141292     array.count = x2a->count;
3976*4520Snw141292     array.tbl = (x2node*)malloc(
3977*4520Snw141292       (sizeof(x2node) + sizeof(x2node*))*size );
3978*4520Snw141292     if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
3979*4520Snw141292     array.ht = (x2node**)&(array.tbl[size]);
3980*4520Snw141292     for(i=0; i<size; i++) array.ht[i] = 0;
3981*4520Snw141292     for(i=0; i<x2a->count; i++){
3982*4520Snw141292       x2node *oldnp, *newnp;
3983*4520Snw141292       oldnp = &(x2a->tbl[i]);
3984*4520Snw141292       h = strhash(oldnp->key) & (size-1);
3985*4520Snw141292       newnp = &(array.tbl[i]);
3986*4520Snw141292       if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3987*4520Snw141292       newnp->next = array.ht[h];
3988*4520Snw141292       newnp->key = oldnp->key;
3989*4520Snw141292       newnp->data = oldnp->data;
3990*4520Snw141292       newnp->from = &(array.ht[h]);
3991*4520Snw141292       array.ht[h] = newnp;
3992*4520Snw141292     }
3993*4520Snw141292     free(x2a->tbl);
3994*4520Snw141292     *x2a = array;
3995*4520Snw141292   }
3996*4520Snw141292   /* Insert the new data */
3997*4520Snw141292   h = ph & (x2a->size-1);
3998*4520Snw141292   np = &(x2a->tbl[x2a->count++]);
3999*4520Snw141292   np->key = key;
4000*4520Snw141292   np->data = data;
4001*4520Snw141292   if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
4002*4520Snw141292   np->next = x2a->ht[h];
4003*4520Snw141292   x2a->ht[h] = np;
4004*4520Snw141292   np->from = &(x2a->ht[h]);
4005*4520Snw141292   return 1;
4006*4520Snw141292 }
4007*4520Snw141292 
4008*4520Snw141292 /* Return a pointer to data assigned to the given key.  Return NULL
4009*4520Snw141292 ** if no such key. */
Symbol_find(key)4010*4520Snw141292 struct symbol *Symbol_find(key)
4011*4520Snw141292 char *key;
4012*4520Snw141292 {
4013*4520Snw141292   int h;
4014*4520Snw141292   x2node *np;
4015*4520Snw141292 
4016*4520Snw141292   if( x2a==0 ) return 0;
4017*4520Snw141292   h = strhash(key) & (x2a->size-1);
4018*4520Snw141292   np = x2a->ht[h];
4019*4520Snw141292   while( np ){
4020*4520Snw141292     if( strcmp(np->key,key)==0 ) break;
4021*4520Snw141292     np = np->next;
4022*4520Snw141292   }
4023*4520Snw141292   return np ? np->data : 0;
4024*4520Snw141292 }
4025*4520Snw141292 
4026*4520Snw141292 /* Return the n-th data.  Return NULL if n is out of range. */
Symbol_Nth(n)4027*4520Snw141292 struct symbol *Symbol_Nth(n)
4028*4520Snw141292 int n;
4029*4520Snw141292 {
4030*4520Snw141292   struct symbol *data;
4031*4520Snw141292   if( x2a && n>0 && n<=x2a->count ){
4032*4520Snw141292     data = x2a->tbl[n-1].data;
4033*4520Snw141292   }else{
4034*4520Snw141292     data = 0;
4035*4520Snw141292   }
4036*4520Snw141292   return data;
4037*4520Snw141292 }
4038*4520Snw141292 
4039*4520Snw141292 /* Return the size of the array */
Symbol_count()4040*4520Snw141292 int Symbol_count()
4041*4520Snw141292 {
4042*4520Snw141292   return x2a ? x2a->count : 0;
4043*4520Snw141292 }
4044*4520Snw141292 
4045*4520Snw141292 /* Return an array of pointers to all data in the table.
4046*4520Snw141292 ** The array is obtained from malloc.  Return NULL if memory allocation
4047*4520Snw141292 ** problems, or if the array is empty. */
Symbol_arrayof()4048*4520Snw141292 struct symbol **Symbol_arrayof()
4049*4520Snw141292 {
4050*4520Snw141292   struct symbol **array;
4051*4520Snw141292   int i,size;
4052*4520Snw141292   if( x2a==0 ) return 0;
4053*4520Snw141292   size = x2a->count;
4054*4520Snw141292   array = (struct symbol **)malloc( sizeof(struct symbol *)*size );
4055*4520Snw141292   if( array ){
4056*4520Snw141292     for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
4057*4520Snw141292   }
4058*4520Snw141292   return array;
4059*4520Snw141292 }
4060*4520Snw141292 
4061*4520Snw141292 /* Compare two configurations */
Configcmp(a,b)4062*4520Snw141292 int Configcmp(a,b)
4063*4520Snw141292 struct config *a;
4064*4520Snw141292 struct config *b;
4065*4520Snw141292 {
4066*4520Snw141292   int x;
4067*4520Snw141292   x = a->rp->index - b->rp->index;
4068*4520Snw141292   if( x==0 ) x = a->dot - b->dot;
4069*4520Snw141292   return x;
4070*4520Snw141292 }
4071*4520Snw141292 
4072*4520Snw141292 /* Compare two states */
statecmp(a,b)4073*4520Snw141292 PRIVATE int statecmp(a,b)
4074*4520Snw141292 struct config *a;
4075*4520Snw141292 struct config *b;
4076*4520Snw141292 {
4077*4520Snw141292   int rc;
4078*4520Snw141292   for(rc=0; rc==0 && a && b;  a=a->bp, b=b->bp){
4079*4520Snw141292     rc = a->rp->index - b->rp->index;
4080*4520Snw141292     if( rc==0 ) rc = a->dot - b->dot;
4081*4520Snw141292   }
4082*4520Snw141292   if( rc==0 ){
4083*4520Snw141292     if( a ) rc = 1;
4084*4520Snw141292     if( b ) rc = -1;
4085*4520Snw141292   }
4086*4520Snw141292   return rc;
4087*4520Snw141292 }
4088*4520Snw141292 
4089*4520Snw141292 /* Hash a state */
statehash(a)4090*4520Snw141292 PRIVATE int statehash(a)
4091*4520Snw141292 struct config *a;
4092*4520Snw141292 {
4093*4520Snw141292   int h=0;
4094*4520Snw141292   while( a ){
4095*4520Snw141292     h = h*571 + a->rp->index*37 + a->dot;
4096*4520Snw141292     a = a->bp;
4097*4520Snw141292   }
4098*4520Snw141292   return h;
4099*4520Snw141292 }
4100*4520Snw141292 
4101*4520Snw141292 /* Allocate a new state structure */
State_new()4102*4520Snw141292 struct state *State_new()
4103*4520Snw141292 {
4104*4520Snw141292   struct state *new;
4105*4520Snw141292   new = (struct state *)malloc( sizeof(struct state) );
4106*4520Snw141292   MemoryCheck(new);
4107*4520Snw141292   return new;
4108*4520Snw141292 }
4109*4520Snw141292 
4110*4520Snw141292 /* There is one instance of the following structure for each
4111*4520Snw141292 ** associative array of type "x3".
4112*4520Snw141292 */
4113*4520Snw141292 struct s_x3 {
4114*4520Snw141292   int size;               /* The number of available slots. */
4115*4520Snw141292                           /*   Must be a power of 2 greater than or */
4116*4520Snw141292                           /*   equal to 1 */
4117*4520Snw141292   int count;              /* Number of currently slots filled */
4118*4520Snw141292   struct s_x3node *tbl;  /* The data stored here */
4119*4520Snw141292   struct s_x3node **ht;  /* Hash table for lookups */
4120*4520Snw141292 };
4121*4520Snw141292 
4122*4520Snw141292 /* There is one instance of this structure for every data element
4123*4520Snw141292 ** in an associative array of type "x3".
4124*4520Snw141292 */
4125*4520Snw141292 typedef struct s_x3node {
4126*4520Snw141292   struct state *data;                  /* The data */
4127*4520Snw141292   struct config *key;                   /* The key */
4128*4520Snw141292   struct s_x3node *next;   /* Next entry with the same hash */
4129*4520Snw141292   struct s_x3node **from;  /* Previous link */
4130*4520Snw141292 } x3node;
4131*4520Snw141292 
4132*4520Snw141292 /* There is only one instance of the array, which is the following */
4133*4520Snw141292 static struct s_x3 *x3a;
4134*4520Snw141292 
4135*4520Snw141292 /* Allocate a new associative array */
State_init()4136*4520Snw141292 void State_init(){
4137*4520Snw141292   if( x3a ) return;
4138*4520Snw141292   x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
4139*4520Snw141292   if( x3a ){
4140*4520Snw141292     x3a->size = 128;
4141*4520Snw141292     x3a->count = 0;
4142*4520Snw141292     x3a->tbl = (x3node*)malloc(
4143*4520Snw141292       (sizeof(x3node) + sizeof(x3node*))*128 );
4144*4520Snw141292     if( x3a->tbl==0 ){
4145*4520Snw141292       free(x3a);
4146*4520Snw141292       x3a = 0;
4147*4520Snw141292     }else{
4148*4520Snw141292       int i;
4149*4520Snw141292       x3a->ht = (x3node**)&(x3a->tbl[128]);
4150*4520Snw141292       for(i=0; i<128; i++) x3a->ht[i] = 0;
4151*4520Snw141292     }
4152*4520Snw141292   }
4153*4520Snw141292 }
4154*4520Snw141292 /* Insert a new record into the array.  Return TRUE if successful.
4155*4520Snw141292 ** Prior data with the same key is NOT overwritten */
State_insert(data,key)4156*4520Snw141292 int State_insert(data,key)
4157*4520Snw141292 struct state *data;
4158*4520Snw141292 struct config *key;
4159*4520Snw141292 {
4160*4520Snw141292   x3node *np;
4161*4520Snw141292   int h;
4162*4520Snw141292   int ph;
4163*4520Snw141292 
4164*4520Snw141292   if( x3a==0 ) return 0;
4165*4520Snw141292   ph = statehash(key);
4166*4520Snw141292   h = ph & (x3a->size-1);
4167*4520Snw141292   np = x3a->ht[h];
4168*4520Snw141292   while( np ){
4169*4520Snw141292     if( statecmp(np->key,key)==0 ){
4170*4520Snw141292       /* An existing entry with the same key is found. */
4171*4520Snw141292       /* Fail because overwrite is not allows. */
4172*4520Snw141292       return 0;
4173*4520Snw141292     }
4174*4520Snw141292     np = np->next;
4175*4520Snw141292   }
4176*4520Snw141292   if( x3a->count>=x3a->size ){
4177*4520Snw141292     /* Need to make the hash table bigger */
4178*4520Snw141292     int i,size;
4179*4520Snw141292     struct s_x3 array;
4180*4520Snw141292     array.size = size = x3a->size*2;
4181*4520Snw141292     array.count = x3a->count;
4182*4520Snw141292     array.tbl = (x3node*)malloc(
4183*4520Snw141292       (sizeof(x3node) + sizeof(x3node*))*size );
4184*4520Snw141292     if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
4185*4520Snw141292     array.ht = (x3node**)&(array.tbl[size]);
4186*4520Snw141292     for(i=0; i<size; i++) array.ht[i] = 0;
4187*4520Snw141292     for(i=0; i<x3a->count; i++){
4188*4520Snw141292       x3node *oldnp, *newnp;
4189*4520Snw141292       oldnp = &(x3a->tbl[i]);
4190*4520Snw141292       h = statehash(oldnp->key) & (size-1);
4191*4520Snw141292       newnp = &(array.tbl[i]);
4192*4520Snw141292       if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4193*4520Snw141292       newnp->next = array.ht[h];
4194*4520Snw141292       newnp->key = oldnp->key;
4195*4520Snw141292       newnp->data = oldnp->data;
4196*4520Snw141292       newnp->from = &(array.ht[h]);
4197*4520Snw141292       array.ht[h] = newnp;
4198*4520Snw141292     }
4199*4520Snw141292     free(x3a->tbl);
4200*4520Snw141292     *x3a = array;
4201*4520Snw141292   }
4202*4520Snw141292   /* Insert the new data */
4203*4520Snw141292   h = ph & (x3a->size-1);
4204*4520Snw141292   np = &(x3a->tbl[x3a->count++]);
4205*4520Snw141292   np->key = key;
4206*4520Snw141292   np->data = data;
4207*4520Snw141292   if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
4208*4520Snw141292   np->next = x3a->ht[h];
4209*4520Snw141292   x3a->ht[h] = np;
4210*4520Snw141292   np->from = &(x3a->ht[h]);
4211*4520Snw141292   return 1;
4212*4520Snw141292 }
4213*4520Snw141292 
4214*4520Snw141292 /* Return a pointer to data assigned to the given key.  Return NULL
4215*4520Snw141292 ** if no such key. */
State_find(key)4216*4520Snw141292 struct state *State_find(key)
4217*4520Snw141292 struct config *key;
4218*4520Snw141292 {
4219*4520Snw141292   int h;
4220*4520Snw141292   x3node *np;
4221*4520Snw141292 
4222*4520Snw141292   if( x3a==0 ) return 0;
4223*4520Snw141292   h = statehash(key) & (x3a->size-1);
4224*4520Snw141292   np = x3a->ht[h];
4225*4520Snw141292   while( np ){
4226*4520Snw141292     if( statecmp(np->key,key)==0 ) break;
4227*4520Snw141292     np = np->next;
4228*4520Snw141292   }
4229*4520Snw141292   return np ? np->data : 0;
4230*4520Snw141292 }
4231*4520Snw141292 
4232*4520Snw141292 /* Return an array of pointers to all data in the table.
4233*4520Snw141292 ** The array is obtained from malloc.  Return NULL if memory allocation
4234*4520Snw141292 ** problems, or if the array is empty. */
State_arrayof()4235*4520Snw141292 struct state **State_arrayof()
4236*4520Snw141292 {
4237*4520Snw141292   struct state **array;
4238*4520Snw141292   int i,size;
4239*4520Snw141292   if( x3a==0 ) return 0;
4240*4520Snw141292   size = x3a->count;
4241*4520Snw141292   array = (struct state **)malloc( sizeof(struct state *)*size );
4242*4520Snw141292   if( array ){
4243*4520Snw141292     for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
4244*4520Snw141292   }
4245*4520Snw141292   return array;
4246*4520Snw141292 }
4247*4520Snw141292 
4248*4520Snw141292 /* Hash a configuration */
confighash(a)4249*4520Snw141292 PRIVATE int confighash(a)
4250*4520Snw141292 struct config *a;
4251*4520Snw141292 {
4252*4520Snw141292   int h=0;
4253*4520Snw141292   h = h*571 + a->rp->index*37 + a->dot;
4254*4520Snw141292   return h;
4255*4520Snw141292 }
4256*4520Snw141292 
4257*4520Snw141292 /* There is one instance of the following structure for each
4258*4520Snw141292 ** associative array of type "x4".
4259*4520Snw141292 */
4260*4520Snw141292 struct s_x4 {
4261*4520Snw141292   int size;               /* The number of available slots. */
4262*4520Snw141292                           /*   Must be a power of 2 greater than or */
4263*4520Snw141292                           /*   equal to 1 */
4264*4520Snw141292   int count;              /* Number of currently slots filled */
4265*4520Snw141292   struct s_x4node *tbl;  /* The data stored here */
4266*4520Snw141292   struct s_x4node **ht;  /* Hash table for lookups */
4267*4520Snw141292 };
4268*4520Snw141292 
4269*4520Snw141292 /* There is one instance of this structure for every data element
4270*4520Snw141292 ** in an associative array of type "x4".
4271*4520Snw141292 */
4272*4520Snw141292 typedef struct s_x4node {
4273*4520Snw141292   struct config *data;                  /* The data */
4274*4520Snw141292   struct s_x4node *next;   /* Next entry with the same hash */
4275*4520Snw141292   struct s_x4node **from;  /* Previous link */
4276*4520Snw141292 } x4node;
4277*4520Snw141292 
4278*4520Snw141292 /* There is only one instance of the array, which is the following */
4279*4520Snw141292 static struct s_x4 *x4a;
4280*4520Snw141292 
4281*4520Snw141292 /* Allocate a new associative array */
Configtable_init()4282*4520Snw141292 void Configtable_init(){
4283*4520Snw141292   if( x4a ) return;
4284*4520Snw141292   x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
4285*4520Snw141292   if( x4a ){
4286*4520Snw141292     x4a->size = 64;
4287*4520Snw141292     x4a->count = 0;
4288*4520Snw141292     x4a->tbl = (x4node*)malloc(
4289*4520Snw141292       (sizeof(x4node) + sizeof(x4node*))*64 );
4290*4520Snw141292     if( x4a->tbl==0 ){
4291*4520Snw141292       free(x4a);
4292*4520Snw141292       x4a = 0;
4293*4520Snw141292     }else{
4294*4520Snw141292       int i;
4295*4520Snw141292       x4a->ht = (x4node**)&(x4a->tbl[64]);
4296*4520Snw141292       for(i=0; i<64; i++) x4a->ht[i] = 0;
4297*4520Snw141292     }
4298*4520Snw141292   }
4299*4520Snw141292 }
4300*4520Snw141292 /* Insert a new record into the array.  Return TRUE if successful.
4301*4520Snw141292 ** Prior data with the same key is NOT overwritten */
Configtable_insert(data)4302*4520Snw141292 int Configtable_insert(data)
4303*4520Snw141292 struct config *data;
4304*4520Snw141292 {
4305*4520Snw141292   x4node *np;
4306*4520Snw141292   int h;
4307*4520Snw141292   int ph;
4308*4520Snw141292 
4309*4520Snw141292   if( x4a==0 ) return 0;
4310*4520Snw141292   ph = confighash(data);
4311*4520Snw141292   h = ph & (x4a->size-1);
4312*4520Snw141292   np = x4a->ht[h];
4313*4520Snw141292   while( np ){
4314*4520Snw141292     if( Configcmp(np->data,data)==0 ){
4315*4520Snw141292       /* An existing entry with the same key is found. */
4316*4520Snw141292       /* Fail because overwrite is not allows. */
4317*4520Snw141292       return 0;
4318*4520Snw141292     }
4319*4520Snw141292     np = np->next;
4320*4520Snw141292   }
4321*4520Snw141292   if( x4a->count>=x4a->size ){
4322*4520Snw141292     /* Need to make the hash table bigger */
4323*4520Snw141292     int i,size;
4324*4520Snw141292     struct s_x4 array;
4325*4520Snw141292     array.size = size = x4a->size*2;
4326*4520Snw141292     array.count = x4a->count;
4327*4520Snw141292     array.tbl = (x4node*)malloc(
4328*4520Snw141292       (sizeof(x4node) + sizeof(x4node*))*size );
4329*4520Snw141292     if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
4330*4520Snw141292     array.ht = (x4node**)&(array.tbl[size]);
4331*4520Snw141292     for(i=0; i<size; i++) array.ht[i] = 0;
4332*4520Snw141292     for(i=0; i<x4a->count; i++){
4333*4520Snw141292       x4node *oldnp, *newnp;
4334*4520Snw141292       oldnp = &(x4a->tbl[i]);
4335*4520Snw141292       h = confighash(oldnp->data) & (size-1);
4336*4520Snw141292       newnp = &(array.tbl[i]);
4337*4520Snw141292       if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4338*4520Snw141292       newnp->next = array.ht[h];
4339*4520Snw141292       newnp->data = oldnp->data;
4340*4520Snw141292       newnp->from = &(array.ht[h]);
4341*4520Snw141292       array.ht[h] = newnp;
4342*4520Snw141292     }
4343*4520Snw141292     free(x4a->tbl);
4344*4520Snw141292     *x4a = array;
4345*4520Snw141292   }
4346*4520Snw141292   /* Insert the new data */
4347*4520Snw141292   h = ph & (x4a->size-1);
4348*4520Snw141292   np = &(x4a->tbl[x4a->count++]);
4349*4520Snw141292   np->data = data;
4350*4520Snw141292   if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
4351*4520Snw141292   np->next = x4a->ht[h];
4352*4520Snw141292   x4a->ht[h] = np;
4353*4520Snw141292   np->from = &(x4a->ht[h]);
4354*4520Snw141292   return 1;
4355*4520Snw141292 }
4356*4520Snw141292 
4357*4520Snw141292 /* Return a pointer to data assigned to the given key.  Return NULL
4358*4520Snw141292 ** if no such key. */
Configtable_find(key)4359*4520Snw141292 struct config *Configtable_find(key)
4360*4520Snw141292 struct config *key;
4361*4520Snw141292 {
4362*4520Snw141292   int h;
4363*4520Snw141292   x4node *np;
4364*4520Snw141292 
4365*4520Snw141292   if( x4a==0 ) return 0;
4366*4520Snw141292   h = confighash(key) & (x4a->size-1);
4367*4520Snw141292   np = x4a->ht[h];
4368*4520Snw141292   while( np ){
4369*4520Snw141292     if( Configcmp(np->data,key)==0 ) break;
4370*4520Snw141292     np = np->next;
4371*4520Snw141292   }
4372*4520Snw141292   return np ? np->data : 0;
4373*4520Snw141292 }
4374*4520Snw141292 
4375*4520Snw141292 /* Remove all data from the table.  Pass each data to the function "f"
4376*4520Snw141292 ** as it is removed.  ("f" may be null to avoid this step.) */
4377*4520Snw141292 void Configtable_clear(f)
4378*4520Snw141292 int(*f)(/* struct config * */);
4379*4520Snw141292 {
4380*4520Snw141292   int i;
4381*4520Snw141292   if( x4a==0 || x4a->count==0 ) return;
4382*4520Snw141292   if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
4383*4520Snw141292   for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
4384*4520Snw141292   x4a->count = 0;
4385*4520Snw141292   return;
4386*4520Snw141292 }
4387