7 re_vendor = re.compile(r'^(?P<vendor_id>[0-9a-fA-F]{4})\s*(?P<vendor_name>.*)')
8 re_vendev = re.compile(r'^\s*(?P<vendor_id>[0-9a-fA-F]{4})\s+'
9 r'(?P<device_id>[0-9a-fA-F]{4})\s+(?P<device_name>.*)')
10 re_device = re.compile(r'^\s+(?P<device_id>[0-9a-fA-F]{4})\s+'
11 r'(?P<device_name>.*)')
12 re_comment = re.compile(r'^(\s*#.*|\s*)$')
15 if isinstance(x, basestring): return int(x, 16)
18 def parse_pci_file(ids_file, file_name):
20 @return dictionary in format:
21 { vendor_id: ( vendor_name
22 , { device_id : device_name
28 vendor_id and device_id are integers
32 nested = {} # (vendor_id, {device_id, device_name})
34 def _add_nested(file_name, line, vendor, dev_id, dev_name):
35 dev_id = x2int(dev_id)
36 if vendor not in nested:
38 if dev_id in nested[vendor]:
39 sys.stderr.write('Warning: device "%04x:%04x" redeclared!'
40 ' File: %s : %d\n'%(vendor, dev_id, file_name, line))
41 nested[vendor][dev_id] = dev_name
43 def _add_vendor(file_name, line, vendor_id, vendor_name):
44 vendor = x2int(vendor_id)
46 sys.stderr.write('Warning: vendor "%04x" redeclared!'
47 ' File: %s : %d\n'%(vendor, file_name, line))
48 res[vendor] = (vendor_name, res[vendor][1])
50 res[vendor] = (vendor_name, {})
52 for dev_id, dev_name in nested[vendor].items():
53 _add_device(file_name, line,
54 vendor, dev_id, dev_name)
57 def _add_device(file_name, line, vendor, dev_id, dev_name):
58 """ @note: does not check for a vendor """
59 dev_id = x2int(dev_id)
60 if dev_id in res[vendor][1]:
61 sys.stderr.write('Warning: device "%04x:%04x" redeclared!'
62 ' File: %s : %d\n'%(vendor, dev_id, file_name, i))
63 res[vendor][1][dev_id] = dev_name
65 for i, l in enumerate(ids_file.readlines(), 1):
66 if re_comment.match(l): continue
67 m = re_vendor.match(l)
69 vendor = x2int(m.group('vendor_id'))
70 _add_vendor(file_name, i, vendor, m.group('vendor_name'))
73 m = re_vendev.match(l)
75 dev_vendor = x2int(m.group('vendor_id'))
76 dev_id = x2int(m.group('device_id'))
77 if vendor != dev_vendor and dev_vendor not in res:
78 #sys.stderr.write('Warning: nested vendor of device "%x:%x"'
79 #' does not match top level vendor "%x"! File: %s : %d\n' %(
80 #dev_vendor, dev_id, vendor, file_name, i))
81 _add_nested(file_name, i,
82 dev_vendor, dev_id, m.group('device_name'))
84 _add_device(file_name, i,
85 dev_vendor, dev_id, m.group('device_name'))
88 m = re_device.match(l)
90 _add_device(file_name, i,
91 vendor, m.group('device_id'), m.group('device_name'))
93 sys.stderr.write("Warning: not handled line: \"%s\"\n" % l[:-1])
95 for vendor, devices in nested.items():
96 sys.stderr.write('Warning: no name for vendor "%04x"! File: %s\n'%(
98 res[vendor] = ('<UNKNOWN>', devices)
101 if __name__ == '__main__':
102 parser = argparse.ArgumentParser(description="Compare new pci.ids to old.")
103 parser.add_argument('old', type=argparse.FileType('r'),
104 help="old pci.ids file")
105 parser.add_argument('new', type=argparse.FileType('r'),
106 help="new pci.ids file")
108 args = parser.parse_args()
109 old = parse_pci_file(args.old, args.old.name)
110 new = parse_pci_file(args.new, args.new.name)
118 for vendor, (vendor_name, devices) in old.items():
119 if vendor not in new:
121 devices_removed += len(devices)
123 if vendor_name != new[vendor][0]:
125 for dev_id, dev_name in devices.items():
126 if dev_id not in new[vendor]:
128 elif dev_name != new[vendor][dev_id]:
131 for vendor, (vendor_name, devices) in new.items():
132 if vendor not in old:
134 devices_added += len(devices)
136 for dev_id, dev_name in devices.items():
137 if dev_id not in old[vendor]:
140 print "old vendor count: %d" % len(old)
141 print "new vendor count: %d" % len(new)
142 print "vendors added: %d" % vendors_added
143 print "vendors removed: %d" % vendors_removed
144 print "vendors renamed: %d" % vendors_renamed
145 print "devices added: %d" % devices_added
146 print "devices removed: %d" % devices_removed
147 print "devices renamed: %d" % devices_renamed