1 /*
2  * build.c -- functions associated with building syntax diagrams.
3  *
4  * SOFTWARE RIGHTS
5  *
6  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
7  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
8  * company may do whatever they wish with source code distributed with
9  * PCCTS or the code generated by PCCTS, including the incorporation of
10  * PCCTS, or its output, into commerical software.
11  *
12  * We encourage users to develop software with PCCTS.  However, we do ask
13  * that credit is given to us for developing PCCTS.  By "credit",
14  * we mean that if you incorporate our source code into one of your
15  * programs (commercial product, research project, or otherwise) that you
16  * acknowledge this fact somewhere in the documentation, research report,
17  * etc...  If you like PCCTS and have developed a nice tool with the
18  * output, please mention that you developed it using PCCTS.  In
19  * addition, we ask that this header remain intact in our source code.
20  * As long as these guidelines are kept, we expect to continue enhancing
21  * this system and expect to make other tools available as they are
22  * completed.
23  *
24  * ANTLR 1.33
25  * Terence Parr
26  * Parr Research Corporation
27  * with Purdue University and AHPCRC, University of Minnesota
28  * 1989-1998
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include "pcctscfg.h"
35 #include "set.h"
36 #include "syn.h"
37 #include "hash.h"
38 #include "generic.h"
39 #include "dlgdef.h"
40 
41 #define SetBlk(g, t, approx) {						   			\
42 			((Junction *)g.left)->jtype = t;					\
43 			((Junction *)g.left)->approx = approx;				\
44 			((Junction *)g.left)->end = (Junction *) g.right;	\
45 			((Junction *)g.right)->jtype = EndBlk;}
46 
47 /* Add the parameter string 'parm' to the parms field of a block-type junction
48  * g.left points to the sentinel node on a block.  i.e. g.left->p1 points to
49  * the actual junction with its jtype == some block-type.
50  */
51 void
52 #ifdef __USE_PROTOS
addParm(Node * p,char * parm)53 addParm( Node *p, char *parm )
54 #else
55 addParm( p, parm )
56 Node *p;
57 char *parm;
58 #endif
59 {
60 	char *q = (char *) malloc( strlen(parm) + 1 );
61 	require(p!=NULL, "addParm: NULL object\n");
62 	require(q!=NULL, "addParm: unable to alloc parameter\n");
63 
64 	strcpy(q, parm);
65 	if ( p->ntype == nRuleRef )
66 	{
67 		((RuleRefNode *)p)->parms = q;
68 	}
69 	else if ( p->ntype == nJunction )
70 	{
71 		((Junction *)p)->parm = q;	/* only one parameter allowed on subrules */
72 	}
73 	else fatal_internal("addParm: invalid node for adding parm");
74 }
75 
76 /*
77  * Build an action node for the syntax diagram
78  *
79  * buildAction(ACTION) ::= --o-->ACTION-->o--
80  *
81  * Where o is a junction node.
82  */
83 Graph
84 #ifdef __USE_PROTOS
buildAction(char * action,int file,int line,int is_predicate)85 buildAction( char *action, int file, int line, int is_predicate )
86 #else
87 buildAction( action, file, line, is_predicate )
88 char *action;
89 int file;
90 int line;
91 int is_predicate;
92 #endif
93 {
94 	Junction *j1, *j2;
95 	Graph g;
96 	ActionNode *a;
97 	require(action!=NULL, "buildAction: invalid action");
98 
99 	j1 = newJunction();
100 	j2 = newJunction();
101 	a = newActionNode();
102 	a->action = (char *) malloc( strlen(action)+1 );
103 	require(a->action!=NULL, "buildAction: cannot alloc space for action\n");
104 	strcpy(a->action, action);
105 	j1->p1 = (Node *) a;
106 	a->next = (Node *) j2;
107 	a->is_predicate = is_predicate;
108 
109     if (is_predicate) {
110         PredEntry   *predEntry;
111         char        *t;
112         char        *key;
113         char        *u;
114         int         inverted=0;
115 
116         t=key=(char *)calloc(1,strlen(a->action)+1);
117 
118         for (u=a->action; *u != '\0' ; u++) {
119           if (*u != ' ') {
120             if (t==key && *u=='!') {
121               inverted=!inverted;
122             } else {
123               *t++=*u;
124             };
125           };
126         };
127 
128         *t='\0';
129 
130 
131         predEntry=(PredEntry *)hash_get(Pname,key);
132         a->predEntry=predEntry;
133         if (predEntry != NULL) a->inverted=inverted;
134     } else {
135 /* MR12c */      char  *strStart=a->action;
136 /* MR12c */      char  *strEnd;
137 /* MR12c */      strEnd=strStart+strlen(strStart)-1;
138 /* MR12c */      for ( ; strEnd >= strStart &&  isspace(*strEnd); strEnd--) *strEnd=0;
139 /* MR12c */      while (*strStart != '\0' && isspace(*strStart)) strStart++;
140 /* MR12c */      if (ci_strequ(strStart,"nohoist")) {
141 /* MR12c */        a->noHoist=1;
142 /* MR12c */      }
143     };
144 
145 	g.left = (Node *) j1; g.right = (Node *) j2;
146 	a->file = file;
147 	a->line = line;
148 	a->rname = CurRule;     /* MR10 */
149 	return g;
150 }
151 
152 /*
153  * Build a token node for the syntax diagram
154  *
155  * buildToken(TOKEN) ::= --o-->TOKEN-->o--
156  *
157  * Where o is a junction node.
158  */
159 Graph
160 #ifdef __USE_PROTOS
buildToken(char * text)161 buildToken( char *text )
162 #else
163 buildToken( text )
164 char *text;
165 #endif
166 {
167 	Junction *j1, *j2;
168 	Graph g;
169 	TokNode *t;
170 	require(text!=NULL, "buildToken: invalid token name");
171 
172 	j1 = newJunction();
173 	j2 = newJunction();
174 	t = newTokNode();
175 	t->altstart = CurAltStart;
176 	if ( *text == '"' ) {t->label=FALSE; t->token = addTexpr( text );}
177 	else {t->label=TRUE; t->token = addTname( text );}
178 	j1->p1 = (Node *) t;
179 	t->next = (Node *) j2;
180 	g.left = (Node *) j1; g.right = (Node *) j2;
181 	return g;
182 }
183 
184 /*
185  * Build a wild-card node for the syntax diagram
186  *
187  * buildToken(TOKEN) ::= --o-->'.'-->o--
188  *
189  * Where o is a junction node.
190  */
191 Graph
192 #ifdef __USE_PROTOS
buildWildCard(char * text)193 buildWildCard( char *text )
194 #else
195 buildWildCard( text )
196 char *text;
197 #endif
198 {
199 	Junction *j1, *j2;
200 	Graph g;
201 	TokNode *t;
202 	TCnode *w;
203 	TermEntry *p;
204 	require(text!=NULL, "buildWildCard: invalid token name");
205 
206 	j1 = newJunction();
207 	j2 = newJunction();
208 	t = newTokNode();
209 
210 	/* If the ref a wild card, make a token class for it */
211 	if ( Tnum(WildCardString) == 0 )
212 	{
213 		w = newTCnode;
214 	  	w->tok = addTname( WildCardString );
215 		set_orel(w->tok, &imag_tokens);
216 		set_orel(w->tok, &tokclasses);
217 		WildCardToken = w->tok;
218 		require((p=(TermEntry *)hash_get(Tname, WildCardString)) != NULL,
219 				"hash table mechanism is broken");
220 		p->classname = 1;	/* entry is class name, not token */
221 		p->tclass = w;		/* save ptr to this tclass def */
222 		list_add(&tclasses, (char *)w);
223 	}
224 	else {
225 		p=(TermEntry *)hash_get(Tname, WildCardString);
226 		require( p!= NULL, "hash table mechanism is broken");
227 		w = p->tclass;
228 	}
229 
230 	t->token = w->tok;
231 	t->wild_card = 1;
232 	t->tclass = w;
233 
234 	t->altstart = CurAltStart;
235 	j1->p1 = (Node *) t;
236 	t->next = (Node *) j2;
237 	g.left = (Node *) j1; g.right = (Node *) j2;
238 	return g;
239 }
240 
241 void
242 #ifdef __USE_PROTOS
setUpperRange(TokNode * t,char * text)243 setUpperRange(TokNode *t, char *text)
244 #else
245 setUpperRange(t, text)
246 TokNode *t;
247 char *text;
248 #endif
249 {
250 	require(t!=NULL, "setUpperRange: NULL token node");
251 	require(text!=NULL, "setUpperRange: NULL token string");
252 
253 	if ( *text == '"' ) {t->upper_range = addTexpr( text );}
254 	else {t->upper_range = addTname( text );}
255 }
256 
257 /*
258  * Build a rule reference node of the syntax diagram
259  *
260  * buildRuleRef(RULE) ::= --o-->RULE-->o--
261  *
262  * Where o is a junction node.
263  *
264  * If rule 'text' has been defined already, don't alloc new space to store string.
265  * Set r->text to point to old copy in string table.
266  */
267 Graph
268 #ifdef __USE_PROTOS
buildRuleRef(char * text)269 buildRuleRef( char *text )
270 #else
271 buildRuleRef( text )
272 char *text;
273 #endif
274 {
275 	Junction *j1, *j2;
276 	Graph g;
277 	RuleRefNode *r;
278 	RuleEntry *p;
279 	require(text!=NULL, "buildRuleRef: invalid rule name");
280 
281 	j1 = newJunction();
282 	j2 = newJunction();
283 	r = newRNode();
284 	r->altstart = CurAltStart;
285 	r->assign = NULL;
286 	if ( (p=(RuleEntry *)hash_get(Rname, text)) != NULL ) r->text = p->str;
287 	else r->text = mystrdup( text );
288 	j1->p1  = (Node *) r;
289 	r->next = (Node *) j2;
290 	g.left = (Node *) j1; g.right = (Node *) j2;
291 	return g;
292 }
293 
294 /*
295  * Or two subgraphs into one graph via:
296  *
297  * Or(G1, G2) ::= --o-G1-o--
298  *                  |    ^
299  *					v    |
300  *                  o-G2-o
301  *
302  * Set the altnum of junction starting G2 to 1 + altnum of junction starting G1.
303  * If, however, the G1 altnum is 0, make it 1 and then
304  * make G2 altnum = G1 altnum + 1.
305  */
306 Graph
307 #ifdef __USE_PROTOS
Or(Graph g1,Graph g2)308 Or( Graph g1, Graph g2 )
309 #else
310 Or( g1, g2 )
311 Graph g1;
312 Graph g2;
313 #endif
314 {
315 	Graph g;
316 	require(g1.left != NULL, "Or: invalid graph");
317 	require(g2.left != NULL && g2.right != NULL, "Or: invalid graph");
318 
319 	((Junction *)g1.left)->p2 = g2.left;
320 	((Junction *)g2.right)->p1 = g1.right;
321 	/* set altnums */
322 	if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
323 	((Junction *)g2.left)->altnum = ((Junction *)g1.left)->altnum + 1;
324 	g.left = g2.left;
325 	g.right = g1.right;
326 	return g;
327 }
328 
329 /*
330  * Catenate two subgraphs
331  *
332  * Cat(G1, G2) ::= --o-G1-o-->o-G2-o--
333  * Cat(NULL,G2)::= --o-G2-o--
334  * Cat(G1,NULL)::= --o-G1-o--
335  */
336 Graph
337 #ifdef __USE_PROTOS
Cat(Graph g1,Graph g2)338 Cat( Graph g1, Graph g2 )
339 #else
340 Cat( g1, g2 )
341 Graph g1;
342 Graph g2;
343 #endif
344 {
345 	Graph g;
346 
347 	if ( g1.left == NULL && g1.right == NULL ) return g2;
348 	if ( g2.left == NULL && g2.right == NULL ) return g1;
349 	((Junction *)g1.right)->p1 = g2.left;
350 	g.left = g1.left;
351 	g.right = g2.right;
352 	return g;
353 }
354 
355 /*
356  * Make a subgraph an optional block
357  *
358  * makeOpt(G) ::= --o-->o-G-o-->o--
359  *                      | 	    ^
360  *						v  	    |
361  *					    o-------o
362  *
363  * Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found.
364  *
365  * The node on the far right is added so that every block owns its own
366  * EndBlk node.
367  */
368 Graph
369 #ifdef __USE_PROTOS
makeOpt(Graph g1,int approx)370 makeOpt( Graph g1, int approx )
371 #else
372 makeOpt( g1, approx )
373 Graph g1;
374 int approx;
375 #endif
376 {
377 	Junction *j1,*j2,*p;
378 	Graph g;
379 	require(g1.left != NULL && g1.right != NULL, "makeOpt: invalid graph");
380 
381 	j1 = newJunction();
382 	j2 = newJunction();
383 	((Junction *)g1.right)->p1 = (Node *) j2;	/* add node to G at end */
384 	g = emptyAlt();
385 	if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
386 	((Junction *)g.left)->altnum = ((Junction *)g1.left)->altnum + 1;
387 	for(p=(Junction *)g1.left; p->p2!=NULL; p=(Junction *)p->p2)
388 		{;}										/* find last alt */
389 	p->p2 = g.left;								/* add optional alternative */
390 	((Junction *)g.right)->p1 = (Node *)j2;		/* opt alt points to EndBlk */
391 	g1.right = (Node *)j2;
392 	SetBlk(g1, aOptBlk, approx);
393 	j1->p1 = g1.left;							/* add generic node in front */
394 	g.left = (Node *) j1;
395 	g.right = g1.right;
396 
397 	return g;
398 }
399 
400 /*
401  * Make a graph into subblock
402  *
403  * makeBlk(G) ::= --o-->o-G-o-->o--
404  *
405  * The node on the far right is added so that every block owns its own
406  * EndBlk node.
407  */
408 Graph
409 #ifdef __USE_PROTOS
makeBlk(Graph g1,int approx)410 makeBlk( Graph g1, int approx )
411 #else
412 makeBlk( g1, approx )
413 Graph g1;
414 int approx;
415 #endif
416 {
417 	Junction *j,*j2;
418 	Graph g;
419 	require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph");
420 
421 	j = newJunction();
422 	j2 = newJunction();
423 	((Junction *)g1.right)->p1 = (Node *) j2;	/* add node to G at end */
424 	g1.right = (Node *)j2;
425 	SetBlk(g1, aSubBlk, approx);
426 	j->p1 = g1.left;							/* add node in front */
427 	g.left = (Node *) j;
428 	g.right = g1.right;
429 
430 	return g;
431 }
432 
433 /*
434  * Make a subgraph into a loop (closure) block -- (...)*
435  *
436  * makeLoop(G) ::=       |---|
437  *					     v   |
438  *			   --o-->o-->o-G-o-->o--
439  *                   |           ^
440  *                   v           |
441  *					 o-----------o
442  *
443  * After making loop, always place generic node out front.  It becomes
444  * the start of enclosing block.  The aLoopBlk is the target of the loop.
445  *
446  * Loop blks have TWO EndBlk nodes--the far right and the node that loops back
447  * to the aLoopBlk node.  Node with which we can branch past loop == aLoopBegin and
448  * one which is loop target == aLoopBlk.
449  * The branch-past (initial) aLoopBegin node has end
450  * pointing to the last EndBlk node.  The loop-target node has end==NULL.
451  *
452  * Loop blocks have a set of locks (from 1..CLL_k) on the aLoopBlk node.
453  */
454 Graph
455 #ifdef __USE_PROTOS
makeLoop(Graph g1,int approx)456 makeLoop( Graph g1, int approx )
457 #else
458 makeLoop( g1, approx )
459 Graph g1;
460 int approx;
461 #endif
462 {
463 	Junction *back, *front, *begin;
464 	Graph g;
465 	require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph");
466 
467 	back = newJunction();
468 	front = newJunction();
469 	begin = newJunction();
470 	g = emptyAlt();
471 	((Junction *)g1.right)->p2 = g1.left;		/* add loop branch to G */
472 	((Junction *)g1.right)->p1 = (Node *) back;	/* add node to G at end */
473 	((Junction *)g1.right)->jtype = EndBlk;		/* mark 1st EndBlk node */
474 	((Junction *)g1.left)->jtype = aLoopBlk;	/* mark 2nd aLoopBlk node */
475 	((Junction *)g1.left)->end = (Junction *) g1.right;
476 	((Junction *)g1.left)->lock = makelocks();
477 	((Junction *)g1.left)->pred_lock = makelocks();
478 	g1.right = (Node *) back;
479 	begin->p1 = (Node *) g1.left;
480 	g1.left = (Node *) begin;
481 	begin->p2 = (Node *) g.left;				/* make bypass arc */
482 	((Junction *)g.right)->p1 = (Node *) back;
483 	SetBlk(g1, aLoopBegin, approx);
484 	front->p1 = g1.left;						/* add node to front */
485 	g1.left = (Node *) front;
486 
487 	return g1;
488 }
489 
490 /*
491  * Make a subgraph into a plus block -- (...)+ -- 1 or more times
492  *
493  * makePlus(G) ::=	 |---|
494  *					 v   |
495  *			   --o-->o-G-o-->o--
496  *
497  * After making loop, always place generic node out front.  It becomes
498  * the start of enclosing block.  The aPlusBlk is the target of the loop.
499  *
500  * Plus blks have TWO EndBlk nodes--the far right and the node that loops back
501  * to the aPlusBlk node.
502  *
503  * Plus blocks have a set of locks (from 1..CLL_k) on the aPlusBlk node.
504  */
505 Graph
506 #ifdef __USE_PROTOS
makePlus(Graph g1,int approx)507 makePlus( Graph g1, int approx )
508 #else
509 makePlus( g1, approx )
510 Graph g1;
511 int approx;
512 #endif
513 {
514 	int has_empty_alt_already = 0;
515 	Graph g;
516 	Junction *j2, *j3, *first_alt;
517 	Junction *last_alt=NULL, *p;
518 	require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph");
519 
520 	first_alt = (Junction *)g1.left;
521 	j2 = newJunction();
522 	j3 = newJunction();
523 	if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;
524 	((Junction *)g1.right)->p2 = g1.left;		/* add loop branch to G */
525 	((Junction *)g1.right)->p1 = (Node *) j2;	/* add node to G at end */
526 	((Junction *)g1.right)->jtype = EndBlk;		/* mark 1st EndBlk node */
527 	g1.right = (Node *) j2;
528 	SetBlk(g1, aPlusBlk, approx);
529 	((Junction *)g1.left)->lock = makelocks();
530 	((Junction *)g1.left)->pred_lock = makelocks();
531 	j3->p1 = g1.left;							/* add node to front */
532 	g1.left = (Node *) j3;
533 
534 	/* add an optional branch which is the "exit" branch of loop */
535 	/* FIRST, check to ensure that there does not already exist
536 	 * an optional path.
537 	 */
538 	/* find last alt */
539 	for(p=first_alt; p!=NULL; p=(Junction *)p->p2)
540 	{
541 		if ( p->p1->ntype == nJunction &&
542 			 p->p1!=NULL &&
543 			 ((Junction *)p->p1)->jtype==Generic &&
544 			 ((Junction *)p->p1)->p1!=NULL &&
545 			 ((Junction *)((Junction *)p->p1)->p1)->jtype==EndBlk )
546 		{
547 			has_empty_alt_already = 1;
548 		}
549 		last_alt = p;
550 	}
551 	if ( !has_empty_alt_already )
552 	{
553 		require(last_alt!=NULL, "last_alt==NULL; bad (..)+");
554 		g = emptyAlt();
555 		last_alt->p2 = g.left;
556 		((Junction *)g.right)->p1 = (Node *) j2;
557 
558 		/* make sure lookahead computation ignores this alt for
559 		* FIRST("(..)+"); but it's still used for computing the FIRST
560 		* of each alternative.
561 		*/
562 		((Junction *)g.left)->ignore = 1;
563 	}
564 
565 	return g1;
566 }
567 
568 /*
569  * Return an optional path:  --o-->o--
570  */
571 Graph
572 #ifdef __USE_PROTOS
emptyAlt(void)573 emptyAlt( void )
574 #else
575 emptyAlt( )
576 #endif
577 {
578 	Junction *j1, *j2;
579 	Graph g;
580 
581 	j1 = newJunction();
582 	j2 = newJunction();
583 	j1->p1 = (Node *) j2;
584 	g.left = (Node *) j1;
585 	g.right = (Node *) j2;
586 
587 	return g;
588 }
589 
590 /* N o d e  A l l o c a t i o n */
591 
592 TokNode *
593 #ifdef __USE_PROTOS
newTokNode(void)594 newTokNode( void )
595 #else
596 newTokNode( )
597 #endif
598 {
599 	static TokNode *FreeList = NULL;
600 	TokNode *p, *newblk;
601 
602 	if ( FreeList == NULL )
603 	{
604 		newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode));
605 		if ( newblk == NULL )
606 			fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
607 		for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++)
608 		{
609 			p->next = (Node *)FreeList;	/* add all new token nodes to FreeList */
610 			FreeList = p;
611 		}
612 	}
613 	p = FreeList;
614 	FreeList = (TokNode *)FreeList->next;/* remove a TokNode node */
615 	p->next = NULL;						/* NULL the ptr we used */
616     memset( (char *) p, 0, sizeof(TokNode));        /* MR10 */
617 	p->ntype = nToken;
618 	p->rname = CurRule;
619 	p->file = CurFile;
620 	p->line = zzline;
621 	p->altstart = NULL;
622 
623 	return p;
624 }
625 
626 RuleRefNode *
627 #ifdef __USE_PROTOS
newRNode(void)628 newRNode( void )
629 #else
630 newRNode( )
631 #endif
632 {
633 	static RuleRefNode *FreeList = NULL;
634 	RuleRefNode *p, *newblk;
635 
636 	if ( FreeList == NULL )
637 	{
638 		newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode));
639 		if ( newblk == NULL )
640 			fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
641 		for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++)
642 		{
643 			p->next = (Node *)FreeList;	/* add all new rref nodes to FreeList */
644 			FreeList = p;
645 		}
646 	}
647 	p = FreeList;
648 	FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */
649 	p->next = NULL;						/* NULL the ptr we used */
650     memset( (char *) p, 0, sizeof(RuleRefNode));        /* MR10 */
651 	p->ntype = nRuleRef;
652 	p->rname = CurRule;
653 	p->file = CurFile;
654 	p->line = zzline;
655 	p->astnode = ASTinclude;
656 	p->altstart = NULL;
657 
658 	return p;
659 }
660 
661 static int junctionSeqNumber=0;         /* MR10 */
662 
663 Junction *
664 #ifdef __USE_PROTOS
newJunction(void)665 newJunction( void )
666 #else
667 newJunction( )
668 #endif
669 {
670 	static Junction *FreeList = NULL;
671 	Junction *p, *newblk;
672 
673 	if ( FreeList == NULL )
674 	{
675 		newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction));
676 		if ( newblk == NULL )
677 			fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
678 		for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++)
679 		{
680 			p->p1 = (Node *)FreeList;	/* add all new Junction nodes to FreeList */
681 			FreeList = p;
682 		}
683 	}
684 	p = FreeList;
685 	FreeList = (Junction *)FreeList->p1;/* remove a Junction node */
686 	p->p1 = NULL;						/* NULL the ptr we used */
687     memset( (char *) p, 0, sizeof(Junction));       /* MR10 */
688 	p->ntype = nJunction;
689 	p->visited = 0;
690 	p->jtype = Generic;
691 	p->rname = CurRule;
692 	p->file = CurFile;
693 	p->line = zzline;
694 	p->exception_label = NULL;
695 	p->fset = (set *) calloc(CLL_k+1, sizeof(set));
696 	require(p->fset!=NULL, "cannot allocate fset in newJunction");
697     p->seq=++junctionSeqNumber;     /* MR10 */
698 
699 	return p;
700 }
701 
702 ActionNode *
703 #ifdef __USE_PROTOS
newActionNode(void)704 newActionNode( void )
705 #else
706 newActionNode( )
707 #endif
708 {
709 	static ActionNode *FreeList = NULL;
710 	ActionNode *p, *newblk;
711 
712 	if ( FreeList == NULL )
713 	{
714 		newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode));
715 		if ( newblk == NULL )
716 			fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));
717 		for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++)
718 		{
719 			p->next = (Node *)FreeList;	/* add all new Action nodes to FreeList */
720 			FreeList = p;
721 		}
722 	}
723 	p = FreeList;
724 	FreeList = (ActionNode *)FreeList->next;/* remove an Action node */
725     memset( (char *) p, 0, sizeof(ActionNode));     /* MR10 */
726 	p->ntype = nAction;
727 	p->next = NULL;						/* NULL the ptr we used */
728 	p->done = 0;
729 	p->pred_fail = NULL;
730 	p->guardpred = NULL;
731     p->ampersandPred = NULL;
732 	return p;
733 }
734 
735 /*
736  * allocate the array of locks (1..CLL_k) used to inhibit infinite recursion.
737  * Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs.
738  * Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes.
739  *
740  * if ( lock[k]==TRUE ) then we have been here before looking for k tokens
741  * of lookahead.
742  */
743 char *
744 #ifdef __USE_PROTOS
makelocks(void)745 makelocks( void )
746 #else
747 makelocks( )
748 #endif
749 {
750 	char *p = (char *) calloc(CLL_k+1, sizeof(char));
751 	require(p!=NULL, "cannot allocate lock array");
752 
753 	return p;
754 }
755 
756 #if 0
757 ** #ifdef __USE_PROTOS
758 ** void my_memset(char *p,char value,int count)
759 ** #else
760 ** void my_memset(p,value,count)
761 **   char      *p;
762 **   char      value;
763 **   int       count;
764 ** #endif
765 ** {
766 **    int      i;
767 **
768 **    for (i=0; i<count; i++) {
769 **     p[i]=value;
770 **   };
771 ** }
772 #endif
773