xref: /OK3568_Linux_fs/kernel/tools/usb/usbip/libsrc/names.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *      names.c  --  USB name database manipulation routines
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *	Copyright (C) 2005 Takahiro Hirofuchi
8*4882a593Smuzhiyun  *		- names_deinit() is added.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <sys/types.h>
12*4882a593Smuzhiyun #include <sys/stat.h>
13*4882a593Smuzhiyun #include <fcntl.h>
14*4882a593Smuzhiyun #include <dirent.h>
15*4882a593Smuzhiyun #include <string.h>
16*4882a593Smuzhiyun #include <errno.h>
17*4882a593Smuzhiyun #include <stdlib.h>
18*4882a593Smuzhiyun #include <unistd.h>
19*4882a593Smuzhiyun #include <stdio.h>
20*4882a593Smuzhiyun #include <ctype.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include "names.h"
23*4882a593Smuzhiyun #include "usbip_common.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun struct vendor {
26*4882a593Smuzhiyun 	struct vendor *next;
27*4882a593Smuzhiyun 	u_int16_t vendorid;
28*4882a593Smuzhiyun 	char name[1];
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun struct product {
32*4882a593Smuzhiyun 	struct product *next;
33*4882a593Smuzhiyun 	u_int16_t vendorid, productid;
34*4882a593Smuzhiyun 	char name[1];
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun struct class {
38*4882a593Smuzhiyun 	struct class *next;
39*4882a593Smuzhiyun 	u_int8_t classid;
40*4882a593Smuzhiyun 	char name[1];
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun struct subclass {
44*4882a593Smuzhiyun 	struct subclass *next;
45*4882a593Smuzhiyun 	u_int8_t classid, subclassid;
46*4882a593Smuzhiyun 	char name[1];
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun struct protocol {
50*4882a593Smuzhiyun 	struct protocol *next;
51*4882a593Smuzhiyun 	u_int8_t classid, subclassid, protocolid;
52*4882a593Smuzhiyun 	char name[1];
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun struct genericstrtable {
56*4882a593Smuzhiyun 	struct genericstrtable *next;
57*4882a593Smuzhiyun 	unsigned int num;
58*4882a593Smuzhiyun 	char name[1];
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define HASH1  0x10
63*4882a593Smuzhiyun #define HASH2  0x02
64*4882a593Smuzhiyun #define HASHSZ 16
65*4882a593Smuzhiyun 
hashnum(unsigned int num)66*4882a593Smuzhiyun static unsigned int hashnum(unsigned int num)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
71*4882a593Smuzhiyun 		if (num & mask1)
72*4882a593Smuzhiyun 			num ^= mask2;
73*4882a593Smuzhiyun 	return num & (HASHSZ-1);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun static struct vendor *vendors[HASHSZ] = { NULL, };
78*4882a593Smuzhiyun static struct product *products[HASHSZ] = { NULL, };
79*4882a593Smuzhiyun static struct class *classes[HASHSZ] = { NULL, };
80*4882a593Smuzhiyun static struct subclass *subclasses[HASHSZ] = { NULL, };
81*4882a593Smuzhiyun static struct protocol *protocols[HASHSZ] = { NULL, };
82*4882a593Smuzhiyun 
names_vendor(u_int16_t vendorid)83*4882a593Smuzhiyun const char *names_vendor(u_int16_t vendorid)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	struct vendor *v;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	v = vendors[hashnum(vendorid)];
88*4882a593Smuzhiyun 	for (; v; v = v->next)
89*4882a593Smuzhiyun 		if (v->vendorid == vendorid)
90*4882a593Smuzhiyun 			return v->name;
91*4882a593Smuzhiyun 	return NULL;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
names_product(u_int16_t vendorid,u_int16_t productid)94*4882a593Smuzhiyun const char *names_product(u_int16_t vendorid, u_int16_t productid)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct product *p;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	p = products[hashnum((vendorid << 16) | productid)];
99*4882a593Smuzhiyun 	for (; p; p = p->next)
100*4882a593Smuzhiyun 		if (p->vendorid == vendorid && p->productid == productid)
101*4882a593Smuzhiyun 			return p->name;
102*4882a593Smuzhiyun 	return NULL;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
names_class(u_int8_t classid)105*4882a593Smuzhiyun const char *names_class(u_int8_t classid)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	struct class *c;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	c = classes[hashnum(classid)];
110*4882a593Smuzhiyun 	for (; c; c = c->next)
111*4882a593Smuzhiyun 		if (c->classid == classid)
112*4882a593Smuzhiyun 			return c->name;
113*4882a593Smuzhiyun 	return NULL;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
names_subclass(u_int8_t classid,u_int8_t subclassid)116*4882a593Smuzhiyun const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	struct subclass *s;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	s = subclasses[hashnum((classid << 8) | subclassid)];
121*4882a593Smuzhiyun 	for (; s; s = s->next)
122*4882a593Smuzhiyun 		if (s->classid == classid && s->subclassid == subclassid)
123*4882a593Smuzhiyun 			return s->name;
124*4882a593Smuzhiyun 	return NULL;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
names_protocol(u_int8_t classid,u_int8_t subclassid,u_int8_t protocolid)127*4882a593Smuzhiyun const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
128*4882a593Smuzhiyun 			   u_int8_t protocolid)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	struct protocol *p;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	p = protocols[hashnum((classid << 16) | (subclassid << 8)
133*4882a593Smuzhiyun 			      | protocolid)];
134*4882a593Smuzhiyun 	for (; p; p = p->next)
135*4882a593Smuzhiyun 		if (p->classid == classid && p->subclassid == subclassid &&
136*4882a593Smuzhiyun 		    p->protocolid == protocolid)
137*4882a593Smuzhiyun 			return p->name;
138*4882a593Smuzhiyun 	return NULL;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun /* add a cleanup function by takahiro */
142*4882a593Smuzhiyun struct pool {
143*4882a593Smuzhiyun 	struct pool *next;
144*4882a593Smuzhiyun 	void *mem;
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun static struct pool *pool_head;
148*4882a593Smuzhiyun 
my_malloc(size_t size)149*4882a593Smuzhiyun static void *my_malloc(size_t size)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	struct pool *p;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	p = calloc(1, sizeof(struct pool));
154*4882a593Smuzhiyun 	if (!p)
155*4882a593Smuzhiyun 		return NULL;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	p->mem = calloc(1, size);
158*4882a593Smuzhiyun 	if (!p->mem) {
159*4882a593Smuzhiyun 		free(p);
160*4882a593Smuzhiyun 		return NULL;
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	p->next = pool_head;
164*4882a593Smuzhiyun 	pool_head = p;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	return p->mem;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
names_free(void)169*4882a593Smuzhiyun void names_free(void)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct pool *pool;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	if (!pool_head)
174*4882a593Smuzhiyun 		return;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	for (pool = pool_head; pool != NULL; ) {
177*4882a593Smuzhiyun 		struct pool *tmp;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 		if (pool->mem)
180*4882a593Smuzhiyun 			free(pool->mem);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 		tmp = pool;
183*4882a593Smuzhiyun 		pool = pool->next;
184*4882a593Smuzhiyun 		free(tmp);
185*4882a593Smuzhiyun 	}
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
new_vendor(const char * name,u_int16_t vendorid)188*4882a593Smuzhiyun static int new_vendor(const char *name, u_int16_t vendorid)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	struct vendor *v;
191*4882a593Smuzhiyun 	unsigned int h = hashnum(vendorid);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	v = vendors[h];
194*4882a593Smuzhiyun 	for (; v; v = v->next)
195*4882a593Smuzhiyun 		if (v->vendorid == vendorid)
196*4882a593Smuzhiyun 			return -1;
197*4882a593Smuzhiyun 	v = my_malloc(sizeof(struct vendor) + strlen(name));
198*4882a593Smuzhiyun 	if (!v)
199*4882a593Smuzhiyun 		return -1;
200*4882a593Smuzhiyun 	strcpy(v->name, name);
201*4882a593Smuzhiyun 	v->vendorid = vendorid;
202*4882a593Smuzhiyun 	v->next = vendors[h];
203*4882a593Smuzhiyun 	vendors[h] = v;
204*4882a593Smuzhiyun 	return 0;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
new_product(const char * name,u_int16_t vendorid,u_int16_t productid)207*4882a593Smuzhiyun static int new_product(const char *name, u_int16_t vendorid,
208*4882a593Smuzhiyun 		       u_int16_t productid)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	struct product *p;
211*4882a593Smuzhiyun 	unsigned int h = hashnum((vendorid << 16) | productid);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	p = products[h];
214*4882a593Smuzhiyun 	for (; p; p = p->next)
215*4882a593Smuzhiyun 		if (p->vendorid == vendorid && p->productid == productid)
216*4882a593Smuzhiyun 			return -1;
217*4882a593Smuzhiyun 	p = my_malloc(sizeof(struct product) + strlen(name));
218*4882a593Smuzhiyun 	if (!p)
219*4882a593Smuzhiyun 		return -1;
220*4882a593Smuzhiyun 	strcpy(p->name, name);
221*4882a593Smuzhiyun 	p->vendorid = vendorid;
222*4882a593Smuzhiyun 	p->productid = productid;
223*4882a593Smuzhiyun 	p->next = products[h];
224*4882a593Smuzhiyun 	products[h] = p;
225*4882a593Smuzhiyun 	return 0;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
new_class(const char * name,u_int8_t classid)228*4882a593Smuzhiyun static int new_class(const char *name, u_int8_t classid)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	struct class *c;
231*4882a593Smuzhiyun 	unsigned int h = hashnum(classid);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	c = classes[h];
234*4882a593Smuzhiyun 	for (; c; c = c->next)
235*4882a593Smuzhiyun 		if (c->classid == classid)
236*4882a593Smuzhiyun 			return -1;
237*4882a593Smuzhiyun 	c = my_malloc(sizeof(struct class) + strlen(name));
238*4882a593Smuzhiyun 	if (!c)
239*4882a593Smuzhiyun 		return -1;
240*4882a593Smuzhiyun 	strcpy(c->name, name);
241*4882a593Smuzhiyun 	c->classid = classid;
242*4882a593Smuzhiyun 	c->next = classes[h];
243*4882a593Smuzhiyun 	classes[h] = c;
244*4882a593Smuzhiyun 	return 0;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
new_subclass(const char * name,u_int8_t classid,u_int8_t subclassid)247*4882a593Smuzhiyun static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun 	struct subclass *s;
250*4882a593Smuzhiyun 	unsigned int h = hashnum((classid << 8) | subclassid);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	s = subclasses[h];
253*4882a593Smuzhiyun 	for (; s; s = s->next)
254*4882a593Smuzhiyun 		if (s->classid == classid && s->subclassid == subclassid)
255*4882a593Smuzhiyun 			return -1;
256*4882a593Smuzhiyun 	s = my_malloc(sizeof(struct subclass) + strlen(name));
257*4882a593Smuzhiyun 	if (!s)
258*4882a593Smuzhiyun 		return -1;
259*4882a593Smuzhiyun 	strcpy(s->name, name);
260*4882a593Smuzhiyun 	s->classid = classid;
261*4882a593Smuzhiyun 	s->subclassid = subclassid;
262*4882a593Smuzhiyun 	s->next = subclasses[h];
263*4882a593Smuzhiyun 	subclasses[h] = s;
264*4882a593Smuzhiyun 	return 0;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
new_protocol(const char * name,u_int8_t classid,u_int8_t subclassid,u_int8_t protocolid)267*4882a593Smuzhiyun static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
268*4882a593Smuzhiyun 			u_int8_t protocolid)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	struct protocol *p;
271*4882a593Smuzhiyun 	unsigned int h = hashnum((classid << 16) | (subclassid << 8)
272*4882a593Smuzhiyun 				 | protocolid);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	p = protocols[h];
275*4882a593Smuzhiyun 	for (; p; p = p->next)
276*4882a593Smuzhiyun 		if (p->classid == classid && p->subclassid == subclassid
277*4882a593Smuzhiyun 		    && p->protocolid == protocolid)
278*4882a593Smuzhiyun 			return -1;
279*4882a593Smuzhiyun 	p = my_malloc(sizeof(struct protocol) + strlen(name));
280*4882a593Smuzhiyun 	if (!p)
281*4882a593Smuzhiyun 		return -1;
282*4882a593Smuzhiyun 	strcpy(p->name, name);
283*4882a593Smuzhiyun 	p->classid = classid;
284*4882a593Smuzhiyun 	p->subclassid = subclassid;
285*4882a593Smuzhiyun 	p->protocolid = protocolid;
286*4882a593Smuzhiyun 	p->next = protocols[h];
287*4882a593Smuzhiyun 	protocols[h] = p;
288*4882a593Smuzhiyun 	return 0;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
parse(FILE * f)291*4882a593Smuzhiyun static void parse(FILE *f)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	char buf[512], *cp;
294*4882a593Smuzhiyun 	unsigned int linectr = 0;
295*4882a593Smuzhiyun 	int lastvendor = -1;
296*4882a593Smuzhiyun 	int lastclass = -1;
297*4882a593Smuzhiyun 	int lastsubclass = -1;
298*4882a593Smuzhiyun 	int lasthut = -1;
299*4882a593Smuzhiyun 	int lastlang = -1;
300*4882a593Smuzhiyun 	unsigned int u;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	while (fgets(buf, sizeof(buf), f)) {
303*4882a593Smuzhiyun 		linectr++;
304*4882a593Smuzhiyun 		/* remove line ends */
305*4882a593Smuzhiyun 		cp = strchr(buf, '\r');
306*4882a593Smuzhiyun 		if (cp)
307*4882a593Smuzhiyun 			*cp = 0;
308*4882a593Smuzhiyun 		cp = strchr(buf, '\n');
309*4882a593Smuzhiyun 		if (cp)
310*4882a593Smuzhiyun 			*cp = 0;
311*4882a593Smuzhiyun 		if (buf[0] == '#' || !buf[0])
312*4882a593Smuzhiyun 			continue;
313*4882a593Smuzhiyun 		cp = buf;
314*4882a593Smuzhiyun 		if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
315*4882a593Smuzhiyun 		    buf[3] == 'S' && buf[4] == 'D' &&
316*4882a593Smuzhiyun 		    buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
317*4882a593Smuzhiyun 		    buf[7] == ' ') {
318*4882a593Smuzhiyun 			continue;
319*4882a593Smuzhiyun 		}
320*4882a593Smuzhiyun 		if (buf[0] == 'P' && buf[1] == 'H' &&
321*4882a593Smuzhiyun 		    buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
322*4882a593Smuzhiyun 			continue;
323*4882a593Smuzhiyun 		}
324*4882a593Smuzhiyun 		if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
325*4882a593Smuzhiyun 		    buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
326*4882a593Smuzhiyun 			continue;
327*4882a593Smuzhiyun 		}
328*4882a593Smuzhiyun 		if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
329*4882a593Smuzhiyun 			lasthut = lastclass = lastvendor = lastsubclass = -1;
330*4882a593Smuzhiyun 			/*
331*4882a593Smuzhiyun 			 * set 1 as pseudo-id to indicate that the parser is
332*4882a593Smuzhiyun 			 * in a `L' section.
333*4882a593Smuzhiyun 			 */
334*4882a593Smuzhiyun 			lastlang = 1;
335*4882a593Smuzhiyun 			continue;
336*4882a593Smuzhiyun 		}
337*4882a593Smuzhiyun 		if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
338*4882a593Smuzhiyun 			/* class spec */
339*4882a593Smuzhiyun 			cp = buf+2;
340*4882a593Smuzhiyun 			while (isspace(*cp))
341*4882a593Smuzhiyun 				cp++;
342*4882a593Smuzhiyun 			if (!isxdigit(*cp)) {
343*4882a593Smuzhiyun 				err("Invalid class spec at line %u", linectr);
344*4882a593Smuzhiyun 				continue;
345*4882a593Smuzhiyun 			}
346*4882a593Smuzhiyun 			u = strtoul(cp, &cp, 16);
347*4882a593Smuzhiyun 			while (isspace(*cp))
348*4882a593Smuzhiyun 				cp++;
349*4882a593Smuzhiyun 			if (!*cp) {
350*4882a593Smuzhiyun 				err("Invalid class spec at line %u", linectr);
351*4882a593Smuzhiyun 				continue;
352*4882a593Smuzhiyun 			}
353*4882a593Smuzhiyun 			if (new_class(cp, u))
354*4882a593Smuzhiyun 				err("Duplicate class spec at line %u class %04x %s",
355*4882a593Smuzhiyun 				    linectr, u, cp);
356*4882a593Smuzhiyun 			dbg("line %5u class %02x %s", linectr, u, cp);
357*4882a593Smuzhiyun 			lasthut = lastlang = lastvendor = lastsubclass = -1;
358*4882a593Smuzhiyun 			lastclass = u;
359*4882a593Smuzhiyun 			continue;
360*4882a593Smuzhiyun 		}
361*4882a593Smuzhiyun 		if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
362*4882a593Smuzhiyun 			/* audio terminal type spec */
363*4882a593Smuzhiyun 			continue;
364*4882a593Smuzhiyun 		}
365*4882a593Smuzhiyun 		if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
366*4882a593Smuzhiyun 		    && isspace(buf[3])) {
367*4882a593Smuzhiyun 			/* HID Descriptor bCountryCode */
368*4882a593Smuzhiyun 			continue;
369*4882a593Smuzhiyun 		}
370*4882a593Smuzhiyun 		if (isxdigit(*cp)) {
371*4882a593Smuzhiyun 			/* vendor */
372*4882a593Smuzhiyun 			u = strtoul(cp, &cp, 16);
373*4882a593Smuzhiyun 			while (isspace(*cp))
374*4882a593Smuzhiyun 				cp++;
375*4882a593Smuzhiyun 			if (!*cp) {
376*4882a593Smuzhiyun 				err("Invalid vendor spec at line %u", linectr);
377*4882a593Smuzhiyun 				continue;
378*4882a593Smuzhiyun 			}
379*4882a593Smuzhiyun 			if (new_vendor(cp, u))
380*4882a593Smuzhiyun 				err("Duplicate vendor spec at line %u vendor %04x %s",
381*4882a593Smuzhiyun 				    linectr, u, cp);
382*4882a593Smuzhiyun 			dbg("line %5u vendor %04x %s", linectr, u, cp);
383*4882a593Smuzhiyun 			lastvendor = u;
384*4882a593Smuzhiyun 			lasthut = lastlang = lastclass = lastsubclass = -1;
385*4882a593Smuzhiyun 			continue;
386*4882a593Smuzhiyun 		}
387*4882a593Smuzhiyun 		if (buf[0] == '\t' && isxdigit(buf[1])) {
388*4882a593Smuzhiyun 			/* product or subclass spec */
389*4882a593Smuzhiyun 			u = strtoul(buf+1, &cp, 16);
390*4882a593Smuzhiyun 			while (isspace(*cp))
391*4882a593Smuzhiyun 				cp++;
392*4882a593Smuzhiyun 			if (!*cp) {
393*4882a593Smuzhiyun 				err("Invalid product/subclass spec at line %u",
394*4882a593Smuzhiyun 				    linectr);
395*4882a593Smuzhiyun 				continue;
396*4882a593Smuzhiyun 			}
397*4882a593Smuzhiyun 			if (lastvendor != -1) {
398*4882a593Smuzhiyun 				if (new_product(cp, lastvendor, u))
399*4882a593Smuzhiyun 					err("Duplicate product spec at line %u product %04x:%04x %s",
400*4882a593Smuzhiyun 					    linectr, lastvendor, u, cp);
401*4882a593Smuzhiyun 				dbg("line %5u product %04x:%04x %s", linectr,
402*4882a593Smuzhiyun 				    lastvendor, u, cp);
403*4882a593Smuzhiyun 				continue;
404*4882a593Smuzhiyun 			}
405*4882a593Smuzhiyun 			if (lastclass != -1) {
406*4882a593Smuzhiyun 				if (new_subclass(cp, lastclass, u))
407*4882a593Smuzhiyun 					err("Duplicate subclass spec at line %u class %02x:%02x %s",
408*4882a593Smuzhiyun 					    linectr, lastclass, u, cp);
409*4882a593Smuzhiyun 				dbg("line %5u subclass %02x:%02x %s", linectr,
410*4882a593Smuzhiyun 				    lastclass, u, cp);
411*4882a593Smuzhiyun 				lastsubclass = u;
412*4882a593Smuzhiyun 				continue;
413*4882a593Smuzhiyun 			}
414*4882a593Smuzhiyun 			if (lasthut != -1) {
415*4882a593Smuzhiyun 				/* do not store hut */
416*4882a593Smuzhiyun 				continue;
417*4882a593Smuzhiyun 			}
418*4882a593Smuzhiyun 			if (lastlang != -1) {
419*4882a593Smuzhiyun 				/* do not store langid */
420*4882a593Smuzhiyun 				continue;
421*4882a593Smuzhiyun 			}
422*4882a593Smuzhiyun 			err("Product/Subclass spec without prior Vendor/Class spec at line %u",
423*4882a593Smuzhiyun 			    linectr);
424*4882a593Smuzhiyun 			continue;
425*4882a593Smuzhiyun 		}
426*4882a593Smuzhiyun 		if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
427*4882a593Smuzhiyun 			/* protocol spec */
428*4882a593Smuzhiyun 			u = strtoul(buf+2, &cp, 16);
429*4882a593Smuzhiyun 			while (isspace(*cp))
430*4882a593Smuzhiyun 				cp++;
431*4882a593Smuzhiyun 			if (!*cp) {
432*4882a593Smuzhiyun 				err("Invalid protocol spec at line %u",
433*4882a593Smuzhiyun 				    linectr);
434*4882a593Smuzhiyun 				continue;
435*4882a593Smuzhiyun 			}
436*4882a593Smuzhiyun 			if (lastclass != -1 && lastsubclass != -1) {
437*4882a593Smuzhiyun 				if (new_protocol(cp, lastclass, lastsubclass,
438*4882a593Smuzhiyun 						 u))
439*4882a593Smuzhiyun 					err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
440*4882a593Smuzhiyun 					    linectr, lastclass, lastsubclass,
441*4882a593Smuzhiyun 					    u, cp);
442*4882a593Smuzhiyun 				dbg("line %5u protocol %02x:%02x:%02x %s",
443*4882a593Smuzhiyun 				    linectr, lastclass, lastsubclass, u, cp);
444*4882a593Smuzhiyun 				continue;
445*4882a593Smuzhiyun 			}
446*4882a593Smuzhiyun 			err("Protocol spec without prior Class and Subclass spec at line %u",
447*4882a593Smuzhiyun 			    linectr);
448*4882a593Smuzhiyun 			continue;
449*4882a593Smuzhiyun 		}
450*4882a593Smuzhiyun 		if (buf[0] == 'H' && buf[1] == 'I' &&
451*4882a593Smuzhiyun 		    buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
452*4882a593Smuzhiyun 			continue;
453*4882a593Smuzhiyun 		}
454*4882a593Smuzhiyun 		if (buf[0] == 'H' && buf[1] == 'U' &&
455*4882a593Smuzhiyun 		    buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
456*4882a593Smuzhiyun 			lastlang = lastclass = lastvendor = lastsubclass = -1;
457*4882a593Smuzhiyun 			/*
458*4882a593Smuzhiyun 			 * set 1 as pseudo-id to indicate that the parser is
459*4882a593Smuzhiyun 			 * in a `HUT' section.
460*4882a593Smuzhiyun 			 */
461*4882a593Smuzhiyun 			lasthut = 1;
462*4882a593Smuzhiyun 			continue;
463*4882a593Smuzhiyun 		}
464*4882a593Smuzhiyun 		if (buf[0] == 'R' && buf[1] == ' ')
465*4882a593Smuzhiyun 			continue;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 		if (buf[0] == 'V' && buf[1] == 'T')
468*4882a593Smuzhiyun 			continue;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 		err("Unknown line at line %u", linectr);
471*4882a593Smuzhiyun 	}
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 
names_init(char * n)475*4882a593Smuzhiyun int names_init(char *n)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun 	FILE *f;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	f = fopen(n, "r");
480*4882a593Smuzhiyun 	if (!f)
481*4882a593Smuzhiyun 		return errno;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	parse(f);
484*4882a593Smuzhiyun 	fclose(f);
485*4882a593Smuzhiyun 	return 0;
486*4882a593Smuzhiyun }
487