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