#! /usr/bin/perl -w use diagnostics; use strict; use Getopt::Long; sub usage () { print STDERR <<"EOF"; Usage: $0 [options] source-filename EOF print STDERR <<'EOF'; where options are: -h, -?, --help print this message -c, --conf FILENAME use FILENAME as configuration file, default '.headers' -d, --directory DIR change to directory DIR -s, --suffix SUFFIX use SUFFIX for all output filenames, default null The configuration file is of the following form: # Comments are preceded by hashes and extend to the end of the line. # List of names of parameters to be substituted (as $param1$, $param2$, # etc.) in order. param1 param2 ... # Multiple records, one per line. # Each record consists of an output filename (automatically used as the value # of the name parameter; suffix will be added if present) followed by a list of # parameter values. Fields are space-separated. Double quotes (") may be used # to delimit fields containing spaces, and double quotes themselves may be # escaped with backslashes. EOF exit; } my %opts = (conf => '.headers', directory => '', suffix => ''); GetOptions(\%opts, 'help|h|?', 'conf|c=s', 'directory|d=s', 'suffix|s=s'); my $source = shift; usage unless defined $source; usage if $opts{'help'}; chdir $opts{'directory'} if $opts{'directory'}; open CONF, $opts{'conf'} or die "Can't open configuration file " . $opts{'conf'} . ": $!"; -r $source or die "Can't read source file $source: $!"; my @params; while () { next if /^#/ || /^\s+/; @params = split; last; } usage unless defined @params && $#params >= 0; # Eek. This matches the next (optionally double-quoted) string on the line. my $stringre = qr/\s*("(?:[^\\]|\\.)*?"|(?:[^\\]|\\.)+?)(?:\s|$)/; while () { next if /^#/ || /^\s+/; my $confline = $_; next unless $confline =~ /$stringre/g; my $target = $1; my %values = (name => $target); my @conffields = ($confline =~ /\G$stringre/g); my $offset = 0; for (my $i = 0; $i + $offset <= $#params && $i <= $#conffields; $i++) { $offset++ while $params[$i + $offset] eq 'name'; last if $i + $offset > $#params; my $value = $conffields[$i]; $value =~ s/^"(.*)"$/$1/; $value =~ s/\\(.)/$1/g; $values{$params[$i + $offset]} = $value; } # Do the substitution in the source file. open SOURCE, $source or die "Can't open source file $source: $!"; open TARGET, ">$target" . $opts{'suffix'} or die "Can't open target file $target" . $opts{'suffix'} . ": $!"; select TARGET; while () { foreach my $param (keys %values) { my $value = $values{$param}; s/\$\Q$param\E\$/$value/g; } s/\$\$/\$/g; print; } select STDOUT; close TARGET; }