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