1 /*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 2003
5 * Bill Paul <[email protected]>. 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
47 extern FILE *yyin;
48 int yyparse (void);
49
50 const char *words[W_MAX]; /* More than we'll need. */
51 int idx;
52
53 static struct section_head sh;
54 static struct reg_head rh;
55 static struct assign_head ah;
56
57 static char *sstrdup (const char *);
58 static struct assign
59 *find_assign (const char *, const char *);
60 static struct assign
61 *find_next_assign
62 (struct assign *);
63 static struct section
64 *find_section (const char *);
65 static int dump_deviceids_pci (void);
66 static int dump_deviceids_pcmcia (void);
67 static int dump_deviceids_usb (void);
68 static void dump_pci_id (const char *);
69 static void dump_pcmcia_id (const char *);
70 static void dump_usb_id (const char *);
71 static void dump_regvals (void);
72 static void dump_paramreg (const struct section *,
73 const struct reg *, int);
74
75 static FILE *ofp;
76
77 int
inf_parse(FILE * fp,FILE * outfp)78 inf_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
100 void
section_add(const char * s)101 section_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
113 static struct assign *
find_assign(const char * s,const char * k)114 find_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
139 static struct assign *
find_next_assign(struct assign * a)140 find_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
157 static const char *
stringcvt(const char * s)158 stringcvt(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
168 struct section *
find_section(const char * s)169 find_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
180 static void
dump_pcmcia_id(const char * s)181 dump_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
228 static void
dump_pci_id(const char * s)229 dump_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
261 static void
dump_usb_id(const char * s)262 dump_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
285 static int
dump_deviceids_pci()286 dump_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
297 nextmanf:
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
335 retry:
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
370 done:
371 /* Emit end of table */
372
373 fprintf(ofp, "\n\n");
374
375 return (found);
376 }
377
378 static int
dump_deviceids_pcmcia()379 dump_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
390 nextmanf:
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
428 retry:
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
463 done:
464 /* Emit end of table */
465
466 fprintf(ofp, "\n\n");
467
468 return (found);
469 }
470
471 static int
dump_deviceids_usb()472 dump_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
483 nextmanf:
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
521 retry:
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
556 done:
557 /* Emit end of table */
558
559 fprintf(ofp, "\n\n");
560
561 return (found);
562 }
563
564 static void
dump_addreg(const char * s,int devidx)565 dump_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
599 static void
dump_enumreg(const struct section * s,const struct reg * r)600 dump_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
617 static void
dump_editreg(const struct section * s,const struct reg * r)618 dump_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 */
639 static void
dump_dwordreg(const struct section * s,const struct reg * r)640 dump_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
659 static void
dump_defaultinfo(const struct section * s,const struct reg * r,int devidx)660 dump_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
679 static void
dump_paramdesc(const struct section * s,const struct reg * r)680 dump_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
696 static void
dump_typeinfo(const struct section * s,const struct reg * r)697 dump_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
720 static void
dump_paramreg(const struct section * s,const struct reg * r,int devidx)721 dump_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
735 static void
dump_regvals(void)736 dump_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
755 nextmanf:
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
771 retry:
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
828 void
assign_add(const char * a)829 assign_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
846 void
define_add(const char * d __unused)847 define_add (const char *d __unused)
848 {
849 #ifdef notdef
850 fprintf(stderr, "define \"%s\"\n", d);
851 #endif
852 return;
853 }
854
855 static char *
sstrdup(const char * str)856 sstrdup(const char *str)
857 {
858 if (str != NULL && strlen(str))
859 return (strdup(str));
860 return (NULL);
861 }
862
863 static int
satoi(const char * nptr)864 satoi (const char *nptr)
865 {
866 if (nptr != NULL && strlen(nptr))
867 return (atoi(nptr));
868 return (0);
869 }
870
871 void
regkey_add(const char * r)872 regkey_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
891 void
push_word(const char * w)892 push_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
907 void
clear_words(void)908 clear_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