gen_lex_hash.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #define NO_YACC_SYMBOLS
  14. #include <global.h>
  15. #include <my_sys.h>
  16. #include <m_string.h>
  17. #ifndef __GNU_LIBRARY__
  18. #define __GNU_LIBRARY__ // Skipp warnings in getopt.h
  19. #endif
  20. #include <getopt.h>
  21. #include "mysql_version.h"
  22. #include "lex.h"
  23. bool opt_search=0,opt_verbose=0;
  24. ulong opt_count=100000;
  25. #define max_allowed_array  8000 // Don't generate bigger arrays than this
  26. #define max_symbol   32767 // Use this for 'not found'
  27. #define how_much_for_plus  8 // 2-8
  28. #define type_count    1 // 1-5
  29. #define char_table_count   5
  30. #define total_symbols  (sizeof(symbols)/sizeof(SYMBOL) +
  31. sizeof(sql_functions)/sizeof(SYMBOL))
  32. #define how_much_and INT_MAX24
  33. /*
  34.   The following only have to work with characters in the set
  35.   used by SQL commands
  36. */
  37. #undef tolower
  38. #define tolower(a) ((a) >= 'A' && (a) <= 'Z') ? ((a)- 'A' + 'a') : (a)
  39. static uint how_long_symbols,function_plus,function_mod,function_type;
  40. static uint char_table[256];
  41. static uchar unique_length[256];
  42. static uchar bits[how_much_and/8+1];
  43. static uint primes[max_allowed_array+1];
  44. static ulong hash_results[type_count][how_much_for_plus+1][total_symbols];
  45. static ulong start_value=0;
  46. struct rand_struct {
  47.   unsigned long seed1,seed2,max_value;
  48.   double max_value_dbl;
  49. };
  50. void randominit(struct rand_struct *rand_st,ulong seed1, ulong seed2)
  51. { /* For mysql 3.21.# */
  52.   rand_st->max_value= 0x3FFFFFFFL;
  53.   rand_st->max_value_dbl=(double) rand_st->max_value;
  54.   rand_st->seed1=seed1%rand_st->max_value ;
  55.   rand_st->seed2=seed2%rand_st->max_value;
  56. }
  57. double rnd(struct rand_struct *rand_st)
  58. {
  59.   rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
  60.   rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
  61.   return (((double) rand_st->seed1)/rand_st->max_value_dbl);
  62. }
  63. static void make_char_table(ulong t1,ulong t2,int type)
  64. {
  65.   uint i;
  66.   struct rand_struct rand_st;
  67.   randominit(&rand_st,t1,t2);
  68.   for (i=0 ; i < 256 ; i++)
  69.   {
  70.     switch (type) {
  71.     case 0: char_table[i]= i + (i << 8); break;
  72.     case 1: char_table[i]= i + ((i ^255 ) << 8); break;
  73.     case 2: char_table[i]= i; break;
  74.     case 3: char_table[i]= i + ((uint) (rnd(&rand_st)*255) << 8); break;
  75.     case 4: char_table[i]= (uint) (rnd(&rand_st)*255) + (i << 8); break;
  76.     }
  77.   }
  78.   char_table[0]|=1+257; // Avoid problems with 0
  79.   for (i=0 ; i < 256 ; i++)
  80.   {
  81.     uint tmp=(uint) (rnd(&rand_st)*255);
  82.     swap(uint,char_table[i],char_table[tmp]);
  83.   }
  84.   /* lower characters should be mapped to upper */
  85.   for (i= 'a' ; i <= 'z' ; i++)
  86.   {
  87.     /* This loop is coded with extra variables to avoid a bug in gcc 2.96 */
  88.     uchar tmp= (uchar) (i - 'a'); // Assume ascii
  89.     tmp+='A';
  90.     char_table[i]=char_table[tmp];
  91.   }
  92. }
  93. /* Fill array primes with primes between start and 'max_allowed_array' */
  94. static void make_prime_array(uint start)
  95. {
  96.   uint i,j,*to;
  97.   uint max_index=(uint) sqrt((double) max_allowed_array);
  98.   bzero((char*) primes,sizeof(primes[0])*max_allowed_array);
  99.   i=2;
  100.   while (i < max_index)
  101.   {
  102.     for (j=i+i ; j <= max_allowed_array ; j+=i)
  103.       primes[j]=1;
  104.     while (primes[++i]) ;
  105.   }
  106.   to=primes;
  107.   for (i=start ; i <= max_allowed_array ; i++)
  108.     if (!primes[i])
  109.       *to++=i;
  110.   *to=0; // end marker
  111. }
  112. #define USE_char_table
  113. static ulong tab_index_function(const char *s,uint add, uint type)
  114. {
  115.   register ulong nr=start_value+char_table[(uchar) *s]; // Nice value
  116.   ulong pos=3;
  117.   uint tmp_length=unique_length[(uchar) *s]-1;
  118.   while (*++s && tmp_length-- > 0)
  119.   {
  120.     switch (type) {
  121.     case 0:
  122.       nr= (nr ^ (char_table[(uchar) *s] + (nr << add)));
  123.       break;
  124.     case 1:
  125.       nr= (nr + (char_table[(uchar) *s] + (nr << add)));
  126.       break;
  127.     case 2:
  128.       nr= (nr ^ (char_table[(uchar) *s] ^ (nr << add)));
  129.       break;
  130.     case 3:
  131.       nr= (char_table[(uchar) *s] ^ (nr << add));
  132.       break;
  133.     case 4:
  134.       nr+= nr+nr+((nr & 63)+pos)*((ulong) char_table[(uchar) *s]);
  135.       pos+=add;
  136.       break;
  137.     }
  138.   }
  139.   return nr & INT_MAX24;
  140. }
  141. static int search(bool write_warning)
  142. {
  143.   uint size_symbols = sizeof(symbols)/sizeof(SYMBOL);
  144.   uint size_functions = sizeof(sql_functions)/sizeof(SYMBOL);
  145.   uint size=size_symbols + size_functions;
  146.   uint i=0,found,*prime,type;
  147.   int igra[max_allowed_array],test_count=INT_MAX;
  148.   uint possible_plus[how_much_for_plus*type_count+type_count];
  149.   how_long_symbols = sizeof(symbols)/sizeof(SYMBOL);
  150.   bzero((char*) possible_plus,sizeof(possible_plus));
  151.   found=0;
  152.   /* Check first which function_plus are possible */
  153.   for (type=0 ; type < type_count ; type ++)
  154.   {
  155.     for (function_plus = 1;
  156.  function_plus <= how_much_for_plus;
  157.  function_plus++)
  158.     {
  159.       bzero((char*) bits,sizeof(bits));
  160.       for (i=0; i < size; i++)
  161.       {
  162. ulong order= tab_index_function ((i < how_long_symbols) ?
  163.  symbols[i].name :
  164.  sql_functions[i-how_long_symbols].name,
  165.  function_plus, type);
  166. hash_results[type][function_plus][i]=order;
  167. uint pos=order/8;
  168. uint bit=order & 7;
  169. if (bits[pos] & (1 << bit))
  170.   break;
  171. bits[pos]|=1 << bit;
  172.       }
  173.       if (i == size)
  174.       {
  175. possible_plus[found++]=function_plus;
  176.       }
  177.     }
  178.     possible_plus[found++]=0; // End marker
  179.   }
  180.   if (found == type_count)
  181.   {
  182.     if (write_warning)
  183.       fprintf(stderr,"
  184. The hash function didn't return a unique value for any parametern
  185. You have to change gen_lex_code.cc, function 'tab_index_function' ton
  186. generate unique values for some parameter.  When you have succeeded in this,n
  187. you have to change 'main' to print out the new functionn");
  188.     return(1);
  189.   }
  190.   if (opt_verbose)
  191.     fprintf (stderr,"Info: Possible add values: %dn",found-type_count);
  192.   for (prime=primes; (function_mod=*prime) ; prime++)
  193.   {
  194.     uint *plus_ptr=possible_plus;
  195.     for (type=0 ; type < type_count ; type++ )
  196.     {
  197.       while ((function_plus= *plus_ptr++))
  198.       {
  199. ulong *order_pos= &hash_results[type][function_plus][0];
  200. if (test_count++ == INT_MAX)
  201. {
  202.   test_count=1;
  203.   bzero((char*) igra,sizeof(igra));
  204. }
  205. for (i=0; i<size ;i++)
  206. {
  207.   ulong order;
  208.   order = *order_pos++ % function_mod;
  209.   if (igra[order] == test_count)
  210.     break;
  211.   igra[order] = test_count;
  212. }
  213. if (i == size)
  214. {
  215.   *prime=0; // Mark this used
  216.   function_type=type;
  217.   return 0; // Found ok value
  218. }
  219.       }
  220.     }
  221.   }
  222.   function_mod=max_allowed_array;
  223.   if (write_warning)
  224.     fprintf (stderr,"Fatal error when generating hash for symbolsn
  225. Didn't find suitable values for perfect hashing:n
  226. You have to edit gen_lex_hash.cc to generate a new hashing function.n
  227. You can try running gen_lex_hash with --search to find a suitable valuen
  228. Symbol array size = %dn",function_mod);
  229.   return -1;
  230. }
  231. void print_arrays()
  232. {
  233.   uint size_symbols = sizeof(symbols)/sizeof(SYMBOL);
  234.   uint size_functions = sizeof(sql_functions)/sizeof(SYMBOL);
  235.   uint size=size_symbols + size_functions;
  236.   uint i;
  237.   fprintf(stderr,"Symbols: %d  Functions: %d;  Total: %dnShifts per char: %d,  Array size: %dn",
  238.   size_symbols,size_functions,size_symbols+size_functions,
  239.   function_plus,function_mod);
  240.   int *prva= (int*) my_alloca(sizeof(int)*function_mod);
  241.   for (i=0 ; i <= function_mod; i++)
  242.     prva[i]= max_symbol;
  243.   for (i=0;i<size;i++)
  244.   {
  245.     ulong order = tab_index_function ((i < how_long_symbols) ? symbols[i].name : sql_functions[i - how_long_symbols].name,function_plus,function_type);
  246.     order %= function_mod;
  247.     prva [order] = i;
  248.   }
  249. #ifdef USE_char_table
  250.   printf("static uint16 char_table[] = {n");
  251.   for (i=0; i < 255 ;i++) // < 255 is correct
  252.   {
  253.     printf("%u,",char_table[i]);
  254.     if (((i+1) & 15) == 0)
  255.       puts("");
  256.   }
  257.   printf("%dn};nnn",char_table[i]);
  258. #endif
  259.   printf("static uchar unique_length[] = {n");
  260.   for (i=0; i < 255 ;i++) // < 255 is correct
  261.   {
  262.     printf("%u,",unique_length[i]);
  263.     if (((i+1) & 15) == 0)
  264.       puts("");
  265.   }
  266.   printf("%dn};nnn",unique_length[i]);
  267.   printf("static uint16 my_function_table[] = {n");
  268.   for (i=0; i < function_mod-1 ;i++)
  269.   {
  270.     printf("%d,",prva[i]);
  271.     if (((i+1) % 12) == 0)
  272.       puts("");
  273.   }
  274.   printf("%dn};nnn",prva[i]);
  275.   my_afree((gptr) prva);
  276. }
  277. static struct option long_options[] =
  278. {
  279.   {"count",     required_argument,    0, 'c'},
  280.   {"search",     no_argument,    0, 'S'},
  281.   {"verbose",     no_argument,    0, 'v'},
  282.   {"version",     no_argument,    0, 'V'},
  283.   {"rnd1",     required_argument,    0, 'r'},
  284.   {"rnd2",     required_argument,    0, 'R'},
  285.   {"type",     required_argument,    0, 't'},
  286.   {0, 0, 0, 0}
  287. };
  288. static void usage(int version)
  289. {
  290.   printf("%s  Ver 3.2 Distrib %s, for %s (%s)n",
  291.  my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
  292.   if (version)
  293.     return;
  294.   puts("Copyright (C) 2000 MySQL AB & MySQL Finland AB, by Sinisa and Monty");
  295.   puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,nand you are welcome to modify and redistribute it under the GPL licensen");
  296.   puts("This program generates a perfect hashing function for the sql_lex.cc");
  297.   printf("Usage: %s [OPTIONS]n", my_progname);
  298.   printf("n
  299. -c, --count=# Try count times to find a optimal hash tablen
  300. -r, --rnd1=# Set 1 part of rnd value for hash generatorn
  301. -R, --rnd2=# Set 2 part of rnd value for hash generatorn
  302. -t, --type=# Set type of char table to generaten
  303. -S, --search Search after good rnd1 and rnd2 valuesn
  304. -v, --verbose Write some information while the program executesn
  305. -V, --version Output version information and exitn");
  306. }
  307. static uint best_type;
  308. static ulong best_t1,best_t2, best_start_value;
  309. static int get_options(int argc, char **argv)
  310. {
  311.   int c,option_index=0;
  312.   while ((c=getopt_long(argc,argv,"?SvVc:r:R:t:",
  313. long_options, &option_index)) != EOF)
  314.   {
  315.     switch(c) {
  316.     case 'c':
  317.       opt_count=atol(optarg);
  318.       break;
  319.     case 'r':
  320.       best_t1=atol(optarg);
  321.       break;
  322.     case 'R':
  323.       best_t2=atol(optarg);
  324.       break;
  325.     case 't':
  326.       best_type=atoi(optarg);
  327.       break;
  328.     case 'S':
  329.       opt_search=1;
  330.       break;
  331.     case 'v':
  332.       opt_verbose=1;
  333.       break;
  334.     case 'V': usage(1); exit(0);
  335.     case 'I':
  336.     case '?':
  337.       usage(0);
  338.       exit(0);
  339.     default:
  340.       fprintf(stderr,"illegal option: -%cn",opterr);
  341.       usage(0);
  342.       exit(1);
  343.     }
  344.   }
  345.   argc-=optind;
  346.   argv+=optind;
  347.   if (argc >= 1)
  348.   {
  349.     usage(0);
  350.      exit(1);
  351.   }
  352.   return(0);
  353. }
  354. static uint max_prefix(const char *name)
  355. {
  356.   uint i;
  357.   uint max_length=1;
  358.   for (i=0 ; i < sizeof(symbols)/sizeof(SYMBOL) ; i++)
  359.   {
  360.     const char *str=symbols[i].name;
  361.     if (str != name)
  362.     {
  363.       const char *str2=name;
  364.       uint length;
  365.       while (*str && *str == *str2)
  366.       {
  367. str++;
  368. str2++;
  369.       }
  370.       length=(uint) (str2 - name)+1;
  371.       if (length > max_length)
  372. max_length=length;
  373.     }
  374.   }
  375.   for (i=0 ; i < sizeof(sql_functions)/sizeof(SYMBOL) ; i++)
  376.   {
  377.     const char *str=sql_functions[i].name;
  378.     if (str != name)
  379.     {
  380.       const char *str2=name;
  381.       uint length;
  382.       while (*str && *str == *str2)
  383.       {
  384. str++;
  385. str2++;
  386.       }
  387.       length=(uint) (str2 - name)+1;
  388.       if (length > max_length)
  389. max_length=length;
  390.     }
  391.   }
  392.   return max_length;
  393. }
  394. static void make_max_length_table(void)
  395. {
  396.   uint i;
  397.   for (i=0 ; i < sizeof(symbols)/sizeof(SYMBOL) ; i++)
  398.   {
  399.     uint length=max_prefix(symbols[i].name);
  400.     if (length > unique_length[(uchar) symbols[i].name[0]])
  401.     {
  402.       unique_length[(uchar) symbols[i].name[0]]=length;
  403.       unique_length[(uchar) tolower(symbols[i].name[0])]=length;
  404.     }
  405.   }
  406.   for (i=0 ; i < sizeof(sql_functions)/sizeof(SYMBOL) ; i++)
  407.   {
  408.     uint length=max_prefix(sql_functions[i].name);
  409.     if (length > unique_length[(uchar) sql_functions[i].name[0]])
  410.     {
  411.       unique_length[(uchar) sql_functions[i].name[0]]=length;
  412.       unique_length[(uchar) tolower(sql_functions[i].name[0])]=length;
  413.     }
  414.   }
  415. }
  416. int main(int argc,char **argv)
  417. {
  418.   struct rand_struct rand_st;
  419.   static uint best_mod,best_add,best_functype;
  420.   int error;
  421.   MY_INIT(argv[0]);
  422.  start_value=5315771L; best_t1=6916833L;  best_t2=3813748L;  best_type=3; /* mode=5839  add=5  type: 0 */
  423.  if (get_options(argc,(char **) argv))
  424.     exit(1);
  425.   make_max_length_table();
  426.   make_char_table(best_t1,best_t2,best_type);
  427.   make_prime_array(sizeof(symbols)/sizeof(SYMBOL) +
  428.    sizeof(sql_functions)/sizeof(SYMBOL));
  429.   if ((error=search(1)) > 0 || error && !opt_search)
  430.     exit(1); // This should work
  431.   best_mod=function_mod; best_add=function_plus; best_functype=function_type;
  432.   if (opt_search)
  433.   {
  434.     time_t start_time=time((time_t*) 0);
  435.     randominit(&rand_st,start_time,start_time/2); // Some random values
  436.     printf("start_value=%ldL;  best_t1=%ldL;  best_t2=%ldL;  best_type=%d; /* mode=%d  add=%d type: %d */n",
  437.    start_value, best_t1,best_t2,best_type,best_mod,best_add,
  438.    best_functype);
  439.     for (uint i=1 ; i <= opt_count ; i++)
  440.     {
  441.       if (i % 10 == 0)
  442.       {
  443. putchar('.');
  444. fflush(stdout);
  445.       }
  446.       ulong t1=(ulong) (rnd(&rand_st)*INT_MAX24);
  447.       ulong t2=(ulong) (rnd(&rand_st)*INT_MAX24);
  448.       uint type=(int) (rnd(&rand_st)*char_table_count);
  449.       start_value=(ulong) (rnd(&rand_st)*INT_MAX24);
  450.       make_char_table(t1,t2,type);
  451.       if (!search(0))
  452.       {
  453. best_mod=function_mod; best_add=function_plus;
  454. best_functype=function_type;
  455. best_t1=t1; best_t2=t2; best_type=type;
  456. best_start_value=start_value;
  457. printf("nstart_value=%ldL; best_t1=%ldL;  best_t2=%ldL;  best_type=%d; /* mode=%d  add=%d  type: %d */n",
  458.        best_start_value,best_t1,best_t2,best_type,best_mod,best_add,
  459.        best_functype);
  460.       }
  461.     }
  462.   }
  463.   function_mod=best_mod; function_plus=best_add;
  464.   make_char_table(best_t1,best_t2,best_type);
  465.   printf("/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult ABn
  466.    This program is free software; you can redistribute it and/or modifyn
  467.    it under the terms of the GNU General Public License as published byn
  468.    the Free Software Foundation; either version 2 of the License, orn
  469.    (at your option) any later version.nn
  470.    This program is distributed in the hope that it will be useful,n
  471.    but WITHOUT ANY WARRANTY; without even the implied warranty ofn
  472.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See then
  473.    GNU General Public License for more details.nn
  474.    You should have received a copy of the GNU General Public Licensen
  475.    along with this program; if not, write to the Free Softwaren
  476.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */nn");
  477. printf("/* This code is generated by gen_lex_hash.cc that seeks for a perfectnhash function */nn");
  478.   printf("#include "lex.h"nn");
  479.   print_arrays();
  480.   printf("/* start_value=%ldL;  best_t1=%ldL;  best_t2=%ldL;  best_type=%d; */ /* mode=%d  add=%d  type: %d */nn",
  481.  best_start_value, best_t1, best_t2, best_type,
  482.  best_mod, best_add, best_functype);
  483.   printf("inline SYMBOL *get_hash_symbol(const char *s,unsigned int length,bool function)n
  484. {n
  485.   ulong idx = %lu+char_table[(uchar) *s];n
  486.   SYMBOL *sim;n
  487.   const char *start=s;n
  488.   int i=unique_length[(uchar) *s++];n
  489.   if (i > (int) length) i=(int) length;n
  490.   while (--i > 0)n
  491.     idx= (idx ^ (char_table[(uchar) *s++] + (idx << %d)));n
  492.   idx=my_function_table[(idx & %d) %% %d];n
  493.   if (idx >= %d)n
  494.   {n
  495.     if (!function || idx >= %d) return (SYMBOL*) 0;n
  496.     sim=sql_functions + (idx - %d);n
  497.   }n
  498.   elsen
  499.     sim=symbols + idx;n
  500.   if ((length != sim->length) || lex_casecmp(start,sim->name,length))n
  501.     return  (SYMBOL *)0;n
  502.   return sim;n
  503. }n",(ulong) start_value,(int) function_plus,(int) how_much_and,function_mod,how_long_symbols,max_symbol,how_long_symbols);
  504.   exit(0);
  505.   return 0;
  506. }