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
45 extern FILE *yyin;
46 int yyparse (void);
47
48 const char *words[W_MAX]; /* More than we'll need. */
49 int idx;
50
51 static struct section_head sh;
52 static struct reg_head rh;
53 static struct assign_head ah;
54
55 static char *sstrdup (const char *);
56 static struct assign
57 *find_assign (const char *, const char *);
58 static struct assign
59 *find_next_assign
60 (struct assign *);
61 static struct section
62 *find_section (const char *);
63 static void dump_deviceids_pci (void);
64 static void dump_deviceids_pcmcia (void);
65 static void dump_deviceids_usb (void);
66 static void dump_pci_id (const char *);
67 static void dump_pcmcia_id (const char *);
68 static void dump_usb_id (const char *);
69 static void dump_regvals (void);
70 static void dump_paramreg (const struct section *,
71 const struct reg *, int);
72
73 static FILE *ofp;
74
75 int
inf_parse(FILE * fp,FILE * outfp)76 inf_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
96 void
section_add(const char * s)97 section_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
109 static struct assign *
find_assign(const char * s,const char * k)110 find_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
135 static struct assign *
find_next_assign(struct assign * a)136 find_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
153 static const char *
stringcvt(const char * s)154 stringcvt(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
164 struct section *
find_section(const char * s)165 find_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
176 static void
dump_pcmcia_id(const char * s)177 dump_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
224 static void
dump_pci_id(const char * s)225 dump_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
257 static void
dump_usb_id(const char * s)258 dump_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
281 static void
dump_deviceids_pci()282 dump_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
293 nextmanf:
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
331 retry:
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
366 done:
367 /* Emit end of table */
368
369 fprintf(ofp, "\n\n");
370
371 return;
372 }
373
374 static void
dump_deviceids_pcmcia()375 dump_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
386 nextmanf:
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
424 retry:
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
459 done:
460 /* Emit end of table */
461
462 fprintf(ofp, "\n\n");
463
464 return;
465 }
466
467 static void
dump_deviceids_usb()468 dump_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
479 nextmanf:
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
517 retry:
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
552 done:
553 /* Emit end of table */
554
555 fprintf(ofp, "\n\n");
556
557 return;
558 }
559
560 static void
dump_addreg(const char * s,int devidx)561 dump_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
595 static void
dump_enumreg(const struct section * s,const struct reg * r)596 dump_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
613 static void
dump_editreg(const struct section * s,const struct reg * r)614 dump_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 */
635 static void
dump_dwordreg(const struct section * s,const struct reg * r)636 dump_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
655 static void
dump_defaultinfo(const struct section * s,const struct reg * r,int devidx)656 dump_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
675 static void
dump_paramdesc(const struct section * s,const struct reg * r)676 dump_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
692 static void
dump_typeinfo(const struct section * s,const struct reg * r)693 dump_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
716 static void
dump_paramreg(const struct section * s,const struct reg * r,int devidx)717 dump_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
731 static void
dump_regvals(void)732 dump_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
751 nextmanf:
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
767 retry:
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
824 void
assign_add(const char * a)825 assign_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
842 void
define_add(const char * d __unused)843 define_add (const char *d __unused)
844 {
845 #ifdef notdef
846 fprintf(stderr, "define \"%s\"\n", d);
847 #endif
848 return;
849 }
850
851 static char *
sstrdup(const char * str)852 sstrdup(const char *str)
853 {
854 if (str != NULL && strlen(str))
855 return (strdup(str));
856 return (NULL);
857 }
858
859 static int
satoi(const char * nptr)860 satoi (const char *nptr)
861 {
862 if (nptr != NULL && strlen(nptr))
863 return (atoi(nptr));
864 return (0);
865 }
866
867 void
regkey_add(const char * r)868 regkey_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
887 void
push_word(const char * w)888 push_word (const char *w)
889 {
890
891 if (idx == W_MAX) {
892 fprintf(stderr, "too many words; try bumping W_MAX in inf.h\n");
893 exit(1);
894 }
895
896 if (w && strlen(w))
897 words[idx++] = w;
898 else
899 words[idx++] = NULL;
900 return;
901 }
902
903 void
clear_words(void)904 clear_words (void)
905 {
906 int i;
907
908 for (i = 0; i < idx; i++) {
909 if (words[i]) {
910 free(__DECONST(char *, words[i]));
911 }
912 }
913 idx = 0;
914 bzero(words, sizeof(words));
915 return;
916 }
917