xref: /freebsd-13-stable/usr.sbin/ndiscvt/inf.c (revision 3d497e17ebd33fe0f58d773e35ab994d750258d6)
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