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