Update lemon and its template to most recent upstream version
This should fix some Coverity warnings about memory management in the lemon tool (less critical), but also fix improper memory accesses in the generated parsers (labeled critical by Coverity). Ref: https://sqlite.org/forum/forumpost/edecf32da3
This commit is contained in:
parent
650cff5b39
commit
68985490c6
|
@ -1591,14 +1591,14 @@ static struct rule *Rule_merge(struct rule *pA, struct rule *pB){
|
|||
** Sort a list of rules in order of increasing iRule value
|
||||
*/
|
||||
static struct rule *Rule_sort(struct rule *rp){
|
||||
int i;
|
||||
unsigned int i;
|
||||
struct rule *pNext;
|
||||
struct rule *x[32];
|
||||
memset(x, 0, sizeof(x));
|
||||
while( rp ){
|
||||
pNext = rp->next;
|
||||
rp->next = 0;
|
||||
for(i=0; i<sizeof(x)/sizeof(x[0]) && x[i]; i++){
|
||||
for(i=0; i<sizeof(x)/sizeof(x[0])-1 && x[i]; i++){
|
||||
rp = Rule_merge(x[i], rp);
|
||||
x[i] = 0;
|
||||
}
|
||||
|
@ -1625,8 +1625,7 @@ static void stats_line(const char *zLabel, int iValue){
|
|||
}
|
||||
|
||||
/* The main program. Parse the command line and do it... */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int main(int argc, char **argv){
|
||||
static int version = 0;
|
||||
static int rpflag = 0;
|
||||
static int basisflag = 0;
|
||||
|
@ -1669,6 +1668,7 @@ int main(int argc, char **argv)
|
|||
struct lemon lem;
|
||||
struct rule *rp;
|
||||
|
||||
(void)argc;
|
||||
OptInit(argv,options,stderr);
|
||||
if( version ){
|
||||
printf("Lemon version 1.0\n");
|
||||
|
@ -2266,7 +2266,7 @@ static void parseonetoken(struct pstate *psp)
|
|||
psp->preccounter = 0;
|
||||
psp->firstrule = psp->lastrule = 0;
|
||||
psp->gp->nrule = 0;
|
||||
/* Fall thru to next case */
|
||||
/* fall through */
|
||||
case WAITING_FOR_DECL_OR_RULE:
|
||||
if( x[0]=='%' ){
|
||||
psp->state = WAITING_FOR_DECL_KEYWORD;
|
||||
|
@ -2426,7 +2426,7 @@ static void parseonetoken(struct pstate *psp)
|
|||
psp->alias[psp->nrhs] = 0;
|
||||
psp->nrhs++;
|
||||
}
|
||||
}else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
|
||||
}else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 && ISUPPER(x[1]) ){
|
||||
struct symbol *msp = psp->rhs[psp->nrhs-1];
|
||||
if( msp->type!=MULTITERMINAL ){
|
||||
struct symbol *origsp = msp;
|
||||
|
@ -2638,8 +2638,10 @@ static void parseonetoken(struct pstate *psp)
|
|||
}
|
||||
nOld = lemonStrlen(zOld);
|
||||
n = nOld + nNew + 20;
|
||||
addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro &&
|
||||
(psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
|
||||
addLineMacro = !psp->gp->nolinenosflag
|
||||
&& psp->insertLineMacro
|
||||
&& psp->tokenlineno>1
|
||||
&& (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
|
||||
if( addLineMacro ){
|
||||
for(z=psp->filename, nBack=0; *z; z++){
|
||||
if( *z=='\\' ) nBack++;
|
||||
|
@ -3516,7 +3518,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
|
|||
{
|
||||
const char *pathlist;
|
||||
char *pathbufptr;
|
||||
char *pathbuf;
|
||||
char *pathbuf = 0;
|
||||
char *path,*cp;
|
||||
char c;
|
||||
|
||||
|
@ -3550,8 +3552,8 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
|
|||
else pathbuf = &cp[1];
|
||||
if( access(path,modemask)==0 ) break;
|
||||
}
|
||||
free(pathbufptr);
|
||||
}
|
||||
free(pathbufptr);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
@ -3617,6 +3619,16 @@ PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
|
|||
}
|
||||
}
|
||||
|
||||
/* Skip forward past the header of the template file to the first "%%"
|
||||
*/
|
||||
PRIVATE void tplt_skip_header(FILE *in, int *lineno)
|
||||
{
|
||||
char line[LINESIZE];
|
||||
while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
|
||||
(*lineno)++;
|
||||
}
|
||||
}
|
||||
|
||||
/* The next function finds the template file and opens it, returning
|
||||
** a pointer to the opened file. */
|
||||
PRIVATE FILE *tplt_open(struct lemon *lemp)
|
||||
|
@ -3625,6 +3637,7 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
|
|||
char buf[1000];
|
||||
FILE *in;
|
||||
char *tpltname;
|
||||
char *toFree = 0;
|
||||
char *cp;
|
||||
|
||||
/* first, see if user specified a template filename on the command line. */
|
||||
|
@ -3656,7 +3669,7 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
|
|||
}else if( access(templatename,004)==0 ){
|
||||
tpltname = templatename;
|
||||
}else{
|
||||
tpltname = pathsearch(lemp->argv0,templatename,0);
|
||||
toFree = tpltname = pathsearch(lemp->argv0,templatename,0);
|
||||
}
|
||||
if( tpltname==0 ){
|
||||
fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
|
||||
|
@ -3666,10 +3679,10 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
|
|||
}
|
||||
in = fopen(tpltname,"rb");
|
||||
if( in==0 ){
|
||||
fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
|
||||
fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname);
|
||||
lemp->errorcnt++;
|
||||
return 0;
|
||||
}
|
||||
free(toFree);
|
||||
return in;
|
||||
}
|
||||
|
||||
|
@ -4287,6 +4300,7 @@ void ReportTable(
|
|||
int mnTknOfst, mxTknOfst;
|
||||
int mnNtOfst, mxNtOfst;
|
||||
struct axset *ax;
|
||||
char *prefix;
|
||||
|
||||
lemp->minShiftReduce = lemp->nstate;
|
||||
lemp->errAction = lemp->minShiftReduce + lemp->nrule;
|
||||
|
@ -4375,7 +4389,26 @@ void ReportTable(
|
|||
fprintf(sql, "COMMIT;\n");
|
||||
}
|
||||
lineno = 1;
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
fprintf(out,
|
||||
"/* This file is automatically generated by Lemon from input grammar\n"
|
||||
"** source file \"%s\". */\n", lemp->filename); lineno += 2;
|
||||
|
||||
/* The first %include directive begins with a C-language comment,
|
||||
** then skip over the header comment of the template file
|
||||
*/
|
||||
if( lemp->include==0 ) lemp->include = "";
|
||||
for(i=0; ISSPACE(lemp->include[i]); i++){
|
||||
if( lemp->include[i]=='\n' ){
|
||||
lemp->include += i+1;
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
if( lemp->include[0]=='/' ){
|
||||
tplt_skip_header(in,&lineno);
|
||||
}else{
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
}
|
||||
|
||||
/* Generate the include code, if any */
|
||||
tplt_print(out,lemp,lemp->include,&lineno);
|
||||
|
@ -4387,17 +4420,18 @@ void ReportTable(
|
|||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate #defines for all tokens */
|
||||
if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
|
||||
else prefix = "";
|
||||
if( mhflag ){
|
||||
const char *prefix;
|
||||
fprintf(out,"#if INTERFACE\n"); lineno++;
|
||||
if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
|
||||
else prefix = "";
|
||||
for(i=1; i<lemp->nterminal; i++){
|
||||
fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
|
||||
lineno++;
|
||||
}
|
||||
fprintf(out,"#endif\n"); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#ifndef %s%s\n", prefix, lemp->symbols[1]->name);
|
||||
}
|
||||
for(i=1; i<lemp->nterminal; i++){
|
||||
fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
|
||||
lineno++;
|
||||
}
|
||||
fprintf(out,"#endif\n"); lineno++;
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Generate the defines */
|
||||
|
|
|
@ -22,17 +22,13 @@
|
|||
** The following is the concatenation of all %include directives from the
|
||||
** input grammar file:
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
/************ Begin %include sections from the grammar ************************/
|
||||
%%
|
||||
/**************** End of %include directives **********************************/
|
||||
/* These constants specify the various numeric values for terminal symbols
|
||||
** in a format understandable to "makeheaders". This section is blank unless
|
||||
** "lemon" is run with the "-m" command-line option.
|
||||
***************** Begin makeheaders token definitions *************************/
|
||||
/* These constants specify the various numeric values for terminal symbols.
|
||||
***************** Begin token definitions *************************************/
|
||||
%%
|
||||
/**************** End makeheaders token definitions ***************************/
|
||||
/**************** End token definitions ***************************************/
|
||||
|
||||
/* The next sections is a series of control #defines.
|
||||
** various aspects of the generated parser.
|
||||
|
@ -229,6 +225,7 @@ typedef struct yyParser yyParser;
|
|||
|
||||
#ifndef NDEBUG
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
static FILE *yyTraceFILE = 0;
|
||||
static char *yyTracePrompt = 0;
|
||||
#endif /* NDEBUG */
|
||||
|
@ -562,7 +559,7 @@ static YYACTIONTYPE yy_find_shift_action(
|
|||
#endif /* YYWILDCARD */
|
||||
return yy_default[stateno];
|
||||
}else{
|
||||
assert( i>=0 && i<sizeof(yy_action)/sizeof(yy_action[0]) );
|
||||
assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) );
|
||||
return yy_action[i];
|
||||
}
|
||||
}while(1);
|
||||
|
@ -721,8 +718,9 @@ static YYACTIONTYPE yy_reduce(
|
|||
(void)yyLookahead;
|
||||
(void)yyLookaheadToken;
|
||||
yymsp = yypParser->yytos;
|
||||
assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
|
||||
if( yyTraceFILE ){
|
||||
yysize = yyRuleInfoNRhs[yyruleno];
|
||||
if( yysize ){
|
||||
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
|
||||
|
|
Loading…
Reference in New Issue