Merge from vendor branch AWK:
[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.1 2006/06/15 13:37:35 swildner Exp $
28 #
29 # usage: mk_pci_vendors [-lq] [-p pcidevs.txt] [-v vendors.txt]
30 #
31 # Generate src/share/misc/pci_vendors from the Hart and Boemler 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 #
37 # -l    Where an entry is found in both input lists, use the entry with
38 #       the longest description.  The default is for the Boemler file to
39 #       override the Hart file.
40 # -q    Do not print diagnostics.
41 # -p    Specify the pathname of the Hart file. (Default ./pcidevs.txt)
42 # -v    Specify the pathname of the Boemler file. (Default ./vendors.txt)
43 #
44 use strict;
45 use Getopt::Std;
46
47 my $PROGNAME = 'mk_pci_vendors';
48 my $VENDORS_FILE = 'vendors.txt';
49 my $PCIDEVS_FILE = 'pcidevs.txt';
50
51 my $cur_vendor;
52 my %opts;
53 my %vendors;
54 my ($descr, $existing, $id, $line, $rv, $winner, $optlused);
55
56 my $IS_VENDOR = 1;
57 my $IS_DEVICE = 2;
58 my $V_DESCR = 0;
59 my $V_DEVSL = 1;
60 my $W_NOCONTEST = 0;
61 my $W_VENDORS = 1;
62 my $W_PCIDEVS = 2;
63
64 sub clean_descr($);
65 sub vendors_parse($\$\$);
66 sub pcidevs_parse($\$\$);
67
68 if (not getopts('lp:qv:', \%opts) or @ARGV > 0) {
69         print STDERR "usage: $PROGNAME [-lq] [-p pcidevs.txt] [-v vendors.txt]\n";
70         exit 1;
71 }
72
73 if (not defined($opts{p})) {
74         $opts{p} = $PCIDEVS_FILE;
75 }
76 if (not defined($opts{v})) {
77         $opts{v} = $VENDORS_FILE;
78 }
79 foreach (('l', 'q')) {
80         if (not exists($opts{$_})) {
81                 $opts{$_} = 0;
82         } else {
83                 $opts{$_} = 1;
84         }
85 }
86
87 open(VENDORS, "< $opts{v}") or
88     die "$PROGNAME: $opts{v}: $!\n";
89 while ($line = <VENDORS>) {
90         chomp($line);
91         $rv = vendors_parse($line, $id, $descr);
92         if ($rv == $IS_VENDOR) {
93                 if (exists($vendors{$id})) {
94                         die "$PROGNAME: $id: duplicate vendor ID\n";
95                 }
96                 $vendors{$id} = [$descr, {}];
97                 $cur_vendor = $id;
98         } elsif ($rv == $IS_DEVICE) {
99                 ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id} = $descr;
100         }
101 }
102 close(VENDORS);
103
104 open(PCIDEVS, "< $opts{p}") or
105     die "$PROGNAME: $opts{p}: $!\n";
106 while ($line = <PCIDEVS>) {
107         chomp($line);
108         $rv = pcidevs_parse($line, $id, $descr);
109         if ($rv == $IS_VENDOR) {
110                 if (not exists($vendors{$id})) {
111                         $vendors{$id} = [$descr, {}];
112                         $winner = $W_NOCONTEST;
113                 } elsif ($opts{l}) {
114                         $existing = $vendors{$id}->[$V_DESCR];
115                         if (length($existing) < length($descr)) {
116                                 $vendors{$id}->[$V_DESCR] = $descr;
117                                 $winner = $W_PCIDEVS;
118                         } else {
119                                 $winner = $W_VENDORS;
120                         }
121                 } else {
122                         $winner = $W_VENDORS;
123                 }
124                 $cur_vendor = $id;
125                 if (not $opts{q} and $winner != $W_NOCONTEST) {
126                         $existing = $vendors{$id}->[$V_DESCR];
127                         print STDERR "$PROGNAME: ",
128                             $winner == $W_VENDORS ? "Boemler" : "Hart",
129                             " vendor wins: $id\t$existing\n";
130                 }
131         } elsif ($rv == $IS_DEVICE) {
132                 if (not exists(${$vendors{$cur_vendor}->[$V_DEVSL]}{$id})) {
133                         ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id} = $descr;
134                         $winner = $W_NOCONTEST;
135                 } elsif ($opts{l}) {
136                         $existing = ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id};
137                         if (length($existing) < length($descr)) {
138                                 ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id} =
139                                     $descr;
140                                 $winner = $W_PCIDEVS;
141                         } else {
142                                 $winner = $W_VENDORS;
143                         }
144                 } else {
145                         $winner = $W_VENDORS;
146                 }
147                 if (not $opts{q} and $winner != $W_NOCONTEST) {
148                         $existing = ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id};
149                         print STDERR "$PROGNAME: ",
150                             $winner == $W_VENDORS ? "Boemler" : "Hart",
151                             " device wins: $id\t$existing\n";
152                 }
153         }
154 }
155 close(PCIDEVS);
156
157 $optlused = $opts{l} ? "with" : "without";
158 print <<HEADER_END;
159 ; \$DragonFly\$
160 ;
161 ; Automatically generated by src/tools/tools/pciid/mk_pci_vendors.pl
162 ; ($optlused the -l option), using the following source lists:
163 ;
164 ;       http://www.pcidatabase.com/reports.php?type=tab-delimeted
165 ;       http://members.datafast.net.au/dft0802/downloads/pcidevs.txt
166 ;
167 ; Manual edits on this file will be lost!
168 ;
169 HEADER_END
170
171 foreach $cur_vendor (sort keys %vendors) {
172         $id = $cur_vendor;
173         $descr = $vendors{$id}->[$V_DESCR];
174         print "$id\t$descr\n";
175         foreach $id (sort keys %{$vendors{$cur_vendor}->[$V_DEVSL]}) {
176                 $descr = ${$vendors{$cur_vendor}->[$V_DEVSL]}{$id};
177                 print "\t$id\t$descr\n";
178         }
179 }
180 exit 0;
181
182
183 # Parse a line from the Boemler file and place the ID and description
184 # in the scalars referenced by $id_ref and $descr_ref.
185 #
186 # On success, returns $IS_VENDOR if the line represents a vendor entity
187 # or $IS_DEVICE if the line represents a device entity.
188 #
189 # Returns 0 on failure.
190 #
191 sub vendors_parse($\$\$)
192 {
193         my ($line, $id_ref, $descr_ref) = @_;
194
195         if ($line =~ /^([A-Fa-f0-9]{4})\t([^\t].+?)\s*$/) {
196                 ($$id_ref, $$descr_ref) = (uc($1), clean_descr($2));
197                 return $IS_VENDOR;
198         } elsif ($line =~ /^\t([A-Fa-f0-9]{4})\t([^\t].+?)\s*$/) {
199                 ($$id_ref, $$descr_ref) = (uc($1), clean_descr($2));
200                 return $IS_DEVICE;
201         } elsif (not $opts{q} and
202             $line !~ /^\s*$/ and $line !~ /^;/) {
203                 chomp($line);
204                 print STDERR "$PROGNAME: ignored Boemler: $line\n";
205         }
206
207         return 0;
208 }
209
210 # Parse a line from the Hart file and place the ID and description
211 # in the scalars referenced by $id_ref and $descr_ref.
212 #
213 # On success, returns $IS_VENDOR if the line represents a vendor entity
214 # or $IS_DEVICE if the line represents a device entity.
215 #
216 # Returns 0 on failure.
217 #
218 sub pcidevs_parse($\$\$)
219 {
220         my ($line, $id_ref, $descr_ref) = @_;
221         my $descr;
222
223         if ($line =~ /^V\t([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 =~ /^D\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 !~ /^[;ORSX]/) {
231                 print STDERR "$PROGNAME: ignored Hart: $line\n";
232         }
233
234         return 0;
235 }
236
237 sub clean_descr($)
238 {
239         my ($descr) = @_;
240
241         return $descr;
242 }