diff --git a/manifest b/manifest index c00f724760..58262a955a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s'%ifdef'\scapability\sto\slemon.\s\sOther\sminor\schanges.\s(CVS\s1836) -D 2004-07-20T12:45:22 +C Lemon\scollapses\scommon\sdestructors\sand\sreduce\sactions\sinto\sa\ssingle\scase.\s(CVS\s1837) +D 2004-07-20T14:06:52 F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -47,13 +47,13 @@ F src/os_mac.c 3d31e26be1411acfb7961033098631b4f3486fdf F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4 F src/os_test.c 6bf10100de2ca199a91fe7ac6474561c8a7166ae F src/os_test.h 6a26a4978492e4bbdbf385554958418ff02db162 -F src/os_unix.c ee607890d9062b51e27de56e9cb14a7f5a598d8c +F src/os_unix.c 02a08065f90ca2737514cdc19d60eb3c4b98fa6b F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13 F src/os_win.c 54181eb73cb4783c4241feca9eaa490768b39008 F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44 F src/pager.c 53a310a7539c7550dc7cbad8e46c62926a40fb31 F src/pager.h 269b6cfc114dba0148203446e41dd19f9647dd53 -F src/parse.y 51c8e696276c409618e66a4ccf316fcff245506e +F src/parse.y 1c22ccb2b60237a7263873892a4d580ea5e53536 F src/pragma.c 8326df8c400f573eb43004dfb8e53e5102acb3e4 F src/printf.c 36090f6d7b4946539de97c1850675ce55ef66c16 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 @@ -185,7 +185,7 @@ F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/view.test ca5c296989d3045f121be9a67588ff88c64874a8 F test/where.test 9c5752b807b78078fab8da6f52e689832579ca20 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b -F tool/lemon.c b771c5147d0e7eb3240f5be754deb5c87d0aae6a +F tool/lemon.c 9ebd2cae1a1b7ab9786e54772413954a4210b2a5 F tool/lempar.c 0b5e7a58634e0d448929b8e85f7981c2aa708d57 F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8 @@ -237,7 +237,7 @@ F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 826b6797a9f08c69b9378cb403d746e91a54dcde -R 81fe5ff7dba086ebc8b9e46590e3934b +P 522ff721ccc33c4b89072fed4e451f0df82e8140 +R e671edd7c958b648f09895c28b19b648 U drh -Z b94ed056d995c2892f36ab8ddb7dedb9 +Z 365b5316c2e2676737e040bedd0d4f8a diff --git a/manifest.uuid b/manifest.uuid index 34c0f72d67..ec33c97656 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -522ff721ccc33c4b89072fed4e451f0df82e8140 \ No newline at end of file +3c5aa850eeec5c75c5200a3707852cc5fc9e780b \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 3bc5a63d31..bdc0ea39ed 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -61,7 +61,7 @@ */ #include "os_common.h" -#if defined(THREADSAFE) && defined(__linux__) +#if defined(THREADSAFE) && THREADSAFE && defined(__linux__) #define getpid pthread_self #endif diff --git a/src/parse.y b/src/parse.y index 756b0c20d4..260e0f2073 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.129 2004/06/30 09:49:24 danielk1977 Exp $ +** @(#) $Id: parse.y,v 1.130 2004/07/20 14:06:52 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -831,11 +831,11 @@ foreach_clause(A) ::= . { A = TK_ROW; } foreach_clause(A) ::= FOR EACH ROW. { A = TK_ROW; } foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; } -%type when_clause {Expr *} +%type when_clause {Expr*} when_clause(A) ::= . { A = 0; } when_clause(A) ::= WHEN expr(X). { A = X; } -%type trigger_cmd_list {TriggerStep *} +%type trigger_cmd_list {TriggerStep*} %destructor trigger_cmd_list {sqlite3DeleteTriggerStep($$);} trigger_cmd_list(A) ::= trigger_cmd(X) SEMI trigger_cmd_list(Y). { X->pNext = Y; @@ -843,7 +843,7 @@ trigger_cmd_list(A) ::= trigger_cmd(X) SEMI trigger_cmd_list(Y). { } trigger_cmd_list(A) ::= . { A = 0; } -%type trigger_cmd {TriggerStep *} +%type trigger_cmd {TriggerStep*} %destructor trigger_cmd {sqlite3DeleteTriggerStep($$);} // UPDATE trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z). diff --git a/tool/lemon.c b/tool/lemon.c index f816de2309..2a784467ca 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -2999,6 +2999,115 @@ struct lemon *lemp; return ret; } +/* +** Append text to a dynamically allocated string. If zText is 0 then +** reset the string to be empty again. Always return the complete text +** of the string (which is overwritten with each call). +*/ +PRIVATE char *append_str(char *zText, int n, int p1, int p2){ + static char *z = 0; + static int alloced = 0; + static int used = 0; + int i, c; + char zInt[40]; + + if( zText==0 ){ + used = 0; + return z; + } + if( n<=0 ) n = strlen(zText); + if( n+sizeof(zInt)*2+used >= alloced ){ + alloced = n + sizeof(zInt)*2 + used + 200; + z = realloc(z, alloced); + } + if( z==0 ) return ""; + while( n-- > 0 ){ + c = *(zText++); + if( c=='%' && zText[0]=='d' ){ + sprintf(zInt, "%d", p1); + p1 = p2; + strcpy(&z[used], zInt); + used += strlen(&z[used]); + zText++; + n--; + }else{ + z[used++] = c; + } + } + z[used] = 0; + return z; +} + +/* +** zCode is a string that is the action associated with a rule. Expand +** the symbols in this string so that the refer to elements of the parser +** stack. Return a new string stored in space obtained from malloc. +*/ +PRIVATE char *translate_code(struct lemon *lemp, struct rule *rp){ + char *cp, *xp; + int i; + char lhsused = 0; /* True if the LHS element has been used */ + char used[MAXRHS]; /* True for each RHS element which is used */ + + for(i=0; inrhs; i++) used[i] = 0; + lhsused = 0; + + append_str(0,0,0,0); + for(cp=rp->code; *cp; cp++){ + if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){ + char saved; + for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++); + saved = *xp; + *xp = 0; + if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ + append_str("yygotominor.yy%d",-1,rp->lhs->dtnum,0); + cp = xp; + lhsused = 1; + }else{ + for(i=0; inrhs; i++){ + if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ + append_str("yymsp[%d].minor.yy%d",-1, + i-rp->nrhs+1,rp->rhs[i]->dtnum); + cp = xp; + used[i] = 1; + break; + } + } + } + *xp = saved; + } + append_str(cp, 1, 0, 0); + } /* End loop */ + + /* Check to make sure the LHS has been used */ + if( rp->lhsalias && !lhsused ){ + ErrorMsg(lemp->filename,rp->ruleline, + "Label \"%s\" for \"%s(%s)\" is never used.", + rp->lhsalias,rp->lhs->name,rp->lhsalias); + lemp->errorcnt++; + } + + /* Generate destructor code for RHS symbols which are not used in the + ** reduce code */ + for(i=0; inrhs; i++){ + if( rp->rhsalias[i] && !used[i] ){ + ErrorMsg(lemp->filename,rp->ruleline, + "Label %s for \"%s(%s)\" is never used.", + rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); + lemp->errorcnt++; + }else if( rp->rhsalias[i]==0 ){ + if( has_destructor(rp->rhs[i],lemp) ){ + append_str(" yy_destructor(%d,&yymsp[%d].minor);\n", -1, + rp->rhs[i]->index,i-rp->nrhs+1); + }else{ + /* No destructor defined for this term */ + } + } + } + cp = append_str(0,0,0,0); + rp->code = Strsafe(cp); +} + /* ** Generate code which executes when the rule "rp" is reduced. Write ** the code to "out". Make sure lineno stays up-to-date. @@ -3009,74 +3118,20 @@ struct rule *rp; struct lemon *lemp; int *lineno; { - char *cp, *xp; + char *cp; int linecnt = 0; - int i; - char lhsused = 0; /* True if the LHS element has been used */ - char used[MAXRHS]; /* True for each RHS element which is used */ - - for(i=0; inrhs; i++) used[i] = 0; - lhsused = 0; /* Generate code to do the reduce action */ if( rp->code ){ fprintf(out,"#line %d \"%s\"\n{",rp->line,lemp->filename); + fprintf(out,"%s",rp->code); for(cp=rp->code; *cp; cp++){ - if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){ - char saved; - for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++); - saved = *xp; - *xp = 0; - if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ - fprintf(out,"yygotominor.yy%d",rp->lhs->dtnum); - cp = xp; - lhsused = 1; - }else{ - for(i=0; inrhs; i++){ - if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ - fprintf(out,"yymsp[%d].minor.yy%d",i-rp->nrhs+1,rp->rhs[i]->dtnum); - cp = xp; - used[i] = 1; - break; - } - } - } - *xp = saved; - } if( *cp=='\n' ) linecnt++; - fputc(*cp,out); } /* End loop */ (*lineno) += 3 + linecnt; fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname); } /* End if( rp->code ) */ - /* Check to make sure the LHS has been used */ - if( rp->lhsalias && !lhsused ){ - ErrorMsg(lemp->filename,rp->ruleline, - "Label \"%s\" for \"%s(%s)\" is never used.", - rp->lhsalias,rp->lhs->name,rp->lhsalias); - lemp->errorcnt++; - } - - /* Generate destructor code for RHS symbols which are not used in the - ** reduce code */ - for(i=0; inrhs; i++){ - if( rp->rhsalias[i] && !used[i] ){ - ErrorMsg(lemp->filename,rp->ruleline, - "Label %s for \"%s(%s)\" is never used.", - rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); - lemp->errorcnt++; - }else if( rp->rhsalias[i]==0 ){ - if( has_destructor(rp->rhs[i],lemp) ){ - fprintf(out," yy_destructor(%d,&yymsp[%d].minor);\n", - rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++; - }else{ - fprintf(out," /* No destructor defined for %s */\n", - rp->rhs[i]->name); - (*lineno)++; - } - } - } return; } @@ -3569,6 +3624,18 @@ int mhflag; /* Output in makeheaders format if true */ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; fprintf(out," case %d:\n",sp->index); lineno++; + + /* Combine duplicate destructors into a single case */ + for(j=i+1; jnsymbol; j++){ + struct symbol *sp2 = lemp->symbols[j]; + if( sp2 && sp2->type!=TERMINAL && sp2->destructor + && sp2->dtnum==sp->dtnum + && strcmp(sp->destructor,sp2->destructor)==0 ){ + fprintf(out," case %d:\n",sp2->index); lineno++; + sp2->destructor = 0; + } + } + emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); fprintf(out," break;\n"); lineno++; } @@ -3604,7 +3671,18 @@ int mhflag; /* Output in makeheaders format if true */ /* Generate code which execution during each REDUCE action */ for(rp=lemp->rule; rp; rp=rp->next){ + if( rp->code ) translate_code(lemp, rp); + } + for(rp=lemp->rule; rp; rp=rp->next){ + struct rule *rp2; + if( rp->code==0 ) continue; fprintf(out," case %d:\n",rp->index); lineno++; + for(rp2=rp->next; rp2; rp2=rp2->next){ + if( rp2->code==rp->code ){ + fprintf(out," case %d:\n",rp2->index); lineno++; + rp2->code = 0; + } + } emit_code(out,rp,lemp,&lineno); fprintf(out," break;\n"); lineno++; }