gen.c revision 1.3
1/*	$NetBSD: gen.c,v 1.3 2019/01/09 16:55:11 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 = true"
60
61#define FROMWIREARGS "rdclass, type, source, dctx, options, target"
62#define FROMWIRECLASS "rdclass"
63#define FROMWIRETYPE "type"
64#define FROMWIREDEF "use_default = true"
65
66#define TOWIREARGS "rdata, cctx, target"
67#define TOWIRECLASS "rdata->rdclass"
68#define TOWIRETYPE "rdata->type"
69#define TOWIREDEF "use_default = true"
70
71#define FROMSTRUCTARGS "rdclass, type, source, target"
72#define FROMSTRUCTCLASS "rdclass"
73#define FROMSTRUCTTYPE "type"
74#define FROMSTRUCTDEF "use_default = true"
75
76#define TOSTRUCTARGS "rdata, target, mctx"
77#define TOSTRUCTCLASS "rdata->rdclass"
78#define TOSTRUCTTYPE "rdata->type"
79#define TOSTRUCTDEF "use_default = 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 = true"
90
91#define ADDITIONALDATAARGS "rdata, add, arg"
92#define ADDITIONALDATACLASS "rdata->rdclass"
93#define ADDITIONALDATATYPE "rdata->type"
94#define ADDITIONALDATADEF "use_default = true"
95
96#define DIGESTARGS "rdata, digest, arg"
97#define DIGESTCLASS "rdata->rdclass"
98#define DIGESTTYPE "rdata->type"
99#define DIGESTDEF "use_default = true"
100
101#define CHECKOWNERARGS "name, rdclass, type, wildcard"
102#define CHECKOWNERCLASS "rdclass"
103#define CHECKOWNERTYPE "type"
104#define CHECKOWNERDEF "result = true"
105
106#define CHECKNAMESARGS "rdata, owner, bad"
107#define CHECKNAMESCLASS "rdata->rdclass"
108#define CHECKNAMESTYPE "rdata->type"
109#define CHECKNAMESDEF "result = 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 classbuf[TYPECLASSBUF];
144} *classes;
145
146static struct tt {
147	struct tt *next;
148	int rdclass;
149	int type;
150	char classbuf[TYPECLASSBUF];
151	char typebuf[TYPECLASSBUF];
152	char dirbuf[DIRNAMESIZE-30];	/* XXX Should be max path length */
153} *types;
154
155static struct ttnam {
156	char typebuf[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->typebuf, 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->classbuf, buf1),
260				funname(tt->typebuf, 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].typebuf[0] != 0 &&
292		    typenames[i].type == type)
293		{
294			return (&typenames[i]);
295		}
296	}
297	return (NULL);
298}
299
300static void
301insert_into_typenames(int type, const char *typebuf, const char *attr) {
302	struct ttnam *ttn = NULL;
303	size_t c;
304	int i, n;
305	char tmp[256];
306
307	INSIST(strlen(typebuf) < TYPECLASSBUF);
308	for (i = 0; i < TYPENAMES; i++) {
309		if (typenames[i].typebuf[0] != 0 &&
310		    typenames[i].type == type &&
311		    strcmp(typebuf, typenames[i].typebuf) != 0)
312		{
313			fprintf(stderr,
314				"Error:  type %d has two names: %s, %s\n",
315				type, typenames[i].typebuf, typebuf);
316			exit(1);
317		}
318		if (typenames[i].typebuf[0] == 0 && ttn == NULL) {
319			ttn = &typenames[i];
320		}
321	}
322	if (ttn == NULL) {
323		fprintf(stderr, "Error: typenames array too small\n");
324		exit(1);
325	}
326
327	/* XXXMUKS: This is redundant due to the INSIST above. */
328	if (strlen(typebuf) > sizeof(ttn->typebuf) - 1) {
329		fprintf(stderr, "Error:  type name %s is too long\n",
330			typebuf);
331		exit(1);
332	}
333
334	strncpy(ttn->typebuf, typebuf, sizeof(ttn->typebuf));
335	ttn->typebuf[sizeof(ttn->typebuf) - 1] = '\0';
336
337	strncpy(ttn->macroname, ttn->typebuf, sizeof(ttn->macroname));
338	ttn->macroname[sizeof(ttn->macroname) - 1] = '\0';
339
340	ttn->type = type;
341	c = strlen(ttn->macroname);
342	while (c > 0) {
343		if (ttn->macroname[c - 1] == '-') {
344			ttn->macroname[c - 1] = '_';
345		}
346		c--;
347	}
348
349	if (attr == NULL) {
350		n = snprintf(tmp, sizeof(tmp),
351			     "RRTYPE_%s_ATTRIBUTES", upper(ttn->macroname));
352		INSIST(n > 0 && (unsigned)n < sizeof(tmp));
353		attr = tmp;
354	}
355
356	if (ttn->attr[0] != 0 && strcmp(attr, ttn->attr) != 0) {
357		fprintf(stderr, "Error:  type %d has different attributes: "
358			"%s, %s\n", type, ttn->attr, attr);
359		exit(1);
360	}
361
362	if (strlen(attr) > sizeof(ttn->attr) - 1) {
363		fprintf(stderr, "Error:  attr (%s) [name %s] is too long\n",
364			attr, typebuf);
365		exit(1);
366	}
367
368	strncpy(ttn->attr, attr, sizeof(ttn->attr));
369	ttn->attr[sizeof(ttn->attr) - 1] = '\0';
370
371	ttn->sorted = 0;
372	if (maxtype < type) {
373		maxtype = type;
374	}
375}
376
377static void
378add(int rdclass, const char *classbuf, int type, const char *typebuf,
379    const char *dirbuf)
380{
381	struct tt *newtt = (struct tt *)malloc(sizeof(*newtt));
382	struct tt *tt, *oldtt;
383	struct cc *newcc;
384	struct cc *cc, *oldcc;
385
386	INSIST(strlen(typebuf) < TYPECLASSBUF);
387	INSIST(strlen(classbuf) < TYPECLASSBUF);
388	INSIST(strlen(dirbuf) < DIRNAMESIZE);
389
390	insert_into_typenames(type, typebuf, NULL);
391
392	if (newtt == NULL) {
393		fprintf(stderr, "malloc() failed\n");
394		exit(1);
395	}
396
397	newtt->next = NULL;
398	newtt->rdclass = rdclass;
399	newtt->type = type;
400
401	strncpy(newtt->classbuf, classbuf, sizeof(newtt->classbuf));
402	newtt->classbuf[sizeof(newtt->classbuf) - 1] = '\0';
403
404	strncpy(newtt->typebuf, typebuf, sizeof(newtt->typebuf));
405	newtt->typebuf[sizeof(newtt->typebuf) - 1] = '\0';
406
407	if (strncmp(dirbuf, "./", 2) == 0) {
408		dirbuf += 2;
409	}
410	strncpy(newtt->dirbuf, dirbuf, sizeof(newtt->dirbuf));
411	newtt->dirbuf[sizeof(newtt->dirbuf) - 1] = '\0';
412
413	tt = types;
414	oldtt = NULL;
415
416	while ((tt != NULL) && (tt->type < type)) {
417		oldtt = tt;
418		tt = tt->next;
419	}
420
421	while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) {
422		if (strcmp(tt->typebuf, typebuf) != 0) {
423			exit(1);
424		}
425		oldtt = tt;
426		tt = tt->next;
427	}
428
429	if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass)) {
430		exit(1);
431	}
432
433	newtt->next = tt;
434	if (oldtt != NULL) {
435		oldtt->next = newtt;
436	} else {
437		types = newtt;
438	}
439
440	/*
441	 * Do a class switch for this type.
442	 */
443	if (rdclass == 0) {
444		return;
445	}
446
447	newcc = (struct cc *)malloc(sizeof(*newcc));
448	if (newcc == NULL) {
449		fprintf(stderr, "malloc() failed\n");
450		exit(1);
451	}
452	newcc->rdclass = rdclass;
453	strncpy(newcc->classbuf, classbuf, sizeof(newcc->classbuf));
454	newcc->classbuf[sizeof(newcc->classbuf) - 1] = '\0';
455	cc = classes;
456	oldcc = NULL;
457
458	while ((cc != NULL) && (cc->rdclass < rdclass)) {
459		oldcc = cc;
460		cc = cc->next;
461	}
462
463	if ((cc != NULL) && cc->rdclass == rdclass) {
464		free((char *)newcc);
465		return;
466	}
467
468	newcc->next = cc;
469	if (oldcc != NULL) {
470		oldcc->next = newcc;
471	} else {
472		classes = newcc;
473	}
474}
475
476static void
477sd(int rdclass, const char *classbuf, const char *dirbuf, char filetype) {
478	char buf[TYPECLASSLEN + sizeof("_65535.h")];
479	char typebuf[TYPECLASSBUF];
480	int type, n;
481	isc_dir_t dir;
482
483	if (!start_directory(dirbuf, &dir)) {
484		return;
485	}
486
487	while (next_file(&dir)) {
488		if (sscanf(dir.filename, TYPECLASSFMT, typebuf, &type) != 2) {
489			continue;
490		}
491		if ((type > 65535) || (type < 0)) {
492			continue;
493		}
494
495		n = snprintf(buf, sizeof(buf), "%s_%d.%c", typebuf,
496			     type, filetype);
497		INSIST(n > 0 && (unsigned)n < sizeof(buf));
498		if (strcmp(buf, dir.filename) != 0) {
499			continue;
500		}
501		add(rdclass, classbuf, type, typebuf, dirbuf);
502	}
503
504	end_directory(&dir);
505}
506
507static unsigned int
508HASH(char *string) {
509	size_t n;
510	unsigned char a, b;
511
512	n = strlen(string);
513	if (n == 0) {
514		fprintf(stderr, "n == 0?\n");
515		exit(1);
516	}
517	a = tolower((unsigned char)string[0]);
518	b = tolower((unsigned char)string[n - 1]);
519
520	return ((a + n) * b) % 256;
521}
522
523int
524main(int argc, char **argv) {
525	char buf[DIRNAMESIZE];		/* XXX Should be max path length */
526	char srcdir[DIRNAMESIZE];	/* XXX Should be max path length */
527	int rdclass;
528	char classbuf[TYPECLASSBUF];
529	struct tt *tt;
530	struct cc *cc;
531	struct ttnam *ttn, *ttn2;
532	unsigned int hash;
533	struct tm *tm;
534	time_t now;
535	char year[11];
536	int lasttype;
537	int code = 1;
538	int class_enum = 0;
539	int type_enum = 0;
540	int structs = 0;
541	int depend = 0;
542	int c, i, j, n;
543	char buf1[TYPECLASSBUF];
544	char filetype = 'c';
545	FILE *fd;
546	char *prefix = NULL;
547	char *suffix = NULL;
548	char *file = NULL;
549	isc_dir_t dir;
550
551	for (i = 0; i < TYPENAMES; i++)
552		memset(&typenames[i], 0, sizeof(typenames[i]));
553
554	srcdir[0] = '\0';
555	while ((c = isc_commandline_parse(argc, argv, "cdits:F:P:S:")) != -1)
556		switch (c) {
557		case 'c':
558			code = 0;
559			depend = 0;
560			type_enum = 0;
561			class_enum = 1;
562			filetype = 'c';
563			structs = 0;
564			break;
565		case 'd':
566			code = 0;
567			depend = 1;
568			class_enum = 0;
569			type_enum = 0;
570			structs = 0;
571			filetype = 'h';
572			break;
573		case 't':
574			code = 0;
575			depend = 0;
576			class_enum = 0;
577			type_enum = 1;
578			filetype = 'c';
579			structs = 0;
580			break;
581		case 'i':
582			code = 0;
583			depend = 0;
584			class_enum = 0;
585			type_enum = 0;
586			structs = 1;
587			filetype = 'h';
588			break;
589		case 's':
590			if (strlen(isc_commandline_argument) >
591			    DIRNAMESIZE - 2 * TYPECLASSLEN  -
592			    sizeof("/rdata/_65535_65535"))
593			{
594				fprintf(stderr, "\"%s\" too long\n",
595					isc_commandline_argument);
596				exit(1);
597			}
598			n = snprintf(srcdir, sizeof(srcdir), "%s/",
599				     isc_commandline_argument);
600			INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
601			break;
602		case 'F':
603			file = isc_commandline_argument;
604			break;
605		case 'P':
606			prefix = isc_commandline_argument;
607			break;
608		case 'S':
609			suffix = isc_commandline_argument;
610			break;
611		case '?':
612			exit(1);
613		}
614
615	n = snprintf(buf, sizeof(buf), "%srdata", srcdir);
616	INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
617
618	if (!start_directory(buf, &dir)) {
619		exit(1);
620	}
621
622	while (next_file(&dir)) {
623		if (sscanf(dir.filename, TYPECLASSFMT, classbuf,
624			   &rdclass) != 2)
625		{
626			continue;
627		}
628		if ((rdclass > 65535) || (rdclass < 0)) {
629			continue;
630		}
631
632		n = snprintf(buf, sizeof(buf), "%srdata/%s_%d",
633			     srcdir, classbuf, rdclass);
634		INSIST(n > 0 && (unsigned)n < sizeof(buf));
635		if (strcmp(buf + 6 + strlen(srcdir), dir.filename) != 0) {
636			continue;
637		}
638		sd(rdclass, classbuf, buf, filetype);
639	}
640	end_directory(&dir);
641	n = snprintf(buf, sizeof(buf), "%srdata/generic", srcdir);
642	INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
643	sd(0, "", buf, filetype);
644
645	if (time(&now) != -1) {
646		if ((tm = localtime(&now)) != NULL && tm->tm_year > 104) {
647			n = snprintf(year, sizeof(year), "-%d",
648				     tm->tm_year + 1900);
649			INSIST(n > 0 && (unsigned)n < sizeof(year));
650		} else {
651			snprintf(year, sizeof(year), "-2016");
652		}
653	} else {
654		snprintf(year, sizeof(year), "-2016");
655	}
656
657	if (!depend) {
658		fprintf(stdout, copyright, year);
659	}
660
661	if (code) {
662		fputs("#ifndef DNS_CODE_H\n", stdout);
663		fputs("#define DNS_CODE_H 1\n\n", stdout);
664
665		fputs("#include <stdbool.h>\n", stdout);
666		fputs("#include <isc/result.h>\n\n", stdout);
667		fputs("#include <dns/name.h>\n\n", stdout);
668
669		for (tt = types; tt != NULL; tt = tt->next) {
670			fprintf(stdout, "#include \"%s/%s_%d.c\"\n",
671				tt->dirbuf, tt->typebuf, tt->type);
672		}
673
674		fputs("\n\n", stdout);
675
676		doswitch("FROMTEXTSWITCH", "fromtext", FROMTEXTARGS,
677			 FROMTEXTTYPE, FROMTEXTCLASS, FROMTEXTDEF);
678		doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS,
679			 TOTEXTTYPE, TOTEXTCLASS, TOTEXTDEF);
680		doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS,
681			 FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF);
682		doswitch("TOWIRESWITCH", "towire", TOWIREARGS,
683			 TOWIRETYPE, TOWIRECLASS, TOWIREDEF);
684		doswitch("COMPARESWITCH", "compare", COMPAREARGS,
685			  COMPARETYPE, COMPARECLASS, COMPAREDEF);
686		doswitch("CASECOMPARESWITCH", "casecompare", COMPAREARGS,
687			  COMPARETYPE, COMPARECLASS, COMPAREDEF);
688		doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS,
689			  FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF);
690		doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS,
691			  TOSTRUCTTYPE, TOSTRUCTCLASS, TOSTRUCTDEF);
692		doswitch("FREESTRUCTSWITCH", "freestruct", FREESTRUCTARGS,
693			  FREESTRUCTTYPE, FREESTRUCTCLASS, FREESTRUCTDEF);
694		doswitch("ADDITIONALDATASWITCH", "additionaldata",
695			 ADDITIONALDATAARGS, ADDITIONALDATATYPE,
696			 ADDITIONALDATACLASS, ADDITIONALDATADEF);
697		doswitch("DIGESTSWITCH", "digest",
698			 DIGESTARGS, DIGESTTYPE,
699			 DIGESTCLASS, DIGESTDEF);
700		doswitch("CHECKOWNERSWITCH", "checkowner",
701			CHECKOWNERARGS, CHECKOWNERTYPE,
702			CHECKOWNERCLASS, CHECKOWNERDEF);
703		doswitch("CHECKNAMESSWITCH", "checknames",
704			CHECKNAMESARGS, CHECKNAMESTYPE,
705			CHECKNAMESCLASS, CHECKNAMESDEF);
706
707		/*
708		 * From here down, we are processing the rdata names and
709		 * attributes.
710		 */
711
712#define PRINT_COMMA(x) (x == maxtype ? "" : ",")
713
714#define METANOTQUESTION  "DNS_RDATATYPEATTR_META | " \
715			 "DNS_RDATATYPEATTR_NOTQUESTION"
716#define METAQUESTIONONLY "DNS_RDATATYPEATTR_META | " \
717			 "DNS_RDATATYPEATTR_QUESTIONONLY"
718#define RESERVEDNAME	 "0"
719#define RESERVED	 "DNS_RDATATYPEATTR_RESERVED"
720
721		/*
722		 * Add in reserved/special types.  This will let us
723		 * sort them without special cases.
724		 */
725		insert_into_typenames(0, "reserved0", RESERVED);
726		insert_into_typenames(100, "uinfo", RESERVEDNAME);
727		insert_into_typenames(101, "uid", RESERVEDNAME);
728		insert_into_typenames(102, "gid", RESERVEDNAME);
729		insert_into_typenames(251, "ixfr", METAQUESTIONONLY);
730		insert_into_typenames(252, "axfr", METAQUESTIONONLY);
731		insert_into_typenames(253, "mailb", METAQUESTIONONLY);
732		insert_into_typenames(254, "maila", METAQUESTIONONLY);
733		insert_into_typenames(255, "any", METAQUESTIONONLY);
734
735		/*
736		 * Spit out a quick and dirty hash function.  Here,
737		 * we walk through the list of type names, and calculate
738		 * a hash.  This isn't perfect, but it will generate "pretty
739		 * good" estimates.  Lowercase the characters before
740		 * computing in all cases.
741		 *
742		 * Here, walk the list from top to bottom, calculating
743		 * the hash (mod 256) for each name.
744		 */
745		fprintf(stdout, "#define RDATATYPE_COMPARE(_s, _d, _tn, _n, _tp) \\\n");
746		fprintf(stdout, "\tdo { \\\n");
747		fprintf(stdout, "\t\tif (sizeof(_s) - 1 == _n && \\\n"
748				"\t\t    strncasecmp(_s,(_tn),"
749				"(sizeof(_s) - 1)) == 0) { \\\n");
750		fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & "
751				  "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
752		fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n");
753		fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n");
754		fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n");
755		fprintf(stdout, "\t\t} \\\n");
756		fprintf(stdout, "\t} while (/*CONSTCOND*/0)\n\n");
757
758		fprintf(stdout, "#define RDATATYPE_FROMTEXT_SW(_hash,"
759				"_typename,_length,_typep) \\\n");
760		fprintf(stdout, "\tswitch (_hash) { \\\n");
761		for (i = 0; i <= maxtype; i++) {
762			ttn = find_typename(i);
763			if (ttn == NULL) {
764				continue;
765			}
766
767			/*
768			 * Skip entries we already processed.
769			 */
770			if (ttn->sorted != 0) {
771				continue;
772			}
773
774			hash = HASH(ttn->typebuf);
775			fprintf(stdout, "\t\tcase %u: \\\n", hash);
776
777			/*
778			 * Find all other entries that happen to match
779			 * this hash.
780			 */
781			for (j = 0; j <= maxtype; j++) {
782				ttn2 = find_typename(j);
783				if (ttn2 == NULL) {
784					continue;
785				}
786				if (hash == HASH(ttn2->typebuf)) {
787					fprintf(stdout, "\t\t\t"
788						"RDATATYPE_COMPARE"
789						"(\"%s\", %d, _typename, "
790						" _length, _typep); \\\n",
791						ttn2->typebuf, ttn2->type);
792					ttn2->sorted = 1;
793				}
794			}
795			fprintf(stdout, "\t\t\tbreak; \\\n");
796		}
797		fprintf(stdout, "\t}\n");
798
799		fprintf(stdout, "#define RDATATYPE_ATTRIBUTE_SW \\\n");
800		fprintf(stdout, "\tswitch (type) { \\\n");
801		for (i = 0; i <= maxtype; i++) {
802			ttn = find_typename(i);
803			if (ttn == NULL) {
804				continue;
805			}
806			fprintf(stdout, "\tcase %d: return (%s); \\\n",
807				i, upper(ttn->attr));
808		}
809		fprintf(stdout, "\t}\n");
810
811		fprintf(stdout, "#define RDATATYPE_TOTEXT_SW \\\n");
812		fprintf(stdout, "\tswitch (type) { \\\n");
813		for (i = 0; i <= maxtype; i++) {
814			ttn = find_typename(i);
815			if (ttn == NULL) {
816				continue;
817			}
818			/*
819			 * Remove KEYDATA (65533) from the type to memonic
820			 * translation as it is internal use only.  This
821			 * stops the tools from displaying KEYDATA instead
822			 * of TYPE65533.
823			 */
824			if (i == 65533U) {
825				continue;
826			}
827			fprintf(stdout, "\tcase %d: return "
828				"(str_totext(\"%s\", target)); \\\n",
829				i, upper(ttn->typebuf));
830		}
831		fprintf(stdout, "\t}\n");
832
833		fputs("#endif /* DNS_CODE_H */\n", stdout);
834	} else if (type_enum) {
835		char *s;
836
837		fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n");
838		fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n");
839
840		fprintf(stdout, "enum {\n");
841		fprintf(stdout, "\tdns_rdatatype_none = 0,\n");
842
843		lasttype = 0;
844		for (tt = types; tt != NULL; tt = tt->next) {
845			if (tt->type != lasttype) {
846				fprintf(stdout,
847					"\tdns_rdatatype_%s = %d,\n",
848					funname(tt->typebuf, buf1),
849					lasttype = tt->type);
850			}
851		}
852
853		fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n");
854		fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n");
855		fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n");
856		fprintf(stdout, "\tdns_rdatatype_maila = 254,\n");
857		fprintf(stdout, "\tdns_rdatatype_any = 255\n");
858
859		fprintf(stdout, "};\n\n");
860
861		fprintf(stdout, "#define dns_rdatatype_none\t"
862			"((dns_rdatatype_t)dns_rdatatype_none)\n");
863
864		for (tt = types; tt != NULL; tt = tt->next) {
865			if (tt->type != lasttype) {
866				s = funname(tt->typebuf, buf1);
867				fprintf(stdout,
868					"#define dns_rdatatype_%s\t%s"
869					"((dns_rdatatype_t)dns_rdatatype_%s)"
870					"\n",
871					s, strlen(s) < 2U ? "\t" : "", s);
872				lasttype = tt->type;
873			}
874		}
875
876		fprintf(stdout, "#define dns_rdatatype_ixfr\t"
877			"((dns_rdatatype_t)dns_rdatatype_ixfr)\n");
878		fprintf(stdout, "#define dns_rdatatype_axfr\t"
879			"((dns_rdatatype_t)dns_rdatatype_axfr)\n");
880		fprintf(stdout, "#define dns_rdatatype_mailb\t"
881			"((dns_rdatatype_t)dns_rdatatype_mailb)\n");
882		fprintf(stdout, "#define dns_rdatatype_maila\t"
883			"((dns_rdatatype_t)dns_rdatatype_maila)\n");
884		fprintf(stdout, "#define dns_rdatatype_any\t"
885			"((dns_rdatatype_t)dns_rdatatype_any)\n");
886
887		fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n");
888
889	} else if (class_enum) {
890		char *s;
891		int classnum;
892
893		fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n");
894		fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n");
895
896		fprintf(stdout, "enum {\n");
897
898		fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n");
899		fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t"
900			"((dns_rdataclass_t)dns_rdataclass_reserved0)\n");
901
902#define PRINTCLASS(name, num) \
903	do { \
904		s = funname(name, buf1); \
905		classnum = num; \
906		fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \
907		       classnum != 255 ? "," : ""); \
908		fprintf(stdout, "#define dns_rdataclass_%s\t" \
909		       "((dns_rdataclass_t)dns_rdataclass_%s)\n", s, s); \
910	} while (/*CONSTCOND*/0)
911
912		for (cc = classes; cc != NULL; cc = cc->next) {
913			if (cc->rdclass == 3) {
914				PRINTCLASS("chaos", 3);
915			} else if (cc->rdclass == 255) {
916				PRINTCLASS("none", 254);
917			}
918			PRINTCLASS(cc->classbuf, cc->rdclass);
919		}
920
921#undef PRINTCLASS
922
923		fprintf(stdout, "};\n\n");
924		fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n");
925	} else if (structs) {
926		if (prefix != NULL) {
927			if ((fd = fopen(prefix,"r")) != NULL) {
928				while (fgets(buf, sizeof(buf), fd) != NULL) {
929					fputs(buf, stdout);
930				}
931				fclose(fd);
932			}
933		}
934		for (tt = types; tt != NULL; tt = tt->next) {
935			snprintf(buf, sizeof(buf), "%s/%s_%d.h",
936				tt->dirbuf, tt->typebuf, tt->type);
937			if ((fd = fopen(buf,"r")) != NULL) {
938				while (fgets(buf, sizeof(buf), fd) != NULL) {
939					fputs(buf, stdout);
940				}
941				fclose(fd);
942			}
943		}
944		if (suffix != NULL) {
945			if ((fd = fopen(suffix,"r")) != NULL) {
946				while (fgets(buf, sizeof(buf), fd) != NULL) {
947					fputs(buf, stdout);
948				}
949				fclose(fd);
950			}
951		}
952	} else if (depend) {
953		for (tt = types; tt != NULL; tt = tt->next) {
954			fprintf(stdout, "%s:\t%s/%s_%d.h\n", file,
955				tt->dirbuf, tt->typebuf, tt->type);
956		}
957	}
958
959	if (ferror(stdout) != 0) {
960		exit(1);
961	}
962
963	return (0);
964}
965