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