1/* 2 * Copyright (c) 2003 3 * Bill Paul <wpaul@windriver.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD$"); 35 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <sys/types.h> 40 41#include <sys/queue.h> 42 43#include "inf.h" 44 45extern FILE *yyin; 46int yyparse (void); 47 48const char *words[W_MAX]; /* More than we'll need. */ 49int idx; 50 51static struct section_head sh; 52static struct reg_head rh; 53static struct assign_head ah; 54 55static char *sstrdup (const char *); 56static struct assign 57 *find_assign (const char *, const char *); 58static struct assign 59 *find_next_assign 60 (struct assign *); 61static struct section 62 *find_section (const char *); 63static void dump_deviceids_pci (void); 64static void dump_deviceids_pcmcia (void); 65static void dump_deviceids_usb (void); 66static void dump_pci_id (const char *); 67static void dump_pcmcia_id (const char *); 68static void dump_usb_id (const char *); 69static void dump_regvals (void); 70static void dump_paramreg (const struct section *, 71 const struct reg *, int); 72 73static FILE *ofp; 74 75int 76inf_parse (FILE *fp, FILE *outfp) 77{ 78 TAILQ_INIT(&sh); 79 TAILQ_INIT(&rh); 80 TAILQ_INIT(&ah); 81 82 ofp = outfp; 83 yyin = fp; 84 yyparse(); 85 86 dump_deviceids_pci(); 87 dump_deviceids_pcmcia(); 88 dump_deviceids_usb(); 89 fprintf(outfp, "#ifdef NDIS_REGVALS\n"); 90 dump_regvals(); 91 fprintf(outfp, "#endif /* NDIS_REGVALS */\n"); 92 93 return (0); 94} 95 96void 97section_add (const char *s) 98{ 99 struct section *sec; 100 101 sec = malloc(sizeof(struct section)); 102 bzero(sec, sizeof(struct section)); 103 sec->name = s; 104 TAILQ_INSERT_TAIL(&sh, sec, link); 105 106 return; 107} 108 109static struct assign * 110find_assign (const char *s, const char *k) 111{ 112 struct assign *assign; 113 char newkey[256]; 114 115 /* Deal with string section lookups. */ 116 117 if (k != NULL && k[0] == '%') { 118 bzero(newkey, sizeof(newkey)); 119 strncpy(newkey, k + 1, strlen(k) - 2); 120 k = newkey; 121 } 122 123 TAILQ_FOREACH(assign, &ah, link) { 124 if (strcasecmp(assign->section->name, s) == 0) { 125 if (k == NULL) 126 return(assign); 127 else 128 if (strcasecmp(assign->key, k) == 0) 129 return(assign); 130 } 131 } 132 return(NULL); 133} 134 135static struct assign * 136find_next_assign (struct assign *a) 137{ 138 struct assign *assign; 139 140 TAILQ_FOREACH(assign, &ah, link) { 141 if (assign == a) 142 break; 143 } 144 145 assign = assign->link.tqe_next; 146 147 if (assign == NULL || assign->section != a->section) 148 return(NULL); 149 150 return (assign); 151} 152 153static const char * 154stringcvt(const char *s) 155{ 156 struct assign *manf; 157 158 manf = find_assign("strings", s); 159 if (manf == NULL) 160 return(s); 161 return(manf->vals[0]); 162} 163 164struct section * 165find_section (const char *s) 166{ 167 struct section *section; 168 169 TAILQ_FOREACH(section, &sh, link) { 170 if (strcasecmp(section->name, s) == 0) 171 return(section); 172 } 173 return(NULL); 174} 175 176static void 177dump_pcmcia_id(const char *s) 178{ 179 char *manstr, *devstr; 180 char *p0, *p; 181 182 p0 = __DECONST(char *, s); 183 184 p = strchr(p0, '\\'); 185 if (p == NULL) 186 return; 187 p0 = p + 1; 188 189 p = strchr(p0, '-'); 190 if (p == NULL) 191 return; 192 *p = '\0'; 193 194 manstr = p0; 195 196 /* Convert any underscores to spaces. */ 197 198 while (*p0 != '\0') { 199 if (*p0 == '_') 200 *p0 = ' '; 201 p0++; 202 } 203 204 p0 = p + 1; 205 p = strchr(p0, '-'); 206 if (p == NULL) 207 return; 208 *p = '\0'; 209 210 devstr = p0; 211 212 /* Convert any underscores to spaces. */ 213 214 while (*p0 != '\0') { 215 if (*p0 == '_') 216 *p0 = ' '; 217 p0++; 218 } 219 220 fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr); 221 return; 222} 223 224static void 225dump_pci_id(const char *s) 226{ 227 char *p; 228 char vidstr[7], didstr[7], subsysstr[14]; 229 230 p = strcasestr(s, "VEN_"); 231 if (p == NULL) 232 return; 233 p += 4; 234 strcpy(vidstr, "0x"); 235 strncat(vidstr, p, 4); 236 p = strcasestr(s, "DEV_"); 237 if (p == NULL) 238 return; 239 p += 4; 240 strcpy(didstr, "0x"); 241 strncat(didstr, p, 4); 242 if (p == NULL) 243 return; 244 p = strcasestr(s, "SUBSYS_"); 245 if (p == NULL) 246 strcpy(subsysstr, "0x00000000"); 247 else { 248 p += 7; 249 strcpy(subsysstr, "0x"); 250 strncat(subsysstr, p, 8); 251 } 252 253 fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr); 254 return; 255} 256 257static void 258dump_usb_id(const char *s) 259{ 260 char *p; 261 char vidstr[7], pidstr[7]; 262 263 p = strcasestr(s, "VID_"); 264 if (p == NULL) 265 return; 266 p += 4; 267 strcpy(vidstr, "0x"); 268 strncat(vidstr, p, 4); 269 p = strcasestr(s, "PID_"); 270 if (p == NULL) 271 return; 272 p += 4; 273 strcpy(pidstr, "0x"); 274 strncat(pidstr, p, 4); 275 if (p == NULL) 276 return; 277 278 fprintf(ofp, "\t\\\n\t{ %s, %s, ", vidstr, pidstr); 279} 280 281static void 282dump_deviceids_pci() 283{ 284 struct assign *manf, *dev; 285 struct section *sec; 286 struct assign *assign; 287 char xpsec[256]; 288 int first = 1, found = 0; 289 290 /* Find manufacturer name */ 291 manf = find_assign("Manufacturer", NULL); 292 293nextmanf: 294 295 /* Find manufacturer section */ 296 if (manf->vals[1] != NULL && 297 (strcasecmp(manf->vals[1], "NT.5.1") == 0 || 298 strcasecmp(manf->vals[1], "NTx86") == 0 || 299 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 || 300 strcasecmp(manf->vals[1], "NTamd64") == 0)) { 301 /* Handle Windows XP INF files. */ 302 snprintf(xpsec, sizeof(xpsec), "%s.%s", 303 manf->vals[0], manf->vals[1]); 304 sec = find_section(xpsec); 305 } else 306 sec = find_section(manf->vals[0]); 307 308 /* See if there are any PCI device definitions. */ 309 310 TAILQ_FOREACH(assign, &ah, link) { 311 if (assign->section == sec) { 312 dev = find_assign("strings", assign->key); 313 if (strcasestr(assign->vals[1], "PCI") != NULL) { 314 found++; 315 break; 316 } 317 } 318 } 319 320 if (found == 0) 321 goto done; 322 323 found = 0; 324 325 if (first == 1) { 326 /* Emit start of PCI device table */ 327 fprintf (ofp, "#define NDIS_PCI_DEV_TABLE"); 328 first = 0; 329 } 330 331retry: 332 333 /* 334 * Now run through all the device names listed 335 * in the manufacturer section and dump out the 336 * device descriptions and vendor/device IDs. 337 */ 338 339 TAILQ_FOREACH(assign, &ah, link) { 340 if (assign->section == sec) { 341 dev = find_assign("strings", assign->key); 342 /* Emit device IDs. */ 343 if (strcasestr(assign->vals[1], "PCI") != NULL) 344 dump_pci_id(assign->vals[1]); 345 else 346 continue; 347 /* Emit device description */ 348 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]); 349 found++; 350 } 351 } 352 353 /* Someone tried to fool us. Shame on them. */ 354 if (!found) { 355 found++; 356 sec = find_section(manf->vals[0]); 357 goto retry; 358 } 359 360 /* Handle Manufacturer sections with multiple entries. */ 361 manf = find_next_assign(manf); 362 363 if (manf != NULL) 364 goto nextmanf; 365 366done: 367 /* Emit end of table */ 368 369 fprintf(ofp, "\n\n"); 370 371 return; 372} 373 374static void 375dump_deviceids_pcmcia() 376{ 377 struct assign *manf, *dev; 378 struct section *sec; 379 struct assign *assign; 380 char xpsec[256]; 381 int first = 1, found = 0; 382 383 /* Find manufacturer name */ 384 manf = find_assign("Manufacturer", NULL); 385 386nextmanf: 387 388 /* Find manufacturer section */ 389 if (manf->vals[1] != NULL && 390 (strcasecmp(manf->vals[1], "NT.5.1") == 0 || 391 strcasecmp(manf->vals[1], "NTx86") == 0 || 392 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 || 393 strcasecmp(manf->vals[1], "NTamd64") == 0)) { 394 /* Handle Windows XP INF files. */ 395 snprintf(xpsec, sizeof(xpsec), "%s.%s", 396 manf->vals[0], manf->vals[1]); 397 sec = find_section(xpsec); 398 } else 399 sec = find_section(manf->vals[0]); 400 401 /* See if there are any PCMCIA device definitions. */ 402 403 TAILQ_FOREACH(assign, &ah, link) { 404 if (assign->section == sec) { 405 dev = find_assign("strings", assign->key); 406 if (strcasestr(assign->vals[1], "PCMCIA") != NULL) { 407 found++; 408 break; 409 } 410 } 411 } 412 413 if (found == 0) 414 goto done; 415 416 found = 0; 417 418 if (first == 1) { 419 /* Emit start of PCMCIA device table */ 420 fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE"); 421 first = 0; 422 } 423 424retry: 425 426 /* 427 * Now run through all the device names listed 428 * in the manufacturer section and dump out the 429 * device descriptions and vendor/device IDs. 430 */ 431 432 TAILQ_FOREACH(assign, &ah, link) { 433 if (assign->section == sec) { 434 dev = find_assign("strings", assign->key); 435 /* Emit device IDs. */ 436 if (strcasestr(assign->vals[1], "PCMCIA") != NULL) 437 dump_pcmcia_id(assign->vals[1]); 438 else 439 continue; 440 /* Emit device description */ 441 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]); 442 found++; 443 } 444 } 445 446 /* Someone tried to fool us. Shame on them. */ 447 if (!found) { 448 found++; 449 sec = find_section(manf->vals[0]); 450 goto retry; 451 } 452 453 /* Handle Manufacturer sections with multiple entries. */ 454 manf = find_next_assign(manf); 455 456 if (manf != NULL) 457 goto nextmanf; 458 459done: 460 /* Emit end of table */ 461 462 fprintf(ofp, "\n\n"); 463 464 return; 465} 466 467static void 468dump_deviceids_usb() 469{ 470 struct assign *manf, *dev; 471 struct section *sec; 472 struct assign *assign; 473 char xpsec[256]; 474 int first = 1, found = 0; 475 476 /* Find manufacturer name */ 477 manf = find_assign("Manufacturer", NULL); 478 479nextmanf: 480 481 /* Find manufacturer section */ 482 if (manf->vals[1] != NULL && 483 (strcasecmp(manf->vals[1], "NT.5.1") == 0 || 484 strcasecmp(manf->vals[1], "NTx86") == 0 || 485 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 || 486 strcasecmp(manf->vals[1], "NTamd64") == 0)) { 487 /* Handle Windows XP INF files. */ 488 snprintf(xpsec, sizeof(xpsec), "%s.%s", 489 manf->vals[0], manf->vals[1]); 490 sec = find_section(xpsec); 491 } else 492 sec = find_section(manf->vals[0]); 493 494 /* See if there are any USB device definitions. */ 495 496 TAILQ_FOREACH(assign, &ah, link) { 497 if (assign->section == sec) { 498 dev = find_assign("strings", assign->key); 499 if (strcasestr(assign->vals[1], "USB") != NULL) { 500 found++; 501 break; 502 } 503 } 504 } 505 506 if (found == 0) 507 goto done; 508 509 found = 0; 510 511 if (first == 1) { 512 /* Emit start of USB device table */ 513 fprintf (ofp, "#define NDIS_USB_DEV_TABLE"); 514 first = 0; 515 } 516 517retry: 518 519 /* 520 * Now run through all the device names listed 521 * in the manufacturer section and dump out the 522 * device descriptions and vendor/device IDs. 523 */ 524 525 TAILQ_FOREACH(assign, &ah, link) { 526 if (assign->section == sec) { 527 dev = find_assign("strings", assign->key); 528 /* Emit device IDs. */ 529 if (strcasestr(assign->vals[1], "USB") != NULL) 530 dump_usb_id(assign->vals[1]); 531 else 532 continue; 533 /* Emit device description */ 534 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]); 535 found++; 536 } 537 } 538 539 /* Someone tried to fool us. Shame on them. */ 540 if (!found) { 541 found++; 542 sec = find_section(manf->vals[0]); 543 goto retry; 544 } 545 546 /* Handle Manufacturer sections with multiple entries. */ 547 manf = find_next_assign(manf); 548 549 if (manf != NULL) 550 goto nextmanf; 551 552done: 553 /* Emit end of table */ 554 555 fprintf(ofp, "\n\n"); 556 557 return; 558} 559 560static void 561dump_addreg(const char *s, int devidx) 562{ 563 struct section *sec; 564 struct reg *reg; 565 566 /* Find the addreg section */ 567 sec = find_section(s); 568 569 /* Dump all the keys defined in it. */ 570 TAILQ_FOREACH(reg, &rh, link) { 571 /* 572 * Keys with an empty subkey are very easy to parse, 573 * so just deal with them here. If a parameter key 574 * of the same name also exists, prefer that one and 575 * skip this one. 576 */ 577 if (reg->section == sec) { 578 if (reg->subkey == NULL) { 579 fprintf(ofp, "\n\t{ \"%s\",", reg->key); 580 fprintf(ofp,"\n\t\"%s \",", reg->key); 581 fprintf(ofp, "\n\t{ \"%s\" }, %d },", 582 reg->value == NULL ? "" : 583 stringcvt(reg->value), devidx); 584 } else if (strncasecmp(reg->subkey, 585 "Ndi\\params", strlen("Ndi\\params")-1) == 0 && 586 (reg->key != NULL && strcasecmp(reg->key, 587 "ParamDesc") == 0)) 588 dump_paramreg(sec, reg, devidx); 589 } 590 } 591 592 return; 593} 594 595static void 596dump_enumreg(const struct section *s, const struct reg *r) 597{ 598 struct reg *reg; 599 char enumkey[256]; 600 601 sprintf(enumkey, "%s\\enum", r->subkey); 602 TAILQ_FOREACH(reg, &rh, link) { 603 if (reg->section != s) 604 continue; 605 if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey)) 606 continue; 607 fprintf(ofp, " [%s=%s]", reg->key, 608 stringcvt(reg->value)); 609 } 610 return; 611} 612 613static void 614dump_editreg(const struct section *s, const struct reg *r) 615{ 616 struct reg *reg; 617 618 TAILQ_FOREACH(reg, &rh, link) { 619 if (reg->section != s) 620 continue; 621 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) 622 continue; 623 if (reg->key == NULL) 624 continue; 625 if (strcasecmp(reg->key, "LimitText") == 0) 626 fprintf(ofp, " [maxchars=%s]", reg->value); 627 if (strcasecmp(reg->key, "Optional") == 0 && 628 strcmp(reg->value, "1") == 0) 629 fprintf(ofp, " [optional]"); 630 } 631 return; 632} 633 634/* Use this for int too */ 635static void 636dump_dwordreg(const struct section *s, const struct reg *r) 637{ 638 struct reg *reg; 639 640 TAILQ_FOREACH(reg, &rh, link) { 641 if (reg->section != s) 642 continue; 643 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) 644 continue; 645 if (reg->key == NULL) 646 continue; 647 if (strcasecmp(reg->key, "min") == 0) 648 fprintf(ofp, " [min=%s]", reg->value); 649 if (strcasecmp(reg->key, "max") == 0) 650 fprintf(ofp, " [max=%s]", reg->value); 651 } 652 return; 653} 654 655static void 656dump_defaultinfo(const struct section *s, const struct reg *r, int devidx) 657{ 658 struct reg *reg; 659 TAILQ_FOREACH(reg, &rh, link) { 660 if (reg->section != s) 661 continue; 662 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) 663 continue; 664 if (reg->key == NULL || strcasecmp(reg->key, "Default")) 665 continue; 666 fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" : 667 stringcvt(reg->value), devidx); 668 return; 669 } 670 /* Default registry entry missing */ 671 fprintf(ofp, "\n\t{ \"\" }, %d },", devidx); 672 return; 673} 674 675static void 676dump_paramdesc(const struct section *s, const struct reg *r) 677{ 678 struct reg *reg; 679 TAILQ_FOREACH(reg, &rh, link) { 680 if (reg->section != s) 681 continue; 682 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) 683 continue; 684 if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc")) 685 continue; 686 fprintf(ofp, "\n\t\"%s", stringcvt(r->value)); 687 break; 688 } 689 return; 690} 691 692static void 693dump_typeinfo(const struct section *s, const struct reg *r) 694{ 695 struct reg *reg; 696 TAILQ_FOREACH(reg, &rh, link) { 697 if (reg->section != s) 698 continue; 699 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey)) 700 continue; 701 if (reg->key == NULL) 702 continue; 703 if (strcasecmp(reg->key, "type")) 704 continue; 705 if (strcasecmp(reg->value, "dword") == 0 || 706 strcasecmp(reg->value, "int") == 0) 707 dump_dwordreg(s, r); 708 if (strcasecmp(reg->value, "enum") == 0) 709 dump_enumreg(s, r); 710 if (strcasecmp(reg->value, "edit") == 0) 711 dump_editreg(s, r); 712 } 713 return; 714} 715 716static void 717dump_paramreg(const struct section *s, const struct reg *r, int devidx) 718{ 719 const char *keyname; 720 721 keyname = r->subkey + strlen("Ndi\\params\\"); 722 fprintf(ofp, "\n\t{ \"%s\",", keyname); 723 dump_paramdesc(s, r); 724 dump_typeinfo(s, r); 725 fprintf(ofp, "\","); 726 dump_defaultinfo(s, r, devidx); 727 728 return; 729} 730 731static void 732dump_regvals(void) 733{ 734 struct assign *manf, *dev; 735 struct section *sec; 736 struct assign *assign; 737 char sname[256]; 738 int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0; 739 740 /* Find signature to check for special case of WinNT. */ 741 assign = find_assign("version", "signature"); 742 if (strcasecmp(assign->vals[0], "$windows nt$") == 0) 743 is_winnt++; 744 745 /* Emit start of block */ 746 fprintf (ofp, "ndis_cfg ndis_regvals[] = {"); 747 748 /* Find manufacturer name */ 749 manf = find_assign("Manufacturer", NULL); 750 751nextmanf: 752 753 /* Find manufacturer section */ 754 if (manf->vals[1] != NULL && 755 (strcasecmp(manf->vals[1], "NT.5.1") == 0 || 756 strcasecmp(manf->vals[1], "NTx86") == 0 || 757 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 || 758 strcasecmp(manf->vals[1], "NTamd64") == 0)) { 759 is_winxp++; 760 /* Handle Windows XP INF files. */ 761 snprintf(sname, sizeof(sname), "%s.%s", 762 manf->vals[0], manf->vals[1]); 763 sec = find_section(sname); 764 } else 765 sec = find_section(manf->vals[0]); 766 767retry: 768 769 TAILQ_FOREACH(assign, &ah, link) { 770 if (assign->section == sec) { 771 found++; 772 /* 773 * Find all the AddReg sections. 774 * Look for section names with .NT, unless 775 * this is a WinXP .INF file. 776 */ 777 778 if (is_winxp) { 779 sprintf(sname, "%s.NTx86", assign->vals[0]); 780 dev = find_assign(sname, "AddReg"); 781 if (dev == NULL) { 782 sprintf(sname, "%s.NT", 783 assign->vals[0]); 784 dev = find_assign(sname, "AddReg"); 785 } 786 if (dev == NULL) 787 dev = find_assign(assign->vals[0], 788 "AddReg"); 789 } else { 790 sprintf(sname, "%s.NT", assign->vals[0]); 791 dev = find_assign(sname, "AddReg"); 792 if (dev == NULL && is_winnt) 793 dev = find_assign(assign->vals[0], 794 "AddReg"); 795 } 796 /* Section not found. */ 797 if (dev == NULL) 798 continue; 799 for (i = 0; i < W_MAX; i++) { 800 if (dev->vals[i] != NULL) 801 dump_addreg(dev->vals[i], devidx); 802 } 803 devidx++; 804 } 805 } 806 807 if (!found) { 808 sec = find_section(manf->vals[0]); 809 is_winxp = 0; 810 found++; 811 goto retry; 812 } 813 814 manf = find_next_assign(manf); 815 816 if (manf != NULL) 817 goto nextmanf; 818 819 fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n"); 820 821 return; 822} 823 824void 825assign_add (const char *a) 826{ 827 struct assign *assign; 828 int i; 829 830 assign = malloc(sizeof(struct assign)); 831 bzero(assign, sizeof(struct assign)); 832 assign->section = TAILQ_LAST(&sh, section_head); 833 assign->key = sstrdup(a); 834 for (i = 0; i < idx; i++) 835 assign->vals[(idx - 1) - i] = sstrdup(words[i]); 836 TAILQ_INSERT_TAIL(&ah, assign, link); 837 838 clear_words(); 839 return; 840} 841 842void 843define_add (const char *d __unused) 844{ 845#ifdef notdef 846 fprintf(stderr, "define \"%s\"\n", d); 847#endif 848 return; 849} 850 851static char * 852sstrdup(const char *str) 853{ 854 if (str != NULL && strlen(str)) 855 return (strdup(str)); 856 return (NULL); 857} 858 859static int 860satoi (const char *nptr) 861{ 862 if (nptr != NULL && strlen(nptr)) 863 return (atoi(nptr)); 864 return (0); 865} 866 867void 868regkey_add (const char *r) 869{ 870 struct reg *reg; 871 872 reg = malloc(sizeof(struct reg)); 873 bzero(reg, sizeof(struct reg)); 874 reg->section = TAILQ_LAST(&sh, section_head); 875 reg->root = sstrdup(r); 876 reg->subkey = sstrdup(words[3]); 877 reg->key = sstrdup(words[2]); 878 reg->flags = satoi(words[1]); 879 reg->value = sstrdup(words[0]); 880 TAILQ_INSERT_TAIL(&rh, reg, link); 881 882 free(__DECONST(char *, r)); 883 clear_words(); 884 return; 885} 886 887void 888push_word (const char *w) 889{ 890 if (w && strlen(w)) 891 words[idx++] = w; 892 else 893 words[idx++] = NULL; 894 return; 895} 896 897void 898clear_words (void) 899{ 900 int i; 901 902 for (i = 0; i < idx; i++) { 903 if (words[i]) { 904 free(__DECONST(char *, words[i])); 905 } 906 } 907 idx = 0; 908 bzero(words, sizeof(words)); 909 return; 910} 911