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: stable/10/usr.sbin/ndiscvt/inf.c 343730 2019-02-04 03:44:07Z avos $");
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 *);
63343730Savosstatic int	dump_deviceids_pci	(void);
64343730Savosstatic int	dump_deviceids_pcmcia	(void);
65343730Savosstatic int	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
86343730Savos	if (dump_deviceids_pci() == 0 &&
87343730Savos	    dump_deviceids_pcmcia() == 0 &&
88343730Savos	    dump_deviceids_usb() == 0)
89343730Savos		return (-1);
90343730Savos
91126706Swpaul	fprintf(outfp, "#ifdef NDIS_REGVALS\n");
92123475Swpaul	dump_regvals();
93126706Swpaul	fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
94123475Swpaul
95123475Swpaul	return (0);
96123475Swpaul}
97123475Swpaul
98123475Swpaulvoid
99123475Swpaulsection_add (const char *s)
100123475Swpaul{
101123475Swpaul	struct section *sec;
102123475Swpaul
103123475Swpaul	sec = malloc(sizeof(struct section));
104123475Swpaul	bzero(sec, sizeof(struct section));
105123475Swpaul	sec->name = s;
106123475Swpaul	TAILQ_INSERT_TAIL(&sh, sec, link);
107123475Swpaul
108123475Swpaul	return;
109123475Swpaul}
110123475Swpaul
111123475Swpaulstatic struct assign *
112123475Swpaulfind_assign (const char *s, const char *k)
113123475Swpaul{
114123475Swpaul	struct assign *assign;
115123475Swpaul	char newkey[256];
116123475Swpaul
117123475Swpaul	/* Deal with string section lookups. */
118123475Swpaul
119123475Swpaul	if (k != NULL && k[0] == '%') {
120123475Swpaul		bzero(newkey, sizeof(newkey));
121123475Swpaul		strncpy(newkey, k + 1, strlen(k) - 2);
122123475Swpaul		k = newkey;
123123475Swpaul	}
124123475Swpaul
125123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
126123475Swpaul		if (strcasecmp(assign->section->name, s) == 0) {
127123475Swpaul			if (k == NULL)
128123475Swpaul				return(assign);
129123475Swpaul			else
130123475Swpaul				if (strcasecmp(assign->key, k) == 0)
131123475Swpaul					return(assign);
132123475Swpaul		}
133123475Swpaul	}
134123475Swpaul	return(NULL);
135123475Swpaul}
136123475Swpaul
137146243Swpaulstatic struct assign *
138146243Swpaulfind_next_assign (struct assign *a)
139146243Swpaul{
140146243Swpaul	struct assign *assign;
141146243Swpaul
142146243Swpaul	TAILQ_FOREACH(assign, &ah, link) {
143146243Swpaul		if (assign == a)
144146243Swpaul			break;
145146243Swpaul	}
146146243Swpaul
147146243Swpaul	assign = assign->link.tqe_next;
148146243Swpaul
149146243Swpaul	if (assign == NULL || assign->section != a->section)
150146243Swpaul		return(NULL);
151146243Swpaul
152146243Swpaul	return (assign);
153146243Swpaul}
154146243Swpaul
155123475Swpaulstatic const char *
156123475Swpaulstringcvt(const char *s)
157123475Swpaul{
158123475Swpaul	struct assign *manf;
159123475Swpaul
160123475Swpaul	manf = find_assign("strings", s);
161123475Swpaul	if (manf == NULL)
162123475Swpaul		return(s);
163123475Swpaul	return(manf->vals[0]);
164123475Swpaul}
165123475Swpaul
166123475Swpaulstruct section *
167123475Swpaulfind_section (const char *s)
168123475Swpaul{
169123475Swpaul	struct section *section;
170123475Swpaul
171123475Swpaul	TAILQ_FOREACH(section, &sh, link) {
172123475Swpaul		if (strcasecmp(section->name, s) == 0)
173123475Swpaul			return(section);
174123475Swpaul	}
175123475Swpaul	return(NULL);
176123475Swpaul}
177123475Swpaul
178123475Swpaulstatic void
179126706Swpauldump_pcmcia_id(const char *s)
180126706Swpaul{
181126706Swpaul	char *manstr, *devstr;
182126706Swpaul	char *p0, *p;
183126706Swpaul
184126706Swpaul	p0 = __DECONST(char *, s);
185126706Swpaul
186126706Swpaul	p = strchr(p0, '\\');
187126706Swpaul	if (p == NULL)
188126706Swpaul		return;
189126706Swpaul	p0 = p + 1;
190126706Swpaul
191126706Swpaul	p = strchr(p0, '-');
192126706Swpaul	if (p == NULL)
193126706Swpaul		return;
194126706Swpaul	*p = '\0';
195126706Swpaul
196126706Swpaul	manstr = p0;
197126706Swpaul
198126706Swpaul	/* Convert any underscores to spaces. */
199126706Swpaul
200126706Swpaul	while (*p0 != '\0') {
201126706Swpaul		if (*p0 == '_')
202126706Swpaul			*p0 = ' ';
203126706Swpaul		p0++;
204126706Swpaul	}
205126706Swpaul
206126706Swpaul	p0 = p + 1;
207126706Swpaul	p = strchr(p0, '-');
208126706Swpaul	if (p == NULL)
209126706Swpaul		return;
210126706Swpaul	*p = '\0';
211126706Swpaul
212126706Swpaul	devstr = p0;
213126706Swpaul
214126706Swpaul	/* Convert any underscores to spaces. */
215126706Swpaul
216126706Swpaul	while (*p0 != '\0') {
217126706Swpaul		if (*p0 == '_')
218126706Swpaul			*p0 = ' ';
219126706Swpaul		p0++;
220126706Swpaul	}
221126706Swpaul
222126706Swpaul	fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr);
223126706Swpaul	return;
224126706Swpaul}
225126706Swpaul
226126706Swpaulstatic void
227123475Swpauldump_pci_id(const char *s)
228123475Swpaul{
229123475Swpaul	char *p;
230123620Swpaul	char vidstr[7], didstr[7], subsysstr[14];
231123475Swpaul
232123475Swpaul	p = strcasestr(s, "VEN_");
233123475Swpaul	if (p == NULL)
234123475Swpaul		return;
235123475Swpaul	p += 4;
236123475Swpaul	strcpy(vidstr, "0x");
237123475Swpaul	strncat(vidstr, p, 4);
238123475Swpaul	p = strcasestr(s, "DEV_");
239123475Swpaul	if (p == NULL)
240123475Swpaul		return;
241123475Swpaul	p += 4;
242123475Swpaul	strcpy(didstr, "0x");
243123475Swpaul	strncat(didstr, p, 4);
244123475Swpaul	if (p == NULL)
245123475Swpaul		return;
246123620Swpaul	p = strcasestr(s, "SUBSYS_");
247123620Swpaul	if (p == NULL)
248123620Swpaul		strcpy(subsysstr, "0x00000000");
249123620Swpaul	else {
250123620Swpaul		p += 7;
251123620Swpaul		strcpy(subsysstr, "0x");
252123620Swpaul		strncat(subsysstr, p, 8);
253123620Swpaul	}
254123475Swpaul
255123620Swpaul	fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
256123475Swpaul	return;
257123475Swpaul}
258123475Swpaul
259123475Swpaulstatic void
260186507Sweongyodump_usb_id(const char *s)
261186507Sweongyo{
262186507Sweongyo	char *p;
263186507Sweongyo	char vidstr[7], pidstr[7];
264186507Sweongyo
265186507Sweongyo	p = strcasestr(s, "VID_");
266186507Sweongyo	if (p == NULL)
267186507Sweongyo		return;
268186507Sweongyo	p += 4;
269186507Sweongyo	strcpy(vidstr, "0x");
270186507Sweongyo	strncat(vidstr, p, 4);
271186507Sweongyo	p = strcasestr(s, "PID_");
272186507Sweongyo	if (p == NULL)
273186507Sweongyo		return;
274186507Sweongyo	p += 4;
275186507Sweongyo	strcpy(pidstr, "0x");
276186507Sweongyo	strncat(pidstr, p, 4);
277186507Sweongyo	if (p == NULL)
278186507Sweongyo		return;
279186507Sweongyo
280186507Sweongyo	fprintf(ofp, "\t\\\n\t{ %s, %s, ", vidstr, pidstr);
281186507Sweongyo}
282186507Sweongyo
283343730Savosstatic int
284126706Swpauldump_deviceids_pci()
285123475Swpaul{
286123475Swpaul	struct assign *manf, *dev;
287123475Swpaul	struct section *sec;
288123475Swpaul	struct assign *assign;
289123483Swpaul	char xpsec[256];
290179855Sweongyo	int first = 1, found = 0;
291123475Swpaul
292123475Swpaul	/* Find manufacturer name */
293123475Swpaul	manf = find_assign("Manufacturer", NULL);
294123475Swpaul
295146243Swpaulnextmanf:
296146243Swpaul
297123475Swpaul	/* Find manufacturer section */
298123483Swpaul	if (manf->vals[1] != NULL &&
299123511Swpaul	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
300124094Swpaul	    strcasecmp(manf->vals[1], "NTx86") == 0 ||
301141963Swpaul	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
302141963Swpaul	    strcasecmp(manf->vals[1], "NTamd64") == 0)) {
303123483Swpaul		/* Handle Windows XP INF files. */
304123483Swpaul		snprintf(xpsec, sizeof(xpsec), "%s.%s",
305123483Swpaul		    manf->vals[0], manf->vals[1]);
306123483Swpaul		sec = find_section(xpsec);
307123483Swpaul	} else
308123483Swpaul		sec = find_section(manf->vals[0]);
309123475Swpaul
310126706Swpaul	/* See if there are any PCI device definitions. */
311123475Swpaul
312126706Swpaul	TAILQ_FOREACH(assign, &ah, link) {
313126706Swpaul		if (assign->section == sec) {
314126706Swpaul			dev = find_assign("strings", assign->key);
315126706Swpaul			if (strcasestr(assign->vals[1], "PCI") != NULL) {
316126706Swpaul				found++;
317126706Swpaul				break;
318126706Swpaul			}
319126706Swpaul		}
320126706Swpaul	}
321126706Swpaul
322126706Swpaul	if (found == 0)
323146243Swpaul		goto done;
324126706Swpaul
325126706Swpaul	found = 0;
326126706Swpaul
327179855Sweongyo	if (first == 1) {
328179855Sweongyo		/* Emit start of PCI device table */
329179855Sweongyo		fprintf (ofp, "#define NDIS_PCI_DEV_TABLE");
330179855Sweongyo		first = 0;
331179855Sweongyo	}
332179855Sweongyo
333125073Swpaulretry:
334125073Swpaul
335123475Swpaul	/*
336123475Swpaul	 * Now run through all the device names listed
337123475Swpaul	 * in the manufacturer section and dump out the
338123475Swpaul	 * device descriptions and vendor/device IDs.
339123475Swpaul	 */
340123475Swpaul
341123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
342123475Swpaul		if (assign->section == sec) {
343123475Swpaul			dev = find_assign("strings", assign->key);
344123475Swpaul			/* Emit device IDs. */
345123475Swpaul			if (strcasestr(assign->vals[1], "PCI") != NULL)
346123475Swpaul				dump_pci_id(assign->vals[1]);
347126706Swpaul			else
348124886Swpaul				continue;
349126706Swpaul			/* Emit device description */
350126706Swpaul			fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
351126706Swpaul			found++;
352126706Swpaul		}
353126706Swpaul	}
354126706Swpaul
355126706Swpaul	/* Someone tried to fool us. Shame on them. */
356126706Swpaul	if (!found) {
357126706Swpaul		found++;
358126706Swpaul		sec = find_section(manf->vals[0]);
359126706Swpaul		goto retry;
360126706Swpaul	}
361126706Swpaul
362146243Swpaul	/* Handle Manufacturer sections with multiple entries. */
363146243Swpaul	manf = find_next_assign(manf);
364146243Swpaul
365146243Swpaul	if (manf != NULL)
366146243Swpaul		goto nextmanf;
367146243Swpaul
368146243Swpauldone:
369126706Swpaul	/* Emit end of table */
370126706Swpaul
371126706Swpaul	fprintf(ofp, "\n\n");
372126706Swpaul
373343730Savos	return (found);
374126706Swpaul}
375126706Swpaul
376343730Savosstatic int
377126706Swpauldump_deviceids_pcmcia()
378126706Swpaul{
379126706Swpaul	struct assign *manf, *dev;
380126706Swpaul	struct section *sec;
381126706Swpaul	struct assign *assign;
382126706Swpaul	char xpsec[256];
383179855Sweongyo	int first = 1, found = 0;
384126706Swpaul
385126706Swpaul	/* Find manufacturer name */
386126706Swpaul	manf = find_assign("Manufacturer", NULL);
387126706Swpaul
388146243Swpaulnextmanf:
389146243Swpaul
390126706Swpaul	/* Find manufacturer section */
391126706Swpaul	if (manf->vals[1] != NULL &&
392126706Swpaul	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
393126706Swpaul	    strcasecmp(manf->vals[1], "NTx86") == 0 ||
394141963Swpaul	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
395141963Swpaul	    strcasecmp(manf->vals[1], "NTamd64") == 0)) {
396126706Swpaul		/* Handle Windows XP INF files. */
397126706Swpaul		snprintf(xpsec, sizeof(xpsec), "%s.%s",
398126706Swpaul		    manf->vals[0], manf->vals[1]);
399126706Swpaul		sec = find_section(xpsec);
400126706Swpaul	} else
401126706Swpaul		sec = find_section(manf->vals[0]);
402126706Swpaul
403126706Swpaul	/* See if there are any PCMCIA device definitions. */
404126706Swpaul
405126706Swpaul	TAILQ_FOREACH(assign, &ah, link) {
406126706Swpaul		if (assign->section == sec) {
407126706Swpaul			dev = find_assign("strings", assign->key);
408126706Swpaul			if (strcasestr(assign->vals[1], "PCMCIA") != NULL) {
409126706Swpaul				found++;
410126706Swpaul				break;
411126706Swpaul			}
412126706Swpaul		}
413126706Swpaul	}
414126706Swpaul
415126706Swpaul	if (found == 0)
416146243Swpaul		goto done;
417126706Swpaul
418126706Swpaul	found = 0;
419126706Swpaul
420179855Sweongyo	if (first == 1) {
421179855Sweongyo		/* Emit start of PCMCIA device table */
422179855Sweongyo		fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE");
423179855Sweongyo		first = 0;
424179855Sweongyo	}
425126706Swpaul
426126706Swpaulretry:
427126706Swpaul
428126706Swpaul	/*
429126706Swpaul	 * Now run through all the device names listed
430126706Swpaul	 * in the manufacturer section and dump out the
431126706Swpaul	 * device descriptions and vendor/device IDs.
432126706Swpaul	 */
433126706Swpaul
434126706Swpaul	TAILQ_FOREACH(assign, &ah, link) {
435126706Swpaul		if (assign->section == sec) {
436126706Swpaul			dev = find_assign("strings", assign->key);
437126706Swpaul			/* Emit device IDs. */
438126706Swpaul			if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
439123475Swpaul				dump_pcmcia_id(assign->vals[1]);
440126706Swpaul			else
441126706Swpaul				continue;
442123475Swpaul			/* Emit device description */
443123480Swpaul			fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
444125073Swpaul			found++;
445123475Swpaul		}
446123475Swpaul	}
447123475Swpaul
448125073Swpaul	/* Someone tried to fool us. Shame on them. */
449125073Swpaul	if (!found) {
450125073Swpaul		found++;
451125073Swpaul		sec = find_section(manf->vals[0]);
452125073Swpaul		goto retry;
453125073Swpaul	}
454125073Swpaul
455146243Swpaul	/* Handle Manufacturer sections with multiple entries. */
456146243Swpaul	manf = find_next_assign(manf);
457146243Swpaul
458146243Swpaul	if (manf != NULL)
459146243Swpaul		goto nextmanf;
460146243Swpaul
461146243Swpauldone:
462123475Swpaul	/* Emit end of table */
463123475Swpaul
464123480Swpaul	fprintf(ofp, "\n\n");
465123480Swpaul
466343730Savos	return (found);
467123475Swpaul}
468123475Swpaul
469343730Savosstatic int
470186507Sweongyodump_deviceids_usb()
471186507Sweongyo{
472186507Sweongyo	struct assign *manf, *dev;
473186507Sweongyo	struct section *sec;
474186507Sweongyo	struct assign *assign;
475186507Sweongyo	char xpsec[256];
476186507Sweongyo	int first = 1, found = 0;
477186507Sweongyo
478186507Sweongyo	/* Find manufacturer name */
479186507Sweongyo	manf = find_assign("Manufacturer", NULL);
480186507Sweongyo
481186507Sweongyonextmanf:
482186507Sweongyo
483186507Sweongyo	/* Find manufacturer section */
484186507Sweongyo	if (manf->vals[1] != NULL &&
485186507Sweongyo	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
486186507Sweongyo	    strcasecmp(manf->vals[1], "NTx86") == 0 ||
487186507Sweongyo	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
488186507Sweongyo	    strcasecmp(manf->vals[1], "NTamd64") == 0)) {
489186507Sweongyo		/* Handle Windows XP INF files. */
490186507Sweongyo		snprintf(xpsec, sizeof(xpsec), "%s.%s",
491186507Sweongyo		    manf->vals[0], manf->vals[1]);
492186507Sweongyo		sec = find_section(xpsec);
493186507Sweongyo	} else
494186507Sweongyo		sec = find_section(manf->vals[0]);
495186507Sweongyo
496186507Sweongyo	/* See if there are any USB device definitions. */
497186507Sweongyo
498186507Sweongyo	TAILQ_FOREACH(assign, &ah, link) {
499186507Sweongyo		if (assign->section == sec) {
500186507Sweongyo			dev = find_assign("strings", assign->key);
501186507Sweongyo			if (strcasestr(assign->vals[1], "USB") != NULL) {
502186507Sweongyo				found++;
503186507Sweongyo				break;
504186507Sweongyo			}
505186507Sweongyo		}
506186507Sweongyo	}
507186507Sweongyo
508186507Sweongyo	if (found == 0)
509186507Sweongyo		goto done;
510186507Sweongyo
511186507Sweongyo	found = 0;
512186507Sweongyo
513186507Sweongyo	if (first == 1) {
514186507Sweongyo		/* Emit start of USB device table */
515186507Sweongyo		fprintf (ofp, "#define NDIS_USB_DEV_TABLE");
516186507Sweongyo		first = 0;
517186507Sweongyo	}
518186507Sweongyo
519186507Sweongyoretry:
520186507Sweongyo
521186507Sweongyo	/*
522186507Sweongyo	 * Now run through all the device names listed
523186507Sweongyo	 * in the manufacturer section and dump out the
524186507Sweongyo	 * device descriptions and vendor/device IDs.
525186507Sweongyo	 */
526186507Sweongyo
527186507Sweongyo	TAILQ_FOREACH(assign, &ah, link) {
528186507Sweongyo		if (assign->section == sec) {
529186507Sweongyo			dev = find_assign("strings", assign->key);
530186507Sweongyo			/* Emit device IDs. */
531186507Sweongyo			if (strcasestr(assign->vals[1], "USB") != NULL)
532186507Sweongyo				dump_usb_id(assign->vals[1]);
533186507Sweongyo			else
534186507Sweongyo				continue;
535186507Sweongyo			/* Emit device description */
536186507Sweongyo			fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
537186507Sweongyo			found++;
538186507Sweongyo		}
539186507Sweongyo	}
540186507Sweongyo
541186507Sweongyo	/* Someone tried to fool us. Shame on them. */
542186507Sweongyo	if (!found) {
543186507Sweongyo		found++;
544186507Sweongyo		sec = find_section(manf->vals[0]);
545186507Sweongyo		goto retry;
546186507Sweongyo	}
547186507Sweongyo
548186507Sweongyo	/* Handle Manufacturer sections with multiple entries. */
549186507Sweongyo	manf = find_next_assign(manf);
550186507Sweongyo
551186507Sweongyo	if (manf != NULL)
552186507Sweongyo		goto nextmanf;
553186507Sweongyo
554186507Sweongyodone:
555186507Sweongyo	/* Emit end of table */
556186507Sweongyo
557186507Sweongyo	fprintf(ofp, "\n\n");
558186507Sweongyo
559343730Savos	return (found);
560186507Sweongyo}
561186507Sweongyo
562186507Sweongyostatic void
563123620Swpauldump_addreg(const char *s, int devidx)
564123475Swpaul{
565123475Swpaul	struct section *sec;
566123475Swpaul	struct reg *reg;
567123475Swpaul
568123475Swpaul	/* Find the addreg section */
569123475Swpaul	sec = find_section(s);
570123475Swpaul
571123475Swpaul	/* Dump all the keys defined in it. */
572123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
573123475Swpaul		/*
574123475Swpaul		 * Keys with an empty subkey are very easy to parse,
575123475Swpaul		 * so just deal with them here. If a parameter key
576123475Swpaul		 * of the same name also exists, prefer that one and
577123475Swpaul		 * skip this one.
578123475Swpaul		 */
579123475Swpaul		if (reg->section == sec) {
580123475Swpaul			if (reg->subkey == NULL) {
581123475Swpaul				fprintf(ofp, "\n\t{ \"%s\",", reg->key);
582123475Swpaul				fprintf(ofp,"\n\t\"%s \",", reg->key);
583123620Swpaul				fprintf(ofp, "\n\t{ \"%s\" }, %d },",
584123475Swpaul				    reg->value == NULL ? "" :
585123620Swpaul				    stringcvt(reg->value), devidx);
586124452Swpaul			} else if (strncasecmp(reg->subkey,
587124452Swpaul			    "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
588124886Swpaul			    (reg->key != NULL && strcasecmp(reg->key,
589124886Swpaul			    "ParamDesc") == 0))
590123620Swpaul				dump_paramreg(sec, reg, devidx);
591123475Swpaul		}
592123475Swpaul	}
593123475Swpaul
594123475Swpaul	return;
595123475Swpaul}
596123475Swpaul
597123475Swpaulstatic void
598123475Swpauldump_enumreg(const struct section *s, const struct reg *r)
599123475Swpaul{
600123475Swpaul	struct reg *reg;
601123475Swpaul	char enumkey[256];
602123475Swpaul
603123475Swpaul	sprintf(enumkey, "%s\\enum", r->subkey);
604123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
605123475Swpaul		if (reg->section != s)
606123475Swpaul			continue;
607123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
608123475Swpaul			continue;
609123483Swpaul		fprintf(ofp, " [%s=%s]", reg->key,
610123483Swpaul		    stringcvt(reg->value));
611123475Swpaul	}
612123475Swpaul	return;
613123475Swpaul}
614123475Swpaul
615123475Swpaulstatic void
616123475Swpauldump_editreg(const struct section *s, const struct reg *r)
617123475Swpaul{
618123475Swpaul	struct reg *reg;
619123475Swpaul
620123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
621123475Swpaul		if (reg->section != s)
622123475Swpaul			continue;
623123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
624123475Swpaul			continue;
625124886Swpaul		if (reg->key == NULL)
626124886Swpaul			continue;
627123475Swpaul		if (strcasecmp(reg->key, "LimitText") == 0)
628123475Swpaul			fprintf(ofp, " [maxchars=%s]", reg->value);
629123475Swpaul		if (strcasecmp(reg->key, "Optional") == 0 &&
630123475Swpaul		    strcmp(reg->value, "1") == 0)
631123475Swpaul			fprintf(ofp, " [optional]");
632123475Swpaul	}
633123475Swpaul	return;
634123475Swpaul}
635123475Swpaul
636123475Swpaul/* Use this for int too */
637123475Swpaulstatic void
638123475Swpauldump_dwordreg(const struct section *s, const struct reg *r)
639123475Swpaul{
640123475Swpaul	struct reg *reg;
641123475Swpaul
642123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
643123475Swpaul		if (reg->section != s)
644123475Swpaul			continue;
645123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
646123475Swpaul			continue;
647124886Swpaul		if (reg->key == NULL)
648124886Swpaul			continue;
649123475Swpaul		if (strcasecmp(reg->key, "min") == 0)
650123475Swpaul			fprintf(ofp, " [min=%s]", reg->value);
651123475Swpaul		if (strcasecmp(reg->key, "max") == 0)
652123475Swpaul			fprintf(ofp, " [max=%s]", reg->value);
653123475Swpaul	}
654123475Swpaul	return;
655123475Swpaul}
656123475Swpaul
657123475Swpaulstatic void
658123620Swpauldump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
659123475Swpaul{
660123475Swpaul	struct reg *reg;
661123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
662123475Swpaul		if (reg->section != s)
663123475Swpaul			continue;
664123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
665123475Swpaul			continue;
666124886Swpaul		if (reg->key == NULL || strcasecmp(reg->key, "Default"))
667123475Swpaul			continue;
668123620Swpaul		fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
669123977Swpaul		    stringcvt(reg->value), devidx);
670178214Sthompsa		return;
671123475Swpaul	}
672178214Sthompsa	/* Default registry entry missing */
673178214Sthompsa	fprintf(ofp, "\n\t{ \"\" }, %d },", devidx);
674123475Swpaul	return;
675123475Swpaul}
676123475Swpaul
677123475Swpaulstatic void
678123475Swpauldump_paramdesc(const struct section *s, const struct reg *r)
679123475Swpaul{
680123475Swpaul	struct reg *reg;
681123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
682123475Swpaul		if (reg->section != s)
683123475Swpaul			continue;
684123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
685123475Swpaul			continue;
686124886Swpaul		if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc"))
687123475Swpaul			continue;
688123475Swpaul		fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
689123475Swpaul			break;
690123475Swpaul	}
691123475Swpaul	return;
692123475Swpaul}
693123475Swpaul
694123475Swpaulstatic void
695123475Swpauldump_typeinfo(const struct section *s, const struct reg *r)
696123475Swpaul{
697123475Swpaul	struct reg *reg;
698123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
699123475Swpaul		if (reg->section != s)
700123475Swpaul			continue;
701123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
702123475Swpaul			continue;
703124886Swpaul		if (reg->key == NULL)
704124886Swpaul			continue;
705123475Swpaul		if (strcasecmp(reg->key, "type"))
706123475Swpaul			continue;
707123475Swpaul		if (strcasecmp(reg->value, "dword") == 0 ||
708123475Swpaul		    strcasecmp(reg->value, "int") == 0)
709123475Swpaul			dump_dwordreg(s, r);
710123475Swpaul		if (strcasecmp(reg->value, "enum") == 0)
711123475Swpaul			dump_enumreg(s, r);
712123475Swpaul		if (strcasecmp(reg->value, "edit") == 0)
713123475Swpaul			dump_editreg(s, r);
714123475Swpaul	}
715123475Swpaul	return;
716123475Swpaul}
717123475Swpaul
718123475Swpaulstatic void
719123620Swpauldump_paramreg(const struct section *s, const struct reg *r, int devidx)
720123475Swpaul{
721123475Swpaul	const char *keyname;
722123475Swpaul
723123475Swpaul	keyname = r->subkey + strlen("Ndi\\params\\");
724123475Swpaul	fprintf(ofp, "\n\t{ \"%s\",", keyname);
725123475Swpaul	dump_paramdesc(s, r);
726123475Swpaul	dump_typeinfo(s, r);
727123475Swpaul	fprintf(ofp, "\",");
728123620Swpaul	dump_defaultinfo(s, r, devidx);
729123475Swpaul
730123475Swpaul	return;
731123475Swpaul}
732123475Swpaul
733141981Swpaulstatic void
734123475Swpauldump_regvals(void)
735123475Swpaul{
736123620Swpaul	struct assign *manf, *dev;
737123475Swpaul	struct section *sec;
738123475Swpaul	struct assign *assign;
739123475Swpaul	char sname[256];
740125073Swpaul	int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0;
741123475Swpaul
742124085Swpaul	/* Find signature to check for special case of WinNT. */
743124085Swpaul	assign = find_assign("version", "signature");
744124085Swpaul	if (strcasecmp(assign->vals[0], "$windows nt$") == 0)
745124085Swpaul		is_winnt++;
746124085Swpaul
747146243Swpaul	/* Emit start of block */
748146243Swpaul	fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
749146243Swpaul
750123475Swpaul	/* Find manufacturer name */
751123475Swpaul	manf = find_assign("Manufacturer", NULL);
752123475Swpaul
753146243Swpaulnextmanf:
754146243Swpaul
755123475Swpaul	/* Find manufacturer section */
756123483Swpaul	if (manf->vals[1] != NULL &&
757123511Swpaul	    (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
758124094Swpaul	    strcasecmp(manf->vals[1], "NTx86") == 0 ||
759141963Swpaul	    strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
760141963Swpaul	    strcasecmp(manf->vals[1], "NTamd64") == 0)) {
761123483Swpaul		is_winxp++;
762123483Swpaul		/* Handle Windows XP INF files. */
763123483Swpaul		snprintf(sname, sizeof(sname), "%s.%s",
764123483Swpaul		    manf->vals[0], manf->vals[1]);
765123483Swpaul		sec = find_section(sname);
766123483Swpaul	} else
767123483Swpaul		sec = find_section(manf->vals[0]);
768123475Swpaul
769125073Swpaulretry:
770125073Swpaul
771123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
772123475Swpaul		if (assign->section == sec) {
773125073Swpaul			found++;
774123483Swpaul			/*
775123483Swpaul			 * Find all the AddReg sections.
776123483Swpaul			 * Look for section names with .NT, unless
777123483Swpaul			 * this is a WinXP .INF file.
778123483Swpaul			 */
779141963Swpaul
780123511Swpaul			if (is_winxp) {
781123511Swpaul				sprintf(sname, "%s.NTx86", assign->vals[0]);
782123511Swpaul				dev = find_assign(sname, "AddReg");
783141963Swpaul				if (dev == NULL) {
784141963Swpaul					sprintf(sname, "%s.NT",
785141963Swpaul					    assign->vals[0]);
786141963Swpaul					dev = find_assign(sname, "AddReg");
787141963Swpaul				}
788123511Swpaul				if (dev == NULL)
789123511Swpaul					dev = find_assign(assign->vals[0],
790123511Swpaul					    "AddReg");
791123511Swpaul			} else {
792123483Swpaul				sprintf(sname, "%s.NT", assign->vals[0]);
793123483Swpaul				dev = find_assign(sname, "AddReg");
794124085Swpaul				if (dev == NULL && is_winnt)
795124085Swpaul					dev = find_assign(assign->vals[0],
796124085Swpaul					    "AddReg");
797123483Swpaul			}
798123483Swpaul			/* Section not found. */
799123483Swpaul			if (dev == NULL)
800123483Swpaul				continue;
801123475Swpaul			for (i = 0; i < W_MAX; i++) {
802123475Swpaul				if (dev->vals[i] != NULL)
803123620Swpaul					dump_addreg(dev->vals[i], devidx);
804123475Swpaul			}
805123620Swpaul			devidx++;
806123475Swpaul		}
807123475Swpaul	}
808123475Swpaul
809125073Swpaul	if (!found) {
810125073Swpaul		sec = find_section(manf->vals[0]);
811125073Swpaul		is_winxp = 0;
812125073Swpaul		found++;
813125073Swpaul		goto retry;
814125073Swpaul	}
815125073Swpaul
816146243Swpaul	manf = find_next_assign(manf);
817146243Swpaul
818146243Swpaul	if (manf != NULL)
819146243Swpaul		goto nextmanf;
820146243Swpaul
821123620Swpaul	fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
822123475Swpaul
823123475Swpaul	return;
824123475Swpaul}
825123475Swpaul
826123475Swpaulvoid
827123475Swpaulassign_add (const char *a)
828123475Swpaul{
829123475Swpaul	struct assign *assign;
830123475Swpaul	int i;
831123475Swpaul
832123475Swpaul	assign = malloc(sizeof(struct assign));
833123475Swpaul	bzero(assign, sizeof(struct assign));
834123475Swpaul	assign->section = TAILQ_LAST(&sh, section_head);
835123475Swpaul	assign->key = sstrdup(a);
836123475Swpaul	for (i = 0; i < idx; i++)
837123475Swpaul		assign->vals[(idx - 1) - i] = sstrdup(words[i]);
838123475Swpaul	TAILQ_INSERT_TAIL(&ah, assign, link);
839123475Swpaul
840123475Swpaul	clear_words();
841123475Swpaul	return;
842123475Swpaul}
843123475Swpaul
844123475Swpaulvoid
845123475Swpauldefine_add (const char *d __unused)
846123475Swpaul{
847123475Swpaul#ifdef notdef
848123475Swpaul	fprintf(stderr, "define \"%s\"\n", d);
849123475Swpaul#endif
850123475Swpaul	return;
851123475Swpaul}
852123475Swpaul
853123475Swpaulstatic char *
854123475Swpaulsstrdup(const char *str)
855123475Swpaul{
856123475Swpaul	if (str != NULL && strlen(str))
857123475Swpaul		return (strdup(str));
858123475Swpaul	return (NULL);
859123475Swpaul}
860123475Swpaul
861123475Swpaulstatic int
862123475Swpaulsatoi (const char *nptr)
863123475Swpaul{
864123475Swpaul	if (nptr != NULL && strlen(nptr))
865123475Swpaul		return (atoi(nptr));
866123475Swpaul	return (0);
867123475Swpaul}
868123475Swpaul
869123475Swpaulvoid
870123475Swpaulregkey_add (const char *r)
871123475Swpaul{
872123475Swpaul	struct reg *reg;
873123475Swpaul
874123475Swpaul	reg = malloc(sizeof(struct reg));
875123475Swpaul	bzero(reg, sizeof(struct reg));
876123475Swpaul	reg->section = TAILQ_LAST(&sh, section_head);
877123475Swpaul	reg->root = sstrdup(r);
878123475Swpaul	reg->subkey = sstrdup(words[3]);
879123475Swpaul	reg->key = sstrdup(words[2]);
880123475Swpaul	reg->flags = satoi(words[1]);
881123475Swpaul	reg->value = sstrdup(words[0]);
882123475Swpaul	TAILQ_INSERT_TAIL(&rh, reg, link);
883123475Swpaul
884123475Swpaul	free(__DECONST(char *, r));
885123475Swpaul	clear_words();
886123475Swpaul	return;
887123475Swpaul}
888123475Swpaul
889123475Swpaulvoid
890123475Swpaulpush_word (const char *w)
891123475Swpaul{
892288924Samdmi3
893288924Samdmi3	if (idx == W_MAX) {
894288924Samdmi3		fprintf(stderr, "too many words; try bumping W_MAX in inf.h\n");
895288924Samdmi3		exit(1);
896288924Samdmi3	}
897288924Samdmi3
898123475Swpaul	if (w && strlen(w))
899123475Swpaul		words[idx++] = w;
900123475Swpaul	else
901123475Swpaul		words[idx++] = NULL;
902123475Swpaul	return;
903123475Swpaul}
904123475Swpaul
905123475Swpaulvoid
906123475Swpaulclear_words (void)
907123475Swpaul{
908123475Swpaul	int i;
909123475Swpaul
910123475Swpaul	for (i = 0; i < idx; i++) {
911123475Swpaul		if (words[i]) {
912123475Swpaul			free(__DECONST(char *, words[i]));
913123475Swpaul		}
914123475Swpaul	}
915123475Swpaul	idx = 0;
916123475Swpaul	bzero(words, sizeof(words));
917123475Swpaul	return;
918123475Swpaul}
919