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; |