Home | History | Annotate | Line # | Download | only in dns
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