No empty .Rs/.Re
[netbsd-mini2440.git] / usr.sbin / ndiscvt / inf.c
blobf3f9d139b477f323055722ca35c39df3b14ea1d0
1 /*
2 * Copyright (c) 2003
3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
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.
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.
33 #include <sys/cdefs.h>
34 #ifdef __FreeBSD__
35 __FBSDID("$FreeBSD: src/usr.sbin/ndiscvt/inf.c,v 1.13.2.1 2005/02/18 16:30:10 wpaul Exp $");
36 #endif
37 #ifdef __NetBSD__
38 __RCSID("$NetBSD: inf.c,v 1.3 2006/04/18 16:49:19 rittera Exp $");
39 #endif
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #ifdef __NetBSD__
47 #include <sys/stdint.h>
48 #endif
50 #include <sys/queue.h>
52 #include "inf.h"
54 #ifndef __DECONST
55 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
56 #endif
59 extern FILE *ndiscvt_in;
60 int ndiscvt_parse (void);
62 const char *words[W_MAX]; /* More than we'll need. */
63 int idx;
65 static struct section_head sh;
66 static struct reg_head rh;
67 static struct assign_head ah;
69 static char *sstrdup (const char *);
70 static struct assign
71 *find_assign (const char *, const char *);
72 static struct section
73 *find_section (const char *);
74 static void dump_deviceids_pci (void);
75 static void dump_deviceids_pcmcia (void);
76 static void dump_pci_id (const char *);
77 static void dump_pcmcia_id (const char *);
78 static void dump_regvals (void);
79 static void dump_paramreg (const struct section *,
80 const struct reg *, int);
82 static FILE *ofp;
84 int
85 inf_parse (FILE *fp, FILE *outfp)
87 TAILQ_INIT(&sh);
88 TAILQ_INIT(&rh);
89 TAILQ_INIT(&ah);
91 ofp = outfp;
92 ndiscvt_in = fp;
93 ndiscvt_parse();
95 dump_deviceids_pci();
96 dump_deviceids_pcmcia();
97 fprintf(outfp, "#ifdef NDIS_REGVALS\n");
98 dump_regvals();
99 fprintf(outfp, "#endif /* NDIS_REGVALS */\n");
101 return (0);
104 void
105 section_add (const char *s)
107 struct section *sec;
109 sec = malloc(sizeof(struct section));
110 bzero(sec, sizeof(struct section));
111 sec->name = s;
112 TAILQ_INSERT_TAIL(&sh, sec, link);
114 return;
117 static struct assign *
118 find_assign (const char *s, const char *k)
120 struct assign *assign;
121 char newkey[256];
123 /* Deal with string section lookups. */
125 if (k != NULL && k[0] == '%') {
126 bzero(newkey, sizeof(newkey));
127 strncpy(newkey, k + 1, strlen(k) - 2);
128 k = newkey;
131 TAILQ_FOREACH(assign, &ah, link) {
132 if (strcasecmp(assign->section->name, s) == 0) {
133 if (k == NULL)
134 return(assign);
135 else
136 if (strcasecmp(assign->key, k) == 0)
137 return(assign);
140 return(NULL);
143 static const char *
144 stringcvt(const char *s)
146 struct assign *manf;
148 manf = find_assign("strings", s);
149 if (manf == NULL)
150 return(s);
151 return(manf->vals[0]);
154 struct section *
155 find_section (const char *s)
157 struct section *section;
159 TAILQ_FOREACH(section, &sh, link) {
160 if (strcasecmp(section->name, s) == 0)
161 return(section);
163 return(NULL);
166 static void
167 dump_pcmcia_id(const char *s)
169 char *manstr, *devstr;
170 char *p0, *p;
172 p0 = __DECONST(char *, s);
174 p = strchr(p0, '\\');
175 if (p == NULL)
176 return;
177 p0 = p + 1;
179 p = strchr(p0, '-');
180 if (p == NULL)
181 return;
182 *p = '\0';
184 manstr = p0;
186 /* Convert any underscores to spaces. */
188 while (*p0 != '\0') {
189 if (*p0 == '_')
190 *p0 = ' ';
191 p0++;
194 p0 = p + 1;
195 p = strchr(p0, '-');
196 if (p == NULL)
197 return;
198 *p = '\0';
200 devstr = p0;
202 /* Convert any underscores to spaces. */
204 while (*p0 != '\0') {
205 if (*p0 == '_')
206 *p0 = ' ';
207 p0++;
210 fprintf(ofp, "\t\\\n\t{ \"%s\", \"%s\", ", manstr, devstr);
211 return;
214 static void
215 dump_pci_id(const char *s)
217 char *p;
218 char vidstr[7], didstr[7], subsysstr[14];
220 p = strcasestr(s, "VEN_");
221 if (p == NULL)
222 return;
223 p += 4;
224 strcpy(vidstr, "0x");
225 strncat(vidstr, p, 4);
226 p = strcasestr(s, "DEV_");
227 if (p == NULL)
228 return;
229 p += 4;
230 strcpy(didstr, "0x");
231 strncat(didstr, p, 4);
232 if (p == NULL)
233 return;
234 p = strcasestr(s, "SUBSYS_");
235 if (p == NULL)
236 strcpy(subsysstr, "0x00000000");
237 else {
238 p += 7;
239 strcpy(subsysstr, "0x");
240 strncat(subsysstr, p, 8);
243 fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
244 return;
247 static void
248 dump_deviceids_pci()
250 struct assign *manf, *dev;
251 struct section *sec;
252 struct assign *assign;
253 char xpsec[256];
254 int found = 0;
256 /* Find manufacturer name */
257 manf = find_assign("Manufacturer", NULL);
259 /* Find manufacturer section */
260 if (manf->vals[1] != NULL &&
261 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
262 strcasecmp(manf->vals[1], "NTx86") == 0 ||
263 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
264 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
265 /* Handle Windows XP INF files. */
266 snprintf(xpsec, sizeof(xpsec), "%s.%s",
267 manf->vals[0], manf->vals[1]);
268 sec = find_section(xpsec);
269 } else
270 sec = find_section(manf->vals[0]);
272 /* See if there are any PCI device definitions. */
274 TAILQ_FOREACH(assign, &ah, link) {
275 if (assign->section == sec) {
276 dev = find_assign("strings", assign->key);
277 if (strcasestr(assign->vals[1], "PCI") != NULL) {
278 found++;
279 break;
284 if (found == 0)
285 return;
287 found = 0;
289 /* Emit start of PCI device table */
290 fprintf (ofp, "#define NDIS_PCI_DEV_TABLE");
292 retry:
295 * Now run through all the device names listed
296 * in the manufacturer section and dump out the
297 * device descriptions and vendor/device IDs.
300 TAILQ_FOREACH(assign, &ah, link) {
301 if (assign->section == sec) {
302 dev = find_assign("strings", assign->key);
303 /* Emit device IDs. */
304 if (strcasestr(assign->vals[1], "PCI") != NULL)
305 dump_pci_id(assign->vals[1]);
306 else
307 continue;
308 /* Emit device description */
309 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
310 found++;
314 /* Someone tried to fool us. Shame on them. */
315 if (!found) {
316 found++;
317 sec = find_section(manf->vals[0]);
318 goto retry;
321 /* Emit end of table */
323 fprintf(ofp, "\n\n");
327 static void
328 dump_deviceids_pcmcia()
330 struct assign *manf, *dev;
331 struct section *sec;
332 struct assign *assign;
333 char xpsec[256];
334 int found = 0;
336 /* Find manufacturer name */
337 manf = find_assign("Manufacturer", NULL);
339 /* Find manufacturer section */
340 if (manf->vals[1] != NULL &&
341 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
342 strcasecmp(manf->vals[1], "NTx86") == 0 ||
343 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
344 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
345 /* Handle Windows XP INF files. */
346 snprintf(xpsec, sizeof(xpsec), "%s.%s",
347 manf->vals[0], manf->vals[1]);
348 sec = find_section(xpsec);
349 } else
350 sec = find_section(manf->vals[0]);
352 /* See if there are any PCMCIA device definitions. */
354 TAILQ_FOREACH(assign, &ah, link) {
355 if (assign->section == sec) {
356 dev = find_assign("strings", assign->key);
357 if (strcasestr(assign->vals[1], "PCMCIA") != NULL) {
358 found++;
359 break;
364 if (found == 0)
365 return;
367 found = 0;
369 /* Emit start of PCMCIA device table */
370 fprintf (ofp, "#define NDIS_PCMCIA_DEV_TABLE");
372 retry:
375 * Now run through all the device names listed
376 * in the manufacturer section and dump out the
377 * device descriptions and vendor/device IDs.
380 TAILQ_FOREACH(assign, &ah, link) {
381 if (assign->section == sec) {
382 dev = find_assign("strings", assign->key);
383 /* Emit device IDs. */
384 if (strcasestr(assign->vals[1], "PCMCIA") != NULL)
385 dump_pcmcia_id(assign->vals[1]);
386 else
387 continue;
388 /* Emit device description */
389 fprintf (ofp, "\t\\\n\t\"%s\" },", dev->vals[0]);
390 found++;
394 /* Someone tried to fool us. Shame on them. */
395 if (!found) {
396 found++;
397 sec = find_section(manf->vals[0]);
398 goto retry;
401 /* Emit end of table */
403 fprintf(ofp, "\n\n");
407 static void
408 dump_addreg(const char *s, int devidx)
410 struct section *sec;
411 struct reg *reg;
413 /* Find the addreg section */
414 sec = find_section(s);
416 /* Dump all the keys defined in it. */
417 TAILQ_FOREACH(reg, &rh, link) {
419 * Keys with an empty subkey are very easy to parse,
420 * so just deal with them here. If a parameter key
421 * of the same name also exists, prefer that one and
422 * skip this one.
424 if (reg->section == sec) {
425 if (reg->subkey == NULL) {
426 fprintf(ofp, "\n\t{ \"%s\",", reg->key);
427 fprintf(ofp,"\n\t\"%s \",", reg->key);
428 fprintf(ofp, "\n\t{ \"%s\" }, %d },",
429 reg->value == NULL ? "" :
430 stringcvt(reg->value), devidx);
431 } else if (strncasecmp(reg->subkey,
432 "Ndi\\params", strlen("Ndi\\params")-1) == 0 &&
433 (reg->key != NULL && strcasecmp(reg->key,
434 "ParamDesc") == 0))
435 dump_paramreg(sec, reg, devidx);
439 return;
442 static void
443 dump_enumreg(const struct section *s, const struct reg *r)
445 struct reg *reg;
446 char enumkey[256];
448 sprintf(enumkey, "%s\\enum", r->subkey);
449 TAILQ_FOREACH(reg, &rh, link) {
450 if (reg->section != s)
451 continue;
452 if (reg->subkey == NULL || strcasecmp(reg->subkey, enumkey))
453 continue;
454 fprintf(ofp, " [%s=%s]", reg->key,
455 stringcvt(reg->value));
457 return;
460 static void
461 dump_editreg(const struct section *s, const struct reg *r)
463 struct reg *reg;
465 TAILQ_FOREACH(reg, &rh, link) {
466 if (reg->section != s)
467 continue;
468 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
469 continue;
470 if (reg->key == NULL)
471 continue;
472 if (strcasecmp(reg->key, "LimitText") == 0)
473 fprintf(ofp, " [maxchars=%s]", reg->value);
474 if (strcasecmp(reg->key, "Optional") == 0 &&
475 strcmp(reg->value, "1") == 0)
476 fprintf(ofp, " [optional]");
478 return;
481 /* Use this for int too */
482 static void
483 dump_dwordreg(const struct section *s, const struct reg *r)
485 struct reg *reg;
487 TAILQ_FOREACH(reg, &rh, link) {
488 if (reg->section != s)
489 continue;
490 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
491 continue;
492 if (reg->key == NULL)
493 continue;
494 if (strcasecmp(reg->key, "min") == 0)
495 fprintf(ofp, " [min=%s]", reg->value);
496 if (strcasecmp(reg->key, "max") == 0)
497 fprintf(ofp, " [max=%s]", reg->value);
499 return;
502 static void
503 dump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
505 struct reg *reg;
506 TAILQ_FOREACH(reg, &rh, link) {
507 if (reg->section != s)
508 continue;
509 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
510 continue;
511 if (reg->key == NULL || strcasecmp(reg->key, "Default"))
512 continue;
513 fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
514 stringcvt(reg->value), devidx);
515 break;
517 return;
520 static void
521 dump_paramdesc(const struct section *s, const struct reg *r)
523 struct reg *reg;
524 TAILQ_FOREACH(reg, &rh, link) {
525 if (reg->section != s)
526 continue;
527 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
528 continue;
529 if (reg->key == NULL || strcasecmp(reg->key, "ParamDesc"))
530 continue;
531 fprintf(ofp, "\n\t\"%s", stringcvt(r->value));
532 break;
534 return;
537 static void
538 dump_typeinfo(const struct section *s, const struct reg *r)
540 struct reg *reg;
541 TAILQ_FOREACH(reg, &rh, link) {
542 if (reg->section != s)
543 continue;
544 if (reg->subkey == NULL || strcasecmp(reg->subkey, r->subkey))
545 continue;
546 if (reg->key == NULL)
547 continue;
548 if (strcasecmp(reg->key, "type"))
549 continue;
550 if (strcasecmp(reg->value, "dword") == 0 ||
551 strcasecmp(reg->value, "int") == 0)
552 dump_dwordreg(s, r);
553 if (strcasecmp(reg->value, "enum") == 0)
554 dump_enumreg(s, r);
555 if (strcasecmp(reg->value, "edit") == 0)
556 dump_editreg(s, r);
558 return;
561 static void
562 dump_paramreg(const struct section *s, const struct reg *r, int devidx)
564 const char *keyname;
566 keyname = r->subkey + strlen("Ndi\\params\\");
567 fprintf(ofp, "\n\t{ \"%s\",", keyname);
568 dump_paramdesc(s, r);
569 dump_typeinfo(s, r);
570 fprintf(ofp, "\",");
571 dump_defaultinfo(s, r, devidx);
573 return;
576 static void
577 dump_regvals(void)
579 struct assign *manf, *dev;
580 struct section *sec;
581 struct assign *assign;
582 char sname[256];
583 int found = 0, i, is_winxp = 0, is_winnt = 0, devidx = 0;
585 /* Find signature to check for special case of WinNT. */
586 assign = find_assign("version", "signature");
587 if (strcasecmp(assign->vals[0], "$windows nt$") == 0)
588 is_winnt++;
590 /* Find manufacturer name */
591 manf = find_assign("Manufacturer", NULL);
593 /* Find manufacturer section */
594 if (manf->vals[1] != NULL &&
595 (strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
596 strcasecmp(manf->vals[1], "NTx86") == 0 ||
597 strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
598 strcasecmp(manf->vals[1], "NTamd64") == 0)) {
599 is_winxp++;
600 /* Handle Windows XP INF files. */
601 snprintf(sname, sizeof(sname), "%s.%s",
602 manf->vals[0], manf->vals[1]);
603 sec = find_section(sname);
604 } else
605 sec = find_section(manf->vals[0]);
607 /* Emit start of block */
608 fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
610 retry:
612 TAILQ_FOREACH(assign, &ah, link) {
613 if (assign->section == sec) {
614 found++;
616 * Find all the AddReg sections.
617 * Look for section names with .NT, unless
618 * this is a WinXP .INF file.
621 if (is_winxp) {
622 sprintf(sname, "%s.NTx86", assign->vals[0]);
623 dev = find_assign(sname, "AddReg");
624 if (dev == NULL) {
625 sprintf(sname, "%s.NT",
626 assign->vals[0]);
627 dev = find_assign(sname, "AddReg");
629 if (dev == NULL)
630 dev = find_assign(assign->vals[0],
631 "AddReg");
632 } else {
633 sprintf(sname, "%s.NT", assign->vals[0]);
634 dev = find_assign(sname, "AddReg");
635 if (dev == NULL && is_winnt)
636 dev = find_assign(assign->vals[0],
637 "AddReg");
639 /* Section not found. */
640 if (dev == NULL)
641 continue;
642 for (i = 0; i < W_MAX; i++) {
643 if (dev->vals[i] != NULL)
644 dump_addreg(dev->vals[i], devidx);
646 devidx++;
650 if (!found) {
651 sec = find_section(manf->vals[0]);
652 is_winxp = 0;
653 found++;
654 goto retry;
657 fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
659 return;
662 void
663 assign_add (const char *a)
665 struct assign *assign;
666 int i;
668 assign = malloc(sizeof(struct assign));
669 bzero(assign, sizeof(struct assign));
670 assign->section = TAILQ_LAST(&sh, section_head);
671 assign->key = sstrdup(a);
672 for (i = 0; i < idx; i++)
673 assign->vals[(idx - 1) - i] = sstrdup(words[i]);
674 TAILQ_INSERT_TAIL(&ah, assign, link);
676 clear_words();
677 return;
680 void
681 define_add (const char *d __unused)
683 #ifdef notdef
684 fprintf(stderr, "define \"%s\"\n", d);
685 #endif
686 return;
689 static char *
690 sstrdup(const char *str)
692 if (str != NULL && strlen(str))
693 return (strdup(str));
694 return (NULL);
697 static int
698 satoi (const char *nptr)
700 if (nptr != NULL && strlen(nptr))
701 return (atoi(nptr));
702 return (0);
705 void
706 regkey_add (const char *r)
708 struct reg *reg;
710 reg = malloc(sizeof(struct reg));
711 bzero(reg, sizeof(struct reg));
712 reg->section = TAILQ_LAST(&sh, section_head);
713 reg->root = sstrdup(r);
714 reg->subkey = sstrdup(words[3]);
715 reg->key = sstrdup(words[2]);
716 reg->flags = satoi(words[1]);
717 reg->value = sstrdup(words[0]);
718 TAILQ_INSERT_TAIL(&rh, reg, link);
720 free(__DECONST(char *, r));
721 clear_words();
722 return;
725 void
726 push_word (const char *w)
728 if (w && strlen(w))
729 words[idx++] = w;
730 else
731 words[idx++] = NULL;
732 return;
735 void
736 clear_words (void)
738 int i;
740 for (i = 0; i < idx; i++) {
741 if (words[i]) {
742 free(__DECONST(char *, words[i]));
745 idx = 0;
746 bzero(words, sizeof(words));
747 return;