1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /*! \file */ 18 19 #include <sys/types.h> 20 21 #include <ctype.h> 22 #include <dirent.h> 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <time.h> 28 #include <unistd.h> 29 30 #define INSIST(cond) \ 31 if (!(cond)) { \ 32 fprintf(stderr, "%s:%d: INSIST(%s)\n", \ 33 __FILE__, __LINE__, #cond); \ 34 abort(); \ 35 } 36 37 #define TOTEXTARGS "rdata, tctx, target" 38 #define TOTEXTCLASS "rdata->rdclass" 39 #define TOTEXTTYPE "rdata->type" 40 #define TOTEXTDEF "use_default = 1" 41 42 #define FROMWIREARGS "rdclass, type, source, dctx, options, target" 43 #define FROMWIRECLASS "rdclass" 44 #define FROMWIRETYPE "type" 45 #define FROMWIREDEF "use_default = 1" 46 47 #define TOWIREARGS "rdata, cctx, target" 48 #define TOWIRECLASS "rdata->rdclass" 49 #define TOWIRETYPE "rdata->type" 50 #define TOWIREDEF "use_default = 1" 51 52 static const char copyright[] = 53 "/*\n" 54 " * Copyright (C) 2004%s Internet Systems Consortium, Inc. (\"ISC\")\n" 55 " * Copyright (C) 1998-2003 Internet Software Consortium.\n" 56 " *\n" 57 " * Permission to use, copy, modify, and distribute this software for any\n" 58 " * purpose with or without fee is hereby granted, provided that the above\n" 59 " * copyright notice and this permission notice appear in all copies.\n" 60 " *\n" 61 " * THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n" 62 " * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n" 63 " * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n" 64 " * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n" 65 " * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n" 66 " * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n" 67 " * PERFORMANCE OF THIS SOFTWARE.\n" 68 " */\n" 69 "\n" 70 "/***************\n" 71 " ***************\n" 72 " *************** THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.\n" 73 " *************** DO NOT EDIT!\n" 74 " ***************\n" 75 " ***************/\n" 76 "\n" 77 "/*! \\file */\n" 78 "\n"; 79 80 #define STR_EXPAND(tok) #tok 81 #define STR(tok) STR_EXPAND(tok) 82 83 #define TYPECLASSLEN 20 /* DNS mnemonic size. Must be less than 100. */ 84 #define TYPECLASSBUF (TYPECLASSLEN + 1) 85 #define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d" 86 #define DIRNAMESIZE 256 87 88 static struct cc { 89 struct cc *next; 90 int rdclass; 91 char classname[TYPECLASSBUF]; 92 } *classes; 93 94 static struct tt { 95 struct tt *next; 96 int rdclass; 97 int type; 98 char classname[TYPECLASSBUF]; 99 char typename[TYPECLASSBUF]; 100 char dirname[DIRNAMESIZE]; /* XXX Should be max path length */ 101 } *types; 102 103 static char * 104 funname(const char *, char *); 105 static void 106 doswitch(const char *, const char *, const char *, const char *, 107 const char *, const char *); 108 static void 109 add(int, const char *, int, const char *, const char *); 110 static void 111 sd(int, const char *, const char *, char); 112 113 114 static char * 115 funname(const char *s, char *buf) { 116 char *b = buf; 117 char c; 118 119 INSIST(strlen(s) < TYPECLASSBUF); 120 while ((c = *s++)) { 121 *b++ = (c == '-') ? '_' : c; 122 } 123 *b = '\0'; 124 return (buf); 125 } 126 127 static void 128 doswitch(const char *name, const char *function, const char *args, 129 const char *tsw, const char *csw, const char *res) 130 { 131 struct tt *tt; 132 int first = 1; 133 int lasttype = 0; 134 int subswitch = 0; 135 char buf1[TYPECLASSBUF], buf2[TYPECLASSBUF]; 136 const char *result = " result ="; 137 138 if (res == NULL) 139 result = ""; 140 141 for (tt = types; tt != NULL; tt = tt->next) { 142 if (first) { 143 fprintf(stdout, "\n#define %s \\\n", name); 144 fprintf(stdout, "\tswitch (%s) { \\\n" /*}*/, tsw); 145 first = 0; 146 } 147 if (tt->type != lasttype && subswitch) { 148 if (res == NULL) 149 fprintf(stdout, "\t\tdefault: break; \\\n"); 150 else 151 fprintf(stdout, 152 "\t\tdefault: %s; break; \\\n", res); 153 fputs(/*{*/ "\t\t} \\\n", stdout); 154 fputs("\t\tbreak; \\\n", stdout); 155 subswitch = 0; 156 } 157 if (tt->rdclass && tt->type != lasttype) { 158 fprintf(stdout, "\tcase %d: switch (%s) { \\\n" /*}*/, 159 tt->type, csw); 160 subswitch = 1; 161 } 162 if (tt->rdclass == 0) 163 fprintf(stdout, 164 "\tcase %d:%s %s_%s(%s); break;", 165 tt->type, result, function, 166 funname(tt->typename, buf1), args); 167 else 168 fprintf(stdout, 169 "\t\tcase %d:%s %s_%s_%s(%s); break;", 170 tt->rdclass, result, function, 171 funname(tt->classname, buf1), 172 funname(tt->typename, buf2), args); 173 fputs(" \\\n", stdout); 174 lasttype = tt->type; 175 } 176 if (subswitch) { 177 if (res == NULL) 178 fprintf(stdout, "\t\tdefault: break; \\\n"); 179 else 180 fprintf(stdout, "\t\tdefault: %s; break; \\\n", res); 181 fputs(/*{*/ "\t\t} \\\n", stdout); 182 fputs("\t\tbreak; \\\n", stdout); 183 } 184 if (first) { 185 if (res == NULL) 186 fprintf(stdout, "\n#define %s\n", name); 187 else 188 fprintf(stdout, "\n#define %s %s;\n", name, res); 189 } else { 190 if (res == NULL) 191 fprintf(stdout, "\tdefault: break; \\\n"); 192 else 193 fprintf(stdout, "\tdefault: %s; break; \\\n", res); 194 fputs(/*{*/ "\t}\n", stdout); 195 } 196 } 197 198 static void 199 add(int rdclass, const char *classname, int type, const char *typename, 200 const char *dirname) 201 { 202 struct tt *newtt = (struct tt *)malloc(sizeof(*newtt)); 203 struct tt *tt, *oldtt; 204 struct cc *newcc; 205 struct cc *cc, *oldcc; 206 207 INSIST(strlen(typename) < TYPECLASSBUF); 208 INSIST(strlen(classname) < TYPECLASSBUF); 209 INSIST(strlen(dirname) < DIRNAMESIZE); 210 211 if (newtt == NULL) { 212 fprintf(stderr, "malloc() failed\n"); 213 exit(1); 214 } 215 216 newtt->next = NULL; 217 newtt->rdclass = rdclass; 218 newtt->type = type; 219 220 strncpy(newtt->classname, classname, sizeof(newtt->classname)); 221 newtt->classname[sizeof(newtt->classname) - 1] = '\0'; 222 223 strncpy(newtt->typename, typename, sizeof(newtt->typename)); 224 newtt->typename[sizeof(newtt->typename) - 1] = '\0'; 225 226 if (strncmp(dirname, "./", 2) == 0) 227 dirname += 2; 228 strncpy(newtt->dirname, dirname, sizeof(newtt->dirname)); 229 newtt->dirname[sizeof(newtt->dirname) - 1] = '\0'; 230 231 tt = types; 232 oldtt = NULL; 233 234 while ((tt != NULL) && (tt->type < type)) { 235 oldtt = tt; 236 tt = tt->next; 237 } 238 239 while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) { 240 if (strcmp(tt->typename, typename) != 0) 241 exit(1); 242 oldtt = tt; 243 tt = tt->next; 244 } 245 246 if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass)) 247 exit(1); 248 249 newtt->next = tt; 250 if (oldtt != NULL) 251 oldtt->next = newtt; 252 else 253 types = newtt; 254 255 /* 256 * Do a class switch for this type. 257 */ 258 if (rdclass == 0) 259 return; 260 261 newcc = (struct cc *)malloc(sizeof(*newcc)); 262 if (newcc == NULL) { 263 fprintf(stderr, "malloc() failed\n"); 264 exit(1); 265 } 266 newcc->rdclass = rdclass; 267 strncpy(newcc->classname, classname, sizeof(newcc->classname)); 268 newcc->classname[sizeof(newcc->classname) - 1] = '\0'; 269 cc = classes; 270 oldcc = NULL; 271 272 while ((cc != NULL) && (cc->rdclass < rdclass)) { 273 oldcc = cc; 274 cc = cc->next; 275 } 276 277 if ((cc != NULL) && cc->rdclass == rdclass) { 278 free((char *)newcc); 279 return; 280 } 281 282 newcc->next = cc; 283 if (oldcc != NULL) 284 oldcc->next = newcc; 285 else 286 classes = newcc; 287 } 288 289 static void 290 sd(int rdclass, const char *classname, const char *dirname, char filetype) { 291 DIR *dirp; 292 struct dirent *dp; 293 char buf[TYPECLASSLEN + sizeof("_65535.h")]; 294 char typename[TYPECLASSBUF]; 295 int type, n; 296 297 if ((dirp = opendir(dirname)) == NULL) 298 return; 299 300 while ((dp = readdir(dirp)) != NULL) { 301 if (sscanf(dp->d_name, TYPECLASSFMT, typename, &type) != 2) 302 continue; 303 if ((type > 65535) || (type < 0)) 304 continue; 305 306 n = snprintf(buf, sizeof(buf), "%s_%d.%c", typename, 307 type, filetype); 308 INSIST(n > 0 && (unsigned)n < sizeof(buf)); 309 if (strcmp(buf, dp->d_name) != 0) 310 continue; 311 add(rdclass, classname, type, typename, dirname); 312 } 313 314 closedir(dirp); 315 } 316 317 int 318 main(int argc, char **argv) { 319 DIR *dirp; 320 struct dirent *dp; 321 char buf[DIRNAMESIZE]; /* XXX Should be max path length */ 322 char srcdir[DIRNAMESIZE]; /* XXX Should be max path length */ 323 int rdclass; 324 char classname[TYPECLASSBUF]; 325 struct tt *tt; 326 struct cc *cc; 327 struct tm *tm; 328 time_t now; 329 char year[11]; 330 int lasttype; 331 int code = 1; 332 int class_enum = 0; 333 int type_enum = 0; 334 int structs = 0; 335 int depend = 0; 336 int c, n; 337 char buf1[TYPECLASSBUF]; 338 char filetype = 'c'; 339 FILE *fd; 340 char *prefix = NULL; 341 char *suffix = NULL; 342 char *file = NULL; 343 344 srcdir[0] = '\0'; 345 while ((c = getopt(argc, argv, "cdits:F:P:S:")) != -1) 346 switch (c) { 347 case 'c': 348 code = 0; 349 depend = 0; 350 type_enum = 0; 351 class_enum = 1; 352 filetype = 'c'; 353 structs = 0; 354 break; 355 case 'd': 356 code = 0; 357 depend = 1; 358 class_enum = 0; 359 type_enum = 0; 360 structs = 0; 361 filetype = 'h'; 362 break; 363 case 't': 364 code = 0; 365 depend = 0; 366 class_enum = 0; 367 type_enum = 1; 368 filetype = 'c'; 369 structs = 0; 370 break; 371 case 'i': 372 code = 0; 373 depend = 0; 374 class_enum = 0; 375 type_enum = 0; 376 structs = 1; 377 filetype = 'h'; 378 break; 379 case 's': 380 if (strlen(optarg) > 381 DIRNAMESIZE - 2 * TYPECLASSLEN - 382 sizeof("/rdata/_65535_65535")) { 383 fprintf(stderr, "\"%s\" too long\n", 384 optarg); 385 exit(1); 386 } 387 n = snprintf(srcdir, sizeof(srcdir), "%s/", 388 optarg); 389 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 390 break; 391 case 'F': 392 file = optarg; 393 break; 394 case 'P': 395 prefix = optarg; 396 break; 397 case 'S': 398 suffix = optarg; 399 break; 400 case '?': 401 exit(1); 402 } 403 404 n = snprintf(buf, sizeof(buf), "%srdata", srcdir); 405 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 406 407 if ((dirp = opendir(buf)) == NULL) 408 exit(1); 409 410 while ((dp = readdir(dirp)) != NULL) { 411 if (sscanf(dp->d_name, TYPECLASSFMT, classname, 412 &rdclass) != 2) 413 continue; 414 if ((rdclass > 65535) || (rdclass < 0)) 415 continue; 416 417 n = snprintf(buf, sizeof(buf), "%srdata/%s_%d", 418 srcdir, classname, rdclass); 419 INSIST(n > 0 && (unsigned)n < sizeof(buf)); 420 if (strcmp(buf + 6 + strlen(srcdir), dp->d_name) != 0) 421 continue; 422 sd(rdclass, classname, buf, filetype); 423 } 424 closedir(dirp); 425 426 n = snprintf(buf, sizeof(buf), "%srdata/generic", srcdir); 427 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 428 sd(0, "", buf, filetype); 429 430 if (time(&now) != -1) { 431 if ((tm = localtime(&now)) != NULL && tm->tm_year > 104) { 432 n = snprintf(year, sizeof(year), "-%d", 433 tm->tm_year + 1900); 434 INSIST(n > 0 && (unsigned)n < sizeof(year)); 435 } else 436 year[0] = 0; 437 } else 438 year[0] = 0; 439 440 if (!depend) 441 fprintf(stdout, copyright, year); 442 443 if (code) { 444 fputs("#ifndef DNS_CODE_H\n", stdout); 445 fputs("#define DNS_CODE_H 1\n\n", stdout); 446 447 fputs("#include <isc/result.h>\n\n", stdout); 448 fputs("#include <dns/name.h>\n\n", stdout); 449 450 for (tt = types; tt != NULL; tt = tt->next) 451 fprintf(stdout, "#include \"%s/%s_%d.c\"\n", 452 tt->dirname, tt->typename, tt->type); 453 454 fputs("\n\n", stdout); 455 456 doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS, 457 TOTEXTTYPE, TOTEXTCLASS, TOTEXTDEF); 458 doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS, 459 FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF); 460 doswitch("TOWIRESWITCH", "towire", TOWIREARGS, 461 TOWIRETYPE, TOWIRECLASS, TOWIREDEF); 462 463 fputs("#endif /* DNS_CODE_H */\n", stdout); 464 } else if (type_enum) { 465 char *s; 466 467 fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n"); 468 fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n"); 469 470 fprintf(stdout, "enum {\n"); 471 fprintf(stdout, "\tdns_rdatatype_none = 0,\n"); 472 473 lasttype = 0; 474 for (tt = types; tt != NULL; tt = tt->next) 475 if (tt->type != lasttype) 476 fprintf(stdout, 477 "\tdns_rdatatype_%s = %d,\n", 478 funname(tt->typename, buf1), 479 lasttype = tt->type); 480 481 fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n"); 482 fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n"); 483 fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n"); 484 fprintf(stdout, "\tdns_rdatatype_maila = 254,\n"); 485 fprintf(stdout, "\tdns_rdatatype_any = 255\n"); 486 487 fprintf(stdout, "};\n\n"); 488 489 fprintf(stdout, "#define dns_rdatatype_none\t" 490 "((dns_rdatatype_t)dns_rdatatype_none)\n"); 491 492 for (tt = types; tt != NULL; tt = tt->next) 493 if (tt->type != lasttype) { 494 s = funname(tt->typename, buf1); 495 fprintf(stdout, 496 "#define dns_rdatatype_%s\t%s" 497 "((dns_rdatatype_t)dns_rdatatype_%s)" 498 "\n", 499 s, strlen(s) < 2U ? "\t" : "", s); 500 lasttype = tt->type; 501 } 502 503 fprintf(stdout, "#define dns_rdatatype_ixfr\t" 504 "((dns_rdatatype_t)dns_rdatatype_ixfr)\n"); 505 fprintf(stdout, "#define dns_rdatatype_axfr\t" 506 "((dns_rdatatype_t)dns_rdatatype_axfr)\n"); 507 fprintf(stdout, "#define dns_rdatatype_mailb\t" 508 "((dns_rdatatype_t)dns_rdatatype_mailb)\n"); 509 fprintf(stdout, "#define dns_rdatatype_maila\t" 510 "((dns_rdatatype_t)dns_rdatatype_maila)\n"); 511 fprintf(stdout, "#define dns_rdatatype_any\t" 512 "((dns_rdatatype_t)dns_rdatatype_any)\n"); 513 514 fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n"); 515 516 } else if (class_enum) { 517 char *s; 518 int classnum; 519 520 fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n"); 521 fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n"); 522 523 fprintf(stdout, "enum {\n"); 524 525 fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n"); 526 fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t" 527 "((dns_rdataclass_t)dns_rdataclass_reserved0)\n"); 528 529 #define PRINTCLASS(name, num) \ 530 do { \ 531 s = funname(name, buf1); \ 532 classnum = num; \ 533 fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \ 534 classnum != 255 ? "," : ""); \ 535 fprintf(stdout, "#define dns_rdataclass_%s\t" \ 536 "((dns_rdataclass_t)dns_rdataclass_%s)\n", s, s); \ 537 } while (0) 538 539 for (cc = classes; cc != NULL; cc = cc->next) { 540 if (cc->rdclass == 3) 541 PRINTCLASS("chaos", 3); 542 else if (cc->rdclass == 255) 543 PRINTCLASS("none", 254); 544 PRINTCLASS(cc->classname, cc->rdclass); 545 } 546 547 #undef PRINTCLASS 548 549 fprintf(stdout, "};\n\n"); 550 fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n"); 551 } else if (structs) { 552 if (prefix != NULL) { 553 if ((fd = fopen(prefix,"r")) != NULL) { 554 while (fgets(buf, sizeof(buf), fd) != NULL) 555 fputs(buf, stdout); 556 fclose(fd); 557 } 558 } 559 for (tt = types; tt != NULL; tt = tt->next) { 560 snprintf(buf, sizeof(buf), "%s/%s_%d.h", 561 tt->dirname, tt->typename, tt->type); 562 if ((fd = fopen(buf,"r")) != NULL) { 563 while (fgets(buf, sizeof(buf), fd) != NULL) 564 fputs(buf, stdout); 565 fclose(fd); 566 } 567 } 568 if (suffix != NULL) { 569 if ((fd = fopen(suffix,"r")) != NULL) { 570 while (fgets(buf, sizeof(buf), fd) != NULL) 571 fputs(buf, stdout); 572 fclose(fd); 573 } 574 } 575 } else if (depend) { 576 for (tt = types; tt != NULL; tt = tt->next) 577 fprintf(stdout, "%s:\t%s/%s_%d.h\n", file, 578 tt->dirname, tt->typename, tt->type); 579 } 580 581 if (ferror(stdout) != 0) 582 exit(1); 583 584 return (0); 585 } 586