xref: /netbsd-src/external/mpl/bind/dist/lib/dns/gen.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
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