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