/* * Copyright (C) Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /*! \file */ #include #include #include #include #include #include #include #include #include #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 = ISC_TRUE" #define FROMWIREARGS "rdclass, type, source, dctx, options, target" #define FROMWIRECLASS "rdclass" #define FROMWIRETYPE "type" #define FROMWIREDEF "use_default = ISC_TRUE" #define TOWIREARGS "rdata, cctx, target" #define TOWIRECLASS "rdata->rdclass" #define TOWIRETYPE "rdata->type" #define TOWIREDEF "use_default = ISC_TRUE" 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 /* DNS mnemonic size. Must be less than 100. */ #define TYPECLASSBUF (TYPECLASSLEN + 1) #define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d" #define ATTRIBUTESIZE 256 #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]; /* XXX Should be max path length */ } *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; /* * Do a class switch for this type. */ 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]; /* XXX Should be max path length */ char srcdir[DIRNAMESIZE]; /* XXX Should be max path length */ 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 \n", stdout); fputs("#include \n\n", stdout); fputs("#include \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); }