summaryrefslogtreecommitdiffstats
path: root/tool
diff options
context:
space:
mode:
Diffstat (limited to 'tool')
-rw-r--r--tool/lemon.c262
-rw-r--r--tool/lempar.c132
-rw-r--r--tool/mkopcodeh.tcl9
-rw-r--r--tool/mksqlite3c.tcl27
-rw-r--r--tool/speed-check.sh3
5 files changed, 297 insertions, 136 deletions
diff --git a/tool/lemon.c b/tool/lemon.c
index 7804837..06b9109 100644
--- a/tool/lemon.c
+++ b/tool/lemon.c
@@ -60,6 +60,82 @@ static char *msort(char*,char**,int(*)(const char*,const char*));
#define lemonStrlen(X) ((int)strlen(X))
/*
+** Header on the linked list of memory allocations.
+*/
+typedef struct MemChunk MemChunk;
+struct MemChunk {
+ MemChunk *pNext;
+ size_t sz;
+ /* Actually memory follows */
+};
+
+/*
+** Global linked list of all memory allocations.
+*/
+static MemChunk *memChunkList = 0;
+
+/*
+** Wrappers around malloc(), calloc(), realloc() and free().
+**
+** All memory allocations are kept on a doubly-linked list. The
+** lemon_free_all() function can be called prior to exit to clean
+** up any memory leaks.
+**
+** This is not necessary. But compilers and getting increasingly
+** fussy about memory leaks, even in command-line programs like Lemon
+** where they do not matter. So this code is provided to hush the
+** warnings.
+*/
+static void *lemon_malloc(size_t nByte){
+ MemChunk *p;
+ if( nByte<0 ) return 0;
+ p = malloc( nByte + sizeof(MemChunk) );
+ if( p==0 ){
+ fprintf(stderr, "Out of memory. Failed to allocate %lld bytes.\n",
+ (long long int)nByte);
+ exit(1);
+ }
+ p->pNext = memChunkList;
+ p->sz = nByte;
+ memChunkList = p;
+ return (void*)&p[1];
+}
+static void *lemon_calloc(size_t nElem, size_t sz){
+ void *p = lemon_malloc(nElem*sz);
+ memset(p, 0, nElem*sz);
+ return p;
+}
+static void lemon_free(void *pOld){
+ if( pOld ){
+ MemChunk *p = (MemChunk*)pOld;
+ p--;
+ memset(pOld, 0, p->sz);
+ }
+}
+static void *lemon_realloc(void *pOld, size_t nNew){
+ void *pNew;
+ MemChunk *p;
+ if( pOld==0 ) return lemon_malloc(nNew);
+ p = (MemChunk*)pOld;
+ p--;
+ if( p->sz>=nNew ) return pOld;
+ pNew = lemon_malloc( nNew );
+ memcpy(pNew, pOld, p->sz);
+ return pNew;
+}
+
+/* Free all outstanding memory allocations.
+** Do this right before exiting.
+*/
+static void lemon_free_all(void){
+ while( memChunkList ){
+ MemChunk *pNext = memChunkList->pNext;
+ free( memChunkList );
+ memChunkList = pNext;
+ }
+}
+
+/*
** 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.
**
@@ -418,6 +494,8 @@ struct lemon {
char *filename; /* Name of the input file */
char *outname; /* Name of the current output file */
char *tokenprefix; /* A prefix added to token names in the .h file */
+ char *reallocFunc; /* Function to use to allocate stack space */
+ char *freeFunc; /* Function to use to free stack space */
int nconflict; /* Number of parsing conflicts */
int nactiontab; /* Number of entries in the yy_action[] table */
int nlookaheadtab; /* Number of entries in yy_lookahead[] */
@@ -495,7 +573,7 @@ static struct action *Action_new(void){
if( actionfreelist==0 ){
int i;
int amt = 100;
- actionfreelist = (struct action *)calloc(amt, sizeof(struct action));
+ actionfreelist = (struct action *)lemon_calloc(amt, sizeof(struct action));
if( actionfreelist==0 ){
fprintf(stderr,"Unable to allocate memory for a new parser action.");
exit(1);
@@ -614,14 +692,14 @@ struct acttab {
/* Free all memory associated with the given acttab */
void acttab_free(acttab *p){
- free( p->aAction );
- free( p->aLookahead );
- free( p );
+ lemon_free( p->aAction );
+ lemon_free( p->aLookahead );
+ lemon_free( p );
}
/* Allocate a new acttab structure */
acttab *acttab_alloc(int nsymbol, int nterminal){
- acttab *p = (acttab *) calloc( 1, sizeof(*p) );
+ acttab *p = (acttab *) lemon_calloc( 1, sizeof(*p) );
if( p==0 ){
fprintf(stderr,"Unable to allocate memory for a new acttab.");
exit(1);
@@ -640,7 +718,7 @@ acttab *acttab_alloc(int nsymbol, int nterminal){
void acttab_action(acttab *p, int lookahead, int action){
if( p->nLookahead>=p->nLookaheadAlloc ){
p->nLookaheadAlloc += 25;
- p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead,
+ p->aLookahead = (struct lookahead_action *) lemon_realloc( p->aLookahead,
sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
if( p->aLookahead==0 ){
fprintf(stderr,"malloc failed\n");
@@ -690,7 +768,7 @@ int acttab_insert(acttab *p, int makeItSafe){
if( p->nAction + n >= p->nActionAlloc ){
int oldAlloc = p->nActionAlloc;
p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
- p->aAction = (struct lookahead_action *) realloc( p->aAction,
+ p->aAction = (struct lookahead_action *) lemon_realloc( p->aAction,
sizeof(p->aAction[0])*p->nActionAlloc);
if( p->aAction==0 ){
fprintf(stderr,"malloc failed\n");
@@ -1312,7 +1390,7 @@ static struct config **basisend = 0; /* End of list of basis configs */
/* Return a pointer to a new configuration */
PRIVATE struct config *newconfig(void){
- return (struct config*)calloc(1, sizeof(struct config));
+ return (struct config*)lemon_calloc(1, sizeof(struct config));
}
/* The configuration "old" is no longer used */
@@ -1528,19 +1606,19 @@ static char *bDefineUsed = 0; /* True for every -D macro actually used */
static void handle_D_option(char *z){
char **paz;
nDefine++;
- azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine);
+ azDefine = (char **) lemon_realloc(azDefine, sizeof(azDefine[0])*nDefine);
if( azDefine==0 ){
fprintf(stderr,"out of memory\n");
exit(1);
}
- bDefineUsed = (char*)realloc(bDefineUsed, nDefine);
+ bDefineUsed = (char*)lemon_realloc(bDefineUsed, nDefine);
if( bDefineUsed==0 ){
fprintf(stderr,"out of memory\n");
exit(1);
}
bDefineUsed[nDefine-1] = 0;
paz = &azDefine[nDefine-1];
- *paz = (char *) malloc( lemonStrlen(z)+1 );
+ *paz = (char *) lemon_malloc( lemonStrlen(z)+1 );
if( *paz==0 ){
fprintf(stderr,"out of memory\n");
exit(1);
@@ -1554,7 +1632,7 @@ static void handle_D_option(char *z){
*/
static char *outputDir = NULL;
static void handle_d_option(char *z){
- outputDir = (char *) malloc( lemonStrlen(z)+1 );
+ outputDir = (char *) lemon_malloc( lemonStrlen(z)+1 );
if( outputDir==0 ){
fprintf(stderr,"out of memory\n");
exit(1);
@@ -1564,7 +1642,7 @@ static void handle_d_option(char *z){
static char *user_templatename = NULL;
static void handle_T_option(char *z){
- user_templatename = (char *) malloc( lemonStrlen(z)+1 );
+ user_templatename = (char *) lemon_malloc( lemonStrlen(z)+1 );
if( user_templatename==0 ){
memory_error();
}
@@ -1801,6 +1879,7 @@ int main(int argc, char **argv){
/* return 0 on success, 1 on failure. */
exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
+ lemon_free_all();
exit(exitcode);
return (exitcode);
}
@@ -2389,7 +2468,7 @@ static void parseonetoken(struct pstate *psp)
case IN_RHS:
if( x[0]=='.' ){
struct rule *rp;
- rp = (struct rule *)calloc( sizeof(struct rule) +
+ rp = (struct rule *)lemon_calloc( sizeof(struct rule) +
sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
if( rp==0 ){
ErrorMsg(psp->filename,psp->tokenlineno,
@@ -2441,17 +2520,17 @@ static void parseonetoken(struct pstate *psp)
struct symbol *msp = psp->rhs[psp->nrhs-1];
if( msp->type!=MULTITERMINAL ){
struct symbol *origsp = msp;
- msp = (struct symbol *) calloc(1,sizeof(*msp));
+ msp = (struct symbol *) lemon_calloc(1,sizeof(*msp));
memset(msp, 0, sizeof(*msp));
msp->type = MULTITERMINAL;
msp->nsubsym = 1;
- msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*));
+ msp->subsym = (struct symbol**)lemon_calloc(1,sizeof(struct symbol*));
msp->subsym[0] = origsp;
msp->name = origsp->name;
psp->rhs[psp->nrhs-1] = msp;
}
msp->nsubsym++;
- msp->subsym = (struct symbol **) realloc(msp->subsym,
+ msp->subsym = (struct symbol **) lemon_realloc(msp->subsym,
sizeof(struct symbol*)*msp->nsubsym);
msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){
@@ -2531,6 +2610,12 @@ static void parseonetoken(struct pstate *psp)
}else if( strcmp(x,"default_type")==0 ){
psp->declargslot = &(psp->gp->vartype);
psp->insertLineMacro = 0;
+ }else if( strcmp(x,"realloc")==0 ){
+ psp->declargslot = &(psp->gp->reallocFunc);
+ psp->insertLineMacro = 0;
+ }else if( strcmp(x,"free")==0 ){
+ psp->declargslot = &(psp->gp->freeFunc);
+ psp->insertLineMacro = 0;
}else if( strcmp(x,"stack_size")==0 ){
psp->declargslot = &(psp->gp->stacksize);
psp->insertLineMacro = 0;
@@ -2661,7 +2746,7 @@ static void parseonetoken(struct pstate *psp)
nLine = lemonStrlen(zLine);
n += nLine + lemonStrlen(psp->filename) + nBack;
}
- *psp->declargslot = (char *) realloc(*psp->declargslot, n);
+ *psp->declargslot = (char *) lemon_realloc(*psp->declargslot, n);
zBuf = *psp->declargslot + nOld;
if( addLineMacro ){
if( nOld && zBuf[-1]!='\n' ){
@@ -2775,7 +2860,7 @@ static void parseonetoken(struct pstate *psp)
}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,
+ msp->subsym = (struct symbol **) lemon_realloc(msp->subsym,
sizeof(struct symbol*)*msp->nsubsym);
if( !ISUPPER(x[0]) ) x++;
msp->subsym[msp->nsubsym-1] = Symbol_new(x);
@@ -2990,10 +3075,10 @@ void Parse(struct lemon *gp)
fseek(fp,0,2);
filesize = ftell(fp);
rewind(fp);
- filebuf = (char *)malloc( filesize+1 );
+ filebuf = (char *)lemon_malloc( filesize+1 );
if( filesize>100000000 || filebuf==0 ){
ErrorMsg(ps.filename,0,"Input file too large.");
- free(filebuf);
+ lemon_free(filebuf);
gp->errorcnt++;
fclose(fp);
return;
@@ -3001,7 +3086,7 @@ void Parse(struct lemon *gp)
if( fread(filebuf,1,filesize,fp)!=filesize ){
ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
filesize);
- free(filebuf);
+ lemon_free(filebuf);
gp->errorcnt++;
fclose(fp);
return;
@@ -3113,7 +3198,7 @@ void Parse(struct lemon *gp)
*cp = (char)c; /* Restore the buffer */
cp = nextcp;
}
- free(filebuf); /* Release the buffer after parsing */
+ lemon_free(filebuf); /* Release the buffer after parsing */
gp->rule = ps.firstrule;
gp->errorcnt = ps.errorcnt;
}
@@ -3131,7 +3216,7 @@ struct plink *Plink_new(void){
if( plink_freelist==0 ){
int i;
int amt = 100;
- plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) );
+ plink_freelist = (struct plink *)lemon_calloc( amt, sizeof(struct plink) );
if( plink_freelist==0 ){
fprintf(stderr,
"Unable to allocate memory for a new follow-set propagation link.\n");
@@ -3184,9 +3269,7 @@ void Plink_delete(struct plink *plp)
** Procedures for generating reports and tables in the LEMON parser generator.
*/
-/* Generate a filename with the given suffix. Space to hold the
-** name comes from malloc() and must be freed by the calling
-** function.
+/* Generate a filename with the given suffix.
*/
PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
{
@@ -3203,7 +3286,7 @@ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
sz += lemonStrlen(suffix);
if( outputDir ) sz += lemonStrlen(outputDir) + 1;
sz += 5;
- name = (char*)malloc( sz );
+ name = (char*)lemon_malloc( sz );
if( name==0 ){
fprintf(stderr,"Can't allocate space for a filename.\n");
exit(1);
@@ -3230,7 +3313,7 @@ PRIVATE FILE *file_open(
){
FILE *fp;
- if( lemp->outname ) free(lemp->outname);
+ if( lemp->outname ) lemon_free(lemp->outname);
lemp->outname = file_makename(lemp, suffix);
fp = fopen(lemp->outname,mode);
if( fp==0 && *mode=='w' ){
@@ -3546,14 +3629,14 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
if( cp ){
c = *cp;
*cp = 0;
- path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
+ path = (char *)lemon_malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
*cp = c;
}else{
pathlist = getenv("PATH");
if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
- pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
- path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
+ pathbuf = (char *) lemon_malloc( lemonStrlen(pathlist) + 1 );
+ path = (char *)lemon_malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
if( (pathbuf != 0) && (path!=0) ){
pathbufptr = pathbuf;
lemon_strcpy(pathbuf, pathlist);
@@ -3569,7 +3652,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
if( access(path,modemask)==0 ) break;
}
}
- free(pathbufptr);
+ lemon_free(pathbufptr);
}
return path;
}
@@ -3700,7 +3783,7 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname);
lemp->errorcnt++;
}
- free(toFree);
+ lemon_free(toFree);
return in;
}
@@ -3829,7 +3912,7 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
}
if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
alloced = n + sizeof(zInt)*2 + used + 200;
- z = (char *) realloc(z, alloced);
+ z = (char *) lemon_realloc(z, alloced);
}
if( z==0 ) return empty;
while( n-- > 0 ){
@@ -4119,7 +4202,7 @@ void print_stack_union(
/* Allocate and initialize types[] and allocate stddt[] */
arraysize = lemp->nsymbol * 2;
- types = (char**)calloc( arraysize, sizeof(char*) );
+ types = (char**)lemon_calloc( arraysize, sizeof(char*) );
if( types==0 ){
fprintf(stderr,"Out of memory.\n");
exit(1);
@@ -4136,7 +4219,7 @@ void print_stack_union(
len = lemonStrlen(sp->datatype);
if( len>maxdtlength ) maxdtlength = len;
}
- stddt = (char*)malloc( maxdtlength*2 + 1 );
+ stddt = (char*)lemon_malloc( maxdtlength*2 + 1 );
if( stddt==0 ){
fprintf(stderr,"Out of memory.\n");
exit(1);
@@ -4185,7 +4268,7 @@ void print_stack_union(
}
if( types[hash]==0 ){
sp->dtnum = hash + 1;
- types[hash] = (char*)malloc( lemonStrlen(stddt)+1 );
+ types[hash] = (char*)lemon_malloc( lemonStrlen(stddt)+1 );
if( types[hash]==0 ){
fprintf(stderr,"Out of memory.\n");
exit(1);
@@ -4207,13 +4290,13 @@ void print_stack_union(
for(i=0; i<arraysize; i++){
if( types[i]==0 ) continue;
fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
- free(types[i]);
+ lemon_free(types[i]);
}
if( lemp->errsym && lemp->errsym->useCnt ){
fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
}
- free(stddt);
- free(types);
+ lemon_free(stddt);
+ lemon_free(types);
fprintf(out,"} YYMINORTYPE;\n"); lineno++;
*plineno = lineno;
}
@@ -4309,7 +4392,7 @@ void ReportTable(
struct action *ap;
struct rule *rp;
struct acttab *pActtab;
- int i, j, n, sz;
+ int i, j, n, sz, mn, mx;
int nLookAhead;
int szActionType; /* sizeof(YYACTIONTYPE) */
int szCodeType; /* sizeof(YYCODETYPE) */
@@ -4442,7 +4525,7 @@ void ReportTable(
if( mhflag ){
char *incName = file_makename(lemp, ".h");
fprintf(out,"#include \"%s\"\n", incName); lineno++;
- free(incName);
+ lemon_free(incName);
}
tplt_xfer(lemp->name,in,out,&lineno);
@@ -4501,6 +4584,21 @@ void ReportTable(
fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
fprintf(out,"#define %sARG_STORE\n",name); lineno++;
}
+ if( lemp->reallocFunc ){
+ fprintf(out,"#define YYREALLOC %s\n", lemp->reallocFunc); lineno++;
+ }else{
+ fprintf(out,"#define YYREALLOC realloc\n"); lineno++;
+ }
+ if( lemp->freeFunc ){
+ fprintf(out,"#define YYFREE %s\n", lemp->freeFunc); lineno++;
+ }else{
+ fprintf(out,"#define YYFREE free\n"); lineno++;
+ }
+ if( lemp->reallocFunc && lemp->freeFunc ){
+ fprintf(out,"#define YYDYNSTACK 1\n"); lineno++;
+ }else{
+ fprintf(out,"#define YYDYNSTACK 0\n"); lineno++;
+ }
if( lemp->ctx && lemp->ctx[0] ){
i = lemonStrlen(lemp->ctx);
while( i>=1 && ISSPACE(lemp->ctx[i-1]) ) i--;
@@ -4534,7 +4632,7 @@ void ReportTable(
** table must be computed before generating the YYNSTATE macro because
** we need to know how many states can be eliminated.
*/
- ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
+ ax = (struct axset *) lemon_calloc(lemp->nxstate*2, sizeof(ax[0]));
if( ax==0 ){
fprintf(stderr,"malloc failed\n");
exit(1);
@@ -4592,7 +4690,7 @@ void ReportTable(
}
#endif
}
- free(ax);
+ lemon_free(ax);
/* Mark rules that are actually used for reduce actions after all
** optimizations have been applied
@@ -4624,6 +4722,22 @@ void ReportTable(
fprintf(out,"#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++;
i = lemp->minReduce + lemp->nrule;
fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
+
+ /* Minimum and maximum token values that have a destructor */
+ mn = mx = 0;
+ for(i=0; i<lemp->nsymbol; i++){
+ struct symbol *sp = lemp->symbols[i];
+
+ if( sp && sp->type!=TERMINAL && sp->destructor ){
+ if( mn==0 || sp->index<mn ) mn = sp->index;
+ if( sp->index>mx ) mx = sp->index;
+ }
+ }
+ if( lemp->tokendest ) mn = 0;
+ if( lemp->vardest ) mx = lemp->nsymbol-1;
+ fprintf(out,"#define YY_MIN_DSTRCTR %d\n", mn); lineno++;
+ fprintf(out,"#define YY_MAX_DSTRCTR %d\n", mx); lineno++;
+
tplt_xfer(lemp->name,in,out,&lineno);
/* Now output the action table and its associates:
@@ -4767,7 +4881,7 @@ void ReportTable(
/* Generate the table of fallback tokens.
*/
if( lemp->has_fallback ){
- int mx = lemp->nterminal - 1;
+ mx = lemp->nterminal - 1;
/* 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--; } */
@@ -5202,7 +5316,7 @@ void SetSize(int n)
/* Allocate a new set */
char *SetNew(void){
char *s;
- s = (char*)calloc( size, 1);
+ s = (char*)lemon_calloc( size, 1);
if( s==0 ){
memory_error();
}
@@ -5212,7 +5326,7 @@ char *SetNew(void){
/* Deallocate a set */
void SetFree(char *s)
{
- free(s);
+ lemon_free(s);
}
/* Add a new element to the set. Return TRUE if the element was added
@@ -5271,7 +5385,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 ){
+ if( z==0 && (cpy=(char *)lemon_malloc( lemonStrlen(y)+1 ))!=0 ){
lemon_strcpy(cpy,y);
z = cpy;
Strsafe_insert(z);
@@ -5307,13 +5421,13 @@ static struct s_x1 *x1a;
/* Allocate a new associative array */
void Strsafe_init(void){
if( x1a ) return;
- x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
+ x1a = (struct s_x1*)lemon_malloc( sizeof(struct s_x1) );
if( x1a ){
x1a->size = 1024;
x1a->count = 0;
- x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*));
+ x1a->tbl = (x1node*)lemon_calloc(1024, sizeof(x1node) + sizeof(x1node*));
if( x1a->tbl==0 ){
- free(x1a);
+ lemon_free(x1a);
x1a = 0;
}else{
int i;
@@ -5348,7 +5462,7 @@ int Strsafe_insert(const char *data)
struct s_x1 array;
array.size = arrSize = x1a->size*2;
array.count = x1a->count;
- array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*));
+ array.tbl = (x1node*)lemon_calloc(arrSize, sizeof(x1node)+sizeof(x1node*));
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
array.ht = (x1node**)&(array.tbl[arrSize]);
for(i=0; i<arrSize; i++) array.ht[i] = 0;
@@ -5363,7 +5477,7 @@ int Strsafe_insert(const char *data)
newnp->from = &(array.ht[h]);
array.ht[h] = newnp;
}
- /* free(x1a->tbl); // This program was originally for 16-bit machines.
+ /* lemon_free(x1a->tbl); // This program was originally for 16-bit machines.
** Don't worry about freeing memory on modern platforms. */
*x1a = array;
}
@@ -5404,7 +5518,7 @@ struct symbol *Symbol_new(const char *x)
sp = Symbol_find(x);
if( sp==0 ){
- sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
+ sp = (struct symbol *)lemon_calloc(1, sizeof(struct symbol) );
MemoryCheck(sp);
sp->name = Strsafe(x);
sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL;
@@ -5475,13 +5589,13 @@ static struct s_x2 *x2a;
/* Allocate a new associative array */
void Symbol_init(void){
if( x2a ) return;
- x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
+ x2a = (struct s_x2*)lemon_malloc( sizeof(struct s_x2) );
if( x2a ){
x2a->size = 128;
x2a->count = 0;
- x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*));
+ x2a->tbl = (x2node*)lemon_calloc(128, sizeof(x2node) + sizeof(x2node*));
if( x2a->tbl==0 ){
- free(x2a);
+ lemon_free(x2a);
x2a = 0;
}else{
int i;
@@ -5516,7 +5630,7 @@ int Symbol_insert(struct symbol *data, const char *key)
struct s_x2 array;
array.size = arrSize = x2a->size*2;
array.count = x2a->count;
- array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*));
+ array.tbl = (x2node*)lemon_calloc(arrSize, sizeof(x2node)+sizeof(x2node*));
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
array.ht = (x2node**)&(array.tbl[arrSize]);
for(i=0; i<arrSize; i++) array.ht[i] = 0;
@@ -5532,7 +5646,7 @@ int Symbol_insert(struct symbol *data, const char *key)
newnp->from = &(array.ht[h]);
array.ht[h] = newnp;
}
- /* free(x2a->tbl); // This program was originally written for 16-bit
+ /* lemon_free(x2a->tbl); // This program was originally written for 16-bit
** machines. Don't worry about freeing this trivial amount of memory
** on modern platforms. Just leak it. */
*x2a = array;
@@ -5593,7 +5707,7 @@ struct symbol **Symbol_arrayof()
int i,arrSize;
if( x2a==0 ) return 0;
arrSize = x2a->count;
- array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *));
+ array = (struct symbol **)lemon_calloc(arrSize, sizeof(struct symbol *));
if( array ){
for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data;
}
@@ -5641,7 +5755,7 @@ PRIVATE unsigned statehash(struct config *a)
struct state *State_new()
{
struct state *newstate;
- newstate = (struct state *)calloc(1, sizeof(struct state) );
+ newstate = (struct state *)lemon_calloc(1, sizeof(struct state) );
MemoryCheck(newstate);
return newstate;
}
@@ -5674,13 +5788,13 @@ static struct s_x3 *x3a;
/* Allocate a new associative array */
void State_init(void){
if( x3a ) return;
- x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
+ x3a = (struct s_x3*)lemon_malloc( sizeof(struct s_x3) );
if( x3a ){
x3a->size = 128;
x3a->count = 0;
- x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*));
+ x3a->tbl = (x3node*)lemon_calloc(128, sizeof(x3node) + sizeof(x3node*));
if( x3a->tbl==0 ){
- free(x3a);
+ lemon_free(x3a);
x3a = 0;
}else{
int i;
@@ -5715,7 +5829,7 @@ int State_insert(struct state *data, struct config *key)
struct s_x3 array;
array.size = arrSize = x3a->size*2;
array.count = x3a->count;
- array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*));
+ array.tbl = (x3node*)lemon_calloc(arrSize, sizeof(x3node)+sizeof(x3node*));
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
array.ht = (x3node**)&(array.tbl[arrSize]);
for(i=0; i<arrSize; i++) array.ht[i] = 0;
@@ -5731,7 +5845,7 @@ int State_insert(struct state *data, struct config *key)
newnp->from = &(array.ht[h]);
array.ht[h] = newnp;
}
- free(x3a->tbl);
+ lemon_free(x3a->tbl);
*x3a = array;
}
/* Insert the new data */
@@ -5772,7 +5886,7 @@ struct state **State_arrayof(void)
int i,arrSize;
if( x3a==0 ) return 0;
arrSize = x3a->count;
- array = (struct state **)calloc(arrSize, sizeof(struct state *));
+ array = (struct state **)lemon_calloc(arrSize, sizeof(struct state *));
if( array ){
for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data;
}
@@ -5814,13 +5928,13 @@ static struct s_x4 *x4a;
/* Allocate a new associative array */
void Configtable_init(void){
if( x4a ) return;
- x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
+ x4a = (struct s_x4*)lemon_malloc( sizeof(struct s_x4) );
if( x4a ){
x4a->size = 64;
x4a->count = 0;
- x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*));
+ x4a->tbl = (x4node*)lemon_calloc(64, sizeof(x4node) + sizeof(x4node*));
if( x4a->tbl==0 ){
- free(x4a);
+ lemon_free(x4a);
x4a = 0;
}else{
int i;
@@ -5855,7 +5969,8 @@ int Configtable_insert(struct config *data)
struct s_x4 array;
array.size = arrSize = x4a->size*2;
array.count = x4a->count;
- array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*));
+ array.tbl = (x4node*)lemon_calloc(arrSize,
+ sizeof(x4node) + sizeof(x4node*));
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
array.ht = (x4node**)&(array.tbl[arrSize]);
for(i=0; i<arrSize; i++) array.ht[i] = 0;
@@ -5870,9 +5985,6 @@ int Configtable_insert(struct config *data)
newnp->from = &(array.ht[h]);
array.ht[h] = newnp;
}
- /* free(x4a->tbl); // This code was originall written for 16-bit machines.
- ** on modern machines, don't worry about freeing this trival amount of
- ** memory. */
*x4a = array;
}
/* Insert the new data */
diff --git a/tool/lempar.c b/tool/lempar.c
index 8cc5789..851a0e2 100644
--- a/tool/lempar.c
+++ b/tool/lempar.c
@@ -67,6 +67,9 @@
** ParseARG_STORE Code to store %extra_argument into yypParser
** ParseARG_FETCH Code to extract %extra_argument from yypParser
** ParseCTX_* As ParseARG_ except for %extra_context
+** YYREALLOC Name of the realloc() function to use
+** YYFREE Name of the free() function to use
+** YYDYNSTACK True if stack space should be extended on heap
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
** YYNSTATE the combined number of states.
@@ -80,6 +83,8 @@
** YY_NO_ACTION The yy_action[] code for no-op
** YY_MIN_REDUCE Minimum value for reduce actions
** YY_MAX_REDUCE Maximum value for reduce actions
+** YY_MIN_DSTRCTR Minimum symbol value that has a destructor
+** YY_MAX_DSTRCTR Maximum symbol value that has a destructor
*/
#ifndef INTERFACE
# define INTERFACE 1
@@ -101,6 +106,22 @@
# define yytestcase(X)
#endif
+/* Macro to determine if stack space has the ability to grow using
+** heap memory.
+*/
+#if YYSTACKDEPTH<=0 || YYDYNSTACK
+# define YYGROWABLESTACK 1
+#else
+# define YYGROWABLESTACK 0
+#endif
+
+/* Guarantee a minimum number of initial stack slots.
+*/
+#if YYSTACKDEPTH<=0
+# undef YYSTACKDEPTH
+# define YYSTACKDEPTH 2 /* Need a minimum stack size */
+#endif
+
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
@@ -212,14 +233,9 @@ struct yyParser {
#endif
ParseARG_SDECL /* A place to hold %extra_argument */
ParseCTX_SDECL /* A place to hold %extra_context */
-#if YYSTACKDEPTH<=0
- int yystksz; /* Current side of the stack */
- yyStackEntry *yystack; /* The parser's stack */
- yyStackEntry yystk0; /* First stack entry */
-#else
- yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
- yyStackEntry *yystackEnd; /* Last entry in the stack */
-#endif
+ yyStackEntry *yystackEnd; /* Last entry in the stack */
+ yyStackEntry *yystack; /* The parser stack */
+ yyStackEntry yystk0[YYSTACKDEPTH]; /* Initial stack space */
};
typedef struct yyParser yyParser;
@@ -273,37 +289,45 @@ static const char *const yyRuleName[] = {
#endif /* NDEBUG */
-#if YYSTACKDEPTH<=0
+#if YYGROWABLESTACK
/*
** Try to increase the size of the parser stack. Return the number
** of errors. Return 0 on success.
*/
static int yyGrowStack(yyParser *p){
+ int oldSize = 1 + (int)(p->yystackEnd - p->yystack);
int newSize;
int idx;
yyStackEntry *pNew;
- newSize = p->yystksz*2 + 100;
- idx = p->yytos ? (int)(p->yytos - p->yystack) : 0;
- if( p->yystack==&p->yystk0 ){
- pNew = malloc(newSize*sizeof(pNew[0]));
- if( pNew ) pNew[0] = p->yystk0;
+ newSize = oldSize*2 + 100;
+ idx = (int)(p->yytos - p->yystack);
+ if( p->yystack==p->yystk0 ){
+ pNew = YYREALLOC(0, newSize*sizeof(pNew[0]));
+ if( pNew==0 ) return 1;
+ memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0]));
}else{
- pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
+ pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]));
+ if( pNew==0 ) return 1;
}
- if( pNew ){
- p->yystack = pNew;
- p->yytos = &p->yystack[idx];
+ p->yystack = pNew;
+ p->yytos = &p->yystack[idx];
#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
- yyTracePrompt, p->yystksz, newSize);
- }
-#endif
- p->yystksz = newSize;
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
+ yyTracePrompt, oldSize, newSize);
}
- return pNew==0;
+#endif
+ p->yystackEnd = &p->yystack[newSize-1];
+ return 0;
}
+#endif /* YYGROWABLESTACK */
+
+#if !YYGROWABLESTACK
+/* For builds that do no have a growable stack, yyGrowStack always
+** returns an error.
+*/
+# define yyGrowStack(X) 1
#endif
/* Datatype of the argument to the memory allocated passed as the
@@ -323,24 +347,14 @@ void ParseInit(void *yypRawParser ParseCTX_PDECL){
#ifdef YYTRACKMAXSTACKDEPTH
yypParser->yyhwm = 0;
#endif
-#if YYSTACKDEPTH<=0
- yypParser->yytos = NULL;
- yypParser->yystack = NULL;
- yypParser->yystksz = 0;
- if( yyGrowStack(yypParser) ){
- yypParser->yystack = &yypParser->yystk0;
- yypParser->yystksz = 1;
- }
-#endif
+ yypParser->yystack = yypParser->yystk0;
+ yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
yypParser->yytos = yypParser->yystack;
yypParser->yystack[0].stateno = 0;
yypParser->yystack[0].major = 0;
-#if YYSTACKDEPTH>0
- yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
-#endif
}
#ifndef Parse_ENGINEALWAYSONSTACK
@@ -426,9 +440,26 @@ static void yy_pop_parser_stack(yyParser *pParser){
*/
void ParseFinalize(void *p){
yyParser *pParser = (yyParser*)p;
- while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
-#if YYSTACKDEPTH<=0
- if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
+
+ /* In-lined version of calling yy_pop_parser_stack() for each
+ ** element left in the stack */
+ yyStackEntry *yytos = pParser->yytos;
+ while( yytos>pParser->yystack ){
+#ifndef NDEBUG
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE,"%sPopping %s\n",
+ yyTracePrompt,
+ yyTokenName[yytos->major]);
+ }
+#endif
+ if( yytos->major>=YY_MIN_DSTRCTR ){
+ yy_destructor(pParser, yytos->major, &yytos->minor);
+ }
+ yytos--;
+ }
+
+#if YYGROWABLESTACK
+ if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack);
#endif
}
@@ -654,25 +685,19 @@ static void yy_shift(
assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
}
#endif
-#if YYSTACKDEPTH>0
- if( yypParser->yytos>yypParser->yystackEnd ){
- yypParser->yytos--;
- yyStackOverflow(yypParser);
- return;
- }
-#else
- if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
+ yytos = yypParser->yytos;
+ if( yytos>yypParser->yystackEnd ){
if( yyGrowStack(yypParser) ){
yypParser->yytos--;
yyStackOverflow(yypParser);
return;
}
+ yytos = yypParser->yytos;
+ assert( yytos <= yypParser->yystackEnd );
}
-#endif
if( yyNewState > YY_MAX_SHIFT ){
yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
}
- yytos = yypParser->yytos;
yytos->stateno = yyNewState;
yytos->major = yyMajor;
yytos->minor.yy0 = yyMinor;
@@ -911,19 +936,12 @@ void Parse(
(int)(yypParser->yytos - yypParser->yystack));
}
#endif
-#if YYSTACKDEPTH>0
if( yypParser->yytos>=yypParser->yystackEnd ){
- yyStackOverflow(yypParser);
- break;
- }
-#else
- if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
if( yyGrowStack(yypParser) ){
yyStackOverflow(yypParser);
break;
}
}
-#endif
}
yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor ParseCTX_PARAM);
}else if( yyact <= YY_MAX_SHIFTREDUCE ){
diff --git a/tool/mkopcodeh.tcl b/tool/mkopcodeh.tcl
index 6fb3b75..18fe1a2 100644
--- a/tool/mkopcodeh.tcl
+++ b/tool/mkopcodeh.tcl
@@ -81,6 +81,7 @@ while {![eof $in]} {
set op($name) -1
set group($name) 0
set jump($name) 0
+ set jump0($name) 0
set in1($name) 0
set in2($name) 0
set in3($name) 0
@@ -109,6 +110,7 @@ while {![eof $in]} {
out2 {set out2($name) 1}
out3 {set out3($name) 1}
ncycle {set ncycle($name) 1}
+ jump0 {set jump($name) 1; set jump0($name) 1;}
}
}
if {$group($name)} {
@@ -137,6 +139,7 @@ puts "/* Automatically generated. Do not edit */"
puts "/* See the tool/mkopcodeh.tcl script for details */"
foreach name {OP_Noop OP_Explain OP_Abortable} {
set jump($name) 0
+ set jump0($name) 0
set in1($name) 0
set in2($name) 0
set in3($name) 0
@@ -256,7 +259,9 @@ for {set i 0} {$i<=$max} {incr i} {
set name $def($i)
puts -nonewline [format {#define %-16s %3d} $name $i]
set com {}
- if {[info exists jump($name)] && $jump($name)} {
+ if {[info exists jump0($name)] && $jump0($name)} {
+ lappend com "jump0"
+ } elseif {[info exists jump($name)] && $jump($name)} {
lappend com "jump"
}
if {[info exists sameas($i)]} {
@@ -289,6 +294,7 @@ for {set i 0} {$i<=$max} {incr i} {
if {$out2($name)} {incr x 16}
if {$out3($name)} {incr x 32}
if {$ncycle($name)} {incr x 64}
+ if {$jump0($name)} {incr x 128}
}
set bv($i) $x
}
@@ -304,6 +310,7 @@ puts "#define OPFLG_IN3 0x08 /* in3: P3 is an input */"
puts "#define OPFLG_OUT2 0x10 /* out2: P2 is an output */"
puts "#define OPFLG_OUT3 0x20 /* out3: P3 is an output */"
puts "#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */"
+puts "#define OPFLG_JUMP0 0x80 /* jump0: P2 might be zero */"
puts "#define OPFLG_INITIALIZER \173\\"
for {set i 0} {$i<=$max} {incr i} {
if {$i%8==0} {
diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl
index 53fa59a..ef8353d 100644
--- a/tool/mksqlite3c.tcl
+++ b/tool/mksqlite3c.tcl
@@ -17,7 +17,7 @@
# After the "tsrc" directory has been created and populated, run
# this script:
#
-# tclsh mksqlite3c.tcl
+# tclsh mksqlite3c.tcl [flags] [extra source files]
#
# The amalgamated SQLite code will be written into sqlite3.c
#
@@ -42,6 +42,7 @@ set linemacros 0
set useapicall 0
set enable_recover 0
set srcdir tsrc
+set extrasrc [list]
for {set i 0} {$i<[llength $argv]} {incr i} {
set x [lindex $argv $i]
@@ -63,8 +64,10 @@ for {set i 0} {$i<[llength $argv]} {incr i} {
} elseif {[regexp {^-?-((help)|\?)$} $x]} {
puts $help
exit 0
- } else {
+ } elseif {[regexp {^-?-} $x]} {
error "unknown command-line option: $x"
+ } else {
+ lappend extrasrc $x
}
}
set in [open $srcdir/sqlite3.h]
@@ -349,6 +352,21 @@ proc copy_file {filename} {
section_comment "End of $tail"
}
+# Read the source file named $filename and write it into the
+# sqlite3.c output file. The only transformation is the trimming
+# of EOL whitespace.
+#
+proc copy_file_verbatim {filename} {
+ global out
+ set in [open $filename r]
+ set tail [file tail $filename]
+ section_comment "Begin EXTRA_SRC file $tail"
+ while {![eof $in]} {
+ set line [string trimright [gets $in]]
+ puts $out $line
+ }
+ section_comment "End of EXTRA_SRC $tail"
+}
# Process the source files. Process files containing commonly
# used subroutines first in order to help the compiler find
@@ -470,13 +488,16 @@ set flist {
sqlite3session.c
fts5.c
stmt.c
-}
+}
if {$enable_recover} {
lappend flist sqlite3recover.c dbdata.c
}
foreach file $flist {
copy_file $srcdir/$file
}
+foreach file $extrasrc {
+ copy_file_verbatim $file
+}
puts $out \
"/* Return the source-id for this library */
diff --git a/tool/speed-check.sh b/tool/speed-check.sh
index 4cc2579..5d425c3 100644
--- a/tool/speed-check.sh
+++ b/tool/speed-check.sh
@@ -161,6 +161,9 @@ while test "$1" != ""; do
--fp)
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset fp"
;;
+ --parsenumber)
+ SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset parsenumber"
+ ;;
--stmtscanstatus)
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtscanstatus"
;;