| Index: third_party/sqlite/src/tool/lemon.c
|
| diff --git a/third_party/sqlite/src/tool/lemon.c b/third_party/sqlite/src/tool/lemon.c
|
| index 898022e28c1589b5c99bac7a990422dce6e089e4..85e94f7007f905754127fd81472f9ff64e631a2d 100644
|
| --- a/third_party/sqlite/src/tool/lemon.c
|
| +++ b/third_party/sqlite/src/tool/lemon.c
|
| @@ -15,7 +15,7 @@
|
|
|
| #ifndef __WIN32__
|
| # if defined(_WIN32) || defined(WIN32)
|
| -# define __WIN32__
|
| +# define __WIN32__
|
| # endif
|
| #endif
|
|
|
| @@ -41,23 +41,6 @@ extern int access(const char *path, int mode);
|
| #endif
|
|
|
| static int showPrecedenceConflict = 0;
|
| -static const char **made_files = NULL;
|
| -static int made_files_count = 0;
|
| -static int successful_exit = 0;
|
| -static void LemonAtExit(void)
|
| -{
|
| - /* if we failed, delete (most) files we made, to unconfuse build tools. */
|
| - int i;
|
| - for (i = 0; i < made_files_count; i++) {
|
| - if (!successful_exit) {
|
| - remove(made_files[i]);
|
| - }
|
| - }
|
| - free(made_files);
|
| - made_files_count = 0;
|
| - made_files = NULL;
|
| -}
|
| -
|
| static char *msort(char*,char**,int(*)(const char*,const char*));
|
|
|
| /*
|
| @@ -67,6 +50,107 @@ static char *msort(char*,char**,int(*)(const char*,const char*));
|
| */
|
| #define lemonStrlen(X) ((int)strlen(X))
|
|
|
| +/*
|
| +** Compilers are starting to complain about the use of sprintf() and strcpy(),
|
| +** saying they are unsafe. So we define our own versions of those routines too.
|
| +**
|
| +** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and
|
| +** lemon_addtext(). The first two are replacements for sprintf() and vsprintf().
|
| +** The third is a helper routine for vsnprintf() that adds texts to the end of a
|
| +** buffer, making sure the buffer is always zero-terminated.
|
| +**
|
| +** The string formatter is a minimal subset of stdlib sprintf() supporting only
|
| +** a few simply conversions:
|
| +**
|
| +** %d
|
| +** %s
|
| +** %.*s
|
| +**
|
| +*/
|
| +static void lemon_addtext(
|
| + char *zBuf, /* The buffer to which text is added */
|
| + int *pnUsed, /* Slots of the buffer used so far */
|
| + const char *zIn, /* Text to add */
|
| + int nIn, /* Bytes of text to add. -1 to use strlen() */
|
| + int iWidth /* Field width. Negative to left justify */
|
| +){
|
| + if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){}
|
| + while( iWidth>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth--; }
|
| + if( nIn==0 ) return;
|
| + memcpy(&zBuf[*pnUsed], zIn, nIn);
|
| + *pnUsed += nIn;
|
| + while( (-iWidth)>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth++; }
|
| + zBuf[*pnUsed] = 0;
|
| +}
|
| +static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){
|
| + int i, j, k, c;
|
| + int nUsed = 0;
|
| + const char *z;
|
| + char zTemp[50];
|
| + str[0] = 0;
|
| + for(i=j=0; (c = zFormat[i])!=0; i++){
|
| + if( c=='%' ){
|
| + int iWidth = 0;
|
| + lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
|
| + c = zFormat[++i];
|
| + if( isdigit(c) || (c=='-' && isdigit(zFormat[i+1])) ){
|
| + if( c=='-' ) i++;
|
| + while( isdigit(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0';
|
| + if( c=='-' ) iWidth = -iWidth;
|
| + c = zFormat[i];
|
| + }
|
| + if( c=='d' ){
|
| + int v = va_arg(ap, int);
|
| + if( v<0 ){
|
| + lemon_addtext(str, &nUsed, "-", 1, iWidth);
|
| + v = -v;
|
| + }else if( v==0 ){
|
| + lemon_addtext(str, &nUsed, "0", 1, iWidth);
|
| + }
|
| + k = 0;
|
| + while( v>0 ){
|
| + k++;
|
| + zTemp[sizeof(zTemp)-k] = (v%10) + '0';
|
| + v /= 10;
|
| + }
|
| + lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k, iWidth);
|
| + }else if( c=='s' ){
|
| + z = va_arg(ap, const char*);
|
| + lemon_addtext(str, &nUsed, z, -1, iWidth);
|
| + }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){
|
| + i += 2;
|
| + k = va_arg(ap, int);
|
| + z = va_arg(ap, const char*);
|
| + lemon_addtext(str, &nUsed, z, k, iWidth);
|
| + }else if( c=='%' ){
|
| + lemon_addtext(str, &nUsed, "%", 1, 0);
|
| + }else{
|
| + fprintf(stderr, "illegal format\n");
|
| + exit(1);
|
| + }
|
| + j = i+1;
|
| + }
|
| + }
|
| + lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
|
| + return nUsed;
|
| +}
|
| +static int lemon_sprintf(char *str, const char *format, ...){
|
| + va_list ap;
|
| + int rc;
|
| + va_start(ap, format);
|
| + rc = lemon_vsprintf(str, format, ap);
|
| + va_end(ap);
|
| + return rc;
|
| +}
|
| +static void lemon_strcpy(char *dest, const char *src){
|
| + while( (*(dest++) = *(src++))!=0 ){}
|
| +}
|
| +static void lemon_strcat(char *dest, const char *src){
|
| + while( *dest ) dest++;
|
| + lemon_strcpy(dest, src);
|
| +}
|
| +
|
| +
|
| /* a few forward declarations... */
|
| struct rule;
|
| struct lemon;
|
| @@ -134,8 +218,6 @@ void ResortStates(struct lemon *);
|
| void SetSize(int); /* All sets will be of size N */
|
| char *SetNew(void); /* A new set for element 0..N */
|
| void SetFree(char*); /* Deallocate a set */
|
| -
|
| -char *SetNew(void); /* A new set for element 0..N */
|
| int SetAdd(char*,int); /* Add element to a set */
|
| int SetUnion(char *,char *); /* A <- A U B, thru element N */
|
| #define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
|
| @@ -672,7 +754,7 @@ void FindRulePrecedences(struct lemon *xp)
|
| }
|
| }else if( sp->prec>=0 ){
|
| rp->precsym = rp->rhs[i];
|
| - }
|
| + }
|
| }
|
| }
|
| }
|
| @@ -703,8 +785,9 @@ void FindFirstSets(struct lemon *lemp)
|
| for(rp=lemp->rule; rp; rp=rp->next){
|
| if( rp->lhs->lambda ) continue;
|
| for(i=0; i<rp->nrhs; i++){
|
| - struct symbol *sp = rp->rhs[i];
|
| - if( sp->type!=TERMINAL || sp->lambda==LEMON_FALSE ) break;
|
| + struct symbol *sp = rp->rhs[i];
|
| + assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE );
|
| + if( sp->lambda==LEMON_FALSE ) break;
|
| }
|
| if( i==rp->nrhs ){
|
| rp->lhs->lambda = LEMON_TRUE;
|
| @@ -729,12 +812,12 @@ void FindFirstSets(struct lemon *lemp)
|
| progress += SetAdd(s1->firstset,s2->subsym[j]->index);
|
| }
|
| break;
|
| - }else if( s1==s2 ){
|
| + }else if( s1==s2 ){
|
| if( s1->lambda==LEMON_FALSE ) break;
|
| - }else{
|
| + }else{
|
| progress += SetUnion(s1->firstset,s2->firstset);
|
| if( s2->lambda==LEMON_FALSE ) break;
|
| - }
|
| + }
|
| }
|
| }
|
| }while( progress );
|
| @@ -977,15 +1060,15 @@ void FindFollowSets(struct lemon *lemp)
|
| if( change ){
|
| plp->cfp->status = INCOMPLETE;
|
| progress = 1;
|
| - }
|
| - }
|
| + }
|
| + }
|
| cfp->status = COMPLETE;
|
| }
|
| }
|
| }while( progress );
|
| }
|
|
|
| -static int resolve_conflict(struct action *,struct action *, struct symbol *);
|
| +static int resolve_conflict(struct action *,struct action *);
|
|
|
| /* Compute the reduce actions, and resolve conflicts.
|
| */
|
| @@ -1011,7 +1094,7 @@ void FindActions(struct lemon *lemp)
|
| ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
|
| Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
|
| }
|
| - }
|
| + }
|
| }
|
| }
|
| }
|
| @@ -1039,7 +1122,7 @@ void FindActions(struct lemon *lemp)
|
| for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
|
| /* The two actions "ap" and "nap" have the same lookahead.
|
| ** Figure out which one should be used */
|
| - lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym);
|
| + lemp->nconflict += resolve_conflict(ap,nap);
|
| }
|
| }
|
| }
|
| @@ -1074,8 +1157,7 @@ void FindActions(struct lemon *lemp)
|
| */
|
| static int resolve_conflict(
|
| struct action *apx,
|
| - struct action *apy,
|
| - struct symbol *errsym /* The error symbol (if defined. NULL otherwise) */
|
| + struct action *apy
|
| ){
|
| struct symbol *spx, *spy;
|
| int errcnt = 0;
|
| @@ -1101,8 +1183,7 @@ static int resolve_conflict(
|
| apx->type = SH_RESOLVED;
|
| }else{
|
| assert( spx->prec==spy->prec && spx->assoc==NONE );
|
| - apy->type = SRCONFLICT;
|
| - errcnt++;
|
| + apx->type = ERROR;
|
| }
|
| }else if( apx->type==REDUCE && apy->type==REDUCE ){
|
| spx = apx->x.rp->precsym;
|
| @@ -1281,11 +1362,11 @@ void Configlist_closure(struct lemon *lemp)
|
| SetAdd(newcfp->fws, xsp->subsym[k]->index);
|
| }
|
| break;
|
| - }else{
|
| + }else{
|
| SetUnion(newcfp->fws,xsp->firstset);
|
| if( xsp->lambda==LEMON_FALSE ) break;
|
| - }
|
| - }
|
| + }
|
| + }
|
| if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
|
| }
|
| }
|
| @@ -1386,7 +1467,7 @@ static void handle_D_option(char *z){
|
| fprintf(stderr,"out of memory\n");
|
| exit(1);
|
| }
|
| - strcpy(*paz, z);
|
| + lemon_strcpy(*paz, z);
|
| for(z=*paz; *z && *z!='='; z++){}
|
| *z = 0;
|
| }
|
| @@ -1397,7 +1478,7 @@ static void handle_T_option(char *z){
|
| if( user_templatename==0 ){
|
| memory_error();
|
| }
|
| - strcpy(user_templatename, z);
|
| + lemon_strcpy(user_templatename, z);
|
| }
|
|
|
| /* The main program. Parse the command line and do it... */
|
| @@ -1433,8 +1514,6 @@ int main(int argc, char **argv)
|
| int exitcode;
|
| struct lemon lem;
|
|
|
| - atexit(LemonAtExit);
|
| -
|
| OptInit(argv,options,stderr);
|
| if( version ){
|
| printf("Lemon version 1.0\n");
|
| @@ -1468,12 +1547,15 @@ int main(int argc, char **argv)
|
| }
|
|
|
| /* Count and index the symbols of the grammar */
|
| - lem.nsymbol = Symbol_count();
|
| Symbol_new("{default}");
|
| + lem.nsymbol = Symbol_count();
|
| lem.symbols = Symbol_arrayof();
|
| - for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
|
| - qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*), Symbolcmpp);
|
| - for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
|
| + for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
|
| + qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp);
|
| + for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
|
| + while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; }
|
| + assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 );
|
| + lem.nsymbol = i - 1;
|
| for(i=1; isupper(lem.symbols[i]->name[0]); i++);
|
| lem.nterminal = i;
|
|
|
| @@ -1537,7 +1619,6 @@ int main(int argc, char **argv)
|
|
|
| /* return 0 on success, 1 on failure. */
|
| exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
|
| - successful_exit = (exitcode == 0);
|
| exit(exitcode);
|
| return (exitcode);
|
| }
|
| @@ -1568,7 +1649,7 @@ int main(int argc, char **argv)
|
| /*
|
| ** Return a pointer to the next structure in the linked list.
|
| */
|
| -#define NEXT(A) (*(char**)(((unsigned long)A)+offset))
|
| +#define NEXT(A) (*(char**)(((char*)A)+offset))
|
|
|
| /*
|
| ** Inputs:
|
| @@ -1962,7 +2043,9 @@ enum e_state {
|
| WAITING_FOR_DESTRUCTOR_SYMBOL,
|
| WAITING_FOR_DATATYPE_SYMBOL,
|
| WAITING_FOR_FALLBACK_ID,
|
| - WAITING_FOR_WILDCARD_ID
|
| + WAITING_FOR_WILDCARD_ID,
|
| + WAITING_FOR_CLASS_ID,
|
| + WAITING_FOR_CLASS_TOKEN
|
| };
|
| struct pstate {
|
| char *filename; /* Name of the input file */
|
| @@ -1972,6 +2055,7 @@ struct pstate {
|
| struct lemon *gp; /* Global state vector */
|
| enum e_state state; /* The state of the parser */
|
| struct symbol *fallback; /* The fallback token */
|
| + struct symbol *tkclass; /* Token class symbol */
|
| struct symbol *lhs; /* Left-hand side of current rule */
|
| const char *lhsalias; /* Alias for the LHS */
|
| int nrhs; /* Number of right-hand side symbols seen */
|
| @@ -2015,10 +2099,10 @@ static void parseonetoken(struct pstate *psp)
|
| }else if( x[0]=='{' ){
|
| if( psp->prevrule==0 ){
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| -"There is no prior rule opon which to attach the code \
|
| +"There is no prior rule upon which to attach the code \
|
| fragment which begins on this line.");
|
| psp->errorcnt++;
|
| - }else if( psp->prevrule->code!=0 ){
|
| + }else if( psp->prevrule->code!=0 ){
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| "Code fragment beginning on this line is not the first \
|
| to follow the previous rule.");
|
| @@ -2026,7 +2110,7 @@ to follow the previous rule.");
|
| }else{
|
| psp->prevrule->line = psp->tokenlineno;
|
| psp->prevrule->code = &x[1];
|
| - }
|
| + }
|
| }else if( x[0]=='[' ){
|
| psp->state = PRECEDENCE_MARK_1;
|
| }else{
|
| @@ -2119,7 +2203,7 @@ to follow the previous rule.");
|
| "Can't allocate enough memory for this rule.");
|
| psp->errorcnt++;
|
| psp->prevrule = 0;
|
| - }else{
|
| + }else{
|
| int i;
|
| rp->ruleline = psp->tokenlineno;
|
| rp->rhs = (struct symbol**)&rp[1];
|
| @@ -2127,7 +2211,7 @@ to follow the previous rule.");
|
| for(i=0; i<psp->nrhs; i++){
|
| rp->rhs[i] = psp->rhs[i];
|
| rp->rhsalias[i] = psp->alias[i];
|
| - }
|
| + }
|
| rp->lhs = psp->lhs;
|
| rp->lhsalias = psp->lhsalias;
|
| rp->nrhs = psp->nrhs;
|
| @@ -2139,12 +2223,12 @@ to follow the previous rule.");
|
| rp->next = 0;
|
| if( psp->firstrule==0 ){
|
| psp->firstrule = psp->lastrule = rp;
|
| - }else{
|
| + }else{
|
| psp->lastrule->next = rp;
|
| psp->lastrule = rp;
|
| - }
|
| + }
|
| psp->prevrule = rp;
|
| - }
|
| + }
|
| psp->state = WAITING_FOR_DECL_OR_RULE;
|
| }else if( isalpha(x[0]) ){
|
| if( psp->nrhs>=MAXRHS ){
|
| @@ -2153,11 +2237,11 @@ to follow the previous rule.");
|
| x);
|
| psp->errorcnt++;
|
| psp->state = RESYNC_AFTER_RULE_ERROR;
|
| - }else{
|
| + }else{
|
| psp->rhs[psp->nrhs] = Symbol_new(x);
|
| psp->alias[psp->nrhs] = 0;
|
| psp->nrhs++;
|
| - }
|
| + }
|
| }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
|
| struct symbol *msp = psp->rhs[psp->nrhs-1];
|
| if( msp->type!=MULTITERMINAL ){
|
| @@ -2221,24 +2305,24 @@ to follow the previous rule.");
|
| if( strcmp(x,"name")==0 ){
|
| psp->declargslot = &(psp->gp->name);
|
| psp->insertLineMacro = 0;
|
| - }else if( strcmp(x,"include")==0 ){
|
| + }else if( strcmp(x,"include")==0 ){
|
| psp->declargslot = &(psp->gp->include);
|
| - }else if( strcmp(x,"code")==0 ){
|
| + }else if( strcmp(x,"code")==0 ){
|
| psp->declargslot = &(psp->gp->extracode);
|
| - }else if( strcmp(x,"token_destructor")==0 ){
|
| + }else if( strcmp(x,"token_destructor")==0 ){
|
| psp->declargslot = &psp->gp->tokendest;
|
| - }else if( strcmp(x,"default_destructor")==0 ){
|
| + }else if( strcmp(x,"default_destructor")==0 ){
|
| psp->declargslot = &psp->gp->vardest;
|
| - }else if( strcmp(x,"token_prefix")==0 ){
|
| + }else if( strcmp(x,"token_prefix")==0 ){
|
| psp->declargslot = &psp->gp->tokenprefix;
|
| psp->insertLineMacro = 0;
|
| - }else if( strcmp(x,"syntax_error")==0 ){
|
| + }else if( strcmp(x,"syntax_error")==0 ){
|
| psp->declargslot = &(psp->gp->error);
|
| - }else if( strcmp(x,"parse_accept")==0 ){
|
| + }else if( strcmp(x,"parse_accept")==0 ){
|
| psp->declargslot = &(psp->gp->accept);
|
| - }else if( strcmp(x,"parse_failure")==0 ){
|
| + }else if( strcmp(x,"parse_failure")==0 ){
|
| psp->declargslot = &(psp->gp->failure);
|
| - }else if( strcmp(x,"stack_overflow")==0 ){
|
| + }else if( strcmp(x,"stack_overflow")==0 ){
|
| psp->declargslot = &(psp->gp->overflow);
|
| }else if( strcmp(x,"extra_argument")==0 ){
|
| psp->declargslot = &(psp->gp->arg);
|
| @@ -2267,21 +2351,23 @@ to follow the previous rule.");
|
| psp->preccounter++;
|
| psp->declassoc = NONE;
|
| psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
|
| - }else if( strcmp(x,"destructor")==0 ){
|
| + }else if( strcmp(x,"destructor")==0 ){
|
| psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
|
| - }else if( strcmp(x,"type")==0 ){
|
| + }else if( strcmp(x,"type")==0 ){
|
| psp->state = WAITING_FOR_DATATYPE_SYMBOL;
|
| }else if( strcmp(x,"fallback")==0 ){
|
| psp->fallback = 0;
|
| psp->state = WAITING_FOR_FALLBACK_ID;
|
| }else if( strcmp(x,"wildcard")==0 ){
|
| psp->state = WAITING_FOR_WILDCARD_ID;
|
| + }else if( strcmp(x,"token_class")==0 ){
|
| + psp->state = WAITING_FOR_CLASS_ID;
|
| }else{
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| "Unknown declaration keyword: \"%%%s\".",x);
|
| psp->errorcnt++;
|
| psp->state = RESYNC_AFTER_DECL_ERROR;
|
| - }
|
| + }
|
| }else{
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| "Illegal declaration keyword: \"%s\".",x);
|
| @@ -2336,10 +2422,10 @@ to follow the previous rule.");
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| "Symbol \"%s\" has already be given a precedence.",x);
|
| psp->errorcnt++;
|
| - }else{
|
| + }else{
|
| sp->prec = psp->preccounter;
|
| sp->assoc = psp->declassoc;
|
| - }
|
| + }
|
| }else{
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| "Can't assign a precedence to \"%s\".",x);
|
| @@ -2369,7 +2455,7 @@ to follow the previous rule.");
|
| for(z=psp->filename, nBack=0; *z; z++){
|
| if( *z=='\\' ) nBack++;
|
| }
|
| - sprintf(zLine, "#line %d ", psp->tokenlineno);
|
| + lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
|
| nLine = lemonStrlen(zLine);
|
| n += nLine + lemonStrlen(psp->filename) + nBack;
|
| }
|
| @@ -2444,6 +2530,40 @@ to follow the previous rule.");
|
| }
|
| }
|
| break;
|
| + case WAITING_FOR_CLASS_ID:
|
| + if( !islower(x[0]) ){
|
| + ErrorMsg(psp->filename, psp->tokenlineno,
|
| + "%%token_class must be followed by an identifier: ", x);
|
| + psp->errorcnt++;
|
| + psp->state = RESYNC_AFTER_DECL_ERROR;
|
| + }else if( Symbol_find(x) ){
|
| + ErrorMsg(psp->filename, psp->tokenlineno,
|
| + "Symbol \"%s\" already used", x);
|
| + psp->errorcnt++;
|
| + psp->state = RESYNC_AFTER_DECL_ERROR;
|
| + }else{
|
| + psp->tkclass = Symbol_new(x);
|
| + psp->tkclass->type = MULTITERMINAL;
|
| + psp->state = WAITING_FOR_CLASS_TOKEN;
|
| + }
|
| + break;
|
| + case WAITING_FOR_CLASS_TOKEN:
|
| + if( x[0]=='.' ){
|
| + psp->state = WAITING_FOR_DECL_OR_RULE;
|
| + }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){
|
| + struct symbol *msp = psp->tkclass;
|
| + msp->nsubsym++;
|
| + msp->subsym = (struct symbol **) realloc(msp->subsym,
|
| + sizeof(struct symbol*)*msp->nsubsym);
|
| + if( !isupper(x[0]) ) x++;
|
| + msp->subsym[msp->nsubsym-1] = Symbol_new(x);
|
| + }else{
|
| + ErrorMsg(psp->filename, psp->tokenlineno,
|
| + "%%token_class argument \"%s\" should be a token", x);
|
| + psp->errorcnt++;
|
| + psp->state = RESYNC_AFTER_DECL_ERROR;
|
| + }
|
| + break;
|
| case RESYNC_AFTER_RULE_ERROR:
|
| /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
|
| ** break; */
|
| @@ -2538,10 +2658,10 @@ void Parse(struct lemon *gp)
|
| filesize = ftell(fp);
|
| rewind(fp);
|
| filebuf = (char *)malloc( filesize+1 );
|
| - if( filebuf==0 ){
|
| - ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.",
|
| - filesize+1);
|
| + if( filesize>100000000 || filebuf==0 ){
|
| + ErrorMsg(ps.filename,0,"Input file too large.");
|
| gp->errorcnt++;
|
| + fclose(fp);
|
| return;
|
| }
|
| if( fread(filebuf,1,filesize,fp)!=filesize ){
|
| @@ -2549,6 +2669,7 @@ void Parse(struct lemon *gp)
|
| filesize);
|
| free(filebuf);
|
| gp->errorcnt++;
|
| + fclose(fp);
|
| return;
|
| }
|
| fclose(fp);
|
| @@ -2607,12 +2728,12 @@ void Parse(struct lemon *gp)
|
| if( c=='\n' ) lineno++;
|
| prevc = c;
|
| cp++;
|
| - }
|
| - }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
|
| + }
|
| + }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
|
| cp = &cp[2];
|
| while( (c= *cp)!=0 && c!='\n' ) cp++;
|
| if( c ) lineno++;
|
| - }else if( c=='\'' || c=='\"' ){ /* String a character literals */
|
| + }else if( c=='\'' || c=='\"' ){ /* String a character literals */
|
| int startchar, prevc;
|
| startchar = c;
|
| prevc = 0;
|
| @@ -2620,8 +2741,8 @@ void Parse(struct lemon *gp)
|
| if( c=='\n' ) lineno++;
|
| if( prevc=='\\' ) prevc = 0;
|
| else prevc = c;
|
| - }
|
| - }
|
| + }
|
| + }
|
| }
|
| if( c==0 ){
|
| ErrorMsg(ps.filename,ps.tokenlineno,
|
| @@ -2736,10 +2857,10 @@ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
|
| fprintf(stderr,"Can't allocate space for a filename.\n");
|
| exit(1);
|
| }
|
| - strcpy(name,lemp->filename);
|
| + lemon_strcpy(name,lemp->filename);
|
| cp = strrchr(name,'.');
|
| if( cp ) *cp = 0;
|
| - strcat(name,suffix);
|
| + lemon_strcat(name,suffix);
|
| return name;
|
| }
|
|
|
| @@ -2761,23 +2882,6 @@ PRIVATE FILE *file_open(
|
| lemp->errorcnt++;
|
| return 0;
|
| }
|
| -
|
| - /* Add files we create to a list, so we can delete them if we fail. This
|
| - ** is to keep makefiles from getting confused. We don't include .out files,
|
| - ** though: this is debug information, and you don't want it deleted if there
|
| - ** was an error you need to track down.
|
| - */
|
| - if(( *mode=='w' ) && (strcmp(suffix, ".out") != 0)){
|
| - const char **ptr = (const char **)
|
| - realloc(made_files, sizeof (const char **) * (made_files_count + 1));
|
| - const char *fname = Strsafe(lemp->outname);
|
| - if ((ptr == NULL) || (fname == NULL)) {
|
| - free(ptr);
|
| - memory_error();
|
| - }
|
| - made_files = ptr;
|
| - made_files[made_files_count++] = fname;
|
| - }
|
| return fp;
|
| }
|
|
|
| @@ -2813,11 +2917,13 @@ void Reprint(struct lemon *lemp)
|
| printf(" ::=");
|
| for(i=0; i<rp->nrhs; i++){
|
| sp = rp->rhs[i];
|
| - printf(" %s", sp->name);
|
| if( sp->type==MULTITERMINAL ){
|
| + printf(" %s", sp->subsym[0]->name);
|
| for(j=1; j<sp->nsubsym; j++){
|
| printf("|%s", sp->subsym[j]->name);
|
| }
|
| + }else{
|
| + printf(" %s", sp->name);
|
| }
|
| /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
|
| }
|
| @@ -2839,11 +2945,13 @@ void ConfigPrint(FILE *fp, struct config *cfp)
|
| if( i==cfp->dot ) fprintf(fp," *");
|
| if( i==rp->nrhs ) break;
|
| sp = rp->rhs[i];
|
| - fprintf(fp," %s", sp->name);
|
| if( sp->type==MULTITERMINAL ){
|
| + fprintf(fp," %s", sp->subsym[0]->name);
|
| for(j=1; j<sp->nsubsym; j++){
|
| fprintf(fp,"|%s",sp->subsym[j]->name);
|
| }
|
| + }else{
|
| + fprintf(fp," %s", sp->name);
|
| }
|
| }
|
| }
|
| @@ -2953,7 +3061,7 @@ void ReportOutput(struct lemon *lemp)
|
| while( cfp ){
|
| char buf[20];
|
| if( cfp->dot==cfp->rp->nrhs ){
|
| - sprintf(buf,"(%d)",cfp->rp->index);
|
| + lemon_sprintf(buf,"(%d)",cfp->rp->index);
|
| fprintf(fp," %5s ",buf);
|
| }else{
|
| fprintf(fp," ");
|
| @@ -3018,7 +3126,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
|
| c = *cp;
|
| *cp = 0;
|
| path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
|
| - if( path ) sprintf(path,"%s/%s",argv0,name);
|
| + if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
|
| *cp = c;
|
| }else{
|
| pathlist = getenv("PATH");
|
| @@ -3027,13 +3135,13 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
|
| path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
|
| if( (pathbuf != 0) && (path!=0) ){
|
| pathbufptr = pathbuf;
|
| - strcpy(pathbuf, pathlist);
|
| + lemon_strcpy(pathbuf, pathlist);
|
| while( *pathbuf ){
|
| cp = strchr(pathbuf,':');
|
| if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)];
|
| c = *cp;
|
| *cp = 0;
|
| - sprintf(path,"%s/%s",pathbuf,name);
|
| + lemon_sprintf(path,"%s/%s",pathbuf,name);
|
| *cp = c;
|
| if( c==0 ) pathbuf[0] = 0;
|
| else pathbuf = &cp[1];
|
| @@ -3124,9 +3232,9 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
|
|
|
| cp = strrchr(lemp->filename,'.');
|
| if( cp ){
|
| - sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
|
| + lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
|
| }else{
|
| - sprintf(buf,"%s.lt",lemp->filename);
|
| + lemon_sprintf(buf,"%s.lt",lemp->filename);
|
| }
|
| if( access(buf,004)==0 ){
|
| tpltname = buf;
|
| @@ -3277,9 +3385,9 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
|
| while( n-- > 0 ){
|
| c = *(zText++);
|
| if( c=='%' && n>0 && zText[0]=='d' ){
|
| - sprintf(zInt, "%d", p1);
|
| + lemon_sprintf(zInt, "%d", p1);
|
| p1 = p2;
|
| - strcpy(&z[used], zInt);
|
| + lemon_strcpy(&z[used], zInt);
|
| used += lemonStrlen(&z[used]);
|
| zText++;
|
| n--;
|
| @@ -3428,12 +3536,16 @@ void print_stack_union(
|
| int maxdtlength; /* Maximum length of any ".datatype" field. */
|
| char *stddt; /* Standardized name for a datatype */
|
| int i,j; /* Loop counters */
|
| - int hash; /* For hashing the name of a type */
|
| + unsigned hash; /* For hashing the name of a type */
|
| const char *name; /* Name of the parser */
|
|
|
| /* Allocate and initialize types[] and allocate stddt[] */
|
| arraysize = lemp->nsymbol * 2;
|
| types = (char**)calloc( arraysize, sizeof(char*) );
|
| + if( types==0 ){
|
| + fprintf(stderr,"Out of memory.\n");
|
| + exit(1);
|
| + }
|
| for(i=0; i<arraysize; i++) types[i] = 0;
|
| maxdtlength = 0;
|
| if( lemp->vartype ){
|
| @@ -3447,7 +3559,7 @@ void print_stack_union(
|
| if( len>maxdtlength ) maxdtlength = len;
|
| }
|
| stddt = (char*)malloc( maxdtlength*2 + 1 );
|
| - if( types==0 || stddt==0 ){
|
| + if( stddt==0 ){
|
| fprintf(stderr,"Out of memory.\n");
|
| exit(1);
|
| }
|
| @@ -3491,7 +3603,7 @@ void print_stack_union(
|
| break;
|
| }
|
| hash++;
|
| - if( hash>=arraysize ) hash = 0;
|
| + if( hash>=(unsigned)arraysize ) hash = 0;
|
| }
|
| if( types[hash]==0 ){
|
| sp->dtnum = hash + 1;
|
| @@ -3500,7 +3612,7 @@ void print_stack_union(
|
| fprintf(stderr,"Out of memory.\n");
|
| exit(1);
|
| }
|
| - strcpy(types[hash],stddt);
|
| + lemon_strcpy(types[hash],stddt);
|
| }
|
| }
|
|
|
| @@ -3586,9 +3698,11 @@ static void writeRuleText(FILE *out, struct rule *rp){
|
| fprintf(out,"%s ::=", rp->lhs->name);
|
| for(j=0; j<rp->nrhs; j++){
|
| struct symbol *sp = rp->rhs[j];
|
| - fprintf(out," %s", sp->name);
|
| - if( sp->type==MULTITERMINAL ){
|
| + if( sp->type!=MULTITERMINAL ){
|
| + fprintf(out," %s", sp->name);
|
| + }else{
|
| int k;
|
| + fprintf(out," %s", sp->subsym[0]->name);
|
| for(k=1; k<sp->nsubsym; k++){
|
| fprintf(out,"|%s",sp->subsym[k]->name);
|
| }
|
| @@ -3889,7 +4003,7 @@ void ReportTable(
|
| /* Generate a table containing the symbolic name of every symbol
|
| */
|
| for(i=0; i<lemp->nsymbol; i++){
|
| - sprintf(line,"\"%s\",",lemp->symbols[i]->name);
|
| + lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
|
| fprintf(out," %-15s",line);
|
| if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
|
| }
|
| @@ -4054,12 +4168,15 @@ void ReportHeader(struct lemon *lemp)
|
| else prefix = "";
|
| in = file_open(lemp,".h","rb");
|
| if( in ){
|
| + int nextChar;
|
| for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
|
| - sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
|
| + lemon_sprintf(pattern,"#define %s%-30s %3d\n",
|
| + prefix,lemp->symbols[i]->name,i);
|
| if( strcmp(line,pattern) ) break;
|
| }
|
| + nextChar = fgetc(in);
|
| fclose(in);
|
| - if( i==lemp->nterminal ){
|
| + if( i==lemp->nterminal && nextChar==EOF ){
|
| /* No change in the file. Don't rewrite it. */
|
| return;
|
| }
|
| @@ -4067,7 +4184,7 @@ void ReportHeader(struct lemon *lemp)
|
| out = file_open(lemp,".h","wb");
|
| if( out ){
|
| for(i=1; i<lemp->nterminal; i++){
|
| - fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
|
| + fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i);
|
| }
|
| fclose(out);
|
| }
|
| @@ -4265,10 +4382,10 @@ int SetUnion(char *s1, char *s2)
|
| ** Code for processing tables in the LEMON parser generator.
|
| */
|
|
|
| -PRIVATE int strhash(const char *x)
|
| +PRIVATE unsigned strhash(const char *x)
|
| {
|
| - int h = 0;
|
| - while( *x) h = h*13 + *(x++);
|
| + unsigned h = 0;
|
| + while( *x ) h = h*13 + *(x++);
|
| return h;
|
| }
|
|
|
| @@ -4284,7 +4401,7 @@ const char *Strsafe(const char *y)
|
| if( y==0 ) return 0;
|
| z = Strsafe_find(y);
|
| if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){
|
| - strcpy(cpy,y);
|
| + lemon_strcpy(cpy,y);
|
| z = cpy;
|
| Strsafe_insert(z);
|
| }
|
| @@ -4323,8 +4440,7 @@ void Strsafe_init(){
|
| if( x1a ){
|
| x1a->size = 1024;
|
| x1a->count = 0;
|
| - x1a->tbl = (x1node*)malloc(
|
| - (sizeof(x1node) + sizeof(x1node*))*1024 );
|
| + x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*));
|
| if( x1a->tbl==0 ){
|
| free(x1a);
|
| x1a = 0;
|
| @@ -4340,8 +4456,8 @@ void Strsafe_init(){
|
| int Strsafe_insert(const char *data)
|
| {
|
| x1node *np;
|
| - int h;
|
| - int ph;
|
| + unsigned h;
|
| + unsigned ph;
|
|
|
| if( x1a==0 ) return 0;
|
| ph = strhash(data);
|
| @@ -4361,8 +4477,7 @@ int Strsafe_insert(const char *data)
|
| struct s_x1 array;
|
| array.size = size = x1a->size*2;
|
| array.count = x1a->count;
|
| - array.tbl = (x1node*)malloc(
|
| - (sizeof(x1node) + sizeof(x1node*))*size );
|
| + array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*));
|
| if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
| array.ht = (x1node**)&(array.tbl[size]);
|
| for(i=0; i<size; i++) array.ht[i] = 0;
|
| @@ -4395,7 +4510,7 @@ int Strsafe_insert(const char *data)
|
| ** if no such key. */
|
| const char *Strsafe_find(const char *key)
|
| {
|
| - int h;
|
| + unsigned h;
|
| x1node *np;
|
|
|
| if( x1a==0 ) return 0;
|
| @@ -4437,11 +4552,15 @@ struct symbol *Symbol_new(const char *x)
|
| return sp;
|
| }
|
|
|
| -/* Compare two symbols for working purposes
|
| +/* Compare two symbols for sorting purposes. Return negative,
|
| +** zero, or positive if a is less then, equal to, or greater
|
| +** than b.
|
| **
|
| ** Symbols that begin with upper case letters (terminals or tokens)
|
| ** must sort before symbols that begin with lower case letters
|
| -** (non-terminals). Other than that, the order does not matter.
|
| +** (non-terminals). And MULTITERMINAL symbols (created using the
|
| +** %token_class directive) must sort at the very end. Other than
|
| +** that, the order does not matter.
|
| **
|
| ** We find experimentally that leaving the symbols in their original
|
| ** order (the order they appeared in the grammar file) gives the
|
| @@ -4449,12 +4568,11 @@ struct symbol *Symbol_new(const char *x)
|
| */
|
| int Symbolcmpp(const void *_a, const void *_b)
|
| {
|
| - const struct symbol **a = (const struct symbol **) _a;
|
| - const struct symbol **b = (const struct symbol **) _b;
|
| - int i1 = (**a).index + 10000000*((**a).name[0]>'Z');
|
| - int i2 = (**b).index + 10000000*((**b).name[0]>'Z');
|
| - assert( i1!=i2 || strcmp((**a).name,(**b).name)==0 );
|
| - return i1-i2;
|
| + const struct symbol *a = *(const struct symbol **) _a;
|
| + const struct symbol *b = *(const struct symbol **) _b;
|
| + int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1;
|
| + int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1;
|
| + return i1==i2 ? a->index - b->index : i1 - i2;
|
| }
|
|
|
| /* There is one instance of the following structure for each
|
| @@ -4489,8 +4607,7 @@ void Symbol_init(){
|
| if( x2a ){
|
| x2a->size = 128;
|
| x2a->count = 0;
|
| - x2a->tbl = (x2node*)malloc(
|
| - (sizeof(x2node) + sizeof(x2node*))*128 );
|
| + x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*));
|
| if( x2a->tbl==0 ){
|
| free(x2a);
|
| x2a = 0;
|
| @@ -4506,8 +4623,8 @@ void Symbol_init(){
|
| int Symbol_insert(struct symbol *data, const char *key)
|
| {
|
| x2node *np;
|
| - int h;
|
| - int ph;
|
| + unsigned h;
|
| + unsigned ph;
|
|
|
| if( x2a==0 ) return 0;
|
| ph = strhash(key);
|
| @@ -4527,8 +4644,7 @@ int Symbol_insert(struct symbol *data, const char *key)
|
| struct s_x2 array;
|
| array.size = size = x2a->size*2;
|
| array.count = x2a->count;
|
| - array.tbl = (x2node*)malloc(
|
| - (sizeof(x2node) + sizeof(x2node*))*size );
|
| + array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*));
|
| if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
| array.ht = (x2node**)&(array.tbl[size]);
|
| for(i=0; i<size; i++) array.ht[i] = 0;
|
| @@ -4563,7 +4679,7 @@ int Symbol_insert(struct symbol *data, const char *key)
|
| ** if no such key. */
|
| struct symbol *Symbol_find(const char *key)
|
| {
|
| - int h;
|
| + unsigned h;
|
| x2node *np;
|
|
|
| if( x2a==0 ) return 0;
|
| @@ -4637,9 +4753,9 @@ PRIVATE int statecmp(struct config *a, struct config *b)
|
| }
|
|
|
| /* Hash a state */
|
| -PRIVATE int statehash(struct config *a)
|
| +PRIVATE unsigned statehash(struct config *a)
|
| {
|
| - int h=0;
|
| + unsigned h=0;
|
| while( a ){
|
| h = h*571 + a->rp->index*37 + a->dot;
|
| a = a->bp;
|
| @@ -4688,8 +4804,7 @@ void State_init(){
|
| if( x3a ){
|
| x3a->size = 128;
|
| x3a->count = 0;
|
| - x3a->tbl = (x3node*)malloc(
|
| - (sizeof(x3node) + sizeof(x3node*))*128 );
|
| + x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*));
|
| if( x3a->tbl==0 ){
|
| free(x3a);
|
| x3a = 0;
|
| @@ -4705,8 +4820,8 @@ void State_init(){
|
| int State_insert(struct state *data, struct config *key)
|
| {
|
| x3node *np;
|
| - int h;
|
| - int ph;
|
| + unsigned h;
|
| + unsigned ph;
|
|
|
| if( x3a==0 ) return 0;
|
| ph = statehash(key);
|
| @@ -4726,8 +4841,7 @@ int State_insert(struct state *data, struct config *key)
|
| struct s_x3 array;
|
| array.size = size = x3a->size*2;
|
| array.count = x3a->count;
|
| - array.tbl = (x3node*)malloc(
|
| - (sizeof(x3node) + sizeof(x3node*))*size );
|
| + array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*));
|
| if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
| array.ht = (x3node**)&(array.tbl[size]);
|
| for(i=0; i<size; i++) array.ht[i] = 0;
|
| @@ -4762,7 +4876,7 @@ int State_insert(struct state *data, struct config *key)
|
| ** if no such key. */
|
| struct state *State_find(struct config *key)
|
| {
|
| - int h;
|
| + unsigned h;
|
| x3node *np;
|
|
|
| if( x3a==0 ) return 0;
|
| @@ -4784,7 +4898,7 @@ struct state **State_arrayof()
|
| int i,size;
|
| if( x3a==0 ) return 0;
|
| size = x3a->count;
|
| - array = (struct state **)malloc( sizeof(struct state *)*size );
|
| + array = (struct state **)calloc(size, sizeof(struct state *));
|
| if( array ){
|
| for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
|
| }
|
| @@ -4792,9 +4906,9 @@ struct state **State_arrayof()
|
| }
|
|
|
| /* Hash a configuration */
|
| -PRIVATE int confighash(struct config *a)
|
| +PRIVATE unsigned confighash(struct config *a)
|
| {
|
| - int h=0;
|
| + unsigned h=0;
|
| h = h*571 + a->rp->index*37 + a->dot;
|
| return h;
|
| }
|
| @@ -4830,8 +4944,7 @@ void Configtable_init(){
|
| if( x4a ){
|
| x4a->size = 64;
|
| x4a->count = 0;
|
| - x4a->tbl = (x4node*)malloc(
|
| - (sizeof(x4node) + sizeof(x4node*))*64 );
|
| + x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*));
|
| if( x4a->tbl==0 ){
|
| free(x4a);
|
| x4a = 0;
|
| @@ -4847,8 +4960,8 @@ void Configtable_init(){
|
| int Configtable_insert(struct config *data)
|
| {
|
| x4node *np;
|
| - int h;
|
| - int ph;
|
| + unsigned h;
|
| + unsigned ph;
|
|
|
| if( x4a==0 ) return 0;
|
| ph = confighash(data);
|
| @@ -4868,8 +4981,7 @@ int Configtable_insert(struct config *data)
|
| struct s_x4 array;
|
| array.size = size = x4a->size*2;
|
| array.count = x4a->count;
|
| - array.tbl = (x4node*)malloc(
|
| - (sizeof(x4node) + sizeof(x4node*))*size );
|
| + array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*));
|
| if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
| array.ht = (x4node**)&(array.tbl[size]);
|
| for(i=0; i<size; i++) array.ht[i] = 0;
|
|
|