Annotation of embedaddon/pciutils/lib/names-parse.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     The PCI Library -- Parsing of the ID list
                      3:  *
                      4:  *     Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #include <stdio.h>
                     10: #include <stdlib.h>
                     11: #include <string.h>
                     12: #include <errno.h>
                     13: 
                     14: #include "internal.h"
                     15: #include "names.h"
                     16: 
                     17: #ifdef PCI_COMPRESSED_IDS
                     18: #include <zlib.h>
                     19: typedef gzFile pci_file;
                     20: #define pci_gets(f, l, s)      gzgets(f, l, s)
                     21: #define pci_eof(f)             gzeof(f)
                     22: 
                     23: static pci_file pci_open(struct pci_access *a)
                     24: {
                     25:   pci_file result;
                     26:   size_t len;
                     27:   char *new_name;
                     28: 
                     29:   result = gzopen(a->id_file_name, "rb");
                     30:   if (result)
                     31:     return result;
                     32:   len = strlen(a->id_file_name);
                     33:   if (len >= 3 && memcmp(a->id_file_name + len - 3, ".gz", 3) != 0)
                     34:     return result;
                     35:   new_name = malloc(len - 2);
                     36:   memcpy(new_name, a->id_file_name, len - 3);
                     37:   new_name[len - 3] = 0;
                     38:   pci_set_name_list_path(a, new_name, 1);
                     39:   return gzopen(a->id_file_name, "rb");
                     40: }
                     41: 
                     42: #define pci_close(f)           gzclose(f)
                     43: #define PCI_ERROR(f, err)                                              \
                     44:        if (!err) {                                                     \
                     45:                int errnum;                                             \
                     46:                gzerror(f, &errnum);                                    \
                     47:                if (errnum >= 0) err = NULL;                            \
                     48:                else if (errnum == Z_ERRNO) err = "I/O error";          \
                     49:                else err = zError(errnum);                              \
                     50:        }
                     51: #else
                     52: typedef FILE * pci_file;
                     53: #define pci_gets(f, l, s)      fgets(l, s, f)
                     54: #define pci_eof(f)             feof(f)
                     55: #define pci_open(a)            fopen(a->id_file_name, "r")
                     56: #define pci_close(f)           fclose(f)
                     57: #define PCI_ERROR(f, err)      if (!err && ferror(f))  err = "I/O error";
                     58: #endif
                     59: 
                     60: static int id_hex(char *p, int cnt)
                     61: {
                     62:   int x = 0;
                     63:   while (cnt--)
                     64:     {
                     65:       x <<= 4;
                     66:       if (*p >= '0' && *p <= '9')
                     67:        x += (*p - '0');
                     68:       else if (*p >= 'a' && *p <= 'f')
                     69:        x += (*p - 'a' + 10);
                     70:       else if (*p >= 'A' && *p <= 'F')
                     71:        x += (*p - 'A' + 10);
                     72:       else
                     73:        return -1;
                     74:       p++;
                     75:     }
                     76:   return x;
                     77: }
                     78: 
                     79: static inline int id_white_p(int c)
                     80: {
                     81:   return (c == ' ') || (c == '\t');
                     82: }
                     83: 
                     84: 
                     85: static const char *id_parse_list(struct pci_access *a, pci_file f, int *lino)
                     86: {
                     87:   char line[MAX_LINE];
                     88:   char *p;
                     89:   int id1=0, id2=0, id3=0, id4=0;
                     90:   int cat = -1;
                     91:   int nest;
                     92:   static const char parse_error[] = "Parse error";
                     93: 
                     94:   *lino = 0;
                     95:   while (pci_gets(f, line, sizeof(line)))
                     96:     {
                     97:       (*lino)++;
                     98:       p = line;
                     99:       while (*p && *p != '\n' && *p != '\r')
                    100:        p++;
                    101:       if (!*p && !pci_eof(f))
                    102:        return "Line too long";
                    103:       *p = 0;
                    104:       if (p > line && (p[-1] == ' ' || p[-1] == '\t'))
                    105:        *--p = 0;
                    106: 
                    107:       p = line;
                    108:       while (id_white_p(*p))
                    109:        p++;
                    110:       if (!*p || *p == '#')
                    111:        continue;
                    112: 
                    113:       p = line;
                    114:       while (*p == '\t')
                    115:        p++;
                    116:       nest = p - line;
                    117: 
                    118:       if (!nest)                                       /* Top-level entries */
                    119:        {
                    120:          if (p[0] == 'C' && p[1] == ' ')               /* Class block */
                    121:            {
                    122:              if ((id1 = id_hex(p+2, 2)) < 0 || !id_white_p(p[4]))
                    123:                return parse_error;
                    124:              cat = ID_CLASS;
                    125:              p += 5;
                    126:            }
                    127:          else if (p[0] == 'S' && p[1] == ' ')
                    128:            {                                           /* Generic subsystem block */
                    129:              if ((id1 = id_hex(p+2, 4)) < 0 || p[6])
                    130:                return parse_error;
                    131:              if (!pci_id_lookup(a, 0, ID_VENDOR, id1, 0, 0, 0))
                    132:                return "Vendor does not exist";
                    133:              cat = ID_GEN_SUBSYSTEM;
                    134:              continue;
                    135:            }
                    136:          else if (p[0] >= 'A' && p[0] <= 'Z' && p[1] == ' ')
                    137:            {                                           /* Unrecognized block (RFU) */
                    138:              cat = ID_UNKNOWN;
                    139:              continue;
                    140:            }
                    141:          else                                          /* Vendor ID */
                    142:            {
                    143:              if ((id1 = id_hex(p, 4)) < 0 || !id_white_p(p[4]))
                    144:                return parse_error;
                    145:              cat = ID_VENDOR;
                    146:              p += 5;
                    147:            }
                    148:          id2 = id3 = id4 = 0;
                    149:        }
                    150:       else if (cat == ID_UNKNOWN)                      /* Nested entries in RFU blocks are skipped */
                    151:        continue;
                    152:       else if (nest == 1)                              /* Nesting level 1 */
                    153:        switch (cat)
                    154:          {
                    155:          case ID_VENDOR:
                    156:          case ID_DEVICE:
                    157:          case ID_SUBSYSTEM:
                    158:            if ((id2 = id_hex(p, 4)) < 0 || !id_white_p(p[4]))
                    159:              return parse_error;
                    160:            p += 5;
                    161:            cat = ID_DEVICE;
                    162:            id3 = id4 = 0;
                    163:            break;
                    164:          case ID_GEN_SUBSYSTEM:
                    165:            if ((id2 = id_hex(p, 4)) < 0 || !id_white_p(p[4]))
                    166:              return parse_error;
                    167:            p += 5;
                    168:            id3 = id4 = 0;
                    169:            break;
                    170:          case ID_CLASS:
                    171:          case ID_SUBCLASS:
                    172:          case ID_PROGIF:
                    173:            if ((id2 = id_hex(p, 2)) < 0 || !id_white_p(p[2]))
                    174:              return parse_error;
                    175:            p += 3;
                    176:            cat = ID_SUBCLASS;
                    177:            id3 = id4 = 0;
                    178:            break;
                    179:          default:
                    180:            return parse_error;
                    181:          }
                    182:       else if (nest == 2)                              /* Nesting level 2 */
                    183:        switch (cat)
                    184:          {
                    185:          case ID_DEVICE:
                    186:          case ID_SUBSYSTEM:
                    187:            if ((id3 = id_hex(p, 4)) < 0 || !id_white_p(p[4]) || (id4 = id_hex(p+5, 4)) < 0 || !id_white_p(p[9]))
                    188:              return parse_error;
                    189:            p += 10;
                    190:            cat = ID_SUBSYSTEM;
                    191:            break;
                    192:          case ID_CLASS:
                    193:          case ID_SUBCLASS:
                    194:          case ID_PROGIF:
                    195:            if ((id3 = id_hex(p, 2)) < 0 || !id_white_p(p[2]))
                    196:              return parse_error;
                    197:            p += 3;
                    198:            cat = ID_PROGIF;
                    199:            id4 = 0;
                    200:            break;
                    201:          default:
                    202:            return parse_error;
                    203:          }
                    204:       else                                             /* Nesting level 3 or more */
                    205:        return parse_error;
                    206:       while (id_white_p(*p))
                    207:        p++;
                    208:       if (!*p)
                    209:        return parse_error;
                    210:       if (pci_id_insert(a, cat, id1, id2, id3, id4, p, SRC_LOCAL))
                    211:        return "Duplicate entry";
                    212:     }
                    213:   return NULL;
                    214: }
                    215: 
                    216: int
                    217: pci_load_name_list(struct pci_access *a)
                    218: {
                    219:   pci_file f;
                    220:   int lino;
                    221:   const char *err;
                    222: 
                    223:   pci_free_name_list(a);
                    224:   a->id_load_failed = 1;
                    225:   if (!(f = pci_open(a)))
                    226:     return 0;
                    227:   err = id_parse_list(a, f, &lino);
                    228:   PCI_ERROR(f, err);
                    229:   pci_close(f);
                    230:   if (err)
                    231:     a->error("%s at %s, line %d\n", err, a->id_file_name, lino);
                    232:   a->id_load_failed = 0;
                    233:   return 1;
                    234: }
                    235: 
                    236: void
                    237: pci_free_name_list(struct pci_access *a)
                    238: {
                    239:   pci_id_cache_flush(a);
                    240:   pci_id_hash_free(a);
                    241:   a->id_load_failed = 0;
                    242: }
                    243: 
                    244: void
                    245: pci_set_name_list_path(struct pci_access *a, char *name, int to_be_freed)
                    246: {
                    247:   if (a->free_id_name)
                    248:     free(a->id_file_name);
                    249:   a->id_file_name = name;
                    250:   a->free_id_name = to_be_freed;
                    251: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>