chiark / gitweb /
pull-mail: New script to encapsulate what my crontab needs to do to pull
[bin.git] / expandvars
1 #! /usr/bin/perl -w
2 use strict;
3 use Getopt::Long;
4
5 sub usage ()
6 {
7     print STDERR <<"EOF";
8 Usage: $0 [options] source-filename
9 EOF
10     print STDERR <<'EOF';
11 where options are:
12
13   -h, -?, --help            print this message
14   -c,     --conf FILENAME   use FILENAME as configuration file, default
15                             '.headers'
16   -d,     --directory DIR   change to directory DIR
17   -s,     --suffix SUFFIX   use SUFFIX for all output filenames, default null
18
19 The configuration file is of the following form:
20
21 # Comments are preceded by hashes and extend to the end of the line.
22 # List of names of parameters to be substituted (as $param1$, $param2$,
23 # etc.) in order.
24 param1 param2 ...
25
26 # Multiple records, one per line.
27 # Each record consists of an output filename (automatically used as the value
28 # of the name parameter; suffix will be added if present) followed by a list of
29 # parameter values. Fields are space-separated. Double quotes (") may be used
30 # to delimit fields containing spaces, and double quotes themselves may be
31 # escaped with backslashes.
32
33 EOF
34     exit;
35 }
36
37 my %opts = (conf => '.headers', directory => '', suffix => '');
38 GetOptions(\%opts, 'help|h|?', 'conf|c=s', 'directory|d=s', 'suffix|s=s');
39 my $source = shift;
40 usage unless defined $source;
41
42 usage if $opts{'help'};
43 chdir $opts{'directory'} if $opts{'directory'};
44 open CONF, $opts{'conf'} or
45     die "Can't open configuration file " . $opts{'conf'} . ": $!";
46 -r $source or die "Can't read source file $source: $!";
47
48 my @params;
49 while (<CONF>)
50 {
51     next if /^#/ || /^\s+/;
52     @params = split;
53     last;
54 }
55
56 usage unless @params;
57
58 # Eek. This matches the next (optionally double-quoted) string on the line.
59 my $stringre = qr/\s*("(?:[^\\]|\\.)*?"|(?:[^\\]|\\.)+?)(?:\s|$)/;
60 while (<CONF>)
61 {
62     next if /^#/ || /^\s+/;
63     my $confline = $_;
64     next unless $confline =~ /$stringre/g;
65     my $target = $1;
66     my %values = (name => $target);
67     my @conffields = ($confline =~ /\G$stringre/g);
68     my $offset = 0;
69     for (my $i = 0; $i + $offset <= $#params && $i <= $#conffields; $i++)
70     {
71         $offset++ while $params[$i + $offset] eq 'name';
72         last if $i + $offset > $#params;
73         my $value = $conffields[$i];
74         $value =~ s/^"(.*)"$/$1/;
75         $value =~ s/\\(.)/$1/g;
76         $values{$params[$i + $offset]} = $value;
77     }
78
79     # Do the substitution in the source file.
80     open SOURCE, $source or die "Can't open source file $source: $!";
81     open TARGET, ">$target" . $opts{'suffix'} or
82         die "Can't open target file $target" . $opts{'suffix'} . ": $!";
83     select TARGET;
84     while (<SOURCE>)
85     {
86         foreach my $param (keys %values)
87         {
88             my $value = $values{$param};
89             s/\$\Q$param\E\$/$value/g;
90         }
91         s/\$\$/\$/g;
92         print;
93     }
94     select STDOUT;
95     close TARGET;
96 }
97