inf.c revision 123475
1123475Swpaul/*
2123475Swpaul * $Id: inf.c,v 1.3 2003/11/30 21:58:16 winter Exp $
3123475Swpaul */
4123475Swpaul
5123475Swpaul#include <sys/cdefs.h>
6123475Swpaul__FBSDID("$FreeBSD: head/usr.sbin/ndiscvt/inf.c 123475 2003-12-11 22:38:14Z wpaul $");
7123475Swpaul
8123475Swpaul#include <stdio.h>
9123475Swpaul#include <stdlib.h>
10123475Swpaul#include <string.h>
11123475Swpaul#include <sys/types.h>
12123475Swpaul
13123475Swpaul#include <sys/queue.h>
14123475Swpaul
15123475Swpaul#include "inf.h"
16123475Swpaul
17123475Swpaulextern FILE *yyin;
18123475Swpaulint yyparse (void);
19123475Swpaul
20123475Swpaulconst char *words[W_MAX];	/* More than we'll need. */
21123475Swpaulint idx;
22123475Swpaul
23123475Swpaulstatic struct section_head sh;
24123475Swpaulstatic struct reg_head rh;
25123475Swpaulstatic struct assign_head ah;
26123475Swpaul
27123475Swpaulstatic char	*sstrdup	(const char *);
28123475Swpaulstatic struct assign
29123475Swpaul		*find_assign	(const char *, const char *);
30123475Swpaulstatic struct section
31123475Swpaul		*find_section	(const char *);
32123475Swpaulstatic void	dump_deviceids	(void);
33123475Swpaulstatic void	dump_pci_id	(const char *);
34123475Swpaulstatic void	dump_regvals	(void);
35123475Swpaulstatic void	dump_paramreg	(const struct section *, const struct reg *);
36123475Swpaul
37123475Swpaulstatic FILE	*ofp;
38123475Swpaul
39123475Swpaulint
40123475Swpaulinf_parse (FILE *fp, FILE *outfp)
41123475Swpaul{
42123475Swpaul	TAILQ_INIT(&sh);
43123475Swpaul	TAILQ_INIT(&rh);
44123475Swpaul	TAILQ_INIT(&ah);
45123475Swpaul
46123475Swpaul	ofp = outfp;
47123475Swpaul	yyin = fp;
48123475Swpaul	yyparse();
49123475Swpaul
50123475Swpaul	dump_deviceids();
51123475Swpaul	dump_regvals();
52123475Swpaul
53123475Swpaul	return (0);
54123475Swpaul}
55123475Swpaul
56123475Swpaulvoid
57123475Swpaulsection_add (const char *s)
58123475Swpaul{
59123475Swpaul	struct section *sec;
60123475Swpaul
61123475Swpaul	sec = malloc(sizeof(struct section));
62123475Swpaul	bzero(sec, sizeof(struct section));
63123475Swpaul	sec->name = s;
64123475Swpaul	TAILQ_INSERT_TAIL(&sh, sec, link);
65123475Swpaul
66123475Swpaul	return;
67123475Swpaul}
68123475Swpaul
69123475Swpaulstatic struct assign *
70123475Swpaulfind_assign (const char *s, const char *k)
71123475Swpaul{
72123475Swpaul	struct assign *assign;
73123475Swpaul	char newkey[256];
74123475Swpaul
75123475Swpaul	/* Deal with string section lookups. */
76123475Swpaul
77123475Swpaul	if (k != NULL && k[0] == '%') {
78123475Swpaul		bzero(newkey, sizeof(newkey));
79123475Swpaul		strncpy(newkey, k + 1, strlen(k) - 2);
80123475Swpaul		k = newkey;
81123475Swpaul	}
82123475Swpaul
83123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
84123475Swpaul		if (strcasecmp(assign->section->name, s) == 0) {
85123475Swpaul			if (k == NULL)
86123475Swpaul				return(assign);
87123475Swpaul			else
88123475Swpaul				if (strcasecmp(assign->key, k) == 0)
89123475Swpaul					return(assign);
90123475Swpaul		}
91123475Swpaul	}
92123475Swpaul	return(NULL);
93123475Swpaul}
94123475Swpaul
95123475Swpaulstatic const char *
96123475Swpaulstringcvt(const char *s)
97123475Swpaul{
98123475Swpaul	struct assign *manf;
99123475Swpaul
100123475Swpaul	manf = find_assign("strings", s);
101123475Swpaul	if (manf == NULL)
102123475Swpaul		return(s);
103123475Swpaul	return(manf->vals[0]);
104123475Swpaul}
105123475Swpaul
106123475Swpaulstruct section *
107123475Swpaulfind_section (const char *s)
108123475Swpaul{
109123475Swpaul	struct section *section;
110123475Swpaul
111123475Swpaul	TAILQ_FOREACH(section, &sh, link) {
112123475Swpaul		if (strcasecmp(section->name, s) == 0)
113123475Swpaul			return(section);
114123475Swpaul	}
115123475Swpaul	return(NULL);
116123475Swpaul}
117123475Swpaul
118123475Swpaulstatic void
119123475Swpauldump_pci_id(const char *s)
120123475Swpaul{
121123475Swpaul	char *p;
122123475Swpaul	char vidstr[7], didstr[7];
123123475Swpaul
124123475Swpaul	p = strcasestr(s, "VEN_");
125123475Swpaul	if (p == NULL)
126123475Swpaul		return;
127123475Swpaul	p += 4;
128123475Swpaul	strcpy(vidstr, "0x");
129123475Swpaul	strncat(vidstr, p, 4);
130123475Swpaul	p = strcasestr(s, "DEV_");
131123475Swpaul	if (p == NULL)
132123475Swpaul		return;
133123475Swpaul	p += 4;
134123475Swpaul	strcpy(didstr, "0x");
135123475Swpaul	strncat(didstr, p, 4);
136123475Swpaul	if (p == NULL)
137123475Swpaul		return;
138123475Swpaul
139123475Swpaul	fprintf(ofp, "\t\\\n\t{ %s, %s,", vidstr, didstr);
140123475Swpaul	return;
141123475Swpaul}
142123475Swpaul
143123475Swpaulstatic void
144123475Swpauldump_deviceids()
145123475Swpaul{
146123475Swpaul	struct assign *manf, *dev;
147123475Swpaul	struct section *sec;
148123475Swpaul	struct assign *assign;
149123475Swpaul
150123475Swpaul	/* Find manufacturer name */
151123475Swpaul	manf = find_assign("Manufacturer", NULL);
152123475Swpaul
153123475Swpaul	/* Find manufacturer section */
154123475Swpaul	sec = find_section(manf->vals[0]);
155123475Swpaul
156123475Swpaul	/* Emit start of device table */
157123475Swpaul	fprintf (ofp, "#define NDIS_DEV_TABLE");
158123475Swpaul
159123475Swpaul	/*
160123475Swpaul	 * Now run through all the device names listed
161123475Swpaul	 * in the manufacturer section and dump out the
162123475Swpaul	 * device descriptions and vendor/device IDs.
163123475Swpaul	 */
164123475Swpaul
165123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
166123475Swpaul		if (assign->section == sec) {
167123475Swpaul			dev = find_assign("strings", assign->key);
168123475Swpaul			/* Emit device IDs. */
169123475Swpaul			if (strcasestr(assign->vals[1], "PCI") != NULL)
170123475Swpaul				dump_pci_id(assign->vals[1]);
171123475Swpaul#ifdef notdef
172123475Swpaul			else if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
173123475Swpaul				dump_pcmcia_id(assign->vals[1]);
174123475Swpaul#endif
175123475Swpaul			/* Emit device description */
176123475Swpaul			fprintf (ofp, "\t\\\n\t\"%s\"", dev->vals[0]);
177123475Swpaul		}
178123475Swpaul	}
179123475Swpaul
180123475Swpaul	/* Emit end of table */
181123475Swpaul
182123475Swpaul	fprintf(ofp, " },\n\n");
183123475Swpaul}
184123475Swpaul
185123475Swpaulstatic void
186123475Swpauldump_addreg(const char *s)
187123475Swpaul{
188123475Swpaul	struct section *sec;
189123475Swpaul	struct reg *reg;
190123475Swpaul
191123475Swpaul	/* Find the addreg section */
192123475Swpaul	sec = find_section(s);
193123475Swpaul
194123475Swpaul	/* Dump all the keys defined in it. */
195123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
196123475Swpaul		/*
197123475Swpaul		 * Keys with an empty subkey are very easy to parse,
198123475Swpaul		 * so just deal with them here. If a parameter key
199123475Swpaul		 * of the same name also exists, prefer that one and
200123475Swpaul		 * skip this one.
201123475Swpaul		 */
202123475Swpaul		if (reg->section == sec) {
203123475Swpaul			if (reg->subkey == NULL) {
204123475Swpaul				fprintf(ofp, "\n\t{ \"%s\",", reg->key);
205123475Swpaul				fprintf(ofp,"\n\t\"%s \",", reg->key);
206123475Swpaul				fprintf(ofp, "\n\t{ \"%s\" } },",
207123475Swpaul				    reg->value == NULL ? "" :
208123475Swpaul				    reg->value);
209123475Swpaul			} else if (strcasestr(reg->subkey,
210123475Swpaul			    "Ndi\\params") != NULL &&
211123475Swpaul			    strcasecmp(reg->key, "ParamDesc") == 0)
212123475Swpaul				dump_paramreg(sec, reg);
213123475Swpaul		}
214123475Swpaul	}
215123475Swpaul
216123475Swpaul	return;
217123475Swpaul}
218123475Swpaul
219123475Swpaulstatic void
220123475Swpauldump_enumreg(const struct section *s, const struct reg *r)
221123475Swpaul{
222123475Swpaul	struct reg *reg;
223123475Swpaul	char enumkey[256];
224123475Swpaul
225123475Swpaul	sprintf(enumkey, "%s\\enum", r->subkey);
226123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
227123475Swpaul		if (reg->section != s)
228123475Swpaul			continue;
229123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
230123475Swpaul			continue;
231123475Swpaul		fprintf(ofp, " [%s=%s]", reg->key, stringcvt(reg->value));
232123475Swpaul	}
233123475Swpaul	return;
234123475Swpaul}
235123475Swpaul
236123475Swpaulstatic void
237123475Swpauldump_editreg(const struct section *s, const struct reg *r)
238123475Swpaul{
239123475Swpaul	struct reg *reg;
240123475Swpaul
241123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
242123475Swpaul		if (reg->section != s)
243123475Swpaul			continue;
244123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
245123475Swpaul			continue;
246123475Swpaul		if (strcasecmp(reg->key, "LimitText") == 0)
247123475Swpaul			fprintf(ofp, " [maxchars=%s]", reg->value);
248123475Swpaul		if (strcasecmp(reg->key, "Optional") == 0 &&
249123475Swpaul		    strcmp(reg->value, "1") == 0)
250123475Swpaul			fprintf(ofp, " [optional]");
251123475Swpaul	}
252123475Swpaul	return;
253123475Swpaul}
254123475Swpaul
255123475Swpaul/* Use this for int too */
256123475Swpaulstatic void
257123475Swpauldump_dwordreg(const struct section *s, const struct reg *r)
258123475Swpaul{
259123475Swpaul	struct reg *reg;
260123475Swpaul
261123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
262123475Swpaul		if (reg->section != s)
263123475Swpaul			continue;
264123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
265123475Swpaul			continue;
266123475Swpaul		if (strcasecmp(reg->key, "min") == 0)
267123475Swpaul			fprintf(ofp, " [min=%s]", reg->value);
268123475Swpaul		if (strcasecmp(reg->key, "max") == 0)
269123475Swpaul			fprintf(ofp, " [max=%s]", reg->value);
270123475Swpaul	}
271123475Swpaul	return;
272123475Swpaul}
273123475Swpaul
274123475Swpaulstatic void
275123475Swpauldump_defaultinfo(const struct section *s, const struct reg *r)
276123475Swpaul{
277123475Swpaul	struct reg *reg;
278123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
279123475Swpaul		if (reg->section != s)
280123475Swpaul			continue;
281123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
282123475Swpaul			continue;
283123475Swpaul		if (strcasecmp(reg->key, "Default"))
284123475Swpaul			continue;
285123475Swpaul		fprintf(ofp, "\n\t{ \"%s\" } },", reg->value == NULL ? "" :
286123475Swpaul		    reg->value);
287123475Swpaul			break;
288123475Swpaul	}
289123475Swpaul	return;
290123475Swpaul}
291123475Swpaul
292123475Swpaulstatic void
293123475Swpauldump_paramdesc(const struct section *s, const struct reg *r)
294123475Swpaul{
295123475Swpaul	struct reg *reg;
296123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
297123475Swpaul		if (reg->section != s)
298123475Swpaul			continue;
299123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
300123475Swpaul			continue;
301123475Swpaul		if (strcasecmp(reg->key, "ParamDesc"))
302123475Swpaul			continue;
303123475Swpaul		fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
304123475Swpaul			break;
305123475Swpaul	}
306123475Swpaul	return;
307123475Swpaul}
308123475Swpaul
309123475Swpaulstatic void
310123475Swpauldump_typeinfo(const struct section *s, const struct reg *r)
311123475Swpaul{
312123475Swpaul	struct reg *reg;
313123475Swpaul	TAILQ_FOREACH(reg, &rh, link) {
314123475Swpaul		if (reg->section != s)
315123475Swpaul			continue;
316123475Swpaul		if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
317123475Swpaul			continue;
318123475Swpaul		if (strcasecmp(reg->key, "type"))
319123475Swpaul			continue;
320123475Swpaul		if (strcasecmp(reg->value, "dword") == 0 ||
321123475Swpaul		    strcasecmp(reg->value, "int") == 0)
322123475Swpaul			dump_dwordreg(s, r);
323123475Swpaul		if (strcasecmp(reg->value, "enum") == 0)
324123475Swpaul			dump_enumreg(s, r);
325123475Swpaul		if (strcasecmp(reg->value, "edit") == 0)
326123475Swpaul			dump_editreg(s, r);
327123475Swpaul	}
328123475Swpaul	return;
329123475Swpaul}
330123475Swpaul
331123475Swpaulstatic void
332123475Swpauldump_paramreg(const struct section *s, const struct reg *r)
333123475Swpaul{
334123475Swpaul	const char *keyname;
335123475Swpaul
336123475Swpaul	keyname = r->subkey + strlen("Ndi\\params\\");
337123475Swpaul	fprintf(ofp, "\n\t{ \"%s\",", keyname);
338123475Swpaul	dump_paramdesc(s, r);
339123475Swpaul	dump_typeinfo(s, r);
340123475Swpaul	fprintf(ofp, "\",");
341123475Swpaul	dump_defaultinfo(s, r);
342123475Swpaul
343123475Swpaul	return;
344123475Swpaul}
345123475Swpaul
346123475Swpaulstatic void
347123475Swpauldump_regvals(void)
348123475Swpaul{
349123475Swpaul	struct assign *manf, *dev, *dev_dup;
350123475Swpaul	struct section *sec;
351123475Swpaul	struct assign *assign;
352123475Swpaul	struct assign_head tmp_ah;
353123475Swpaul	char sname[256];
354123475Swpaul	int i;
355123475Swpaul
356123475Swpaul	TAILQ_INIT(&tmp_ah);
357123475Swpaul
358123475Swpaul	/* Find manufacturer name */
359123475Swpaul	manf = find_assign("Manufacturer", NULL);
360123475Swpaul
361123475Swpaul	/* Find manufacturer section */
362123475Swpaul	sec = find_section(manf->vals[0]);
363123475Swpaul
364123475Swpaul	/* Emit start of block */
365123475Swpaul	fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
366123475Swpaul
367123475Swpaul	TAILQ_FOREACH(assign, &ah, link) {
368123475Swpaul		/* Avoid repeating the same section. */
369123475Swpaul		i = 0;
370123475Swpaul		TAILQ_FOREACH(dev_dup, &tmp_ah, link)
371123475Swpaul			if (strcmp(dev_dup->vals[0], assign->vals[0]) == 0) {
372123475Swpaul				i++;
373123475Swpaul				break;
374123475Swpaul		}
375123475Swpaul		if (i)
376123475Swpaul			continue;
377123475Swpaul		dev_dup = malloc(sizeof(struct assign));
378123475Swpaul		bcopy((char *)assign, (char *)dev_dup,
379123475Swpaul		    sizeof(struct assign));
380123475Swpaul		TAILQ_INSERT_TAIL(&tmp_ah, dev_dup, link);
381123475Swpaul		if (assign->section == sec) {
382123475Swpaul			/* Ignore Windows 95-era data. */
383123475Swpaul			sprintf(sname, "%s.NT", assign->vals[0]);
384123475Swpaul			/* Find all the AddReg sections. */
385123475Swpaul			dev = find_assign(sname, "AddReg");
386123475Swpaul			for (i = 0; i < W_MAX; i++) {
387123475Swpaul				if (dev->vals[i] != NULL)
388123475Swpaul					dump_addreg(dev->vals[i]);
389123475Swpaul			}
390123475Swpaul		}
391123475Swpaul	}
392123475Swpaul
393123475Swpaul	fprintf(ofp, "\n\t{ NULL, NULL, { 0 } }\n};\n\n");
394123475Swpaul
395123475Swpaul	return;
396123475Swpaul}
397123475Swpaul
398123475Swpaulvoid
399123475Swpaulassign_add (const char *a)
400123475Swpaul{
401123475Swpaul	struct assign *assign;
402123475Swpaul	int i;
403123475Swpaul
404123475Swpaul	assign = malloc(sizeof(struct assign));
405123475Swpaul	bzero(assign, sizeof(struct assign));
406123475Swpaul	assign->section = TAILQ_LAST(&sh, section_head);
407123475Swpaul	assign->key = sstrdup(a);
408123475Swpaul	for (i = 0; i < idx; i++)
409123475Swpaul		assign->vals[(idx - 1) - i] = sstrdup(words[i]);
410123475Swpaul	TAILQ_INSERT_TAIL(&ah, assign, link);
411123475Swpaul
412123475Swpaul	clear_words();
413123475Swpaul	return;
414123475Swpaul}
415123475Swpaul
416123475Swpaulvoid
417123475Swpauldefine_add (const char *d __unused)
418123475Swpaul{
419123475Swpaul#ifdef notdef
420123475Swpaul	fprintf(stderr, "define \"%s\"\n", d);
421123475Swpaul#endif
422123475Swpaul	return;
423123475Swpaul}
424123475Swpaul
425123475Swpaulstatic char *
426123475Swpaulsstrdup(const char *str)
427123475Swpaul{
428123475Swpaul	if (str != NULL && strlen(str))
429123475Swpaul		return (strdup(str));
430123475Swpaul	return (NULL);
431123475Swpaul}
432123475Swpaul
433123475Swpaulstatic int
434123475Swpaulsatoi (const char *nptr)
435123475Swpaul{
436123475Swpaul	if (nptr != NULL && strlen(nptr))
437123475Swpaul		return (atoi(nptr));
438123475Swpaul	return (0);
439123475Swpaul}
440123475Swpaul
441123475Swpaulvoid
442123475Swpaulregkey_add (const char *r)
443123475Swpaul{
444123475Swpaul	struct reg *reg;
445123475Swpaul
446123475Swpaul	reg = malloc(sizeof(struct reg));
447123475Swpaul	bzero(reg, sizeof(struct reg));
448123475Swpaul	reg->section = TAILQ_LAST(&sh, section_head);
449123475Swpaul	reg->root = sstrdup(r);
450123475Swpaul	reg->subkey = sstrdup(words[3]);
451123475Swpaul	reg->key = sstrdup(words[2]);
452123475Swpaul	reg->flags = satoi(words[1]);
453123475Swpaul	reg->value = sstrdup(words[0]);
454123475Swpaul	TAILQ_INSERT_TAIL(&rh, reg, link);
455123475Swpaul
456123475Swpaul	free(__DECONST(char *, r));
457123475Swpaul	clear_words();
458123475Swpaul	return;
459123475Swpaul}
460123475Swpaul
461123475Swpaulvoid
462123475Swpaulpush_word (const char *w)
463123475Swpaul{
464123475Swpaul	if (w && strlen(w))
465123475Swpaul		words[idx++] = w;
466123475Swpaul	else
467123475Swpaul		words[idx++] = NULL;
468123475Swpaul	return;
469123475Swpaul}
470123475Swpaul
471123475Swpaulvoid
472123475Swpaulclear_words (void)
473123475Swpaul{
474123475Swpaul	int i;
475123475Swpaul
476123475Swpaul	for (i = 0; i < idx; i++) {
477123475Swpaul		if (words[i]) {
478123475Swpaul			free(__DECONST(char *, words[i]));
479123475Swpaul		}
480123475Swpaul	}
481123475Swpaul	idx = 0;
482123475Swpaul	bzero(words, sizeof(words));
483123475Swpaul	return;
484123475Swpaul}
485