]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Lemon collapses common destructors and reduce actions into a single case. (CVS 1837)
authordrh <drh@noemail.net>
Tue, 20 Jul 2004 14:06:51 +0000 (14:06 +0000)
committerdrh <drh@noemail.net>
Tue, 20 Jul 2004 14:06:51 +0000 (14:06 +0000)
FossilOrigin-Name: 3c5aa850eeec5c75c5200a3707852cc5fc9e780b

manifest
manifest.uuid
src/os_unix.c
src/parse.y
tool/lemon.c

index c00f72476080a42778edb87d01764f72e97aba8b..58262a955afc8a9f192b33b284c91363695e4835 100644 (file)
--- 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
index 34c0f72d6747d2ca6237577e7b4f3762382757cb..ec33c976560e3b17ede29f44847ca0ce9ebaefda 100644 (file)
@@ -1 +1 @@
-522ff721ccc33c4b89072fed4e451f0df82e8140
\ No newline at end of file
+3c5aa850eeec5c75c5200a3707852cc5fc9e780b
\ No newline at end of file
index 3bc5a63d31e518550ef0b38e8b643c2dfbe5e30b..bdc0ea39edbddabf3ecb2682cb842daec98f34ec 100644 (file)
@@ -61,7 +61,7 @@
 */
 #include "os_common.h"
 
-#if defined(THREADSAFE) && defined(__linux__)
+#if defined(THREADSAFE) && THREADSAFE && defined(__linux__)
 #define getpid pthread_self
 #endif
 
index 756b0c20d4a54707db8ec552ccd3688e0cac5ea6..260e0f207300ef22cee351c4ac17b44d8b91f087 100644 (file)
@@ -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).  
index f816de2309a7ac5b20a5889ceae3ceb73ca78050..2a784467caac6de8bf7c9646f1fa0993d0e529be 100644 (file)
@@ -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; i<rp->nrhs; 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; i<rp->nrhs; 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; i<rp->nrhs; 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; i<rp->nrhs; 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; i<rp->nrhs; 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; i<rp->nrhs; 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; j<lemp->nsymbol; 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++;
   }