MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gen_lex_hash.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software Foundation,
15  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
16 
80 #define NO_YACC_SYMBOLS
81 #include <my_global.h>
82 #include "mysql_version.h"
83 #include "lex.h"
84 #include <stdlib.h>
85 #include <stdio.h>
86 #include <string.h>
87 
88 #include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
89 
91 {
92  int first_char;
93  char last_char;
94  union{
95  hash_lex_struct *char_tails;
96  int iresult;
97  };
98  int ithis;
99 };
100 
101 hash_lex_struct *get_hash_struct_by_len(hash_lex_struct **root_by_len,
102  int len, int *max_len)
103 {
104  if (*max_len<len){
105  *root_by_len= (hash_lex_struct *)realloc((char*)*root_by_len,
106  sizeof(hash_lex_struct)*len);
107  hash_lex_struct *cur, *end= *root_by_len + len;
108  for (cur= *root_by_len + *max_len; cur<end; cur++)
109  cur->first_char= 0;
110  *max_len= len;
111  }
112  return (*root_by_len)+(len-1);
113 }
114 
115 void insert_into_hash(hash_lex_struct *root, const char *name,
116  int len_from_begin, int index, int function)
117 {
118  hash_lex_struct *end, *cur, *tails;
119 
120  if (!root->first_char)
121  {
122  root->first_char= -1;
123  root->iresult= index;
124  return;
125  }
126 
127  if (root->first_char == -1)
128  {
129  int index2= root->iresult;
130  const char *name2= (index2 < 0 ? sql_functions[-index2-1] :
131  symbols[index2]).name + len_from_begin;
132  root->first_char= (int) (uchar) name2[0];
133  root->last_char= (char) root->first_char;
134  tails= (hash_lex_struct*)malloc(sizeof(hash_lex_struct));
135  root->char_tails= tails;
136  tails->first_char= -1;
137  tails->iresult= index2;
138  }
139 
140  size_t real_size= (root->last_char-root->first_char+1);
141 
142  if (root->first_char>(*name))
143  {
144  size_t new_size= root->last_char-(*name)+1;
145  if (new_size<real_size) printf("error!!!!\n");
146  tails= root->char_tails;
147  tails= (hash_lex_struct*)realloc((char*)tails,
148  sizeof(hash_lex_struct)*new_size);
149  root->char_tails= tails;
150  memmove(tails+(new_size-real_size),tails,real_size*sizeof(hash_lex_struct));
151  end= tails + new_size - real_size;
152  for (cur= tails; cur<end; cur++)
153  cur->first_char= 0;
154  root->first_char= (int) (uchar) *name;
155  }
156 
157  if (root->last_char<(*name))
158  {
159  size_t new_size= (*name)-root->first_char+1;
160  if (new_size<real_size) printf("error!!!!\n");
161  tails= root->char_tails;
162  tails= (hash_lex_struct*)realloc((char*)tails,
163  sizeof(hash_lex_struct)*new_size);
164  root->char_tails= tails;
165  end= tails + new_size;
166  for (cur= tails+real_size; cur<end; cur++)
167  cur->first_char= 0;
168  root->last_char= (*name);
169  }
170 
171  insert_into_hash(root->char_tails+(*name)-root->first_char,
172  name+1,len_from_begin+1,index,function);
173 }
174 
175 
176 hash_lex_struct *root_by_len= 0;
177 int max_len=0;
178 
179 hash_lex_struct *root_by_len2= 0;
180 int max_len2=0;
181 
182 void insert_symbols()
183 {
184  size_t i= 0;
185  SYMBOL *cur;
186  for (cur= symbols; i<array_elements(symbols); cur++, i++){
187  hash_lex_struct *root=
188  get_hash_struct_by_len(&root_by_len,cur->length,&max_len);
189  insert_into_hash(root,cur->name,0,(uint) i,0);
190  }
191 }
192 
193 void insert_sql_functions()
194 {
195  int i= 0;
196  SYMBOL *cur;
197  for (cur= sql_functions; i < (int) array_elements(sql_functions); cur++, i++)
198  {
199  hash_lex_struct *root=
200  get_hash_struct_by_len(&root_by_len,cur->length,&max_len);
201  insert_into_hash(root,cur->name,0,-i-1,1);
202  }
203 }
204 
205 void calc_length()
206 {
207  SYMBOL *cur, *end= symbols + array_elements(symbols);
208  for (cur= symbols; cur < end; cur++)
209  cur->length=(uchar) strlen(cur->name);
210  end= sql_functions + array_elements(sql_functions);
211  for (cur= sql_functions; cur<end; cur++)
212  cur->length=(uchar) strlen(cur->name);
213 }
214 
215 void generate_find_structs()
216 {
217  root_by_len= 0;
218  max_len=0;
219 
220  insert_symbols();
221 
222  root_by_len2= root_by_len;
223  max_len2= max_len;
224 
225  root_by_len= 0;
226  max_len= 0;
227 
228  insert_symbols();
229  insert_sql_functions();
230 }
231 
232 char *hash_map= 0;
233 int size_hash_map= 0;
234 
235 void add_struct_to_map(hash_lex_struct *st)
236 {
237  st->ithis= size_hash_map/4;
238  size_hash_map+= 4;
239  hash_map= (char*)realloc((char*)hash_map,size_hash_map);
240  hash_map[size_hash_map-4]= (char) (st->first_char == -1 ? 0 :
241  st->first_char);
242  hash_map[size_hash_map-3]= (char) (st->first_char == -1 ||
243  st->first_char == 0 ? 0 : st->last_char);
244  if (st->first_char == -1)
245  {
246  hash_map[size_hash_map-2]= ((unsigned int)(int16)st->iresult)&255;
247  hash_map[size_hash_map-1]= ((unsigned int)(int16)st->iresult)>>8;
248  }
249  else if (st->first_char == 0)
250  {
251  hash_map[size_hash_map-2]= ((unsigned int)(int16)array_elements(symbols))&255;
252  hash_map[size_hash_map-1]= ((unsigned int)(int16)array_elements(symbols))>>8;
253  }
254 }
255 
256 
257 void add_structs_to_map(hash_lex_struct *st, int len)
258 {
259  hash_lex_struct *cur, *end= st+len;
260  for (cur= st; cur<end; cur++)
261  add_struct_to_map(cur);
262  for (cur= st; cur<end; cur++)
263  {
264  if (cur->first_char && cur->first_char != -1)
265  add_structs_to_map(cur->char_tails,cur->last_char-cur->first_char+1);
266  }
267 }
268 
269 void set_links(hash_lex_struct *st, int len)
270 {
271  hash_lex_struct *cur, *end= st+len;
272  for (cur= st; cur<end; cur++)
273  {
274  if (cur->first_char != 0 && cur->first_char != -1)
275  {
276  int ilink= cur->char_tails->ithis;
277  hash_map[cur->ithis*4+2]= ilink%256;
278  hash_map[cur->ithis*4+3]= ilink/256;
279  set_links(cur->char_tails,cur->last_char-cur->first_char+1);
280  }
281  }
282 }
283 
284 
285 void print_hash_map(const char *name)
286 {
287  char *cur;
288  int i;
289 
290  printf("static uchar %s[%d]= {\n",name,size_hash_map);
291  for (i=0, cur= hash_map; i<size_hash_map; i++, cur++)
292  {
293  switch(i%4){
294  case 0: case 1:
295  if (!*cur)
296  printf("0, ");
297  else
298  printf("\'%c\', ",*cur);
299  break;
300  case 2: printf("%u, ",(uint)(uchar)*cur); break;
301  case 3: printf("%u,\n",(uint)(uchar)*cur); break;
302  }
303  }
304  printf("};\n");
305 }
306 
307 
308 void print_find_structs()
309 {
310  add_structs_to_map(root_by_len,max_len);
311  set_links(root_by_len,max_len);
312  print_hash_map("sql_functions_map");
313 
314  hash_map= 0;
315  size_hash_map= 0;
316 
317  printf("\n");
318 
319  add_structs_to_map(root_by_len2,max_len2);
320  set_links(root_by_len2,max_len2);
321  print_hash_map("symbols_map");
322 }
323 
324 int check_dup_symbols(SYMBOL *s1, SYMBOL *s2)
325 {
326  if (s1->length!=s2->length || strncmp(s1->name,s2->name,s1->length))
327  return 0;
328 
329  const char *err_tmpl= "\ngen_lex_hash fatal error : \
330 Unfortunately gen_lex_hash can not generate a hash,\n since \
331 your lex.h has duplicate definition for a symbol \"%s\"\n\n";
332  printf (err_tmpl,s1->name);
333  fprintf (stderr,err_tmpl,s1->name);
334 
335  return 1;
336 }
337 
338 
339 int check_duplicates()
340 {
341  SYMBOL *cur1, *cur2, *s_end, *f_end;
342 
343  s_end= symbols + array_elements(symbols);
344  f_end= sql_functions + array_elements(sql_functions);
345 
346  for (cur1= symbols; cur1<s_end; cur1++)
347  {
348  for (cur2= cur1+1; cur2<s_end; cur2++)
349  {
350  if (check_dup_symbols(cur1,cur2))
351  return 1;
352  }
353  for (cur2= sql_functions; cur2<f_end; cur2++)
354  {
355  if (check_dup_symbols(cur1,cur2))
356  return 1;
357  }
358  }
359 
360  for (cur1= sql_functions; cur1<f_end; cur1++)
361  {
362  for (cur2= cur1+1; cur2< f_end; cur2++)
363  {
364  if (check_dup_symbols(cur1,cur2))
365  return 1;
366  }
367  }
368  return 0;
369 }
370 
371 
372 int main(int argc,char **argv)
373 {
374 
375 
376  /* Broken up to indicate that it's not advice to you, gentle reader. */
377  printf("/*\n\n Do " "not " "edit " "this " "file " "directly!\n\n*/\n");
378 
379  puts("/*");
380  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
381  puts("*/");
382 
383  /* Broken up to indicate that it's not advice to you, gentle reader. */
384  printf("/* Do " "not " "edit " "this " "file! This is generated by "
385  "gen_lex_hash.cc\nthat seeks for a perfect hash function */\n\n");
386  printf("#include \"lex.h\"\n\n");
387 
388  calc_length();
389 
390  if (check_duplicates())
391  exit(1);
392 
393  generate_find_structs();
394  print_find_structs();
395 
396  printf("\nstatic unsigned int sql_functions_max_len=%d;\n", max_len);
397  printf("\nstatic unsigned int symbols_max_len=%d;\n\n", max_len2);
398 
399  printf("\
400 static SYMBOL *get_hash_symbol(const char *s,\n\
401  unsigned int len,bool function)\n\
402 {\n\
403  register uchar *hash_map;\n\
404  register const char *cur_str= s;\n\
405 \n\
406  if (len == 0) {\n\
407  DBUG_PRINT(\"warning\", (\"get_hash_symbol() received a request for a zero-length symbol, which is probably a mistake.\"));\
408  return(NULL);\n\
409  }\n"
410 );
411 
412  printf("\
413  if (function){\n\
414  if (len>sql_functions_max_len) return 0;\n\
415  hash_map= sql_functions_map;\n\
416  register uint32 cur_struct= uint4korr(hash_map+((len-1)*4));\n\
417 \n\
418  for (;;){\n\
419  register uchar first_char= (uchar)cur_struct;\n\
420 \n\
421  if (first_char == 0)\n\
422  {\n\
423  register int16 ires= (int16)(cur_struct>>16);\n\
424  if (ires==array_elements(symbols)) return 0;\n\
425  register SYMBOL *res;\n\
426  if (ires>=0) \n\
427  res= symbols+ires;\n\
428  else\n\
429  res= sql_functions-ires-1;\n\
430  register uint count= (uint) (cur_str - s);\n\
431  return lex_casecmp(cur_str,res->name+count,len-count) ? 0 : res;\n\
432  }\n\
433 \n\
434  register uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str];\n\
435  if (cur_char<first_char) return 0;\n\
436  cur_struct>>=8;\n\
437  if (cur_char>(uchar)cur_struct) return 0;\n\
438 \n\
439  cur_struct>>=8;\n\
440  cur_struct= uint4korr(hash_map+\n\
441  (((uint16)cur_struct + cur_char - first_char)*4));\n\
442  cur_str++;\n\
443  }\n"
444 );
445 
446  printf("\
447  }else{\n\
448  if (len>symbols_max_len) return 0;\n\
449  hash_map= symbols_map;\n\
450  register uint32 cur_struct= uint4korr(hash_map+((len-1)*4));\n\
451 \n\
452  for (;;){\n\
453  register uchar first_char= (uchar)cur_struct;\n\
454 \n\
455  if (first_char==0){\n\
456  register int16 ires= (int16)(cur_struct>>16);\n\
457  if (ires==array_elements(symbols)) return 0;\n\
458  register SYMBOL *res= symbols+ires;\n\
459  register uint count= (uint) (cur_str - s);\n\
460  return lex_casecmp(cur_str,res->name+count,len-count)!=0 ? 0 : res;\n\
461  }\n\
462 \n\
463  register uchar cur_char= (uchar)to_upper_lex[(uchar)*cur_str];\n\
464  if (cur_char<first_char) return 0;\n\
465  cur_struct>>=8;\n\
466  if (cur_char>(uchar)cur_struct) return 0;\n\
467 \n\
468  cur_struct>>=8;\n\
469  cur_struct= uint4korr(hash_map+\n\
470  (((uint16)cur_struct + cur_char - first_char)*4));\n\
471  cur_str++;\n\
472  }\n\
473  }\n\
474 }\n"
475 );
476  exit(0);
477 }
478