/ Check-in [d292ba51]
Login

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

Overview
Comment:Incremental code compaction in expr.c. Now about 4% smaller. Lots more work to do. (CVS 1183)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:d292ba5148059dce3893b80eabdca4af9f75194e
User & Date: drh 2004-01-16 15:55:38
Context
2004-01-16
16:42
More compaction of expr.c. (CVS 1184) check-in: 92e7f780 user: drh tags: trunk
15:55
Incremental code compaction in expr.c. Now about 4% smaller. Lots more work to do. (CVS 1183) check-in: d292ba51 user: drh tags: trunk
13:58
Fix a buffer-overflow problem in the randStr function (used only for testing). (CVS 1182) check-in: 42c79edc user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains routines used for analyzing expressions and
    13     13   ** for generating VDBE code that evaluates expressions in SQLite.
    14     14   **
    15         -** $Id: expr.c,v 1.104 2004/01/14 03:12:42 drh Exp $
           15  +** $Id: expr.c,v 1.105 2004/01/16 15:55:38 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <ctype.h>
    19     19   
    20     20   /*
    21     21   ** Construct a new expression node and return a pointer to it.  Memory
    22     22   ** for this node is obtained from sqliteMalloc().  The calling function
    23     23   ** is responsible for making sure the node eventually gets freed.
    24     24   */
    25     25   Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
    26     26     Expr *pNew;
    27     27     pNew = sqliteMalloc( sizeof(Expr) );
    28     28     if( pNew==0 ){
    29         -    sqliteExprDelete(pLeft);
    30         -    sqliteExprDelete(pRight);
           29  +    /* When malloc fails, we leak memory from pLeft and pRight */
    31     30       return 0;
    32     31     }
    33     32     pNew->op = op;
    34     33     pNew->pLeft = pLeft;
    35     34     pNew->pRight = pRight;
    36     35     if( pToken ){
    37     36       assert( pToken->dyn==0 );
    38     37       pNew->token = *pToken;
    39     38       pNew->span = *pToken;
    40     39     }else{
    41         -    pNew->token.dyn = 0;
    42         -    pNew->token.z = 0;
    43         -    pNew->token.n = 0;
           40  +    assert( pNew->token.dyn==0 );
           41  +    assert( pNew->token.z==0 );
           42  +    assert( pNew->token.n==0 );
    44     43       if( pLeft && pRight ){
    45     44         sqliteExprSpan(pNew, &pLeft->span, &pRight->span);
    46     45       }else{
    47     46         pNew->span = pNew->token;
    48     47       }
    49     48     }
    50     49     return pNew;
................................................................................
    51     50   }
    52     51   
    53     52   /*
    54     53   ** Set the Expr.span field of the given expression to span all
    55     54   ** text between the two given tokens.
    56     55   */
    57     56   void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
    58         -  if( pExpr && pRight && pRight->z && pLeft && pLeft->z ){
           57  +  assert( pRight!=0 );
           58  +  assert( pLeft!=0 );
           59  +  /* Note: pExpr might be NULL due to a prior malloc failure */
           60  +  if( pExpr && pRight->z && pLeft->z ){
    59     61       if( pLeft->dyn==0 && pRight->dyn==0 ){
    60     62         pExpr->span.z = pLeft->z;
    61     63         pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z);
    62     64       }else{
    63     65         pExpr->span.z = 0;
    64         -      pExpr->span.n = 0;
    65         -      pExpr->span.dyn = 0;
    66     66       }
    67     67     }
    68     68   }
    69     69   
    70     70   /*
    71     71   ** Construct a new expression node for a function with multiple
    72     72   ** arguments.
    73     73   */
    74     74   Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
    75     75     Expr *pNew;
    76     76     pNew = sqliteMalloc( sizeof(Expr) );
    77     77     if( pNew==0 ){
    78         -    sqliteExprListDelete(pList);
           78  +    /* sqliteExprListDelete(pList); // Leak pList when malloc fails */
    79     79       return 0;
    80     80     }
    81     81     pNew->op = TK_FUNCTION;
    82     82     pNew->pList = pList;
    83         -  pNew->token.dyn = 0;
    84     83     if( pToken ){
    85     84       assert( pToken->dyn==0 );
    86     85       pNew->token = *pToken;
    87     86     }else{
    88     87       pNew->token.z = 0;
    89         -    pNew->token.n = 0;
    90     88     }
    91     89     pNew->span = pNew->token;
    92     90     return pNew;
    93     91   }
    94     92   
    95     93   /*
    96     94   ** Recursively delete an expression tree.
    97     95   */
    98     96   void sqliteExprDelete(Expr *p){
    99     97     if( p==0 ) return;
   100         -  if( p->span.dyn && p->span.z ) sqliteFree((char*)p->span.z);
   101         -  if( p->token.dyn && p->token.z ) sqliteFree((char*)p->token.z);
   102         -  if( p->pLeft ) sqliteExprDelete(p->pLeft);
   103         -  if( p->pRight ) sqliteExprDelete(p->pRight);
   104         -  if( p->pList ) sqliteExprListDelete(p->pList);
   105         -  if( p->pSelect ) sqliteSelectDelete(p->pSelect);
           98  +  if( p->span.dyn ) sqliteFree((char*)p->span.z);
           99  +  if( p->token.dyn ) sqliteFree((char*)p->token.z);
          100  +  sqliteExprDelete(p->pLeft);
          101  +  sqliteExprDelete(p->pRight);
          102  +  sqliteExprListDelete(p->pList);
          103  +  sqliteSelectDelete(p->pSelect);
   106    104     sqliteFree(p);
   107    105   }
   108    106   
   109    107   
   110    108   /*
   111    109   ** The following group of routines make deep copies of expressions,
   112    110   ** expression lists, ID lists, and select statements.  The copies can
................................................................................
   125    123     pNew = sqliteMallocRaw( sizeof(*p) );
   126    124     if( pNew==0 ) return 0;
   127    125     memcpy(pNew, p, sizeof(*pNew));
   128    126     if( p->token.z!=0 ){
   129    127       pNew->token.z = sqliteStrDup(p->token.z);
   130    128       pNew->token.dyn = 1;
   131    129     }else{
   132         -    pNew->token.z = 0;
   133         -    pNew->token.n = 0;
   134         -    pNew->token.dyn = 0;
          130  +    assert( pNew->token.z==0 );
   135    131     }
   136    132     pNew->span.z = 0;
   137         -  pNew->span.n = 0;
   138         -  pNew->span.dyn = 0;
   139    133     pNew->pLeft = sqliteExprDup(p->pLeft);
   140    134     pNew->pRight = sqliteExprDup(p->pRight);
   141    135     pNew->pList = sqliteExprListDup(p->pList);
   142    136     pNew->pSelect = sqliteSelectDup(p->pSelect);
   143    137     return pNew;
   144    138   }
   145    139   void sqliteTokenCopy(Token *pTo, Token *pFrom){
   146    140     if( pTo->dyn ) sqliteFree((char*)pTo->z);
   147    141     if( pFrom->z ){
   148    142       pTo->n = pFrom->n;
   149    143       pTo->z = sqliteStrNDup(pFrom->z, pFrom->n);
   150    144       pTo->dyn = 1;
   151    145     }else{
   152         -    pTo->n = 0;
   153    146       pTo->z = 0;
   154         -    pTo->dyn = 0;
   155    147     }
   156    148   }
   157    149   ExprList *sqliteExprListDup(ExprList *p){
   158    150     ExprList *pNew;
   159    151     int i;
   160    152     if( p==0 ) return 0;
   161    153     pNew = sqliteMalloc( sizeof(*pNew) );
................................................................................
   183    175   }
   184    176   SrcList *sqliteSrcListDup(SrcList *p){
   185    177     SrcList *pNew;
   186    178     int i;
   187    179     int nByte;
   188    180     if( p==0 ) return 0;
   189    181     nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
   190         -  pNew = sqliteMalloc( nByte );
          182  +  pNew = sqliteMallocRaw( nByte );
   191    183     if( pNew==0 ) return 0;
   192    184     pNew->nSrc = pNew->nAlloc = p->nSrc;
   193    185     for(i=0; i<p->nSrc; i++){
   194         -    pNew->a[i].zDatabase = sqliteStrDup(p->a[i].zDatabase);
   195         -    pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
   196         -    pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias);
   197         -    pNew->a[i].jointype = p->a[i].jointype;
   198         -    pNew->a[i].iCursor = p->a[i].iCursor;
   199         -    pNew->a[i].pTab = 0;
   200         -    pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect);
   201         -    pNew->a[i].pOn = sqliteExprDup(p->a[i].pOn);
   202         -    pNew->a[i].pUsing = sqliteIdListDup(p->a[i].pUsing);
          186  +    struct SrcList_item *pNewItem = &pNew->a[i];
          187  +    struct SrcList_item *pOldItem = &p->a[i];
          188  +    pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase);
          189  +    pNewItem->zName = sqliteStrDup(pOldItem->zName);
          190  +    pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
          191  +    pNewItem->jointype = pOldItem->jointype;
          192  +    pNewItem->iCursor = pOldItem->iCursor;
          193  +    pNewItem->pTab = 0;
          194  +    pNewItem->pSelect = sqliteSelectDup(pOldItem->pSelect);
          195  +    pNewItem->pOn = sqliteExprDup(pOldItem->pOn);
          196  +    pNewItem->pUsing = sqliteIdListDup(pOldItem->pUsing);
   203    197     }
   204    198     return pNew;
   205    199   }
   206    200   IdList *sqliteIdListDup(IdList *p){
   207    201     IdList *pNew;
   208    202     int i;
   209    203     if( p==0 ) return 0;
   210         -  pNew = sqliteMalloc( sizeof(*pNew) );
          204  +  pNew = sqliteMallocRaw( sizeof(*pNew) );
   211    205     if( pNew==0 ) return 0;
   212    206     pNew->nId = pNew->nAlloc = p->nId;
   213         -  pNew->a = sqliteMalloc( p->nId*sizeof(p->a[0]) );
          207  +  pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) );
   214    208     if( pNew->a==0 ) return 0;
   215    209     for(i=0; i<p->nId; i++){
   216         -    pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
   217         -    pNew->a[i].idx = p->a[i].idx;
          210  +    struct IdList_item *pNewItem = &pNew->a[i];
          211  +    struct IdList_item *pOldItem = &p->a[i];
          212  +    pNewItem->zName = sqliteStrDup(pOldItem->zName);
          213  +    pNewItem->idx = pOldItem->idx;
   218    214     }
   219    215     return pNew;
   220    216   }
   221    217   Select *sqliteSelectDup(Select *p){
   222    218     Select *pNew;
   223    219     if( p==0 ) return 0;
   224         -  pNew = sqliteMalloc( sizeof(*p) );
          220  +  pNew = sqliteMallocRaw( sizeof(*p) );
   225    221     if( pNew==0 ) return 0;
   226    222     pNew->isDistinct = p->isDistinct;
   227    223     pNew->pEList = sqliteExprListDup(p->pEList);
   228    224     pNew->pSrc = sqliteSrcListDup(p->pSrc);
   229    225     pNew->pWhere = sqliteExprDup(p->pWhere);
   230    226     pNew->pGroupBy = sqliteExprListDup(p->pGroupBy);
   231    227     pNew->pHaving = sqliteExprDup(p->pHaving);
................................................................................
   246    242   ** initially NULL, then create a new expression list.
   247    243   */
   248    244   ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
   249    245     int i;
   250    246     if( pList==0 ){
   251    247       pList = sqliteMalloc( sizeof(ExprList) );
   252    248       if( pList==0 ){
   253         -      sqliteExprDelete(pExpr);
          249  +      /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
   254    250         return 0;
   255    251       }
   256         -    pList->nAlloc = 0;
          252  +    assert( pList->nAlloc==0 );
   257    253     }
   258    254     if( pList->nAlloc<=pList->nExpr ){
   259         -    struct ExprList_item *a;
   260    255       pList->nAlloc = pList->nAlloc*2 + 4;
   261         -    a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]));
   262         -    if( a==0 ){
   263         -      sqliteExprDelete(pExpr);
          256  +    pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]));
          257  +    if( pList->a==0 ){
          258  +      /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */
          259  +      pList->nExpr = pList->nAlloc = 0;
   264    260         return pList;
   265    261       }
   266         -    pList->a = a;
   267    262     }
   268         -  if( pList->a && (pExpr || pName) ){
   269         -    i = pList->nExpr++;
   270         -    memset(&pList->a[i], 0, sizeof(pList->a[i]));
   271         -    pList->a[i].pExpr = pExpr;
          263  +  assert( pList->a!=0 );
          264  +  if( pExpr || pName ){
          265  +    struct ExprList_item *pItem = &pList->a[pList->nExpr++];
          266  +    memset(pItem, 0, sizeof(*pItem));
          267  +    pItem->pExpr = pExpr;
   272    268       if( pName ){
   273         -      sqliteSetNString(&pList->a[i].zName, pName->z, pName->n, 0);
   274         -      sqliteDequote(pList->a[i].zName);
          269  +      sqliteSetNString(&pItem->zName, pName->z, pName->n, 0);
          270  +      sqliteDequote(pItem->zName);
   275    271       }
   276    272     }
   277    273     return pList;
   278    274   }
   279    275   
   280    276   /*
   281    277   ** Delete an entire expression list.

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.208 2004/01/15 02:44:03 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.209 2004/01/16 15:55:38 drh Exp $
    15     15   */
    16     16   #include "config.h"
    17     17   #include "sqlite.h"
    18     18   #include "hash.h"
    19     19   #include "vdbe.h"
    20     20   #include "parse.h"
    21     21   #include "btree.h"
................................................................................
   583    583     u8 iDb;          /* Index in sqlite.aDb[] of where this index is stored */
   584    584     Index *pNext;    /* The next index associated with the same table */
   585    585   };
   586    586   
   587    587   /*
   588    588   ** Each token coming out of the lexer is an instance of
   589    589   ** this structure.  Tokens are also used as part of an expression.
          590  +**
          591  +** Note if Token.z==0 then Token.dyn and Token.n are undefined and
          592  +** may contain random values.  Do not make any assuptions about Token.dyn
          593  +** and Token.n when Token.z==0.
   590    594   */
   591    595   struct Token {
   592    596     const char *z;      /* Text of the token.  Not NULL-terminated! */
   593    597     unsigned dyn  : 1;  /* True for malloced memory, false for static */
   594    598     unsigned n    : 31; /* Number of characters in this token */
   595    599   };
   596    600