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