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