gen.c revision 262706
1290001Sglebius/*
2290001Sglebius * Copyright (C) 2004-2009, 2012, 2013  Internet Systems Consortium, Inc. ("ISC")
3290001Sglebius * Copyright (C) 1998-2003  Internet Software Consortium.
4290001Sglebius *
5290001Sglebius * Permission to use, copy, modify, and/or distribute this software for any
6290001Sglebius * purpose with or without fee is hereby granted, provided that the above
7290001Sglebius * copyright notice and this permission notice appear in all copies.
8290001Sglebius *
9290001Sglebius * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10290001Sglebius * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11290001Sglebius * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12290001Sglebius * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13290001Sglebius * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14290001Sglebius * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15290001Sglebius * PERFORMANCE OF THIS SOFTWARE.
16290001Sglebius */
17290001Sglebius
18290001Sglebius/*! \file */
19290001Sglebius
20290001Sglebius#ifdef WIN32
21290001Sglebius/*
22290001Sglebius * Silence compiler warnings about using strcpy and friends.
23290001Sglebius */
24290001Sglebius#define _CRT_SECURE_NO_DEPRECATE 1
25290001Sglebius/*
26290001Sglebius * We use snprintf.
27290001Sglebius */
28290001Sglebius#define snprintf _snprintf
29290001Sglebius#endif
30290001Sglebius
31290001Sglebius#include <sys/types.h>
32290001Sglebius
33290001Sglebius#include <ctype.h>
34290001Sglebius#include <stdlib.h>
35290001Sglebius#include <stdio.h>
36290001Sglebius#include <stdlib.h>
37290001Sglebius#include <string.h>
38290001Sglebius#include <time.h>
39290001Sglebius
40290001Sglebius#ifdef WIN32
41290001Sglebius#include "gen-win32.h"
42290001Sglebius#else
43290001Sglebius#include "gen-unix.h"
44290001Sglebius#endif
45290001Sglebius
46290001Sglebius#define INSIST(cond) \
47290001Sglebius	if (!(cond)) { \
48290001Sglebius		fprintf(stderr, "%s:%d: INSIST(%s)\n", \
49290001Sglebius			 __FILE__, __LINE__, #cond); \
50290001Sglebius		abort(); \
51290001Sglebius	}
52290001Sglebius
53290001Sglebius#define FROMTEXTARGS "rdclass, type, lexer, origin, options, target, callbacks"
54290001Sglebius#define FROMTEXTCLASS "rdclass"
55290001Sglebius#define FROMTEXTTYPE "type"
56290001Sglebius#define FROMTEXTDEF "result = DNS_R_UNKNOWN"
57290001Sglebius
58290001Sglebius#define TOTEXTARGS "rdata, tctx, target"
59290001Sglebius#define TOTEXTCLASS "rdata->rdclass"
60290001Sglebius#define TOTEXTTYPE "rdata->type"
61290001Sglebius#define TOTEXTDEF "use_default = ISC_TRUE"
62290001Sglebius
63290001Sglebius#define FROMWIREARGS "rdclass, type, source, dctx, options, target"
64290001Sglebius#define FROMWIRECLASS "rdclass"
65290001Sglebius#define FROMWIRETYPE "type"
66290001Sglebius#define FROMWIREDEF "use_default = ISC_TRUE"
67290001Sglebius
68290001Sglebius#define TOWIREARGS "rdata, cctx, target"
69290001Sglebius#define TOWIRECLASS "rdata->rdclass"
70290001Sglebius#define TOWIRETYPE "rdata->type"
71290001Sglebius#define TOWIREDEF "use_default = ISC_TRUE"
72290001Sglebius
73290001Sglebius#define FROMSTRUCTARGS "rdclass, type, source, target"
74290001Sglebius#define FROMSTRUCTCLASS "rdclass"
75290001Sglebius#define FROMSTRUCTTYPE "type"
76290001Sglebius#define FROMSTRUCTDEF "use_default = ISC_TRUE"
77290001Sglebius
78290001Sglebius#define TOSTRUCTARGS "rdata, target, mctx"
79290001Sglebius#define TOSTRUCTCLASS "rdata->rdclass"
80290001Sglebius#define TOSTRUCTTYPE "rdata->type"
81290001Sglebius#define TOSTRUCTDEF "use_default = ISC_TRUE"
82290001Sglebius
83290001Sglebius#define FREESTRUCTARGS "source"
84290001Sglebius#define FREESTRUCTCLASS "common->rdclass"
85290001Sglebius#define FREESTRUCTTYPE "common->rdtype"
86290001Sglebius#define FREESTRUCTDEF NULL
87290001Sglebius
88290001Sglebius#define COMPAREARGS "rdata1, rdata2"
89290001Sglebius#define COMPARECLASS "rdata1->rdclass"
90290001Sglebius#define COMPARETYPE "rdata1->type"
91290001Sglebius#define COMPAREDEF "use_default = ISC_TRUE"
92290001Sglebius
93290001Sglebius#define ADDITIONALDATAARGS "rdata, add, arg"
94290001Sglebius#define ADDITIONALDATACLASS "rdata->rdclass"
95290001Sglebius#define ADDITIONALDATATYPE "rdata->type"
96290001Sglebius#define ADDITIONALDATADEF "use_default = ISC_TRUE"
97290001Sglebius
98290001Sglebius#define DIGESTARGS "rdata, digest, arg"
99290001Sglebius#define DIGESTCLASS "rdata->rdclass"
100290001Sglebius#define DIGESTTYPE "rdata->type"
101290001Sglebius#define DIGESTDEF "use_default = ISC_TRUE"
102290001Sglebius
103290001Sglebius#define CHECKOWNERARGS "name, rdclass, type, wildcard"
104290001Sglebius#define CHECKOWNERCLASS "rdclass"
105290001Sglebius#define CHECKOWNERTYPE "type"
106290001Sglebius#define CHECKOWNERDEF "result = ISC_TRUE"
107290001Sglebius
108290001Sglebius#define CHECKNAMESARGS "rdata, owner, bad"
109290001Sglebius#define CHECKNAMESCLASS "rdata->rdclass"
110290001Sglebius#define CHECKNAMESTYPE "rdata->type"
111290001Sglebius#define CHECKNAMESDEF "result = ISC_TRUE"
112290001Sglebius
113290001Sglebiusstatic const char copyright[] =
114290001Sglebius"/*\n"
115290001Sglebius" * Copyright (C) 2004%s Internet Systems Consortium, Inc. (\"ISC\")\n"
116290001Sglebius" * Copyright (C) 1998-2003 Internet Software Consortium.\n"
117290001Sglebius" *\n"
118290001Sglebius" * Permission to use, copy, modify, and distribute this software for any\n"
119290001Sglebius" * purpose with or without fee is hereby granted, provided that the above\n"
120290001Sglebius" * copyright notice and this permission notice appear in all copies.\n"
121290001Sglebius" *\n"
122290001Sglebius" * THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n"
123290001Sglebius" * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n"
124290001Sglebius" * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n"
125290001Sglebius" * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n"
126290001Sglebius" * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n"
127290001Sglebius" * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n"
128290001Sglebius" * PERFORMANCE OF THIS SOFTWARE.\n"
129290001Sglebius" */\n"
130290001Sglebius"\n"
131290001Sglebius"/***************\n"
132290001Sglebius" ***************\n"
133290001Sglebius" ***************   THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.\n"
134290001Sglebius" ***************   DO NOT EDIT!\n"
135290001Sglebius" ***************\n"
136290001Sglebius" ***************/\n"
137290001Sglebius"\n"
138290001Sglebius"/*! \\file */\n"
139290001Sglebius"\n";
140290001Sglebius
141290001Sglebius#define STR_EXPAND(tok) #tok
142290001Sglebius#define STR(tok) STR_EXPAND(tok)
143290001Sglebius
144290001Sglebius#define TYPENAMES 256
145290001Sglebius#define TYPECLASSLEN 20		/* DNS mnemonic size. Must be less than 100. */
146290001Sglebius#define TYPECLASSBUF (TYPECLASSLEN + 1)
147290001Sglebius#define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d"
148290001Sglebius#define ATTRIBUTESIZE 256
149290001Sglebius#define DIRNAMESIZE 256
150290001Sglebius
151290001Sglebiusstatic struct cc {
152290001Sglebius	struct cc *next;
153290001Sglebius	int rdclass;
154290001Sglebius	char classname[TYPECLASSBUF];
155290001Sglebius} *classes;
156290001Sglebius
157290001Sglebiusstatic struct tt {
158290001Sglebius	struct tt *next;
159290001Sglebius	int rdclass;
160290001Sglebius	int type;
161290001Sglebius	char classname[TYPECLASSBUF];
162290001Sglebius	char typename[TYPECLASSBUF];
163290001Sglebius	char dirname[DIRNAMESIZE];	/* XXX Should be max path length */
164290001Sglebius} *types;
165290001Sglebius
166290001Sglebiusstatic struct ttnam {
167290001Sglebius	char typename[TYPECLASSBUF];
168290001Sglebius	char macroname[TYPECLASSBUF];
169290001Sglebius	char attr[ATTRIBUTESIZE];
170290001Sglebius	unsigned int sorted;
171290001Sglebius	int type;
172290001Sglebius} typenames[TYPENAMES];
173290001Sglebius
174290001Sglebiusstatic int maxtype = -1;
175290001Sglebius
176290001Sglebiusstatic char *
177290001Sglebiusupper(char *);
178290001Sglebiusstatic char *
179290001Sglebiusfunname(const char *, char *);
180290001Sglebiusstatic void
181290001Sglebiusdoswitch(const char *, const char *, const char *, const char *,
182290001Sglebius	 const char *, const char *);
183290001Sglebiusstatic void
184290001Sglebiusadd(int, const char *, int, const char *, const char *);
185290001Sglebiusstatic void
186290001Sglebiussd(int, const char *, const char *, char);
187290001Sglebiusstatic void
188290001Sglebiusinsert_into_typenames(int, const char *, const char *);
189290001Sglebius
190290001Sglebius/*%
191290001Sglebius * If you use more than 10 of these in, say, a printf(), you'll have problems.
192290001Sglebius */
193290001Sglebiusstatic char *
194290001Sglebiusupper(char *s) {
195290001Sglebius	static int buf_to_use = 0;
196290001Sglebius	static char buf[10][256];
197290001Sglebius	char *b;
198290001Sglebius	int c;
199290001Sglebius
200290001Sglebius	buf_to_use++;
201290001Sglebius	if (buf_to_use > 9)
202290001Sglebius		buf_to_use = 0;
203290001Sglebius
204290001Sglebius	b = buf[buf_to_use];
205290001Sglebius	memset(b, 0, 256);
206290001Sglebius
207290001Sglebius	while ((c = (*s++) & 0xff))
208290001Sglebius		*b++ = islower(c) ? toupper(c) : c;
209290001Sglebius	*b = '\0';
210290001Sglebius	return (buf[buf_to_use]);
211290001Sglebius}
212290001Sglebius
213290001Sglebiusstatic char *
214290001Sglebiusfunname(const char *s, char *buf) {
215290001Sglebius	char *b = buf;
216290001Sglebius	char c;
217290001Sglebius
218290001Sglebius	INSIST(strlen(s) < TYPECLASSBUF);
219290001Sglebius	while ((c = *s++)) {
220290001Sglebius		*b++ = (c == '-') ? '_' : c;
221290001Sglebius	}
222290001Sglebius	*b = '\0';
223290001Sglebius	return (buf);
224290001Sglebius}
225290001Sglebius
226290001Sglebiusstatic void
227290001Sglebiusdoswitch(const char *name, const char *function, const char *args,
228290001Sglebius	 const char *tsw, const char *csw, const char *res)
229290001Sglebius{
230290001Sglebius	struct tt *tt;
231290001Sglebius	int first = 1;
232290001Sglebius	int lasttype = 0;
233290001Sglebius	int subswitch = 0;
234290001Sglebius	char buf1[TYPECLASSBUF], buf2[TYPECLASSBUF];
235290001Sglebius	const char *result = " result =";
236290001Sglebius
237290001Sglebius	if (res == NULL)
238290001Sglebius		result = "";
239290001Sglebius
240290001Sglebius	for (tt = types; tt != NULL; tt = tt->next) {
241290001Sglebius		if (first) {
242290001Sglebius			fprintf(stdout, "\n#define %s \\\n", name);
243290001Sglebius			fprintf(stdout, "\tswitch (%s) { \\\n" /*}*/, tsw);
244290001Sglebius			first = 0;
245290001Sglebius		}
246290001Sglebius		if (tt->type != lasttype && subswitch) {
247290001Sglebius			if (res == NULL)
248290001Sglebius				fprintf(stdout, "\t\tdefault: break; \\\n");
249290001Sglebius			else
250290001Sglebius				fprintf(stdout,
251290001Sglebius					"\t\tdefault: %s; break; \\\n", res);
252290001Sglebius			fputs(/*{*/ "\t\t} \\\n", stdout);
253290001Sglebius			fputs("\t\tbreak; \\\n", stdout);
254290001Sglebius			subswitch = 0;
255290001Sglebius		}
256290001Sglebius		if (tt->rdclass && tt->type != lasttype) {
257290001Sglebius			fprintf(stdout, "\tcase %d: switch (%s) { \\\n" /*}*/,
258290001Sglebius				tt->type, csw);
259290001Sglebius			subswitch = 1;
260290001Sglebius		}
261290001Sglebius		if (tt->rdclass == 0)
262290001Sglebius			fprintf(stdout,
263290001Sglebius				"\tcase %d:%s %s_%s(%s); break;",
264290001Sglebius				tt->type, result, function,
265290001Sglebius				funname(tt->typename, buf1), args);
266290001Sglebius		else
267290001Sglebius			fprintf(stdout,
268290001Sglebius				"\t\tcase %d:%s %s_%s_%s(%s); break;",
269290001Sglebius				tt->rdclass, result, function,
270290001Sglebius				funname(tt->classname, buf1),
271290001Sglebius				funname(tt->typename, buf2), args);
272290001Sglebius		fputs(" \\\n", stdout);
273290001Sglebius		lasttype = tt->type;
274290001Sglebius	}
275290001Sglebius	if (subswitch) {
276290001Sglebius		if (res == NULL)
277290001Sglebius			fprintf(stdout, "\t\tdefault: break; \\\n");
278290001Sglebius		else
279290001Sglebius			fprintf(stdout, "\t\tdefault: %s; break; \\\n", res);
280290001Sglebius		fputs(/*{*/ "\t\t} \\\n", stdout);
281290001Sglebius		fputs("\t\tbreak; \\\n", stdout);
282290001Sglebius	}
283290001Sglebius	if (first) {
284290001Sglebius		if (res == NULL)
285290001Sglebius			fprintf(stdout, "\n#define %s\n", name);
286290001Sglebius		else
287290001Sglebius			fprintf(stdout, "\n#define %s %s;\n", name, res);
288290001Sglebius	} else {
289290001Sglebius		if (res == NULL)
290290001Sglebius			fprintf(stdout, "\tdefault: break; \\\n");
291290001Sglebius		else
292290001Sglebius			fprintf(stdout, "\tdefault: %s; break; \\\n", res);
293290001Sglebius		fputs(/*{*/ "\t}\n", stdout);
294290001Sglebius	}
295290001Sglebius}
296290001Sglebius
297290001Sglebiusstatic struct ttnam *
298290001Sglebiusfind_typename(int type) {
299290001Sglebius	int i;
300290001Sglebius
301290001Sglebius	for (i = 0; i < TYPENAMES; i++) {
302290001Sglebius		if (typenames[i].typename[0] != 0 &&
303290001Sglebius		    typenames[i].type == type)
304290001Sglebius			return (&typenames[i]);
305290001Sglebius	}
306290001Sglebius	return (NULL);
307290001Sglebius}
308290001Sglebius
309290001Sglebiusstatic void
310290001Sglebiusinsert_into_typenames(int type, const char *typename, const char *attr) {
311290001Sglebius	struct ttnam *ttn = NULL;
312290001Sglebius	size_t c;
313290001Sglebius	int i, n;
314290001Sglebius	char tmp[256];
315290001Sglebius
316290001Sglebius	INSIST(strlen(typename) < TYPECLASSBUF);
317290001Sglebius	for (i = 0; i < TYPENAMES; i++) {
318290001Sglebius		if (typenames[i].typename[0] != 0 &&
319290001Sglebius		    typenames[i].type == type &&
320290001Sglebius		    strcmp(typename, typenames[i].typename) != 0) {
321290001Sglebius			fprintf(stderr,
322290001Sglebius				"Error:  type %d has two names: %s, %s\n",
323290001Sglebius				type, typenames[i].typename, typename);
324290001Sglebius			exit(1);
325290001Sglebius		}
326290001Sglebius		if (typenames[i].typename[0] == 0 && ttn == NULL)
327290001Sglebius			ttn = &typenames[i];
328	}
329	if (ttn == NULL) {
330		fprintf(stderr, "Error: typenames array too small\n");
331		exit(1);
332	}
333
334	if (strlen(typename) > sizeof(ttn->typename) - 1) {
335		fprintf(stderr, "Error:  type name %s is too long\n",
336			typename);
337		exit(1);
338	}
339	strncpy(ttn->typename, typename, sizeof(ttn->typename));
340	ttn->type = type;
341
342	strncpy(ttn->macroname, ttn->typename, sizeof(ttn->macroname));
343	c = strlen(ttn->macroname);
344	while (c > 0) {
345		if (ttn->macroname[c - 1] == '-')
346			ttn->macroname[c - 1] = '_';
347		c--;
348	}
349
350	if (attr == NULL) {
351		n = snprintf(tmp, sizeof(tmp),
352			     "RRTYPE_%s_ATTRIBUTES", upper(ttn->macroname));
353		INSIST(n > 0 && (unsigned)n < sizeof(tmp));
354		attr = tmp;
355	}
356
357	if (ttn->attr[0] != 0 && strcmp(attr, ttn->attr) != 0) {
358		fprintf(stderr, "Error:  type %d has different attributes: "
359			"%s, %s\n", type, ttn->attr, attr);
360		exit(1);
361	}
362
363	if (strlen(attr) > sizeof(ttn->attr) - 1) {
364		fprintf(stderr, "Error:  attr (%s) [name %s] is too long\n",
365			attr, typename);
366		exit(1);
367	}
368	strncpy(ttn->attr, attr, sizeof(ttn->attr));
369	ttn->sorted = 0;
370	if (maxtype < type)
371		maxtype = type;
372}
373
374static void
375add(int rdclass, const char *classname, int type, const char *typename,
376    const char *dirname)
377{
378	struct tt *newtt = (struct tt *)malloc(sizeof(*newtt));
379	struct tt *tt, *oldtt;
380	struct cc *newcc;
381	struct cc *cc, *oldcc;
382
383	INSIST(strlen(typename) < TYPECLASSBUF);
384	INSIST(strlen(classname) < TYPECLASSBUF);
385	INSIST(strlen(dirname) < DIRNAMESIZE);
386
387	insert_into_typenames(type, typename, NULL);
388
389	if (newtt == NULL) {
390		fprintf(stderr, "malloc() failed\n");
391		exit(1);
392	}
393
394	newtt->next = NULL;
395	newtt->rdclass = rdclass;
396	newtt->type = type;
397	strncpy(newtt->classname, classname, sizeof(newtt->classname));
398	strncpy(newtt->typename, typename, sizeof(newtt->typename));
399	if (strncmp(dirname, "./", 2) == 0)
400		dirname += 2;
401	strncpy(newtt->dirname, dirname, sizeof(newtt->dirname));
402
403	tt = types;
404	oldtt = NULL;
405
406	while ((tt != NULL) && (tt->type < type)) {
407		oldtt = tt;
408		tt = tt->next;
409	}
410
411	while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) {
412		if (strcmp(tt->typename, typename) != 0)
413			exit(1);
414		oldtt = tt;
415		tt = tt->next;
416	}
417
418	if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass))
419		exit(1);
420
421	newtt->next = tt;
422	if (oldtt != NULL)
423		oldtt->next = newtt;
424	else
425		types = newtt;
426
427	/*
428	 * Do a class switch for this type.
429	 */
430	if (rdclass == 0)
431		return;
432
433	newcc = (struct cc *)malloc(sizeof(*newcc));
434	if (newcc == NULL) {
435		fprintf(stderr, "malloc() failed\n");
436		exit(1);
437	}
438	newcc->rdclass = rdclass;
439	strncpy(newcc->classname, classname, sizeof(newcc->classname));
440	cc = classes;
441	oldcc = NULL;
442
443	while ((cc != NULL) && (cc->rdclass < rdclass)) {
444		oldcc = cc;
445		cc = cc->next;
446	}
447
448	if ((cc != NULL) && cc->rdclass == rdclass) {
449		free((char *)newcc);
450		return;
451	}
452
453	newcc->next = cc;
454	if (oldcc != NULL)
455		oldcc->next = newcc;
456	else
457		classes = newcc;
458}
459
460static void
461sd(int rdclass, const char *classname, const char *dirname, char filetype) {
462	char buf[TYPECLASSLEN + sizeof("_65535.h")];
463	char typename[TYPECLASSBUF];
464	int type, n;
465	isc_dir_t dir;
466
467	if (!start_directory(dirname, &dir))
468		return;
469
470	while (next_file(&dir)) {
471		if (sscanf(dir.filename, TYPECLASSFMT, typename, &type) != 2)
472			continue;
473		if ((type > 65535) || (type < 0))
474			continue;
475
476		n = snprintf(buf, sizeof(buf), "%s_%d.%c", typename,
477			     type, filetype);
478		INSIST(n > 0 && (unsigned)n < sizeof(buf));
479		if (strcmp(buf, dir.filename) != 0)
480			continue;
481		add(rdclass, classname, type, typename, dirname);
482	}
483
484	end_directory(&dir);
485}
486
487static unsigned int
488HASH(char *string) {
489	size_t n;
490	unsigned char a, b;
491
492	n = strlen(string);
493	if (n == 0) {
494		fprintf(stderr, "n == 0?\n");
495		exit(1);
496	}
497	a = tolower((unsigned char)string[0]);
498	b = tolower((unsigned char)string[n - 1]);
499
500	return ((a + n) * b) % 256;
501}
502
503int
504main(int argc, char **argv) {
505	char buf[DIRNAMESIZE];		/* XXX Should be max path length */
506	char srcdir[DIRNAMESIZE];	/* XXX Should be max path length */
507	int rdclass;
508	char classname[TYPECLASSBUF];
509	struct tt *tt;
510	struct cc *cc;
511	struct ttnam *ttn, *ttn2;
512	unsigned int hash;
513	struct tm *tm;
514	time_t now;
515	char year[11];
516	int lasttype;
517	int code = 1;
518	int class_enum = 0;
519	int type_enum = 0;
520	int structs = 0;
521	int depend = 0;
522	int c, i, j, n;
523	char buf1[TYPECLASSBUF];
524	char filetype = 'c';
525	FILE *fd;
526	char *prefix = NULL;
527	char *suffix = NULL;
528	char *file = NULL;
529	isc_dir_t dir;
530
531	for (i = 0; i < TYPENAMES; i++)
532		memset(&typenames[i], 0, sizeof(typenames[i]));
533
534	strcpy(srcdir, "");
535	while ((c = isc_commandline_parse(argc, argv, "cdits:F:P:S:")) != -1)
536		switch (c) {
537		case 'c':
538			code = 0;
539			depend = 0;
540			type_enum = 0;
541			class_enum = 1;
542			filetype = 'c';
543			structs = 0;
544			break;
545		case 'd':
546			code = 0;
547			depend = 1;
548			class_enum = 0;
549			type_enum = 0;
550			structs = 0;
551			filetype = 'h';
552			break;
553		case 't':
554			code = 0;
555			depend = 0;
556			class_enum = 0;
557			type_enum = 1;
558			filetype = 'c';
559			structs = 0;
560			break;
561		case 'i':
562			code = 0;
563			depend = 0;
564			class_enum = 0;
565			type_enum = 0;
566			structs = 1;
567			filetype = 'h';
568			break;
569		case 's':
570			if (strlen(isc_commandline_argument) >
571			    DIRNAMESIZE - 2 * TYPECLASSLEN  -
572			    sizeof("/rdata/_65535_65535")) {
573				fprintf(stderr, "\"%s\" too long\n",
574					isc_commandline_argument);
575				exit(1);
576			}
577			n = snprintf(srcdir, sizeof(srcdir), "%s/",
578				     isc_commandline_argument);
579			INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
580			break;
581		case 'F':
582			file = isc_commandline_argument;
583			break;
584		case 'P':
585			prefix = isc_commandline_argument;
586			break;
587		case 'S':
588			suffix = isc_commandline_argument;
589			break;
590		case '?':
591			exit(1);
592		}
593
594	n = snprintf(buf, sizeof(buf), "%srdata", srcdir);
595	INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
596
597	if (!start_directory(buf, &dir))
598		exit(1);
599
600	while (next_file(&dir)) {
601		if (sscanf(dir.filename, TYPECLASSFMT, classname,
602			   &rdclass) != 2)
603			continue;
604		if ((rdclass > 65535) || (rdclass < 0))
605			continue;
606
607		n = snprintf(buf, sizeof(buf), "%srdata/%s_%d",
608			     srcdir, classname, rdclass);
609		INSIST(n > 0 && (unsigned)n < sizeof(buf));
610		if (strcmp(buf + 6 + strlen(srcdir), dir.filename) != 0)
611			continue;
612		sd(rdclass, classname, buf, filetype);
613	}
614	end_directory(&dir);
615	n = snprintf(buf, sizeof(buf), "%srdata/generic", srcdir);
616	INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
617	sd(0, "", buf, filetype);
618
619	if (time(&now) != -1) {
620		if ((tm = localtime(&now)) != NULL && tm->tm_year > 104) {
621			n = snprintf(year, sizeof(year), "-%d",
622				     tm->tm_year + 1900);
623			INSIST(n > 0 && (unsigned)n < sizeof(year));
624		} else
625			year[0] = 0;
626	} else
627		year[0] = 0;
628
629	if (!depend) fprintf(stdout, copyright, year);
630
631	if (code) {
632		fputs("#ifndef DNS_CODE_H\n", stdout);
633		fputs("#define DNS_CODE_H 1\n\n", stdout);
634
635		fputs("#include <isc/boolean.h>\n", stdout);
636		fputs("#include <isc/result.h>\n\n", stdout);
637		fputs("#include <dns/name.h>\n\n", stdout);
638
639		for (tt = types; tt != NULL; tt = tt->next)
640			fprintf(stdout, "#include \"%s/%s_%d.c\"\n",
641				tt->dirname, tt->typename, tt->type);
642
643		fputs("\n\n", stdout);
644
645		doswitch("FROMTEXTSWITCH", "fromtext", FROMTEXTARGS,
646			 FROMTEXTTYPE, FROMTEXTCLASS, FROMTEXTDEF);
647		doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS,
648			 TOTEXTTYPE, TOTEXTCLASS, TOTEXTDEF);
649		doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS,
650			 FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF);
651		doswitch("TOWIRESWITCH", "towire", TOWIREARGS,
652			 TOWIRETYPE, TOWIRECLASS, TOWIREDEF);
653		doswitch("COMPARESWITCH", "compare", COMPAREARGS,
654			  COMPARETYPE, COMPARECLASS, COMPAREDEF);
655		doswitch("CASECOMPARESWITCH", "casecompare", COMPAREARGS,
656			  COMPARETYPE, COMPARECLASS, COMPAREDEF);
657		doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS,
658			  FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF);
659		doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS,
660			  TOSTRUCTTYPE, TOSTRUCTCLASS, TOSTRUCTDEF);
661		doswitch("FREESTRUCTSWITCH", "freestruct", FREESTRUCTARGS,
662			  FREESTRUCTTYPE, FREESTRUCTCLASS, FREESTRUCTDEF);
663		doswitch("ADDITIONALDATASWITCH", "additionaldata",
664			 ADDITIONALDATAARGS, ADDITIONALDATATYPE,
665			 ADDITIONALDATACLASS, ADDITIONALDATADEF);
666		doswitch("DIGESTSWITCH", "digest",
667			 DIGESTARGS, DIGESTTYPE,
668			 DIGESTCLASS, DIGESTDEF);
669		doswitch("CHECKOWNERSWITCH", "checkowner",
670			CHECKOWNERARGS, CHECKOWNERTYPE,
671			CHECKOWNERCLASS, CHECKOWNERDEF);
672		doswitch("CHECKNAMESSWITCH", "checknames",
673			CHECKNAMESARGS, CHECKNAMESTYPE,
674			CHECKNAMESCLASS, CHECKNAMESDEF);
675
676		/*
677		 * From here down, we are processing the rdata names and
678		 * attributes.
679		 */
680
681#define PRINT_COMMA(x) (x == maxtype ? "" : ",")
682
683#define METANOTQUESTION  "DNS_RDATATYPEATTR_META | " \
684			 "DNS_RDATATYPEATTR_NOTQUESTION"
685#define METAQUESTIONONLY "DNS_RDATATYPEATTR_META | " \
686			 "DNS_RDATATYPEATTR_QUESTIONONLY"
687#define RESERVED "DNS_RDATATYPEATTR_RESERVED"
688
689		/*
690		 * Add in reserved/special types.  This will let us
691		 * sort them without special cases.
692		 */
693		insert_into_typenames(0, "reserved0", RESERVED);
694		insert_into_typenames(31, "eid", RESERVED);
695		insert_into_typenames(32, "nimloc", RESERVED);
696		insert_into_typenames(34, "atma", RESERVED);
697		insert_into_typenames(100, "uinfo", RESERVED);
698		insert_into_typenames(101, "uid", RESERVED);
699		insert_into_typenames(102, "gid", RESERVED);
700		insert_into_typenames(251, "ixfr", METAQUESTIONONLY);
701		insert_into_typenames(252, "axfr", METAQUESTIONONLY);
702		insert_into_typenames(253, "mailb", METAQUESTIONONLY);
703		insert_into_typenames(254, "maila", METAQUESTIONONLY);
704		insert_into_typenames(255, "any", METAQUESTIONONLY);
705
706		/*
707		 * Spit out a quick and dirty hash function.  Here,
708		 * we walk through the list of type names, and calculate
709		 * a hash.  This isn't perfect, but it will generate "pretty
710		 * good" estimates.  Lowercase the characters before
711		 * computing in all cases.
712		 *
713		 * Here, walk the list from top to bottom, calculating
714		 * the hash (mod 256) for each name.
715		 */
716		fprintf(stdout, "#define RDATATYPE_COMPARE(_s, _d, _tn, _n, _tp) \\\n");
717		fprintf(stdout, "\tdo { \\\n");
718		fprintf(stdout, "\t\tif (sizeof(_s) - 1 == _n && \\\n"
719				"\t\t    strncasecmp(_s,(_tn),"
720				"(sizeof(_s) - 1)) == 0) { \\\n");
721		fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & "
722				  "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
723		fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n");
724		fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n");
725		fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n");
726		fprintf(stdout, "\t\t} \\\n");
727		fprintf(stdout, "\t} while (0)\n\n");
728
729		fprintf(stdout, "#define RDATATYPE_FROMTEXT_SW(_hash,"
730				"_typename,_length,_typep) \\\n");
731		fprintf(stdout, "\tswitch (_hash) { \\\n");
732		for (i = 0; i <= maxtype; i++) {
733			ttn = find_typename(i);
734			if (ttn == NULL)
735				continue;
736
737			/*
738			 * Skip entries we already processed.
739			 */
740			if (ttn->sorted != 0)
741				continue;
742
743			hash = HASH(ttn->typename);
744			fprintf(stdout, "\t\tcase %u: \\\n", hash);
745
746			/*
747			 * Find all other entries that happen to match
748			 * this hash.
749			 */
750			for (j = 0; j <= maxtype; j++) {
751				ttn2 = find_typename(j);
752				if (ttn2 == NULL)
753					continue;
754				if (hash == HASH(ttn2->typename)) {
755					fprintf(stdout, "\t\t\tRDATATYPE_COMPARE"
756					       "(\"%s\", %u, "
757					       "_typename, _length, _typep); \\\n",
758					       ttn2->typename, ttn2->type);
759					ttn2->sorted = 1;
760				}
761			}
762			fprintf(stdout, "\t\t\tbreak; \\\n");
763		}
764		fprintf(stdout, "\t}\n");
765
766		fprintf(stdout, "#define RDATATYPE_ATTRIBUTE_SW \\\n");
767		fprintf(stdout, "\tswitch (type) { \\\n");
768		for (i = 0; i <= maxtype; i++) {
769			ttn = find_typename(i);
770			if (ttn == NULL)
771				continue;
772			fprintf(stdout, "\tcase %u: return (%s); \\\n",
773				i, upper(ttn->attr));
774		}
775		fprintf(stdout, "\t}\n");
776
777		fprintf(stdout, "#define RDATATYPE_TOTEXT_SW \\\n");
778		fprintf(stdout, "\tswitch (type) { \\\n");
779		for (i = 0; i <= maxtype; i++) {
780			ttn = find_typename(i);
781			if (ttn == NULL)
782				continue;
783			/*
784			 * Remove KEYDATA (65533) from the type to memonic
785			 * translation as it is internal use only.  This
786			 * stops the tools from displaying KEYDATA instead
787			 * of TYPE65533.
788			 */
789			if (i == 65533U)
790				continue;
791			fprintf(stdout, "\tcase %u: return "
792				"(str_totext(\"%s\", target)); \\\n",
793				i, upper(ttn->typename));
794		}
795		fprintf(stdout, "\t}\n");
796
797		fputs("#endif /* DNS_CODE_H */\n", stdout);
798	} else if (type_enum) {
799		char *s;
800
801		fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n");
802		fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n");
803
804		fprintf(stdout, "enum {\n");
805		fprintf(stdout, "\tdns_rdatatype_none = 0,\n");
806
807		lasttype = 0;
808		for (tt = types; tt != NULL; tt = tt->next)
809			if (tt->type != lasttype)
810				fprintf(stdout,
811					"\tdns_rdatatype_%s = %d,\n",
812					funname(tt->typename, buf1),
813					lasttype = tt->type);
814
815		fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n");
816		fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n");
817		fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n");
818		fprintf(stdout, "\tdns_rdatatype_maila = 254,\n");
819		fprintf(stdout, "\tdns_rdatatype_any = 255\n");
820
821		fprintf(stdout, "};\n\n");
822
823		fprintf(stdout, "#define dns_rdatatype_none\t"
824			"((dns_rdatatype_t)dns_rdatatype_none)\n");
825
826		for (tt = types; tt != NULL; tt = tt->next)
827			if (tt->type != lasttype) {
828				s = funname(tt->typename, buf1);
829				fprintf(stdout,
830					"#define dns_rdatatype_%s\t%s"
831					"((dns_rdatatype_t)dns_rdatatype_%s)"
832					"\n",
833					s, strlen(s) < 2U ? "\t" : "", s);
834				lasttype = tt->type;
835			}
836
837		fprintf(stdout, "#define dns_rdatatype_ixfr\t"
838			"((dns_rdatatype_t)dns_rdatatype_ixfr)\n");
839		fprintf(stdout, "#define dns_rdatatype_axfr\t"
840			"((dns_rdatatype_t)dns_rdatatype_axfr)\n");
841		fprintf(stdout, "#define dns_rdatatype_mailb\t"
842			"((dns_rdatatype_t)dns_rdatatype_mailb)\n");
843		fprintf(stdout, "#define dns_rdatatype_maila\t"
844			"((dns_rdatatype_t)dns_rdatatype_maila)\n");
845		fprintf(stdout, "#define dns_rdatatype_any\t"
846			"((dns_rdatatype_t)dns_rdatatype_any)\n");
847
848		fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n");
849
850	} else if (class_enum) {
851		char *s;
852		int classnum;
853
854		fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n");
855		fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n");
856
857		fprintf(stdout, "enum {\n");
858
859		fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n");
860		fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t"
861			"((dns_rdataclass_t)dns_rdataclass_reserved0)\n");
862
863#define PRINTCLASS(name, num) \
864	do { \
865		s = funname(name, buf1); \
866		classnum = num; \
867		fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \
868		       classnum != 255 ? "," : ""); \
869		fprintf(stdout, "#define dns_rdataclass_%s\t" \
870		       "((dns_rdataclass_t)dns_rdataclass_%s)\n", s, s); \
871	} while (0)
872
873		for (cc = classes; cc != NULL; cc = cc->next) {
874			if (cc->rdclass == 3)
875				PRINTCLASS("chaos", 3);
876			else if (cc->rdclass == 255)
877				PRINTCLASS("none", 254);
878			PRINTCLASS(cc->classname, cc->rdclass);
879		}
880
881#undef PRINTCLASS
882
883		fprintf(stdout, "};\n\n");
884		fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n");
885	} else if (structs) {
886		if (prefix != NULL) {
887			if ((fd = fopen(prefix,"r")) != NULL) {
888				while (fgets(buf, sizeof(buf), fd) != NULL)
889					fputs(buf, stdout);
890				fclose(fd);
891			}
892		}
893		for (tt = types; tt != NULL; tt = tt->next) {
894			snprintf(buf, sizeof(buf), "%s/%s_%d.h",
895				tt->dirname, tt->typename, tt->type);
896			if ((fd = fopen(buf,"r")) != NULL) {
897				while (fgets(buf, sizeof(buf), fd) != NULL)
898					fputs(buf, stdout);
899				fclose(fd);
900			}
901		}
902		if (suffix != NULL) {
903			if ((fd = fopen(suffix,"r")) != NULL) {
904				while (fgets(buf, sizeof(buf), fd) != NULL)
905					fputs(buf, stdout);
906				fclose(fd);
907			}
908		}
909	} else if (depend) {
910		for (tt = types; tt != NULL; tt = tt->next)
911			fprintf(stdout, "%s:\t%s/%s_%d.h\n", file,
912				tt->dirname, tt->typename, tt->type);
913	}
914
915	if (ferror(stdout) != 0)
916		exit(1);
917
918	return (0);
919}
920