#include <sys/types.h>
#include <ctype.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define INSIST(cond) \
if (!(cond)) { \
fprintf(stderr, "%s:%d: INSIST(%s)\n", \
__FILE__, __LINE__, #cond); \
abort(); \
}
#define TOTEXTARGS "rdata, tctx, target"
#define TOTEXTCLASS "rdata->rdclass"
#define TOTEXTTYPE "rdata->type"
#define TOTEXTDEF "use_default = 1"
#define FROMWIREARGS "rdclass, type, source, dctx, options, target"
#define FROMWIRECLASS "rdclass"
#define FROMWIRETYPE "type"
#define FROMWIREDEF "use_default = 1"
#define TOWIREARGS "rdata, cctx, target"
#define TOWIRECLASS "rdata->rdclass"
#define TOWIRETYPE "rdata->type"
#define TOWIREDEF "use_default = 1"
static const char copyright[] =
"/*\n"
" * Copyright (C) 2004%s Internet Systems Consortium, Inc. (\"ISC\")\n"
" * Copyright (C) 1998-2003 Internet Software Consortium.\n"
" *\n"
" * Permission to use, copy, modify, and distribute this software for any\n"
" * purpose with or without fee is hereby granted, provided that the above\n"
" * copyright notice and this permission notice appear in all copies.\n"
" *\n"
" * THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n"
" * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n"
" * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n"
" * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n"
" * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n"
" * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n"
" * PERFORMANCE OF THIS SOFTWARE.\n"
" */\n"
"\n"
"/***************\n"
" ***************\n"
" *************** THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.\n"
" *************** DO NOT EDIT!\n"
" ***************\n"
" ***************/\n"
"\n"
"/*! \\file */\n"
"\n";
#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)
#define TYPECLASSLEN 20
#define TYPECLASSBUF (TYPECLASSLEN + 1)
#define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d"
#define DIRNAMESIZE 256
static struct cc {
struct cc *next;
int rdclass;
char classname[TYPECLASSBUF];
} *classes;
static struct tt {
struct tt *next;
int rdclass;
int type;
char classname[TYPECLASSBUF];
char typename[TYPECLASSBUF];
char dirname[DIRNAMESIZE];
} *types;
static char *
funname(const char *, char *);
static void
doswitch(const char *, const char *, const char *, const char *,
const char *, const char *);
static void
add(int, const char *, int, const char *, const char *);
static void
sd(int, const char *, const char *, char);
static char *
funname(const char *s, char *buf) {
char *b = buf;
char c;
INSIST(strlen(s) < TYPECLASSBUF);
while ((c = *s++)) {
*b++ = (c == '-') ? '_' : c;
}
*b = '\0';
return (buf);
}
static void
doswitch(const char *name, const char *function, const char *args,
const char *tsw, const char *csw, const char *res)
{
struct tt *tt;
int first = 1;
int lasttype = 0;
int subswitch = 0;
char buf1[TYPECLASSBUF], buf2[TYPECLASSBUF];
const char *result = " result =";
if (res == NULL)
result = "";
for (tt = types; tt != NULL; tt = tt->next) {
if (first) {
fprintf(stdout, "\n#define %s \\\n", name);
fprintf(stdout, "\tswitch (%s) { \\\n" , tsw);
first = 0;
}
if (tt->type != lasttype && subswitch) {
if (res == NULL)
fprintf(stdout, "\t\tdefault: break; \\\n");
else
fprintf(stdout,
"\t\tdefault: %s; break; \\\n", res);
fputs( "\t\t} \\\n", stdout);
fputs("\t\tbreak; \\\n", stdout);
subswitch = 0;
}
if (tt->rdclass && tt->type != lasttype) {
fprintf(stdout, "\tcase %d: switch (%s) { \\\n" ,
tt->type, csw);
subswitch = 1;
}
if (tt->rdclass == 0)
fprintf(stdout,
"\tcase %d:%s %s_%s(%s); break;",
tt->type, result, function,
funname(tt->typename, buf1), args);
else
fprintf(stdout,
"\t\tcase %d:%s %s_%s_%s(%s); break;",
tt->rdclass, result, function,
funname(tt->classname, buf1),
funname(tt->typename, buf2), args);
fputs(" \\\n", stdout);
lasttype = tt->type;
}
if (subswitch) {
if (res == NULL)
fprintf(stdout, "\t\tdefault: break; \\\n");
else
fprintf(stdout, "\t\tdefault: %s; break; \\\n", res);
fputs( "\t\t} \\\n", stdout);
fputs("\t\tbreak; \\\n", stdout);
}
if (first) {
if (res == NULL)
fprintf(stdout, "\n#define %s\n", name);
else
fprintf(stdout, "\n#define %s %s;\n", name, res);
} else {
if (res == NULL)
fprintf(stdout, "\tdefault: break; \\\n");
else
fprintf(stdout, "\tdefault: %s; break; \\\n", res);
fputs( "\t}\n", stdout);
}
}
static void
add(int rdclass, const char *classname, int type, const char *typename,
const char *dirname)
{
struct tt *newtt = (struct tt *)malloc(sizeof(*newtt));
struct tt *tt, *oldtt;
struct cc *newcc;
struct cc *cc, *oldcc;
INSIST(strlen(typename) < TYPECLASSBUF);
INSIST(strlen(classname) < TYPECLASSBUF);
INSIST(strlen(dirname) < DIRNAMESIZE);
if (newtt == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(1);
}
newtt->next = NULL;
newtt->rdclass = rdclass;
newtt->type = type;
strncpy(newtt->classname, classname, sizeof(newtt->classname));
newtt->classname[sizeof(newtt->classname) - 1] = '\0';
strncpy(newtt->typename, typename, sizeof(newtt->typename));
newtt->typename[sizeof(newtt->typename) - 1] = '\0';
if (strncmp(dirname, "./", 2) == 0)
dirname += 2;
strncpy(newtt->dirname, dirname, sizeof(newtt->dirname));
newtt->dirname[sizeof(newtt->dirname) - 1] = '\0';
tt = types;
oldtt = NULL;
while ((tt != NULL) && (tt->type < type)) {
oldtt = tt;
tt = tt->next;
}
while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) {
if (strcmp(tt->typename, typename) != 0)
exit(1);
oldtt = tt;
tt = tt->next;
}
if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass))
exit(1);
newtt->next = tt;
if (oldtt != NULL)
oldtt->next = newtt;
else
types = newtt;
if (rdclass == 0)
return;
newcc = (struct cc *)malloc(sizeof(*newcc));
if (newcc == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(1);
}
newcc->rdclass = rdclass;
strncpy(newcc->classname, classname, sizeof(newcc->classname));
newcc->classname[sizeof(newcc->classname) - 1] = '\0';
cc = classes;
oldcc = NULL;
while ((cc != NULL) && (cc->rdclass < rdclass)) {
oldcc = cc;
cc = cc->next;
}
if ((cc != NULL) && cc->rdclass == rdclass) {
free((char *)newcc);
return;
}
newcc->next = cc;
if (oldcc != NULL)
oldcc->next = newcc;
else
classes = newcc;
}
static void
sd(int rdclass, const char *classname, const char *dirname, char filetype) {
DIR *dirp;
struct dirent *dp;
char buf[TYPECLASSLEN + sizeof("_65535.h")];
char typename[TYPECLASSBUF];
int type, n;
if ((dirp = opendir(dirname)) == NULL)
return;
while ((dp = readdir(dirp)) != NULL) {
if (sscanf(dp->d_name, TYPECLASSFMT, typename, &type) != 2)
continue;
if ((type > 65535) || (type < 0))
continue;
n = snprintf(buf, sizeof(buf), "%s_%d.%c", typename,
type, filetype);
INSIST(n > 0 && (unsigned)n < sizeof(buf));
if (strcmp(buf, dp->d_name) != 0)
continue;
add(rdclass, classname, type, typename, dirname);
}
closedir(dirp);
}
int
main(int argc, char **argv) {
DIR *dirp;
struct dirent *dp;
char buf[DIRNAMESIZE];
char srcdir[DIRNAMESIZE];
int rdclass;
char classname[TYPECLASSBUF];
struct tt *tt;
struct cc *cc;
struct tm *tm;
time_t now;
char year[11];
int lasttype;
int code = 1;
int class_enum = 0;
int type_enum = 0;
int structs = 0;
int depend = 0;
int c, n;
char buf1[TYPECLASSBUF];
char filetype = 'c';
FILE *fd;
char *prefix = NULL;
char *suffix = NULL;
char *file = NULL;
srcdir[0] = '\0';
while ((c = getopt(argc, argv, "cdits:F:P:S:")) != -1)
switch (c) {
case 'c':
code = 0;
depend = 0;
type_enum = 0;
class_enum = 1;
filetype = 'c';
structs = 0;
break;
case 'd':
code = 0;
depend = 1;
class_enum = 0;
type_enum = 0;
structs = 0;
filetype = 'h';
break;
case 't':
code = 0;
depend = 0;
class_enum = 0;
type_enum = 1;
filetype = 'c';
structs = 0;
break;
case 'i':
code = 0;
depend = 0;
class_enum = 0;
type_enum = 0;
structs = 1;
filetype = 'h';
break;
case 's':
if (strlen(optarg) >
DIRNAMESIZE - 2 * TYPECLASSLEN -
sizeof("/rdata/_65535_65535")) {
fprintf(stderr, "\"%s\" too long\n",
optarg);
exit(1);
}
n = snprintf(srcdir, sizeof(srcdir), "%s/",
optarg);
INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
break;
case 'F':
file = optarg;
break;
case 'P':
prefix = optarg;
break;
case 'S':
suffix = optarg;
break;
case '?':
exit(1);
}
n = snprintf(buf, sizeof(buf), "%srdata", srcdir);
INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
if ((dirp = opendir(buf)) == NULL)
exit(1);
while ((dp = readdir(dirp)) != NULL) {
if (sscanf(dp->d_name, TYPECLASSFMT, classname,
&rdclass) != 2)
continue;
if ((rdclass > 65535) || (rdclass < 0))
continue;
n = snprintf(buf, sizeof(buf), "%srdata/%s_%d",
srcdir, classname, rdclass);
INSIST(n > 0 && (unsigned)n < sizeof(buf));
if (strcmp(buf + 6 + strlen(srcdir), dp->d_name) != 0)
continue;
sd(rdclass, classname, buf, filetype);
}
closedir(dirp);
n = snprintf(buf, sizeof(buf), "%srdata/generic", srcdir);
INSIST(n > 0 && (unsigned)n < sizeof(srcdir));
sd(0, "", buf, filetype);
if (time(&now) != -1) {
if ((tm = localtime(&now)) != NULL && tm->tm_year > 104) {
n = snprintf(year, sizeof(year), "-%d",
tm->tm_year + 1900);
INSIST(n > 0 && (unsigned)n < sizeof(year));
} else
year[0] = 0;
} else
year[0] = 0;
if (!depend)
fprintf(stdout, copyright, year);
if (code) {
fputs("#ifndef DNS_CODE_H\n", stdout);
fputs("#define DNS_CODE_H 1\n\n", stdout);
fputs("#include <isc/result.h>\n\n", stdout);
fputs("#include <dns/name.h>\n\n", stdout);
for (tt = types; tt != NULL; tt = tt->next)
fprintf(stdout, "#include \"%s/%s_%d.c\"\n",
tt->dirname, tt->typename, tt->type);
fputs("\n\n", stdout);
doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS,
TOTEXTTYPE, TOTEXTCLASS, TOTEXTDEF);
doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS,
FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF);
doswitch("TOWIRESWITCH", "towire", TOWIREARGS,
TOWIRETYPE, TOWIRECLASS, TOWIREDEF);
fputs("#endif /* DNS_CODE_H */\n", stdout);
} else if (type_enum) {
char *s;
fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n");
fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n");
fprintf(stdout, "enum {\n");
fprintf(stdout, "\tdns_rdatatype_none = 0,\n");
lasttype = 0;
for (tt = types; tt != NULL; tt = tt->next)
if (tt->type != lasttype)
fprintf(stdout,
"\tdns_rdatatype_%s = %d,\n",
funname(tt->typename, buf1),
lasttype = tt->type);
fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n");
fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n");
fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n");
fprintf(stdout, "\tdns_rdatatype_maila = 254,\n");
fprintf(stdout, "\tdns_rdatatype_any = 255\n");
fprintf(stdout, "};\n\n");
fprintf(stdout, "#define dns_rdatatype_none\t"
"((dns_rdatatype_t)dns_rdatatype_none)\n");
for (tt = types; tt != NULL; tt = tt->next)
if (tt->type != lasttype) {
s = funname(tt->typename, buf1);
fprintf(stdout,
"#define dns_rdatatype_%s\t%s"
"((dns_rdatatype_t)dns_rdatatype_%s)"
"\n",
s, strlen(s) < 2U ? "\t" : "", s);
lasttype = tt->type;
}
fprintf(stdout, "#define dns_rdatatype_ixfr\t"
"((dns_rdatatype_t)dns_rdatatype_ixfr)\n");
fprintf(stdout, "#define dns_rdatatype_axfr\t"
"((dns_rdatatype_t)dns_rdatatype_axfr)\n");
fprintf(stdout, "#define dns_rdatatype_mailb\t"
"((dns_rdatatype_t)dns_rdatatype_mailb)\n");
fprintf(stdout, "#define dns_rdatatype_maila\t"
"((dns_rdatatype_t)dns_rdatatype_maila)\n");
fprintf(stdout, "#define dns_rdatatype_any\t"
"((dns_rdatatype_t)dns_rdatatype_any)\n");
fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n");
} else if (class_enum) {
char *s;
int classnum;
fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n");
fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n");
fprintf(stdout, "enum {\n");
fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n");
fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t"
"((dns_rdataclass_t)dns_rdataclass_reserved0)\n");
#define PRINTCLASS(name, num) \
do { \
s = funname(name, buf1); \
classnum = num; \
fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \
classnum != 255 ? "," : ""); \
fprintf(stdout, "#define dns_rdataclass_%s\t" \
"((dns_rdataclass_t)dns_rdataclass_%s)\n", s, s); \
} while (0)
for (cc = classes; cc != NULL; cc = cc->next) {
if (cc->rdclass == 3)
PRINTCLASS("chaos", 3);
else if (cc->rdclass == 255)
PRINTCLASS("none", 254);
PRINTCLASS(cc->classname, cc->rdclass);
}
#undef PRINTCLASS
fprintf(stdout, "};\n\n");
fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n");
} else if (structs) {
if (prefix != NULL) {
if ((fd = fopen(prefix,"r")) != NULL) {
while (fgets(buf, sizeof(buf), fd) != NULL)
fputs(buf, stdout);
fclose(fd);
}
}
for (tt = types; tt != NULL; tt = tt->next) {
snprintf(buf, sizeof(buf), "%s/%s_%d.h",
tt->dirname, tt->typename, tt->type);
if ((fd = fopen(buf,"r")) != NULL) {
while (fgets(buf, sizeof(buf), fd) != NULL)
fputs(buf, stdout);
fclose(fd);
}
}
if (suffix != NULL) {
if ((fd = fopen(suffix,"r")) != NULL) {
while (fgets(buf, sizeof(buf), fd) != NULL)
fputs(buf, stdout);
fclose(fd);
}
}
} else if (depend) {
for (tt = types; tt != NULL; tt = tt->next)
fprintf(stdout, "%s:\t%s/%s_%d.h\n", file,
tt->dirname, tt->typename, tt->type);
}
if (ferror(stdout) != 0)
exit(1);
return (0);
}