| OLD | NEW | 
 | (Empty) | 
|    1 /* |  | 
|    2 ** Compile and run this standalone program in order to generate code that |  | 
|    3 ** implements a function that will translate alphabetic identifiers into |  | 
|    4 ** parser token codes. |  | 
|    5 */ |  | 
|    6 #include <stdio.h> |  | 
|    7 #include <string.h> |  | 
|    8 #include <stdlib.h> |  | 
|    9 #include <assert.h> |  | 
|   10  |  | 
|   11 /* |  | 
|   12 ** A header comment placed at the beginning of generated code. |  | 
|   13 */ |  | 
|   14 static const char zHdr[] =  |  | 
|   15   "/***** This file contains automatically generated code ******\n" |  | 
|   16   "**\n" |  | 
|   17   "** The code in this file has been automatically generated by\n" |  | 
|   18   "**\n" |  | 
|   19   "**     $Header: /home/drh/sqlite/trans/cvs/sqlite/sqlite/tool/mkkeywordhash.c
     ,v 1.38 2009/06/09 14:27:41 drh Exp $\n" |  | 
|   20   "**\n" |  | 
|   21   "** The code in this file implements a function that determines whether\n" |  | 
|   22   "** or not a given identifier is really an SQL keyword.  The same thing\n" |  | 
|   23   "** might be implemented more directly using a hand-written hash table.\n" |  | 
|   24   "** But by using this automatically generated code, the size of the code\n" |  | 
|   25   "** is substantially reduced.  This is important for embedded applications\n" |  | 
|   26   "** on platforms with limited memory.\n" |  | 
|   27   "*/\n" |  | 
|   28 ; |  | 
|   29  |  | 
|   30 /* |  | 
|   31 ** All the keywords of the SQL language are stored in a hash |  | 
|   32 ** table composed of instances of the following structure. |  | 
|   33 */ |  | 
|   34 typedef struct Keyword Keyword; |  | 
|   35 struct Keyword { |  | 
|   36   char *zName;         /* The keyword name */ |  | 
|   37   char *zTokenType;    /* Token value for this keyword */ |  | 
|   38   int mask;            /* Code this keyword if non-zero */ |  | 
|   39   int id;              /* Unique ID for this record */ |  | 
|   40   int hash;            /* Hash on the keyword */ |  | 
|   41   int offset;          /* Offset to start of name string */ |  | 
|   42   int len;             /* Length of this keyword, not counting final \000 */ |  | 
|   43   int prefix;          /* Number of characters in prefix */ |  | 
|   44   int longestSuffix;   /* Longest suffix that is a prefix on another word */ |  | 
|   45   int iNext;           /* Index in aKeywordTable[] of next with same hash */ |  | 
|   46   int substrId;        /* Id to another keyword this keyword is embedded in */ |  | 
|   47   int substrOffset;    /* Offset into substrId for start of this keyword */ |  | 
|   48   char zOrigName[20];  /* Original keyword name before processing */ |  | 
|   49 }; |  | 
|   50  |  | 
|   51 /* |  | 
|   52 ** Define masks used to determine which keywords are allowed |  | 
|   53 */ |  | 
|   54 #ifdef SQLITE_OMIT_ALTERTABLE |  | 
|   55 #  define ALTER      0 |  | 
|   56 #else |  | 
|   57 #  define ALTER      0x00000001 |  | 
|   58 #endif |  | 
|   59 #define ALWAYS       0x00000002 |  | 
|   60 #ifdef SQLITE_OMIT_ANALYZE |  | 
|   61 #  define ANALYZE    0 |  | 
|   62 #else |  | 
|   63 #  define ANALYZE    0x00000004 |  | 
|   64 #endif |  | 
|   65 #ifdef SQLITE_OMIT_ATTACH |  | 
|   66 #  define ATTACH     0 |  | 
|   67 #else |  | 
|   68 #  define ATTACH     0x00000008 |  | 
|   69 #endif |  | 
|   70 #ifdef SQLITE_OMIT_AUTOINCREMENT |  | 
|   71 #  define AUTOINCR   0 |  | 
|   72 #else |  | 
|   73 #  define AUTOINCR   0x00000010 |  | 
|   74 #endif |  | 
|   75 #ifdef SQLITE_OMIT_CAST |  | 
|   76 #  define CAST       0 |  | 
|   77 #else |  | 
|   78 #  define CAST       0x00000020 |  | 
|   79 #endif |  | 
|   80 #ifdef SQLITE_OMIT_COMPOUND_SELECT |  | 
|   81 #  define COMPOUND   0 |  | 
|   82 #else |  | 
|   83 #  define COMPOUND   0x00000040 |  | 
|   84 #endif |  | 
|   85 #ifdef SQLITE_OMIT_CONFLICT_CLAUSE |  | 
|   86 #  define CONFLICT   0 |  | 
|   87 #else |  | 
|   88 #  define CONFLICT   0x00000080 |  | 
|   89 #endif |  | 
|   90 #ifdef SQLITE_OMIT_EXPLAIN |  | 
|   91 #  define EXPLAIN    0 |  | 
|   92 #else |  | 
|   93 #  define EXPLAIN    0x00000100 |  | 
|   94 #endif |  | 
|   95 #ifdef SQLITE_OMIT_FOREIGN_KEY |  | 
|   96 #  define FKEY       0 |  | 
|   97 #else |  | 
|   98 #  define FKEY       0x00000200 |  | 
|   99 #endif |  | 
|  100 #ifdef SQLITE_OMIT_PRAGMA |  | 
|  101 #  define PRAGMA     0 |  | 
|  102 #else |  | 
|  103 #  define PRAGMA     0x00000400 |  | 
|  104 #endif |  | 
|  105 #ifdef SQLITE_OMIT_REINDEX |  | 
|  106 #  define REINDEX    0 |  | 
|  107 #else |  | 
|  108 #  define REINDEX    0x00000800 |  | 
|  109 #endif |  | 
|  110 #ifdef SQLITE_OMIT_SUBQUERY |  | 
|  111 #  define SUBQUERY   0 |  | 
|  112 #else |  | 
|  113 #  define SUBQUERY   0x00001000 |  | 
|  114 #endif |  | 
|  115 #ifdef SQLITE_OMIT_TRIGGER |  | 
|  116 #  define TRIGGER    0 |  | 
|  117 #else |  | 
|  118 #  define TRIGGER    0x00002000 |  | 
|  119 #endif |  | 
|  120 #if defined(SQLITE_OMIT_AUTOVACUUM) && \ |  | 
|  121     (defined(SQLITE_OMIT_VACUUM) || defined(SQLITE_OMIT_ATTACH)) |  | 
|  122 #  define VACUUM     0 |  | 
|  123 #else |  | 
|  124 #  define VACUUM     0x00004000 |  | 
|  125 #endif |  | 
|  126 #ifdef SQLITE_OMIT_VIEW |  | 
|  127 #  define VIEW       0 |  | 
|  128 #else |  | 
|  129 #  define VIEW       0x00008000 |  | 
|  130 #endif |  | 
|  131 #ifdef SQLITE_OMIT_VIRTUALTABLE |  | 
|  132 #  define VTAB       0 |  | 
|  133 #else |  | 
|  134 #  define VTAB       0x00010000 |  | 
|  135 #endif |  | 
|  136 #ifdef SQLITE_OMIT_AUTOVACUUM |  | 
|  137 #  define AUTOVACUUM 0 |  | 
|  138 #else |  | 
|  139 #  define AUTOVACUUM 0x00020000 |  | 
|  140 #endif |  | 
|  141  |  | 
|  142 /* |  | 
|  143 ** These are the keywords |  | 
|  144 */ |  | 
|  145 static Keyword aKeywordTable[] = { |  | 
|  146   { "ABORT",            "TK_ABORT",        CONFLICT|TRIGGER       }, |  | 
|  147   { "ADD",              "TK_ADD",          ALTER                  }, |  | 
|  148   { "AFTER",            "TK_AFTER",        TRIGGER                }, |  | 
|  149   { "ALL",              "TK_ALL",          ALWAYS                 }, |  | 
|  150   { "ALTER",            "TK_ALTER",        ALTER                  }, |  | 
|  151   { "ANALYZE",          "TK_ANALYZE",      ANALYZE                }, |  | 
|  152   { "AND",              "TK_AND",          ALWAYS                 }, |  | 
|  153   { "AS",               "TK_AS",           ALWAYS                 }, |  | 
|  154   { "ASC",              "TK_ASC",          ALWAYS                 }, |  | 
|  155   { "ATTACH",           "TK_ATTACH",       ATTACH                 }, |  | 
|  156   { "AUTOINCREMENT",    "TK_AUTOINCR",     AUTOINCR               }, |  | 
|  157   { "BEFORE",           "TK_BEFORE",       TRIGGER                }, |  | 
|  158   { "BEGIN",            "TK_BEGIN",        ALWAYS                 }, |  | 
|  159   { "BETWEEN",          "TK_BETWEEN",      ALWAYS                 }, |  | 
|  160   { "BY",               "TK_BY",           ALWAYS                 }, |  | 
|  161   { "CASCADE",          "TK_CASCADE",      FKEY                   }, |  | 
|  162   { "CASE",             "TK_CASE",         ALWAYS                 }, |  | 
|  163   { "CAST",             "TK_CAST",         CAST                   }, |  | 
|  164   { "CHECK",            "TK_CHECK",        ALWAYS                 }, |  | 
|  165   { "COLLATE",          "TK_COLLATE",      ALWAYS                 }, |  | 
|  166   { "COLUMN",           "TK_COLUMNKW",     ALTER                  }, |  | 
|  167   { "COMMIT",           "TK_COMMIT",       ALWAYS                 }, |  | 
|  168   { "CONFLICT",         "TK_CONFLICT",     CONFLICT               }, |  | 
|  169   { "CONSTRAINT",       "TK_CONSTRAINT",   ALWAYS                 }, |  | 
|  170   { "CREATE",           "TK_CREATE",       ALWAYS                 }, |  | 
|  171   { "CROSS",            "TK_JOIN_KW",      ALWAYS                 }, |  | 
|  172   { "CURRENT_DATE",     "TK_CTIME_KW",     ALWAYS                 }, |  | 
|  173   { "CURRENT_TIME",     "TK_CTIME_KW",     ALWAYS                 }, |  | 
|  174   { "CURRENT_TIMESTAMP","TK_CTIME_KW",     ALWAYS                 }, |  | 
|  175   { "DATABASE",         "TK_DATABASE",     ATTACH                 }, |  | 
|  176   { "DEFAULT",          "TK_DEFAULT",      ALWAYS                 }, |  | 
|  177   { "DEFERRED",         "TK_DEFERRED",     ALWAYS                 }, |  | 
|  178   { "DEFERRABLE",       "TK_DEFERRABLE",   FKEY                   }, |  | 
|  179   { "DELETE",           "TK_DELETE",       ALWAYS                 }, |  | 
|  180   { "DESC",             "TK_DESC",         ALWAYS                 }, |  | 
|  181   { "DETACH",           "TK_DETACH",       ATTACH                 }, |  | 
|  182   { "DISTINCT",         "TK_DISTINCT",     ALWAYS                 }, |  | 
|  183   { "DROP",             "TK_DROP",         ALWAYS                 }, |  | 
|  184   { "END",              "TK_END",          ALWAYS                 }, |  | 
|  185   { "EACH",             "TK_EACH",         TRIGGER                }, |  | 
|  186   { "ELSE",             "TK_ELSE",         ALWAYS                 }, |  | 
|  187   { "ESCAPE",           "TK_ESCAPE",       ALWAYS                 }, |  | 
|  188   { "EXCEPT",           "TK_EXCEPT",       COMPOUND               }, |  | 
|  189   { "EXCLUSIVE",        "TK_EXCLUSIVE",    ALWAYS                 }, |  | 
|  190   { "EXISTS",           "TK_EXISTS",       ALWAYS                 }, |  | 
|  191   { "EXPLAIN",          "TK_EXPLAIN",      EXPLAIN                }, |  | 
|  192   { "FAIL",             "TK_FAIL",         CONFLICT|TRIGGER       }, |  | 
|  193   { "FOR",              "TK_FOR",          TRIGGER                }, |  | 
|  194   { "FOREIGN",          "TK_FOREIGN",      FKEY                   }, |  | 
|  195   { "FROM",             "TK_FROM",         ALWAYS                 }, |  | 
|  196   { "FULL",             "TK_JOIN_KW",      ALWAYS                 }, |  | 
|  197   { "GLOB",             "TK_LIKE_KW",      ALWAYS                 }, |  | 
|  198   { "GROUP",            "TK_GROUP",        ALWAYS                 }, |  | 
|  199   { "HAVING",           "TK_HAVING",       ALWAYS                 }, |  | 
|  200   { "IF",               "TK_IF",           ALWAYS                 }, |  | 
|  201   { "IGNORE",           "TK_IGNORE",       CONFLICT|TRIGGER       }, |  | 
|  202   { "IMMEDIATE",        "TK_IMMEDIATE",    ALWAYS                 }, |  | 
|  203   { "IN",               "TK_IN",           ALWAYS                 }, |  | 
|  204   { "INDEX",            "TK_INDEX",        ALWAYS                 }, |  | 
|  205   { "INDEXED",          "TK_INDEXED",      ALWAYS                 }, |  | 
|  206   { "INITIALLY",        "TK_INITIALLY",    FKEY                   }, |  | 
|  207   { "INNER",            "TK_JOIN_KW",      ALWAYS                 }, |  | 
|  208   { "INSERT",           "TK_INSERT",       ALWAYS                 }, |  | 
|  209   { "INSTEAD",          "TK_INSTEAD",      TRIGGER                }, |  | 
|  210   { "INTERSECT",        "TK_INTERSECT",    COMPOUND               }, |  | 
|  211   { "INTO",             "TK_INTO",         ALWAYS                 }, |  | 
|  212   { "IS",               "TK_IS",           ALWAYS                 }, |  | 
|  213   { "ISNULL",           "TK_ISNULL",       ALWAYS                 }, |  | 
|  214   { "JOIN",             "TK_JOIN",         ALWAYS                 }, |  | 
|  215   { "KEY",              "TK_KEY",          ALWAYS                 }, |  | 
|  216   { "LEFT",             "TK_JOIN_KW",      ALWAYS                 }, |  | 
|  217   { "LIKE",             "TK_LIKE_KW",      ALWAYS                 }, |  | 
|  218   { "LIMIT",            "TK_LIMIT",        ALWAYS                 }, |  | 
|  219   { "MATCH",            "TK_MATCH",        ALWAYS                 }, |  | 
|  220   { "NATURAL",          "TK_JOIN_KW",      ALWAYS                 }, |  | 
|  221   { "NOT",              "TK_NOT",          ALWAYS                 }, |  | 
|  222   { "NOTNULL",          "TK_NOTNULL",      ALWAYS                 }, |  | 
|  223   { "NULL",             "TK_NULL",         ALWAYS                 }, |  | 
|  224   { "OF",               "TK_OF",           ALWAYS                 }, |  | 
|  225   { "OFFSET",           "TK_OFFSET",       ALWAYS                 }, |  | 
|  226   { "ON",               "TK_ON",           ALWAYS                 }, |  | 
|  227   { "OR",               "TK_OR",           ALWAYS                 }, |  | 
|  228   { "ORDER",            "TK_ORDER",        ALWAYS                 }, |  | 
|  229   { "OUTER",            "TK_JOIN_KW",      ALWAYS                 }, |  | 
|  230   { "PLAN",             "TK_PLAN",         EXPLAIN                }, |  | 
|  231   { "PRAGMA",           "TK_PRAGMA",       PRAGMA                 }, |  | 
|  232   { "PRIMARY",          "TK_PRIMARY",      ALWAYS                 }, |  | 
|  233   { "QUERY",            "TK_QUERY",        EXPLAIN                }, |  | 
|  234   { "RAISE",            "TK_RAISE",        TRIGGER                }, |  | 
|  235   { "REFERENCES",       "TK_REFERENCES",   FKEY                   }, |  | 
|  236   { "REGEXP",           "TK_LIKE_KW",      ALWAYS                 }, |  | 
|  237   { "REINDEX",          "TK_REINDEX",      REINDEX                }, |  | 
|  238   { "RELEASE",          "TK_RELEASE",      ALWAYS                 }, |  | 
|  239   { "RENAME",           "TK_RENAME",       ALTER                  }, |  | 
|  240   { "REPLACE",          "TK_REPLACE",      CONFLICT               }, |  | 
|  241   { "RESTRICT",         "TK_RESTRICT",     FKEY                   }, |  | 
|  242   { "RIGHT",            "TK_JOIN_KW",      ALWAYS                 }, |  | 
|  243   { "ROLLBACK",         "TK_ROLLBACK",     ALWAYS                 }, |  | 
|  244   { "ROW",              "TK_ROW",          TRIGGER                }, |  | 
|  245   { "SAVEPOINT",        "TK_SAVEPOINT",    ALWAYS                 }, |  | 
|  246   { "SELECT",           "TK_SELECT",       ALWAYS                 }, |  | 
|  247   { "SET",              "TK_SET",          ALWAYS                 }, |  | 
|  248   { "TABLE",            "TK_TABLE",        ALWAYS                 }, |  | 
|  249   { "TEMP",             "TK_TEMP",         ALWAYS                 }, |  | 
|  250   { "TEMPORARY",        "TK_TEMP",         ALWAYS                 }, |  | 
|  251   { "THEN",             "TK_THEN",         ALWAYS                 }, |  | 
|  252   { "TO",               "TK_TO",           ALWAYS                 }, |  | 
|  253   { "TRANSACTION",      "TK_TRANSACTION",  ALWAYS                 }, |  | 
|  254   { "TRIGGER",          "TK_TRIGGER",      TRIGGER                }, |  | 
|  255   { "UNION",            "TK_UNION",        COMPOUND               }, |  | 
|  256   { "UNIQUE",           "TK_UNIQUE",       ALWAYS                 }, |  | 
|  257   { "UPDATE",           "TK_UPDATE",       ALWAYS                 }, |  | 
|  258   { "USING",            "TK_USING",        ALWAYS                 }, |  | 
|  259   { "VACUUM",           "TK_VACUUM",       VACUUM                 }, |  | 
|  260   { "VALUES",           "TK_VALUES",       ALWAYS                 }, |  | 
|  261   { "VIEW",             "TK_VIEW",         VIEW                   }, |  | 
|  262   { "VIRTUAL",          "TK_VIRTUAL",      VTAB                   }, |  | 
|  263   { "WHEN",             "TK_WHEN",         ALWAYS                 }, |  | 
|  264   { "WHERE",            "TK_WHERE",        ALWAYS                 }, |  | 
|  265 }; |  | 
|  266  |  | 
|  267 /* Number of keywords */ |  | 
|  268 static int nKeyword = (sizeof(aKeywordTable)/sizeof(aKeywordTable[0])); |  | 
|  269  |  | 
|  270 /* An array to map all upper-case characters into their corresponding |  | 
|  271 ** lower-case character.  |  | 
|  272 */ |  | 
|  273 const unsigned char sqlite3UpperToLower[] = { |  | 
|  274       0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, |  | 
|  275      18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, |  | 
|  276      36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, |  | 
|  277      54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, |  | 
|  278     104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, |  | 
|  279     122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107, |  | 
|  280     108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, |  | 
|  281     126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, |  | 
|  282     144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, |  | 
|  283     162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, |  | 
|  284     180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, |  | 
|  285     198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, |  | 
|  286     216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233, |  | 
|  287     234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, |  | 
|  288     252,253,254,255 |  | 
|  289 }; |  | 
|  290 #define UpperToLower sqlite3UpperToLower |  | 
|  291  |  | 
|  292 /* |  | 
|  293 ** Comparision function for two Keyword records |  | 
|  294 */ |  | 
|  295 static int keywordCompare1(const void *a, const void *b){ |  | 
|  296   const Keyword *pA = (Keyword*)a; |  | 
|  297   const Keyword *pB = (Keyword*)b; |  | 
|  298   int n = pA->len - pB->len; |  | 
|  299   if( n==0 ){ |  | 
|  300     n = strcmp(pA->zName, pB->zName); |  | 
|  301   } |  | 
|  302   return n; |  | 
|  303 } |  | 
|  304 static int keywordCompare2(const void *a, const void *b){ |  | 
|  305   const Keyword *pA = (Keyword*)a; |  | 
|  306   const Keyword *pB = (Keyword*)b; |  | 
|  307   int n = pB->longestSuffix - pA->longestSuffix; |  | 
|  308   if( n==0 ){ |  | 
|  309     n = strcmp(pA->zName, pB->zName); |  | 
|  310   } |  | 
|  311   return n; |  | 
|  312 } |  | 
|  313 static int keywordCompare3(const void *a, const void *b){ |  | 
|  314   const Keyword *pA = (Keyword*)a; |  | 
|  315   const Keyword *pB = (Keyword*)b; |  | 
|  316   int n = pA->offset - pB->offset; |  | 
|  317   return n; |  | 
|  318 } |  | 
|  319  |  | 
|  320 /* |  | 
|  321 ** Return a KeywordTable entry with the given id |  | 
|  322 */ |  | 
|  323 static Keyword *findById(int id){ |  | 
|  324   int i; |  | 
|  325   for(i=0; i<nKeyword; i++){ |  | 
|  326     if( aKeywordTable[i].id==id ) break; |  | 
|  327   } |  | 
|  328   return &aKeywordTable[i]; |  | 
|  329 } |  | 
|  330  |  | 
|  331 /* |  | 
|  332 ** This routine does the work.  The generated code is printed on standard |  | 
|  333 ** output. |  | 
|  334 */ |  | 
|  335 int main(int argc, char **argv){ |  | 
|  336   int i, j, k, h; |  | 
|  337   int bestSize, bestCount; |  | 
|  338   int count; |  | 
|  339   int nChar; |  | 
|  340   int totalLen = 0; |  | 
|  341   int aHash[1000];  /* 1000 is much bigger than nKeyword */ |  | 
|  342   char zText[2000]; |  | 
|  343  |  | 
|  344   /* Remove entries from the list of keywords that have mask==0 */ |  | 
|  345   for(i=j=0; i<nKeyword; i++){ |  | 
|  346     if( aKeywordTable[i].mask==0 ) continue; |  | 
|  347     if( j<i ){ |  | 
|  348       aKeywordTable[j] = aKeywordTable[i]; |  | 
|  349     } |  | 
|  350     j++; |  | 
|  351   } |  | 
|  352   nKeyword = j; |  | 
|  353  |  | 
|  354   /* Fill in the lengths of strings and hashes for all entries. */ |  | 
|  355   for(i=0; i<nKeyword; i++){ |  | 
|  356     Keyword *p = &aKeywordTable[i]; |  | 
|  357     p->len = strlen(p->zName); |  | 
|  358     assert( p->len<sizeof(p->zOrigName) ); |  | 
|  359     strcpy(p->zOrigName, p->zName); |  | 
|  360     totalLen += p->len; |  | 
|  361     p->hash = (UpperToLower[(int)p->zName[0]]*4) ^ |  | 
|  362               (UpperToLower[(int)p->zName[p->len-1]]*3) ^ p->len; |  | 
|  363     p->id = i+1; |  | 
|  364   } |  | 
|  365  |  | 
|  366   /* Sort the table from shortest to longest keyword */ |  | 
|  367   qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare1); |  | 
|  368  |  | 
|  369   /* Look for short keywords embedded in longer keywords */ |  | 
|  370   for(i=nKeyword-2; i>=0; i--){ |  | 
|  371     Keyword *p = &aKeywordTable[i]; |  | 
|  372     for(j=nKeyword-1; j>i && p->substrId==0; j--){ |  | 
|  373       Keyword *pOther = &aKeywordTable[j]; |  | 
|  374       if( pOther->substrId ) continue; |  | 
|  375       if( pOther->len<=p->len ) continue; |  | 
|  376       for(k=0; k<=pOther->len-p->len; k++){ |  | 
|  377         if( memcmp(p->zName, &pOther->zName[k], p->len)==0 ){ |  | 
|  378           p->substrId = pOther->id; |  | 
|  379           p->substrOffset = k; |  | 
|  380           break; |  | 
|  381         } |  | 
|  382       } |  | 
|  383     } |  | 
|  384   } |  | 
|  385  |  | 
|  386   /* Compute the longestSuffix value for every word */ |  | 
|  387   for(i=0; i<nKeyword; i++){ |  | 
|  388     Keyword *p = &aKeywordTable[i]; |  | 
|  389     if( p->substrId ) continue; |  | 
|  390     for(j=0; j<nKeyword; j++){ |  | 
|  391       Keyword *pOther; |  | 
|  392       if( j==i ) continue; |  | 
|  393       pOther = &aKeywordTable[j]; |  | 
|  394       if( pOther->substrId ) continue; |  | 
|  395       for(k=p->longestSuffix+1; k<p->len && k<pOther->len; k++){ |  | 
|  396         if( memcmp(&p->zName[p->len-k], pOther->zName, k)==0 ){ |  | 
|  397           p->longestSuffix = k; |  | 
|  398         } |  | 
|  399       } |  | 
|  400     } |  | 
|  401   } |  | 
|  402  |  | 
|  403   /* Sort the table into reverse order by length */ |  | 
|  404   qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare2); |  | 
|  405  |  | 
|  406   /* Fill in the offset for all entries */ |  | 
|  407   nChar = 0; |  | 
|  408   for(i=0; i<nKeyword; i++){ |  | 
|  409     Keyword *p = &aKeywordTable[i]; |  | 
|  410     if( p->offset>0 || p->substrId ) continue; |  | 
|  411     p->offset = nChar; |  | 
|  412     nChar += p->len; |  | 
|  413     for(k=p->len-1; k>=1; k--){ |  | 
|  414       for(j=i+1; j<nKeyword; j++){ |  | 
|  415         Keyword *pOther = &aKeywordTable[j]; |  | 
|  416         if( pOther->offset>0 || pOther->substrId ) continue; |  | 
|  417         if( pOther->len<=k ) continue; |  | 
|  418         if( memcmp(&p->zName[p->len-k], pOther->zName, k)==0 ){ |  | 
|  419           p = pOther; |  | 
|  420           p->offset = nChar - k; |  | 
|  421           nChar = p->offset + p->len; |  | 
|  422           p->zName += k; |  | 
|  423           p->len -= k; |  | 
|  424           p->prefix = k; |  | 
|  425           j = i; |  | 
|  426           k = p->len; |  | 
|  427         } |  | 
|  428       } |  | 
|  429     } |  | 
|  430   } |  | 
|  431   for(i=0; i<nKeyword; i++){ |  | 
|  432     Keyword *p = &aKeywordTable[i]; |  | 
|  433     if( p->substrId ){ |  | 
|  434       p->offset = findById(p->substrId)->offset + p->substrOffset; |  | 
|  435     } |  | 
|  436   } |  | 
|  437  |  | 
|  438   /* Sort the table by offset */ |  | 
|  439   qsort(aKeywordTable, nKeyword, sizeof(aKeywordTable[0]), keywordCompare3); |  | 
|  440  |  | 
|  441   /* Figure out how big to make the hash table in order to minimize the |  | 
|  442   ** number of collisions */ |  | 
|  443   bestSize = nKeyword; |  | 
|  444   bestCount = nKeyword*nKeyword; |  | 
|  445   for(i=nKeyword/2; i<=2*nKeyword; i++){ |  | 
|  446     for(j=0; j<i; j++) aHash[j] = 0; |  | 
|  447     for(j=0; j<nKeyword; j++){ |  | 
|  448       h = aKeywordTable[j].hash % i; |  | 
|  449       aHash[h] *= 2; |  | 
|  450       aHash[h]++; |  | 
|  451     } |  | 
|  452     for(j=count=0; j<i; j++) count += aHash[j]; |  | 
|  453     if( count<bestCount ){ |  | 
|  454       bestCount = count; |  | 
|  455       bestSize = i; |  | 
|  456     } |  | 
|  457   } |  | 
|  458  |  | 
|  459   /* Compute the hash */ |  | 
|  460   for(i=0; i<bestSize; i++) aHash[i] = 0; |  | 
|  461   for(i=0; i<nKeyword; i++){ |  | 
|  462     h = aKeywordTable[i].hash % bestSize; |  | 
|  463     aKeywordTable[i].iNext = aHash[h]; |  | 
|  464     aHash[h] = i+1; |  | 
|  465   } |  | 
|  466  |  | 
|  467   /* Begin generating code */ |  | 
|  468   printf("%s", zHdr); |  | 
|  469   printf("/* Hash score: %d */\n", bestCount); |  | 
|  470   printf("static int keywordCode(const char *z, int n){\n"); |  | 
|  471   printf("  /* zText[] encodes %d bytes of keywords in %d bytes */\n", |  | 
|  472           totalLen + nKeyword, nChar+1 ); |  | 
|  473   for(i=j=k=0; i<nKeyword; i++){ |  | 
|  474     Keyword *p = &aKeywordTable[i]; |  | 
|  475     if( p->substrId ) continue; |  | 
|  476     memcpy(&zText[k], p->zName, p->len); |  | 
|  477     k += p->len; |  | 
|  478     if( j+p->len>70 ){ |  | 
|  479       printf("%*s */\n", 74-j, ""); |  | 
|  480       j = 0; |  | 
|  481     } |  | 
|  482     if( j==0 ){ |  | 
|  483       printf("  /*   "); |  | 
|  484       j = 8; |  | 
|  485     } |  | 
|  486     printf("%s", p->zName); |  | 
|  487     j += p->len; |  | 
|  488   } |  | 
|  489   if( j>0 ){ |  | 
|  490     printf("%*s */\n", 74-j, ""); |  | 
|  491   } |  | 
|  492   printf("  static const char zText[%d] = {\n", nChar); |  | 
|  493   zText[nChar] = 0; |  | 
|  494   for(i=j=0; i<k; i++){ |  | 
|  495     if( j==0 ){ |  | 
|  496       printf("    "); |  | 
|  497     } |  | 
|  498     if( zText[i]==0 ){ |  | 
|  499       printf("0"); |  | 
|  500     }else{ |  | 
|  501       printf("'%c',", zText[i]); |  | 
|  502     } |  | 
|  503     j += 4; |  | 
|  504     if( j>68 ){ |  | 
|  505       printf("\n"); |  | 
|  506       j = 0; |  | 
|  507     } |  | 
|  508   } |  | 
|  509   if( j>0 ) printf("\n"); |  | 
|  510   printf("  };\n"); |  | 
|  511  |  | 
|  512   printf("  static const unsigned char aHash[%d] = {\n", bestSize); |  | 
|  513   for(i=j=0; i<bestSize; i++){ |  | 
|  514     if( j==0 ) printf("    "); |  | 
|  515     printf(" %3d,", aHash[i]); |  | 
|  516     j++; |  | 
|  517     if( j>12 ){ |  | 
|  518       printf("\n"); |  | 
|  519       j = 0; |  | 
|  520     } |  | 
|  521   } |  | 
|  522   printf("%s  };\n", j==0 ? "" : "\n");     |  | 
|  523  |  | 
|  524   printf("  static const unsigned char aNext[%d] = {\n", nKeyword); |  | 
|  525   for(i=j=0; i<nKeyword; i++){ |  | 
|  526     if( j==0 ) printf("    "); |  | 
|  527     printf(" %3d,", aKeywordTable[i].iNext); |  | 
|  528     j++; |  | 
|  529     if( j>12 ){ |  | 
|  530       printf("\n"); |  | 
|  531       j = 0; |  | 
|  532     } |  | 
|  533   } |  | 
|  534   printf("%s  };\n", j==0 ? "" : "\n");     |  | 
|  535  |  | 
|  536   printf("  static const unsigned char aLen[%d] = {\n", nKeyword); |  | 
|  537   for(i=j=0; i<nKeyword; i++){ |  | 
|  538     if( j==0 ) printf("    "); |  | 
|  539     printf(" %3d,", aKeywordTable[i].len+aKeywordTable[i].prefix); |  | 
|  540     j++; |  | 
|  541     if( j>12 ){ |  | 
|  542       printf("\n"); |  | 
|  543       j = 0; |  | 
|  544     } |  | 
|  545   } |  | 
|  546   printf("%s  };\n", j==0 ? "" : "\n");     |  | 
|  547  |  | 
|  548   printf("  static const unsigned short int aOffset[%d] = {\n", nKeyword); |  | 
|  549   for(i=j=0; i<nKeyword; i++){ |  | 
|  550     if( j==0 ) printf("    "); |  | 
|  551     printf(" %3d,", aKeywordTable[i].offset); |  | 
|  552     j++; |  | 
|  553     if( j>12 ){ |  | 
|  554       printf("\n"); |  | 
|  555       j = 0; |  | 
|  556     } |  | 
|  557   } |  | 
|  558   printf("%s  };\n", j==0 ? "" : "\n"); |  | 
|  559  |  | 
|  560   printf("  static const unsigned char aCode[%d] = {\n", nKeyword); |  | 
|  561   for(i=j=0; i<nKeyword; i++){ |  | 
|  562     char *zToken = aKeywordTable[i].zTokenType; |  | 
|  563     if( j==0 ) printf("    "); |  | 
|  564     printf("%s,%*s", zToken, (int)(14-strlen(zToken)), ""); |  | 
|  565     j++; |  | 
|  566     if( j>=5 ){ |  | 
|  567       printf("\n"); |  | 
|  568       j = 0; |  | 
|  569     } |  | 
|  570   } |  | 
|  571   printf("%s  };\n", j==0 ? "" : "\n"); |  | 
|  572  |  | 
|  573   printf("  int h, i;\n"); |  | 
|  574   printf("  if( n<2 ) return TK_ID;\n"); |  | 
|  575   printf("  h = ((charMap(z[0])*4) ^\n" |  | 
|  576          "      (charMap(z[n-1])*3) ^\n" |  | 
|  577          "      n) %% %d;\n", bestSize); |  | 
|  578   printf("  for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n"); |  | 
|  579   printf("    if( aLen[i]==n &&" |  | 
|  580                    " sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){\n"); |  | 
|  581   for(i=0; i<nKeyword; i++){ |  | 
|  582     printf("      testcase( i==%d ); /* %s */\n", |  | 
|  583            i, aKeywordTable[i].zOrigName); |  | 
|  584   } |  | 
|  585   printf("      return aCode[i];\n"); |  | 
|  586   printf("    }\n"); |  | 
|  587   printf("  }\n"); |  | 
|  588   printf("  return TK_ID;\n"); |  | 
|  589   printf("}\n"); |  | 
|  590   printf("int sqlite3KeywordCode(const unsigned char *z, int n){\n"); |  | 
|  591   printf("  return keywordCode((char*)z, n);\n"); |  | 
|  592   printf("}\n"); |  | 
|  593  |  | 
|  594   return 0; |  | 
|  595 } |  | 
| OLD | NEW |