home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pccts.zip / pccts / antlr / build.c < prev    next >
C/C++ Source or Header  |  1994-03-31  |  17KB  |  682 lines

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