2 * Generator of Word Recognition Hash Tables
3 * (a.k.a. simple gperf replacement)
5 * (c) 1999 Martin Mares <mj@ucw.cz>
19 static unsigned int hash(char *c)
27 static int /* Sequential search */
28 fast_isprime(unsigned x) /* We know x != 2 && x != 3 */
48 nextprime(unsigned x) /* Returns some prime greater than X */
52 x += 5 - (x % 6); /* x is 6k-1 */
64 int main(int argc, char **argv)
67 struct word *words = NULL;
69 char buf[1024], *c, namebuf[256];
75 fprintf(stderr, "Usage: genhash <input> <output> <func_name>\n");
78 fi = fopen(argv[1], "r");
79 if (!fi) { fprintf(stderr, "Cannot open input file: %m\n"); return 1; }
80 fo = fopen(argv[2], "w");
81 if (!fo) { fprintf(stderr, "Cannot open output file: %m\n"); return 1; }
84 fgets(buf, sizeof(buf)-1, fi);
85 if (strncmp(buf, "%{", 2)) { fprintf(stderr, "Syntax error at <%s>\n", buf); return 1; }
87 while (fgets(buf, sizeof(buf)-1, fi) && strcmp(buf, "%}\n"))
89 fgets(namebuf, sizeof(namebuf)-1, fi);
90 if (strncmp(namebuf, "struct ", 7) || !(c = strchr(namebuf+7, ' ')))
91 { fprintf(stderr, "Syntax error at <%s>\n", namebuf); return 1; }
93 while (fgets(buf, sizeof(buf)-1, fi) && strcmp(buf, "%%\n"))
95 while (fgets(buf, sizeof(buf)-1, fi))
97 c = strchr(buf, '\n');
100 c = strchr(buf, ',');
101 w = alloca(sizeof(struct word));
105 { fprintf(stderr, "No comma?\n"); return 1; }
106 w->w = alloca(strlen(buf)+1);
108 w->extra = alloca(strlen(c)+1);
118 skip = nextprime(size*3/4);
120 ht = alloca(size * sizeof(struct word *));
121 bzero(ht, size * sizeof(struct word *));
122 for(w=words; w; w=w->next)
124 int h = hash(w->w) & (size - 1);
126 h = (h + skip) & (size - 1);
130 fprintf(fo, "static %s htable[] = {\n", namebuf);
131 for(i=0; i<size; i++)
133 fprintf(fo, "{ \"%s\", %s },\n", ht[i]->w, ht[i]->extra);
135 fprintf(fo, "{ NULL },\n");
136 fprintf(fo, "};\n\nconst %s *%s(register const char *x, register unsigned int len)\n\
138 const char *c = x;\n\
139 unsigned int h = 0;\n\
141 h = (h * 37) + *c++;\n\
143 while (htable[h].name)\n\
145 if (!strcmp(htable[h].name, x))\n\
146 return &htable[h];\n\
147 h = (h + %d) & %d;\n\
150 }\n", namebuf, argv[3], size-1, skip, size-1);