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