Import of bind-9.3.2-P1
[dragonfly.git] / contrib / bind-9.3 / lib / dns / gen.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: gen.c,v 1.65.2.5.2.6 2004/03/15 01:02:54 marka Exp $ */
19
20 #include <config.h>
21
22 #include <sys/types.h>
23
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30
31 #ifdef WIN32
32 #include "gen-win32.h"
33 #else
34 #include "gen-unix.h"
35 #endif
36
37 #define FROMTEXTARGS "rdclass, type, lexer, origin, options, target, callbacks"
38 #define FROMTEXTCLASS "rdclass"
39 #define FROMTEXTTYPE "type"
40 #define FROMTEXTDEF "result = DNS_R_UNKNOWN"
41
42 #define TOTEXTARGS "rdata, tctx, target"
43 #define TOTEXTCLASS "rdata->rdclass"
44 #define TOTEXTTYPE "rdata->type"
45 #define TOTEXTDEF "use_default = ISC_TRUE"
46
47 #define FROMWIREARGS "rdclass, type, source, dctx, options, target"
48 #define FROMWIRECLASS "rdclass"
49 #define FROMWIRETYPE "type"
50 #define FROMWIREDEF "use_default = ISC_TRUE"
51
52 #define TOWIREARGS "rdata, cctx, target"
53 #define TOWIRECLASS "rdata->rdclass"
54 #define TOWIRETYPE "rdata->type"
55 #define TOWIREDEF "use_default = ISC_TRUE"
56
57 #define FROMSTRUCTARGS "rdclass, type, source, target"
58 #define FROMSTRUCTCLASS "rdclass"
59 #define FROMSTRUCTTYPE "type"
60 #define FROMSTRUCTDEF "use_default = ISC_TRUE"
61
62 #define TOSTRUCTARGS "rdata, target, mctx"
63 #define TOSTRUCTCLASS "rdata->rdclass"
64 #define TOSTRUCTTYPE "rdata->type"
65 #define TOSTRUCTDEF "use_default = ISC_TRUE"
66
67 #define FREESTRUCTARGS "source"
68 #define FREESTRUCTCLASS "common->rdclass"
69 #define FREESTRUCTTYPE "common->rdtype"
70 #define FREESTRUCTDEF NULL
71
72 #define COMPAREARGS "rdata1, rdata2"
73 #define COMPARECLASS "rdata1->rdclass"
74 #define COMPARETYPE "rdata1->type"
75 #define COMPAREDEF "use_default = ISC_TRUE"
76
77 #define ADDITIONALDATAARGS "rdata, add, arg"
78 #define ADDITIONALDATACLASS "rdata->rdclass"
79 #define ADDITIONALDATATYPE "rdata->type"
80 #define ADDITIONALDATADEF "use_default = ISC_TRUE"
81
82 #define DIGESTARGS "rdata, digest, arg"
83 #define DIGESTCLASS "rdata->rdclass"
84 #define DIGESTTYPE "rdata->type"
85 #define DIGESTDEF "use_default = ISC_TRUE"
86
87 #define CHECKOWNERARGS "name, rdclass, type, wildcard"
88 #define CHECKOWNERCLASS "rdclass"
89 #define CHECKOWNERTYPE "type"
90 #define CHECKOWNERDEF "result = ISC_TRUE"
91
92 #define CHECKNAMESARGS "rdata, owner, bad"
93 #define CHECKNAMESCLASS "rdata->rdclass"
94 #define CHECKNAMESTYPE "rdata->type"
95 #define CHECKNAMESDEF "result = ISC_TRUE"
96
97 const char copyright[] =
98 "/*\n"
99 " * Copyright (C) 2004%s Internet Systems Consortium, Inc. (\"ISC\")\n"
100 " * Copyright (C) 1998-2003 Internet Software Consortium.\n"
101 " *\n"
102 " * Permission to use, copy, modify, and distribute this software for any\n"
103 " * purpose with or without fee is hereby granted, provided that the above\n"
104 " * copyright notice and this permission notice appear in all copies.\n"
105 " *\n"
106 " * THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n"
107 " * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n"
108 " * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n"
109 " * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n"
110 " * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n"
111 " * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n"
112 " * PERFORMANCE OF THIS SOFTWARE.\n"
113 " */\n"
114 "\n"
115 "/***************\n"
116 " ***************\n"
117 " ***************   THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.\n"
118 " ***************   DO NOT EDIT!\n"
119 " ***************\n"
120 " ***************/\n"
121 "\n";
122
123 #define TYPENAMES 256
124
125 struct cc {
126         struct cc *next;
127         int rdclass;
128         char classname[11];
129 } *classes;
130
131 struct tt {
132         struct tt *next;
133         int rdclass;
134         int type;
135         char classname[11];
136         char typename[11];
137         char dirname[256];              /* XXX Should be max path length */
138 } *types;
139
140 struct ttnam {
141         char typename[11];
142         char macroname[11];
143         char attr[256];
144         unsigned int sorted;
145         int type;
146 } typenames[TYPENAMES];
147
148 int maxtype = -1;
149
150 char *
151 upper(char *);
152 char *
153 funname(const char *, char *);
154 void
155 doswitch(const char *, const char *, const char *, const char *,
156          const char *, const char *);
157 void
158 dodecl(char *, char *, char *);
159 void
160 add(int, const char *, int, const char *, const char *);
161 void
162 sd(int, const char *, const char *, char);
163 void
164 insert_into_typenames(int, const char *, const char *);
165
166 /*
167  * If you use more than 10 of these in, say, a printf(), you'll have problems.
168  */
169 char *
170 upper(char *s) {
171         static int buf_to_use = 0;
172         static char buf[10][256];
173         char *b;
174         int c;
175
176         buf_to_use++;
177         if (buf_to_use > 9)
178                 buf_to_use = 0;
179
180         b = buf[buf_to_use];
181         memset(b, 0, 256);
182
183         while ((c = (*s++) & 0xff))
184                 *b++ = islower(c) ? toupper(c) : c;
185         *b = '\0';
186         return (buf[buf_to_use]);
187 }
188
189 char *
190 funname(const char *s, char *buf) {
191         char *b = buf;
192         char c;
193
194         while ((c = *s++)) {
195                 *b++ = (c == '-') ? '_' : c;
196         }
197         *b = '\0';
198         return (buf);
199 }
200
201 void
202 doswitch(const char *name, const char *function, const char *args,
203          const char *tsw, const char *csw, const char *res)
204 {
205         struct tt *tt;
206         int first = 1;
207         int lasttype = 0;
208         int subswitch = 0;
209         char buf1[11], buf2[11];
210         const char *result = " result =";
211
212         if (res == NULL)
213                 result = "";
214
215         for (tt = types; tt != NULL; tt = tt->next) {
216                 if (first) {
217                         fprintf(stdout, "\n#define %s \\\n", name);
218                         fprintf(stdout, "\tswitch (%s) { \\\n" /*}*/, tsw);
219                         first = 0;
220                 }
221                 if (tt->type != lasttype && subswitch) {
222                         if (res == NULL)
223                                 fprintf(stdout, "\t\tdefault: break; \\\n");
224                         else
225                                 fprintf(stdout,
226                                         "\t\tdefault: %s; break; \\\n", res);
227                         fputs(/*{*/ "\t\t} \\\n", stdout);
228                         fputs("\t\tbreak; \\\n", stdout);
229                         subswitch = 0;
230                 }
231                 if (tt->rdclass && tt->type != lasttype) {
232                         fprintf(stdout, "\tcase %d: switch (%s) { \\\n" /*}*/,
233                                 tt->type, csw);
234                         subswitch = 1;
235                 }
236                 if (tt->rdclass == 0)
237                         fprintf(stdout,
238                                 "\tcase %d:%s %s_%s(%s); break;",
239                                 tt->type, result, function,
240                                 funname(tt->typename, buf1), args);
241                 else
242                         fprintf(stdout,
243                                 "\t\tcase %d:%s %s_%s_%s(%s); break;",
244                                 tt->rdclass, result, function,
245                                 funname(tt->classname, buf1),
246                                 funname(tt->typename, buf2), args);
247                 fputs(" \\\n", stdout);
248                 lasttype = tt->type;
249         }
250         if (subswitch) {
251                 if (res == NULL)
252                         fprintf(stdout, "\t\tdefault: break; \\\n");
253                 else
254                         fprintf(stdout, "\t\tdefault: %s; break; \\\n", res);
255                 fputs(/*{*/ "\t\t} \\\n", stdout);
256                 fputs("\t\tbreak; \\\n", stdout);
257         }
258         if (first) {
259                 if (res == NULL)
260                         fprintf(stdout, "\n#define %s\n", name);
261                 else
262                         fprintf(stdout, "\n#define %s %s;\n", name, res);
263         } else {
264                 if (res == NULL)
265                         fprintf(stdout, "\tdefault: break; \\\n");
266                 else
267                         fprintf(stdout, "\tdefault: %s; break; \\\n", res);
268                 fputs(/*{*/ "\t}\n", stdout);
269         }
270 }
271
272 void
273 dodecl(char *type, char *function, char *args) {
274         struct tt *tt;
275         char buf1[11], buf2[11];
276
277         fputs("\n", stdout);
278         for (tt = types; tt; tt = tt->next)
279                 if (tt->rdclass)
280                         fprintf(stdout,
281                                 "static inline %s %s_%s_%s(%s);\n",
282                                 type, function,
283                                 funname(tt->classname, buf1),
284                                 funname(tt->typename, buf2), args);
285                 else
286                         fprintf(stdout,
287                                 "static inline %s %s_%s(%s);\n",
288                                 type, function,
289                                 funname(tt->typename, buf1), args);
290 }
291
292 static struct ttnam *
293 find_typename(int type) {
294         int i;
295
296         for (i = 0; i < TYPENAMES; i++) {
297                 if (typenames[i].typename[0] != 0 &&
298                     typenames[i].type == type)
299                         return (&typenames[i]);
300         }
301         return (NULL);
302 }
303
304 void
305 insert_into_typenames(int type, const char *typename, const char *attr) {
306         struct ttnam *ttn = NULL;
307         int c, i;
308         char tmp[256];
309
310         for (i = 0; i < TYPENAMES; i++) {
311                 if (typenames[i].typename[0] != 0 &&
312                     typenames[i].type == type &&
313                     strcmp(typename, typenames[i].typename) != 0) {
314                         fprintf(stderr,
315                                 "Error:  type %d has two names: %s, %s\n",
316                                 type, typenames[i].typename, typename);
317                         exit(1);
318                 }
319                 if (typenames[i].typename[0] == 0 && ttn == NULL)
320                         ttn = &typenames[i];
321         }
322         if (ttn == NULL) {
323                 fprintf(stderr, "Error: typenames array too small\n");
324                 exit(1);
325         }
326         
327         if (strlen(typename) > sizeof(ttn->typename) - 1) {
328                 fprintf(stderr, "Error:  type name %s is too long\n",
329                         typename);
330                 exit(1);
331         }
332         strcpy(ttn->typename, typename);
333         ttn->type = type;
334
335         strcpy(ttn->macroname, ttn->typename);
336         c = strlen(ttn->macroname);
337         while (c > 0) {
338                 if (ttn->macroname[c - 1] == '-')
339                         ttn->macroname[c - 1] = '_';
340                 c--;
341         }
342
343         if (attr == NULL) {
344                 sprintf(tmp, "RRTYPE_%s_ATTRIBUTES", upper(ttn->macroname));
345                 attr = tmp;
346         }
347
348         if (ttn->attr[0] != 0 && strcmp(attr, ttn->attr) != 0) {
349                 fprintf(stderr, "Error:  type %d has different attributes: "
350                         "%s, %s\n", type, ttn->attr, attr);
351                 exit(1);
352         }
353
354         if (strlen(attr) > sizeof(ttn->attr) - 1) {
355                 fprintf(stderr, "Error:  attr (%s) [name %s] is too long\n",
356                         attr, typename);
357                 exit(1);
358         }
359         strcpy(ttn->attr, attr);
360         ttn->sorted = 0;
361         if (maxtype < type)
362                 maxtype = type;
363 }
364
365 void
366 add(int rdclass, const char *classname, int type, const char *typename,
367     const char *dirname)
368 {
369         struct tt *newtt = (struct tt *)malloc(sizeof(*newtt));
370         struct tt *tt, *oldtt;
371         struct cc *newcc;
372         struct cc *cc, *oldcc;
373
374         insert_into_typenames(type, typename, NULL);
375
376         if (newtt == NULL) {
377                 fprintf(stderr, "malloc() failed\n");
378                 exit(1);
379         }
380
381         newtt->next = NULL;
382         newtt->rdclass = rdclass;
383         newtt->type = type;
384         strcpy(newtt->classname, classname);
385         strcpy(newtt->typename, typename);
386         strcpy(newtt->dirname, dirname);
387
388         tt = types;
389         oldtt = NULL;
390
391         while ((tt != NULL) && (tt->type < type)) {
392                 oldtt = tt;
393                 tt = tt->next;
394         }
395
396         while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) {
397                 if (strcmp(tt->typename, typename) != 0)
398                         exit(1);
399                 oldtt = tt;
400                 tt = tt->next;
401         }
402
403         if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass))
404                 exit(1);
405
406         newtt->next = tt;
407         if (oldtt != NULL)
408                 oldtt->next = newtt;
409         else
410                 types = newtt;
411
412         /*
413          * Do a class switch for this type.
414          */
415         if (rdclass == 0)
416                 return;
417
418         newcc = (struct cc *)malloc(sizeof(*newcc));
419         newcc->rdclass = rdclass;
420         strcpy(newcc->classname, classname);
421         cc = classes;
422         oldcc = NULL;
423
424         while ((cc != NULL) && (cc->rdclass < rdclass)) {
425                 oldcc = cc;
426                 cc = cc->next;
427         }
428
429         if ((cc != NULL) && cc->rdclass == rdclass) {
430                 free((char *)newcc);
431                 return;
432         }
433
434         newcc->next = cc;
435         if (oldcc != NULL)
436                 oldcc->next = newcc;
437         else
438                 classes = newcc;
439 }
440
441 void
442 sd(int rdclass, const char *classname, const char *dirname, char filetype) {
443         char buf[sizeof("0123456789_65535.h")];
444         char fmt[sizeof("%10[-0-9a-z]_%d.h")];
445         int type;
446         char typename[11];
447         isc_dir_t dir;
448
449         if (!start_directory(dirname, &dir))
450                 return;
451
452         sprintf(fmt,"%s%c", "%10[-0-9a-z]_%d.", filetype);
453         while (next_file(&dir)) {
454                 if (sscanf(dir.filename, fmt, typename, &type) != 2)
455                         continue;
456                 if ((type > 65535) || (type < 0))
457                         continue;
458
459                 sprintf(buf, "%s_%d.%c", typename, type, filetype);
460                 if (strcmp(buf, dir.filename) != 0)
461                         continue;
462                 add(rdclass, classname, type, typename, dirname);
463         }
464
465         end_directory(&dir);
466 }
467
468 static unsigned int
469 HASH(char *string) {
470         unsigned int n;
471         unsigned char a, b;
472
473         n = strlen(string);
474         if (n == 0) {
475                 fprintf(stderr, "n == 0?\n");
476                 exit(1);
477         }
478         a = tolower((unsigned char)string[0]);
479         b = tolower((unsigned char)string[n - 1]);
480
481         return ((a + n) * b) % 256;
482 }
483
484 int
485 main(int argc, char **argv) {
486         char buf[256];                  /* XXX Should be max path length */
487         char srcdir[256];               /* XXX Should be max path length */
488         int rdclass;
489         char classname[11];
490         struct tt *tt;
491         struct cc *cc;
492         struct ttnam *ttn, *ttn2;
493         unsigned int hash;
494         struct tm *tm;
495         time_t now;
496         char year[11];
497         int lasttype;
498         int code = 1;
499         int class_enum = 0;
500         int type_enum = 0;
501         int structs = 0;
502         int depend = 0;
503         int c, i, j;
504         char buf1[11];
505         char filetype = 'c';
506         FILE *fd;
507         char *prefix = NULL;
508         char *suffix = NULL;
509         char *file = NULL;
510         isc_dir_t dir;
511
512         for (i = 0; i < TYPENAMES; i++)
513                 memset(&typenames[i], 0, sizeof(typenames[i]));
514
515         strcpy(srcdir, "");
516         while ((c = isc_commandline_parse(argc, argv, "cdits:F:P:S:")) != -1)
517                 switch (c) {
518                 case 'c':
519                         code = 0;
520                         depend = 0;
521                         type_enum = 0;
522                         class_enum = 1;
523                         filetype = 'c';
524                         structs = 0;
525                         break;
526                 case 'd':
527                         code = 0;
528                         depend = 1;
529                         class_enum = 0;
530                         type_enum = 0;
531                         structs = 0;
532                         filetype = 'h';
533                         break;
534                 case 't':
535                         code = 0;
536                         depend = 0;
537                         class_enum = 0;
538                         type_enum = 1;
539                         filetype = 'c';
540                         structs = 0;
541                         break;
542                 case 'i':
543                         code = 0;
544                         depend = 0;
545                         class_enum = 0;
546                         type_enum = 0;
547                         structs = 1;
548                         filetype = 'h';
549                         break;
550                 case 's':
551                         sprintf(srcdir, "%s/", isc_commandline_argument);
552                         break;
553                 case 'F':
554                         file = isc_commandline_argument;
555                         break;
556                 case 'P':
557                         prefix = isc_commandline_argument;
558                         break;
559                 case 'S':
560                         suffix = isc_commandline_argument;
561                         break;
562                 case '?':
563                         exit(1);
564                 }
565
566         sprintf(buf, "%srdata", srcdir);
567
568         if (!start_directory(buf, &dir))
569                 exit(1);
570
571         while (next_file(&dir)) {
572                 if (sscanf(dir.filename, "%10[0-9a-z]_%d",
573                            classname, &rdclass) != 2)
574                         continue;
575                 if ((rdclass > 65535) || (rdclass < 0))
576                         continue;
577
578                 sprintf(buf, "%srdata/%s_%d", srcdir, classname, rdclass);
579                 if (strcmp(buf + 6 + strlen(srcdir), dir.filename) != 0)
580                         continue;
581                 sd(rdclass, classname, buf, filetype);
582         }
583         end_directory(&dir);
584         sprintf(buf, "%srdata/generic", srcdir);
585         sd(0, "", buf, filetype);
586
587         if (time(&now) != -1) {
588                 if ((tm = localtime(&now)) != NULL && tm->tm_year > 104) 
589                         sprintf(year, "-%d", tm->tm_year + 1900);
590                 else
591                         year[0] = 0;
592         } else
593                 year[0] = 0;
594
595         if (!depend) fprintf(stdout, copyright, year);
596
597         if (code) {
598                 fputs("#ifndef DNS_CODE_H\n", stdout);
599                 fputs("#define DNS_CODE_H 1\n\n", stdout);
600
601                 fputs("#include <isc/boolean.h>\n", stdout);
602                 fputs("#include <isc/result.h>\n\n", stdout);
603                 fputs("#include <dns/name.h>\n\n", stdout);
604
605                 for (tt = types; tt != NULL; tt = tt->next)
606                         fprintf(stdout, "#include \"%s/%s_%d.c\"\n",
607                                 tt->dirname, tt->typename, tt->type);
608
609                 fputs("\n\n", stdout);
610
611                 doswitch("FROMTEXTSWITCH", "fromtext", FROMTEXTARGS,
612                          FROMTEXTTYPE, FROMTEXTCLASS, FROMTEXTDEF);
613                 doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS,
614                          TOTEXTTYPE, TOTEXTCLASS, TOTEXTDEF);
615                 doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS,
616                          FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF);
617                 doswitch("TOWIRESWITCH", "towire", TOWIREARGS,
618                          TOWIRETYPE, TOWIRECLASS, TOWIREDEF);
619                 doswitch("COMPARESWITCH", "compare", COMPAREARGS,
620                           COMPARETYPE, COMPARECLASS, COMPAREDEF);
621                 doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS,
622                           FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF);
623                 doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS,
624                           TOSTRUCTTYPE, TOSTRUCTCLASS, TOSTRUCTDEF);
625                 doswitch("FREESTRUCTSWITCH", "freestruct", FREESTRUCTARGS,
626                           FREESTRUCTTYPE, FREESTRUCTCLASS, FREESTRUCTDEF);
627                 doswitch("ADDITIONALDATASWITCH", "additionaldata",
628                          ADDITIONALDATAARGS, ADDITIONALDATATYPE,
629                          ADDITIONALDATACLASS, ADDITIONALDATADEF);
630                 doswitch("DIGESTSWITCH", "digest",
631                          DIGESTARGS, DIGESTTYPE,
632                          DIGESTCLASS, DIGESTDEF);
633                 doswitch("CHECKOWNERSWITCH", "checkowner",
634                         CHECKOWNERARGS, CHECKOWNERTYPE,
635                         CHECKOWNERCLASS, CHECKOWNERDEF);
636                 doswitch("CHECKNAMESSWITCH", "checknames",
637                         CHECKNAMESARGS, CHECKNAMESTYPE,
638                         CHECKNAMESCLASS, CHECKNAMESDEF);
639
640                 /*
641                  * From here down, we are processing the rdata names and
642                  * attributes.
643                  */
644
645 #define PRINT_COMMA(x) (x == maxtype ? "" : ",")
646
647 #define METANOTQUESTION  "DNS_RDATATYPEATTR_META | " \
648                          "DNS_RDATATYPEATTR_NOTQUESTION"
649 #define METAQUESTIONONLY "DNS_RDATATYPEATTR_META | " \
650                          "DNS_RDATATYPEATTR_QUESTIONONLY"
651 #define RESERVED "DNS_RDATATYPEATTR_RESERVED"
652
653                 /*
654                  * Add in reserved/special types.  This will let us
655                  * sort them without special cases.
656                  */
657                 insert_into_typenames(0, "reserved0", RESERVED);
658                 insert_into_typenames(31, "eid", RESERVED);
659                 insert_into_typenames(32, "nimloc", RESERVED);
660                 insert_into_typenames(34, "atma", RESERVED);
661                 insert_into_typenames(100, "uinfo", RESERVED);
662                 insert_into_typenames(101, "uid", RESERVED);
663                 insert_into_typenames(102, "gid", RESERVED);
664                 insert_into_typenames(251, "ixfr", METAQUESTIONONLY);
665                 insert_into_typenames(252, "axfr", METAQUESTIONONLY);
666                 insert_into_typenames(253, "mailb", METAQUESTIONONLY);
667                 insert_into_typenames(254, "maila", METAQUESTIONONLY);
668                 insert_into_typenames(255, "any", METAQUESTIONONLY);
669
670                 /*
671                  * Spit out a quick and dirty hash function.  Here,
672                  * we walk through the list of type names, and calculate
673                  * a hash.  This isn't perfect, but it will generate "pretty
674                  * good" estimates.  Lowercase the characters before
675                  * computing in all cases.
676                  *
677                  * Here, walk the list from top to bottom, calculating
678                  * the hash (mod 256) for each name.
679                  */
680                 fprintf(stdout, "#define RDATATYPE_COMPARE(_s, _d, _tn, _n, _tp) \\\n");
681                 fprintf(stdout, "\tdo { \\\n");
682                 fprintf(stdout, "\t\tif (sizeof(_s) - 1 == _n && \\\n"
683                                 "\t\t    strncasecmp(_s,(_tn),"
684                                 "(sizeof(_s) - 1)) == 0) { \\\n");
685                 fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & "
686                                   "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
687                 fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n");
688                 fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n");
689                 fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n");
690                 fprintf(stdout, "\t\t} \\\n");
691                 fprintf(stdout, "\t} while (0)\n\n");
692
693                 fprintf(stdout, "#define RDATATYPE_FROMTEXT_SW(_hash,"
694                                 "_typename,_length,_typep) \\\n");
695                 fprintf(stdout, "\tswitch (_hash) { \\\n");
696                 for (i = 0; i <= maxtype; i++) {
697                         ttn = find_typename(i);
698                         if (ttn == NULL)
699                                 continue;
700
701                         /*
702                          * Skip entries we already processed.
703                          */
704                         if (ttn->sorted != 0)
705                                 continue;
706
707                         hash = HASH(ttn->typename);
708                         fprintf(stdout, "\t\tcase %u: \\\n", hash);
709
710                         /*
711                          * Find all other entries that happen to match
712                          * this hash.
713                          */
714                         for (j = 0; j <= maxtype; j++) {
715                                 ttn2 = find_typename(j);
716                                 if (ttn2 == NULL)
717                                         continue;
718                                 if (hash == HASH(ttn2->typename)) {
719                                         fprintf(stdout, "\t\t\tRDATATYPE_COMPARE"
720                                                "(\"%s\", %u, "
721                                                "_typename, _length, _typep); \\\n",
722                                                ttn2->typename, ttn2->type);
723                                         ttn2->sorted = 1;
724                                 }
725                         }
726                         fprintf(stdout, "\t\t\tbreak; \\\n");
727                 }
728                 fprintf(stdout, "\t}\n");
729
730                 fprintf(stdout, "#define RDATATYPE_ATTRIBUTE_SW \\\n");
731                 fprintf(stdout, "\tswitch (type) { \\\n");
732                 for (i = 0; i <= maxtype; i++) {
733                         ttn = find_typename(i);
734                         if (ttn == NULL)
735                                 continue;
736                         fprintf(stdout, "\tcase %u: return (%s); \\\n",
737                                 i, upper(ttn->attr));
738                 }
739                 fprintf(stdout, "\t}\n");
740
741                 fprintf(stdout, "#define RDATATYPE_TOTEXT_SW \\\n");
742                 fprintf(stdout, "\tswitch (type) { \\\n");
743                 for (i = 0; i <= maxtype; i++) {
744                         ttn = find_typename(i);
745                         if (ttn == NULL)
746                                 continue;
747                         fprintf(stdout, "\tcase %u: return "
748                                 "(str_totext(\"%s\", target)); \\\n",
749                                 i, upper(ttn->typename));
750                 }
751                 fprintf(stdout, "\t}\n");
752
753                 fputs("#endif /* DNS_CODE_H */\n", stdout);
754         } else if (type_enum) {
755                 char *s;
756
757                 fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n");
758                 fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n");
759
760                 fprintf(stdout, "enum {\n");
761                 fprintf(stdout, "\tdns_rdatatype_none = 0,\n");
762
763                 lasttype = 0;
764                 for (tt = types; tt != NULL; tt = tt->next)
765                         if (tt->type != lasttype)
766                                 fprintf(stdout,
767                                         "\tdns_rdatatype_%s = %d,\n",
768                                         funname(tt->typename, buf1),
769                                         lasttype = tt->type);
770
771                 fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n");
772                 fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n");
773                 fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n");
774                 fprintf(stdout, "\tdns_rdatatype_maila = 254,\n");
775                 fprintf(stdout, "\tdns_rdatatype_any = 255\n");
776
777                 fprintf(stdout, "};\n\n");
778
779                 fprintf(stdout, "#define dns_rdatatype_none\t"
780                         "((dns_rdatatype_t)dns_rdatatype_none)\n");
781
782                 for (tt = types; tt != NULL; tt = tt->next)
783                         if (tt->type != lasttype) {
784                                 s = funname(tt->typename, buf1);
785                                 fprintf(stdout,
786                                         "#define dns_rdatatype_%s\t%s"
787                                         "((dns_rdatatype_t)dns_rdatatype_%s)"
788                                         "\n",
789                                         s, strlen(s) < 2U ? "\t" : "", s);
790                                 lasttype = tt->type;
791                         }
792
793                 fprintf(stdout, "#define dns_rdatatype_ixfr\t"
794                         "((dns_rdatatype_t)dns_rdatatype_ixfr)\n");
795                 fprintf(stdout, "#define dns_rdatatype_axfr\t"
796                         "((dns_rdatatype_t)dns_rdatatype_axfr)\n");
797                 fprintf(stdout, "#define dns_rdatatype_mailb\t"
798                         "((dns_rdatatype_t)dns_rdatatype_mailb)\n");
799                 fprintf(stdout, "#define dns_rdatatype_maila\t"
800                         "((dns_rdatatype_t)dns_rdatatype_maila)\n");
801                 fprintf(stdout, "#define dns_rdatatype_any\t"
802                         "((dns_rdatatype_t)dns_rdatatype_any)\n");
803
804                 fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n");
805
806         } else if (class_enum) {
807                 char *s;
808                 int classnum;
809
810                 fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n");
811                 fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n");
812
813                 fprintf(stdout, "enum {\n");
814
815                 fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n");
816                 fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t"
817                         "((dns_rdataclass_t)dns_rdataclass_reserved0)\n");
818
819 #define PRINTCLASS(name, num) \
820         do { \
821                 s = funname(name, buf1); \
822                 classnum = num; \
823                 fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \
824                        classnum != 255 ? "," : ""); \
825                 fprintf(stdout, "#define dns_rdataclass_%s\t" \
826                        "((dns_rdataclass_t)dns_rdataclass_%s)\n", s, s); \
827         } while (0)
828
829                 for (cc = classes; cc != NULL; cc = cc->next) {
830                         if (cc->rdclass == 4) {
831                                 PRINTCLASS("ch", 3);
832                                 PRINTCLASS("chaos", 3);
833
834                         } else if (cc->rdclass == 255) {
835                                 PRINTCLASS("none", 254);
836                         }
837                         PRINTCLASS(cc->classname, cc->rdclass);
838                 }
839
840 #undef PRINTCLASS
841
842                 fprintf(stdout, "};\n\n");
843                 fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n");
844         } else if (structs) {
845                 if (prefix != NULL) {
846                         if ((fd = fopen(prefix,"r")) != NULL) {
847                                 while (fgets(buf, sizeof(buf), fd) != NULL)
848                                         fputs(buf, stdout);
849                                 fclose(fd);
850                         }
851                 }
852                 for (tt = types; tt != NULL; tt = tt->next) {
853                         sprintf(buf, "%s/%s_%d.h",
854                                 tt->dirname, tt->typename, tt->type);
855                         if ((fd = fopen(buf,"r")) != NULL) {
856                                 while (fgets(buf, sizeof(buf), fd) != NULL)
857                                         fputs(buf, stdout);
858                                 fclose(fd);
859                         }
860                 }
861                 if (suffix != NULL) {
862                         if ((fd = fopen(suffix,"r")) != NULL) {
863                                 while (fgets(buf, sizeof(buf), fd) != NULL)
864                                         fputs(buf, stdout);
865                                 fclose(fd);
866                         }
867                 }
868         } else if (depend) {
869                 for (tt = types; tt != NULL; tt = tt->next)
870                         fprintf(stdout, "%s:\t%s/%s_%d.h\n", file,
871                                 tt->dirname, tt->typename, tt->type);
872         }
873
874         if (ferror(stdout) != 0)
875                 exit(1);
876
877         return (0);
878 }