1/*
2 *	Generate devlist.h and classlist.h from the PCI ID file.
3 *
4 *	(c) 1999--2002 Martin Mares <mj@ucw.cz>
5 */
6
7#include <stdio.h>
8#include <string.h>
9
10#define MAX_NAME_SIZE 79
11
12static void
13pq(FILE *f, const char *c)
14{
15	while (*c) {
16		if (*c == '"')
17			fprintf(f, "\\\"");
18		else {
19			fputc(*c, f);
20			if (*c == '?' && c[1] == '?') {
21				/* Avoid trigraphs */
22				fprintf(f, "\" \"");
23			}
24		}
25		c++;
26	}
27}
28
29int
30main(void)
31{
32	char line[1024], *c, *bra, vend[8];
33	int vendors = 0;
34	int mode = 0;
35	int lino = 0;
36	int vendor_len = 0;
37	FILE *devf, *clsf;
38
39	devf = fopen("devlist.h", "w");
40	clsf = fopen("classlist.h", "w");
41	if (!devf || !clsf) {
42		fprintf(stderr, "Cannot create output file!\n");
43		return 1;
44	}
45
46	while (fgets(line, sizeof(line)-1, stdin)) {
47		lino++;
48		if ((c = strchr(line, '\n')))
49			*c = 0;
50		if (!line[0] || line[0] == '#')
51			continue;
52		if (line[1] == ' ') {
53			if (line[0] == 'C' && strlen(line) > 4 && line[4] == ' ') {
54				vend[0] = line[2];
55				vend[1] = line[3];
56				vend[2] = 0;
57				mode = 2;
58			} else goto err;
59		}
60		else if (line[0] == '\t') {
61			if (line[1] == '\t')
62				continue;
63			switch (mode) {
64			case 1:
65				if (strlen(line) > 5 && line[5] == ' ') {
66					c = line + 5;
67					while (*c == ' ')
68						*c++ = 0;
69					if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) {
70						/* Too long, try cutting off long description */
71						bra = strchr(c, '[');
72						if (bra && bra > c && bra[-1] == ' ')
73							bra[-1] = 0;
74						if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) {
75							fprintf(stderr, "Line %d: Device name too long\n", lino);
76							fprintf(stderr, "%s\n", c);
77							return 1;
78						}
79					}
80					fprintf(devf, "\tDEVICE(%s,%s,\"", vend, line+1);
81					pq(devf, c);
82					fputs("\")\n", devf);
83				} else goto err;
84				break;
85			case 2:
86				if (strlen(line) > 3 && line[3] == ' ') {
87					c = line + 3;
88					while (*c == ' ')
89						*c++ = 0;
90					fprintf(clsf, "CLASS(%s%s, \"%s\")\n", vend, line+1, c);
91				} else goto err;
92				break;
93			default:
94				goto err;
95			}
96		} else if (strlen(line) > 4 && line[4] == ' ') {
97			c = line + 4;
98			while (*c == ' ')
99				*c++ = 0;
100			if (vendors)
101				fputs("ENDVENDOR()\n\n", devf);
102			vendors++;
103			strcpy(vend, line);
104			vendor_len = strlen(c);
105			if (vendor_len + 24 > MAX_NAME_SIZE) {
106				fprintf(stderr, "Line %d: Vendor name too long\n", lino);
107				return 1;
108			}
109			fprintf(devf, "VENDOR(%s,\"", vend);
110			pq(devf, c);
111			fputs("\")\n", devf);
112			mode = 1;
113		} else {
114		err:
115			fprintf(stderr, "Line %d: Syntax error in mode %d: %s\n", lino, mode, line);
116			return 1;
117		}
118	}
119	fputs("ENDVENDOR()\n\
120\n\
121#undef VENDOR\n\
122#undef DEVICE\n\
123#undef ENDVENDOR\n", devf);
124	fputs("\n#undef CLASS\n", clsf);
125
126	fclose(devf);
127	fclose(clsf);
128
129	return 0;
130}
131