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 #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 int dump_deviceids_pci (void);
64 static int dump_deviceids_pcmcia (void);
65 static int 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 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
98 void
section_add(const char * s)99 section_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
111 static struct assign *
find_assign(const char * s,const char * k)112 find_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
137 static struct assign *
find_next_assign(struct assign * a)138 find_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
155 static const char *
stringcvt(const char * s)156 stringcvt(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
166 struct section *
find_section(const char * s)167 find_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
178 static void
dump_pcmcia_id(const char * s)179 dump_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
226 static void
dump_pci_id(const char * s)227 dump_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
259 static void
dump_usb_id(const char * s)260 dump_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
283 static int
dump_deviceids_pci()284 dump_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
295 nextmanf:
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
333 retry:
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
368 done:
369 /* Emit end of table */
370
371 fprintf(ofp, "\n\n");
372
373 return (found);
374 }
375
376 static int
dump_deviceids_pcmcia()377 dump_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
388 nextmanf:
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
426 retry:
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
461 done:
462 /* Emit end of table */
463
464 fprintf(ofp, "\n\n");
465
466 return (found);
467 }
468
469 static int
dump_deviceids_usb()470 dump_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
481 nextmanf:
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
519 retry:
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
554 done:
555 /* Emit end of table */
556
557 fprintf(ofp, "\n\n");
558
559 return (found);
560 }
561
562 static void
dump_addreg(const char * s,int devidx)563 dump_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
597 static void
dump_enumreg(const struct section * s,const struct reg * r)598 dump_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
615 static void
dump_editreg(const struct section * s,const struct reg * r)616 dump_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 */
637 static void
dump_dwordreg(const struct section * s,const struct reg * r)638 dump_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
657 static void
dump_defaultinfo(const struct section * s,const struct reg * r,int devidx)658 dump_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
677 static void
dump_paramdesc(const struct section * s,const struct reg * r)678 dump_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
694 static void
dump_typeinfo(const struct section * s,const struct reg * r)695 dump_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
718 static void
dump_paramreg(const struct section * s,const struct reg * r,int devidx)719 dump_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
733 static void
dump_regvals(void)734 dump_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
753 nextmanf:
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
769 retry:
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
826 void
assign_add(const char * a)827 assign_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
844 void
define_add(const char * d __unused)845 define_add (const char *d __unused)
846 {
847 #ifdef notdef
848 fprintf(stderr, "define \"%s\"\n", d);
849 #endif
850 return;
851 }
852
853 static char *
sstrdup(const char * str)854 sstrdup(const char *str)
855 {
856 if (str != NULL && strlen(str))
857 return (strdup(str));
858 return (NULL);
859 }
860
861 static int
satoi(const char * nptr)862 satoi (const char *nptr)
863 {
864 if (nptr != NULL && strlen(nptr))
865 return (atoi(nptr));
866 return (0);
867 }
868
869 void
regkey_add(const char * r)870 regkey_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
889 void
push_word(const char * w)890 push_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
905 void
clear_words(void)906 clear_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