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