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