~ubuntu-branches/ubuntu/utopic/hwinfo/utopic

« back to all changes in this revision

Viewing changes to src/ids/convert_hd

  • Committer: Bazaar Package Importer
  • Author(s): James Vega
  • Date: 2006-11-03 07:28:15 UTC
  • mfrom: (1.2.1 upstream) (3.1.7 edgy)
  • Revision ID: james.westby@ubuntu.com-20061103072815-7g9d6kzk0xn54159
Add cpu.c-alpha_bogo patch, which fixes a FTBFS on alpha because of an
undefined variable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/perl
 
2
 
 
3
use Getopt::Long;
 
4
use XML::Writer;
 
5
use XML::Parser;
 
6
use IO;
 
7
use Dumpvalue;
 
8
 
 
9
sub help;
 
10
 
 
11
sub read_name_file;
 
12
sub read_driver_file;
 
13
sub read_id_file;
 
14
sub read_pcimap_file;
 
15
sub read_usbmap_file;
 
16
sub read_alias_file;
 
17
sub read_modinfo_file;
 
18
sub eisa_id;
 
19
sub eisa_str;
 
20
 
 
21
sub remove_nops;
 
22
sub remove_duplicates;
 
23
sub fix_driver_info;
 
24
 
 
25
sub cmp_id;
 
26
sub cmp_skey;
 
27
sub cmp_item;
 
28
 
 
29
sub match_id;
 
30
sub match_skey;
 
31
sub match_item;
 
32
 
 
33
sub join_skey;
 
34
 
 
35
sub split_item;
 
36
 
 
37
sub get_xml_data;
 
38
sub parse_xml_item;
 
39
sub parse_xml_key;
 
40
sub parse_xml_id;
 
41
sub parse_xml_id_id;
 
42
sub parse_xml_id_range;
 
43
sub parse_xml_id_mask;
 
44
sub parse_xml_driver;
 
45
sub parse_xml_driver_display;
 
46
sub parse_xml_driver_module;
 
47
sub parse_xml_driver_mouse;
 
48
sub parse_xml_driver_xfree;
 
49
sub parse_xml_pair;
 
50
sub parse_xml_cdata;
 
51
sub idstr2value;
 
52
 
 
53
sub dump2ids;
 
54
sub dump2xml;
 
55
sub dump_xml_item;
 
56
sub dump_xml_names;
 
57
sub dump_xml_drivers;
 
58
sub id2xml;
 
59
 
 
60
sub hd_dtd;
 
61
sub hd_dtd_internal;
 
62
 
 
63
$dump = new Dumpvalue();
 
64
 
 
65
(
 
66
  $he_other, $he_bus_id, $he_baseclass_id, $he_subclass_id, $he_progif_id,
 
67
  $he_vendor_id, $he_device_id, $he_subvendor_id, $he_subdevice_id, $he_rev_id,
 
68
  $he_bus_name, $he_baseclass_name, $he_subclass_name, $he_progif_name,
 
69
  $he_vendor_name, $he_device_name, $he_subvendor_name, $he_subdevice_name,
 
70
  $he_rev_name, $he_serial, $he_driver, $he_requires, $he_hwclass,
 
71
  $he_nomask,
 
72
  $he_driver_module_insmod, $he_driver_module_modprobe,
 
73
  $he_driver_module_config, $he_driver_xfree, $he_driver_xfree_config,
 
74
  $he_driver_mouse, $he_driver_display, $he_driver_any
 
75
) = ( 0 .. 100 );
 
76
$he_class_id = $he_nomask;
 
77
 
 
78
@ent_names = (
 
79
  "other", "bus.id", "baseclass.id", "subclass.id", "progif.id",
 
80
  "vendor.id", "device.id", "subvendor.id", "subdevice.id", "rev.id",
 
81
  "bus.name", "baseclass.name", "subclass.name", "progif.name",
 
82
  "vendor.name", "device.name", "subvendor.name", "subdevice.name",
 
83
  "rev.name", "serial", "driver", "requires", "hwclass",
 
84
  "class.id", "driver.module.insmod", "driver.module.modprobe",
 
85
  "driver.module.config", "driver.xfree", "driver.xfree.config",
 
86
  "driver.mouse", "driver.display", "driver.any"
 
87
);
 
88
@ent_values{@ent_names} = ( 0 .. 100 );
 
89
 
 
90
@xml_names = (
 
91
  "other", "bus", "baseclass", "subclass", "progif",
 
92
  "vendor", "device", "subvendor", "subdevice", "revision",
 
93
  "bus", "baseclass", "subclass", "progif",
 
94
  "vendor", "device", "subvendor", "subdevice",
 
95
  "revision", "serial", "driver", "requires"
 
96
);
 
97
@xml_values{@xml_names} = ( 0 .. 100 );
 
98
 
 
99
( $tag_none, $tag_pci, $tag_eisa, $tag_usb, $tag_special, $tag_pcmcia ) = ( 0 .. 5 );
 
100
 
 
101
@tag_name = ( "", "pci", "eisa", "usb", "special", "pcmcia" );
 
102
@tag_values{@tag_name} = ( 0 .. 5 );
 
103
$tag_values{none} = 0;
 
104
 
 
105
( $flag_id, $flag_range, $flag_mask, $flag_string, $flag_regexp ) = ( 0 .. 4 );
 
106
$flag_cont = 8;
 
107
 
 
108
# map usb modules to device classes
 
109
%usbmod2class = (
 
110
  'ov511'     => [ 0x10f, 0 ],
 
111
  'pwc'       => [ 0x10f, 0 ],
 
112
  'hpusbscsi' => [ 0x10c, 0 ],
 
113
  'microtek'  => [ 0x10c, 0 ],
 
114
  'scanner'   => [ 0x10c, 0 ]
 
115
);
 
116
 
 
117
@hwclass_names = (
 
118
  undef, "system", "cpu", "keyboard", "braille", "mouse", "joystick",
 
119
  "printer", "scanner", "chipcard", "monitor", "tv card", "graphics card",
 
120
  "framebuffer", "camera", "sound", "storage", "network", "isdn adapter",
 
121
  "modem", "network interface", "disk", "partition", "cdrom", "floppy",
 
122
  "manual", "usb controller", "usb", "bios", "pci", "isapnp", "bridge",
 
123
  "hub", "scsi", "ide", "memory", "dvb card", "pcmcia", "pcmcia controller",
 
124
  "firewire", "firewire controller", "hotplug", "hotplug controller", "zip",
 
125
  "pppoe", "wlan card", "redasd", "dsl adapter", "block device", "tape",
 
126
  "vesa bios", "bluetooth", "unknown"
 
127
);
 
128
@hwclass_values{@hwclass_names} = ( 0 .. 255 );
 
129
 
 
130
 
 
131
# options
 
132
$opt_write_ids = 1;
 
133
$opt_write_xml = 0;
 
134
$opt_sort_ids = 0;
 
135
$opt_sort_reverse = 0;
 
136
$opt_sort_random = 0;           # for testing
 
137
$opt_split = 0;
 
138
$opt_with_source = 0;
 
139
$opt_fix_driver = 1;
 
140
$opt_help = 0;
 
141
$opt_internal_dtd = 0;
 
142
 
 
143
$opt_ok = GetOptions(
 
144
  'ids'           => \$opt_write_ids,
 
145
  'no-ids'        => sub { $opt_write_ids = 0 },
 
146
  'xml'           => \$opt_write_xml,
 
147
  'no-xml'        => sub { $opt_write_xml = 0 },
 
148
  'sort'          => \$opt_sort,
 
149
  'reverse'       => \$opt_sort_reverse,
 
150
  'random'        => \$opt_sort_random,
 
151
  'split'         => \$opt_split,
 
152
  'with-source'   => \$opt_with_source,
 
153
  'fix-driver'    => \$opt_fix_driver,
 
154
  'no-fix-driver' => sub { $opt_fix_driver = 0 },
 
155
  'internal-dtd'  => \$opt_internal_dtd,
 
156
  'help'          => \&help
 
157
) ;
 
158
 
 
159
for $f (@ARGV) {
 
160
  if(open F, $f) {
 
161
    @f = (<F>);
 
162
    close F;
 
163
 
 
164
    # file format check
 
165
 
 
166
    undef $format;
 
167
 
 
168
    for (@f) {
 
169
      if(/^\s*\<\?xml\s/) {
 
170
        $format = 'xml';
 
171
        last;
 
172
      }
 
173
 
 
174
      if(/^#\s+pci\s+module\s+vendor\s+device\s+subvendor\s+subdevice\s+class\s+class_mask\s+driver_data\s*$/) {
 
175
        $format = 'pcimap';
 
176
        last;
 
177
      }
 
178
 
 
179
      if(/^#\s+usb\s+module\s+match_flags\s+idVendor\s+idProduct\s+/) {
 
180
        $format = 'usbmap';
 
181
        last;
 
182
      }
 
183
 
 
184
      if(/^\s*alias\s+(pci|pnp|usb):\S+\s+\S+$/) {
 
185
        $format = 'alias';
 
186
        last;
 
187
      }
 
188
 
 
189
      if(/^\s*alias:\s+(pci|pnp|usb):\S+\s*$/) {
 
190
        $format = 'modinfo';
 
191
        last;
 
192
      }
 
193
 
 
194
    }
 
195
 
 
196
    if(!$format) {
 
197
      $i = join "|", map "\Q$_", @ent_names;
 
198
      for (@f) {
 
199
        if(/^\s*[+&|]?($i)\s/) {
 
200
          $format = 'ids';
 
201
          last;
 
202
        }
 
203
      }
 
204
    }
 
205
 
 
206
    if(!$format) {
 
207
      for (@f) {
 
208
        if(/^\t[a-z]\s/) {
 
209
          $format = 'drivers';
 
210
          last;
 
211
        }
 
212
      }
 
213
    }
 
214
 
 
215
    $format = 'names' if !$format;
 
216
 
 
217
    if($format eq 'names') {
 
218
 
 
219
      print STDERR "======  \"$f\": name info  ======\n";
 
220
      read_name_file $f, \@f;
 
221
 
 
222
    }
 
223
    elsif($format eq 'drivers') {
 
224
 
 
225
      print STDERR "======  \"$f\": driver info  ======\n";
 
226
      read_driver_file $f, \@f;
 
227
 
 
228
    }
 
229
    elsif($format eq 'xml') {
 
230
 
 
231
      print STDERR "======  \"$f\": xml info  ======\n";
 
232
      $xmlp = new XML::Parser(Style => 'Tree', ParseParamEnt => 1);
 
233
      get_xml_data $xmlp->parsefile($f);
 
234
 
 
235
    }
 
236
    elsif($format eq 'ids') {
 
237
 
 
238
      print STDERR "======  \"$f\": id info  ======\n";
 
239
      read_id_file $f, \@f;
 
240
 
 
241
    }
 
242
    elsif($format eq 'pcimap') {
 
243
 
 
244
      print STDERR "======  \"$f\": pcimap info  ======\n";
 
245
      read_pcimap_file $f, \@f;
 
246
 
 
247
    }
 
248
    elsif($format eq 'usbmap') {
 
249
 
 
250
      print STDERR "======  \"$f\": usbmap info  ======\n";
 
251
      read_usbmap_file $f, \@f;
 
252
 
 
253
    }
 
254
    elsif($format eq 'alias') {
 
255
 
 
256
      print STDERR "======  \"$f\": alias info  ======\n";
 
257
      read_alias_file $f, \@f;
 
258
 
 
259
    }
 
260
    elsif($format eq 'modinfo') {
 
261
 
 
262
      print STDERR "======  \"$f\": module info  ======\n";
 
263
      read_modinfo_file $f, \@f;
 
264
 
 
265
    }
 
266
  }
 
267
  else {
 
268
    die "$f: $!\n"
 
269
  }
 
270
}
 
271
 
 
272
print STDERR "removing unnecessary items\n";
 
273
remove_nops;
 
274
 
 
275
print STDERR "got ${\scalar @hd} items\n";
 
276
 
 
277
if($opt_fix_driver) {
 
278
  fix_driver_info;
 
279
}
 
280
 
 
281
if($opt_split) {
 
282
  print STDERR "splitting items\n";
 
283
  for (@hd) {
 
284
    push @hd_new, split_item($_);
 
285
  }
 
286
  @hd = @hd_new;
 
287
  undef @hd_new;
 
288
}
 
289
 
 
290
if($opt_sort_ids) {
 
291
  print STDERR "sorting\n";
 
292
  if($opt_sort_random) {
 
293
    @hd = sort { $cmp_item_cnt++, rand() <=> rand() } @hd;
 
294
  }
 
295
  elsif($opt_sort_reverse) {
 
296
    @hd = sort { cmp_item $b, $a } @hd;
 
297
  }
 
298
  else {
 
299
    @hd = sort { cmp_item $a, $b } @hd;
 
300
  }
 
301
}
 
302
 
 
303
if($opt_write_ids) {
 
304
  print STDERR "writing \"hd.ids\"\n";
 
305
  dump2ids;
 
306
}
 
307
 
 
308
if($opt_write_xml) {
 
309
  print STDERR "writing \"hd.xml\"\n";
 
310
  dump2xml;
 
311
}
 
312
 
 
313
print STDERR "cmps: $cmp_item_cnt\n" if $cmp_item_cnt;
 
314
 
 
315
# $dump->dumpValue( \@hd );
 
316
 
 
317
 
 
318
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
319
 
 
320
sub help
 
321
{
 
322
  print STDERR
 
323
  "Usage: convert_hd [options] files\n" .
 
324
  "Convert various hardware info to libhd/hwinfo internal format or to XML.\n" .
 
325
  "  --ids           write internal format (default) to \"hd.ids\"\n" .
 
326
  "  --no-ids        do not write internal format\n" .
 
327
  "  --xml           write XML to \"hd.xml\", DTD to \"hd.dtd\"\n" .
 
328
  "  --no-xml        do not write XML (default)\n" .
 
329
  "  --with-source   add comment to each item indicating info source\n" .
 
330
  "  --internal-dtd  generate internal dtd\n\n" .
 
331
  "  Note: for more sophisticated operations on hardware data use check_hd.\n";
 
332
 
 
333
  exit 0;
 
334
}
 
335
 
 
336
 
 
337
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
338
sub num
 
339
{
 
340
  return $_[0] =~ /^0/ ? oct $_[0] : return $_[0] + 0;
 
341
}
 
342
 
 
343
 
 
344
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
345
#
 
346
# read file with name/class info
 
347
#
 
348
# (either pciutils or SaX/SaX2 format)
 
349
#
 
350
 
 
351
sub read_name_file
 
352
{
 
353
  my ( $file_name, $file, $line, $sax_version, $tag, $id, $val, $ent );
 
354
  my ( @id0, @id1, @id2, @id3, @id4, $raw, $opt, $ext, $srv, $str );
 
355
  local $_;
 
356
 
 
357
  my $rnf_add_id0 = sub
 
358
  {
 
359
    my ( $id0, $name0, $ent_id0, $ent_name0, $id, $val );
 
360
 
 
361
    # note: $tag belongs to read_name_file()
 
362
    ( $ent_id0, $ent_name0, $tag, $id0, $name0 ) = @_;
 
363
 
 
364
    $ent = $ent_id0;
 
365
 
 
366
    @id0 = ( $flag_id, $tag, $id0 );
 
367
    undef @id1; undef @id2; undef @id3;
 
368
 
 
369
    $id->[$ent_id0] = [ @id0 ];
 
370
    $val->[$ent_name0] = [ $flag_string, $name0 ];
 
371
 
 
372
    push @hd, [ "$file_name($line)", [ $id ], $val ];
 
373
  };
 
374
 
 
375
  my $rnf_add_bus = sub
 
376
  {
 
377
    $rnf_add_id0->($he_bus_id, $he_bus_name, 0, @_);
 
378
  };
 
379
 
 
380
  my $rnf_add_baseclass = sub
 
381
  {
 
382
    $rnf_add_id0->($he_baseclass_id, $he_baseclass_name, 0, @_);
 
383
  };
 
384
 
 
385
  my $rnf_add_vendor = sub
 
386
  {
 
387
    $rnf_add_id0->($he_vendor_id, $he_vendor_name, @_);
 
388
  };
 
389
 
 
390
  my $rnf_add_subdevice = sub
 
391
  {
 
392
    my ( $id2, $id3, $range, $name, $class, $id, $val );
 
393
 
 
394
    ( $id2, $id3, $range, $name, $class ) = @_;
 
395
 
 
396
    @id2 = ( $flag_id, $tag, $id2 );
 
397
    @id3 = ( $flag_id, $tag, $id3 );
 
398
    $id3[3] = $range if defined $range;
 
399
 
 
400
    if($ent == $he_device_id || $ent == $he_subdevice_id) {
 
401
      $ent = $he_subdevice_id;
 
402
 
 
403
      $id->[$he_vendor_id] = [ @id0 ];
 
404
      $id->[$he_device_id] = [ @id1 ];
 
405
      $id->[$he_subvendor_id] = [ @id2 ];
 
406
      $id->[$he_subdevice_id] = [ @id3 ];
 
407
      $val->[$he_subdevice_name] = [ $flag_string, $name ];
 
408
      if(defined $class) {
 
409
        $val->[$he_baseclass_id] = [ $flag_id, $tag_none, $class >> 8 ];
 
410
        $val->[$he_subclass_id] = [ $flag_id, $tag_none, $class & 0xff ];
 
411
      }
 
412
    }
 
413
    else {
 
414
      die "oops $file_name($line): subdevice id expected\n";
 
415
    }
 
416
 
 
417
    push @hd, [ "$file_name($line)", [ $id ], $val ];
 
418
  };
 
419
 
 
420
  ( $file_name, $file ) = @_;
 
421
 
 
422
  $line = 0;
 
423
  undef $sax_version;
 
424
 
 
425
  for (@$file) {
 
426
    $line++;
 
427
    chomp;
 
428
    s/\s*$//;
 
429
    next if /^\s*[#;]/;
 
430
    next if /^$/;
 
431
 
 
432
    # SaX Identity file
 
433
    if(/^NAME=(.+?)�DEVICE=(.+?)�VID=0x([0-9a-fA-F]+?)�DID=0x([0-9a-fA-F]+?)�SERVER=([^�]+)(�EXT=([^�]*))?(�OPT=([^�]*))?(�RAW=([^�]*))?$/) {
 
434
      #       1            2           3                     4                      5      6     7        8     9        10    11
 
435
 
 
436
      $rnf_add_vendor->($tag_pci, hex($3), $1);
 
437
 
 
438
      @id0 = ( $flag_id, $tag, hex($3) );
 
439
      @id1 = ( $flag_id, $tag, hex($4) );
 
440
      @id3 = ( $flag_string, $2 );
 
441
 
 
442
      $id = [];
 
443
      $val = [];
 
444
 
 
445
      $id->[$he_vendor_id] = [ @id0 ];
 
446
      $id->[$he_device_id] = [ @id1 ];
 
447
      $val->[$he_device_name] = [ @id3 ];
 
448
 
 
449
      push @hd, [ "$file_name($line)", [ $id ], $val ];
 
450
 
 
451
      ( $srv, $ext, $opt, $raw ) = ( $5, $7, $9, $11 );
 
452
      $sax_tmp = $srv =~ /^3DLABS|MACH64|P9000|RUSH|S3|SVGA|TGA$/ ? 1 : 2;
 
453
      $sax_version = $sax_tmp unless defined $sax_version;
 
454
      die "line has SaX$sax_tmp format (expected SaX$sax_version): $file_name($line)\n" if $sax_tmp != $sax_version;
 
455
 
 
456
      $id = [];
 
457
      $val = [];
 
458
 
 
459
      $id->[$he_vendor_id] = [ @id0 ];
 
460
      $id->[$he_device_id] = [ @id1 ];
 
461
 
 
462
      if($opt) {
 
463
        $str = join "|", ( $sax_version == 1 ? 3 : 4, $srv, undef, undef, $ext, $opt );
 
464
      }
 
465
      elsif($ext) {
 
466
        $str = join "|", ( $sax_version == 1 ? 3 : 4, $srv, undef, undef, $ext );
 
467
      }
 
468
      else {
 
469
        $str = join "|", ( $sax_version == 1 ? 3 : 4, $srv );
 
470
      }
 
471
 
 
472
      @id4 = ( "x\t$str" );
 
473
      if($raw) {
 
474
        for $str (split /,/, $raw) { $id4[0] .= "\x00X\t$str" }
 
475
      }
 
476
 
 
477
      $val->[$he_driver] = [ $flag_string, @id4 ];
 
478
 
 
479
      push @hd, [ "$file_name($line)", [ $id ], $val ];
 
480
    }
 
481
 
 
482
    elsif(/^B\s+([0-9a-fA-F]+)\s+(.*?)\s*$/) {
 
483
 
 
484
      $rnf_add_bus->(hex($1), $2);
 
485
 
 
486
    }
 
487
 
 
488
    elsif(/^C\s+([0-9a-fA-F]+)\s+(.*?)\s*$/) {
 
489
 
 
490
      $rnf_add_baseclass->(hex($1), $2);
 
491
 
 
492
    }
 
493
 
 
494
    elsif(/^([0-9a-fA-F]{4})(\s+(.*?))?\s*$/) {
 
495
 
 
496
      $rnf_add_vendor->($tag_pci, hex($1), $3);
 
497
 
 
498
    }
 
499
 
 
500
    elsif(/^u([0-9a-fA-F]{4})(\s+(.*?))?\s*$/) {
 
501
 
 
502
      $rnf_add_vendor->($tag_usb, hex($1), $3);
 
503
 
 
504
    }
 
505
 
 
506
    elsif(/^s([0-9a-fA-F]{4})(\s+(.*?))?\s*$/) {
 
507
 
 
508
      $rnf_add_vendor->($tag_special, hex($1), $3);
 
509
 
 
510
    }
 
511
 
 
512
    elsif(/^([A-Z_@]{3})(\s+(.*?))?\s*$/) {
 
513
 
 
514
      $rnf_add_vendor->($tag_eisa, eisa_id($1), $3);
 
515
 
 
516
    }
 
517
 
 
518
    elsif(/^\t([0-9a-fA-F]{1,4})(\+([0-9a-fA-F]+))?(\.([0-9a-fA-F]+))?(\s+(.*?))?\s*$/) {
 
519
 
 
520
      $range = $3 ? hex($3) : undef;
 
521
      $class = $5 ? hex($5) : undef;
 
522
 
 
523
      @id1 = ( $flag_id, $tag, hex($1) );
 
524
      $id1[3] = $range if defined $range;
 
525
      undef @id2; undef @id3;
 
526
 
 
527
      $id = [];
 
528
      $val = [];
 
529
 
 
530
      if($ent == $he_baseclass_id || $ent == $he_subclass_id) {
 
531
        $ent = $he_subclass_id;
 
532
 
 
533
        $id->[$he_baseclass_id] = [ @id0 ];
 
534
        $id->[$he_subclass_id] = [ @id1 ];
 
535
        $val->[$he_subclass_name] = [ $flag_string, $7 ];
 
536
      }
 
537
      elsif($ent == $he_vendor_id || $ent == $he_device_id || $ent == $he_subdevice_id) {
 
538
        $ent = $he_device_id;
 
539
 
 
540
        $id->[$he_vendor_id] = [ @id0 ];
 
541
        $id->[$he_device_id] = [ @id1 ];
 
542
        $val->[$he_device_name] = [ $flag_string, $7 ];
 
543
        if(defined $class) {
 
544
          $val->[$he_baseclass_id] = [ $flag_id, $tag_none, $class >> 8 ];
 
545
          $val->[$he_subclass_id] = [ $flag_id, $tag_none, $class & 0xff ];
 
546
        }
 
547
      }
 
548
      else {
 
549
        die "oops $file_name($line): device id expected\n";
 
550
      }
 
551
 
 
552
      push @hd, [ "$file_name($line)", [ $id ], $val ];
 
553
 
 
554
    }
 
555
 
 
556
    elsif($ent == $he_subclass_id && /^\t\t([0-9a-fA-F]+)\s+(.*?)\s*$/) {
 
557
 
 
558
      @id2 = ( $flag_id, $tag, hex($1) );
 
559
      undef @id3;
 
560
 
 
561
      $id = [];
 
562
      $val = [];
 
563
 
 
564
      $id->[$he_baseclass_id] = [ @id0 ];
 
565
      $id->[$he_subclass_id] = [ @id1 ];
 
566
      $id->[$he_progif_id] = [ @id2 ];
 
567
      $val->[$he_progif_name] = [ $flag_string, $2 ];
 
568
 
 
569
      push @hd, [ "$file_name($line)", [ $id ], $val ];
 
570
 
 
571
    }
 
572
 
 
573
    elsif(/^\t\t([0-9a-fA-F]{4})\s+([0-9a-fA-F]{4})(\+([0-9a-fA-F]+))?(\.([0-9a-fA-F]+))?(\s+(.*?))?\s*$/) {
 
574
 
 
575
      $rnf_add_subdevice->(hex($1), hex($2), $4 ? hex($4) : undef, $8, $6 ? hex($6) : undef);
 
576
 
 
577
    }
 
578
 
 
579
    elsif(/^\t\t([A-Z_@]{3})\s+([0-9a-fA-F]{4})(\+([0-9a-fA-F]+))?(\.([0-9a-fA-F]+))?(\s+(.*?))?\s*$/) {
 
580
 
 
581
      $rnf_add_subdevice->(eisa_id($1), hex($2), $4 ? hex($4) : undef, $8, $6 ? hex($6) : undef);
 
582
 
 
583
    }
 
584
 
 
585
    elsif(/^\t\t([0-9a-fA-F]{4})([0-9a-fA-F]{4})\s+(.*?)\s*$/) {
 
586
 
 
587
      # NOTE: subvendor & subdevice ids are reversed!
 
588
      $rnf_add_subdevice->(hex($2), hex($1), undef, $3);
 
589
 
 
590
    }
 
591
 
 
592
    else {
 
593
      die "invalid line: $file_name($line)\n";
 
594
    }
 
595
  }
 
596
}
 
597
 
 
598
 
 
599
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
600
#
 
601
# read file with driver info
 
602
#
 
603
 
 
604
sub read_driver_file
 
605
{
 
606
  my ( $line, @drv, $file, $file_name, $drv_type, $tag );
 
607
  local $_;
 
608
 
 
609
  my $rdf_save_drv = sub
 
610
  {
 
611
    if($drv_type) {
 
612
      push @hd, [ @drv ] if defined @drv;
 
613
      @drv = ( "$file_name($line)" );
 
614
      $drv[2][$he_driver] = [ $flag_string ];
 
615
      $drv_type = undef;
 
616
    }
 
617
  };
 
618
 
 
619
  my $rdf_add_id = sub
 
620
  {
 
621
    my ( $tag, $id0, $id1, $range1, $id2, $id3, $range3, $id );
 
622
 
 
623
    ( $tag, $id0, $id1, $range1, $id2, $id3, $range3 ) = @_;
 
624
 
 
625
    $rdf_save_drv->();
 
626
 
 
627
    $id = [];
 
628
 
 
629
    @id0 = ( $flag_id, $tag, $id0 );
 
630
    @id1 = ( $flag_id, $tag, $id1 );
 
631
    $id1[3] = $range1 if defined $range1;
 
632
 
 
633
    $id->[$he_vendor_id] = [ @id0 ];
 
634
    $id->[$he_device_id] = [ @id1 ];
 
635
 
 
636
    if(defined $id2) {
 
637
      @id2 = ( $flag_id, $tag, $id2 );
 
638
      @id3 = ( $flag_id, $tag, $id3 );
 
639
      $id3[3] = $range3 if defined $range3;
 
640
 
 
641
      $id->[$he_subvendor_id] = [ @id2 ];
 
642
      $id->[$he_subdevice_id] = [ @id3 ];
 
643
    }
 
644
    push @{$drv[1]}, $id;
 
645
  };
 
646
 
 
647
  ( $file_name, $file ) = @_;
 
648
 
 
649
  $drv_type = 1;
 
650
 
 
651
  for (@$file) {
 
652
    $line++;
 
653
    chomp;
 
654
    s/\s*$//;
 
655
    next if /^[#;]/;
 
656
    next if /^$/;
 
657
 
 
658
    if(/^([us]?)([0-9a-fA-F]{4})\s+([0-9a-fA-F]{4})(\+([0-9a-fA-F]+))?\s*$/) {
 
659
 
 
660
      $tag = $tag_pci;
 
661
      $tag = $tag_usb if $1 eq 'u';
 
662
      $tag = $tag_special if $1 eq 's';
 
663
 
 
664
      $rdf_add_id->($tag, hex($2), hex($3), $5 ? hex($5) : undef);
 
665
 
 
666
    }
 
667
 
 
668
    elsif(/^([A-Z_@]{3})\s+([0-9a-fA-F]{4})(\+([0-9a-fA-F]+))?\s*$/) {
 
669
 
 
670
      $rdf_add_id->($tag_eisa, eisa_id($1), hex($2), $4 ? hex($4) : undef);
 
671
 
 
672
    }
 
673
 
 
674
    elsif(/^([us]?)([0-9a-fA-F]{4})\s+([0-9a-fA-F]{4})(\+([0-9a-fA-F]+))?\s+([us]?)([0-9a-fA-F]{4})\s+([0-9a-fA-F]{4})(\+([0-9a-fA-F]+))?\s*$/) {
 
675
 
 
676
      $tag = $tag_pci;
 
677
      $tag = $tag_usb if $1 eq 'u';
 
678
      $tag = $tag_special if $1 eq 's';
 
679
 
 
680
      $rdf_add_id->($tag, hex($2), hex($3), $5 ? hex($5) : undef, hex($7), hex($8), $10 ? hex($10) : undef);
 
681
 
 
682
    }
 
683
 
 
684
    elsif(/^([A-Z_@]{3})\s+([0-9a-fA-F]{4})(\+([0-9a-fA-F]+))?\s+([A-Z_@]{3})\s+([0-9a-fA-F]{4})(\+([0-9a-fA-F]+))?\s*$/) {
 
685
 
 
686
      $rdf_add_id->($tag_eisa, eisa_id($1), hex($2), $4 ? hex($4) : undef, eisa_id($5), hex($6), $8 ? hex($8) : undef);
 
687
 
 
688
    }
 
689
 
 
690
    elsif(/^\t([a-z])\s+(.*?)\s*$/) {
 
691
 
 
692
      push @{$drv[2][$he_driver]}, "$1\t$2";
 
693
      $drv_type = $1;
 
694
 
 
695
    }
 
696
 
 
697
    elsif($drv_type && /^\t\t\s*(.*)$/) {
 
698
 
 
699
      $drv_type = "X" if $drv_type eq "x";
 
700
      $drv_type = "M" if $drv_type eq "m";
 
701
      $drv[2][$he_driver][-1] .= "\x00$drv_type\t$1";
 
702
 
 
703
    }
 
704
 
 
705
    else {
 
706
      die "invalid line: $file_name($line)\n";
 
707
    }
 
708
  }
 
709
 
 
710
  $rdf_save_drv->();
 
711
}
 
712
 
 
713
 
 
714
sub num
 
715
{
 
716
  return $_[0] =~ /^0/ ? oct $_[0] : return $_[0] + 0;
 
717
}
 
718
 
 
719
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
720
#
 
721
# read file with id info
 
722
#
 
723
 
 
724
sub read_id_file
 
725
{
 
726
  my ( $line, $file, $file_name, $tag, $pre, $fields, @item, @id, $state, $keyid );
 
727
  my ( $is_id, $i, $j );
 
728
  local $_;
 
729
 
 
730
  my $rif_save_item = sub
 
731
  {
 
732
    if(@item > 1) {
 
733
      push @hd, [ @item ];
 
734
    }
 
735
    @item = ( "$file_name($line)" );
 
736
  };
 
737
 
 
738
  # parse id field
 
739
  my $str2id = sub
 
740
  {
 
741
    my ($val, $id, $tag, $mask, $range, @id);
 
742
 
 
743
    $val = shift;
 
744
 
 
745
    if($val =~ s/^(${\join '|', @tag_name})\s+//o) {
 
746
      die "internal oops: $file_name($line)\n" unless exists $tag_values{$1};
 
747
      $tag = $tag_values{$1};
 
748
    }
 
749
    else {
 
750
      $tag = 0;
 
751
    }
 
752
 
 
753
    if($val =~ /^\s*(\S+)\s*([&+])\s*(\S+)\s*$/) {
 
754
      $id = $1;
 
755
      if($2 eq "+") {
 
756
        $range = $3;
 
757
      }
 
758
      else {
 
759
        $mask = $3;
 
760
      }
 
761
    }
 
762
    else {
 
763
      $id = $val;
 
764
    }
 
765
 
 
766
    if(defined $range) {
 
767
      if($range =~ /^(0x[0-9a-zA-Z]+|\d+)$/) {
 
768
        $range = num $range;
 
769
      }
 
770
      else {
 
771
        die "$file_name($line): invalid range\n"
 
772
      }
 
773
    }
 
774
 
 
775
    if(defined $mask) {
 
776
      if($mask =~ /^(0x[0-9a-zA-Z]+|\d+)$/) {
 
777
        $mask = num $mask;
 
778
      }
 
779
      else {
 
780
        die "$file_name($line): invalid mask\n"
 
781
      }
 
782
    }
 
783
 
 
784
    if($id =~ /^(0x[0-9a-zA-Z]+|\d+)$/) {
 
785
      $id = num $id;
 
786
    }
 
787
    elsif(($tag == $tag_none || $tag == $tag_eisa) && $id =~ /^[A-Z_@]{3}$/) {
 
788
      $id = eisa_id $id;
 
789
      $tag = $tag_eisa;
 
790
    }
 
791
    else {
 
792
      die "$file_name($line): invalid id\n"
 
793
    }
 
794
 
 
795
    @id = ( $flag_id, $tag, $id );
 
796
    $id[3] = $range if defined $range;
 
797
    $id[4] = $mask if defined $mask;
 
798
 
 
799
    return \@id;
 
800
  };
 
801
 
 
802
  ( $file_name, $file ) = @_;
 
803
 
 
804
  $fields = join "|", map "\Q$_", @ent_names;
 
805
 
 
806
  $state = 0;
 
807
 
 
808
  $rif_save_item->();
 
809
 
 
810
  for (@$file) {
 
811
    $line++;
 
812
    chomp;
 
813
    s/\s*$//;
 
814
    next if /^\s*[#;]/;
 
815
    next if /^$/;
 
816
 
 
817
    if(/^\s*([+&|]?)($fields)\s+(.+)/) {
 
818
      ($pre, $key, $val) = ($1, $2, $3);
 
819
      # print ">$pre< $is_id>$key< >$val<\n";
 
820
      die "internal oops: $file_name($line)\n" unless exists $ent_values{$key};
 
821
      $keyid = $ent_values{$key};
 
822
      $is_id = $keyid < $he_nomask && $key =~ /\.id$/ ? 1 : 0;
 
823
    }
 
824
    else {
 
825
      die "invalid line: $file_name($line)\n";
 
826
    }
 
827
 
 
828
    if($pre eq "") {
 
829
      die "invalid line: $file_name($line)\n" unless $state == 0 || $state == 2;
 
830
      if($state == 2) {
 
831
        $item[2] = [ @id ];
 
832
        undef @id;
 
833
      }
 
834
      $rif_save_item->();
 
835
      $state = 1;
 
836
    }
 
837
    elsif($pre eq "|") {
 
838
      die "invalid line: $file_name($line)\n" unless $state == 1;
 
839
      push @{$item[1]}, [ @id ];
 
840
      undef @id;
 
841
    }
 
842
    elsif($pre eq "&") {
 
843
      die "invalid line: $file_name($line)\n" unless $state == 1;
 
844
    }
 
845
    elsif($pre eq "+") {
 
846
      die "invalid line: $file_name($line)\n" unless $state == 1 || $state == 2;
 
847
      if($state == 1) {
 
848
        push @{$item[1]}, [ @id ];
 
849
        undef @id;
 
850
      }
 
851
      $state = 2;
 
852
    }
 
853
    else {
 
854
      die "internal oops: $file_name($line)\n";
 
855
    }
 
856
 
 
857
    if($is_id) {
 
858
      $id[$keyid] = $str2id->($val);
 
859
    }
 
860
    elsif($keyid == $he_hwclass) {
 
861
      $i = 0;
 
862
      for $j (reverse split /\|/, $val) {
 
863
        $i = ($i << 8) + $hwclass_values{$j} if $hwclass_values{$j};
 
864
        last if $i > 0xffff;
 
865
      }
 
866
      $id[$keyid] = [ $flag_id, 0, $i ] if $i;
 
867
    }
 
868
    elsif($keyid < $he_nomask) {
 
869
      $id[$keyid] = [ $flag_string, $val ];
 
870
    }
 
871
    elsif($keyid == $he_class_id) {
 
872
      $i = ${$str2id->($val)}[2];
 
873
      $id[$he_baseclass_id] = [ $flag_id, $tag_none, $i >> 8 ];
 
874
      $id[$he_subclass_id] = [ $flag_id, $tag_none, $i & 0xff ];
 
875
    }
 
876
    else {
 
877
      undef $i;
 
878
      if($keyid == $he_driver_module_insmod) {
 
879
        $i = "i";
 
880
      }
 
881
      elsif($keyid == $he_driver_module_modprobe) {
 
882
        $i = "m";
 
883
      }
 
884
      elsif($keyid == $he_driver_module_config) {
 
885
        $i = "M";
 
886
      }
 
887
      elsif($keyid == $he_driver_xfree) {
 
888
        $i = "x";
 
889
      }
 
890
      elsif($keyid == $he_driver_xfree_config) {
 
891
        $i = "X";
 
892
      }
 
893
      elsif($keyid == $he_driver_mouse) {
 
894
        $i = "p";
 
895
      }
 
896
      elsif($keyid == $he_driver_display) {
 
897
        $i = "d";
 
898
      }
 
899
      elsif($keyid == $he_driver_any) {
 
900
        $i = "a";
 
901
      }
 
902
      else {
 
903
        die "unhandled entry: $file_name($line)\n"
 
904
      }
 
905
      $val = "$i\t$val";
 
906
      if(!defined $id[$he_driver]) {
 
907
        $id[$he_driver] = [ $flag_string ];
 
908
      }
 
909
      if($i eq "X" || $i eq "M") {
 
910
        $id[$he_driver]->[-1] .= "\x00$val"
 
911
      }
 
912
      else {
 
913
        push @{$id[$he_driver]}, $val;
 
914
      }
 
915
    }
 
916
  }
 
917
 
 
918
  if($state == 2) {
 
919
    $item[2] = [ @id ];
 
920
    undef @id;
 
921
  }
 
922
 
 
923
  $rif_save_item->();
 
924
}
 
925
 
 
926
 
 
927
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
928
#
 
929
# read pcimap file
 
930
#
 
931
 
 
932
sub read_pcimap_file
 
933
{
 
934
  my (@l, $id, $n, $key, $val, $mask);
 
935
  local $_;
 
936
 
 
937
  ( $file_name, $file ) = @_;
 
938
 
 
939
  for (@$file) {
 
940
    $line++;
 
941
    chomp;
 
942
    s/\s*$//;
 
943
    next if /^\s*#/;
 
944
    next if /^$/;
 
945
 
 
946
    @l = split;
 
947
 
 
948
    die "invalid line: $file_name($line)\n" unless @l == 8;
 
949
 
 
950
    $val = [];
 
951
 
 
952
    $val->[$he_driver] = [ $flag_string, "m\t$l[0]" ];
 
953
 
 
954
    $key = [];
 
955
 
 
956
    $key->[$he_vendor_id] = [ $flag_id, $tag_pci, $n ] if ($n = num $l[1]) != 0xffffffff;
 
957
    $key->[$he_device_id] = [ $flag_id, $tag_pci, $n ] if ($n = num $l[2]) != 0xffffffff;
 
958
    $key->[$he_subvendor_id] = [ $flag_id, $tag_pci, $n ] if ($n = num $l[3]) != 0xffffffff;
 
959
    $key->[$he_subdevice_id] = [ $flag_id, $tag_pci, $n ] if ($n = num $l[4]) != 0xffffffff;
 
960
 
 
961
    $n = num $l[6];
 
962
 
 
963
    if($mask = ($n >> 16) & 0xff) {
 
964
      $key->[$he_baseclass_id] = [ $flag_id, $tag_none, (num($l[5]) >> 16) & 0xff ];
 
965
      if($mask != 0xff) {
 
966
        $key->[$he_baseclass_id][4] = (~$mask & 0xff);
 
967
      }
 
968
    }
 
969
 
 
970
    if($mask = ($n >> 8) & 0xff) {
 
971
      $key->[$he_subclass_id] = [ $flag_id, $tag_none, (num($l[5]) >> 8) & 0xff ];
 
972
      if($mask != 0xff) {
 
973
        $key->[$he_subclass_id][4] = (~$mask & 0xff);
 
974
      }
 
975
    }
 
976
 
 
977
    if($mask = $n & 0xff) {
 
978
      $key->[$he_progif_id] = [ $flag_id, $tag_none, num($l[5]) & 0xff ];
 
979
      if($mask != 0xff) {
 
980
        $key->[$he_progif_id][4] = (~$mask & 0xff);
 
981
      }
 
982
    }
 
983
 
 
984
    push @hd, [ "$file_name($line)", [ $key ], $val ];
 
985
  }
 
986
}
 
987
 
 
988
 
 
989
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
990
#
 
991
# read usbmap file
 
992
#
 
993
 
 
994
sub read_usbmap_file
 
995
{
 
996
  my (@l, $id, $n, $key, $val, $mask);
 
997
  local $_;
 
998
 
 
999
  ( $file_name, $file ) = @_;
 
1000
 
 
1001
  for (@$file) {
 
1002
    $line++;
 
1003
    chomp;
 
1004
    s/\s*$//;
 
1005
    next if /^\s*#/;
 
1006
    next if /^$/;
 
1007
 
 
1008
    @l = split;
 
1009
 
 
1010
    die "invalid line: $file_name($line)\n" unless @l == 13;
 
1011
 
 
1012
    next if num($l[1]) != 3;    # match_flags != 3
 
1013
 
 
1014
    $val = [];
 
1015
 
 
1016
    $key = [];
 
1017
 
 
1018
    $key->[$he_vendor_id] = [ $flag_id, $tag_usb, num($l[2]) ];
 
1019
    $key->[$he_device_id] = [ $flag_id, $tag_usb, num($l[3]) ];
 
1020
 
 
1021
    $val->[$he_driver] = [ $flag_string, "m\t$l[0]" ];
 
1022
 
 
1023
    if($usbmod2class{$l[0]}) {
 
1024
      $val->[$he_baseclass_id] = [ $flag_id, $tag_none, $usbmod2class{$l[0]}[0] ] if defined $usbmod2class{$l[0]}[0];
 
1025
      $val->[$he_subclass_id] = [ $flag_id, $tag_none, $usbmod2class{$l[0]}[1] ] if defined $usbmod2class{$l[0]}[1];
 
1026
    }
 
1027
 
 
1028
    push @hd, [ "$file_name($line)", [ $key ], $val ];
 
1029
  }
 
1030
}
 
1031
 
 
1032
 
 
1033
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1034
#
 
1035
# read alias file
 
1036
#
 
1037
 
 
1038
sub read_alias_file
 
1039
{
 
1040
  my ($f, $id, $n, $key, $val, $mask, $tag, $module, $spec, $t1, $t2);
 
1041
  local $_;
 
1042
 
 
1043
  $f = '[0-9A-F*]+';
 
1044
 
 
1045
  ( $file_name, $file ) = @_;
 
1046
 
 
1047
  for (@$file) {
 
1048
    $line++;
 
1049
    chomp;
 
1050
    s/\s*$//;
 
1051
    next if /^\s*#/;
 
1052
    next if /^$/;
 
1053
 
 
1054
    next unless /^\s*alias\s+(pci|pnp|usb):(\S+)\s+(\S+)/;
 
1055
 
 
1056
    $tag = $tag_pci if $1 eq 'pci';
 
1057
    $tag = $tag_eisa if $1 eq 'pnp';
 
1058
    $tag = $tag_usb if $1 eq 'usb';
 
1059
 
 
1060
    $spec = $2;
 
1061
    $module = $3;
 
1062
 
 
1063
    $val = [];
 
1064
 
 
1065
    $val->[$he_driver] = [ $flag_string, "m\t$module" ];
 
1066
 
 
1067
    $key = [];
 
1068
 
 
1069
    if($spec =~ /^v($f)d($f)sv($f)sd($f)bc($f)sc($f)i($f)$/ ) {
 
1070
      $key->[$he_vendor_id] = [ $flag_id, $tag, hex $1 ] if $1 ne '*';
 
1071
      $key->[$he_device_id] = [ $flag_id, $tag, hex $2 ] if $2 ne '*';
 
1072
      $key->[$he_subvendor_id] = [ $flag_id, $tag, hex $3 ] if $3 ne '*';
 
1073
      $key->[$he_subdevice_id] = [ $flag_id, $tag, hex $4 ] if $4 ne '*';
 
1074
      $key->[$he_baseclass_id] = [ $flag_id, $tag_none, hex $5 ] if $5 ne '*';
 
1075
      $key->[$he_subclass_id] = [ $flag_id, $tag_none, hex $6 ] if $6 ne '*';
 
1076
      $key->[$he_progif_id] = [ $flag_id, $tag_none, hex $7 ] if $7 ne '*';
 
1077
 
 
1078
      push @hd, [ "$file_name($line)", [ $key ], $val ];
 
1079
    }
 
1080
    elsif($spec =~ /^v($f)p($f)dl($f)dh($f)dc($f)dsc($f)dp($f)ic($f)isc($f)ip($f)$/ ) {
 
1081
 
 
1082
      if(
 
1083
        $3 == '*' && $4 == '*' && $5 == '*' &&
 
1084
        $6 == '*' && $7 == '*' && $8 == '*' &&
 
1085
        $9 == '*' && $10 == '*'
 
1086
      ) {
 
1087
        $key->[$he_vendor_id] = [ $flag_id, $tag, hex $1 ] if $1 ne '*';
 
1088
        $key->[$he_device_id] = [ $flag_id, $tag, hex $2 ] if $2 ne '*';
 
1089
 
 
1090
        push @hd, [ "$file_name($line)", [ $key ], $val ];
 
1091
      }
 
1092
    }
 
1093
    elsif($spec =~ /^[c|d](\S{3})([0-9a-fA-FX]{4})/ ) {
 
1094
      $t1 = $1;
 
1095
      $t2 = $2;
 
1096
 
 
1097
      if($t1 =~ /[\@A-Z\[\\\]\^_]{3}/ && $t2 ne 'XXXX') {
 
1098
        $key->[$he_vendor_id] = [ $flag_id, $tag, eisa_id $t1 ];
 
1099
        $key->[$he_device_id] = [ $flag_id, $tag, hex $t2 ];
 
1100
 
 
1101
        push @hd, [ "$file_name($line)", [ $key ], $val ];
 
1102
      }
 
1103
    }
 
1104
    else {
 
1105
      die "invalid line: $file_name($line)\n"
 
1106
    }
 
1107
  }
 
1108
}
 
1109
 
 
1110
 
 
1111
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1112
#
 
1113
# read modinfo data
 
1114
#
 
1115
 
 
1116
sub read_modinfo_file
 
1117
{
 
1118
  my ($f, $id, $n, $key, $val, $mask, $tag, $module, $spec, $t1, $t2);
 
1119
  local $_;
 
1120
 
 
1121
  $f = '[0-9A-F*]+';
 
1122
 
 
1123
  ( $file_name, $file ) = @_;
 
1124
 
 
1125
  for (@$file) {
 
1126
    $line++;
 
1127
    chomp;
 
1128
    s/\s*$//;
 
1129
    next if /^\s*#/;
 
1130
    next if /^$/;
 
1131
 
 
1132
    if(m#([^/]+)\.ko:$#) {
 
1133
      $module = $1;
 
1134
      next;
 
1135
    }
 
1136
 
 
1137
    next unless /^\s*alias:\s+(pci|pnp|usb):(\S+)\s*$/;
 
1138
 
 
1139
    $tag = $tag_pci if $1 eq 'pci';
 
1140
    $tag = $tag_eisa if $1 eq 'pnp';
 
1141
    $tag = $tag_usb if $1 eq 'usb';
 
1142
 
 
1143
    $spec = $2;
 
1144
 
 
1145
    $val = [];
 
1146
 
 
1147
    $val->[$he_driver] = [ $flag_string, "m\t$module" ];
 
1148
 
 
1149
    $key = [];
 
1150
 
 
1151
    if($spec =~ /^v($f)d($f)sv($f)sd($f)bc($f)sc($f)i($f)$/ ) {
 
1152
      $key->[$he_vendor_id] = [ $flag_id, $tag, hex $1 ] if $1 ne '*';
 
1153
      $key->[$he_device_id] = [ $flag_id, $tag, hex $2 ] if $2 ne '*';
 
1154
      $key->[$he_subvendor_id] = [ $flag_id, $tag, hex $3 ] if $3 ne '*';
 
1155
      $key->[$he_subdevice_id] = [ $flag_id, $tag, hex $4 ] if $4 ne '*';
 
1156
      $key->[$he_baseclass_id] = [ $flag_id, $tag_none, hex $5 ] if $5 ne '*';
 
1157
      $key->[$he_subclass_id] = [ $flag_id, $tag_none, hex $6 ] if $6 ne '*';
 
1158
      $key->[$he_progif_id] = [ $flag_id, $tag_none, hex $7 ] if $7 ne '*';
 
1159
 
 
1160
      push @hd, [ "$file_name($line)", [ $key ], $val ];
 
1161
    }
 
1162
    elsif($spec =~ /^v($f)p($f)dl($f)dh($f)dc($f)dsc($f)dp($f)ic($f)isc($f)ip($f)$/ ) {
 
1163
 
 
1164
      if(
 
1165
        $3 == '*' && $4 == '*' && $5 == '*' &&
 
1166
        $6 == '*' && $7 == '*' && $8 == '*' &&
 
1167
        $9 == '*' && $10 == '*'
 
1168
      ) {
 
1169
        $key->[$he_vendor_id] = [ $flag_id, $tag, hex $1 ] if $1 ne '*';
 
1170
        $key->[$he_device_id] = [ $flag_id, $tag, hex $2 ] if $2 ne '*';
 
1171
 
 
1172
        push @hd, [ "$file_name($line)", [ $key ], $val ];
 
1173
      }
 
1174
    }
 
1175
    elsif($spec =~ /^[c|d](\S{3})([0-9a-fA-FX]{4})/ ) {
 
1176
      $t1 = $1;
 
1177
      $t2 = $2;
 
1178
 
 
1179
      if($t1 =~ /[\@A-Z\[\\\]\^_]{3}/ && $t2 ne 'XXXX') {
 
1180
        $key->[$he_vendor_id] = [ $flag_id, $tag, eisa_id $t1 ];
 
1181
        $key->[$he_device_id] = [ $flag_id, $tag, hex $t2 ];
 
1182
 
 
1183
        push @hd, [ "$file_name($line)", [ $key ], $val ];
 
1184
      }
 
1185
    }
 
1186
    else {
 
1187
      die "invalid line: $file_name($line)\n"
 
1188
    }
 
1189
  }
 
1190
}
 
1191
 
 
1192
 
 
1193
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1194
#
 
1195
# convert 3-letter eisa id to number
 
1196
#
 
1197
 
 
1198
sub eisa_id
 
1199
{
 
1200
  my ( $str, $id, $i, $j );
 
1201
 
 
1202
  $str = shift;
 
1203
  $id = 0;
 
1204
 
 
1205
  die "internal oops" unless length($str) == 3;
 
1206
  for($i = 0; $i < 3; $i++) {
 
1207
    $id <<= 5;
 
1208
    $j = ord substr $str, $i, 1;
 
1209
    $j -= ord('A') - 1;
 
1210
    die "internal oops" unless $j >= 0 && $j <= 0x1f;
 
1211
    $id += $j;
 
1212
  }
 
1213
  
 
1214
  return $id;
 
1215
}
 
1216
 
 
1217
 
 
1218
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1219
#
 
1220
# convert numerical eisa id to 3-letter string
 
1221
#
 
1222
 
 
1223
sub eisa_str
 
1224
{
 
1225
  my ( $id, $str );
 
1226
 
 
1227
  $id = shift;
 
1228
 
 
1229
  die "internal oops: eisa id \"$id\"" unless $id >= 0 && $id <= 0x7fff;
 
1230
 
 
1231
  $str  = chr((($id >> 10) & 0x1f) + ord('A') - 1);
 
1232
  $str .= chr((($id >>  5) & 0x1f) + ord('A') - 1);
 
1233
  $str .= chr(( $id        & 0x1f) + ord('A') - 1);
 
1234
 
 
1235
  return $str;
 
1236
}
 
1237
 
 
1238
 
 
1239
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1240
#
 
1241
# remove entries that have no effect
 
1242
#
 
1243
 
 
1244
sub remove_nops
 
1245
{
 
1246
  my ($hd, $id, $f, $i, $cf);
 
1247
  local $_;
 
1248
 
 
1249
  for $hd (@hd) {
 
1250
    if(!defined($hd->[1]) || !@{$hd->[1]} || !defined($hd->[2]) || !@{$hd->[2]}) {
 
1251
      undef $hd;
 
1252
      next;
 
1253
    }
 
1254
    for $id (@{$hd->[1]}, $hd->[2]) {
 
1255
      if(defined($id)) {
 
1256
        $cf = 0;
 
1257
        for $f (@$id) {
 
1258
          if(defined $f) {
 
1259
            $cf++;
 
1260
            if(@$f == 2 && $f->[0] == $flag_string && $f->[1] eq "") {
 
1261
              undef $f;
 
1262
              $cf--;
 
1263
            }
 
1264
          }
 
1265
        }
 
1266
        undef $id if !$cf;
 
1267
      }
 
1268
    }
 
1269
    if(!defined($hd->[1]) || !@{$hd->[1]} || !defined($hd->[2]) || !@{$hd->[2]}) {
 
1270
      print STDERR "$hd->[0] has no info, dropped\n";
 
1271
      undef $hd;
 
1272
      next;
 
1273
    }
 
1274
  }
 
1275
 
 
1276
  @hd = grep { defined } @hd;
 
1277
}
 
1278
 
 
1279
 
 
1280
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1281
#
 
1282
# remove duplicate entries
 
1283
#
 
1284
 
 
1285
sub remove_duplicates
 
1286
{
 
1287
  my ($hd, $hd0, $hd1, $len, $i, $j, $m, $v, $buf, $errors, $drop);
 
1288
  local $_;
 
1289
 
 
1290
  $len = @hd;
 
1291
 
 
1292
  for($j = 0; $j < $len; $j++) {
 
1293
    print STDERR ">> $j\r";
 
1294
    $hd0 = \$hd[$j];
 
1295
    for($i = $j + 1; $i < $len; $i++) {
 
1296
      $hd1 = \$hd[$i];
 
1297
      $m = match_item $$hd0, $$hd1;
 
1298
      # print "$$hd0->[0] -- $$hd1->[0]: $m\n";
 
1299
      if($m) {
 
1300
        $drop = cmp_item $$hd0, $$hd1;
 
1301
        $drop = !$drop || abs($drop) == 2 ? ", dropped" : undef;
 
1302
        undef $buf;
 
1303
        # print STDERR "j: $$hd0->[0], $$hd1->[0]\n";
 
1304
        $v = join_skey $$hd0->[2], $$hd1->[2], \$buf, \$errors;
 
1305
        if($errors) {
 
1306
          print STDERR "$$hd1->[0] conflicts with $$hd0->[0]$drop:\n$buf\n";
 
1307
          $$hd1 = undef if $drop;
 
1308
        }
 
1309
        else {
 
1310
          if($drop) {
 
1311
            print STDERR "$$hd1->[0] added to $$hd0->[0] and dropped\n";
 
1312
            $$hd0->[2] = $v;
 
1313
#            $$hd1 = undef;
 
1314
          }
 
1315
          else {
 
1316
            print STDERR "$$hd1->[0] shadowed by $$hd0->[0]\n";
 
1317
            $$hd0->[2] = $v;
 
1318
          }
 
1319
        }
 
1320
      }
 
1321
    }
 
1322
  }
 
1323
 
 
1324
  @hd = grep { defined } @hd;
 
1325
 
 
1326
  for $hd (@hd) {
 
1327
    if(
 
1328
      !defined($hd->[2]) ||
 
1329
      !defined($hd->[2][$he_driver]) ||
 
1330
      !(defined($hd->[2][$he_device_name]) || defined($hd->[2][$he_subdevice_name]))
 
1331
    ) {
 
1332
      undef $hd;
 
1333
      next;
 
1334
    }
 
1335
  }
 
1336
 
 
1337
  @hd = grep { defined } @hd;
 
1338
 
 
1339
}
 
1340
 
 
1341
 
 
1342
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1343
#
 
1344
# remove duplicate entries
 
1345
#
 
1346
 
 
1347
sub remove_duplicatesx
 
1348
{
 
1349
  my ($hd0, $hd1, $len, $i, $j, $m, $v, $buf, $errors, $drop);
 
1350
  local $_;
 
1351
 
 
1352
  $len = @hd;
 
1353
 
 
1354
  for($j = 0; $j < $len; $j++) {
 
1355
    print STDERR ">> $j\r";
 
1356
    $hd0 = \$hd[$j];
 
1357
    for($i = $j + 1; $i < $len; $i++) {
 
1358
      $hd1 = \$hd[$i];
 
1359
      $m = match_item $$hd0, $$hd1;
 
1360
      # print "$$hd0->[0] -- $$hd1->[0]: $m\n";
 
1361
      if($m) {
 
1362
        $drop = cmp_item $$hd0, $$hd1;
 
1363
        $drop = !$drop || abs($drop) == 2 ? ", dropped" : undef;
 
1364
        undef $buf;
 
1365
        $v = join_skey $$hd0->[2], $$hd1->[2], \$buf, \$errors;
 
1366
        if($errors) {
 
1367
          print STDERR "$$hd1->[0] conflicts with $$hd0->[0]$drop:\n$buf\n";
 
1368
          $$hd1 = undef if $drop;
 
1369
        }
 
1370
        else {
 
1371
          if($drop) {
 
1372
            print STDERR "$$hd1->[0] added to $$hd0->[0] and dropped\n";
 
1373
            $$hd0->[2] = $v;
 
1374
            $$hd1 = undef;
 
1375
          }
 
1376
          else {
 
1377
            print STDERR "$$hd1->[0] shadowed by $$hd0->[0]\n";
 
1378
          }
 
1379
        }
 
1380
      }
 
1381
    }
 
1382
  }
 
1383
 
 
1384
  @hd = grep { defined } @hd;
 
1385
}
 
1386
 
 
1387
 
 
1388
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1389
#
 
1390
# fix drive info
 
1391
#
 
1392
 
 
1393
sub fix_driver_info
 
1394
{
 
1395
  my ($hd, $hid, $drv, $i, @i, @info, @req, %req);
 
1396
 
 
1397
  for $hd (@hd) {
 
1398
    if(
 
1399
      !defined($hd->[2]) ||
 
1400
      !defined($hd->[2][$he_driver])
 
1401
    ) {
 
1402
      next;
 
1403
    }
 
1404
    $hid = $hd->[2][$he_driver];
 
1405
    next unless $hid->[0] == $flag_string;
 
1406
 
 
1407
    undef @req;
 
1408
 
 
1409
    for $drv (@$hid[1 .. @$hid - 1]) {
 
1410
      @i = split /\x00/, $drv;
 
1411
      for $i (@i) {
 
1412
        next if $i =~ /^[MX]\t/;
 
1413
        $i =~ s/\|+$//;
 
1414
        next unless $i =~ /^x\t/;
 
1415
        @info = split /\|/, $i;
 
1416
        # remove leasding 'XF86_' from server name
 
1417
        $info[1] =~ s/^XF86_// if $info[1];
 
1418
        # sort package, extension and option lists
 
1419
        push @req, split /,/, $info[3] if $info[3];
 
1420
        # $info[3] = join ',', sort split /,/, $info[3] if $info[3];
 
1421
        $info[3] = undef if $info[3];
 
1422
        $info[4] = join ',', sort split /,/, $info[4] if $info[4];
 
1423
        $info[5] = join ',', sort split /,/, $info[5] if $info[5];
 
1424
        $info[6] = join ',', sort { $a <=> $b } split /,/, $info[6] if $info[6];
 
1425
        $i = join '|', @info;  
 
1426
      }
 
1427
      $drv = join "\x00", @i;
 
1428
      # print ">$drv<\n"
 
1429
    }
 
1430
 
 
1431
    if(@req) {
 
1432
      $hid = $hd->[2][$he_requires];
 
1433
      if($hid) {
 
1434
        if($hid->[0] != $flag_string) {
 
1435
          die "oops, invalid data"
 
1436
        }
 
1437
        push @req, split /\|/, $hid->[1];
 
1438
        $hid->[1] = join '|', @req;
 
1439
      }
 
1440
      else {
 
1441
        $hd->[2][$he_requires] = [ $flag_string, join('|', @req) ];
 
1442
      }
 
1443
    }
 
1444
  }
 
1445
 
 
1446
  for $hd (@hd) {
 
1447
    if(
 
1448
      !defined($hd->[2]) ||
 
1449
      !defined($hd->[2][$he_requires])
 
1450
    ) {
 
1451
      next;
 
1452
    }
 
1453
    $hid = $hd->[2][$he_requires];
 
1454
    next unless $hid->[0] == $flag_string;
 
1455
 
 
1456
    undef @req;
 
1457
    undef %req;
 
1458
 
 
1459
    @req = split /\|/, $hid->[1];
 
1460
    @req{@req} = @req;
 
1461
 
 
1462
    $hid->[1] = join '|', sort keys %req;
 
1463
  }
 
1464
}
 
1465
 
 
1466
 
 
1467
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1468
#
 
1469
# hd: [ "source", [ skey, skey, ... ], [ val ] ]
 
1470
# skey/val: [ ... , id, ..., id, ... ]
 
1471
# id: [ $flag_id, $tag, $value, $range, $mask ]
 
1472
# id: [ $flag_string, "str", "str", ... ]
 
1473
 
 
1474
sub cmp_id
 
1475
{
 
1476
  my ($id0, $id1, $len0, $len1, $len, $i, $k);
 
1477
 
 
1478
  ($id0, $id1) = @_;
 
1479
 
 
1480
  return 0 if !defined($id0) && !defined($id1);
 
1481
  return -1 if !defined($id0);
 
1482
  return 1 if !defined($id1);
 
1483
 
 
1484
  if($id0->[0] != $id1->[0]) {
 
1485
    return $id0->[0] <=> $id1->[0];
 
1486
  }
 
1487
 
 
1488
  $len0 = @$id0;
 
1489
  $len1 = @$id1;
 
1490
  $len = $len0 < $len1 ? $len0 : $len1;
 
1491
 
 
1492
  if($id0->[0] == $flag_string) {
 
1493
    for($i = 1; $i < $len; $i++) {
 
1494
      $k = $id0->[$i] cmp $id1->[$i];
 
1495
      return $k if $k;
 
1496
    }
 
1497
    return $len0 <=> $len1;
 
1498
  }
 
1499
 
 
1500
  if($id0->[0] == $flag_id) {
 
1501
    $k = $id0->[1] <=> $id1->[1];
 
1502
    return $k if $k;
 
1503
    $k = $id0->[2] <=> $id1->[2];
 
1504
    return $k if $k;
 
1505
    $k = $len0 <=> $len1;
 
1506
    return $k if $k || $len <= 3;
 
1507
    # print "-\n";
 
1508
    # $dump->dumpValue( $id0 );
 
1509
    # $dump->dumpValue( $id1 );
 
1510
    # die "internal oops: strange id" if $len < 4;
 
1511
    $i = $len - 1;
 
1512
    return -1 if !defined($id0->[$i]);
 
1513
    return 1 if !defined($id1->[$i]);
 
1514
    return $id0->[$i] <=> $id1->[$i];
 
1515
  }
 
1516
 
 
1517
  die "internal oops: can't compare that!";
 
1518
}
 
1519
 
 
1520
 
 
1521
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1522
#
 
1523
sub cmp_skey
 
1524
{
 
1525
  my ($skey0, $skey1, $len0, $len1, $len, $i, $k);
 
1526
 
 
1527
  ($skey0, $skey1) = @_;
 
1528
 
 
1529
  return 0 if !defined($skey0) && !defined($skey1);
 
1530
  return -1 if !defined($skey0);
 
1531
  return 1 if !defined($skey1);
 
1532
 
 
1533
  $len0 = @$skey0;
 
1534
  $len1 = @$skey1;
 
1535
  $len = $len0 < $len1 ? $len0 : $len1;
 
1536
 
 
1537
  # $dump->dumpValue( $skey0 );
 
1538
  # $dump->dumpValue( $skey1 );
 
1539
 
 
1540
  for($i = 0; $i < $len; $i++) {
 
1541
    next unless defined($skey0->[$i]) || defined($skey1->[$i]);
 
1542
 
 
1543
    # note: this looks reversed, but is intentional!
 
1544
    return 1 if !defined($skey0->[$i]);
 
1545
    return -1 if !defined($skey1->[$i]);
 
1546
 
 
1547
    $k = cmp_id $skey0->[$i], $skey1->[$i];
 
1548
 
 
1549
    return $k if $k;
 
1550
  }
 
1551
 
 
1552
  return $len0 <=> $len1;
 
1553
}
 
1554
 
 
1555
 
 
1556
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1557
#
 
1558
#   0: equal
 
1559
# +-1: differing keys
 
1560
# +-2: differing values
 
1561
#
 
1562
sub cmp_item
 
1563
{
 
1564
  my ($item0, $item1, $len0, $len1, $len, $i, $k);
 
1565
 
 
1566
  ($item0, $item1) = @_;
 
1567
 
 
1568
  $cmp_item_cnt++;
 
1569
 
 
1570
  return 0 if !defined($item0) && !defined($item1);
 
1571
  return -1 if !defined($item0);
 
1572
  return 1 if !defined($item1);
 
1573
 
 
1574
  $len0 = @{$item0->[1]};
 
1575
  $len1 = @{$item1->[1]};
 
1576
  $len = $len0 < $len1 ? $len0 : $len1;
 
1577
 
 
1578
#  $dump->dumpValue( $item0 );
 
1579
 
 
1580
  for($i = 0; $i < $len; $i++) {
 
1581
    return -1 if !defined($item0->[1][$i]);
 
1582
    return 1 if !defined($item1->[1][$i]);
 
1583
    $k = cmp_skey $item0->[1][$i], $item1->[1][$i];
 
1584
    # print "  skey: $k\n";
 
1585
    return $k if $k;
 
1586
  }
 
1587
  $k = $len0 <=> $len1;
 
1588
  return $k if $k;
 
1589
 
 
1590
  return 0 if !defined($item0->[2]) && !defined($item1->[2]);
 
1591
  return -2 if !defined($item0->[2]);
 
1592
  return 2 if !defined($item1->[2]);
 
1593
 
 
1594
  $k = cmp_skey $item0->[2], $item1->[2];
 
1595
  # print "  val: $k\n";
 
1596
  return 2 * $k;
 
1597
}
 
1598
 
 
1599
 
 
1600
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1601
#
 
1602
# check if id1 is part of id0
 
1603
#
 
1604
# return:
 
1605
#   1: yes
 
1606
#   0: no
 
1607
#   undef: don't know
 
1608
#
 
1609
# hd: [ "source", [ skey, skey, ... ], [ val ] ]
 
1610
# skey/val: [ ... , id, ..., id, ... ]
 
1611
# id: [ $flag_id, $tag, $value, $range, $mask ]
 
1612
# id: [ $flag_string, "str", "str", ... ]
 
1613
 
 
1614
sub match_id
 
1615
{
 
1616
  my ($id0, $id1, $len0, $len1, $len, $i, $k);
 
1617
 
 
1618
  ($id0, $id1) = @_;
 
1619
 
 
1620
  return 0 if !defined($id0) || !defined($id1);
 
1621
 
 
1622
  return 0 if $id0->[0] != $id1->[0];
 
1623
 
 
1624
  $len0 = @$id0;
 
1625
  $len1 = @$id1;
 
1626
  $len = $len0 < $len1 ? $len0 : $len1;
 
1627
 
 
1628
  if($id0->[0] == $flag_string) {
 
1629
    for($i = 1; $i < $len; $i++) {
 
1630
      return 0 if $id0->[$i] cmp $id1->[$i];
 
1631
    }
 
1632
    return $len0 != $len1 ? 0 : 1;
 
1633
  }
 
1634
 
 
1635
  if($id0->[0] == $flag_id) {
 
1636
    return 0 if $id0->[1] != $id1->[1];
 
1637
    if($len1 == 3) {
 
1638
      if($len0 == 3) {
 
1639
        return $id0->[2] != $id1->[2] ? 0 : 1;
 
1640
      }
 
1641
      elsif($len0 == 4) {
 
1642
        return $id1->[2] >= $id0->[2] && $id1->[2] < $id0->[2] + $id0->[3] ? 1 : 0;
 
1643
      }
 
1644
      elsif($len0 == 5) {
 
1645
        return ($id1->[2] & ~$id0->[4]) == $id0->[2] ? 1 : 0;
 
1646
      }
 
1647
      else {
 
1648
        die "invalid id";
 
1649
      }
 
1650
    }
 
1651
    elsif($len1 == 4) {
 
1652
      return undef;
 
1653
    }
 
1654
    elsif($len1 == 5) {
 
1655
      return undef;
 
1656
    }
 
1657
    else {
 
1658
      die "invalid id";
 
1659
    }
 
1660
  }
 
1661
 
 
1662
  die "internal oops: can't match that!";
 
1663
}
 
1664
 
 
1665
 
 
1666
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1667
#
 
1668
# skey1 part of skey0?
 
1669
#
 
1670
sub match_skey
 
1671
{
 
1672
  my ($skey0, $skey1, $len0, $len1, $len, $i, $k);
 
1673
 
 
1674
  ($skey0, $skey1) = @_;
 
1675
 
 
1676
  return 0 if !defined($skey0) || !defined($skey1);
 
1677
 
 
1678
  $len0 = @$skey0;
 
1679
  $len1 = @$skey1;
 
1680
 
 
1681
  $len = $len0 > $len1 ? $len0 : $len1;
 
1682
 
 
1683
  # $dump->dumpValue( $skey0 );
 
1684
  # $dump->dumpValue( $skey1 );
 
1685
 
 
1686
  for($i = 0; $i < $len; $i++) {
 
1687
    next unless defined($skey1->[$i]);
 
1688
 
 
1689
    return 0 if !defined($skey0->[$i]) && defined($skey1->[$i]);
 
1690
 
 
1691
    $k = match_id $skey0->[$i], $skey1->[$i];
 
1692
 
 
1693
    return $k if !$k;
 
1694
  }
 
1695
 
 
1696
  return 1;
 
1697
}
 
1698
 
 
1699
 
 
1700
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1701
#
 
1702
# item1 part of item0?
 
1703
#
 
1704
sub match_item
 
1705
{
 
1706
  my ($item0, $item1, $len0, $len1, $i, $j, $k, $m);
 
1707
 
 
1708
  ($item0, $item1) = @_;
 
1709
 
 
1710
  $match_item_cnt++;
 
1711
 
 
1712
  return 0 if !defined($item0) || !defined($item1);
 
1713
 
 
1714
  $len0 = @{$item0->[1]};
 
1715
  $len1 = @{$item1->[1]};
 
1716
 
 
1717
  for($j = 0; $j < $len1; $j++) {
 
1718
    for($i = 0; $i < $len0; $i++) {
 
1719
      $k = match_skey $item0->[1][$i], $item1->[1][$j];
 
1720
      $m = $k if defined $k;
 
1721
      return $k if $k;
 
1722
    }
 
1723
  }
 
1724
 
 
1725
  return $m
 
1726
}
 
1727
 
 
1728
 
 
1729
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1730
#
 
1731
# add skey1 to skey0
 
1732
#
 
1733
sub join_skey
 
1734
{
 
1735
  my ($skey0, $skey1, $len, $i, $k, $n, $buf, $err);
 
1736
 
 
1737
  ($skey0, $skey1, $buf, $errors) = @_;
 
1738
 
 
1739
  $$errors = 0;
 
1740
 
 
1741
  return undef if !defined($skey0) && !defined($skey1);
 
1742
  return [ @$skey0 ] if !defined($skey1);
 
1743
  return [ @$skey1 ] if !defined($skey0);
 
1744
 
 
1745
  $n = [ @$skey0 ];
 
1746
 
 
1747
  $len = @$skey1;
 
1748
 
 
1749
  for($i = 0; $i < $len; $i++) {
 
1750
    next unless defined $skey1->[$i];
 
1751
 
 
1752
    $n->[$i] = $skey1->[$i];
 
1753
 
 
1754
    next unless defined $skey0->[$i];
 
1755
 
 
1756
    $k = cmp_id $skey0->[$i], $skey1->[$i];
 
1757
 
 
1758
    if($k) {
 
1759
      if(defined $buf) {
 
1760
        if($i != $he_driver) {
 
1761
          $$buf .= ent_name_pr("  0:", $ent_names[$i]);
 
1762
          $$buf .= id_dump($i, $skey0->[$i]) . "\n";
 
1763
          $$buf .= ent_name_pr("  1:", $ent_names[$i]);
 
1764
          $$buf .= id_dump($i, $skey1->[$i]) . "\n";
 
1765
        }
 
1766
        else {
 
1767
          $$buf .= drv_dump("  0:", $skey0->[$i]);
 
1768
          $$buf =~ s/\n&/\n  0:/;
 
1769
          $$buf .= drv_dump("  1:", $skey1->[$i]);
 
1770
          $$buf =~ s/\n&/\n  1:/;
 
1771
        }
 
1772
      }
 
1773
      $$errors++ if defined $errors;
 
1774
    }
 
1775
  }
 
1776
 
 
1777
  return $n;
 
1778
}
 
1779
 
 
1780
 
 
1781
 
 
1782
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1783
#
 
1784
# split key fields
 
1785
#
 
1786
sub split_item
 
1787
{
 
1788
  my ($item, @items, $tmp);
 
1789
  local $_;
 
1790
 
 
1791
  $item = shift;
 
1792
 
 
1793
  return $item if !defined($item) || !defined($item->[1]);
 
1794
 
 
1795
  for (@{$item->[1]}) {
 
1796
    $tmp = [ @$item ];
 
1797
    $tmp->[1] = [ $_ ];
 
1798
    push @items, $tmp;
 
1799
  }
 
1800
 
 
1801
  return @items;
 
1802
}
 
1803
 
 
1804
 
 
1805
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
1806
 
 
1807
sub get_xml_data
 
1808
{
 
1809
  my ($xml, $i, $j);
 
1810
 
 
1811
  $xml = shift;
 
1812
 
 
1813
  if($xml->[0] ne 'hwdata') {
 
1814
    die "invalid XML root element (expected 'hwdata')\n"
 
1815
  }
 
1816
 
 
1817
  for($i = 1; $i < @{$xml->[1]}; $i += 2) {
 
1818
    if($xml->[1][$i] eq 'item') {
 
1819
      push @hd, parse_xml_item($xml->[1][$i + 1]);
 
1820
    }
 
1821
  }
 
1822
}
 
1823
 
 
1824
 
 
1825
sub parse_xml_item
 
1826
{
 
1827
  my (@xml, %attr, $i, $item);
 
1828
 
 
1829
  @xml = @{$_[0]};
 
1830
  %attr = %{shift @xml};
 
1831
 
 
1832
  for($i = 0; $i < @xml; $i += 2) {
 
1833
    if($xml[$i] eq 'key') {
 
1834
      push @{$item->[1]}, parse_xml_key($xml[$i + 1]);
 
1835
    }
 
1836
    else {
 
1837
      $item->[2] = parse_xml_key($_[0]);
 
1838
    }
 
1839
  }
 
1840
 
 
1841
  return $item;
 
1842
}
 
1843
 
 
1844
 
 
1845
sub parse_xml_key
 
1846
{
 
1847
  my (@xml, %attr, $i, @key, $val, $id, $is_id, $keyid, $keyid2, $tmp);
 
1848
 
 
1849
  @xml = @{$_[0]};
 
1850
  %attr = %{shift @xml};
 
1851
 
 
1852
  for($i = 0; $i < @xml; $i += 2) {
 
1853
    next if $xml[$i] eq '0' || $xml[$i] eq 'key';
 
1854
    
 
1855
    $keyid = $xml_values{$xml[$i]};
 
1856
    $is_id = $keyid < $he_nomask && $ent_names[$keyid] =~ /\.(id|name)$/ ? 1 : 0;
 
1857
 
 
1858
    if(!defined($keyid)) {
 
1859
      die "invalid key element \"$xml[$i]\"\n";
 
1860
    }
 
1861
 
 
1862
    if($keyid == $he_driver) {
 
1863
      $id = parse_xml_driver($xml[$i + 1]);
 
1864
      if(!defined($key[$keyid])) {
 
1865
        $key[$keyid] = $id;
 
1866
      }
 
1867
      else {
 
1868
        push @{$key[$keyid]}, $id->[1];
 
1869
      }
 
1870
    }
 
1871
    elsif($is_id) {
 
1872
      $id = parse_xml_id($xml[$i + 1]);
 
1873
      if($id->[0] == $flag_id) {
 
1874
        $tmp = $ent_names[$keyid];
 
1875
        $tmp =~ s/\.name$/.id/;
 
1876
        $keyid2 = $ent_values{$tmp};
 
1877
        if(!defined($keyid2)) {
 
1878
          die "oops, no .id for $xml[$i]?";
 
1879
        }
 
1880
      }
 
1881
      else {
 
1882
        $tmp = $ent_names[$keyid];
 
1883
        $tmp =~ s/\.id$/.name/;
 
1884
        $keyid2 = $ent_values{$tmp};
 
1885
        if(!defined($keyid2)) {
 
1886
          die "oops, no .name for $xml[$i]?";
 
1887
        }
 
1888
      }
 
1889
      $key[$keyid2] = $id;
 
1890
    }
 
1891
    else {
 
1892
      $val = parse_xml_cdata($xml[$i + 1]);
 
1893
      if(defined($key[$keyid]) && $keyid == $he_requires) {
 
1894
        $key[$keyid][1] .= "|$val";
 
1895
      }
 
1896
      else {
 
1897
        $key[$keyid] = [ $flag_string, $val ];
 
1898
      }
 
1899
    }
 
1900
  }
 
1901
 
 
1902
  return [ @key ];
 
1903
}
 
1904
 
 
1905
 
 
1906
sub parse_xml_id
 
1907
{
 
1908
  my (@xml, %attr, $i, $id, $val);
 
1909
 
 
1910
  @xml = @{$_[0]};
 
1911
  %attr = %{shift @xml};
 
1912
 
 
1913
  for($i = 0; $i < @xml; $i += 2) {
 
1914
    next if $xml[$i] eq '0';
 
1915
 
 
1916
    if($xml[$i] eq 'id') {
 
1917
      $id = parse_xml_id_id($xml[$i + 1]);
 
1918
    }
 
1919
    elsif($xml[$i] eq 'idrange') {
 
1920
      $id = parse_xml_id_range($xml[$i + 1]);
 
1921
    }
 
1922
    elsif($xml[$i] eq 'idmask') {
 
1923
      $id = parse_xml_id_mask($xml[$i + 1]);
 
1924
    }
 
1925
    elsif($xml[$i] eq 'name') {
 
1926
      $val = parse_xml_cdata($xml[$i + 1]);
 
1927
      $id = [ $flag_string, $val ];
 
1928
    }
 
1929
    else {
 
1930
      die "invalid id element \"$xml[$i]\"\n";
 
1931
    }
 
1932
  }
 
1933
 
 
1934
  return $id;
 
1935
}
 
1936
 
 
1937
 
 
1938
sub parse_xml_id_id
 
1939
{
 
1940
  my (@xml, %attr, $i, $tag, $value);
 
1941
 
 
1942
  @xml = @{$_[0]};
 
1943
  %attr = %{shift @xml};
 
1944
 
 
1945
  $tag = $tag_values{$attr{type}};
 
1946
 
 
1947
  if(!defined($tag)) {
 
1948
    die "missing/unsupported id attribute \"$attr{type}\"\n";
 
1949
  }
 
1950
 
 
1951
  for($i = 0; $i < @xml; $i += 2) {
 
1952
    if($xml[$i] eq '0') {
 
1953
      $value = idstr2value $tag, $xml[$i + 1];
 
1954
    }
 
1955
    else {
 
1956
      die "cdata expected, got \"$xml[$i]\"\n";
 
1957
    }
 
1958
  }
 
1959
 
 
1960
  return [ $flag_id, $tag, $value ];
 
1961
}
 
1962
 
 
1963
 
 
1964
sub parse_xml_id_range
 
1965
{
 
1966
  my (@xml, %attr, $i, $tag, $value, $range);
 
1967
 
 
1968
  @xml = @{$_[0]};
 
1969
  %attr = %{shift @xml};
 
1970
 
 
1971
  $tag = $tag_values{$attr{type}};
 
1972
 
 
1973
  if(!defined($tag)) {
 
1974
    die "missing/unsupported id attribute \"$attr{type}\"\n";
 
1975
  }
 
1976
 
 
1977
  for($i = 0; $i < @xml; $i += 2) {
 
1978
    next if $xml[$i] eq '0';
 
1979
    if($xml[$i] eq 'first') {
 
1980
      $value = idstr2value $tag, parse_xml_cdata($xml[$i + 1]);
 
1981
    }
 
1982
    elsif($xml[$i] eq 'last') {
 
1983
      $range = idstr2value $tag, parse_xml_cdata($xml[$i + 1]);
 
1984
    }
 
1985
    else {
 
1986
      die "invalid idrange element \"$xml[$i]\"\n";
 
1987
    }
 
1988
  }
 
1989
 
 
1990
  if(!defined($value) || !defined($range)) {
 
1991
    die "invalid idrange\n";
 
1992
  }
 
1993
 
 
1994
  return [ $flag_id, $tag, $value, $range - $value + 1 ];
 
1995
}
 
1996
 
 
1997
 
 
1998
sub parse_xml_id_mask
 
1999
{
 
2000
  my (@xml, %attr, $i, $tag, $value, $mask);
 
2001
 
 
2002
  @xml = @{$_[0]};
 
2003
  %attr = %{shift @xml};
 
2004
 
 
2005
  $tag = $tag_values{$attr{type}};
 
2006
 
 
2007
  if(!defined($tag)) {
 
2008
    die "missing/unsupported id attribute \"$attr{type}\"\n";
 
2009
  }
 
2010
 
 
2011
  for($i = 0; $i < @xml; $i += 2) {
 
2012
    next if $xml[$i] eq '0';
 
2013
    if($xml[$i] eq 'value') {
 
2014
      $value = idstr2value $tag, parse_xml_cdata($xml[$i + 1]);
 
2015
    }
 
2016
    elsif($xml[$i] eq 'mask') {
 
2017
      $mask = idstr2value $tag, parse_xml_cdata($xml[$i + 1]);
 
2018
    }
 
2019
    else {
 
2020
      die "invalid idmask element \"$xml[$i]\"\n";
 
2021
    }
 
2022
  }
 
2023
 
 
2024
  if(!defined($value) || !defined($mask)) {
 
2025
    die "invalid idmask\n";
 
2026
  }
 
2027
 
 
2028
  return [ $flag_id, $tag, $value, undef, $mask ];
 
2029
}
 
2030
 
 
2031
 
 
2032
sub parse_xml_driver
 
2033
{
 
2034
  my (@xml, %attr, $i, $val);
 
2035
 
 
2036
  @xml = @{$_[0]};
 
2037
  %attr = %{shift @xml};
 
2038
 
 
2039
  for($i = 0; $i < @xml; $i += 2) {
 
2040
    next if $xml[$i] eq '0';
 
2041
 
 
2042
    if($xml[$i] eq 'any') {
 
2043
      $val = "a\t" . parse_xml_cdata($xml[$i + 1]);
 
2044
    }
 
2045
    elsif($xml[$i] eq 'display') {
 
2046
      $val = parse_xml_driver_display($xml[$i + 1]);
 
2047
    }
 
2048
    elsif($xml[$i] eq 'module') {
 
2049
      $val = parse_xml_driver_module($xml[$i + 1]);
 
2050
    }
 
2051
    elsif($xml[$i] eq 'mouse') {
 
2052
      $val = parse_xml_driver_mouse($xml[$i + 1]);
 
2053
    }
 
2054
    elsif($xml[$i] eq 'xfree') {
 
2055
      $val = parse_xml_driver_xfree($xml[$i + 1]);
 
2056
    }
 
2057
    else {
 
2058
      die "invalid driver element \"$xml[$i]\"\n";
 
2059
    }
 
2060
  }
 
2061
 
 
2062
  return [ $flag_string, $val ];
 
2063
}
 
2064
 
 
2065
 
 
2066
sub parse_xml_driver_display
 
2067
{
 
2068
  my (@xml, %attr, $i, @val);
 
2069
 
 
2070
  @xml = @{$_[0]};
 
2071
  %attr = %{shift @xml};
 
2072
 
 
2073
  for($i = 0; $i < @xml; $i += 2) {
 
2074
    next if $xml[$i] eq '0';
 
2075
 
 
2076
    if($xml[$i] eq 'resolution') {
 
2077
      $val[0] = join('x', parse_xml_pair($xml[$i + 1], 'width', 'height'));
 
2078
    }
 
2079
    elsif($xml[$i] eq 'vsync') {
 
2080
      $val[1] = join('-', parse_xml_pair($xml[$i + 1], 'min', 'max'));
 
2081
    }
 
2082
    elsif($xml[$i] eq 'hsync') {
 
2083
      $val[2] = join('-', parse_xml_pair($xml[$i + 1], 'min', 'max'));
 
2084
    }
 
2085
    elsif($xml[$i] eq 'bandwidth') {
 
2086
      $val[3] = parse_xml_cdata($xml[$i + 1]);
 
2087
    }
 
2088
    else {
 
2089
      die "invalid display element \"$xml[$i]\"\n";
 
2090
    }
 
2091
  }
 
2092
 
 
2093
  if(!@val) {
 
2094
    die "invalid display info\n";
 
2095
  }
 
2096
 
 
2097
  return "d\t" . join('|', @val);
 
2098
}
 
2099
 
 
2100
 
 
2101
sub parse_xml_driver_module
 
2102
{
 
2103
  my (@xml, %attr, $i, $val, $type, @conf, @mods);
 
2104
 
 
2105
  @xml = @{$_[0]};
 
2106
  %attr = %{shift @xml};
 
2107
 
 
2108
  for($i = 0; $i < @xml; $i += 2) {
 
2109
    next if $xml[$i] eq '0';
 
2110
 
 
2111
    $val = parse_xml_cdata($xml[$i + 1]);
 
2112
 
 
2113
    if($xml[$i] eq 'modprobe') {
 
2114
      if($type && $type ne 'm') {
 
2115
        die "invalid module info: \"$xml[$i]\"\n";
 
2116
      }
 
2117
      $type = 'm';
 
2118
      push @mods, $val;
 
2119
    }
 
2120
    elsif($xml[$i] eq 'insmod') {
 
2121
      if($type && $type ne 'i') {
 
2122
        die "invalid module info: \"$xml[$i]\"\n";
 
2123
      }
 
2124
      $type = 'i';
 
2125
      push @mods, $val;
 
2126
    }
 
2127
    elsif($xml[$i] eq 'modconf') {
 
2128
      if($type && $type ne 'm') {
 
2129
        die "invalid module info: \"$xml[$i]\"\n";
 
2130
      }
 
2131
      push @conf, "\x00M\t$val";
 
2132
    }
 
2133
    else {
 
2134
      die "invalid module element \"$xml[$i]\"\n";
 
2135
    }
 
2136
  }
 
2137
 
 
2138
  if(!$type && !@mods) {
 
2139
    die "invalid module info\n";
 
2140
  }
 
2141
 
 
2142
  $val = "$type\t" . join('|', @mods);
 
2143
 
 
2144
  if(@conf) {
 
2145
    $val .= join('', @conf);
 
2146
  }
 
2147
 
 
2148
  return $val;
 
2149
}
 
2150
 
 
2151
 
 
2152
sub parse_xml_driver_mouse
 
2153
{
 
2154
  my (@xml, %attr, $i, $val, @val);
 
2155
 
 
2156
  @xml = @{$_[0]};
 
2157
  %attr = %{shift @xml};
 
2158
 
 
2159
  for($i = 0; $i < @xml; $i += 2) {
 
2160
    next if $xml[$i] eq '0';
 
2161
 
 
2162
    $val = parse_xml_cdata($xml[$i + 1]);
 
2163
 
 
2164
    if($xml[$i] eq 'xf86') {
 
2165
      $val[0] = $val;
 
2166
    }
 
2167
    elsif($xml[$i] eq 'gpm') {
 
2168
      $val[1] = $val;
 
2169
    }
 
2170
    elsif($xml[$i] eq 'buttons') {
 
2171
      $val[2] = $val;
 
2172
    }
 
2173
    elsif($xml[$i] eq 'wheels') {
 
2174
      $val[3] = $val;
 
2175
    }
 
2176
    else {
 
2177
      die "invalid mouse element \"$xml[$i]\"\n";
 
2178
    }
 
2179
  }
 
2180
 
 
2181
  if(!@val) {
 
2182
    die "invalid mouse info\n";
 
2183
  }
 
2184
 
 
2185
  return "p\t" . join('|', @val);
 
2186
}
 
2187
 
 
2188
 
 
2189
sub parse_xml_driver_xfree
 
2190
{
 
2191
  my (@xml, %attr, $i, $val, @val, @conf);
 
2192
 
 
2193
  @xml = @{$_[0]};
 
2194
  %attr = %{shift @xml};
 
2195
 
 
2196
  for($i = 0; $i < @xml; $i += 2) {
 
2197
    next if $xml[$i] eq '0';
 
2198
 
 
2199
    if($xml[$i] eq 'has3d') {
 
2200
      $val[2] = '3d';
 
2201
    }
 
2202
    else {
 
2203
      $val = parse_xml_cdata($xml[$i + 1]);
 
2204
 
 
2205
      if($xml[$i] eq 'version') {
 
2206
        $val[0] = $val;
 
2207
      }
 
2208
      elsif($xml[$i] eq 'server') {
 
2209
        $val[1] = $val;
 
2210
      }
 
2211
      elsif($xml[$i] eq 'extension') {
 
2212
        $val[4] .= "," if defined $val[4];
 
2213
        $val[4] .= $val;
 
2214
      }
 
2215
      elsif($xml[$i] eq 'option') {
 
2216
        $val[5] .= "," if defined $val[5];
 
2217
        $val[5] .= $val;
 
2218
      }
 
2219
      elsif($xml[$i] eq 'bpp') {
 
2220
        $val[6] .= "," if defined $val[6];
 
2221
        $val[6] .= $val;
 
2222
      }
 
2223
      elsif($xml[$i] eq 'dacspeed') {
 
2224
        $val[7] = $val;
 
2225
      }
 
2226
      elsif($xml[$i] eq 'script') {
 
2227
        $val[8] = $val;
 
2228
      }
 
2229
      elsif($xml[$i] eq 'xf86conf') {
 
2230
        push @conf, "\x00X\t$val";
 
2231
      }
 
2232
      else {
 
2233
        die "invalid xfree element \"$xml[$i]\"\n";
 
2234
      }
 
2235
    }
 
2236
  }
 
2237
 
 
2238
  if(!@val) {
 
2239
    die "invalid xfree info\n";
 
2240
  }
 
2241
 
 
2242
  $val = "x\t" . join('|', @val);
 
2243
 
 
2244
  if(@conf) {
 
2245
    $val .= join('', @conf);
 
2246
  }
 
2247
 
 
2248
  return $val;
 
2249
}
 
2250
 
 
2251
 
 
2252
sub parse_xml_pair
 
2253
{
 
2254
  my (@xml, %attr, $i, $val0, $val1, $elem0, $elem1);
 
2255
 
 
2256
  $elem0 = $_[1];
 
2257
  $elem1 = $_[2];
 
2258
 
 
2259
  @xml = @{$_[0]};
 
2260
  %attr = %{shift @xml};
 
2261
 
 
2262
  for($i = 0; $i < @xml; $i += 2) {
 
2263
    next if $xml[$i] eq '0';
 
2264
    if($xml[$i] eq $elem0) {
 
2265
      $val0 = parse_xml_cdata($xml[$i + 1]);
 
2266
    }
 
2267
    elsif($xml[$i] eq $elem1) {
 
2268
      $val1 = parse_xml_cdata($xml[$i + 1]);
 
2269
    }
 
2270
    else {
 
2271
      die "invalid element \"$xml[$i]\"\n";
 
2272
    }
 
2273
  }
 
2274
 
 
2275
  if(!defined($val0) || !defined($val1)) {
 
2276
    die "invalid element\n";
 
2277
  }
 
2278
 
 
2279
  return ($val0, $val1);
 
2280
}
 
2281
 
 
2282
 
 
2283
sub parse_xml_cdata
 
2284
{
 
2285
  my (@xml, %attr, $i);
 
2286
 
 
2287
  @xml = @{$_[0]};
 
2288
  %attr = %{shift @xml};
 
2289
 
 
2290
  for($i = 0; $i < @xml; $i += 2) {
 
2291
    if($xml[$i] eq '0') {
 
2292
      return $xml[$i + 1]
 
2293
    }
 
2294
  }
 
2295
}
 
2296
 
 
2297
 
 
2298
sub idstr2value
 
2299
{
 
2300
  my ($tag, $value);
 
2301
 
 
2302
  ($tag, $value) = @_;
 
2303
 
 
2304
  if($tag == $tag_eisa && length($value) == 3 && $value !~ /^[0-9]/) {
 
2305
    $value = eisa_id $value;
 
2306
  }
 
2307
  else {
 
2308
    $value = num $value;
 
2309
  }
 
2310
 
 
2311
  return $value;
 
2312
}
 
2313
 
 
2314
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
2315
 
 
2316
sub ent_name_pr
 
2317
{
 
2318
  my ($str, $len);
 
2319
 
 
2320
  $str = $_[0] . $_[1];
 
2321
 
 
2322
  $len = length $str;
 
2323
 
 
2324
  $str .= "\t";
 
2325
  $len = ($len & ~7) + 8;
 
2326
  $str .= "\t" x ((24 - $len)/8) if $len < 24;
 
2327
  
 
2328
  return $str;
 
2329
}
 
2330
 
 
2331
 
 
2332
sub id_dump
 
2333
{
 
2334
  my ($id, $ent, $str, $tag, $format, $u, $s);
 
2335
 
 
2336
  ($ent, $id) = @_;
 
2337
 
 
2338
  if($id->[0] == $flag_id) {
 
2339
    $tag = $id->[1];
 
2340
    if($ent == $he_hwclass) {
 
2341
      $str = "";
 
2342
      for($u = $id->[2] & 0xffffff; $u; $u >>= 8) {
 
2343
        if(defined $hwclass_names[$u & 0xff]) {
 
2344
          $str .= $hwclass_names[$u & 0xff];
 
2345
          $str .= "|" if $u > 0x100;
 
2346
        }
 
2347
      }
 
2348
    }
 
2349
    elsif($tag == $tag_eisa && ($ent == $he_vendor_id || $ent == $he_subvendor_id)) {
 
2350
      $str = eisa_str $id->[2];
 
2351
    }
 
2352
    else {
 
2353
      $str .= $tag_name[$tag];
 
2354
      $str .= " " if $tag;
 
2355
      $format = "0x%04x";
 
2356
      $format = "0x%02x" if $ent == $he_bus_id || $ent == $he_subclass_id || $ent == $he_progif_id;
 
2357
      $format = "0x%03x" if $ent == $he_baseclass_id;
 
2358
      $str .= sprintf $format, $id->[2];
 
2359
    }
 
2360
    if(defined $id->[3]) {
 
2361
      $str .= sprintf "+0x%04x", $id->[3];
 
2362
    }
 
2363
    elsif(defined $id->[4]) {
 
2364
      $str .= sprintf "&0x%04x", $id->[4];
 
2365
    }
 
2366
  }
 
2367
  elsif($id->[0] == $flag_string) {
 
2368
    if(defined($id->[2])) {
 
2369
      die "oops: strage string data\n";
 
2370
    }
 
2371
    $str = $id->[1];
 
2372
  }
 
2373
  else {
 
2374
    die "oops: unknown id flag\n"
 
2375
  }
 
2376
  
 
2377
  return $str;
 
2378
}
 
2379
 
 
2380
 
 
2381
sub drv_dump
 
2382
{
 
2383
  my ($id, $str, $i, $pre, $type, $drv, $buf);
 
2384
 
 
2385
  ($pre, $id) = @_;
 
2386
 
 
2387
  die "oops: invalid driver data\n" if $id->[0] != $flag_string;
 
2388
 
 
2389
  for($i = 1; $i < @{$id}; $i++) {
 
2390
    for $drv (split /\x00/, $id->[$i]) {
 
2391
      $type = substr $drv, 0, 2;
 
2392
 
 
2393
      if($type eq "x\t") {
 
2394
        $buf .= ent_name_pr($pre, $ent_names[$he_driver_xfree]);
 
2395
        $buf .= substr($drv, 2) . "\n";
 
2396
      }
 
2397
      elsif($type eq "X\t") {
 
2398
        $buf .= ent_name_pr($pre, $ent_names[$he_driver_xfree_config]);
 
2399
        $buf .= substr($drv, 2) . "\n";
 
2400
      }
 
2401
      elsif($type eq "i\t") {
 
2402
        $buf .= ent_name_pr($pre, $ent_names[$he_driver_module_insmod]);
 
2403
        $buf .= substr($drv, 2) . "\n";
 
2404
      }
 
2405
      elsif($type eq "m\t") {
 
2406
        $buf .= ent_name_pr($pre, $ent_names[$he_driver_module_modprobe]);
 
2407
        $buf .= substr($drv, 2) . "\n";
 
2408
      }
 
2409
      elsif($type eq "M\t") {
 
2410
        $buf .= ent_name_pr($pre, $ent_names[$he_driver_module_config]);
 
2411
        $buf .= substr($drv, 2) . "\n";
 
2412
      }
 
2413
      elsif($type eq "p\t") {
 
2414
        $buf .= ent_name_pr($pre, $ent_names[$he_driver_mouse]);
 
2415
        $buf .= substr($drv, 2) . "\n";
 
2416
      }
 
2417
      elsif($type eq "d\t") {
 
2418
        $buf .= ent_name_pr($pre, $ent_names[$he_driver_display]);
 
2419
        $buf .= substr($drv, 2) . "\n";
 
2420
      }
 
2421
      elsif($type eq "a\t") {
 
2422
        $buf .= ent_name_pr($pre, $ent_names[$he_driver_any]);
 
2423
        $buf .= substr($drv, 2) . "\n";
 
2424
      }
 
2425
      else {
 
2426
        die "oops: unhandled driver info type: $drv\n";
 
2427
      }
 
2428
 
 
2429
      $pre = "&" if $pre ne "+";
 
2430
    }
 
2431
  }
 
2432
 
 
2433
  return $buf;
 
2434
}
 
2435
 
 
2436
 
 
2437
sub ent_dump
 
2438
{
 
2439
  my ($pre, $id, $ent, $buf);
 
2440
 
 
2441
  ($buf, $pre, $id) = @_;
 
2442
 
 
2443
  $pre = defined($pre) ? "|" : " " if $pre ne "+";
 
2444
  for($ent = 0; $ent < @{$id}; $ent++) {
 
2445
    if(defined $id->[$ent]) {
 
2446
      if($ent != $he_driver) {
 
2447
        $$buf .= ent_name_pr($pre, $ent_names[$ent]);
 
2448
        $$buf .= id_dump($ent, $id->[$ent]);
 
2449
        $$buf .= "\n";
 
2450
      }
 
2451
      else {
 
2452
        $$buf .= drv_dump($pre, $id->[$ent]);
 
2453
      }
 
2454
      $pre = "&" if $pre ne "+";
 
2455
    }
 
2456
  }
 
2457
 
 
2458
  return $pre;
 
2459
}
 
2460
 
 
2461
 
 
2462
sub dump2ids
 
2463
{
 
2464
  my ($item, $id, $ent, $pre, $buf);
 
2465
 
 
2466
  # $dump->dumpValue( \@hd );
 
2467
 
 
2468
  open F, ">hd.ids";
 
2469
 
 
2470
  for $item (@hd) {
 
2471
    undef $buf;
 
2472
    undef $pre;
 
2473
    print F "# $item->[0]\n" if $opt_with_source;
 
2474
    for $id (@{$item->[1]}) {
 
2475
      $pre = ent_dump \$buf, $pre, $id;
 
2476
    }
 
2477
    $pre = "+";
 
2478
    ent_dump \$buf, $pre, $item->[2];
 
2479
    $buf .= "\n";
 
2480
 
 
2481
    print F $buf;
 
2482
  }
 
2483
 
 
2484
  close F;
 
2485
}
 
2486
 
 
2487
 
 
2488
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
2489
 
 
2490
sub dump2xml
 
2491
{
 
2492
  my ($item, $dtd);
 
2493
 
 
2494
  if($opt_internal_dtd) {
 
2495
    $dtd = hd_dtd_internal;
 
2496
  }
 
2497
  else {
 
2498
    $dtd = "<!DOCTYPE hwdata SYSTEM \"hd.dtd\">\n";
 
2499
  }
 
2500
 
 
2501
  $xml_file = new IO::File(">hd.xml");
 
2502
  $xml = new XML::Writer(OUTPUT => $xml_file, DATA_MODE => 1, DATA_INDENT => 2);
 
2503
 
 
2504
  $xml->xmlDecl("utf-8");
 
2505
 
 
2506
  print $xml_file "\n$dtd";
 
2507
 
 
2508
  $xml->startTag("hwdata");
 
2509
 
 
2510
  print $xml_file "\n";
 
2511
 
 
2512
  for $item (@hd) {
 
2513
    dump_xml_item $item;
 
2514
  }
 
2515
 
 
2516
  $xml->endTag("hwdata");
 
2517
  $xml->end();
 
2518
 
 
2519
  if(!$opt_internal_dtd) {
 
2520
    print STDERR "writing \"hd.dtd\"\n";
 
2521
    open DTD, ">hd.dtd";
 
2522
    print DTD hd_dtd;
 
2523
    close DTD;
 
2524
  }
 
2525
}
 
2526
 
 
2527
 
 
2528
sub dump_xml_id
 
2529
{
 
2530
  my ($ent, $id, $i, $tag, $str, $format, $range, $mask);
 
2531
 
 
2532
  ($ent, $id) = @_;
 
2533
 
 
2534
  $i = $xml_names[$ent];
 
2535
 
 
2536
  die "oops: entry $ent not allowed here\n" unless $i;
 
2537
 
 
2538
  if($ent == $he_requires) {
 
2539
    if($id->[0] == $flag_string) {
 
2540
      die "oops: strange string data\n" if defined $id->[2];
 
2541
      for $str (split /\|/, $id->[1]) {
 
2542
        $xml->dataElement("requires", $str);
 
2543
      }
 
2544
    }
 
2545
    else {
 
2546
      die "oops: requires _id_???\n"
 
2547
    }
 
2548
  }
 
2549
  else {
 
2550
    $xml->startTag($i);
 
2551
 
 
2552
    if($ent == $he_serial) {
 
2553
      if($id->[0] == $flag_string) {
 
2554
        die "oops: strange string data\n" if defined $id->[2];
 
2555
        $xml->characters($id->[1]);
 
2556
      }
 
2557
      else {
 
2558
        die "oops: serial _id_???\n"
 
2559
      }
 
2560
    }
 
2561
    else {
 
2562
      if($id->[0] == $flag_id) {
 
2563
        $tag = $id->[1];
 
2564
        if($tag == $tag_eisa && ($ent == $he_vendor_id || $ent == $he_subvendor_id)) {
 
2565
          $str = eisa_str $id->[2];
 
2566
        }
 
2567
        else {
 
2568
          $format = "0x%04x";
 
2569
          $format = "0x%02x" if $ent == $he_bus_id || $ent == $he_subclass_id || $ent == $he_progif_id;
 
2570
          $format = "0x%03x" if $ent == $he_baseclass_id;
 
2571
          $str = sprintf $format, $id->[2];
 
2572
        }
 
2573
        if(defined $id->[3]) {
 
2574
          if($tag == $tag_eisa && ($ent == $he_vendor_id || $ent == $he_subvendor_id)) {
 
2575
            $range = eisa_str $id->[2] + $id->[3] - 1;
 
2576
          }
 
2577
          else {
 
2578
            $range = sprintf "0x%04x", $id->[2] + $id->[3] - 1;
 
2579
          }
 
2580
        }
 
2581
        elsif(defined $id->[4]) {
 
2582
          $mask = sprintf "0x%04x", $id->[4];
 
2583
        }
 
2584
        $tag = $tag_name[$tag];
 
2585
 
 
2586
        if(defined $range) {
 
2587
          if($tag) {
 
2588
            $xml->startTag("idrange", "type" => $tag);
 
2589
          }
 
2590
          else {
 
2591
            $xml->startTag("idrange");
 
2592
          }
 
2593
          $xml->dataElement("first", $str);
 
2594
          $xml->dataElement("last", $range);
 
2595
          $xml->endTag();
 
2596
        }
 
2597
        elsif(defined $mask) {
 
2598
          if($tag) {
 
2599
            $xml->startTag("idmask", "type" => $tag);
 
2600
          }
 
2601
          else {
 
2602
            $xml->startTag("idmask");
 
2603
          }
 
2604
          $xml->dataElement("value", $str);
 
2605
          $xml->dataElement("mask", $mask);
 
2606
          $xml->endTag();
 
2607
        }
 
2608
        else {
 
2609
          if($tag) {
 
2610
            $xml->dataElement("id", $str, "type" => $tag);
 
2611
          }
 
2612
          else {
 
2613
            $xml->dataElement("id", $str);
 
2614
          }
 
2615
        }
 
2616
      }
 
2617
      elsif($id->[0] == $flag_string) {
 
2618
        die "oops: strage string data\n" if defined $id->[2];
 
2619
        $xml->dataElement("name", $id->[1]);
 
2620
      }
 
2621
      else {
 
2622
        die "oops: unknown id flag\n"
 
2623
      }
 
2624
    }
 
2625
 
 
2626
    $xml->endTag();
 
2627
  }
 
2628
}
 
2629
 
 
2630
 
 
2631
sub dump_xml_drv
 
2632
{
 
2633
  my ($id, $str, $i, $j, $k, $type, $drv, $info, @info, $current);
 
2634
 
 
2635
  $id = shift;
 
2636
 
 
2637
  die "oops: invalid driver data\n" if $id->[0] != $flag_string;
 
2638
 
 
2639
  for($i = 1; $i < @{$id}; $i++) {
 
2640
 
 
2641
    $xml->startTag('driver');
 
2642
 
 
2643
    undef $current;
 
2644
 
 
2645
    for $drv (split /\x00/, $id->[$i]) {
 
2646
      $type = substr $drv, 0, 2;
 
2647
      $info = substr $drv, 2;
 
2648
      @info = split /\|/, $info;
 
2649
 
 
2650
      if($type eq "i\t") {
 
2651
        $xml->endTag() if $current; $current = $type;
 
2652
        $xml->startTag('module');
 
2653
        for $j (@info) {
 
2654
          $xml->dataElement('insmod', $j);
 
2655
        }
 
2656
      }
 
2657
      elsif($type eq "m\t") {
 
2658
        $xml->endTag() if $current; $current = $type;
 
2659
        $xml->startTag('module');
 
2660
        for $j (@info) {
 
2661
          $xml->dataElement('modprobe', $j);
 
2662
        }
 
2663
      }
 
2664
      elsif($type eq "M\t") {
 
2665
        die "oops: incorrect driver info: $drv\n" unless $current eq "m\t";
 
2666
        $xml->dataElement('modconf', $info);
 
2667
      }
 
2668
      elsif($type eq "a\t") {
 
2669
        $xml->endTag() if $current; $current = undef;;
 
2670
        $xml->dataElement('any', $info);
 
2671
      }
 
2672
      elsif($type eq "d\t") {
 
2673
        $xml->endTag() if $current; $current = undef;
 
2674
        $xml->startTag('display');
 
2675
        if($info[0] =~ /^(\d+)x(\d+)$/) {
 
2676
          ($j, $k) = ($1, $2);
 
2677
          $xml->startTag('resolution');
 
2678
          $xml->dataElement('width', $j);
 
2679
          $xml->dataElement('height', $k);
 
2680
          $xml->endTag('resolution');
 
2681
        }
 
2682
        if($info[1] =~ /^(\d+)-(\d+)$/) {
 
2683
          ($j, $k) = ($1, $2);
 
2684
          $xml->startTag('vsync');
 
2685
          $xml->dataElement('min', $j);
 
2686
          $xml->dataElement('max', $k);
 
2687
          $xml->endTag('vsync');
 
2688
        }
 
2689
        if($info[2] =~ /^(\d+)-(\d+)$/) {
 
2690
          ($j, $k) = ($1, $2);
 
2691
          $xml->startTag('hsync');
 
2692
          $xml->dataElement('min', $j);
 
2693
          $xml->dataElement('max', $k);
 
2694
          $xml->endTag('hsync');
 
2695
        }
 
2696
        if($info[3] =~ /^\d+$/) {
 
2697
          $xml->dataElement('bandwidth', $info[3]);
 
2698
        }
 
2699
        $xml->endTag('display');
 
2700
      }
 
2701
      elsif($type eq "x\t") {
 
2702
        $xml->endTag() if $current; $current = $type;
 
2703
        $xml->startTag('xfree');
 
2704
        if(defined $info[0]) {
 
2705
          $xml->dataElement('version', $info[0]);
 
2706
        }
 
2707
        if($info[1]) {
 
2708
          $xml->dataElement('server', $info[1]);
 
2709
        }
 
2710
        if($info[2]) {
 
2711
          $xml->emptyTag('has3d');
 
2712
        }
 
2713
#        if($info[3]) {
 
2714
#          for $j (split /,/, $info[3]) {
 
2715
#            $xml->dataElement('package', $j);
 
2716
#          }
 
2717
#        }
 
2718
        if($info[4]) {
 
2719
          for $j (split /,/, $info[4]) {
 
2720
            $xml->dataElement('extension', $j);
 
2721
          }
 
2722
        }
 
2723
        if($info[5]) {
 
2724
          for $j (split /,/, $info[5]) {
 
2725
            $xml->dataElement('option', $j);
 
2726
          }
 
2727
        }
 
2728
        if($info[6]) {
 
2729
          for $j (split /,/, $info[6]) {
 
2730
            $xml->dataElement('bpp', $j);
 
2731
          }
 
2732
        }
 
2733
        if($info[7] =~ /^\d+$/) {
 
2734
          $xml->dataElement('dacspeed', $info[7]);
 
2735
        }
 
2736
        if($info[8]) {
 
2737
          $xml->dataElement('script', $info[8]);
 
2738
        }
 
2739
      }
 
2740
      elsif($type eq "X\t") {
 
2741
        die "oops: incorrect driver info: $drv\n" unless $current eq "x\t";
 
2742
        $xml->dataElement('xf86conf', $info);
 
2743
      }
 
2744
      elsif($type eq "p\t") {
 
2745
        $xml->endTag() if $current; $current = undef;
 
2746
        $xml->startTag('mouse');
 
2747
        if($info[0]) {
 
2748
          $xml->dataElement('xf86', $info[0]);
 
2749
        }
 
2750
        if($info[1]) {
 
2751
          $xml->dataElement('gpm', $info[1]);
 
2752
        }
 
2753
        if($info[2] ne "") {
 
2754
          $xml->dataElement('buttons', $info[2]);
 
2755
        }
 
2756
        if($info[3] ne "") {
 
2757
          $xml->dataElement('wheels', $info[3]);
 
2758
        }
 
2759
        $xml->endTag('mouse');
 
2760
      }
 
2761
      else {
 
2762
        $xml->endTag() if $current; $current = undef;
 
2763
        # die "oops: unhandled driver info type: $drv\n";
 
2764
      }
 
2765
    }
 
2766
 
 
2767
    $xml->endTag() if $current;
 
2768
 
 
2769
    $xml->endTag('driver');
 
2770
 
 
2771
  }
 
2772
}
 
2773
 
 
2774
 
 
2775
sub dump_xml_ent
 
2776
{
 
2777
  my ($id, $ent);
 
2778
 
 
2779
  $id = shift;
 
2780
 
 
2781
  for($ent = 0; $ent < @{$id}; $ent++) {
 
2782
    if(defined $id->[$ent]) {
 
2783
      if($ent != $he_driver) {
 
2784
        dump_xml_id $ent, $id->[$ent];
 
2785
      }
 
2786
      else {
 
2787
        dump_xml_drv $id->[$ent];
 
2788
      }
 
2789
    }
 
2790
  }
 
2791
 
 
2792
}
 
2793
 
 
2794
 
 
2795
sub dump_xml_item
 
2796
{
 
2797
  my ($item, $id);
 
2798
 
 
2799
  $item = shift;
 
2800
 
 
2801
  $xml->startTag('item');
 
2802
 
 
2803
  for $id (@{$item->[1]}) {
 
2804
    $xml->startTag('key');
 
2805
    dump_xml_ent $id;
 
2806
    $xml->endTag('key');
 
2807
  }
 
2808
 
 
2809
  dump_xml_ent $item->[2];
 
2810
 
 
2811
  $xml->endTag('item');
 
2812
  print $xml_file "\n";
 
2813
}
 
2814
 
 
2815
 
 
2816
sub hd_dtd
 
2817
{
 
2818
  my $dtd = <<'EOF'
 
2819
<!-- libhd DTD V0.2 -->
 
2820
 
 
2821
<!ENTITY % keyfields "bus|baseclass|subclass|progif|vendor|device|subvendor|subdevice|revision|serial|driver|requires">
 
2822
<!ENTITY % idelements "id|idrange|idmask|name">
 
2823
<!ENTITY % idtypes "none|pci|eisa|usb|pcmcia|special">
 
2824
 
 
2825
<!ELEMENT hwdata (item*)>
 
2826
 
 
2827
<!ELEMENT item (key+,(%keyfields;)*)>
 
2828
 
 
2829
<!ELEMENT key (%keyfields;)+>
 
2830
 
 
2831
  <!ELEMENT bus (%idelements;)>
 
2832
  <!ELEMENT baseclass (%idelements;)>
 
2833
  <!ELEMENT subclass (%idelements;)>
 
2834
  <!ELEMENT progif (%idelements;)>
 
2835
  <!ELEMENT vendor (%idelements;)>
 
2836
  <!ELEMENT device (%idelements;)>
 
2837
  <!ELEMENT subvendor (%idelements;)>
 
2838
  <!ELEMENT subdevice (%idelements;)>
 
2839
  <!ELEMENT revision (%idelements;)>
 
2840
  <!ELEMENT serial (#PCDATA)>
 
2841
  <!ELEMENT requires (#PCDATA)>
 
2842
  <!ELEMENT id (#PCDATA)>
 
2843
  <!ELEMENT idrange (first,last)>
 
2844
    <!ELEMENT first (#PCDATA)>
 
2845
    <!ELEMENT last (#PCDATA)>
 
2846
  <!ELEMENT idmask (value,mask)>
 
2847
    <!ELEMENT value (#PCDATA)>
 
2848
    <!ELEMENT mask (#PCDATA)>
 
2849
  <!ATTLIST id type (%idtypes;) "none">
 
2850
  <!ATTLIST idrange type (%idtypes;) "none">
 
2851
  <!ATTLIST idmask type (%idtypes;) "none">
 
2852
  <!ELEMENT name (#PCDATA)>
 
2853
 
 
2854
<!ELEMENT driver (any|display|module|mouse|xfree)?>
 
2855
 
 
2856
  <!ELEMENT any (#PCDATA)>
 
2857
 
 
2858
  <!ELEMENT display (resolution?,vsync?,hsync?,bandwidth?)>
 
2859
    <!ELEMENT resolution (width,height)>
 
2860
      <!ELEMENT width (#PCDATA)>
 
2861
      <!ELEMENT height (#PCDATA)>
 
2862
    <!ELEMENT vsync (min,max)>
 
2863
    <!ELEMENT hsync (min,max)>
 
2864
      <!ELEMENT min (#PCDATA)>
 
2865
      <!ELEMENT max (#PCDATA)>
 
2866
    <!ELEMENT bandwidth (#PCDATA)>
 
2867
 
 
2868
  <!ELEMENT module (insmod+|(modprobe+,modconf*))>
 
2869
    <!ELEMENT insmod (#PCDATA)>
 
2870
    <!ELEMENT modprobe (#PCDATA)>
 
2871
    <!ELEMENT modconf (#PCDATA)>
 
2872
 
 
2873
  <!ELEMENT mouse (xf86?,gpm?,buttons?,wheels?)>
 
2874
    <!ELEMENT xf86 (#PCDATA)>
 
2875
    <!ELEMENT gpm (#PCDATA)>
 
2876
    <!ELEMENT buttons (#PCDATA)>
 
2877
    <!ELEMENT wheels (#PCDATA)>
 
2878
 
 
2879
  <!ELEMENT xfree (version,server?,has3d?,extension*,option*,bpp*,dacspeed?,script?,xf86conf*)>
 
2880
    <!ELEMENT version (#PCDATA)>
 
2881
    <!ELEMENT server (#PCDATA)>
 
2882
    <!ELEMENT has3d EMPTY>
 
2883
    <!ELEMENT extension (#PCDATA)>
 
2884
    <!ELEMENT option (#PCDATA)>
 
2885
    <!ELEMENT bpp (#PCDATA)>
 
2886
    <!ELEMENT dacspeed (#PCDATA)>
 
2887
    <!ELEMENT script (#PCDATA)>
 
2888
    <!ELEMENT xf86conf (#PCDATA)>
 
2889
EOF
 
2890
;
 
2891
 
 
2892
  return $dtd;
 
2893
}
 
2894
 
 
2895
 
 
2896
sub hd_dtd_internal
 
2897
{
 
2898
  my $dtd = <<'EOF'
 
2899
<!DOCTYPE hwdata [
 
2900
  <!ELEMENT hwdata (item*)>
 
2901
  <!ELEMENT item (key+,(bus|baseclass|subclass|progif|vendor|device|subvendor|subdevice|revision|serial|driver|requires)*)>
 
2902
    <!ELEMENT key (bus|baseclass|subclass|progif|vendor|device|subvendor|subdevice|revision|serial|driver|requires)+>
 
2903
      <!ELEMENT bus (id|idrange|idmask|name)>
 
2904
      <!ELEMENT baseclass (id|idrange|idmask|name)>
 
2905
      <!ELEMENT subclass (id|idrange|idmask|name)>
 
2906
      <!ELEMENT progif (id|idrange|idmask|name)>
 
2907
      <!ELEMENT vendor (id|idrange|idmask|name)>
 
2908
      <!ELEMENT device (id|idrange|idmask|name)>
 
2909
      <!ELEMENT subvendor (id|idrange|idmask|name)>
 
2910
      <!ELEMENT subdevice (id|idrange|idmask|name)>
 
2911
      <!ELEMENT revision (id|idrange|idmask|name)>
 
2912
      <!ELEMENT serial (#PCDATA)>
 
2913
      <!ELEMENT requires (#PCDATA)>
 
2914
      <!ELEMENT id (#PCDATA)>
 
2915
      <!ELEMENT idrange (first,last)>
 
2916
        <!ELEMENT first (#PCDATA)>
 
2917
        <!ELEMENT last (#PCDATA)>
 
2918
      <!ELEMENT idmask (value,mask)>
 
2919
        <!ELEMENT value (#PCDATA)>
 
2920
        <!ELEMENT mask (#PCDATA)>
 
2921
      <!ATTLIST id type (none|pci|eisa|usb|pcmcia|special) "none">
 
2922
      <!ATTLIST idrange type (none|pci|eisa|usb|special) "none">
 
2923
      <!ATTLIST idmask type (none|pci|eisa|usb|special) "none">
 
2924
    <!ELEMENT name (#PCDATA)>
 
2925
    <!ELEMENT driver (any|display|module|mouse|xfree)?>
 
2926
      <!ELEMENT any (#PCDATA)>
 
2927
      <!ELEMENT display (resolution?,vsync?,hsync?,bandwidth?)>
 
2928
        <!ELEMENT resolution (width,height)>
 
2929
          <!ELEMENT width (#PCDATA)>
 
2930
          <!ELEMENT height (#PCDATA)>
 
2931
        <!ELEMENT vsync (min,max)>
 
2932
        <!ELEMENT hsync (min,max)>
 
2933
          <!ELEMENT min (#PCDATA)>
 
2934
          <!ELEMENT max (#PCDATA)>
 
2935
        <!ELEMENT bandwidth (#PCDATA)>
 
2936
      <!ELEMENT module (insmod+|(modprobe+,modconf*))>
 
2937
        <!ELEMENT insmod (#PCDATA)>
 
2938
        <!ELEMENT modprobe (#PCDATA)>
 
2939
        <!ELEMENT modconf (#PCDATA)>
 
2940
      <!ELEMENT mouse (xf86?,gpm?,buttons?,wheels?)>
 
2941
        <!ELEMENT xf86 (#PCDATA)>
 
2942
        <!ELEMENT gpm (#PCDATA)>
 
2943
        <!ELEMENT buttons (#PCDATA)>
 
2944
        <!ELEMENT wheels (#PCDATA)>
 
2945
      <!ELEMENT xfree (version,server?,has3d?,extension*,option*,bpp*,dacspeed?,script?,xf86conf*)>
 
2946
        <!ELEMENT version (#PCDATA)>
 
2947
        <!ELEMENT server (#PCDATA)>
 
2948
        <!ELEMENT has3d EMPTY>
 
2949
        <!ELEMENT extension (#PCDATA)>
 
2950
        <!ELEMENT option (#PCDATA)>
 
2951
        <!ELEMENT bpp (#PCDATA)>
 
2952
        <!ELEMENT dacspeed (#PCDATA)>
 
2953
        <!ELEMENT script (#PCDATA)>
 
2954
        <!ELEMENT xf86conf (#PCDATA)>
 
2955
]> 
 
2956
EOF
 
2957
;
 
2958
 
 
2959
  return $dtd;
 
2960
}
 
2961