gen.c revision 1.8 1 /* $NetBSD: gen.c,v 1.8 2021/04/05 11:27:02 rillig 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 https://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(100, "uinfo", RESERVEDNAME);
786 insert_into_typenames(101, "uid", RESERVEDNAME);
787 insert_into_typenames(102, "gid", RESERVEDNAME);
788 insert_into_typenames(103, "unspec", RESERVEDNAME);
789 insert_into_typenames(251, "ixfr", METAQUESTIONONLY);
790 insert_into_typenames(252, "axfr", METAQUESTIONONLY);
791 insert_into_typenames(253, "mailb", METAQUESTIONONLY);
792 insert_into_typenames(254, "maila", METAQUESTIONONLY);
793 insert_into_typenames(255, "any", METAQUESTIONONLY);
794
795 /*
796 * Spit out a quick and dirty hash function. Here,
797 * we walk through the list of type names, and calculate
798 * a hash. This isn't perfect, but it will generate "pretty
799 * good" estimates. Lowercase the characters before
800 * computing in all cases.
801 *
802 * Here, walk the list from top to bottom, calculating
803 * the hash (mod 256) for each name.
804 */
805 fprintf(stdout, "#define RDATATYPE_COMPARE(_s, _d, _tn, _n, "
806 "_tp) \\\n");
807 fprintf(stdout, "\tdo { \\\n");
808 fprintf(stdout, "\t\tif (sizeof(_s) - 1 == _n && \\\n"
809 "\t\t strncasecmp(_s,(_tn),"
810 "(sizeof(_s) - 1)) == 0) { \\\n");
811 fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & "
812 "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
813 fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n");
814 fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n");
815 fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n");
816 fprintf(stdout, "\t\t} \\\n");
817 fprintf(stdout, "\t} while (/*CONSTCOND*/0)\n\n");
818
819 fprintf(stdout, "#define RDATATYPE_FROMTEXT_SW(_hash,"
820 "_typename,_length,_typep) \\\n");
821 fprintf(stdout, "\tswitch (_hash) { \\\n");
822 for (i = 0; i <= maxtype; i++) {
823 ttn = find_typename(i);
824 if (ttn == NULL) {
825 continue;
826 }
827
828 /*
829 * Skip entries we already processed.
830 */
831 if (ttn->sorted != 0) {
832 continue;
833 }
834
835 hash = HASH(ttn->typebuf);
836 fprintf(stdout, "\t\tcase %u: \\\n", hash);
837
838 /*
839 * Find all other entries that happen to match
840 * this hash.
841 */
842 for (j = 0; j <= maxtype; j++) {
843 ttn2 = find_typename(j);
844 if (ttn2 == NULL) {
845 continue;
846 }
847 if (hash == HASH(ttn2->typebuf)) {
848 fprintf(stdout,
849 "\t\t\t"
850 "RDATATYPE_COMPARE"
851 "(\"%s\", %d, _typename, "
852 " _length, _typep); \\\n",
853 ttn2->typebuf, ttn2->type);
854 ttn2->sorted = 1;
855 }
856 }
857 fprintf(stdout, "\t\t\tbreak; \\\n");
858 }
859 fprintf(stdout, "\t}\n");
860
861 fprintf(stdout, "#define RDATATYPE_ATTRIBUTE_SW \\\n");
862 fprintf(stdout, "\tswitch (type) { \\\n");
863 for (i = 0; i <= maxtype; i++) {
864 ttn = find_typename(i);
865 if (ttn == NULL) {
866 continue;
867 }
868 fprintf(stdout, "\tcase %d: return (%s); \\\n", i,
869 upper(ttn->attr));
870 }
871 fprintf(stdout, "\t}\n");
872
873 fprintf(stdout, "#define RDATATYPE_TOTEXT_SW \\\n");
874 fprintf(stdout, "\tswitch (type) { \\\n");
875 for (i = 0; i <= maxtype; i++) {
876 ttn = find_typename(i);
877 if (ttn == NULL) {
878 continue;
879 }
880 /*
881 * Remove KEYDATA (65533) from the type to memonic
882 * translation as it is internal use only. This
883 * stops the tools from displaying KEYDATA instead
884 * of TYPE65533.
885 */
886 if (i == 65533U) {
887 continue;
888 }
889 fprintf(stdout,
890 "\tcase %d: return "
891 "(str_totext(\"%s\", target)); \\\n",
892 i, upper(ttn->typebuf));
893 }
894 fprintf(stdout, "\t}\n");
895
896 fputs("#endif /* DNS_CODE_H */\n", stdout);
897 } else if (type_enum) {
898 char *s;
899
900 fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n");
901 fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n");
902
903 fprintf(stdout, "enum {\n");
904 fprintf(stdout, "\tdns_rdatatype_none = 0,\n");
905
906 lasttype = 0;
907 for (tt = types; tt != NULL; tt = tt->next) {
908 if (tt->type != lasttype) {
909 fprintf(stdout, "\tdns_rdatatype_%s = %d,\n",
910 funname(tt->typebuf, buf1),
911 lasttype = tt->type);
912 }
913 }
914
915 fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n");
916 fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n");
917 fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n");
918 fprintf(stdout, "\tdns_rdatatype_maila = 254,\n");
919 fprintf(stdout, "\tdns_rdatatype_any = 255\n");
920
921 fprintf(stdout, "};\n\n");
922
923 fprintf(stdout, "#define dns_rdatatype_none\t"
924 "((dns_rdatatype_t)dns_rdatatype_none)\n");
925
926 for (tt = types; tt != NULL; tt = tt->next) {
927 if (tt->type != lasttype) {
928 s = funname(tt->typebuf, buf1);
929 fprintf(stdout,
930 "#define dns_rdatatype_%s\t%s"
931 "((dns_rdatatype_t)dns_rdatatype_%s)"
932 "\n",
933 s, strlen(s) < 2U ? "\t" : "", s);
934 lasttype = tt->type;
935 }
936 }
937
938 fprintf(stdout, "#define dns_rdatatype_ixfr\t"
939 "((dns_rdatatype_t)dns_rdatatype_ixfr)\n");
940 fprintf(stdout, "#define dns_rdatatype_axfr\t"
941 "((dns_rdatatype_t)dns_rdatatype_axfr)\n");
942 fprintf(stdout, "#define dns_rdatatype_mailb\t"
943 "((dns_rdatatype_t)dns_rdatatype_mailb)\n");
944 fprintf(stdout, "#define dns_rdatatype_maila\t"
945 "((dns_rdatatype_t)dns_rdatatype_maila)\n");
946 fprintf(stdout, "#define dns_rdatatype_any\t"
947 "((dns_rdatatype_t)dns_rdatatype_any)\n");
948
949 fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n");
950 } else if (class_enum) {
951 char *s;
952 int classnum;
953
954 fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n");
955 fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n");
956
957 fprintf(stdout, "enum {\n");
958
959 fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n");
960 fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t"
961 "((dns_rdataclass_t)dns_rdataclass_reserved0)"
962 "\n");
963
964 #define PRINTCLASS(name, num) \
965 do { \
966 s = funname(name, buf1); \
967 classnum = num; \
968 fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \
969 classnum != 255 ? "," : ""); \
970 fprintf(stdout, \
971 "#define dns_rdataclass_%s\t" \
972 "((dns_rdataclass_t)dns_rdataclass_%s)\n", \
973 s, s); \
974 } while (0)
975
976 for (cc = classes; cc != NULL; cc = cc->next) {
977 if (cc->rdclass == 3) {
978 PRINTCLASS("chaos", 3);
979 } else if (cc->rdclass == 255) {
980 PRINTCLASS("none", 254);
981 }
982 PRINTCLASS(cc->classbuf, cc->rdclass);
983 }
984
985 #undef PRINTCLASS
986
987 fprintf(stdout, "};\n\n");
988 fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n");
989 } else if (structs) {
990 if (prefix != NULL) {
991 if ((fd = fopen(prefix, "r")) != NULL) {
992 while (fgets(buf, sizeof(buf), fd) != NULL) {
993 fputs(buf, stdout);
994 }
995 fclose(fd);
996 }
997 }
998 for (tt = types; tt != NULL; tt = tt->next) {
999 snprintf(buf, sizeof(buf), "%s/%s_%d.h", tt->dirbuf,
1000 tt->typebuf, tt->type);
1001 if ((fd = fopen(buf, "r")) != NULL) {
1002 while (fgets(buf, sizeof(buf), fd) != NULL) {
1003 fputs(buf, stdout);
1004 }
1005 fclose(fd);
1006 }
1007 }
1008 if (suffix != NULL) {
1009 if ((fd = fopen(suffix, "r")) != NULL) {
1010 while (fgets(buf, sizeof(buf), fd) != NULL) {
1011 fputs(buf, stdout);
1012 }
1013 fclose(fd);
1014 }
1015 }
1016 } else if (depend) {
1017 for (tt = types; tt != NULL; tt = tt->next) {
1018 fprintf(stdout, "%s:\t%s/%s_%d.h\n", file, tt->dirbuf,
1019 tt->typebuf, tt->type);
1020 }
1021 }
1022
1023 if (ferror(stdout) != 0) {
1024 exit(1);
1025 }
1026
1027 return (0);
1028 }
1029