Lemon: import fresh lemon from upstream

- get latest lemon from upstream (SQLite)
- update and apply the patches
- introduce CC0-1.0 license indication
- update documentation
This commit is contained in:
Jaap Keuter 2020-12-03 20:33:08 +01:00 committed by AndersBroman
parent 10e9ac701b
commit 27acec97e9
11 changed files with 447 additions and 211 deletions

View File

@ -7,15 +7,17 @@ Git mirror of the upstream Fossil repository: https://github.com/mackyle/sqlite
The lempar.c and lemon.c are taken from sqlite and are modified as little as
possible to make it easier to synchronize changes. Last updated at:
commit 1150d3841d9381555a4b427835fd617d3465040d
Date: Sat Sep 8 16:55:18 2018 +0000
Add a missing call to free() in Lemon.
commit 273ee151217b04c640c1af148e36c518678c89fa
Author: mistachkin <mistachkin@noemail.net>
Date: Mon Sep 21 20:18:44 2020 +0000
Fix harmless compiler warning seen with MSVC.
To check for changes (adjust "previous commit" accordingly):
git clone --depth=1000 https://github.com/mackyle/sqlite
git clone --depth=1000 https://github.com/sqlite/sqlite
cd sqlite/tools
git log -p 1150d3841d.. lemon.c lempar.c
git log -p 273ee15121.. lemon.c lempar.c
To create a Wireshark version (steps 1-3) and validate the result (steps 4-5):
1. Copy the two files.
@ -39,5 +41,5 @@ A note about the Lemon patches, we have no intention to fork Lemon and maintain
it. These patches are written to address static analyzer warnings without
actually modifying the functionality. If upstream is willing to accept patches,
then that would be great and the intention is to make it as easy as possible.
The lemon and lempar patches are dedicated to the public domain. (IANAL, but I
hope this is sufficient.)
The lemon and lempar patches are dedicated to the public domain, as set forward
in Creative Commons Zero v1.0 Universal (IANAL, but I hope this is sufficient).

View File

@ -48,6 +48,7 @@ extern int access(const char *path, int mode);
#define MAXRHS 1000
#endif
extern void memory_error();
static int showPrecedenceConflict = 0;
static char *msort(char*,char**,int(*)(const char*,const char*));
@ -217,7 +218,7 @@ void Plink_delete(struct plink *);
/********** From the file "report.h" *************************************/
void Reprint(struct lemon *);
void ReportOutput(struct lemon *);
void ReportTable(struct lemon *, int);
void ReportTable(struct lemon *, int, int);
void ReportHeader(struct lemon *);
void CompressTables(struct lemon *);
void ResortStates(struct lemon *);
@ -291,13 +292,15 @@ struct rule {
const char *code; /* The code executed when this rule is reduced */
const char *codePrefix; /* Setup code before code[] above */
const char *codeSuffix; /* Breakdown code after code[] above */
int noCode; /* True if this rule has no associated C code */
int codeEmitted; /* True if the code has been emitted already */
struct symbol *precsym; /* Precedence symbol for this rule */
int index; /* An index number for this rule */
int iRule; /* Rule number as used in the generated tables */
Boolean noCode; /* True if this rule has no associated C code */
Boolean codeEmitted; /* True if the code has been emitted already */
Boolean canReduce; /* True if this rule is ever reduced */
Boolean doesReduce; /* Reduce actions occur after optimization */
Boolean neverReduce; /* Reduce is theoretically possible, but prevented
** by actions or other outside implementation */
struct rule *nextlhs; /* Next rule with the same LHS */
struct rule *next; /* Next rule in the global list */
};
@ -384,6 +387,7 @@ struct lemon {
int nstate; /* Number of states */
int nxstate; /* nstate with tail degenerate states removed */
int nrule; /* Number of rules */
int nruleWithAction; /* Number of rules with actions */
int nsymbol; /* Number of terminal and nonterminal symbols */
int nterminal; /* Number of terminal symbols */
int minShiftReduce; /* Minimum shift-reduce action value */
@ -419,6 +423,7 @@ struct lemon {
int nlookaheadtab; /* Number of entries in yy_lookahead[] */
int tablesize; /* Total table size of all tables in bytes */
int basisflag; /* Print only basis configurations */
int printPreprocessed; /* Show preprocessor output on stdout */
int has_fallback; /* True if any %fallback is seen in the grammar */
int nolinenosflag; /* True if #line statements should not be printed */
char *argv0; /* Name of the program */
@ -483,22 +488,22 @@ void Configtable_clear(int(*)(struct config *));
/* Allocate a new parser action */
static struct action *Action_new(void){
static struct action *freelist = 0;
static struct action *actionfreelist = 0;
struct action *newaction;
if( freelist==0 ){
if( actionfreelist==0 ){
int i;
int amt = 100;
freelist = (struct action *)calloc(amt, sizeof(struct action));
if( freelist==0 ){
actionfreelist = (struct action *)calloc(amt, sizeof(struct action));
if( actionfreelist==0 ){
fprintf(stderr,"Unable to allocate memory for a new parser action.");
exit(1);
}
for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
freelist[amt-1].next = 0;
for(i=0; i<amt-1; i++) actionfreelist[i].next = &actionfreelist[i+1];
actionfreelist[amt-1].next = 0;
}
newaction = freelist;
freelist = freelist->next;
newaction = actionfreelist;
actionfreelist = actionfreelist->next;
return newaction;
}
@ -908,9 +913,9 @@ void FindStates(struct lemon *lemp)
sp = Symbol_find(lemp->start);
if( sp==0 ){
ErrorMsg(lemp->filename,0,
"The specified start symbol \"%s\" is not \
in a nonterminal of the grammar. \"%s\" will be used as the start \
symbol instead.",lemp->start,lemp->startRule->lhs->name);
"The specified start symbol \"%s\" is not "
"in a nonterminal of the grammar. \"%s\" will be used as the start "
"symbol instead.",lemp->start,lemp->startRule->lhs->name);
lemp->errorcnt++;
sp = lemp->startRule->lhs;
}
@ -926,9 +931,9 @@ symbol instead.",lemp->start,lemp->startRule->lhs->name);
for(i=0; i<rp->nrhs; i++){
if( rp->rhs[i]==sp ){ /* FIX ME: Deal with multiterminals */
ErrorMsg(lemp->filename,0,
"The start symbol \"%s\" occurs on the \
right-hand side of a rule. This will result in a parser which \
does not work properly.",sp->name);
"The start symbol \"%s\" occurs on the "
"right-hand side of a rule. This will result in a parser which "
"does not work properly.",sp->name);
lemp->errorcnt++;
}
}
@ -994,7 +999,9 @@ PRIVATE struct state *getstate(struct lemon *lemp)
int ret =
#endif
State_insert(stp,stp->bp); /* Add to the state table */
#ifndef NDEBUG
assert(ret == 1); /* CSA hint: stp did not leak, it has escaped. */
#endif
buildshifts(lemp,stp); /* Recursively compute successor states */
}
return stp;
@ -1593,14 +1600,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;
}
@ -1627,8 +1634,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;
@ -1638,14 +1644,15 @@ static void stats_line(const char *zLabel, int iValue){
static int mhflag = 0;
static int nolinenosflag = 0;
static int noResort = 0;
(void) argc; /* Mark unused, similar to Q_UNUSED */
static int sqlFlag = 0;
static int printPP = 0;
static struct s_options options[] = {
{OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
{OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
{OPT_FSTR, "d", (char*)&handle_d_option, "Output directory. Default '.'"},
{OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
{OPT_FLAG, "E", (char*)&printPP, "Print input file after preprocessing."},
{OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"},
{OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
{OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"},
@ -1658,6 +1665,8 @@ static void stats_line(const char *zLabel, int iValue){
{OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
{OPT_FLAG, "s", (char*)&statistics,
"Print parser stats to standard output."},
{OPT_FLAG, "S", (char*)&sqlFlag,
"Generate the *.sql file describing the parser tables."},
{OPT_FLAG, "x", (char*)&version, "Print the version number."},
{OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
{OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"},
@ -1668,6 +1677,7 @@ static void stats_line(const char *zLabel, int iValue){
struct lemon lem;
struct rule *rp;
(void)argc;
OptInit(argv,options,stderr);
if( version ){
printf("Lemon version 1.0\n");
@ -1688,11 +1698,12 @@ static void stats_line(const char *zLabel, int iValue){
lem.filename = OptArg(0);
lem.basisflag = basisflag;
lem.nolinenosflag = nolinenosflag;
lem.printPreprocessed = printPP;
Symbol_new("$");
/* Parse the input file */
Parse(&lem);
if( lem.errorcnt ) exit(lem.errorcnt);
if( lem.printPreprocessed || lem.errorcnt ) exit(lem.errorcnt);
assert(lem.rule); /* Hint for CSA (no errors => rule found). */
if( lem.nrule==0 ){
fprintf(stderr,"Empty grammar.\n");
@ -1720,6 +1731,7 @@ static void stats_line(const char *zLabel, int iValue){
for(i=0, rp=lem.rule; rp; rp=rp->next){
rp->iRule = rp->code ? i++ : -1;
}
lem.nruleWithAction = i;
for(rp=lem.rule; rp; rp=rp->next){
if( rp->iRule<0 ) rp->iRule = i++;
}
@ -1767,7 +1779,7 @@ static void stats_line(const char *zLabel, int iValue){
if( !quiet ) ReportOutput(&lem);
/* Generate the source code for the parser */
ReportTable(&lem, mhflag);
ReportTable(&lem, mhflag, sqlFlag);
/* Produce a header file for use by the scanner. (This step is
** omitted if the "-m" option is used because makeheaders will
@ -1917,7 +1929,7 @@ static char *msort(
return ep;
}
/************************ From the file "option.c" **************************/
static char **argv;
static char **g_argv;
static struct s_options *op;
static FILE *errstream;
@ -1930,14 +1942,14 @@ static FILE *errstream;
static void errline(int n, int k, FILE *err)
{
int spcnt, i;
if( argv[0] ) fprintf(err,"%s",argv[0]);
spcnt = lemonStrlen(argv[0]) + 1;
for(i=1; i<n && argv[i]; i++){
fprintf(err," %s",argv[i]);
spcnt += lemonStrlen(argv[i])+1;
if( g_argv[0] ) fprintf(err,"%s",g_argv[0]);
spcnt = lemonStrlen(g_argv[0]) + 1;
for(i=1; i<n && g_argv[i]; i++){
fprintf(err," %s",g_argv[i]);
spcnt += lemonStrlen(g_argv[i])+1;
}
spcnt += k;
for(; argv[i]; i++) fprintf(err," %s",argv[i]);
for(; g_argv[i]; i++) fprintf(err," %s",g_argv[i]);
if( spcnt<20 ){
fprintf(err,"\n%*s^-- here\n",spcnt,"");
}else{
@ -1953,13 +1965,13 @@ static int argindex(int n)
{
int i;
int dashdash = 0;
if( argv!=0 && *argv!=0 ){
for(i=1; argv[i]; i++){
if( dashdash || !ISOPT(argv[i]) ){
if( g_argv!=0 && *g_argv!=0 ){
for(i=1; g_argv[i]; i++){
if( dashdash || !ISOPT(g_argv[i]) ){
if( n==0 ) return i;
n--;
}
if( strcmp(argv[i],"--")==0 ) dashdash = 1;
if( strcmp(g_argv[i],"--")==0 ) dashdash = 1;
}
}
return -1;
@ -1976,9 +1988,9 @@ static int handleflags(int i, FILE *err)
int errcnt = 0;
int j;
for(j=0; op[j].label; j++){
if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
if( strncmp(&g_argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
}
v = argv[i][0]=='-' ? 1 : 0;
v = g_argv[i][0]=='-' ? 1 : 0;
if( op[j].label==0 ){
if( err ){
fprintf(err,"%sundefined option.\n",emsg);
@ -1992,7 +2004,7 @@ static int handleflags(int i, FILE *err)
}else if( op[j].type==OPT_FFLAG ){
(*(void(*)(int))(op[j].arg))(v);
}else if( op[j].type==OPT_FSTR ){
(*(void(*)(char *))(op[j].arg))(&argv[i][2]);
(*(void(*)(char *))(op[j].arg))(&g_argv[i][2]);
}else{
if( err ){
fprintf(err,"%smissing argument on switch.\n",emsg);
@ -2014,11 +2026,11 @@ static int handleswitch(int i, FILE *err)
char *cp;
int j;
int errcnt = 0;
cp = strchr(argv[i],'=');
cp = strchr(g_argv[i],'=');
assert( cp!=0 );
*cp = 0;
for(j=0; op[j].label; j++){
if( strcmp(argv[i],op[j].label)==0 ) break;
if( strcmp(g_argv[i],op[j].label)==0 ) break;
}
*cp = '=';
if( op[j].label==0 ){
@ -2045,7 +2057,7 @@ static int handleswitch(int i, FILE *err)
if( err ){
fprintf(err,
"%sillegal character in floating-point argument.\n",emsg);
errline(i,(int)((char*)end-(char*)argv[i]),err);
errline(i,(int)((char*)end-(char*)g_argv[i]),err);
}
errcnt++;
}
@ -2056,7 +2068,7 @@ static int handleswitch(int i, FILE *err)
if( *end ){
if( err ){
fprintf(err,"%sillegal character in integer argument.\n",emsg);
errline(i,(int)((char*)end-(char*)argv[i]),err);
errline(i,(int)((char*)end-(char*)g_argv[i]),err);
}
errcnt++;
}
@ -2096,15 +2108,15 @@ static int handleswitch(int i, FILE *err)
int OptInit(char **a, struct s_options *o, FILE *err)
{
int errcnt = 0;
argv = a;
g_argv = a;
op = o;
errstream = err;
if( argv && *argv && op ){
if( g_argv && *g_argv && op ){
int i;
for(i=1; argv[i]; i++){
if( argv[i][0]=='+' || argv[i][0]=='-' ){
for(i=1; g_argv[i]; i++){
if( g_argv[i][0]=='+' || g_argv[i][0]=='-' ){
errcnt += handleflags(i,err);
}else if( strchr(argv[i],'=') ){
}else if( strchr(g_argv[i],'=') ){
errcnt += handleswitch(i,err);
}
}
@ -2121,10 +2133,10 @@ int OptNArgs(void){
int cnt = 0;
int dashdash = 0;
int i;
if( argv!=0 && argv[0]!=0 ){
for(i=1; argv[i]; i++){
if( dashdash || !ISOPT(argv[i]) ) cnt++;
if( strcmp(argv[i],"--")==0 ) dashdash = 1;
if( g_argv!=0 && g_argv[0]!=0 ){
for(i=1; g_argv[i]; i++){
if( dashdash || !ISOPT(g_argv[i]) ) cnt++;
if( strcmp(g_argv[i],"--")==0 ) dashdash = 1;
}
}
return cnt;
@ -2134,7 +2146,7 @@ char *OptArg(int n)
{
int i;
i = argindex(n);
return i>=0 ? argv[i] : 0;
return i>=0 ? g_argv[i] : 0;
}
void OptErr(int n)
@ -2264,7 +2276,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;
@ -2276,14 +2288,16 @@ static void parseonetoken(struct pstate *psp)
}else if( x[0]=='{' ){
if( psp->prevrule==0 ){
ErrorMsg(psp->filename,psp->tokenlineno,
"There is no prior rule upon which to attach the code \
fragment which begins on this line.");
"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 ){
ErrorMsg(psp->filename,psp->tokenlineno,
"Code fragment beginning on this line is not the first \
to follow the previous rule.");
"Code fragment beginning on this line is not the first "
"to follow the previous rule.");
psp->errorcnt++;
}else if( strcmp(x, "{NEVER-REDUCE")==0 ){
psp->prevrule->neverReduce = 1;
}else{
psp->prevrule->line = psp->tokenlineno;
psp->prevrule->code = &x[1];
@ -2309,8 +2323,8 @@ to follow the previous rule.");
psp->errorcnt++;
}else if( psp->prevrule->precsym!=0 ){
ErrorMsg(psp->filename,psp->tokenlineno,
"Precedence mark on this line is not the first \
to follow the previous rule.");
"Precedence mark on this line is not the first "
"to follow the previous rule.");
psp->errorcnt++;
}else{
psp->prevrule->precsym = Symbol_new(x);
@ -2422,7 +2436,7 @@ to follow the previous rule.");
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;
@ -2634,8 +2648,10 @@ to follow the previous rule.");
}
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++;
@ -2738,7 +2754,7 @@ to follow the previous rule.");
case WAITING_FOR_CLASS_ID:
if( !ISLOWER(x[0]) ){
ErrorMsg(psp->filename, psp->tokenlineno,
"%%token_class must be followed by an identifier: ", x);
"%%token_class must be followed by an identifier: %s", x);
psp->errorcnt++;
psp->state = RESYNC_AFTER_DECL_ERROR;
}else if( Symbol_find(x) ){
@ -2779,13 +2795,108 @@ to follow the previous rule.");
}
}
/* The text in the input is part of the argument to an %ifdef or %ifndef.
** Evaluate the text as a boolean expression. Return true or false.
*/
static int eval_preprocessor_boolean(char *z, int lineno){
int neg = 0;
int res = 0;
int okTerm = 1;
int i;
for(i=0; z[i]!=0; i++){
if( ISSPACE(z[i]) ) continue;
if( z[i]=='!' ){
if( !okTerm ) goto pp_syntax_error;
neg = !neg;
continue;
}
if( z[i]=='|' && z[i+1]=='|' ){
if( okTerm ) goto pp_syntax_error;
if( res ) return 1;
i++;
okTerm = 1;
continue;
}
if( z[i]=='&' && z[i+1]=='&' ){
if( okTerm ) goto pp_syntax_error;
if( !res ) return 0;
i++;
okTerm = 1;
continue;
}
if( z[i]=='(' ){
int k;
int n = 1;
if( !okTerm ) goto pp_syntax_error;
for(k=i+1; z[k]; k++){
if( z[k]==')' ){
n--;
if( n==0 ){
z[k] = 0;
res = eval_preprocessor_boolean(&z[i+1], -1);
z[k] = ')';
if( res<0 ){
i = i-res;
goto pp_syntax_error;
}
i = k;
break;
}
}else if( z[k]=='(' ){
n++;
}else if( z[k]==0 ){
i = k;
goto pp_syntax_error;
}
}
if( neg ){
res = !res;
neg = 0;
}
okTerm = 0;
continue;
}
if( ISALPHA(z[i]) ){
int j, k, n;
if( !okTerm ) goto pp_syntax_error;
for(k=i+1; ISALNUM(z[k]) || z[k]=='_'; k++){}
n = k - i;
res = 0;
for(j=0; j<nDefine; j++){
if( strncmp(azDefine[j],&z[i],n)==0 && azDefine[j][n]==0 ){
res = 1;
break;
}
}
i = k-1;
if( neg ){
res = !res;
neg = 0;
}
okTerm = 0;
continue;
}
goto pp_syntax_error;
}
return res;
pp_syntax_error:
if( lineno>0 ){
fprintf(stderr, "%%if syntax error on line %d.\n", lineno);
fprintf(stderr, " %.*s <-- syntax error here\n", i+1, z);
exit(1);
}else{
return -(i+1);
}
}
/* Run the preprocessor over the input file text. The global variables
** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
** macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and
** comments them out. Text in between is also commented out as appropriate.
*/
static void preprocess_input(char *z){
int i, j, k, n;
int i, j, k;
int exclude = 0;
int start = 0;
int lineno = 1;
@ -2801,21 +2912,33 @@ static void preprocess_input(char *z){
}
}
for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
}else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6]))
|| (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){
}else if( strncmp(&z[i],"%else",5)==0 && ISSPACE(z[i+5]) ){
if( exclude==1){
exclude = 0;
for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
}else if( exclude==0 ){
exclude = 1;
start = i;
start_lineno = lineno;
}
for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
}else if( strncmp(&z[i],"%ifdef ",7)==0
|| strncmp(&z[i],"%if ",4)==0
|| strncmp(&z[i],"%ifndef ",8)==0 ){
if( exclude ){
exclude++;
}else{
for(j=i+7; ISSPACE(z[j]); j++){}
for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){}
exclude = 1;
for(k=0; k<nDefine; k++){
if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){
exclude = 0;
break;
}
}
if( z[i+3]=='n' ) exclude = !exclude;
int isNot;
int iBool;
for(j=i; z[j] && !ISSPACE(z[j]); j++){}
iBool = j;
isNot = (j==i+7);
while( z[j] && z[j]!='\n' ){ j++; }
k = z[j];
z[j] = 0;
exclude = eval_preprocessor_boolean(&z[iBool], lineno);
z[j] = k;
if( !isNot ) exclude = !exclude;
if( exclude ){
start = i;
start_lineno = lineno;
@ -2883,6 +3006,10 @@ void Parse(struct lemon *gp)
/* Make an initial pass through the file to handle %ifdef and %ifndef */
preprocess_input(filebuf);
if( gp->printPreprocessed ){
printf("%s\n", filebuf);
return;
}
/* Now scan the text of the input file */
lineno = 1;
@ -2913,7 +3040,8 @@ void Parse(struct lemon *gp)
}
if( c==0 ){
ErrorMsg(ps.filename,startline,
"String starting on this line is not terminated before the end of the file.");
"String starting on this line is not terminated before "
"the end of the file.");
ps.errorcnt++;
nextcp = cp;
}else{
@ -2952,7 +3080,8 @@ void Parse(struct lemon *gp)
}
if( c==0 ){
ErrorMsg(ps.filename,ps.tokenlineno,
"C code starting on this line is not terminated before the end of the file.");
"C code starting on this line is not terminated before "
"the end of the file.");
ps.errorcnt++;
nextcp = cp;
}else{
@ -3398,8 +3527,8 @@ void ReportOutput(struct lemon *lemp)
PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
{
const char *pathlist;
char *pathbufptr;
char *pathbuf;
char *pathbufptr = 0;
char *pathbuf = 0;
char *path,*cp;
char c;
@ -3434,8 +3563,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;
}
@ -3501,6 +3630,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)
@ -3509,11 +3648,9 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
char buf[1000];
FILE *in;
char *tpltname;
char *toFree = 0;
char *cp;
/* We always require the -T option, avoid memleak in the other code path. */
assert(user_templatename);
/* first, see if user specified a template filename on the command line. */
if (user_templatename != 0) {
if( access(user_templatename,004)==-1 ){
@ -3543,7 +3680,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",
@ -3553,10 +3690,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;
}
@ -3862,7 +3999,7 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
ErrorMsg(lemp->filename,rp->ruleline,
"%s(%s) has the same label as the LHS but is not the left-most "
"symbol on the RHS.",
rp->rhs[i]->name, rp->rhsalias);
rp->rhs[i]->name, rp->rhsalias[i]);
lemp->errorcnt++;
}
for(j=0; j<i; j++){
@ -4156,9 +4293,10 @@ static void writeRuleText(FILE *out, struct rule *rp){
/* Generate C source code for the parser */
void ReportTable(
struct lemon *lemp,
int mhflag /* Output in makeheaders format if true */
int mhflag, /* Output in makeheaders format if true */
int sqlFlag /* Generate the *.sql file too */
){
FILE *out, *in;
FILE *out, *in, *sql;
char line[LINESIZE];
int lineno;
struct state *stp;
@ -4166,12 +4304,14 @@ void ReportTable(
struct rule *rp;
struct acttab *pActtab;
int i, j, n, sz;
int nLookAhead;
int szActionType; /* sizeof(YYACTIONTYPE) */
int szCodeType; /* sizeof(YYCODETYPE) */
const char *name;
int mnTknOfst, mxTknOfst;
int mnNtOfst, mxNtOfst;
struct axset *ax;
char *prefix;
lemp->minShiftReduce = lemp->nstate;
lemp->errAction = lemp->minShiftReduce + lemp->nrule;
@ -4187,8 +4327,99 @@ void ReportTable(
fclose(in);
return;
}
if( sqlFlag==0 ){
sql = 0;
}else{
sql = file_open(lemp, ".sql", "wb");
if( sql==0 ){
fclose(in);
fclose(out);
return;
}
fprintf(sql,
"BEGIN;\n"
"CREATE TABLE symbol(\n"
" id INTEGER PRIMARY KEY,\n"
" name TEXT NOT NULL,\n"
" isTerminal BOOLEAN NOT NULL,\n"
" fallback INTEGER REFERENCES symbol"
" DEFERRABLE INITIALLY DEFERRED\n"
");\n"
);
for(i=0; i<lemp->nsymbol; i++){
fprintf(sql,
"INSERT INTO symbol(id,name,isTerminal,fallback)"
"VALUES(%d,'%s',%s",
i, lemp->symbols[i]->name,
i<lemp->nterminal ? "TRUE" : "FALSE"
);
if( lemp->symbols[i]->fallback ){
fprintf(sql, ",%d);\n", lemp->symbols[i]->fallback->index);
}else{
fprintf(sql, ",NULL);\n");
}
}
fprintf(sql,
"CREATE TABLE rule(\n"
" ruleid INTEGER PRIMARY KEY,\n"
" lhs INTEGER REFERENCES symbol(id),\n"
" txt TEXT\n"
");\n"
"CREATE TABLE rulerhs(\n"
" ruleid INTEGER REFERENCES rule(ruleid),\n"
" pos INTEGER,\n"
" sym INTEGER REFERENCES symbol(id)\n"
");\n"
);
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
assert( i==rp->iRule );
fprintf(sql,
"INSERT INTO rule(ruleid,lhs,txt)VALUES(%d,%d,'",
rp->iRule, rp->lhs->index
);
writeRuleText(sql, rp);
fprintf(sql,"');\n");
for(j=0; j<rp->nrhs; j++){
struct symbol *sp = rp->rhs[j];
if( sp->type!=MULTITERMINAL ){
fprintf(sql,
"INSERT INTO rulerhs(ruleid,pos,sym)VALUES(%d,%d,%d);\n",
i,j,sp->index
);
}else{
int k;
for(k=0; k<sp->nsubsym; k++){
fprintf(sql,
"INSERT INTO rulerhs(ruleid,pos,sym)VALUES(%d,%d,%d);\n",
i,j,sp->subsym[k]->index
);
}
}
}
}
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);
@ -4200,17 +4431,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 */
@ -4362,6 +4594,8 @@ void ReportTable(
** been computed */
fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
fprintf(out,"#define YYNRULE_WITH_ACTION %d\n",lemp->nruleWithAction);
lineno++;
fprintf(out,"#define YYNTOKEN %d\n",lemp->nterminal); lineno++;
fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++;
i = lemp->minShiftReduce;
@ -4416,15 +4650,30 @@ void ReportTable(
if( la<0 ) la = lemp->nsymbol;
if( j==0 ) fprintf(out," /* %5d */ ", i);
fprintf(out, " %4d,", la);
if( j==9 || i==n-1 ){
if( j==9 ){
fprintf(out, "\n"); lineno++;
j = 0;
}else{
j++;
}
}
/* Add extra entries to the end of the yy_lookahead[] table so that
** yy_shift_ofst[]+iToken will always be a valid index into the array,
** even for the largest possible value of yy_shift_ofst[] and iToken. */
nLookAhead = lemp->nterminal + lemp->nactiontab;
while( i<nLookAhead ){
if( j==0 ) fprintf(out," /* %5d */ ", i);
fprintf(out, " %4d,", lemp->nterminal);
if( j==9 ){
fprintf(out, "\n"); lineno++;
j = 0;
}else{
j++;
}
i++;
}
if( j>0 ){ fprintf(out, "\n"); lineno++; }
fprintf(out, "};\n"); lineno++;
acttab_free(pActtab);
/* Output the yy_shift_ofst[] table */
n = lemp->nxstate;
@ -4503,7 +4752,9 @@ void ReportTable(
*/
if( lemp->has_fallback ){
int mx = lemp->nterminal - 1;
while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
/* 2019-08-28: Generate fallback entries for every token to avoid
** having to do a range check on the index */
/* while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } */
lemp->tablesize += (mx+1)*szCodeType;
for(i=0; i<=mx; i++){
struct symbol *p = lemp->symbols[i];
@ -4605,13 +4856,20 @@ void ReportTable(
tplt_print(out,lemp,lemp->overflow,&lineno);
tplt_xfer(lemp->name,in,out,&lineno);
/* Generate the table of rule information
/* Generate the tables of rule information. yyRuleInfoLhs[] and
** yyRuleInfoNRhs[].
**
** Note: This code depends on the fact that rules are number
** sequentually beginning with 0.
*/
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
fprintf(out," { %4d, %4d }, /* (%d) ",rp->lhs->index,-rp->nrhs,i);
fprintf(out," %4d, /* (%d) ", rp->lhs->index, i);
rule_print(out, rp);
fprintf(out," */\n"); lineno++;
}
tplt_xfer(lemp->name,in,out,&lineno);
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
fprintf(out," %3d, /* (%d) ", -rp->nrhs, i);
rule_print(out, rp);
fprintf(out," */\n"); lineno++;
}
@ -4657,7 +4915,10 @@ void ReportTable(
assert( rp->noCode );
fprintf(out," /* (%d) ", rp->iRule);
writeRuleText(out, rp);
if( rp->doesReduce ){
if( rp->neverReduce ){
fprintf(out, " (NEVER REDUCES) */ assert(yyruleno!=%d);\n",
rp->iRule); lineno++;
}else if( rp->doesReduce ){
fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
}else{
fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n",
@ -4682,8 +4943,10 @@ void ReportTable(
/* Append any addition code the user desires */
tplt_print(out,lemp,lemp->extracode,&lineno);
acttab_free(pActtab);
fclose(in);
fclose(out);
if( sql ) fclose(sql);
return;
}
@ -4926,7 +5189,6 @@ char *SetNew(void){
char *s;
s = (char*)calloc( size, 1);
if( s==0 ){
extern void memory_error();
memory_error();
}
return s;

View File

@ -22,16 +22,13 @@
** The following is the concatenation of all %include directives from the
** input grammar file:
*/
#include <stdio.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.
@ -228,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 */
@ -520,15 +518,18 @@ static YYACTIONTYPE yy_find_shift_action(
do{
i = yy_shift_ofst[stateno];
assert( i>=0 );
/* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */
assert( i<=YY_ACTTAB_COUNT );
assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD );
assert( iLookAhead!=YYNOCODE );
assert( iLookAhead < YYNTOKEN );
i += iLookAhead;
if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){
assert( i<(int)YY_NLOOKAHEAD );
if( yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
&& (iFallback = yyFallback[iLookAhead])!=0 ){
assert( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) );
iFallback = yyFallback[iLookAhead];
if( iFallback!=0 ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
@ -543,16 +544,8 @@ static YYACTIONTYPE yy_find_shift_action(
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
if(
#if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) &&
yy_lookahead[j]==YYWILDCARD && iLookAhead>0
){
assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) );
if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
@ -566,6 +559,7 @@ static YYACTIONTYPE yy_find_shift_action(
#endif /* YYWILDCARD */
return yy_default[stateno];
}else{
assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) );
return yy_action[i];
}
}while(1);
@ -685,13 +679,15 @@ static void yy_shift(
yyTraceShift(yypParser, yyNewState, "Shift");
}
/* The following table contains information about every rule that
** is used during the reduce.
*/
static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
signed char nrhs; /* Negative of the number of RHS symbols in the rule */
} yyRuleInfo[] = {
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = {
%%
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
** of symbols on the right-hand side of that rule. */
static const signed char yyRuleInfoNRhs[] = {
%%
};
@ -722,16 +718,20 @@ 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])) ){
yysize = yyRuleInfo[yyruleno].nrhs;
if( yyTraceFILE ){
yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
yyTracePrompt,
yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno);
yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
yymsp[yysize].stateno);
}else{
fprintf(yyTraceFILE, "%sReduce %d [%s].\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno]);
fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
yyTracePrompt, yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
}
}
#endif /* NDEBUG */
@ -739,7 +739,7 @@ static YYACTIONTYPE yy_reduce(
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
if( yyRuleInfo[yyruleno].nrhs==0 ){
if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
@ -781,9 +781,9 @@ static YYACTIONTYPE yy_reduce(
%%
/********** End reduce actions ************************************************/
};
assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
yygoto = yyRuleInfoLhs[yyruleno];
yysize = yyRuleInfoNRhs[yyruleno];
yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
/* There are no SHIFTREDUCE actions on nonterminals because the table
@ -987,10 +987,9 @@ void Parse(
yymajor = YYNOCODE;
}else{
while( yypParser->yytos >= yypParser->yystack
&& yymx != YYERRORSYMBOL
&& (yyact = yy_find_reduce_action(
yypParser->yytos->stateno,
YYERRORSYMBOL)) >= YY_MIN_REDUCE
YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE
){
yy_pop_parser_stack(yypParser);
}
@ -1067,12 +1066,11 @@ void Parse(
*/
int ParseFallback(int iToken){
#ifdef YYFALLBACK
if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){
return yyFallback[iToken];
}
assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
return yyFallback[iToken];
#else
(void)iToken;
#endif
return 0;
#endif
}
#endif

View File

@ -1,13 +1,14 @@
Make ParseInit and ParseFinalize static to fix -Wmissing-prototypes in
dtd_grammar.c. Hide ParseFinalize to fix -Wunused-function since this feature
dtd_grammar.c. Hide ParseFallback to fix -Wunused-function since this feature
is not used by Wireshark.
Mark yymajor as _U_ since none of the lemon grammar files seem to use it in
their %syntax_error directive, this fixes -Wunused-parameter
SPDX-License-Identifier: CC0-1.0
--- a/lempar.c
+++ b/lempar.c
@@ -319,7 +319,7 @@ static int yyGrowStack(yyParser *p){
@@ -317,7 +317,7 @@ static int yyGrowStack(yyParser *p){
/* Initialize a new parser that has already been allocated.
*/
-void ParseInit(void *yypRawParser ParseCTX_PDECL){
@ -15,7 +16,7 @@ their %syntax_error directive, this fixes -Wunused-parameter
yyParser *yypParser = (yyParser*)yypRawParser;
ParseCTX_STORE
#ifdef YYTRACKMAXSTACKDEPTH
@@ -426,7 +426,7 @@ static void yy_pop_parser_stack(yyParser *pParser){
@@ -424,7 +424,7 @@ static void yy_pop_parser_stack(yyParser *pParser){
/*
** Clear all secondary memory allocations from the parser
*/
@ -33,16 +34,16 @@ their %syntax_error directive, this fixes -Wunused-parameter
ParseTOKENTYPE yyminor /* The minor type of the error token */
){
ParseARG_FETCH
@@ -1060,6 +1060,7 @@ void Parse(
@@ -1059,6 +1059,7 @@ void Parse(
return;
}
+#if 0
/*
** Return the fallback token corresponding to canonical token iToken, or
** 0 if iToken has no fallback.
@@ -1074,3 +1075,4 @@ int ParseFallback(int iToken){
#endif
@@ -1072,3 +1073,4 @@ int ParseFallback(int iToken){
return 0;
#endif
}
+#endif

View File

@ -1,7 +1,8 @@
Avoid dead store warning, the same assignment happens later in this function.
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -3950,7 +3950,7 @@ void print_stack_union(
@@ -4090,7 +4101,7 @@ void print_stack_union(
int *plineno, /* Pointer to the line number */
int mhflag /* True if generating makeheaders output */
){

View File

@ -1,7 +1,8 @@
Assertions to avoid false null-pointer dereferences.
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -690,11 +690,13 @@ int acttab_insert(acttab *p, int makeItSafe){
@@ -695,11 +695,13 @@ int acttab_insert(acttab *p, int makeItSafe){
fprintf(stderr,"malloc failed\n");
exit(1);
}
@ -12,10 +13,10 @@ Assertions to avoid false null-pointer dereferences.
}
}
+ assert(p->aAction); /* Hint for CSA (for p->aAction[i] below) */
/* Scan the existing action table looking for an offset that is a
** duplicate of the current transaction set. Fall out of the loop
@@ -1078,6 +1080,7 @@ void FindLinks(struct lemon *lemp)
@@ -1083,6 +1091,7 @@ void FindLinks(struct lemon *lemp)
** which the link is attached. */
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
@ -23,10 +24,10 @@ Assertions to avoid false null-pointer dereferences.
for(cfp=stp->cfp; cfp; cfp=cfp->next){
cfp->stp = stp;
}
@@ -1684,6 +1687,7 @@ int main(int argc, char **argv)
@@ -1695,6 +1704,7 @@ int main(int argc, char **argv)
/* Parse the input file */
Parse(&lem);
if( lem.errorcnt ) exit(lem.errorcnt);
if( lem.printPreprocessed || lem.errorcnt ) exit(lem.errorcnt);
+ assert(lem.rule); /* Hint for CSA (no errors => rule found). */
if( lem.nrule==0 ){
fprintf(stderr,"Empty grammar.\n");

View File

@ -4,9 +4,10 @@ false positive (use-after-free). Change done with:
sed -e 's#\*\(x[1-4]a\) = array;$#memcpy(\1, \&array, sizeof(array)); /* & */#'
Link: https://bugs.llvm.org/show_bug.cgi?id=39356
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -5076,7 +5076,7 @@ int Strsafe_insert(const char *data)
@@ -5338,7 +5349,7 @@ int Strsafe_insert(const char *data)
array.ht[h] = newnp;
}
free(x1a->tbl);
@ -15,7 +16,7 @@ Link: https://bugs.llvm.org/show_bug.cgi?id=39356
}
/* Insert the new data */
h = ph & (x1a->size-1);
@@ -5244,7 +5244,7 @@ int Symbol_insert(struct symbol *data, const char *key)
@@ -5506,7 +5517,7 @@ int Symbol_insert(struct symbol *data, const char *key)
array.ht[h] = newnp;
}
free(x2a->tbl);
@ -24,7 +25,7 @@ Link: https://bugs.llvm.org/show_bug.cgi?id=39356
}
/* Insert the new data */
h = ph & (x2a->size-1);
@@ -5441,7 +5441,7 @@ int State_insert(struct state *data, struct config *key)
@@ -5703,7 +5714,7 @@ int State_insert(struct state *data, struct config *key)
array.ht[h] = newnp;
}
free(x3a->tbl);
@ -33,7 +34,7 @@ Link: https://bugs.llvm.org/show_bug.cgi?id=39356
}
/* Insert the new data */
h = ph & (x3a->size-1);
@@ -5580,7 +5580,7 @@ int Configtable_insert(struct config *data)
@@ -5842,7 +5853,7 @@ int Configtable_insert(struct config *data)
array.ht[h] = newnp;
}
free(x4a->tbl);

View File

@ -1,7 +1,8 @@
Avoid leaking pathbuf when path==0 by marking allocation failures as fatal.
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -3413,6 +3413,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
@@ -3538,6 +3548,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );

View File

@ -1,17 +0,0 @@
The memory of pathsearch is leaked by tplt_open. Instead of functionally modify
the code to fix the leak, just assert that we will never reach that code path
since Wireshark always sets the template option.
Not suitable for proposing to upstream since the assumption might not hold!
--- a/lemon.c
+++ b/lemon.c
@@ -3505,6 +3505,9 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
char *tpltname;
char *cp;
+ /* We always require the -T option, avoid memleak in the other code path. */
+ assert(user_templatename);
+
/* first, see if user specified a template filename on the command line. */
if (user_templatename != 0) {
if( access(user_templatename,004)==-1 ){

View File

@ -1,17 +0,0 @@
Fix memory leak in ReportTable, the data structure does not escape this
function (directly or indirectly via another function), so freeing it seems the
right thing to do.
acttab_free was added upstream in commit 5c0b1c80aa, 2003-10-21 via
"Convert lemon to use a single perfect hash table for storing the actions.
This should make the resulting parser both smaller and faster. (CVS 1112)"
--- a/lemon.c
+++ b/lemon.c
@@ -4418,6 +4418,7 @@ void ReportTable(
}
}
fprintf(out, "};\n"); lineno++;
+ acttab_free(pActtab);
/* Output the yy_shift_ofst[] table */
n = lemp->nxstate;

View File

@ -1,9 +1,10 @@
CSA thought that stp would leak if State_insert returns early: when x3a is NULL
(memory allocation failure) or when the state existed before (cannot happen for
the initial state). So annotate it as such.
SPDX-License-Identifier: CC0-1.0
--- a/lemon.c
+++ b/lemon.c
@@ -990,7 +990,11 @@ PRIVATE struct state *getstate(struct lemon *lemp)
@@ -993,7 +995,13 @@ PRIVATE struct state *getstate(struct lemon *lemp)
stp->cfp = cfp; /* Remember the configuration closure */
stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
stp->ap = 0; /* No actions, yet. */
@ -11,7 +12,9 @@ the initial state). So annotate it as such.
+ int ret =
+#endif
State_insert(stp,stp->bp); /* Add to the state table */
+#ifndef NDEBUG
+ assert(ret == 1); /* CSA hint: stp did not leak, it has escaped. */
+#endif
buildshifts(lemp,stp); /* Recursively compute successor states */
}
return stp;