summaryrefslogtreecommitdiff
path: root/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c')
-rw-r--r--BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c1864
1 files changed, 0 insertions, 1864 deletions
diff --git a/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c b/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c
deleted file mode 100644
index 3f58da34c5..0000000000
--- a/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c
+++ /dev/null
@@ -1,1864 +0,0 @@
-/*
- * misc.c
- *
- * Manage tokens, regular expressions.
- * Print methods for debugging
- * Compute follow lists onto tail ends of rules.
- *
- * The following functions are visible:
- *
- * int addTname(char *); Add token name
- * int addTexpr(char *); Add token expression
- * int Tnum(char *); Get number of expr/token
- * void Tklink(char *, char *); Link a name with an expression
- * int hasAction(expr); Does expr already have action assigned?
- * void setHasAction(expr); Indicate that expr now has an action
- * Entry *newEntry(char *,int); Create new table entry with certain size
- * void list_add(ListNode **list, char *e)
- * void list_free(ListNode **list, int freeData); *** MR10 ***
- * void list_apply(ListNode *list, void (*f)())
- * void lexclass(char *m); switch to new/old lexical class
- * void lexmode(int i); switch to old lexical class i
- *
- * SOFTWARE RIGHTS
- *
- * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
- * Set (PCCTS) -- PCCTS is in the public domain. An individual or
- * company may do whatever they wish with source code distributed with
- * PCCTS or the code generated by PCCTS, including the incorporation of
- * PCCTS, or its output, into commerical software.
- *
- * We encourage users to develop software with PCCTS. However, we do ask
- * that credit is given to us for developing PCCTS. By "credit",
- * we mean that if you incorporate our source code into one of your
- * programs (commercial product, research project, or otherwise) that you
- * acknowledge this fact somewhere in the documentation, research report,
- * etc... If you like PCCTS and have developed a nice tool with the
- * output, please mention that you developed it using PCCTS. In
- * addition, we ask that this header remain intact in our source code.
- * As long as these guidelines are kept, we expect to continue enhancing
- * this system and expect to make other tools available as they are
- * completed.
- *
- * ANTLR 1.33
- * Terence Parr
- * Parr Research Corporation
- * with Purdue University and AHPCRC, University of Minnesota
- * 1989-2001
- */
-
-#include <stdio.h>
-#include "pcctscfg.h"
-#include "set.h"
-#include "syn.h"
-#include "hash.h"
-#include "generic.h"
-#include "dlgdef.h"
-#include <ctype.h>
-
-static int tsize=TSChunk; /* size of token str arrays */
-
-static void
-#ifdef __USE_PROTOS
-RemapForcedTokensInSyntaxDiagram(Node *);
-#else
-RemapForcedTokensInSyntaxDiagram();
-#endif
-
- /* T o k e n M a n i p u l a t i o n */
-
-/*
- * add token 't' to the TokenStr/Expr array. Make more room if necessary.
- * 't' is either an expression or a token name.
- *
- * There is only one TokenStr array, but multiple ExprStr's. Therefore,
- * for each lex class (element of lclass) we must extend the ExprStr array.
- * ExprStr's and TokenStr are always all the same size.
- *
- * Also, there is a Texpr hash table for each automaton.
- */
-static void
-#ifdef __USE_PROTOS
-Ttrack( char *t )
-#else
-Ttrack( t )
-char *t;
-#endif
-{
- if ( TokenNum >= tsize ) /* terminal table overflow? */
- {
- char **p;
- int i, more, j;
-
- more = TSChunk * (1 + ((TokenNum-tsize) / TSChunk));
- tsize += more;
- TokenStr = (char **) realloc((char *)TokenStr, tsize*sizeof(char *));
- require(TokenStr != NULL, "Ttrack: can't extend TokenStr");
- for (i=0; i<NumLexClasses; i++)
- {
- lclass[i].exprs = (char **)
- realloc((char *)lclass[i].exprs, tsize*sizeof(char *));
- require(lclass[i].exprs != NULL, "Ttrack: can't extend ExprStr");
- for (p= &lclass[i].exprs[tsize-more],j=1; j<=more; j++) *p++ = NULL;
- }
- for (p= &TokenStr[tsize-more],i=1; i<=more; i++) *p++ = NULL;
- lexmode( CurrentLexClass ); /* reset ExprStr in case table moved */
- }
- /* note: we use the actual ExprStr/TokenStr array
- * here as TokenInd doesn't exist yet
- */
- if ( *t == '"' ) ExprStr[TokenNum] = t;
- else TokenStr[TokenNum] = t;
-}
-
-static Expr *
-#ifdef __USE_PROTOS
-newExpr( char *e )
-#else
-newExpr( e )
-char *e;
-#endif
-{
- Expr *p = (Expr *) calloc(1, sizeof(Expr));
- require(p!=NULL, "newExpr: cannot alloc Expr node");
-
- p->expr = e;
- p->lclass = CurrentLexClass;
- return p;
-}
-
-/* switch to lexical class/mode m. This amounts to creating a new
- * lex mode if one does not already exist and making ExprStr point
- * to the correct char string array. We must also switch Texpr tables.
- *
- * BTW, we need multiple ExprStr arrays because more than one automaton
- * may have the same label for a token, but with different expressions.
- * We need to track an expr for each automaton. If we disallowed this
- * feature, only one ExprStr would be required.
- */
-void
-#ifdef __USE_PROTOS
-lexclass( char *m )
-#else
-lexclass( m )
-char *m;
-#endif
-{
- int i;
- TermEntry *p;
- static char EOFSTR[] = "\"@\"";
-
- if ( hash_get(Tname, m) != NULL )
- {
- warn(eMsg1("lexclass name conflicts with token/errclass label '%s'",m));
- }
- /* does m already exist? */
- i = LexClassIndex(m);
- if ( i != -1 ) {lexmode(i); return;}
- /* must make new one */
- NumLexClasses++;
- CurrentLexClass = NumLexClasses-1;
- require(NumLexClasses<=MaxLexClasses, "number of allowable lexclasses exceeded\nIncrease MaxLexClasses in generic.h and recompile all C files");
- lclass[CurrentLexClass].classnum = m;
- lclass[CurrentLexClass].exprs = (char **) calloc(tsize, sizeof(char *));
- require(lclass[CurrentLexClass].exprs!=NULL,
- "lexclass: cannot allocate ExprStr");
- lclass[CurrentLexClass].htable = newHashTable();
- ExprStr = lclass[CurrentLexClass].exprs;
- Texpr = lclass[CurrentLexClass].htable;
- /* define EOF for each automaton */
- p = newTermEntry( EOFSTR );
- p->token = EofToken; /* couldn't have remapped tokens yet, use EofToken */
- hash_add(Texpr, EOFSTR, (Entry *)p);
- list_add(&ExprOrder, (void *)newExpr(EOFSTR));
- /* note: we use the actual ExprStr array
- * here as TokenInd doesn't exist yet
- */
- ExprStr[EofToken] = EOFSTR;
-}
-
-void
-#ifdef __USE_PROTOS
-lexmode( int i )
-#else
-lexmode( i )
-int i;
-#endif
-{
- require(i<NumLexClasses, "lexmode: invalid mode");
- ExprStr = lclass[i].exprs;
- Texpr = lclass[i].htable;
- CurrentLexClass = i;
-}
-
-/* return index into lclass array of lexical class. return -1 if nonexistent */
-int
-#ifdef __USE_PROTOS
-LexClassIndex( char *cl )
-#else
-LexClassIndex( cl )
-char *cl;
-#endif
-{
- int i;
-
- for (i=0; i<NumLexClasses; i++)
- {
- if ( strcmp(lclass[i].classnum, cl) == 0 ) return i;
- }
- return -1;
-}
-
-int
-#ifdef __USE_PROTOS
-hasAction( char *expr )
-#else
-hasAction( expr )
-char *expr;
-#endif
-{
- TermEntry *p;
- require(expr!=NULL, "hasAction: invalid expr");
-
- p = (TermEntry *) hash_get(Texpr, expr);
- require(p!=NULL, eMsg1("hasAction: expr '%s' doesn't exist",expr));
- return (p->action!=NULL);
-}
-
-void
-#ifdef __USE_PROTOS
-setHasAction( char *expr, char *action )
-#else
-setHasAction( expr, action )
-char *expr;
-char *action;
-#endif
-{
- TermEntry *p;
- require(expr!=NULL, "setHasAction: invalid expr");
-
- p = (TermEntry *) hash_get(Texpr, expr);
- require(p!=NULL, eMsg1("setHasAction: expr '%s' doesn't exist",expr));
- p->action = action;
-}
-
-ForcedToken *
-#ifdef __USE_PROTOS
-newForcedToken(char *token, int tnum)
-#else
-newForcedToken(token, tnum)
-char *token;
-int tnum;
-#endif
-{
- ForcedToken *ft = (ForcedToken *) calloc(1, sizeof(ForcedToken));
- require(ft!=NULL, "out of memory");
- ft->token = token;
- ft->tnum = tnum;
- return ft;
-}
-
-/*
- * Make a token indirection array that remaps token numbers and then walk
- * the appropriate symbol tables and SynDiag to change token numbers
- */
-void
-#ifdef __USE_PROTOS
-RemapForcedTokens(void)
-#else
-RemapForcedTokens()
-#endif
-{
- ListNode *p;
- ForcedToken *q;
- int max_token_number=0; /* MR9 23-Sep-97 Removed "unsigned" */
- int i;
-
- if ( ForcedTokens == NULL ) return;
-
- /* find max token num */
- for (p = ForcedTokens->next; p!=NULL; p=p->next)
- {
- q = (ForcedToken *) p->elem;
- if ( q->tnum > max_token_number ) max_token_number = q->tnum;
- }
- fprintf(stderr, "max token number is %d\n", max_token_number);
-
- /* make token indirection array */
- TokenInd = (int *) calloc(max_token_number+1, sizeof(int));
- LastTokenCounted = TokenNum;
- TokenNum = max_token_number+1;
- require(TokenInd!=NULL, "RemapForcedTokens: cannot allocate TokenInd");
-
- /* fill token indirection array and change token id htable ; swap token indices */
- for (i=1; i<TokenNum; i++) TokenInd[i] = i;
- for (p = ForcedTokens->next; p!=NULL; p=p->next)
- {
- TermEntry *te;
- int old_pos, t;
-
- q = (ForcedToken *) p->elem;
- fprintf(stderr, "%s forced to %d\n", q->token, q->tnum);
- te = (TermEntry *) hash_get(Tname, q->token);
- require(te!=NULL, "RemapForcedTokens: token not in hash table");
- old_pos = te->token;
- fprintf(stderr, "Before: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]);
- fprintf(stderr, "Before: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]);
- q = (ForcedToken *) p->elem;
- t = TokenInd[old_pos];
- TokenInd[old_pos] = q->tnum;
- TokenInd[q->tnum] = t;
- te->token = q->tnum; /* update token type id symbol table */
- fprintf(stderr, "After: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]);
- fprintf(stderr, "After: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]);
-
- /* Change the token number in the sym tab entry for the exprs
- * at the old position of the token id and the target position
- */
- /* update expr at target (if any) of forced token id */
- if ( q->tnum < TokenNum ) /* is it a valid position? */
- {
- for (i=0; i<NumLexClasses; i++)
- {
- if ( lclass[i].exprs[q->tnum]!=NULL )
- {
- /* update the symbol table for this expr */
- TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[q->tnum]);
- require(e!=NULL, "RemapForcedTokens: expr not in hash table");
- e->token = old_pos;
- fprintf(stderr, "found expr '%s' at target %d in lclass[%d]; changed to %d\n",
- lclass[i].exprs[q->tnum], q->tnum, i, old_pos);
- }
- }
- }
- /* update expr at old position (if any) of forced token id */
- for (i=0; i<NumLexClasses; i++)
- {
- if ( lclass[i].exprs[old_pos]!=NULL )
- {
- /* update the symbol table for this expr */
- TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[old_pos]);
- require(e!=NULL, "RemapForcedTokens: expr not in hash table");
- e->token = q->tnum;
- fprintf(stderr, "found expr '%s' for id %s in lclass[%d]; changed to %d\n",
- lclass[i].exprs[old_pos], q->token, i, q->tnum);
- }
- }
- }
-
- /* Update SynDiag */
- RemapForcedTokensInSyntaxDiagram((Node *)SynDiag);
-}
-
-static void
-#ifdef __USE_PROTOS
-RemapForcedTokensInSyntaxDiagram(Node *p)
-#else
-RemapForcedTokensInSyntaxDiagram(p)
-Node *p;
-#endif
-{
- Junction *j = (Junction *) p;
- RuleRefNode *r = (RuleRefNode *) p;
- TokNode *t = (TokNode *)p;
-
- if ( p==NULL ) return;
- require(p->ntype>=1 && p->ntype<=NumNodeTypes, "Remap...: invalid diagram node");
- switch ( p->ntype )
- {
- case nJunction :
- if ( j->visited ) return;
- if ( j->jtype == EndRule ) return;
- j->visited = TRUE;
- RemapForcedTokensInSyntaxDiagram( j->p1 );
- RemapForcedTokensInSyntaxDiagram( j->p2 );
- j->visited = FALSE;
- return;
- case nRuleRef :
- RemapForcedTokensInSyntaxDiagram( r->next );
- return;
- case nToken :
- if ( t->remapped ) return; /* we've been here before */
- t->remapped = 1;
- fprintf(stderr, "remapping %d to %d\n", t->token, TokenInd[t->token]);
- t->token = TokenInd[t->token];
- RemapForcedTokensInSyntaxDiagram( t->next );
- return;
- case nAction :
- RemapForcedTokensInSyntaxDiagram( ((ActionNode *)p)->next );
- return;
- default :
- fatal_internal("invalid node type");
- }
-}
-
-/*
- * Add a token name. Return the token number associated with it. If it already
- * exists, then return the token number assigned to it.
- *
- * Track the order in which tokens are found so that the DLG output maintains
- * that order. It also lets us map token numbers to strings.
- */
-int
-#ifdef __USE_PROTOS
-addTname( char *token )
-#else
-addTname( token )
-char *token;
-#endif
-{
- TermEntry *p;
- require(token!=NULL, "addTname: invalid token name");
-
- if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token;
- p = newTermEntry( token );
- Ttrack( p->str );
- p->token = TokenNum++;
- hash_add(Tname, token, (Entry *)p);
- return p->token;
-}
-
-/* This is the same as addTname except we force the TokenNum to be tnum.
- * We don't have to use the Forced token stuff as no tokens will have
- * been defined with #tokens when this is called. This is only called
- * when a #tokdefs meta-op is used.
- */
-int
-#ifdef __USE_PROTOS
-addForcedTname( char *token, int tnum )
-#else
-addForcedTname( token, tnum )
-char *token;
-int tnum;
-#endif
-{
- TermEntry *p;
- require(token!=NULL, "addTname: invalid token name");
-
- if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token;
- p = newTermEntry( token );
- Ttrack( p->str );
- p->token = tnum;
- hash_add(Tname, token, (Entry *)p);
- return p->token;
-}
-
-/*
- * Add a token expr. Return the token number associated with it. If it already
- * exists, then return the token number assigned to it.
- */
-int
-#ifdef __USE_PROTOS
-addTexpr( char *expr )
-#else
-addTexpr( expr )
-char *expr;
-#endif
-{
- TermEntry *p;
- require(expr!=NULL, "addTexpr: invalid regular expression");
-
- if ( (p=(TermEntry *)hash_get(Texpr, expr)) != NULL ) return p->token;
- p = newTermEntry( expr );
- Ttrack( p->str );
- /* track the order in which they occur */
- list_add(&ExprOrder, (void *)newExpr(p->str));
- p->token = TokenNum++;
- hash_add(Texpr, expr, (Entry *)p);
- return p->token;
-}
-
-/* return the token number of 'term'. Return 0 if no 'term' exists */
-int
-#ifdef __USE_PROTOS
-Tnum( char *term )
-#else
-Tnum( term )
-char *term;
-#endif
-{
- TermEntry *p;
- require(term!=NULL, "Tnum: invalid terminal");
-
- if ( *term=='"' ) p = (TermEntry *) hash_get(Texpr, term);
- else p = (TermEntry *) hash_get(Tname, term);
- if ( p == NULL ) return 0;
- else return p->token;
-}
-
-/* associate a Name with an expr. If both have been already assigned
- * token numbers, then an error is reported. Add the token or expr
- * that has not been added if no error. This 'represents' the #token
- * ANTLR pseudo-op. If both have not been defined, define them both
- * linked to same token number.
- */
-void
-#ifdef __USE_PROTOS
-Tklink( char *token, char *expr )
-#else
-Tklink( token, expr )
-char *token;
-char *expr;
-#endif
-{
- TermEntry *p, *q;
- require(token!=NULL && expr!=NULL, "Tklink: invalid token name and/or expr");
-
- p = (TermEntry *) hash_get(Tname, token);
- q = (TermEntry *) hash_get(Texpr, expr);
- if ( p != NULL && q != NULL ) /* both defined */
- {
- warn( eMsg2("token name %s and rexpr %s already defined; ignored",
- token, expr) );
- return;
- }
- if ( p==NULL && q==NULL ) /* both not defined */
- {
- int t = addTname( token );
- q = newTermEntry( expr );
- hash_add(Texpr, expr, (Entry *)q);
- q->token = t;
- /* note: we use the actual ExprStr array
- * here as TokenInd doesn't exist yet
- */
- ExprStr[t] = q->str;
- /* track the order in which they occur */
- list_add(&ExprOrder, (void *)newExpr(q->str));
- return;
- }
- if ( p != NULL ) /* one is defined, one is not */
- {
- q = newTermEntry( expr );
- hash_add(Texpr, expr, (Entry *)q);
- q->token = p->token;
- ExprStr[p->token] = q->str; /* both expr and token str defined now */
- list_add(&ExprOrder, (void *)newExpr(q->str));
- }
- else /* trying to associate name with expr here*/
- {
- p = newTermEntry( token );
- hash_add(Tname, token, (Entry *)p);
- p->token = q->token;
- TokenStr[p->token] = p->str;/* both expr and token str defined now */
- }
-}
-
-/*
- * Given a string, this function allocates and returns a pointer to a
- * hash table record of size 'sz' whose "str" pointer is reset to a position
- * in the string table.
- */
-Entry *
-#ifdef __USE_PROTOS
-newEntry( char *text, int sz )
-#else
-newEntry( text, sz )
-char *text;
-int sz;
-#endif
-{
- Entry *p;
- require(text!=NULL, "new: NULL terminal");
-
- if ( (p = (Entry *) calloc(1,sz)) == 0 )
- {
- fatal_internal("newEntry: out of memory for terminals\n");
- exit(PCCTS_EXIT_FAILURE);
- }
- p->str = mystrdup(text);
-
- return(p);
-}
-
-/*
- * add an element to a list.
- *
- * Any non-empty list has a sentinel node whose 'elem' pointer is really
- * a pointer to the last element. (i.e. length(list) = #elemIn(list)+1).
- * Elements are appended to the list.
- */
-void
-#ifdef __USE_PROTOS
-list_add( ListNode **list, void *e )
-#else
-list_add( list, e )
-ListNode **list;
-void *e;
-#endif
-{
- ListNode *p, *tail;
- require(e!=NULL, "list_add: attempting to add NULL list element");
-
- p = newListNode;
- require(p!=NULL, "list_add: cannot alloc new list node");
- p->elem = e;
- if ( *list == NULL )
- {
- ListNode *sentinel = newListNode;
- require(sentinel!=NULL, "list_add: cannot alloc sentinel node");
- *list=sentinel;
- sentinel->next = p;
- sentinel->elem = (char *)p; /* set tail pointer */
- }
- else /* find end of list */
- {
- tail = (ListNode *) (*list)->elem; /* get tail pointer */
- tail->next = p;
- (*list)->elem = (char *) p; /* reset tail */
- }
-}
-
-/* MR10 list_free() frees the ListNode elements in the list */
-/* MR10 if freeData then free the data elements of the list too */
-
-void
-#ifdef __USE_PROTOS
-list_free(ListNode **list,int freeData)
-#else
-list_free(list,freeData)
- ListNode **list;
- int freeData;
-#endif
-{
- ListNode *p;
- ListNode *next;
-
- if (list == NULL) return;
- if (*list == NULL) return;
- for (p=*list; p != NULL; p=next) {
- next=p->next;
- if (freeData && p->elem != NULL) {
- free( (char *) p->elem);
- };
- free( (char *) p);
- };
- *list=NULL;
-}
-
-void
-#ifdef __USE_PROTOS
-list_apply( ListNode *list, void (*f)(void *) )
-#else
-list_apply( list, f )
-ListNode *list;
-void (*f)();
-#endif
-{
- ListNode *p;
- require(f!=NULL, "list_apply: NULL function to apply");
-
- if ( list == NULL ) return;
- for (p = list->next; p!=NULL; p=p->next) (*f)( p->elem );
-}
-
-/* MR27 */
-
-#ifdef __USE_PROTOS
-int list_search_cstring(ListNode *list, char * cstring)
-#else
-int list_search_cstring(list, cstring)
- ListNode * list;
- char * cstring;
-#endif
-{
- ListNode *p;
- if (list == NULL ) return 0;
- for (p = list->next; p!=NULL; p=p->next) {
- if (p->elem == NULL) continue;
- if (0 == strcmp((char *) p->elem , cstring)) return 1;
- }
- return 0;
-}
-
- /* F O L L O W C y c l e S t u f f */
-
-/* make a key based upon (rulename, computation, k value).
- * Computation values are 'i'==FIRST, 'o'==FOLLOW.
- */
-
-/* MR10 Make the key all characters so it can be read easily */
-/* MR10 by a simple dump program. Also, separates */
-/* MR10 'o' and 'i' from rule name */
-
-char *
-#ifdef __USE_PROTOS
-Fkey( char *rule, int computation, int k )
-#else
-Fkey( rule, computation, k )
-char *rule;
-int computation;
-int k;
-#endif
-{
- static char key[MaxRuleName+2+2+1]; /* MR10 */
- int i;
-
- if ( k > 99 ) /* MR10 */
- fatal("k>99 is too big for this implementation of ANTLR!\n"); /* MR10 */
- if ( (i=strlen(rule)) > MaxRuleName ) /* MR10 */
- fatal( eMsgd("rule name > max of %d\n", MaxRuleName) ); /* MR10 */
- strcpy(key,rule);
-
-/* MR10 */ key[i]='*';
-/* MR10 */ key[i+1] = (char) computation; /* MR20 G. Hobbelt */
-/* MR10 */ if (k < 10) {
-/* MR10 */ key[i+2] = (char) ( '0' + k);
-/* MR10 */ key[i+3] = '\0';
-/* MR10 */ } else {
-/* MR10 */ key[i+2] = (char) ( '0' + k/10);
-/* MR10 */ key[i+3] = (char) ( '0' + k % 10);
-/* MR10 */ key[i+4] = '\0';
-/* MR10 */ };
-
- return key;
-}
-
-/* Push a rule onto the kth FOLLOW stack */
-void
-#ifdef __USE_PROTOS
-FoPush( char *rule, int k )
-#else
-FoPush( rule, k )
-char *rule;
-int k;
-#endif
-{
- RuleEntry *r;
- require(rule!=NULL, "FoPush: tried to push NULL rule");
- require(k<=CLL_k, "FoPush: tried to access non-existent stack");
-
- /*fprintf(stderr, "FoPush(%s)\n", rule);*/
- r = (RuleEntry *) hash_get(Rname, rule);
- if ( r == NULL ) {fatal_internal( eMsg1("rule %s must be defined but isn't", rule) );}
- if ( FoStack[k] == NULL ) /* Does the kth stack exist yet? */
- {
- /*fprintf(stderr, "allocating FoStack\n");*/
- FoStack[k] = (int *) calloc(FoStackSize, sizeof(int));
- require(FoStack[k]!=NULL, "FoPush: cannot allocate FOLLOW stack\n");
- }
- if ( FoTOS[k] == NULL )
- {
- FoTOS[k]=FoStack[k];
- *(FoTOS[k]) = r->rulenum;
- }
- else
- {
-#ifdef MEMCHK
- require(valid(FoStack[k]), "FoPush: invalid FoStack");
-#endif
- if ( FoTOS[k] >= &(FoStack[k][FoStackSize-1]) )
- fatal( eMsgd("exceeded max depth of FOLLOW recursion (%d)\n",
- FoStackSize) );
- require(FoTOS[k]>=FoStack[k],
- eMsg1("FoPush: FoStack stack-ptr is playing out of its sandbox",
- rule));
- ++(FoTOS[k]);
- *(FoTOS[k]) = r->rulenum;
- }
- {
- /*
-**** int *p;
-**** fprintf(stderr, "FoStack[k=%d]:\n", k);
-**** for (p=FoStack[k]; p<=FoTOS[k]; p++)
-**** {
-**** fprintf(stderr, "\t%s\n", RulePtr[*p]->rname);
-**** }
- */
- }
-}
-
-/* Pop one rule off of the FOLLOW stack. TOS ptr is NULL if empty. */
-void
-#ifdef __USE_PROTOS
-FoPop( int k )
-#else
-FoPop( k )
-int k;
-#endif
-{
- require(k<=CLL_k, "FoPop: tried to access non-existent stack");
- /*fprintf(stderr, "FoPop\n");*/
- require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]),
- "FoPop: FoStack stack-ptr is playing out of its sandbox");
- if ( FoTOS[k] == FoStack[k] ) FoTOS[k] = NULL;
- else (FoTOS[k])--;
-}
-
-/* Compute FOLLOW cycle.
- * Mark all FOLLOW sets for rules in cycle as incomplete.
- * Then, save cycle on the cycle list (Cycles) for later resolution.
- * The Cycle is stored in the form:
- * (head of cycle==croot, rest of rules in cycle==cyclicDep)
- *
- * e.g. (Fo means "FOLLOW of", "-->" means requires or depends on)
- *
- * Fo(x)-->Fo(a)-->Fo(b)-->Fo(c)-->Fo(x)
- * ^----Infinite recursion (cycle)
- *
- * the cycle would be: x -> {a,b,c} or stored as (x,{a,b,c}). Fo(x) depends
- * on the FOLLOW of a,b, and c. The root of a cycle is always complete after
- * Fo(x) finishes. Fo(a,b,c) however are not. It turns out that all rules
- * in a FOLLOW cycle have the same FOLLOW set.
- */
-void
-#ifdef __USE_PROTOS
-RegisterCycle( char *rule, int k )
-#else
-RegisterCycle( rule, k )
-char *rule;
-int k;
-#endif
-{
- CacheEntry *f;
- Cycle *c;
- int *p;
- RuleEntry *r;
- require(rule!=NULL, "RegisterCycle: tried to register NULL rule");
- require(k<=CLL_k, "RegisterCycle: tried to access non-existent stack");
-
- /*fprintf(stderr, "RegisterCycle(%s)\n", rule);*/
- /* Find cycle start */
- r = (RuleEntry *) hash_get(Rname, rule);
- require(r!=NULL,eMsg1("rule %s must be defined but isn't", rule));
- require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]),
- eMsg1("RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox",
- rule));
-/*** if ( FoTOS[k]<FoStack[k]||FoTOS[k]>&(FoStack[k][FoStackSize-1]) )
-**** {
-**** fprintf(stderr, "RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox\n",
-**** rule);
-**** fprintf(stderr, "RegisterCycle: sp==0x%x out of bounds 0x%x...0x%x\n",
-**** FoTOS[k], FoStack[k], &(FoStack[k][FoStackSize-1]));
-**** exit(PCCTS_EXIT_FAILURE);
-**** }
-****/
-
-#ifdef MEMCHK
- require(valid(FoStack[k]), "RegisterCycle: invalid FoStack");
-#endif
- for (p=FoTOS[k]; *p != r->rulenum && p >= FoStack[k]; --p) {;}
- require(p>=FoStack[k], "RegisterCycle: FoStack is screwed up beyond belief");
- if ( p == FoTOS[k] ) return; /* don't worry about cycles to oneself */
-
- /* compute cyclic dependents (rules in cycle except head) */
- c = newCycle;
- require(c!=NULL, "RegisterCycle: couldn't alloc new cycle");
- c->cyclicDep = empty;
- c->croot = *p++; /* record root of cycle */
- for (; p<=FoTOS[k]; p++)
- {
- /* Mark all dependent rules as incomplete */
- f = (CacheEntry *) hash_get(Fcache, Fkey(RulePtr[*p]->rname,'o',k));
- if ( f==NULL )
- {
- f = newCacheEntry( Fkey(RulePtr[*p]->rname,'o',k) );
- hash_add(Fcache, Fkey(RulePtr[*p]->rname,'o',k), (Entry *)f);
- }
- f->incomplete = TRUE;
-
- set_orel(*p, &(c->cyclicDep)); /* mark rule as dependent of croot */
- }
- list_add(&(Cycles[k]), (void *)c);
-}
-
-/* make all rules in cycle complete
- *
- * while ( some set has changed ) do
- * for each cycle do
- * if degree of FOLLOW set for croot > old degree then
- * update all FOLLOW sets for rules in cyclic dependency
- * change = TRUE
- * endif
- * endfor
- * endwhile
- */
-void
-#ifdef __USE_PROTOS
-ResolveFoCycles( int k )
-#else
-ResolveFoCycles( k )
-int k;
-#endif
-{
- ListNode *p, *q;
- Cycle *c;
- int changed = 1;
- CacheEntry *f,*g;
- int r;
-/* int i; */ /* MR10 not useful */
- unsigned d;
-
- unsigned *cursor; /* MR10 */
- unsigned *origin; /* MR10 */
-
- /*fprintf(stderr, "Resolving following cycles for %d\n", k);*/
- while ( changed )
- {
- changed = 0;
-/* MR10 i = 0; */
- for (p = Cycles[k]->next; p!=NULL; p=p->next)
- {
- c = (Cycle *) p->elem;
- /*fprintf(stderr, "cycle %d: %s -->", i++, RulePtr[c->croot]->rname);*/
- /*s_fprT(stderr, c->cyclicDep);*/
- /*fprintf(stderr, "\n");*/
- f = (CacheEntry *)
- hash_get(Fcache, Fkey(RulePtr[c->croot]->rname,'o',k));
- require(f!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[c->croot]->rname) );
- if ( (d=set_deg(f->fset)) > c->deg )
- {
- /*fprintf(stderr, "Fo(%s) has changed\n", RulePtr[c->croot]->rname);*/
- changed = 1;
- c->deg = d; /* update cycle FOLLOW set degree */
-
-/* MR10 */ origin=set_pdq(c->cyclicDep);
-/* MR10 */ for (cursor=origin; *cursor != nil; cursor++) {
-/* MR10 */ r=*cursor;
-
-/******** while ( !set_nil(c->cyclicDep) ) { *****/
-/******** r = set_int(c->cyclicDep); *****/
-/******** set_rm(r, c->cyclicDep); *****/
-
- /*fprintf(stderr, "updating Fo(%s)\n", RulePtr[r]->rname);*/
- g = (CacheEntry *)
- hash_get(Fcache, Fkey(RulePtr[r]->rname,'o',k));
- require(g!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[r]->rname) );
- set_orin(&(g->fset), f->fset);
- g->incomplete = FALSE;
- }
-/* MR10 */ free( (char *) origin);
-/* MR10 */ origin=NULL;
- }
- }
-/* MR10 - this if statement appears to be meaningless since i is always 0 */
-/* MR10 if ( i == 1 ) changed = 0; */ /* if only 1 cycle, no need to repeat */
- }
- /* kill Cycle list */
- for (q = Cycles[k]->next; q != NULL; q=p)
- {
- p = q->next;
- set_free( ((Cycle *)q->elem)->cyclicDep );
- free((char *)q);
- }
- free( (char *)Cycles[k] );
- Cycles[k] = NULL;
-}
-
-
- /* P r i n t i n g S y n t a x D i a g r a m s */
-
-static void
-#ifdef __USE_PROTOS
-pBlk( Junction *q, int btype )
-#else
-pBlk( q, btype )
-Junction *q;
-int btype;
-#endif
-{
- int k,a;
- Junction *alt, *p;
-
- q->end->pvisited = TRUE;
- if ( btype == aLoopBegin )
- {
- require(q->p2!=NULL, "pBlk: invalid ()* block");
- PRINT(q->p1);
- alt = (Junction *)q->p2;
- PRINT(alt->p1);
- if ( PrintAnnotate )
- {
- printf(" /* Opt ");
- k = 1;
- while ( !set_nil(alt->fset[k]) )
- {
- s_fprT(stdout, alt->fset[k]);
- if ( k++ == CLL_k ) break;
- if ( !set_nil(alt->fset[k]) ) printf(", ");
- }
- printf(" */\n");
- }
- return;
- }
- for (a=1,alt=q; alt != NULL; alt= (Junction *) alt->p2, a++)
- {
- if ( alt->p1 != NULL ) PRINT(alt->p1);
- if ( PrintAnnotate )
- {
- printf( " /* [%d] ", alt->altnum);
- k = 1;
- while ( !set_nil(alt->fset[k]) )
- {
- s_fprT(stdout, alt->fset[k]);
- if ( k++ == CLL_k ) break;
- if ( !set_nil(alt->fset[k]) ) printf(", ");
- }
- if ( alt->p2 == NULL && btype == aOptBlk )
- printf( " (optional branch) */\n");
- else printf( " */\n");
- }
-
- /* ignore implied empty alt of Plus blocks */
- if ( alt->p2 != NULL && ((Junction *)alt->p2)->ignore ) break;
-
- if ( alt->p2 != NULL && !(((Junction *)alt->p2)->p2==NULL && btype == aOptBlk) )
- {
- if ( pLevel == 1 )
- {
- printf("\n");
- if ( a+1==pAlt1 || a+1==pAlt2 ) printf("=>");
- printf("\t");
- }
- else printf(" ");
- printf("|");
- if ( pLevel == 1 )
- {
- p = (Junction *) ((Junction *)alt->p2)->p1;
- while ( p!=NULL )
- {
- if ( p->ntype==nAction )
- {
- p=(Junction *)((ActionNode *)p)->next;
- continue;
- }
- if ( p->ntype!=nJunction )
- {
- break;
- }
- if ( p->jtype==EndBlk || p->jtype==EndRule )
- {
- p = NULL;
- break;
- }
- p = (Junction *)p->p1;
- }
- if ( p==NULL ) printf("\n\t"); /* Empty alt? */
- }
- }
- }
- q->end->pvisited = FALSE;
-}
-
-/* How to print out a junction */
-void
-#ifdef __USE_PROTOS
-pJunc( Junction *q )
-#else
-pJunc( q )
-Junction *q;
-#endif
-{
- int dum_k;
- int doing_rule;
- require(q!=NULL, "pJunc: NULL node");
- require(q->ntype==nJunction, "pJunc: not junction");
-
- if ( q->pvisited == TRUE ) return;
- q->pvisited = TRUE;
- switch ( q->jtype )
- {
- case aSubBlk :
- if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
- if ( q->end->p1 != NULL && ((Junction *)q->end->p1)->ntype==nJunction &&
- ((Junction *)q->end->p1)->jtype == EndRule ) doing_rule = 1;
- else doing_rule = 0;
- pLevel++;
- if ( pLevel==1 )
- {
- if ( pAlt1==1 ) printf("=>");
- printf("\t");
- }
- else printf(" ");
- if ( doing_rule )
- {
- if ( pLevel==1 ) printf(" ");
- pBlk(q,q->jtype);
- }
- else {
- printf("(");
- if ( pLevel==1 ) printf(" ");
- pBlk(q,q->jtype);
- if ( pLevel>1 ) printf(" ");
- printf(")");
- }
- if ( q->guess ) printf("?");
- pLevel--;
- if ( PrintAnnotate ) freeBlkFsets(q);
- if ( q->end->p1 != NULL ) PRINT(q->end->p1);
- break;
- case aOptBlk :
- if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
- pLevel++;
- if ( pLevel==1 )
- {
- if ( pAlt1==1 ) printf("=>");
- printf("\t");
- }
- else printf(" ");
- printf("{");
- if ( pLevel==1 ) printf(" ");
- pBlk(q,q->jtype);
- if ( pLevel>1 ) printf(" ");
- else printf("\n\t");
- printf("}");
- pLevel--;
- if ( PrintAnnotate ) freeBlkFsets(q);
- if ( q->end->p1 != NULL ) PRINT(q->end->p1);
- break;
- case aLoopBegin :
- if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
- pLevel++;
- if ( pLevel==1 )
- {
- if ( pAlt1==1 ) printf("=>");
- printf("\t");
- }
- else printf(" ");
- printf("(");
- if ( pLevel==1 ) printf(" ");
- pBlk(q,q->jtype);
- if ( pLevel>1 ) printf(" ");
- else printf("\n\t");
- printf(")*");
- pLevel--;
- if ( PrintAnnotate ) freeBlkFsets(q);
- if ( q->end->p1 != NULL ) PRINT(q->end->p1);
- break;
- case aLoopBlk :
- if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
- pBlk(q,q->jtype);
- if ( PrintAnnotate ) freeBlkFsets(q);
- break;
- case aPlusBlk :
- if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
- pLevel++;
- if ( pLevel==1 )
- {
- if ( pAlt1==1 ) printf("=>");
- printf("\t");
- }
- else printf(" ");
- printf("(");
- if ( pLevel==1 ) printf(" ");
- pBlk(q,q->jtype);
- if ( pLevel>1 ) printf(" ");
- printf(")+");
- pLevel--;
- if ( PrintAnnotate ) freeBlkFsets(q);
- if ( q->end->p1 != NULL ) PRINT(q->end->p1);
- break;
- case EndBlk :
- break;
- case RuleBlk :
- printf( "\n%s :\n", q->rname);
- PRINT(q->p1);
- if ( q->p2 != NULL ) PRINT(q->p2);
- break;
- case Generic :
- if ( q->p1 != NULL ) PRINT(q->p1);
- q->pvisited = FALSE;
- if ( q->p2 != NULL ) PRINT(q->p2);
- break;
- case EndRule :
- printf( "\n\t;\n");
- break;
- }
- q->pvisited = FALSE;
-}
-
-/* How to print out a rule reference node */
-void
-#ifdef __USE_PROTOS
-pRuleRef( RuleRefNode *p )
-#else
-pRuleRef( p )
-RuleRefNode *p;
-#endif
-{
- require(p!=NULL, "pRuleRef: NULL node");
- require(p->ntype==nRuleRef, "pRuleRef: not rule ref node");
-
- printf( " %s", p->text);
- PRINT(p->next);
-}
-
-/* How to print out a terminal node */
-void
-#ifdef __USE_PROTOS
-pToken( TokNode *p )
-#else
-pToken( p )
-TokNode *p;
-#endif
-{
- require(p!=NULL, "pToken: NULL node");
- require(p->ntype==nToken, "pToken: not token node");
-
- if ( p->wild_card ) printf(" .");
- printf( " %s", TerminalString(p->token));
- PRINT(p->next);
-}
-
-/* How to print out a terminal node */
-void
-#ifdef __USE_PROTOS
-pAction( ActionNode *p )
-#else
-pAction( p )
-ActionNode *p;
-#endif
-{
- require(p!=NULL, "pAction: NULL node");
- require(p->ntype==nAction, "pAction: not action node");
-
- PRINT(p->next);
-}
-
- /* F i l l F o l l o w L i s t s */
-
-/*
- * Search all rules for all rule reference nodes, q to rule, r.
- * Add q->next to follow list dangling off of rule r.
- * i.e.
- *
- * r: -o-R-o-->o--> Ptr to node following rule r in another rule
- * |
- * o--> Ptr to node following another reference to r.
- *
- * This is the data structure employed to avoid FOLLOW set computation. We
- * simply compute the FIRST (reach) of the EndRule Node which follows the
- * list found at the end of all rules which are referenced elsewhere. Rules
- * not invoked by other rules have no follow list (r->end->p1==NULL).
- * Generally, only start symbols are not invoked by another rule.
- *
- * Note that this mechanism also gives a free cross-reference mechanism.
- *
- * The entire syntax diagram is layed out like this:
- *
- * SynDiag
- * |
- * v
- * o-->R1--o
- * |
- * o-->R2--o
- * |
- * ...
- * |
- * o-->Rn--o
- *
- */
-void
-#ifdef __USE_PROTOS
-FoLink( Node *p )
-#else
-FoLink( p )
-Node *p;
-#endif
-{
- RuleEntry *q;
- Junction *j = (Junction *) p;
- RuleRefNode *r = (RuleRefNode *) p;
-
- if ( p==NULL ) return;
- require(p->ntype>=1 && p->ntype<=NumNodeTypes,
- eMsgd("FoLink: invalid diagram node: ntype==%d",p->ntype));
- switch ( p->ntype )
- {
- case nJunction :
- if ( j->fvisited ) return;
- if ( j->jtype == EndRule ) return;
- j->fvisited = TRUE;
- FoLink( j->p1 );
- FoLink( j->p2 );
-/* MR14 */
-/* MR14 */ /* Need to determine whether the guess block is an */
-/* MR14 */ /* of the form (alpha)? beta before follow sets are */
-/* MR14 */ /* computed. This is necessary to solve problem */
-/* MR14 */ /* of doing follow on the alpha of an (alpha)? beta block. */
-/* MR14 */
-/* MR14 */ /* This is performed by analysis_point as a side-effect. */
-/* MR14 */
-/* MR14 */
-/* MR14 */ if (j->jtype == aSubBlk && j->guess) {
-/* MR14 */ Junction *ignore;
-/* MR14 */ ignore=analysis_point(j);
-/* MR14 */ }
-/* MR14 */
- return;
- case nRuleRef :
- if ( r->linked ) return;
- q = (RuleEntry *) hash_get(Rname, r->text);
- if ( q == NULL )
- {
- warnFL( eMsg1("rule %s not defined",r->text), FileStr[r->file], r->line );
- }
- else
- {
- if ( r->parms!=NULL && RulePtr[q->rulenum]->pdecl==NULL )
- {
- warnFL( eMsg1("rule %s accepts no parameter(s)", r->text),
- FileStr[r->file], r->line );
- }
- if ( r->parms==NULL && RulePtr[q->rulenum]->pdecl!=NULL )
- {
- warnFL( eMsg1("rule %s requires parameter(s)", r->text),
- FileStr[r->file], r->line );
- }
- if ( r->assign!=NULL && RulePtr[q->rulenum]->ret==NULL )
- {
- warnFL( eMsg1("rule %s yields no return value(s)", r->text),
- FileStr[r->file], r->line );
- }
- if ( r->assign==NULL && RulePtr[q->rulenum]->ret!=NULL )
- {
- warnFL( eMsg1("rule %s returns a value(s)", r->text),
- FileStr[r->file], r->line );
- }
- if ( !r->linked )
- {
- addFoLink( r->next, r->rname, RulePtr[q->rulenum] );
- r->linked = TRUE;
- }
- }
- FoLink( r->next );
- return;
- case nToken :
- FoLink( ((TokNode *)p)->next );
- return;
- case nAction :
- FoLink( ((ActionNode *)p)->next );
- return;
- default :
- fatal_internal("invalid node type");
- }
-}
-
-/*
- * Add a reference to the end of a rule.
- *
- * 'r' points to the RuleBlk node in a rule. r->end points to the last node
- * (EndRule jtype) in a rule.
- *
- * Initial:
- * r->end --> o
- *
- * After:
- * r->end --> o-->o--> Ptr to node following rule r in another rule
- * |
- * o--> Ptr to node following another reference to r.
- *
- * Note that the links are added to the head of the list so that r->end->p1
- * always points to the most recently added follow-link. At the end, it should
- * point to the last reference found in the grammar (starting from the 1st rule).
- */
-void
-#ifdef __USE_PROTOS
-addFoLink( Node *p, char *rname, Junction *r )
-#else
-addFoLink( p, rname, r )
-Node *p;
-char *rname;
-Junction *r;
-#endif
-{
- Junction *j;
- require(r!=NULL, "addFoLink: incorrect rule graph");
- require(r->end!=NULL, "addFoLink: incorrect rule graph");
- require(r->end->jtype==EndRule, "addFoLink: incorrect rule graph");
- require(p!=NULL, "addFoLink: NULL FOLLOW link");
-
- j = newJunction();
- j->rname = rname; /* rname on follow links point to target rule */
- j->p1 = p; /* link to other rule */
- j->p2 = (Node *) r->end->p1;/* point to head of list */
- r->end->p1 = (Node *) j; /* reset head to point to new node */
-}
-
-void
-#ifdef __USE_PROTOS
-GenCrossRef( Junction *p )
-#else
-GenCrossRef( p )
-Junction *p;
-#endif
-{
- set a;
- Junction *j;
- RuleEntry *q;
- unsigned e;
- require(p!=NULL, "GenCrossRef: why are you passing me a null grammar?");
-
- printf("Cross Reference:\n\n");
- a = empty;
- for (; p!=NULL; p = (Junction *)p->p2)
- {
- printf("Rule %20s referenced by {", p->rname);
- /* make a set of rules for uniqueness */
- for (j = (Junction *)(p->end)->p1; j!=NULL; j = (Junction *)j->p2)
- {
- q = (RuleEntry *) hash_get(Rname, j->rname);
- require(q!=NULL, "GenCrossRef: FoLinks are screwed up");
- set_orel(q->rulenum, &a);
- }
- for (; !set_nil(a); set_rm(e, a))
- {
- e = set_int(a);
- printf(" %s", RulePtr[e]->rname);
- }
- printf(" }\n");
- }
- set_free( a );
-}
-
-/*
- The single argument is a pointer to the start of an element of a
- C++ style function prototypet list. Given a pointer to the start of
- an formal we must locate the comma (or the end of the string)
- and locate the datatype, formal name, and initial value expression.
-
- The function returns a pointer to the character following the comma
- which terminates the formal declaration, or a pointer to the end of
- the string if none was found.
-
- I thought we were parsing specialists, how come I'm doing this by
- hand written code ?
-
- Examples of input:
-
- Foo f,
- Foo f = Foo(1),
- Foo f = Foo(1,2),
- Foo f = &farray[1,2],
- Foo f = ",",
- Foo f = ',',
- TFoo<int,char> f = TFoo<int,char>(1,2),
-
- A non-zero value for nesting indicates a problem matching '(' and ')',
- '[' and ']', '<' and '>', '{' and '}', or improperly terminated string
- or character literal.
-
-*/
-
-
-/*
- * Don't care if it is a valid string literal or not, just find the end
- * Start with pointer to leading "\""
- */
-
-#ifdef __USE_PROTOS
-char * skipStringLiteral(char *pCurrent)
-#else
-char * skipStringLiteral(pCurrent)
-char *pCurrent;
-#endif
-{
- char *p = pCurrent;
- if (*p == 0) return p;
- require (*p == '\"', "skipStringLiteral")
- p++;
- for (p = p; *p != 0; p++) {
- if (*p == '\\') {
- p++;
- if (*p == 0) break;
- p++;
- }
- if (*p == '\"') {
- p++;
- break;
- }
- }
- return p;
-}
-
-/*
- * Don't care if it is a valid character literal or not, just find the end
- * Start with pointer to leading "'"
- */
-
-#ifdef __USE_PROTOS
-char * skipCharLiteral(char *pStart)
-#else
-char * skipCharLiteral(pStart)
- char *pStart;
-#endif
-{
- char *p = pStart;
- if (*p == 0) return p;
- require (*p == '\'', "skipCharLiteral")
- p++;
- for (p = p; *p != 0; p++) {
- if (*p == '\\') {
- p++;
- if (*p == 0) break;
- p++;
- }
- if (*p == '\'') {
- p++;
- break;
- }
- }
- return p;
-}
-
-#ifdef __USE_PROTOS
-char * skipSpaces(char *pStart)
-#else
-char * skipSpaces(pStart)
-char * pStart;
-#endif
-{
- char *p = pStart;
- while (*p != 0 && isspace(*p)) p++;
- return p;
-}
-
-#ifdef __USE_PROTOS
-char * skipToSeparatorOrEqualSign(char *pStart, int *pNest)
-#else
-char * skipToSeparatorOrEqualSign(pStart, pNest)
-char *pStart;
-int *pNest;
-#endif
-{
- char *p = pStart;
-
- int nest = 0;
-
- *pNest = (-1);
-
- while (*p != 0) {
- switch (*p) {
-
- case '(' :
- case '[' :
- case '<' :
- case '{' :
- nest++;
- p++;
- break;
-
- case ')' :
- case ']' :
- case '>' :
- case '}' :
- nest--;
- p++;
- break;
-
- case '"' :
- p = skipStringLiteral(p);
- break;
-
- case '\'' :
- p = skipCharLiteral(p);
- break;
-
- case '\\':
- p++;
- if (*p == 0) goto EXIT;
- p++;
- break;
-
- case ',':
- case '=':
- if (nest == 0) goto EXIT;
- p++;
- break;
-
- default:
- p++;
- }
- }
-EXIT:
- *pNest = nest;
- return p;
-}
-
-#ifdef __USE_PROTOS
-char * skipToSeparator(char *pStart, int *pNest)
-#else
-char * skipToSeparator(pStart, pNest)
-char *pStart;
-int *pNest;
-#endif
-{
- char * p = pStart;
- for ( ; ; ) {
- p = skipToSeparatorOrEqualSign(p, pNest);
- if (*pNest != 0) return p;
- if (*p == ',') return p;
- if (*p == 0) return p;
- p++;
- }
-}
-
-/* skip to just past the "=" separating the declaration from the initialization value */
-
-#ifdef __USE_PROTOS
-char * getInitializer(char *pStart)
-#else
-char * getInitializer(pStart)
-char * pStart;
-#endif
-{
- char *p;
- char *pDataType;
- char *pSymbol;
- char *pEqualSign;
- char *pValue;
- char *pSeparator;
- int nest = 0;
-
- require(pStart!=NULL, "getInitializer: invalid string");
-
- p = endFormal(pStart,
- &pDataType,
- &pSymbol,
- &pEqualSign,
- &pValue,
- &pSeparator,
- &nest);
- if (nest != 0) return NULL;
- if (pEqualSign == NULL) return NULL;
- if (pValue == NULL) return NULL;
- return strBetween(pValue, NULL, pSeparator);
-}
-
-/*
- Examines the string from pStart to pEnd-1.
- If the string has 0 length or is entirely white space
- returns 1. Otherwise 0.
-*/
-
-#ifdef __USE_PROTOS
-int isWhiteString(const char *pStart, const char *pEnd)
-#else
-int isWhiteString(pStart, pEnd)
-const char *pStart;
-const char *pEnd;
-#endif
-{
- const char *p;
- for (p = pStart; p < pEnd; p++) {
- if (! isspace(*p)) return 0;
- }
- return 1;
-}
-
-/*
- This replaces HasComma() which couldn't distinguish
-
- foo ["a,b"]
-
- from:
-
- foo[a,b]
-
-*/
-
-#ifdef __USE_PROTOS
-int hasMultipleOperands(char *pStart)
-#else
-int hasMultipleOperands(pStart)
-char *pStart;
-#endif
-{
- char *p = pStart;
- int nest = 0;
-
- p = skipSpaces(p);
- if (*p == 0) return 0;
- p = skipToSeparator(p, &nest);
- if (nest == 0 && *p == ',') return 1;
- return 0;
-}
-
-
-#define MAX_STR_BETWEEN_WORK_AREA 1000
-
-static char strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA];
-
-
-/*
- strBetween(pStart, pNext, pStop)
-
- Creates a null terminated string by copying the text between two pointers
- to a work area. The start of the string is pStart. The end of the string
- is the character before pNext, or if pNext is null then the character before
- pStop. Trailing spaces are not included in the copy operation.
-
- This is used when a string contains several parts. The pNext part may be
- optional. The pStop will stop the scan when the optional part is not present
- (is a null pointer).
-*/
-
-#ifdef __USE_PROTOS
-char *strBetween(char *pStart, char *pNext, char *pStop)
-#else
-char *strBetween(pStart, pNext, pStop)
-char *pStart;
-char *pNext;
-char *pStop;
-#endif
-{
- char *p;
- char *q = strBetweenWorkArea;
- const char *pEnd;
-
- pEnd = (pNext != NULL) ? pNext : pStop;
-
- require (pEnd != NULL, "pEnd == NULL");
- require (pEnd >= pStart, "pEnd < pStart");
- for (pEnd--; pEnd >= pStart; pEnd--) { /* MR31 */
- if (! isspace(*pEnd)) break;
- }
- for (p = pStart;
- p <= pEnd && q < &strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA-2];
- p++, q++) {
- *q = *p;
- }
- *q = 0;
- return strBetweenWorkArea;
-}
-
-/*
- function Returns pointer to character following separator at
- value which to continue search for next formal. If at the
- end of the string a pointer to the null byte at the
- end of the string is returned.
-
- pStart Pointer to the starting position of the formal list
-
- This may be the middle of a longer string, for example
- when looking for the end of formal #3 starting from
- the middle of the complete formal list.
-
- ppDataType Returns a pointer to the start of the data type in the
- formal. Example: pointer to "Foo".
-
- ppSymbol Returns a pointer to the start of the formal symbol.
- Example: pointer to "f".
-
- ppEqualSign Returns a pointer to the equal sign separating the
- formal symbol from the initial value. If there is
- no "=" then this will be NULL.
-
- ppValue Returns a pointer to the initial value part of the
- formal declaration. Example: pointer to "&farray[1,2]"
-
- ppSeparator Returns a pointer to the character which terminated the
- scan. This should be a pointer to a comma or a null
- byte which terminates the string.
-
- pNest Returns the nesting level when a separator was found.
- This is non-zero for any kind of error. This is zero
- for a successful parse of this portion of the formal
- list.
-
-*/
-
-#ifdef __USE_PROTOS
-char * endFormal(char *pStart,
- char **ppDataType,
- char **ppSymbol,
- char **ppEqualSign,
- char **ppValue,
- char **ppSeparator,
- int *pNest)
-#else
-char * endFormal(pStart,
- ppDataType,
- ppSymbol,
- ppEqualSign,
- ppValue,
- ppSeparator,
- pNest)
-char *pStart;
-char **ppDataType;
-char **ppSymbol;
-char **ppEqualSign;
-char **ppValue;
-char **ppSeparator;
-int *pNest;
-
-#endif
-{
- char *p = pStart;
- char *q;
-
- *ppDataType = NULL;
- *ppSymbol = NULL;
- *ppEqualSign = NULL;
- *ppValue = NULL;
- *ppSeparator = NULL;
-
- *pNest = 0;
-
- /* The first non-blank is the start of the datatype */
-
- p = skipSpaces(p);
- if (*p == 0) goto EXIT;
- *ppDataType = p;
-
- /* We are not looking for the symbol, we are looking
- for the separator that follows the symbol. Then
- we'll back up.
-
- Search for the ',' or '=" or null terminator.
- */
-
- p = skipToSeparatorOrEqualSign(p, pNest);
-
- if (*pNest != 0) goto EXIT;
-
- /*
- Work backwards to find start of symbol
- Skip spaces between the end of symbol and separator
- Assume that there are no spaces in the formal, but
- there is a space preceding the formal
- */
-
- for (q = &p[-1]; q >= *ppDataType; q--) {
- if (! isspace(*q)) break;
- }
- if (q < *ppDataType) goto EXIT;
-
- /*
- MR26 Handle things like: IIR_Bool (IIR_Decl::*constraint)()
- Backup until we hit the end of a symbol string, then find the
- start of the symbol string. This wont' work for functions
- with prototypes, but works for the most common cases. For
- others, use typedef names.
- */
-
-/* MR26 */ for (q = q; q >= *ppDataType; q--) {
-/* MR26 */ if (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$') break;
-/* MR26 */ }
-/* MR26 */ if (q < *ppDataType) goto EXIT;
-
- for (q = q; q >= *ppDataType; q--) {
- if ( ! (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$')) break;
- }
-
- *ppSymbol = &q[1];
-
- if (*p == ',' || *p == 0) {
- *ppSeparator = p;
- goto EXIT;
- }
-
- *ppEqualSign = p;
- p = skipSpaces(++p);
- *ppValue = p;
- if (*p == 0) goto EXIT;
-
-
- while (*p != 0 && *pNest == 0 && *p != ',') {
- p = skipToSeparator(p, pNest);
- }
- if (*pNest == 0) *ppSeparator = p;
-
-EXIT:
- if (*p == ',') p++;
- return p;
-}