xref: /freebsd-12.1/usr.sbin/ndiscvt/inf.c (revision dc177ebe)
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