Annotation of embedaddon/pciutils/lib/names-parse.c, revision 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>