1123475Swpaul/*
2124060Swpaul * Copyright (c) 2003
3124060Swpaul *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
4124060Swpaul *
5124060Swpaul * Redistribution and use in source and binary forms, with or without
6124060Swpaul * modification, are permitted provided that the following conditions
7124060Swpaul * are met:
8124060Swpaul * 1. Redistributions of source code must retain the above copyright
9124060Swpaul *    notice, this list of conditions and the following disclaimer.
10124060Swpaul * 2. Redistributions in binary form must reproduce the above copyright
11124060Swpaul *    notice, this list of conditions and the following disclaimer in the
12124060Swpaul *    documentation and/or other materials provided with the distribution.
13124060Swpaul * 3. All advertising materials mentioning features or use of this software
14124060Swpaul *    must display the following acknowledgement:
15124060Swpaul *	This product includes software developed by Bill Paul.
16124060Swpaul * 4. Neither the name of the author nor the names of any co-contributors
17124060Swpaul *    may be used to endorse or promote products derived from this software
18124060Swpaul *    without specific prior written permission.
19124060Swpaul *
20124060Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21124060Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22124060Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23124060Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24124060Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25124060Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26124060Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27124060Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28124060Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29124060Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30124060Swpaul * THE POSSIBILITY OF SUCH DAMAGE.
31123475Swpaul */
32123475Swpaul
33123475Swpaul#include <sys/cdefs.h>
34123475Swpaul__FBSDID("$FreeBSD$");
35123475Swpaul
36123475Swpaul#include <stdio.h>
37123475Swpaul#include <stdlib.h>
38123475Swpaul#include <string.h>
39123475Swpaul#include <sys/types.h>
40123475Swpaul
41123475Swpaul#include <sys/queue.h>
42123475Swpaul
43123475Swpaul#include "inf.h"
44123475Swpaul
45123475Swpaulextern FILE *yyin;
46123475Swpaulint yyparse (void);
47123475Swpaul
48123475Swpaulconst char *words[W_MAX];	/* More than we'll need. */
49123475Swpaulint idx;
50123475Swpaul
51123475Swpaulstatic struct section_head sh;
52123475Swpaulstatic struct reg_head rh;
53123475Swpaulstatic struct assign_head ah;
54123475Swpaul
55123475Swpaulstatic char	*sstrdup	(const char *);
56123475Swpaulstatic struct assign
57123475Swpaul		*find_assign	(const char *, const char *);
58146243Swpaulstatic struct assign
59146243Swpaul		*find_next_assign
60146243Swpaul				(struct assign *);
61123475Swpaulstatic struct section
62123475Swpaul		*find_section	(const char *);
63126706Swpaulstatic void	dump_deviceids_pci	(void);
64126706Swpaulstatic void	dump_deviceids_pcmcia	(void);
65186507Sweongyostatic void	dump_deviceids_usb	(void);
66123475Swpaulstatic void	dump_pci_id	(const char *);
67126706Swpaulstatic void	dump_pcmcia_id	(const char *);
68186507Sweongyostatic void	dump_usb_id	(const char *);
69141981Swpaulstatic void	dump_regvals	(void);
70123620Swpaulstatic void	dump_paramreg	(const struct section *,
71123620Swpaul				const struct reg *, int);
72123475Swpaul
73123475Swpaulstatic FILE	*ofp;
74123475Swpaul
75123475Swpaulint
76123475Swpaulinf_parse (FILE *fp, FILE *outfp)
77123475Swpaul{
78123475Swpaul	TAILQ_INIT(&sh);
79123475Swpaul	TAILQ_INIT(&rh);
80123475Swpaul	TAILQ_INIT(&ah);
81123475Swpaul
82123475Swpaul	ofp = outfp;
83123475Swpaul	yyin = fp;
84123475Swpaul	yyparse();
85123475Swpaul
86126706Swpaul	dump_deviceids_pci();
87126706Swpaul	dump_deviceids_pcmcia();
88186507Sweongyo	dump_deviceids_usb();
89126706Swpaul	fprintf(outfp, "#ifdef NDIS_REGVALS\n");
90123475Swpaul	dump_regvals();
91126706Swpaul	fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
92123475Swpaul
93123475Swpaul	return (0);
94123475Swpaul}
95123475Swpaul
96123475Swpaulvoid
97123475Swpaulsection_add (const char *s)
98123475Swpaul{
99123475Swpaul	struct section *sec;
100123475Swpaul
101123475Swpaul	sec = malloc(sizeof(struct section));
102123475Swpaul	bzero(sec, sizeof(struct section));
103123475Swpaul	sec->name = s;
104123475Swpaul	TAILQ_INSERT_TAIL(&sh, sec, link);
105123475Swpaul
106123475Swpaul	return;
107123475Swpaul}
108123475Swpaul
109123475Swpaulstatic struct assign *
110123475Swpaulfind_assign (const char *s, const char *k)
111123475Swpaul{
112123475Swpaul	struct assign *assign;
113123475Swpaul	char newkey[256];
114123475Swpaul
115123475Swpaul	/* Deal with string section lookups. */
116123475Swpaul
117123475Swpaul	if (k != NULL && k[0] == '%') {
118123475Swpaul		bzero(newkey, sizeof(newkey));
119123475Swpaul		strncpy(newkey, k + 1, strlen(k) - 2);
120123475Swpaul		k = newkey;
121123475Swpaul	}
122123475Swpaul
123123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
124123475Swpaul		if (strcasecmp(assign->section->name, s) == 0) {
125123475Swpaul			if (k == NULL)
126123475Swpaul				return(assign);
127123475Swpaul			else
128123475Swpaul				if (strcasecmp(assign->key, k) == 0)
129123475Swpaul					return(assign);
130123475Swpaul		}
131123475Swpaul	}
132123475Swpaul	return(NULL);
133123475Swpaul}
134123475Swpaul
135146243Swpaulstatic struct assign *
136146243Swpaulfind_next_assign (struct assign *a)
137146243Swpaul{
138146243Swpaul	struct assign *assign;
139146243Swpaul
140146243Swpaul	TAILQ_FOREACH(assign, &ah, link) {
141146243Swpaul		if (assign == a)
142146243Swpaul			break;
143146243Swpaul	}
144146243Swpaul
145146243Swpaul	assign = assign->link.tqe_next;
146146243Swpaul
147146243Swpaul	if (assign == NULL || assign->section != a->section)
148146243Swpaul		return(NULL);
149146243Swpaul
150146243Swpaul	return (assign);
151146243Swpaul}
152146243Swpaul
153123475Swpaulstatic const char *
154123475Swpaulstringcvt(const char *s)
155123475Swpaul{
156123475Swpaul	struct assign *manf;
157123475Swpaul
158123475Swpaul	manf = find_assign("strings", s);
159123475Swpaul	if (manf == NULL)
160123475Swpaul		return(s);
161123475Swpaul	return(manf->vals[0]);
162123475Swpaul}
163123475Swpaul
164123475Swpaulstruct section *
165123475Swpaulfind_section (const char *s)
166123475Swpaul{
167123475Swpaul	struct section *section;
168123475Swpaul
169123475Swpaul	TAILQ_FOREACH(section, &sh, link) {
170123475Swpaul		if (strcasecmp(section->name, s) == 0)
171123475Swpaul			return(section);
172123475Swpaul	}
173123475Swpaul	return(NULL);
174123475Swpaul}
175123475Swpaul
176123475Swpaulstatic void
177126706Swpauldump_pcmcia_id(const char *s)
178126706Swpaul{
179126706Swpaul	char *manstr, *devstr;
180126706Swpaul	char *p0, *p;
181126706Swpaul
182126706Swpaul	p0 = __DECONST(char *, s);
183126706Swpaul
184126706Swpaul	p = strchr(p0, '\\');
185126706Swpaul	if (p == NULL)
186126706Swpaul		return;
187126706Swpaul	p0 = p + 1;
188126706Swpaul
189126706Swpaul	p = strchr(p0, '-');
190126706Swpaul	if (p == NULL)
191126706Swpaul		return;
192126706Swpaul	*p = '\0';
193126706Swpaul
194126706Swpaul	manstr = p0;
195126706Swpaul
196126706Swpaul	/* Convert any underscores to spaces. */
197126706Swpaul
198126706Swpaul	while (*p0 != '\0') {
199126706Swpaul		if (*p0 == '_')
200126706Swpaul			*p0 = ' ';
201126706Swpaul		p0++;
202126706Swpaul	}
203126706Swpaul
204126706Swpaul	p0 = p + 1;
205126706Swpaul	p = strchr(p0, '-');
206126706Swpaul	if (p == NULL)
207126706Swpaul		return;
208126706Swpaul	*p = '\0';
209126706Swpaul
210126706Swpaul	devstr = p0;
211126706Swpaul
212126706Swpaul	/* Convert any underscores to spaces. */
213126706Swpaul
214126706Swpaul	while (*p0 != '\0') {
215126706Swpaul		if (*p0 == '_')
216126706Swpaul			*p0 = ' ';
217126706Swpaul		p0++;
218126706Swpaul	}
219126706Swpaul
220126706Swpaul	fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr);
221126706Swpaul	return;
222126706Swpaul}
223126706Swpaul
224126706Swpaulstatic void
225123475Swpauldump_pci_id(const char *s)
226123475Swpaul{
227123475Swpaul	char *p;
228123620Swpaul	char vidstr[7], didstr[7], subsysstr[14];
229123475Swpaul
230123475Swpaul	p = strcasestr(s, "VEN_");
231123475Swpaul	if (p == NULL)
232123475Swpaul		return;
233123475Swpaul	p += 4;
234123475Swpaul	strcpy(vidstr, "0x");
235123475Swpaul	strncat(vidstr, p, 4);
236123475Swpaul	p = strcasestr(s, "DEV_");
237123475Swpaul	if (p == NULL)
238123475Swpaul		return;
239123475Swpaul	p += 4;
240123475Swpaul	strcpy(didstr, "0x");
241123475Swpaul	strncat(didstr, p, 4);
242123475Swpaul	if (p == NULL)
243123475Swpaul		return;
244123620Swpaul	p = strcasestr(s, "SUBSYS_");
245123620Swpaul	if (p == NULL)
246123620Swpaul		strcpy(subsysstr, "0x00000000");
247123620Swpaul	else {
248123620Swpaul		p += 7;
249123620Swpaul		strcpy(subsysstr, "0x");
250123620Swpaul		strncat(subsysstr, p, 8);
251123620Swpaul	}
252123475Swpaul
253123620Swpaul	fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
254123475Swpaul	return;
255123475Swpaul}
256123475Swpaul
257123475Swpaulstatic void
258186507Sweongyodump_usb_id(const char *s)
259186507Sweongyo{
260186507Sweongyo	char *p;
261186507Sweongyo	char vidstr[7], pidstr[7];
262186507Sweongyo
263186507Sweongyo	p = strcasestr(s, "VID_");
264186507Sweongyo	if (p == NULL)
265186507Sweongyo		return;
266186507Sweongyo	p += 4;
267186507Sweongyo	strcpy(vidstr, "0x");
268186507Sweongyo	strncat(vidstr, p, 4);
269186507Sweongyo	p = strcasestr(s, "PID_");
270186507Sweongyo	if (p == NULL)
271186507Sweongyo		return;
272186507Sweongyo	p += 4;
273186507Sweongyo	strcpy(pidstr, "0x");
274186507Sweongyo	strncat(pidstr, p, 4);
275186507Sweongyo	if (p == NULL)
276186507Sweongyo		return;
277186507Sweongyo
278186507Sweongyo	fprintf(ofp, "\t\\\n\t{ %s, %s, ", vidstr, pidstr);
279186507Sweongyo}
280186507Sweongyo
281186507Sweongyostatic void
282126706Swpauldump_deviceids_pci()
283123475Swpaul{
284123475Swpaul	struct assign *manf, *dev;
285123475Swpaul	struct section *sec;
286123475Swpaul	struct assign *assign;
287123483Swpaul	char xpsec[256];
288179855Sweongyo	int first = 1, found = 0;
289123475Swpaul
290123475Swpaul	/* Find manufacturer name */
291123475Swpaul	manf = find_assign("Manufacturer", NULL);
292123475Swpaul
293146243Swpaulnextmanf:
294146243Swpaul
295123475Swpaul	/* Find manufacturer section */
296123483Swpaul	if (manf->vals[1] != NULL &&
297123511Swpaul	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
298124094Swpaul	    strcasecmp(manf->vals[1], "NTx86") == 0 ||
299141963Swpaul	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
300141963Swpaul	    strcasecmp(manf->vals[1], "NTamd64") == 0)) {
301123483Swpaul		/* Handle Windows XP INF files. */
302123483Swpaul		snprintf(xpsec, sizeof(xpsec), "%s.%s",
303123483Swpaul		    manf->vals[0], manf->vals[1]);
304123483Swpaul		sec = find_section(xpsec);
305123483Swpaul	} else
306123483Swpaul		sec = find_section(manf->vals[0]);
307123475Swpaul
308126706Swpaul	/* See if there are any PCI device definitions. */
309123475Swpaul
310126706Swpaul	TAILQ_FOREACH(assign, &ah, link) {
311126706Swpaul		if (assign->section == sec) {
312126706Swpaul			dev = find_assign("strings", assign->key);
313126706Swpaul			if (strcasestr(assign->vals[1], "PCI") != NULL) {
314126706Swpaul				found++;
315126706Swpaul				break;
316126706Swpaul			}
317126706Swpaul		}
318126706Swpaul	}
319126706Swpaul
320126706Swpaul	if (found == 0)
321146243Swpaul		goto done;
322126706Swpaul
323126706Swpaul	found = 0;
324126706Swpaul
325179855Sweongyo	if (first == 1) {
326179855Sweongyo		/* Emit start of PCI device table */
327179855Sweongyo		fprintf (ofp, "#define NDIS_PCI_DEV_TABLE");
328179855Sweongyo		first = 0;
329179855Sweongyo	}
330179855Sweongyo
331125073Swpaulretry:
332125073Swpaul
333123475Swpaul	/*
334123475Swpaul	 * Now run through all the device names listed
335123475Swpaul	 * in the manufacturer section and dump out the
336123475Swpaul	 * device descriptions and vendor/device IDs.
337123475Swpaul	 */
338123475Swpaul
339123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
340123475Swpaul		if (assign->section == sec) {
341123475Swpaul			dev = find_assign("strings", assign->key);
342123475Swpaul			/* Emit device IDs. */
343123475Swpaul			if (strcasestr(assign->vals[1], "PCI") != NULL)
344123475Swpaul				dump_pci_id(assign->vals[1]);
345126706Swpaul			else
346124886Swpaul				continue;
347126706Swpaul			/* Emit device description */
348126706Swpaul			fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
349126706Swpaul			found++;
350126706Swpaul		}
351126706Swpaul	}
352126706Swpaul
353126706Swpaul	/* Someone tried to fool us. Shame on them. */
354126706Swpaul	if (!found) {
355126706Swpaul		found++;
356126706Swpaul		sec = find_section(manf->vals[0]);
357126706Swpaul		goto retry;
358126706Swpaul	}
359126706Swpaul
360146243Swpaul	/* Handle Manufacturer sections with multiple entries. */
361146243Swpaul	manf = find_next_assign(manf);
362146243Swpaul
363146243Swpaul	if (manf != NULL)
364146243Swpaul		goto nextmanf;
365146243Swpaul
366146243Swpauldone:
367126706Swpaul	/* Emit end of table */
368126706Swpaul
369126706Swpaul	fprintf(ofp, "\n\n");
370126706Swpaul
371146243Swpaul	return;
372126706Swpaul}
373126706Swpaul
374126706Swpaulstatic void
375126706Swpauldump_deviceids_pcmcia()
376126706Swpaul{
377126706Swpaul	struct assign *manf, *dev;
378126706Swpaul	struct section *sec;
379126706Swpaul	struct assign *assign;
380126706Swpaul	char xpsec[256];
381179855Sweongyo	int first = 1, found = 0;
382126706Swpaul
383126706Swpaul	/* Find manufacturer name */
384126706Swpaul	manf = find_assign("Manufacturer", NULL);
385126706Swpaul
386146243Swpaulnextmanf:
387146243Swpaul
388126706Swpaul	/* Find manufacturer section */
389126706Swpaul	if (manf->vals[1] != NULL &&
390126706Swpaul	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
391126706Swpaul	    strcasecmp(manf->vals[1], "NTx86") == 0 ||
392141963Swpaul	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
393141963Swpaul	    strcasecmp(manf->vals[1], "NTamd64") == 0)) {
394126706Swpaul		/* Handle Windows XP INF files. */
395126706Swpaul		snprintf(xpsec, sizeof(xpsec), "%s.%s",
396126706Swpaul		    manf->vals[0], manf->vals[1]);
397126706Swpaul		sec = find_section(xpsec);
398126706Swpaul	} else
399126706Swpaul		sec = find_section(manf->vals[0]);
400126706Swpaul
401126706Swpaul	/* See if there are any PCMCIA device definitions. */
402126706Swpaul
403126706Swpaul	TAILQ_FOREACH(assign, &ah, link) {
404126706Swpaul		if (assign->section == sec) {
405126706Swpaul			dev = find_assign("strings", assign->key);
406126706Swpaul			if (strcasestr(assign->vals[1], "PCMCIA") != NULL) {
407126706Swpaul				found++;
408126706Swpaul				break;
409126706Swpaul			}
410126706Swpaul		}
411126706Swpaul	}
412126706Swpaul
413126706Swpaul	if (found == 0)
414146243Swpaul		goto done;
415126706Swpaul
416126706Swpaul	found = 0;
417126706Swpaul
418179855Sweongyo	if (first == 1) {
419179855Sweongyo		/* Emit start of PCMCIA device table */
420179855Sweongyo		fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE");
421179855Sweongyo		first = 0;
422179855Sweongyo	}
423126706Swpaul
424126706Swpaulretry:
425126706Swpaul
426126706Swpaul	/*
427126706Swpaul	 * Now run through all the device names listed
428126706Swpaul	 * in the manufacturer section and dump out the
429126706Swpaul	 * device descriptions and vendor/device IDs.
430126706Swpaul	 */
431126706Swpaul
432126706Swpaul	TAILQ_FOREACH(assign, &ah, link) {
433126706Swpaul		if (assign->section == sec) {
434126706Swpaul			dev = find_assign("strings", assign->key);
435126706Swpaul			/* Emit device IDs. */
436126706Swpaul			if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
437123475Swpaul				dump_pcmcia_id(assign->vals[1]);
438126706Swpaul			else
439126706Swpaul				continue;
440123475Swpaul			/* Emit device description */
441123480Swpaul			fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
442125073Swpaul			found++;
443123475Swpaul		}
444123475Swpaul	}
445123475Swpaul
446125073Swpaul	/* Someone tried to fool us. Shame on them. */
447125073Swpaul	if (!found) {
448125073Swpaul		found++;
449125073Swpaul		sec = find_section(manf->vals[0]);
450125073Swpaul		goto retry;
451125073Swpaul	}
452125073Swpaul
453146243Swpaul	/* Handle Manufacturer sections with multiple entries. */
454146243Swpaul	manf = find_next_assign(manf);
455146243Swpaul
456146243Swpaul	if (manf != NULL)
457146243Swpaul		goto nextmanf;
458146243Swpaul
459146243Swpauldone:
460123475Swpaul	/* Emit end of table */
461123475Swpaul
462123480Swpaul	fprintf(ofp, "\n\n");
463123480Swpaul
464146243Swpaul	return;
465123475Swpaul}
466123475Swpaul
467123475Swpaulstatic void
468186507Sweongyodump_deviceids_usb()
469186507Sweongyo{
470186507Sweongyo	struct assign *manf, *dev;
471186507Sweongyo	struct section *sec;
472186507Sweongyo	struct assign *assign;
473186507Sweongyo	char xpsec[256];
474186507Sweongyo	int first = 1, found = 0;
475186507Sweongyo
476186507Sweongyo	/* Find manufacturer name */
477186507Sweongyo	manf = find_assign("Manufacturer", NULL);
478186507Sweongyo
479186507Sweongyonextmanf:
480186507Sweongyo
481186507Sweongyo	/* Find manufacturer section */
482186507Sweongyo	if (manf->vals[1] != NULL &&
483186507Sweongyo	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
484186507Sweongyo	    strcasecmp(manf->vals[1], "NTx86") == 0 ||
485186507Sweongyo	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
486186507Sweongyo	    strcasecmp(manf->vals[1], "NTamd64") == 0)) {
487186507Sweongyo		/* Handle Windows XP INF files. */
488186507Sweongyo		snprintf(xpsec, sizeof(xpsec), "%s.%s",
489186507Sweongyo		    manf->vals[0], manf->vals[1]);
490186507Sweongyo		sec = find_section(xpsec);
491186507Sweongyo	} else
492186507Sweongyo		sec = find_section(manf->vals[0]);
493186507Sweongyo
494186507Sweongyo	/* See if there are any USB device definitions. */
495186507Sweongyo
496186507Sweongyo	TAILQ_FOREACH(assign, &ah, link) {
497186507Sweongyo		if (assign->section == sec) {
498186507Sweongyo			dev = find_assign("strings", assign->key);
499186507Sweongyo			if (strcasestr(assign->vals[1], "USB") != NULL) {
500186507Sweongyo				found++;
501186507Sweongyo				break;
502186507Sweongyo			}
503186507Sweongyo		}
504186507Sweongyo	}
505186507Sweongyo
506186507Sweongyo	if (found == 0)
507186507Sweongyo		goto done;
508186507Sweongyo
509186507Sweongyo	found = 0;
510186507Sweongyo
511186507Sweongyo	if (first == 1) {
512186507Sweongyo		/* Emit start of USB device table */
513186507Sweongyo		fprintf (ofp, "#define NDIS_USB_DEV_TABLE");
514186507Sweongyo		first = 0;
515186507Sweongyo	}
516186507Sweongyo
517186507Sweongyoretry:
518186507Sweongyo
519186507Sweongyo	/*
520186507Sweongyo	 * Now run through all the device names listed
521186507Sweongyo	 * in the manufacturer section and dump out the
522186507Sweongyo	 * device descriptions and vendor/device IDs.
523186507Sweongyo	 */
524186507Sweongyo
525186507Sweongyo	TAILQ_FOREACH(assign, &ah, link) {
526186507Sweongyo		if (assign->section == sec) {
527186507Sweongyo			dev = find_assign("strings", assign->key);
528186507Sweongyo			/* Emit device IDs. */
529186507Sweongyo			if (strcasestr(assign->vals[1], "USB") != NULL)
530186507Sweongyo				dump_usb_id(assign->vals[1]);
531186507Sweongyo			else
532186507Sweongyo				continue;
533186507Sweongyo			/* Emit device description */
534186507Sweongyo			fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
535186507Sweongyo			found++;
536186507Sweongyo		}
537186507Sweongyo	}
538186507Sweongyo
539186507Sweongyo	/* Someone tried to fool us. Shame on them. */
540186507Sweongyo	if (!found) {
541186507Sweongyo		found++;
542186507Sweongyo		sec = find_section(manf->vals[0]);
543186507Sweongyo		goto retry;
544186507Sweongyo	}
545186507Sweongyo
546186507Sweongyo	/* Handle Manufacturer sections with multiple entries. */
547186507Sweongyo	manf = find_next_assign(manf);
548186507Sweongyo
549186507Sweongyo	if (manf != NULL)
550186507Sweongyo		goto nextmanf;
551186507Sweongyo
552186507Sweongyodone:
553186507Sweongyo	/* Emit end of table */
554186507Sweongyo
555186507Sweongyo	fprintf(ofp, "\n\n");
556186507Sweongyo
557186507Sweongyo	return;
558186507Sweongyo}
559186507Sweongyo
560186507Sweongyostatic void
561123620Swpauldump_addreg(const char *s, int devidx)
562123475Swpaul{
563123475Swpaul	struct section *sec;
564123475Swpaul	struct reg *reg;
565123475Swpaul
566123475Swpaul	/* Find the addreg section */
567123475Swpaul	sec = find_section(s);
568123475Swpaul
569123475Swpaul	/* Dump all the keys defined in it. */
570123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
571123475Swpaul		/*
572123475Swpaul		 * Keys with an empty subkey are very easy to parse,
573123475Swpaul		 * so just deal with them here. If a parameter key
574123475Swpaul		 * of the same name also exists, prefer that one and
575123475Swpaul		 * skip this one.
576123475Swpaul		 */
577123475Swpaul		if (reg->section == sec) {
578123475Swpaul			if (reg->subkey == NULL) {
579123475Swpaul				fprintf(ofp, "\n\t{ \"%s\",", reg->key);
580123475Swpaul				fprintf(ofp,"\n\t\"%s \",", reg->key);
581123620Swpaul				fprintf(ofp, "\n\t{ \"%s\" }, %d },",
582123475Swpaul				    reg->value == NULL ? "" :
583123620Swpaul				    stringcvt(reg->value), devidx);
584124452Swpaul			} else if (strncasecmp(reg->subkey,
585124452Swpaul			    "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
586124886Swpaul			    (reg->key != NULL && strcasecmp(reg->key,
587124886Swpaul			    "ParamDesc") == 0))
588123620Swpaul				dump_paramreg(sec, reg, devidx);
589123475Swpaul		}
590123475Swpaul	}
591123475Swpaul
592123475Swpaul	return;
593123475Swpaul}
594123475Swpaul
595123475Swpaulstatic void
596123475Swpauldump_enumreg(const struct section *s, const struct reg *r)
597123475Swpaul{
598123475Swpaul	struct reg *reg;
599123475Swpaul	char enumkey[256];
600123475Swpaul
601123475Swpaul	sprintf(enumkey, "%s\\enum", r->subkey);
602123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
603123475Swpaul		if (reg->section != s)
604123475Swpaul			continue;
605123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
606123475Swpaul			continue;
607123483Swpaul		fprintf(ofp, " [%s=%s]", reg->key,
608123483Swpaul		    stringcvt(reg->value));
609123475Swpaul	}
610123475Swpaul	return;
611123475Swpaul}
612123475Swpaul
613123475Swpaulstatic void
614123475Swpauldump_editreg(const struct section *s, const struct reg *r)
615123475Swpaul{
616123475Swpaul	struct reg *reg;
617123475Swpaul
618123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
619123475Swpaul		if (reg->section != s)
620123475Swpaul			continue;
621123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
622123475Swpaul			continue;
623124886Swpaul		if (reg->key == NULL)
624124886Swpaul			continue;
625123475Swpaul		if (strcasecmp(reg->key, "LimitText") == 0)
626123475Swpaul			fprintf(ofp, " [maxchars=%s]", reg->value);
627123475Swpaul		if (strcasecmp(reg->key, "Optional") == 0 &&
628123475Swpaul		    strcmp(reg->value, "1") == 0)
629123475Swpaul			fprintf(ofp, " [optional]");
630123475Swpaul	}
631123475Swpaul	return;
632123475Swpaul}
633123475Swpaul
634123475Swpaul/* Use this for int too */
635123475Swpaulstatic void
636123475Swpauldump_dwordreg(const struct section *s, const struct reg *r)
637123475Swpaul{
638123475Swpaul	struct reg *reg;
639123475Swpaul
640123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
641123475Swpaul		if (reg->section != s)
642123475Swpaul			continue;
643123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
644123475Swpaul			continue;
645124886Swpaul		if (reg->key == NULL)
646124886Swpaul			continue;
647123475Swpaul		if (strcasecmp(reg->key, "min") == 0)
648123475Swpaul			fprintf(ofp, " [min=%s]", reg->value);
649123475Swpaul		if (strcasecmp(reg->key, "max") == 0)
650123475Swpaul			fprintf(ofp, " [max=%s]", reg->value);
651123475Swpaul	}
652123475Swpaul	return;
653123475Swpaul}
654123475Swpaul
655123475Swpaulstatic void
656123620Swpauldump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
657123475Swpaul{
658123475Swpaul	struct reg *reg;
659123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
660123475Swpaul		if (reg->section != s)
661123475Swpaul			continue;
662123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
663123475Swpaul			continue;
664124886Swpaul		if (reg->key == NULL || strcasecmp(reg->key, "Default"))
665123475Swpaul			continue;
666123620Swpaul		fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
667123977Swpaul		    stringcvt(reg->value), devidx);
668178214Sthompsa		return;
669123475Swpaul	}
670178214Sthompsa	/* Default registry entry missing */
671178214Sthompsa	fprintf(ofp, "\n\t{ \"\" }, %d },", devidx);
672123475Swpaul	return;
673123475Swpaul}
674123475Swpaul
675123475Swpaulstatic void
676123475Swpauldump_paramdesc(const struct section *s, const struct reg *r)
677123475Swpaul{
678123475Swpaul	struct reg *reg;
679123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
680123475Swpaul		if (reg->section != s)
681123475Swpaul			continue;
682123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
683123475Swpaul			continue;
684124886Swpaul		if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc"))
685123475Swpaul			continue;
686123475Swpaul		fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
687123475Swpaul			break;
688123475Swpaul	}
689123475Swpaul	return;
690123475Swpaul}
691123475Swpaul
692123475Swpaulstatic void
693123475Swpauldump_typeinfo(const struct section *s, const struct reg *r)
694123475Swpaul{
695123475Swpaul	struct reg *reg;
696123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
697123475Swpaul		if (reg->section != s)
698123475Swpaul			continue;
699123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
700123475Swpaul			continue;
701124886Swpaul		if (reg->key == NULL)
702124886Swpaul			continue;
703123475Swpaul		if (strcasecmp(reg->key, "type"))
704123475Swpaul			continue;
705123475Swpaul		if (strcasecmp(reg->value, "dword") == 0 ||
706123475Swpaul		    strcasecmp(reg->value, "int") == 0)
707123475Swpaul			dump_dwordreg(s, r);
708123475Swpaul		if (strcasecmp(reg->value, "enum") == 0)
709123475Swpaul			dump_enumreg(s, r);
710123475Swpaul		if (strcasecmp(reg->value, "edit") == 0)
711123475Swpaul			dump_editreg(s, r);
712123475Swpaul	}
713123475Swpaul	return;
714123475Swpaul}
715123475Swpaul
716123475Swpaulstatic void
717123620Swpauldump_paramreg(const struct section *s, const struct reg *r, int devidx)
718123475Swpaul{
719123475Swpaul	const char *keyname;
720123475Swpaul
721123475Swpaul	keyname = r->subkey + strlen("Ndi\\params\\");
722123475Swpaul	fprintf(ofp, "\n\t{ \"%s\",", keyname);
723123475Swpaul	dump_paramdesc(s, r);
724123475Swpaul	dump_typeinfo(s, r);
725123475Swpaul	fprintf(ofp, "\",");
726123620Swpaul	dump_defaultinfo(s, r, devidx);
727123475Swpaul
728123475Swpaul	return;
729123475Swpaul}
730123475Swpaul
731141981Swpaulstatic void
732123475Swpauldump_regvals(void)
733123475Swpaul{
734123620Swpaul	struct assign *manf, *dev;
735123475Swpaul	struct section *sec;
736123475Swpaul	struct assign *assign;
737123475Swpaul	char sname[256];
738125073Swpaul	int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0;
739123475Swpaul
740124085Swpaul	/* Find signature to check for special case of WinNT. */
741124085Swpaul	assign = find_assign("version", "signature");
742124085Swpaul	if (strcasecmp(assign->vals[0], "$windows nt$") == 0)
743124085Swpaul		is_winnt++;
744124085Swpaul
745146243Swpaul	/* Emit start of block */
746146243Swpaul	fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
747146243Swpaul
748123475Swpaul	/* Find manufacturer name */
749123475Swpaul	manf = find_assign("Manufacturer", NULL);
750123475Swpaul
751146243Swpaulnextmanf:
752146243Swpaul
753123475Swpaul	/* Find manufacturer section */
754123483Swpaul	if (manf->vals[1] != NULL &&
755123511Swpaul	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
756124094Swpaul	    strcasecmp(manf->vals[1], "NTx86") == 0 ||
757141963Swpaul	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
758141963Swpaul	    strcasecmp(manf->vals[1], "NTamd64") == 0)) {
759123483Swpaul		is_winxp++;
760123483Swpaul		/* Handle Windows XP INF files. */
761123483Swpaul		snprintf(sname, sizeof(sname), "%s.%s",
762123483Swpaul		    manf->vals[0], manf->vals[1]);
763123483Swpaul		sec = find_section(sname);
764123483Swpaul	} else
765123483Swpaul		sec = find_section(manf->vals[0]);
766123475Swpaul
767125073Swpaulretry:
768125073Swpaul
769123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
770123475Swpaul		if (assign->section == sec) {
771125073Swpaul			found++;
772123483Swpaul			/*
773123483Swpaul			 * Find all the AddReg sections.
774123483Swpaul			 * Look for section names with .NT, unless
775123483Swpaul			 * this is a WinXP .INF file.
776123483Swpaul			 */
777141963Swpaul
778123511Swpaul			if (is_winxp) {
779123511Swpaul				sprintf(sname, "%s.NTx86", assign->vals[0]);
780123511Swpaul				dev = find_assign(sname, "AddReg");
781141963Swpaul				if (dev == NULL) {
782141963Swpaul					sprintf(sname, "%s.NT",
783141963Swpaul					    assign->vals[0]);
784141963Swpaul					dev = find_assign(sname, "AddReg");
785141963Swpaul				}
786123511Swpaul				if (dev == NULL)
787123511Swpaul					dev = find_assign(assign->vals[0],
788123511Swpaul					    "AddReg");
789123511Swpaul			} else {
790123483Swpaul				sprintf(sname, "%s.NT", assign->vals[0]);
791123483Swpaul				dev = find_assign(sname, "AddReg");
792124085Swpaul				if (dev == NULL && is_winnt)
793124085Swpaul					dev = find_assign(assign->vals[0],
794124085Swpaul					    "AddReg");
795123483Swpaul			}
796123483Swpaul			/* Section not found. */
797123483Swpaul			if (dev == NULL)
798123483Swpaul				continue;
799123475Swpaul			for (i = 0; i < W_MAX; i++) {
800123475Swpaul				if (dev->vals[i] != NULL)
801123620Swpaul					dump_addreg(dev->vals[i], devidx);
802123475Swpaul			}
803123620Swpaul			devidx++;
804123475Swpaul		}
805123475Swpaul	}
806123475Swpaul
807125073Swpaul	if (!found) {
808125073Swpaul		sec = find_section(manf->vals[0]);
809125073Swpaul		is_winxp = 0;
810125073Swpaul		found++;
811125073Swpaul		goto retry;
812125073Swpaul	}
813125073Swpaul
814146243Swpaul	manf = find_next_assign(manf);
815146243Swpaul
816146243Swpaul	if (manf != NULL)
817146243Swpaul		goto nextmanf;
818146243Swpaul
819123620Swpaul	fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
820123475Swpaul
821123475Swpaul	return;
822123475Swpaul}
823123475Swpaul
824123475Swpaulvoid
825123475Swpaulassign_add (const char *a)
826123475Swpaul{
827123475Swpaul	struct assign *assign;
828123475Swpaul	int i;
829123475Swpaul
830123475Swpaul	assign = malloc(sizeof(struct assign));
831123475Swpaul	bzero(assign, sizeof(struct assign));
832123475Swpaul	assign->section = TAILQ_LAST(&sh, section_head);
833123475Swpaul	assign->key = sstrdup(a);
834123475Swpaul	for (i = 0; i < idx; i++)
835123475Swpaul		assign->vals[(idx - 1) - i] = sstrdup(words[i]);
836123475Swpaul	TAILQ_INSERT_TAIL(&ah, assign, link);
837123475Swpaul
838123475Swpaul	clear_words();
839123475Swpaul	return;
840123475Swpaul}
841123475Swpaul
842123475Swpaulvoid
843123475Swpauldefine_add (const char *d __unused)
844123475Swpaul{
845123475Swpaul#ifdef notdef
846123475Swpaul	fprintf(stderr, "define \"%s\"\n", d);
847123475Swpaul#endif
848123475Swpaul	return;
849123475Swpaul}
850123475Swpaul
851123475Swpaulstatic char *
852123475Swpaulsstrdup(const char *str)
853123475Swpaul{
854123475Swpaul	if (str != NULL && strlen(str))
855123475Swpaul		return (strdup(str));
856123475Swpaul	return (NULL);
857123475Swpaul}
858123475Swpaul
859123475Swpaulstatic int
860123475Swpaulsatoi (const char *nptr)
861123475Swpaul{
862123475Swpaul	if (nptr != NULL && strlen(nptr))
863123475Swpaul		return (atoi(nptr));
864123475Swpaul	return (0);
865123475Swpaul}
866123475Swpaul
867123475Swpaulvoid
868123475Swpaulregkey_add (const char *r)
869123475Swpaul{
870123475Swpaul	struct reg *reg;
871123475Swpaul
872123475Swpaul	reg = malloc(sizeof(struct reg));
873123475Swpaul	bzero(reg, sizeof(struct reg));
874123475Swpaul	reg->section = TAILQ_LAST(&sh, section_head);
875123475Swpaul	reg->root = sstrdup(r);
876123475Swpaul	reg->subkey = sstrdup(words[3]);
877123475Swpaul	reg->key = sstrdup(words[2]);
878123475Swpaul	reg->flags = satoi(words[1]);
879123475Swpaul	reg->value = sstrdup(words[0]);
880123475Swpaul	TAILQ_INSERT_TAIL(&rh, reg, link);
881123475Swpaul
882123475Swpaul	free(__DECONST(char *, r));
883123475Swpaul	clear_words();
884123475Swpaul	return;
885123475Swpaul}
886123475Swpaul
887123475Swpaulvoid
888123475Swpaulpush_word (const char *w)
889123475Swpaul{
890123475Swpaul	if (w && strlen(w))
891123475Swpaul		words[idx++] = w;
892123475Swpaul	else
893123475Swpaul		words[idx++] = NULL;
894123475Swpaul	return;
895123475Swpaul}
896123475Swpaul
897123475Swpaulvoid
898123475Swpaulclear_words (void)
899123475Swpaul{
900123475Swpaul	int i;
901123475Swpaul
902123475Swpaul	for (i = 0; i < idx; i++) {
903123475Swpaul		if (words[i]) {
904123475Swpaul			free(__DECONST(char *, words[i]));
905123475Swpaul		}
906123475Swpaul	}
907123475Swpaul	idx = 0;
908123475Swpaul	bzero(words, sizeof(words));
909123475Swpaul	return;
910123475Swpaul}
911