Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / tools / tools / pciid / mk_pci_vendors.pl
1 #!/usr/bin/perl -w
2 #
3 # Copyright (C) 2001 Sheldon Hearn.  All rights reserved.
4
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 # 1. Redistributions of source code must retain the above copyright
9 #    notice, this list of conditions and the following disclaimer.
10 # 2. Redistributions in binary form must reproduce the above copyright
11 #    notice, this list of conditions and the following disclaimer in the
12 #    documentation and/or other materials provided with the distribution.
13
14 # THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 # SUCH DAMAGE.
25
26 # $FreeBSD: src/tools/tools/pciid/mk_pci_vendors.pl,v 1.5 2004/06/28 11:46:48 mux Exp $
27 # $DragonFly: src/tools/tools/pciid/mk_pci_vendors.pl,v 1.2 2008/03/08 20:17:38 swildner Exp $
28 #
29 # usage: mk_pci_vendors [-lq] [-p pcidevs.txt] [-v vendors.txt] [-x pci.ids]
30 #
31 # Generate src/share/misc/pci_vendors from the Hart, Boemler and Mares lists,
32 # currently available at:
33 #
34 # Boemler:      http://www.pcidatabase.com/reports.php?type=tab-delimeted
35 # Hart:         http://members.datafast.net.au/dft0802/downloads/pcidevs.txt
36 # Mares:        http://pciids.sourceforge.net/pci.ids
37 #
38 # -l    Where an entry is found in the Boemler and the Hart lists, use the
39 #       entry with the longest description.  The -l option doesn't affect
40 #       the Mares list whose entries are only used if they are new.  The
41 #       default is for the Boemler file to override the Hart file to
42 #       override the Mares file.
43 # -q    Do not print diagnostics.
44 # -p    Specify the pathname of the Hart file. (Default ./pcidevs.txt)
45 # -v    Specify the pathname of the Boemler file. (Default ./vendors.txt)
46 # -x    Specify the pathname of the Mares file. (Default ./pci.ids)
47 #
48 use strict;
49 use Getopt::Std;
50
51 my $PROGNAME = 'mk_pci_vendors';
52 my $VENDORS_FILE = 'vendors.txt';
53 my $PCIDEVS_FILE = 'pcidevs.txt';
54 my $PCIIDS_FILE = 'pci.ids';
55
56 my $cur_vendor;
57 my %opts;
58 my %vendors;
59 my ($descr, $existing, $id, $line, $rv, $winner, $optlused);
60
61 my $IS_VENDOR = 1;
62 my $IS_DEVICE = 2;
63 my $V_DESCR = 0;
64 my $V_DEVSL = 1;
65 my $W_NOCONTEST = 0;
66 my $W_VENDORS = 1;
67 my $W_PCIDEVS = 2;
68
69 sub clean_descr($);
70 sub vendors_parse($\$\$);
71 sub pcidevs_parse($\$\$);
72 sub pciids_parse($\$\$);
73
74 if (not getopts('lp:qv:x:', \%opts) or @ARGV > 0) {
75         print STDERR "usage: $PROGNAME [-lq] [-p pcidevs.txt] [-v vendors.txt] [-x pci.ids]\n";
76         exit 1;
77 }
78
79 if (not defined($opts{p})) {
80         $opts{p} = $PCIDEVS_FILE;
81 }
82 if (not defined($opts{v})) {
83         $opts{v} = $VENDORS_FILE;
84 }
85 if (not defined($opts{x})) {
86         $opts{x} = $PCIIDS_FILE;
87 }
88 foreach (('l', 'q')) {
89         if (not exists($opts{$_})) {
90                 $opts{$_} = 0;
91         } else {
92                 $opts{$_} = 1;
93         }
94 }
95
96 open(VENDORS, "< $opts{v}") or
97     die "$PROGNAME: $opts{v}: $!\n";
98 while ($line = <VENDORS>) {
99         chomp($line);
100         $rv = vendors_parse($line, $id, $descr);
101         if ($rv == $IS_VENDOR) {
102                 if (exists($vendors{$id})) {
103                         die "$PROGNAME: $id: duplicate vendor ID\n";
104                 }
105                 $vendors{$id} = [$descr, {}];
106                 $cur_vendor = $id;
107         } elsif ($rv == $IS_DEVICE) {
108                 ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id} = $descr;
109         }
110 }
111 close(VENDORS);
112
113 open(PCIDEVS, "< $opts{p}") or
114     die "$PROGNAME: $opts{p}: $!\n";
115 while ($line = <PCIDEVS>) {
116         chomp($line);
117         $rv = pcidevs_parse($line, $id, $descr);
118         if ($rv == $IS_VENDOR) {
119                 if (not exists($vendors{$id})) {
120                         $vendors{$id} = [$descr, {}];
121                         $winner = $W_NOCONTEST;
122                 } elsif ($opts{l}) {
123                         $existing = $vendors{$id}->[$V_DESCR];
124                         if (length($existing) < length($descr)) {
125                                 $vendors{$id}->[$V_DESCR] = $descr;
126                                 $winner = $W_PCIDEVS;
127                         } else {
128                                 $winner = $W_VENDORS;
129                         }
130                 } else {
131                         $winner = $W_VENDORS;
132                 }
133                 $cur_vendor = $id;
134                 if (not $opts{q} and $winner != $W_NOCONTEST) {
135                         $existing = $vendors{$id}->[$V_DESCR];
136                         print STDERR "$PROGNAME: ",
137                             $winner == $W_VENDORS ? "Boemler" : "Hart",
138                             " vendor wins: $id\t$existing\n";
139                 }
140         } elsif ($rv == $IS_DEVICE) {
141                 if (not exists(${$vendors{$cur_vendor}->[$V_DEVSL]}{$id})) {
142                         ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id} = $descr;
143                         $winner = $W_NOCONTEST;
144                 } elsif ($opts{l}) {
145                         $existing = ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id};
146                         if (length($existing) < length($descr)) {
147                                 ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id} =
148                                     $descr;
149                                 $winner = $W_PCIDEVS;
150                         } else {
151                                 $winner = $W_VENDORS;
152                         }
153                 } else {
154                         $winner = $W_VENDORS;
155                 }
156                 if (not $opts{q} and $winner != $W_NOCONTEST) {
157                         $existing = ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id};
158                         print STDERR "$PROGNAME: ",
159                             $winner == $W_VENDORS ? "Boemler" : "Hart",
160                             " device wins: $id\t$existing\n";
161                 }
162         }
163 }
164 close(PCIDEVS);
165
166 open(PCIIDS, "< $opts{x}") or
167     die "$PROGNAME: $opts{x}: $!\n";
168 while ($line = <PCIIDS>) {
169         chomp($line);
170         $rv = pciids_parse($line, $id, $descr);
171         if ($rv == $IS_VENDOR) {
172                 if (not exists($vendors{$id})) {
173                         $vendors{$id} = [$descr, {}];
174                 }
175         $cur_vendor = $id;
176         } elsif ($rv == $IS_DEVICE) {
177                 if (not exists(${$vendors{$cur_vendor}->[$V_DEVSL]}{$id})) {
178                         ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id} = $descr;
179                 }
180         }
181 }
182 close(PCIIDS);
183
184 $optlused = $opts{l} ? "with" : "without";
185 print <<HEADER_END;
186 ; \$DragonFly\$
187 ;
188 ; Automatically generated by src/tools/tools/pciid/mk_pci_vendors.pl
189 ; ($optlused the -l option), using the following source lists:
190 ;
191 ;       http://www.pcidatabase.com/reports.php?type=tab-delimeted
192 ;       http://members.datafast.net.au/dft0802/downloads/pcidevs.txt
193 ;       http://pciids.sourceforge.net/pci.ids
194 ;
195 ; Manual edits on this file will be lost!
196 ;
197 HEADER_END
198
199 foreach $cur_vendor (sort keys %vendors) {
200         $id = $cur_vendor;
201         $descr = $vendors{$id}->[$V_DESCR];
202         print "$id\t$descr\n";
203         foreach $id (sort keys %{$vendors{$cur_vendor}->[$V_DEVSL]}) {
204                 $descr = ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id};
205                 print "\t$id\t$descr\n";
206         }
207 }
208 exit 0;
209
210
211 # Parse a line from the Boemler file and place the ID and description
212 # in the scalars referenced by $id_ref and $descr_ref.
213 #
214 # On success, returns $IS_VENDOR if the line represents a vendor entity
215 # or $IS_DEVICE if the line represents a device entity.
216 #
217 # Returns 0 on failure.
218 #
219 sub vendors_parse($\$\$)
220 {
221         my ($line, $id_ref, $descr_ref) = @_;
222
223         if ($line =~ /^([A-Fa-f0-9]{4})\t([^\t].+?)\s*$/) {
224                 ($$id_ref, $$descr_ref) = (uc($1), clean_descr($2));
225                 return $IS_VENDOR;
226         } elsif ($line =~ /^\t([A-Fa-f0-9]{4})\t([^\t].+?)\s*$/) {
227                 ($$id_ref, $$descr_ref) = (uc($1), clean_descr($2));
228                 return $IS_DEVICE;
229         } elsif (not $opts{q} and
230             $line !~ /^\s*$/ and $line !~ /^;/) {
231                 chomp($line);
232                 print STDERR "$PROGNAME: ignored Boemler: $line\n";
233         }
234
235         return 0;
236 }
237
238 # Parse a line from the Hart file and place the ID and description
239 # in the scalars referenced by $id_ref and $descr_ref.
240 #
241 # On success, returns $IS_VENDOR if the line represents a vendor entity
242 # or $IS_DEVICE if the line represents a device entity.
243 #
244 # Returns 0 on failure.
245 #
246 sub pcidevs_parse($\$\$)
247 {
248         my ($line, $id_ref, $descr_ref) = @_;
249         my $descr;
250
251         if ($line =~ /^V\t([A-Fa-f0-9]{4})\t([^\t].+?)\s*$/) {
252                 ($$id_ref, $$descr_ref) = (uc($1), clean_descr($2));
253                 return $IS_VENDOR;
254         } elsif ($line =~ /^D\t([A-Fa-f0-9]{4})\t([^\t].+?)\s*$/) {
255                 ($$id_ref, $$descr_ref) = (uc($1), clean_descr($2));
256                 return $IS_DEVICE;
257         } elsif (not $opts{q} and
258             $line !~ /^\s*$/ and $line !~ /^[;ORSX]/) {
259                 print STDERR "$PROGNAME: ignored Hart: $line\n";
260         }
261
262         return 0;
263 }
264
265 # Parse a line from the Mares file and place the ID and description
266 # in the scalars referenced by $id_ref and $descr_ref.
267 #
268 # On success, returns $IS_VENDOR if the line represents a vendor entity
269 # or $IS_DEVICE if the line represents a device entity.
270 #
271 # Returns 0 on failure.
272 #
273 sub pciids_parse($\$\$)
274 {
275         my ($line, $id_ref, $descr_ref) = @_;
276         my $descr;
277
278         if ($line =~ /^([A-Fa-f0-9]{4})  (.+?)$/) {
279                 ($$id_ref, $$descr_ref) = (uc($1), clean_descr($2));
280                 return $IS_VENDOR;
281         } elsif ($line =~ /^\t([A-Fa-f0-9]{4})  (.+?)$/) {
282                 ($$id_ref, $$descr_ref) = (uc($1), clean_descr($2));
283                 return $IS_DEVICE;
284         } elsif (not $opts{q} and
285             $line !~ /^\s*$/ and $line !~ /^#/) {
286                 chomp($line);
287                 print STDERR "$PROGNAME: ignored Mares: $line\n";
288         }
289
290         return 0;
291 }
292
293 sub clean_descr($)
294 {
295         my ($descr) = @_;
296
297         return $descr;
298 }