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