xref: /NextBSD/usr.sbin/ndiscvt/inf.c (revision 84d351007654069f9643c8e4b4802a7f5f08ee42)
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