#!/usr/bin/perl -w
# Usages:
-# ./farnell-find.pl NNN-NNNN
+# ./farnell-find.pl [<options>] NNN-NNNN
# Prints info about the specified relevant part.
-# ./farnell-find.pl <file> [<sort>...]
-# Processes input file <file> and sorts output according to
-# <sort> (several may be specified). <sort>s can be `desc'
-# `avail' `price' (first mentioned is most significant.
-# Default sort order is `avail price desc'.
+# ./farnell-find.pl [<options>] <file> ...
+# Processes input files and produces BOM parts list.
+# Options:
+# -S<sort>
+# Specifies sort order for BOM. Several may be specified, first
+# one on the command line is least significant. Can be `desc'
+# `avail' `price'. Default sort order is avail, then price,
+# then desc (equivalent to -Sdesc -Sprice -Savail).
#
# Input format: lines, #-comments, blank lines ignored.
# Indent level is relevant, but only 0, 1, >1 relevant.
# is <desc prefix> with a space and the remainder of the part
# name appended.
# end
-# Ends the file. Mandatory.
+# Ends the file. Optional.
use strict;
use POSIX;
use IO::Handle;
+use IO::File;
our(@warn);
our(@fault);
# $parts{"$circuit\n$sper"}[]{Part} or item
# $parts{"$circuit\n$sper"}[]{Qty}
# $parts{"$circuit\n$sper"}[]{Use}
-# $parts{"$circuit\n$sper"}[]{LineNo}
+# $parts{"$circuit\n$sper"}[]{FileLine}
our(%partdef);
# $partdef{"part name"}= $item;
# $iteminstances{$item}[]{Use} includes circuit
# $iteminstances{$item}[]{Qty}
# $iteminstances{$item}[]{Mult} number of this iteratable
-# $iteminstances{$item}[]{LineNo}
+# $iteminstances{$item}[]{FileLine}
our(%itemdesc);
# $itemdesc{$item}[]= $desc;
return $1;
}
-sub read_spec () {
+sub read_spec ($) {
+ my ($filename) = @_;
local ($_);
my ($circuit,$iteratable,$desc);
- my ($part,$qty,$use);
+ my ($part,$qty,$use,$f);
+ $f= new IO::File $filename, 'r' or die "$filename: $!\n";
for (;;) {
- $!=0; $_=<F>; die unless defined $_;
+ $_=<$f>;
+ die "$filename: read: $!\n" if $f->error;
+ last unless defined $_;
chomp; s/\s+$//;
last if m/^end$/;
next if m/^\#/ || !m/\S/;
($part,$qty,$use) = ($1,$2,$3);
$qty .= $partfrac_unique++ if $qty =~ m,/$,;
push @{ $parts{"$circuit\n$iteratable"} }, {
- Part => $part, Qty => $qty, Use => $use, LineNo => $.
- };
+ Part => $part, Qty => $qty, Use => $use,
+ FileLine => "$filename:$."
+ };
} elsif (m/^($part_re)\s+\?\s+\=\s+(\S.*)$/) {
die if exists $pkinddesc{$1};
$pkinddesc{$1}= $2;
die "$_ ?";
}
}
+ $f->close;
}
sub itemsortmap ($) {
} elsif ($how eq 'avail') {
$o .= $bi->{Avail};
} else {
- die "unknown sort option \`$o'\n";
+ die;
}
}
return $o;
} elsif (exists $partdef{$part}) {
$item= $partdef{$part};
} else {
- push @fault, "unknown part $part (line $pe->{LineNo})";
+ push @fault, "unknown part $part ($pe->{FileLine})";
next;
}
push @{ $iteminstances{$item} }, {
Use => $use,
Qty => $pe->{Qty},
Mult => $count,
- LineNo => $pe->{LineNo}
+ FileLine => $pe->{FileLine}
};
}
}
$desclen= 42;
foreach $item (sort keys %iteminstances) {
$why= defined $itemdesc{$item} ? $itemdesc{$item}[0].'; ' : '';
- $why .= "line ".(join ",", map { $_->{LineNo} }
- @{ $iteminstances{$item} });
+ $why .= join ",", map { $_->{FileLine} } @{ $iteminstances{$item} };
$bi= by_item($item, $why);
$iteminfo{$item}= $bi;
}
foreach $item (keys %iteminstances) {
$totalqty= { };
foreach $ii (@{ $iteminstances{$item} }) {
- addqty($totalqty, $ii->{Qty}, $ii->{Mult}, $item, $ii->{LineNo});
+ addqty($totalqty, $ii->{Qty}, $ii->{Mult}, $item, $ii->{FileLine});
}
$bi= $iteminfo{$item};
next unless $bi;
die "errors\n" if @fault;
}
+@sorthow= qw(avail price desc);
+
+while (@ARGV && $ARGV[0] =~ m/^\-/) {
+ $_= shift @ARGV;
+ last if m/^\-\-$/;
+ if (m/^\-S(avail|price|desc)$/) {
+ unshift @sorthow, $1;
+ } else {
+ die "unknown option \`$_'\n";
+ }
+}
+
if (@ARGV==1 && $ARGV[0] =~ m/^\d\d\d\-/) {
my ($chr, $k);
$chr= by_item($ARGV[0]);
foreach $k (sort keys %$chr) {
printf "%-20s %s\n", $k, $chr->{$k} or die $!;
}
-} elsif (@ARGV>=1) {
+} elsif (@ARGV) {
my ($filename);
- ($filename, @sorthow) = @ARGV;
- push @sorthow, qw(avail price desc);
- open F, "< $filename" or die $!;
- read_spec();
- close F or die $!;
+ foreach $filename (@ARGV) {
+ read_spec($filename);
+ }
analyse_spec();
exit !!@fault;
} else {