1 /* $NetBSD: gen.c,v 1.11 2023/01/25 21:43:30 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #ifdef WIN32 19 /* 20 * Silence compiler warnings about using strcpy and friends. 21 */ 22 #define _CRT_SECURE_NO_DEPRECATE 1 23 /* 24 * We use snprintf which was defined late in Windows even it is in C99. 25 */ 26 #if _MSC_VER < 1900 27 #define snprintf _snprintf 28 #endif /* if _MSC_VER < 1900 */ 29 #endif /* ifdef WIN32 */ 30 31 #include <ctype.h> 32 #include <errno.h> 33 #include <limits.h> 34 #include <stdint.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <sys/types.h> 39 #include <time.h> 40 41 #ifndef PATH_MAX 42 #define PATH_MAX 1024 43 #endif /* ifndef PATH_MAX */ 44 45 #ifdef WIN32 46 #include "gen-win32.h" 47 #else /* ifdef WIN32 */ 48 #include "gen-unix.h" 49 #endif /* ifdef WIN32 */ 50 51 #ifndef ULLONG_MAX 52 #define ULLONG_MAX (~0ULL) 53 #endif /* ifndef ULLONG_MAX */ 54 55 #define INSIST(cond) \ 56 if (!(cond)) { \ 57 fprintf(stderr, "%s:%d: INSIST(%s)\n", __FILE__, __LINE__, \ 58 #cond); \ 59 abort(); \ 60 } 61 62 #define FROMTEXTARGS "rdclass, type, lexer, origin, options, target, callbacks" 63 #define FROMTEXTCLASS "rdclass" 64 #define FROMTEXTTYPE "type" 65 #define FROMTEXTDEF "result = DNS_R_UNKNOWN" 66 67 #define TOTEXTARGS "rdata, tctx, target" 68 #define TOTEXTCLASS "rdata->rdclass" 69 #define TOTEXTTYPE "rdata->type" 70 #define TOTEXTDEF "use_default = true" 71 72 #define FROMWIREARGS "rdclass, type, source, dctx, options, target" 73 #define FROMWIRECLASS "rdclass" 74 #define FROMWIRETYPE "type" 75 #define FROMWIREDEF "use_default = true" 76 77 #define TOWIREARGS "rdata, cctx, target" 78 #define TOWIRECLASS "rdata->rdclass" 79 #define TOWIRETYPE "rdata->type" 80 #define TOWIREDEF "use_default = true" 81 82 #define FROMSTRUCTARGS "rdclass, type, source, target" 83 #define FROMSTRUCTCLASS "rdclass" 84 #define FROMSTRUCTTYPE "type" 85 #define FROMSTRUCTDEF "use_default = true" 86 87 #define TOSTRUCTARGS "rdata, target, mctx" 88 #define TOSTRUCTCLASS "rdata->rdclass" 89 #define TOSTRUCTTYPE "rdata->type" 90 #define TOSTRUCTDEF "use_default = true" 91 92 #define FREESTRUCTARGS "source" 93 #define FREESTRUCTCLASS "common->rdclass" 94 #define FREESTRUCTTYPE "common->rdtype" 95 #define FREESTRUCTDEF NULL 96 97 #define COMPAREARGS "rdata1, rdata2" 98 #define COMPARECLASS "rdata1->rdclass" 99 #define COMPARETYPE "rdata1->type" 100 #define COMPAREDEF "use_default = true" 101 102 #define ADDITIONALDATAARGS "rdata, add, arg" 103 #define ADDITIONALDATACLASS "rdata->rdclass" 104 #define ADDITIONALDATATYPE "rdata->type" 105 #define ADDITIONALDATADEF "use_default = true" 106 107 #define DIGESTARGS "rdata, digest, arg" 108 #define DIGESTCLASS "rdata->rdclass" 109 #define DIGESTTYPE "rdata->type" 110 #define DIGESTDEF "use_default = true" 111 112 #define CHECKOWNERARGS "name, rdclass, type, wildcard" 113 #define CHECKOWNERCLASS "rdclass" 114 #define CHECKOWNERTYPE "type" 115 #define CHECKOWNERDEF "result = true" 116 117 #define CHECKNAMESARGS "rdata, owner, bad" 118 #define CHECKNAMESCLASS "rdata->rdclass" 119 #define CHECKNAMESTYPE "rdata->type" 120 #define CHECKNAMESDEF "result = true" 121 122 static const char copyright[] = "/*\n" 123 " * Copyright (C) 1998%s Internet Systems " 124 "Consortium, Inc. (\"ISC\")\n" 125 " *\n" 126 " * This Source Code Form is subject to the " 127 "terms of the Mozilla Public\n" 128 " * License, v. 2.0. If a copy of the MPL was " 129 "not distributed with this\n" 130 " * file, you can obtain one at " 131 "https://mozilla.org/MPL/2.0/.\n" 132 " */\n" 133 "\n" 134 "/***************\n" 135 " ***************\n" 136 " *************** THIS FILE IS AUTOMATICALLY " 137 "GENERATED BY gen.c.\n" 138 " *************** DO NOT EDIT!\n" 139 " ***************\n" 140 " ***************/\n" 141 "\n" 142 "/*! \\file */\n" 143 "\n"; 144 145 #define STR_EXPAND(tok) #tok 146 #define STR(tok) STR_EXPAND(tok) 147 148 #define TYPENAMES 256 149 #define TYPECLASSLEN 20 /* DNS mnemonic size. Must be less than 100. */ 150 #define TYPECLASSBUF (TYPECLASSLEN + 1) 151 #define TYPECLASSFMT "%" STR(TYPECLASSLEN) "[-0-9a-z]_%d" 152 #define ATTRIBUTESIZE 256 153 154 static struct cc { 155 struct cc *next; 156 int rdclass; 157 char classbuf[TYPECLASSBUF]; 158 } *classes; 159 160 static struct tt { 161 struct tt *next; 162 uint16_t rdclass; 163 uint16_t type; 164 char classbuf[TYPECLASSBUF]; 165 char typebuf[TYPECLASSBUF]; 166 char dirbuf[PATH_MAX - 30]; 167 } *types; 168 169 static struct ttnam { 170 char typebuf[TYPECLASSBUF]; 171 char macroname[TYPECLASSBUF]; 172 char attr[ATTRIBUTESIZE]; 173 unsigned int sorted; 174 uint16_t type; 175 } typenames[TYPENAMES]; 176 177 static int maxtype = -1; 178 179 static char * 180 upper(char *); 181 static char * 182 funname(const char *, char *); 183 static void 184 doswitch(const char *, const char *, const char *, const char *, const char *, 185 const char *); 186 static void 187 add(int, const char *, int, const char *, const char *); 188 static void 189 sd(int, const char *, const char *, char); 190 static void 191 insert_into_typenames(int, const char *, const char *); 192 193 /*% 194 * If you use more than 10 of these in, say, a printf(), you'll have problems. 195 */ 196 static char * 197 upper(char *s) { 198 static int buf_to_use = 0; 199 static char buf[10][256]; 200 char *b; 201 int c; 202 203 buf_to_use++; 204 if (buf_to_use > 9) { 205 buf_to_use = 0; 206 } 207 208 b = buf[buf_to_use]; 209 memset(b, 0, 256); 210 211 while ((c = (*s++) & 0xff)) { 212 *b++ = islower(c) ? toupper(c) : c; 213 } 214 *b = '\0'; 215 return (buf[buf_to_use]); 216 } 217 218 static char * 219 funname(const char *s, char *buf) { 220 char *b = buf; 221 char c; 222 223 INSIST(strlen(s) < TYPECLASSBUF); 224 while ((c = *s++)) { 225 *b++ = (c == '-') ? '_' : c; 226 } 227 *b = '\0'; 228 return (buf); 229 } 230 231 static void 232 doswitch(const char *name, const char *function, const char *args, 233 const char *tsw, const char *csw, const char *res) { 234 struct tt *tt; 235 int first = 1; 236 int lasttype = 0; 237 int subswitch = 0; 238 char buf1[TYPECLASSBUF], buf2[TYPECLASSBUF]; 239 const char *result = " result ="; 240 241 if (res == NULL) { 242 result = ""; 243 } 244 245 for (tt = types; tt != NULL; tt = tt->next) { 246 if (first) { 247 fprintf(stdout, "\n#define %s \\\n", name); 248 fprintf(stdout, "\tswitch (%s) { \\\n" /*}*/, tsw); 249 first = 0; 250 } 251 if (tt->type != lasttype && subswitch) { 252 if (res == NULL) { 253 fprintf(stdout, "\t\tdefault: break; \\\n"); 254 } else { 255 fprintf(stdout, "\t\tdefault: %s; break; \\\n", 256 res); 257 } 258 fputs(/*{*/ "\t\t} \\\n", stdout); 259 fputs("\t\tbreak; \\\n", stdout); 260 subswitch = 0; 261 } 262 if (tt->rdclass && tt->type != lasttype) { 263 fprintf(stdout, "\tcase %d: switch (%s) { \\\n" /*}*/, 264 tt->type, csw); 265 subswitch = 1; 266 } 267 if (tt->rdclass == 0) { 268 fprintf(stdout, "\tcase %d:%s %s_%s(%s); break;", 269 tt->type, result, function, 270 funname(tt->typebuf, buf1), args); 271 } else { 272 fprintf(stdout, "\t\tcase %d:%s %s_%s_%s(%s); break;", 273 tt->rdclass, result, function, 274 funname(tt->classbuf, buf1), 275 funname(tt->typebuf, buf2), args); 276 } 277 fputs(" \\\n", stdout); 278 lasttype = tt->type; 279 } 280 if (subswitch) { 281 if (res == NULL) { 282 fprintf(stdout, "\t\tdefault: break; \\\n"); 283 } else { 284 fprintf(stdout, "\t\tdefault: %s; break; \\\n", res); 285 } 286 fputs(/*{*/ "\t\t} \\\n", stdout); 287 fputs("\t\tbreak; \\\n", stdout); 288 } 289 if (first) { 290 if (res == NULL) { 291 fprintf(stdout, "\n#define %s\n", name); 292 } else { 293 fprintf(stdout, "\n#define %s %s;\n", name, res); 294 } 295 } else { 296 if (res == NULL) { 297 fprintf(stdout, "\tdefault: break; \\\n"); 298 } else { 299 fprintf(stdout, "\tdefault: %s; break; \\\n", res); 300 } 301 fputs(/*{*/ "\t}\n", stdout); 302 } 303 } 304 305 static struct ttnam * 306 find_typename(int type) { 307 int i; 308 309 for (i = 0; i < TYPENAMES; i++) { 310 if (typenames[i].typebuf[0] != 0 && typenames[i].type == type) { 311 return (&typenames[i]); 312 } 313 } 314 return (NULL); 315 } 316 317 static void 318 insert_into_typenames(int type, const char *typebuf, const char *attr) { 319 struct ttnam *ttn = NULL; 320 size_t c; 321 int i, n; 322 char tmp[256]; 323 324 INSIST(strlen(typebuf) < TYPECLASSBUF); 325 for (i = 0; i < TYPENAMES; i++) { 326 if (typenames[i].typebuf[0] != 0 && typenames[i].type == type && 327 strcmp(typebuf, typenames[i].typebuf) != 0) 328 { 329 fprintf(stderr, 330 "Error: type %d has two names: %s, %s\n", type, 331 typenames[i].typebuf, typebuf); 332 exit(1); 333 } 334 if (typenames[i].typebuf[0] == 0 && ttn == NULL) { 335 ttn = &typenames[i]; 336 } 337 } 338 if (ttn == NULL) { 339 fprintf(stderr, "Error: typenames array too small\n"); 340 exit(1); 341 } 342 343 /* XXXMUKS: This is redundant due to the INSIST above. */ 344 if (strlen(typebuf) > sizeof(ttn->typebuf) - 1) { 345 fprintf(stderr, "Error: type name %s is too long\n", typebuf); 346 exit(1); 347 } 348 349 strncpy(ttn->typebuf, typebuf, sizeof(ttn->typebuf)); 350 ttn->typebuf[sizeof(ttn->typebuf) - 1] = '\0'; 351 352 strncpy(ttn->macroname, ttn->typebuf, sizeof(ttn->macroname)); 353 ttn->macroname[sizeof(ttn->macroname) - 1] = '\0'; 354 355 ttn->type = type; 356 c = strlen(ttn->macroname); 357 while (c > 0) { 358 if (ttn->macroname[c - 1] == '-') { 359 ttn->macroname[c - 1] = '_'; 360 } 361 c--; 362 } 363 364 if (attr == NULL) { 365 n = snprintf(tmp, sizeof(tmp), "RRTYPE_%s_ATTRIBUTES", 366 upper(ttn->macroname)); 367 INSIST(n > 0 && (unsigned)n < sizeof(tmp)); 368 attr = tmp; 369 } 370 371 if (ttn->attr[0] != 0 && strcmp(attr, ttn->attr) != 0) { 372 fprintf(stderr, 373 "Error: type %d has different attributes: " 374 "%s, %s\n", 375 type, ttn->attr, attr); 376 exit(1); 377 } 378 379 if (strlen(attr) > sizeof(ttn->attr) - 1) { 380 fprintf(stderr, "Error: attr (%s) [name %s] is too long\n", 381 attr, typebuf); 382 exit(1); 383 } 384 385 strncpy(ttn->attr, attr, sizeof(ttn->attr)); 386 ttn->attr[sizeof(ttn->attr) - 1] = '\0'; 387 388 ttn->sorted = 0; 389 if (maxtype < type) { 390 maxtype = type; 391 } 392 } 393 394 static void 395 add(int rdclass, const char *classbuf, int type, const char *typebuf, 396 const char *dirbuf) { 397 struct tt *newtt = (struct tt *)malloc(sizeof(*newtt)); 398 struct tt *tt, *oldtt; 399 struct cc *newcc; 400 struct cc *cc, *oldcc; 401 402 INSIST(strlen(typebuf) < TYPECLASSBUF); 403 INSIST(strlen(classbuf) < TYPECLASSBUF); 404 INSIST(strlen(dirbuf) < PATH_MAX); 405 406 insert_into_typenames(type, typebuf, NULL); 407 408 if (newtt == NULL) { 409 fprintf(stderr, "malloc() failed\n"); 410 exit(1); 411 } 412 413 newtt->next = NULL; 414 newtt->rdclass = rdclass; 415 newtt->type = type; 416 417 strncpy(newtt->classbuf, classbuf, sizeof(newtt->classbuf)); 418 newtt->classbuf[sizeof(newtt->classbuf) - 1] = '\0'; 419 420 strncpy(newtt->typebuf, typebuf, sizeof(newtt->typebuf)); 421 newtt->typebuf[sizeof(newtt->typebuf) - 1] = '\0'; 422 423 if (strncmp(dirbuf, "./", 2) == 0) { 424 dirbuf += 2; 425 } 426 strncpy(newtt->dirbuf, dirbuf, sizeof(newtt->dirbuf)); 427 newtt->dirbuf[sizeof(newtt->dirbuf) - 1] = '\0'; 428 429 tt = types; 430 oldtt = NULL; 431 432 while ((tt != NULL) && (tt->type < type)) { 433 oldtt = tt; 434 tt = tt->next; 435 } 436 437 while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) { 438 if (strcmp(tt->typebuf, typebuf) != 0) { 439 exit(1); 440 } 441 oldtt = tt; 442 tt = tt->next; 443 } 444 445 if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass)) { 446 exit(1); 447 } 448 449 newtt->next = tt; 450 if (oldtt != NULL) { 451 oldtt->next = newtt; 452 } else { 453 types = newtt; 454 } 455 456 /* 457 * Do a class switch for this type. 458 */ 459 if (rdclass == 0) { 460 return; 461 } 462 463 newcc = (struct cc *)malloc(sizeof(*newcc)); 464 if (newcc == NULL) { 465 fprintf(stderr, "malloc() failed\n"); 466 exit(1); 467 } 468 newcc->rdclass = rdclass; 469 strncpy(newcc->classbuf, classbuf, sizeof(newcc->classbuf)); 470 newcc->classbuf[sizeof(newcc->classbuf) - 1] = '\0'; 471 cc = classes; 472 oldcc = NULL; 473 474 while ((cc != NULL) && (cc->rdclass < rdclass)) { 475 oldcc = cc; 476 cc = cc->next; 477 } 478 479 if ((cc != NULL) && cc->rdclass == rdclass) { 480 free((char *)newcc); 481 return; 482 } 483 484 newcc->next = cc; 485 if (oldcc != NULL) { 486 oldcc->next = newcc; 487 } else { 488 classes = newcc; 489 } 490 } 491 492 static void 493 sd(int rdclass, const char *classbuf, const char *dirbuf, char filetype) { 494 char buf[TYPECLASSLEN + sizeof("_65535.h")]; 495 char typebuf[TYPECLASSBUF]; 496 int type, n; 497 isc_dir_t dir; 498 499 if (!start_directory(dirbuf, &dir)) { 500 return; 501 } 502 503 while (next_file(&dir)) { 504 if (sscanf(dir.filename, TYPECLASSFMT, typebuf, &type) != 2) { 505 continue; 506 } 507 if ((type > 65535) || (type < 0)) { 508 continue; 509 } 510 511 n = snprintf(buf, sizeof(buf), "%s_%d.%c", typebuf, type, 512 filetype); 513 INSIST(n > 0 && (unsigned)n < sizeof(buf)); 514 if (strcmp(buf, dir.filename) != 0) { 515 continue; 516 } 517 add(rdclass, classbuf, type, typebuf, dirbuf); 518 } 519 520 end_directory(&dir); 521 } 522 523 static unsigned int 524 HASH(char *string) { 525 size_t n; 526 unsigned char a, b; 527 528 n = strlen(string); 529 if (n == 0) { 530 fprintf(stderr, "n == 0?\n"); 531 exit(1); 532 } 533 a = tolower((unsigned char)string[0]); 534 b = tolower((unsigned char)string[n - 1]); 535 536 return (((a + n) * b) % 256); 537 } 538 539 int 540 main(int argc, char **argv) { 541 char buf[PATH_MAX]; 542 char srcdir[PATH_MAX]; 543 int rdclass; 544 char classbuf[TYPECLASSBUF]; 545 struct tt *tt; 546 struct cc *cc; 547 struct ttnam *ttn, *ttn2; 548 unsigned int hash; 549 time_t now; 550 char year[11]; 551 int lasttype; 552 int code = 1; 553 int class_enum = 0; 554 int type_enum = 0; 555 int structs = 0; 556 int depend = 0; 557 int c, i, j, n; 558 char buf1[TYPECLASSBUF]; 559 char filetype = 'c'; 560 FILE *fd; 561 char *prefix = NULL; 562 char *suffix = NULL; 563 char *file = NULL; 564 char *source_date_epoch; 565 unsigned long long epoch; 566 char *endptr; 567 isc_dir_t dir; 568 569 for (i = 0; i < TYPENAMES; i++) { 570 memset(&typenames[i], 0, sizeof(typenames[i])); 571 } 572 573 srcdir[0] = '\0'; 574 while ((c = isc_commandline_parse(argc, argv, "cdits:F:P:S:")) != -1) { 575 switch (c) { 576 case 'c': 577 code = 0; 578 depend = 0; 579 type_enum = 0; 580 class_enum = 1; 581 filetype = 'c'; 582 structs = 0; 583 break; 584 case 'd': 585 code = 0; 586 depend = 1; 587 class_enum = 0; 588 type_enum = 0; 589 structs = 0; 590 filetype = 'h'; 591 break; 592 case 't': 593 code = 0; 594 depend = 0; 595 class_enum = 0; 596 type_enum = 1; 597 filetype = 'c'; 598 structs = 0; 599 break; 600 case 'i': 601 code = 0; 602 depend = 0; 603 class_enum = 0; 604 type_enum = 0; 605 structs = 1; 606 filetype = 'h'; 607 break; 608 case 's': 609 if (strlen(isc_commandline_argument) > 610 PATH_MAX - 2 * TYPECLASSLEN - 611 sizeof("/rdata/_65535_65535")) 612 { 613 fprintf(stderr, "\"%s\" too long\n", 614 isc_commandline_argument); 615 exit(1); 616 } 617 n = snprintf(srcdir, sizeof(srcdir), "%s/", 618 isc_commandline_argument); 619 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 620 break; 621 case 'F': 622 file = isc_commandline_argument; 623 break; 624 case 'P': 625 prefix = isc_commandline_argument; 626 break; 627 case 'S': 628 suffix = isc_commandline_argument; 629 break; 630 case '?': 631 exit(1); 632 } 633 } 634 635 n = snprintf(buf, sizeof(buf), "%srdata", srcdir); 636 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 637 638 if (!start_directory(buf, &dir)) { 639 exit(1); 640 } 641 642 while (next_file(&dir)) { 643 if (sscanf(dir.filename, TYPECLASSFMT, classbuf, &rdclass) != 2) 644 { 645 continue; 646 } 647 if ((rdclass > 65535) || (rdclass < 0)) { 648 continue; 649 } 650 651 n = snprintf(buf, sizeof(buf), "%srdata/%s_%d", srcdir, 652 classbuf, rdclass); 653 INSIST(n > 0 && (unsigned)n < sizeof(buf)); 654 if (strcmp(buf + 6 + strlen(srcdir), dir.filename) != 0) { 655 continue; 656 } 657 sd(rdclass, classbuf, buf, filetype); 658 } 659 end_directory(&dir); 660 n = snprintf(buf, sizeof(buf), "%srdata/generic", srcdir); 661 INSIST(n > 0 && (unsigned)n < sizeof(srcdir)); 662 sd(0, "", buf, filetype); 663 664 source_date_epoch = getenv("SOURCE_DATE_EPOCH"); 665 if (source_date_epoch) { 666 errno = 0; 667 epoch = strtoull(source_date_epoch, &endptr, 10); 668 if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0)) || 669 (errno != 0 && epoch == 0)) 670 { 671 fprintf(stderr, 672 "Environment variable " 673 "$SOURCE_DATE_EPOCH: strtoull: %s\n", 674 strerror(errno)); 675 exit(EXIT_FAILURE); 676 } 677 if (endptr == source_date_epoch) { 678 fprintf(stderr, 679 "Environment variable " 680 "$SOURCE_DATE_EPOCH: " 681 "No digits were found: %s\n", 682 endptr); 683 exit(EXIT_FAILURE); 684 } 685 if (*endptr != '\0') { 686 fprintf(stderr, 687 "Environment variable " 688 "$SOURCE_DATE_EPOCH: Trailing garbage: %s\n", 689 endptr); 690 exit(EXIT_FAILURE); 691 } 692 if (epoch > ULONG_MAX) { 693 fprintf(stderr, 694 "Environment variable " 695 "$SOURCE_DATE_EPOCH: value must be " 696 "smaller than or equal to: %lu but " 697 "was found to be: %llu \n", 698 ULONG_MAX, epoch); 699 exit(EXIT_FAILURE); 700 } 701 now = epoch; 702 } else { 703 time(&now); 704 } 705 706 if (now != -1) { 707 struct tm t, *tm = gmtime_r(&now, &t); 708 709 if (tm != NULL && tm->tm_year > 104) { 710 n = snprintf(year, sizeof(year), "-%d", 711 tm->tm_year + 1900); 712 INSIST(n > 0 && (unsigned)n < sizeof(year)); 713 } else { 714 snprintf(year, sizeof(year), "-2016"); 715 } 716 } else { 717 snprintf(year, sizeof(year), "-2016"); 718 } 719 720 if (!depend) { 721 fprintf(stdout, copyright, year); 722 } 723 724 if (code) { 725 fputs("#ifndef DNS_CODE_H\n", stdout); 726 fputs("#define DNS_CODE_H 1\n\n", stdout); 727 728 fputs("#include <stdbool.h>\n", stdout); 729 fputs("#include <isc/result.h>\n\n", stdout); 730 fputs("#include <dns/name.h>\n\n", stdout); 731 732 for (tt = types; tt != NULL; tt = tt->next) { 733 fprintf(stdout, "#include \"%s/%s_%d.c\"\n", tt->dirbuf, 734 tt->typebuf, tt->type); 735 } 736 737 fputs("\n\n", stdout); 738 739 doswitch("FROMTEXTSWITCH", "fromtext", FROMTEXTARGS, 740 FROMTEXTTYPE, FROMTEXTCLASS, FROMTEXTDEF); 741 doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS, TOTEXTTYPE, 742 TOTEXTCLASS, TOTEXTDEF); 743 doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS, 744 FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF); 745 doswitch("TOWIRESWITCH", "towire", TOWIREARGS, TOWIRETYPE, 746 TOWIRECLASS, TOWIREDEF); 747 doswitch("COMPARESWITCH", "compare", COMPAREARGS, COMPARETYPE, 748 COMPARECLASS, COMPAREDEF); 749 doswitch("CASECOMPARESWITCH", "casecompare", COMPAREARGS, 750 COMPARETYPE, COMPARECLASS, COMPAREDEF); 751 doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS, 752 FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF); 753 doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS, 754 TOSTRUCTTYPE, TOSTRUCTCLASS, TOSTRUCTDEF); 755 doswitch("FREESTRUCTSWITCH", "freestruct", FREESTRUCTARGS, 756 FREESTRUCTTYPE, FREESTRUCTCLASS, FREESTRUCTDEF); 757 doswitch("ADDITIONALDATASWITCH", "additionaldata", 758 ADDITIONALDATAARGS, ADDITIONALDATATYPE, 759 ADDITIONALDATACLASS, ADDITIONALDATADEF); 760 doswitch("DIGESTSWITCH", "digest", DIGESTARGS, DIGESTTYPE, 761 DIGESTCLASS, DIGESTDEF); 762 doswitch("CHECKOWNERSWITCH", "checkowner", CHECKOWNERARGS, 763 CHECKOWNERTYPE, CHECKOWNERCLASS, CHECKOWNERDEF); 764 doswitch("CHECKNAMESSWITCH", "checknames", CHECKNAMESARGS, 765 CHECKNAMESTYPE, CHECKNAMESCLASS, CHECKNAMESDEF); 766 767 /* 768 * From here down, we are processing the rdata names and 769 * attributes. 770 */ 771 772 #define PRINT_COMMA(x) (x == maxtype ? "" : ",") 773 774 #define METANOTQUESTION \ 775 "DNS_RDATATYPEATTR_META | " \ 776 "DNS_RDATATYPEATTR_NOTQUESTION" 777 #define METAQUESTIONONLY \ 778 "DNS_RDATATYPEATTR_META | " \ 779 "DNS_RDATATYPEATTR_QUESTIONONLY" 780 #define RESERVEDNAME "0" 781 #define RESERVED "DNS_RDATATYPEATTR_RESERVED" 782 783 /* 784 * Add in reserved/special types. This will let us 785 * sort them without special cases. 786 */ 787 insert_into_typenames(100, "uinfo", RESERVEDNAME); 788 insert_into_typenames(101, "uid", RESERVEDNAME); 789 insert_into_typenames(102, "gid", RESERVEDNAME); 790 insert_into_typenames(103, "unspec", RESERVEDNAME); 791 insert_into_typenames(251, "ixfr", METAQUESTIONONLY); 792 insert_into_typenames(252, "axfr", METAQUESTIONONLY); 793 insert_into_typenames(253, "mailb", METAQUESTIONONLY); 794 insert_into_typenames(254, "maila", METAQUESTIONONLY); 795 insert_into_typenames(255, "any", METAQUESTIONONLY); 796 797 /* 798 * Spit out a quick and dirty hash function. Here, 799 * we walk through the list of type names, and calculate 800 * a hash. This isn't perfect, but it will generate "pretty 801 * good" estimates. Lowercase the characters before 802 * computing in all cases. 803 * 804 * Here, walk the list from top to bottom, calculating 805 * the hash (mod 256) for each name. 806 */ 807 fprintf(stdout, "#define RDATATYPE_COMPARE(_s, _d, _tn, _n, " 808 "_tp) \\\n"); 809 fprintf(stdout, "\tdo { \\\n"); 810 fprintf(stdout, "\t\tif (sizeof(_s) - 1 == _n && \\\n" 811 "\t\t strncasecmp(_s,(_tn)," 812 "(sizeof(_s) - 1)) == 0) { \\\n"); 813 fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & " 814 "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n"); 815 fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n"); 816 fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n"); 817 fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n"); 818 fprintf(stdout, "\t\t} \\\n"); 819 fprintf(stdout, "\t} while (0)\n\n"); 820 821 fprintf(stdout, "#define RDATATYPE_FROMTEXT_SW(_hash," 822 "_typename,_length,_typep) \\\n"); 823 fprintf(stdout, "\tswitch (_hash) { \\\n"); 824 for (i = 0; i <= maxtype; i++) { 825 ttn = find_typename(i); 826 if (ttn == NULL) { 827 continue; 828 } 829 830 /* 831 * Skip entries we already processed. 832 */ 833 if (ttn->sorted != 0) { 834 continue; 835 } 836 837 hash = HASH(ttn->typebuf); 838 fprintf(stdout, "\t\tcase %u: \\\n", hash); 839 840 /* 841 * Find all other entries that happen to match 842 * this hash. 843 */ 844 for (j = 0; j <= maxtype; j++) { 845 ttn2 = find_typename(j); 846 if (ttn2 == NULL) { 847 continue; 848 } 849 if (hash == HASH(ttn2->typebuf)) { 850 fprintf(stdout, 851 "\t\t\t" 852 "RDATATYPE_COMPARE" 853 "(\"%s\", %d, _typename, " 854 " _length, _typep); \\\n", 855 ttn2->typebuf, ttn2->type); 856 ttn2->sorted = 1; 857 } 858 } 859 fprintf(stdout, "\t\t\tbreak; \\\n"); 860 } 861 fprintf(stdout, "\t}\n"); 862 863 fprintf(stdout, "#define RDATATYPE_ATTRIBUTE_SW \\\n"); 864 fprintf(stdout, "\tswitch (type) { \\\n"); 865 for (i = 0; i <= maxtype; i++) { 866 ttn = find_typename(i); 867 if (ttn == NULL) { 868 continue; 869 } 870 fprintf(stdout, "\tcase %d: return (%s); \\\n", i, 871 upper(ttn->attr)); 872 } 873 fprintf(stdout, "\t}\n"); 874 875 fprintf(stdout, "#define RDATATYPE_TOTEXT_SW \\\n"); 876 fprintf(stdout, "\tswitch (type) { \\\n"); 877 for (i = 0; i <= maxtype; i++) { 878 ttn = find_typename(i); 879 if (ttn == NULL) { 880 continue; 881 } 882 /* 883 * Remove KEYDATA (65533) from the type to memonic 884 * translation as it is internal use only. This 885 * stops the tools from displaying KEYDATA instead 886 * of TYPE65533. 887 */ 888 if (i == 65533U) { 889 continue; 890 } 891 fprintf(stdout, 892 "\tcase %d: return " 893 "(str_totext(\"%s\", target)); \\\n", 894 i, upper(ttn->typebuf)); 895 } 896 fprintf(stdout, "\t}\n"); 897 898 fputs("#endif /* DNS_CODE_H */\n", stdout); 899 } else if (type_enum) { 900 char *s; 901 902 fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n"); 903 fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n"); 904 905 fprintf(stdout, "enum {\n"); 906 fprintf(stdout, "\tdns_rdatatype_none = 0,\n"); 907 908 lasttype = 0; 909 for (tt = types; tt != NULL; tt = tt->next) { 910 if (tt->type != lasttype) { 911 fprintf(stdout, "\tdns_rdatatype_%s = %d,\n", 912 funname(tt->typebuf, buf1), 913 lasttype = tt->type); 914 } 915 } 916 917 fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n"); 918 fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n"); 919 fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n"); 920 fprintf(stdout, "\tdns_rdatatype_maila = 254,\n"); 921 fprintf(stdout, "\tdns_rdatatype_any = 255\n"); 922 923 fprintf(stdout, "};\n\n"); 924 925 fprintf(stdout, "#define dns_rdatatype_none\t" 926 "((dns_rdatatype_t)dns_rdatatype_none)\n"); 927 928 for (tt = types; tt != NULL; tt = tt->next) { 929 if (tt->type != lasttype) { 930 s = funname(tt->typebuf, buf1); 931 fprintf(stdout, 932 "#define dns_rdatatype_%s\t%s" 933 "((dns_rdatatype_t)dns_rdatatype_%s)" 934 "\n", 935 s, strlen(s) < 2U ? "\t" : "", s); 936 lasttype = tt->type; 937 } 938 } 939 940 fprintf(stdout, "#define dns_rdatatype_ixfr\t" 941 "((dns_rdatatype_t)dns_rdatatype_ixfr)\n"); 942 fprintf(stdout, "#define dns_rdatatype_axfr\t" 943 "((dns_rdatatype_t)dns_rdatatype_axfr)\n"); 944 fprintf(stdout, "#define dns_rdatatype_mailb\t" 945 "((dns_rdatatype_t)dns_rdatatype_mailb)\n"); 946 fprintf(stdout, "#define dns_rdatatype_maila\t" 947 "((dns_rdatatype_t)dns_rdatatype_maila)\n"); 948 fprintf(stdout, "#define dns_rdatatype_any\t" 949 "((dns_rdatatype_t)dns_rdatatype_any)\n"); 950 951 fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n"); 952 } else if (class_enum) { 953 char *s; 954 int classnum; 955 956 fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n"); 957 fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n"); 958 959 fprintf(stdout, "enum {\n"); 960 961 fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n"); 962 fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t" 963 "((dns_rdataclass_t)dns_rdataclass_reserved0)" 964 "\n"); 965 966 #define PRINTCLASS(name, num) \ 967 do { \ 968 s = funname(name, buf1); \ 969 classnum = num; \ 970 fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \ 971 classnum != 255 ? "," : ""); \ 972 fprintf(stdout, \ 973 "#define dns_rdataclass_%s\t" \ 974 "((dns_rdataclass_t)dns_rdataclass_%s)\n", \ 975 s, s); \ 976 } while (0) 977 978 for (cc = classes; cc != NULL; cc = cc->next) { 979 if (cc->rdclass == 3) { 980 PRINTCLASS("chaos", 3); 981 } else if (cc->rdclass == 255) { 982 PRINTCLASS("none", 254); 983 } 984 PRINTCLASS(cc->classbuf, cc->rdclass); 985 } 986 987 #undef PRINTCLASS 988 989 fprintf(stdout, "};\n\n"); 990 fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n"); 991 } else if (structs) { 992 if (prefix != NULL) { 993 if ((fd = fopen(prefix, "r")) != NULL) { 994 while (fgets(buf, sizeof(buf), fd) != NULL) { 995 fputs(buf, stdout); 996 } 997 fclose(fd); 998 } 999 } 1000 for (tt = types; tt != NULL; tt = tt->next) { 1001 snprintf(buf, sizeof(buf), "%s/%s_%d.h", tt->dirbuf, 1002 tt->typebuf, tt->type); 1003 if ((fd = fopen(buf, "r")) != NULL) { 1004 while (fgets(buf, sizeof(buf), fd) != NULL) { 1005 fputs(buf, stdout); 1006 } 1007 fclose(fd); 1008 } 1009 } 1010 if (suffix != NULL) { 1011 if ((fd = fopen(suffix, "r")) != NULL) { 1012 while (fgets(buf, sizeof(buf), fd) != NULL) { 1013 fputs(buf, stdout); 1014 } 1015 fclose(fd); 1016 } 1017 } 1018 } else if (depend) { 1019 for (tt = types; tt != NULL; tt = tt->next) { 1020 fprintf(stdout, "%s:\t%s/%s_%d.h\n", file, tt->dirbuf, 1021 tt->typebuf, tt->type); 1022 } 1023 } 1024 1025 if (ferror(stdout) != 0) { 1026 exit(1); 1027 } 1028 1029 return (0); 1030 } 1031