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>