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