/ Check-in [3c5aa850]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Lemon collapses common destructors and reduce actions into a single case. (CVS 1837)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3c5aa850eeec5c75c5200a3707852cc5fc9e780b
User & Date: drh 2004-07-20 14:06:52
Context
2004-07-20
18:23
Simplify the where.c logic by flipping expression over so that the controlling variable is always on the left. (CVS 1838) check-in: ec8bfa38 user: drh tags: trunk
14:06
Lemon collapses common destructors and reduce actions into a single case. (CVS 1837) check-in: 3c5aa850 user: drh tags: trunk
12:45
Add the '%ifdef' capability to lemon. Other minor changes. (CVS 1836) check-in: 522ff721 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

    57     57   
    58     58   
    59     59   /*
    60     60   ** Include code that is common to all os_*.c files
    61     61   */
    62     62   #include "os_common.h"
    63     63   
    64         -#if defined(THREADSAFE) && defined(__linux__)
           64  +#if defined(THREADSAFE) && THREADSAFE && defined(__linux__)
    65     65   #define getpid pthread_self
    66     66   #endif
    67     67   
    68     68   /*
    69     69   ** Here is the dirt on POSIX advisory locks:  ANSI STD 1003.1 (1996)
    70     70   ** section 6.5.2.2 lines 483 through 490 specify that when a process
    71     71   ** sets or clears a lock, that operation overrides any prior locks set

Changes to src/parse.y.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains SQLite's grammar for SQL.  Process this file
    13     13   ** using the lemon parser generator to generate C code that runs
    14     14   ** the parser.  Lemon will also generate a header file containing
    15     15   ** numeric codes for all of the tokens.
    16     16   **
    17         -** @(#) $Id: parse.y,v 1.129 2004/06/30 09:49:24 danielk1977 Exp $
           17  +** @(#) $Id: parse.y,v 1.130 2004/07/20 14:06:52 drh Exp $
    18     18   */
    19     19   %token_prefix TK_
    20     20   %token_type {Token}
    21     21   %default_type {Token}
    22     22   %extra_argument {Parse *pParse}
    23     23   %syntax_error {
    24     24     if( pParse->zErrMsg==0 ){
................................................................................
   827    827   trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X; }
   828    828   
   829    829   %type foreach_clause {int}
   830    830   foreach_clause(A) ::= .                   { A = TK_ROW; }
   831    831   foreach_clause(A) ::= FOR EACH ROW.       { A = TK_ROW; }
   832    832   foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; }
   833    833   
   834         -%type when_clause {Expr *}
          834  +%type when_clause {Expr*}
   835    835   when_clause(A) ::= .             { A = 0; }
   836    836   when_clause(A) ::= WHEN expr(X). { A = X; }
   837    837   
   838         -%type trigger_cmd_list {TriggerStep *}
          838  +%type trigger_cmd_list {TriggerStep*}
   839    839   %destructor trigger_cmd_list {sqlite3DeleteTriggerStep($$);}
   840    840   trigger_cmd_list(A) ::= trigger_cmd(X) SEMI trigger_cmd_list(Y). {
   841    841     X->pNext = Y;
   842    842     A = X;
   843    843   }
   844    844   trigger_cmd_list(A) ::= . { A = 0; }
   845    845   
   846         -%type trigger_cmd {TriggerStep *}
          846  +%type trigger_cmd {TriggerStep*}
   847    847   %destructor trigger_cmd {sqlite3DeleteTriggerStep($$);}
   848    848   // UPDATE 
   849    849   trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z).  
   850    850                  { A = sqlite3TriggerUpdateStep(&X, Y, Z, R); }
   851    851   
   852    852   // INSERT
   853    853   trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) 

Changes to tool/lemon.c.

  2994   2994     if( sp->type==TERMINAL ){
  2995   2995       ret = lemp->tokendest!=0;
  2996   2996     }else{
  2997   2997       ret = lemp->vardest!=0 || sp->destructor!=0;
  2998   2998     }
  2999   2999     return ret;
  3000   3000   }
         3001  +
         3002  +/*
         3003  +** Append text to a dynamically allocated string.  If zText is 0 then
         3004  +** reset the string to be empty again.  Always return the complete text
         3005  +** of the string (which is overwritten with each call).
         3006  +*/
         3007  +PRIVATE char *append_str(char *zText, int n, int p1, int p2){
         3008  +  static char *z = 0;
         3009  +  static int alloced = 0;
         3010  +  static int used = 0;
         3011  +  int i, c;
         3012  +  char zInt[40];
         3013  +
         3014  +  if( zText==0 ){
         3015  +    used = 0;
         3016  +    return z;
         3017  +  }
         3018  +  if( n<=0 ) n = strlen(zText);
         3019  +  if( n+sizeof(zInt)*2+used >= alloced ){
         3020  +    alloced = n + sizeof(zInt)*2 + used + 200;
         3021  +    z = realloc(z,  alloced);
         3022  +  }
         3023  +  if( z==0 ) return "";
         3024  +  while( n-- > 0 ){
         3025  +    c = *(zText++);
         3026  +    if( c=='%' && zText[0]=='d' ){
         3027  +      sprintf(zInt, "%d", p1);
         3028  +      p1 = p2;
         3029  +      strcpy(&z[used], zInt);
         3030  +      used += strlen(&z[used]);
         3031  +      zText++;
         3032  +      n--;
         3033  +    }else{
         3034  +      z[used++] = c;
         3035  +    }
         3036  +  }
         3037  +  z[used] = 0;
         3038  +  return z;
         3039  +}
         3040  +
         3041  +/*
         3042  +** zCode is a string that is the action associated with a rule.  Expand
         3043  +** the symbols in this string so that the refer to elements of the parser
         3044  +** stack.  Return a new string stored in space obtained from malloc.
         3045  +*/
         3046  +PRIVATE char *translate_code(struct lemon *lemp, struct rule *rp){
         3047  +  char *cp, *xp;
         3048  +  int i;
         3049  +  char lhsused = 0;    /* True if the LHS element has been used */
         3050  +  char used[MAXRHS];   /* True for each RHS element which is used */
         3051  +
         3052  +  for(i=0; i<rp->nrhs; i++) used[i] = 0;
         3053  +  lhsused = 0;
         3054  +
         3055  +  append_str(0,0,0,0);
         3056  +  for(cp=rp->code; *cp; cp++){
         3057  +    if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
         3058  +      char saved;
         3059  +      for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
         3060  +      saved = *xp;
         3061  +      *xp = 0;
         3062  +      if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
         3063  +        append_str("yygotominor.yy%d",-1,rp->lhs->dtnum,0);
         3064  +        cp = xp;
         3065  +        lhsused = 1;
         3066  +      }else{
         3067  +        for(i=0; i<rp->nrhs; i++){
         3068  +          if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
         3069  +            append_str("yymsp[%d].minor.yy%d",-1,
         3070  +                       i-rp->nrhs+1,rp->rhs[i]->dtnum);
         3071  +            cp = xp;
         3072  +            used[i] = 1;
         3073  +            break;
         3074  +          }
         3075  +        }
         3076  +      }
         3077  +      *xp = saved;
         3078  +    }
         3079  +    append_str(cp, 1, 0, 0);
         3080  +  } /* End loop */
         3081  +
         3082  +  /* Check to make sure the LHS has been used */
         3083  +  if( rp->lhsalias && !lhsused ){
         3084  +    ErrorMsg(lemp->filename,rp->ruleline,
         3085  +      "Label \"%s\" for \"%s(%s)\" is never used.",
         3086  +        rp->lhsalias,rp->lhs->name,rp->lhsalias);
         3087  +    lemp->errorcnt++;
         3088  +  }
         3089  +
         3090  +  /* Generate destructor code for RHS symbols which are not used in the
         3091  +  ** reduce code */
         3092  +  for(i=0; i<rp->nrhs; i++){
         3093  +    if( rp->rhsalias[i] && !used[i] ){
         3094  +      ErrorMsg(lemp->filename,rp->ruleline,
         3095  +        "Label %s for \"%s(%s)\" is never used.",
         3096  +        rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
         3097  +      lemp->errorcnt++;
         3098  +    }else if( rp->rhsalias[i]==0 ){
         3099  +      if( has_destructor(rp->rhs[i],lemp) ){
         3100  +        append_str("  yy_destructor(%d,&yymsp[%d].minor);\n", -1,
         3101  +           rp->rhs[i]->index,i-rp->nrhs+1);
         3102  +      }else{
         3103  +        /* No destructor defined for this term */
         3104  +      }
         3105  +    }
         3106  +  }
         3107  +  cp = append_str(0,0,0,0);
         3108  +  rp->code = Strsafe(cp);
         3109  +}
  3001   3110   
  3002   3111   /* 
  3003   3112   ** Generate code which executes when the rule "rp" is reduced.  Write
  3004   3113   ** the code to "out".  Make sure lineno stays up-to-date.
  3005   3114   */
  3006   3115   PRIVATE void emit_code(out,rp,lemp,lineno)
  3007   3116   FILE *out;
  3008   3117   struct rule *rp;
  3009   3118   struct lemon *lemp;
  3010   3119   int *lineno;
  3011   3120   {
  3012         - char *cp, *xp;
         3121  + char *cp;
  3013   3122    int linecnt = 0;
  3014         - int i;
  3015         - char lhsused = 0;    /* True if the LHS element has been used */
  3016         - char used[MAXRHS];   /* True for each RHS element which is used */
  3017         -
  3018         - for(i=0; i<rp->nrhs; i++) used[i] = 0;
  3019         - lhsused = 0;
  3020   3123   
  3021   3124    /* Generate code to do the reduce action */
  3022   3125    if( rp->code ){
  3023   3126      fprintf(out,"#line %d \"%s\"\n{",rp->line,lemp->filename);
         3127  +   fprintf(out,"%s",rp->code);
  3024   3128      for(cp=rp->code; *cp; cp++){
  3025         -     if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
  3026         -       char saved;
  3027         -       for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
  3028         -       saved = *xp;
  3029         -       *xp = 0;
  3030         -       if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
  3031         -         fprintf(out,"yygotominor.yy%d",rp->lhs->dtnum);
  3032         -         cp = xp;
  3033         -         lhsused = 1;
  3034         -       }else{
  3035         -         for(i=0; i<rp->nrhs; i++){
  3036         -           if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
  3037         -             fprintf(out,"yymsp[%d].minor.yy%d",i-rp->nrhs+1,rp->rhs[i]->dtnum);
  3038         -             cp = xp;
  3039         -             used[i] = 1;
  3040         -             break;
  3041         -           }
  3042         -         }
  3043         -       }
  3044         -       *xp = saved;
  3045         -     }
  3046   3129        if( *cp=='\n' ) linecnt++;
  3047         -     fputc(*cp,out);
  3048   3130      } /* End loop */
  3049   3131      (*lineno) += 3 + linecnt;
  3050   3132      fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
  3051   3133    } /* End if( rp->code ) */
  3052   3134   
  3053         - /* Check to make sure the LHS has been used */
  3054         - if( rp->lhsalias && !lhsused ){
  3055         -   ErrorMsg(lemp->filename,rp->ruleline,
  3056         -     "Label \"%s\" for \"%s(%s)\" is never used.",
  3057         -       rp->lhsalias,rp->lhs->name,rp->lhsalias);
  3058         -   lemp->errorcnt++;
  3059         - }
  3060         -
  3061         - /* Generate destructor code for RHS symbols which are not used in the
  3062         - ** reduce code */
  3063         - for(i=0; i<rp->nrhs; i++){
  3064         -   if( rp->rhsalias[i] && !used[i] ){
  3065         -     ErrorMsg(lemp->filename,rp->ruleline,
  3066         -       "Label %s for \"%s(%s)\" is never used.",
  3067         -       rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
  3068         -     lemp->errorcnt++;
  3069         -   }else if( rp->rhsalias[i]==0 ){
  3070         -     if( has_destructor(rp->rhs[i],lemp) ){
  3071         -       fprintf(out,"  yy_destructor(%d,&yymsp[%d].minor);\n",
  3072         -          rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++;
  3073         -     }else{
  3074         -       fprintf(out,"        /* No destructor defined for %s */\n",
  3075         -        rp->rhs[i]->name);
  3076         -        (*lineno)++;
  3077         -     }
  3078         -   }
  3079         - }
  3080   3135    return;
  3081   3136   }
  3082   3137   
  3083   3138   /*
  3084   3139   ** Print the definition of the union used for the parser's data stack.
  3085   3140   ** This union contains fields for every possible data type for tokens
  3086   3141   ** and nonterminals.  In the process of computing and printing this
................................................................................
  3565   3620         fprintf(out,"      break;\n"); lineno++;
  3566   3621       }
  3567   3622     }
  3568   3623     for(i=0; i<lemp->nsymbol; i++){
  3569   3624       struct symbol *sp = lemp->symbols[i];
  3570   3625       if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
  3571   3626       fprintf(out,"    case %d:\n",sp->index); lineno++;
         3627  +
         3628  +    /* Combine duplicate destructors into a single case */
         3629  +    for(j=i+1; j<lemp->nsymbol; j++){
         3630  +      struct symbol *sp2 = lemp->symbols[j];
         3631  +      if( sp2 && sp2->type!=TERMINAL && sp2->destructor
         3632  +          && sp2->dtnum==sp->dtnum
         3633  +          && strcmp(sp->destructor,sp2->destructor)==0 ){
         3634  +         fprintf(out,"    case %d:\n",sp2->index); lineno++;
         3635  +         sp2->destructor = 0;
         3636  +      }
         3637  +    }
         3638  +
  3572   3639       emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
  3573   3640       fprintf(out,"      break;\n"); lineno++;
  3574   3641     }
  3575   3642     if( lemp->vardest ){
  3576   3643       struct symbol *dflt_sp = 0;
  3577   3644       for(i=0; i<lemp->nsymbol; i++){
  3578   3645         struct symbol *sp = lemp->symbols[i];
................................................................................
  3600   3667     for(rp=lemp->rule; rp; rp=rp->next){
  3601   3668       fprintf(out,"  { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
  3602   3669     }
  3603   3670     tplt_xfer(lemp->name,in,out,&lineno);
  3604   3671   
  3605   3672     /* Generate code which execution during each REDUCE action */
  3606   3673     for(rp=lemp->rule; rp; rp=rp->next){
         3674  +    if( rp->code ) translate_code(lemp, rp);
         3675  +  }
         3676  +  for(rp=lemp->rule; rp; rp=rp->next){
         3677  +    struct rule *rp2;
         3678  +    if( rp->code==0 ) continue;
  3607   3679       fprintf(out,"      case %d:\n",rp->index); lineno++;
         3680  +    for(rp2=rp->next; rp2; rp2=rp2->next){
         3681  +      if( rp2->code==rp->code ){
         3682  +        fprintf(out,"      case %d:\n",rp2->index); lineno++;
         3683  +        rp2->code = 0;
         3684  +      }
         3685  +    }
  3608   3686       emit_code(out,rp,lemp,&lineno);
  3609   3687       fprintf(out,"        break;\n"); lineno++;
  3610   3688     }
  3611   3689     tplt_xfer(lemp->name,in,out,&lineno);
  3612   3690   
  3613   3691     /* Generate code which executes if a parse fails */
  3614   3692     tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);