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