]> mj.ucw.cz Git - pciutils.git/blob - names.c
Fixed problems with glibc 1.99 on PPC. Thanks, Geert.
[pciutils.git] / names.c
1 /*
2  *      $Id: names.c,v 1.6 1998/07/17 08:57:16 mj Exp $
3  *
4  *      Linux PCI Utilities -- Device ID to Name Translation
5  *
6  *      Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
7  *
8  *      Can be freely distributed and used under the terms of the GNU GPL.
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/stat.h>
17
18 #include "pciutils.h"
19
20 int show_numeric_ids;
21
22 char *pci_ids = ETC_PCI_IDS;
23
24 static byte *name_list;
25 static int name_list_loaded;
26
27 struct nl_entry {
28   struct nl_entry *next;
29   word id1, id2;
30   int cat;
31   byte *name;
32 };
33
34 #define NL_VENDOR 0
35 #define NL_DEVICE 1
36 #define NL_CLASS 2
37 #define NL_SUBCLASS 3
38 #define NL_SUBSYSTEM_VENDOR 4
39 #define NL_SUBSYSTEM_DEVICE 5
40
41 #define HASH_SIZE 1024
42
43 static struct nl_entry *nl_hash[HASH_SIZE];
44
45 static inline unsigned int nl_calc_hash(int cat, int id1, int id2)
46 {
47   unsigned int h;
48
49   h = id1 ^ id2 ^ (cat << 5);
50   h += (h >> 6);
51   return h & (HASH_SIZE-1);
52 }
53
54 static struct nl_entry *nl_lookup(int cat, int id1, int id2)
55 {
56   unsigned int h = nl_calc_hash(cat, id1, id2);
57   struct nl_entry *n = nl_hash[h];
58
59   while (n && (n->id1 != id1 || n->id2 != id2 || n->cat != cat))
60     n = n->next;
61   return n;
62 }
63
64 static int nl_add(int cat, int id1, int id2, byte *text)
65 {
66   unsigned int h = nl_calc_hash(cat, id1, id2);
67   struct nl_entry *n = nl_hash[h];
68
69   while (n && (n->id1 != id1 || n->id2 != id2 || n->cat != cat))
70     n = n->next;
71   if (n)
72     return 1;
73   n = xmalloc(sizeof(struct nl_entry));
74   n->id1 = id1;
75   n->id2 = id2;
76   n->cat = cat;
77   n->name = text;
78   n->next = nl_hash[h];
79   nl_hash[h] = n;
80   return 0;
81 }
82
83 static void
84 err_name_list(char *msg)
85 {
86   fprintf(stderr, "%s: %s: %m\n", pci_ids, msg);
87   exit(1);
88 }
89
90 static void
91 parse_name_list(void)
92 {
93   byte *p = name_list;
94   byte *q, *r;
95   int lino = 0;
96   unsigned int id1=0, id2=0;
97   int cat, last_cat = -1;
98
99   while (*p)
100     {
101       lino++;
102       q = p;
103       while (*p && *p != '\n')
104         {
105           if (*p == '#')
106             {
107               *p++ = 0;
108               while (*p && *p != '\n')
109                 p++;
110               break;
111             }
112           if (*p == '\t')
113             *p = ' ';
114           p++;
115         }
116       if (*p == '\n')
117         *p++ = 0;
118       if (!*q)
119         continue;
120       r = p;
121       while (r > q && r[-1] == ' ')
122         *--r = 0;
123       r = q;
124       while (*q == ' ')
125         q++;
126       if (r == q)
127         {
128           if (q[0] == 'C' && q[1] == ' ')
129             {
130               if (strlen(q+2) < 3 ||
131                   q[4] != ' ' ||
132                   sscanf(q+2, "%x", &id1) != 1)
133                 goto parserr;
134               cat = last_cat = NL_CLASS;
135             }
136           else if (q[0] == 'S' && q[1] == ' ')
137             {
138               if (strlen(q+2) < 5 ||
139                   q[6] != ' ' ||
140                   sscanf(q+2, "%x", &id1) != 1)
141                 goto parserr;
142               cat = last_cat = NL_SUBSYSTEM_VENDOR;
143               q += 2;
144             }
145           else
146             {
147               if (strlen(q) < 5 ||
148                   q[4] != ' ' ||
149                   sscanf(q, "%x", &id1) != 1)
150                 goto parserr;
151               cat = last_cat = NL_VENDOR;
152             }
153           id2 = 0;
154         }
155       else
156         {
157           if (sscanf(q, "%x", &id2) != 1)
158             goto parserr;
159           if (last_cat < 0)
160             goto parserr;
161           if (last_cat == NL_CLASS)
162             cat = NL_SUBCLASS;
163           else
164             cat = last_cat+1;
165         }
166       q += 4;
167       while (*q == ' ')
168         q++;
169       if (!*q)
170         goto parserr;
171       if (nl_add(cat, id1, id2, q))
172         {
173           fprintf(stderr, "%s, line %d: duplicate entry\n", pci_ids, lino);
174           exit(1);
175         }
176     }
177   return;
178
179 parserr:
180   fprintf(stderr, "%s, line %d: parse error\n", pci_ids, lino);
181   exit(1);
182 }
183
184 static void
185 load_name_list(void)
186 {
187   int fd;
188   struct stat st;
189
190   fd = open(pci_ids, O_RDONLY);
191   if (fd < 0)
192     {
193       show_numeric_ids = 1;
194       return;
195     }
196   if (fstat(fd, &st) < 0)
197     err_name_list("stat");
198   name_list = xmalloc(st.st_size + 1);
199   if (read(fd, name_list, st.st_size) != st.st_size)
200     err_name_list("read");
201   name_list[st.st_size] = 0;
202   parse_name_list();
203   close(fd);
204   name_list_loaded = 1;
205 }
206
207 char *
208 do_lookup_vendor(int cat, word i)
209 {
210   static char vendbuf[6];
211
212   if (!show_numeric_ids && !name_list_loaded)
213     load_name_list();
214   if (!show_numeric_ids)
215     {
216       struct nl_entry *e;
217
218       e = nl_lookup(cat, i, 0);
219       if (e)
220         return e->name;
221     }
222   sprintf(vendbuf, "%04x", i);
223   return vendbuf;
224 }
225
226 char *
227 do_lookup_device(int cat, word v, word i)
228 {
229   static char devbuf[6];
230
231   if (!show_numeric_ids && !name_list_loaded)
232     load_name_list();
233   if (!show_numeric_ids)
234     {
235       struct nl_entry *e;
236
237       e = nl_lookup(cat, v, i);
238       if (e)
239         return e->name;
240     }
241   sprintf(devbuf, "%04x", i);
242   return devbuf;
243 }
244
245 char *
246 do_lookup_device_full(int cat, word v, word i)
247 {
248   static char fullbuf[256];
249
250   if (!show_numeric_ids && !name_list_loaded)
251     load_name_list();
252   if (!show_numeric_ids)
253     {
254       struct nl_entry *e, *e2;
255
256       e = nl_lookup(cat, v, 0);
257       e2 = nl_lookup(cat+1, v, i);
258       if (!e)
259         sprintf(fullbuf, "Unknown device %04x:%04x", v, i);
260       else if (!e2)
261         sprintf(fullbuf, "%s: Unknown device %04x", e->name, i);
262       else
263         sprintf(fullbuf, "%s %s", e->name, e2->name);
264     }
265   else
266     sprintf(fullbuf, "%04x:%04x", v, i);
267   return fullbuf;
268 }
269
270 char *
271 lookup_vendor(word i)
272 {
273   return do_lookup_vendor(NL_VENDOR, i);
274 }
275
276 char *
277 lookup_subsys_vendor(word i)
278 {
279   return do_lookup_vendor(NL_SUBSYSTEM_VENDOR, i);
280 }
281
282 char *
283 lookup_device(word i, word v)
284 {
285   return do_lookup_device(NL_DEVICE, v, i);
286 }
287
288 char *
289 lookup_subsys_device(word v, word i)
290 {
291   return do_lookup_device(NL_SUBSYSTEM_DEVICE, v, i);
292 }
293
294 char *
295 lookup_device_full(word v, word i)
296 {
297   return do_lookup_device_full(NL_VENDOR, v, i);
298 }
299
300 char *
301 lookup_subsys_device_full(word v, word i)
302 {
303   return do_lookup_device_full(NL_SUBSYSTEM_VENDOR, v, i);
304 }
305
306 char *
307 lookup_class(word c)
308 {
309   static char classbuf[80];
310
311   if (!show_numeric_ids && !name_list_loaded)
312     load_name_list();
313   if (!show_numeric_ids)
314     {
315       struct nl_entry *e;
316
317       e = nl_lookup(NL_SUBCLASS, c >> 8, c & 0xff);
318       if (e)
319         return e->name;
320       e = nl_lookup(NL_CLASS, c, 0);
321       if (e)
322         sprintf(classbuf, "%s [%04x]", e->name, c);
323       else
324         sprintf(classbuf, "Unknown class [%04x]", c);
325     }
326   else
327     sprintf(classbuf, "Class %04x", c);
328   return classbuf;
329 }