#
# Usage:
#
-# perl configure.pl [configfile1 configfile2 ...] < input_file > output_file
+# perl configure.pl configfile1 configfile2 ... < input_file > output_file
+#
+# perl configure.pl --option1 ... name=value ... configfile1 configfile2 ... --input inputfile1 inputfile2 ... --output outputfile1 outputfile2
#
# Or './configure.pl' instead of 'perl configure.pl' but then we're making
# the assumption that Perl is installed at '/usr/bin/perl'.
# go there. Instead I can handle this on the level of the makefile (which
# is configurable by configure.pl)
#
-# The script reads configuration from all files given in the command line
-# parameters. The effect is similar to reading a single concatenated file.
-#
-# Then it reads standard input line by line.
+# There are 3 types of commandline parameters:
+# * in form 'name=value' where 'name' is a valid setting name (described
+# further below): this setting will be loaded from commandline directly
+# (and literally - no processing) before reading any configuration files
+# * starting from '--': these are options:
+# * --d, --debug - will print debug information to standard error
+# * --da, --debugall, --debug_all - as above but will also include debug
+# information produced after finished processing the config files
+# * --l, --list - will print the final list of all settings to standard
+# error
+# * --la, --listall, --list_all - as above but will include settings not
+# available for applying in files (starting with '_')
+# * --i, --in, --input - all further file paths are for input files
+# * --o, --out, --output - all further file paths are for output files
+# * -- - all further file paths are for configuration files
+# * anything else will be treated as a path to a file: input, output,
+# or configuration. By default configuration files are expected.
+#
+# The script reads configuration from all configuration iles given in the
+# command line parameters. The effect is similar to reading a single
+# concatenated file.
+#
+# Configuration files are read once and in the same order as the command line
+# parameters.
+#
+# Settings provided directly in command line are read before the files. So the
+# files can override such settings.
+#
+# Next, input files are read, converted, and saved to output files.
+#
+# The input and output files are procesed in the same order as the command line
+# parameters. First input file is converted to first output file and so on.
+# If there are more output files than input files, then the extra output
+# files will not be written.
+# If there are less output files than input files, then instead of the missing
+# files the standard output is used.
+# If there are no input files, then instead the standard input is used (as if
+# it was 1 file)
+#
+# It reads input line by line.
# In each line it looks for replacement patterns, replaces them if found,
# and prints the line to the output.
#
-# Configuration files are read once in the same order as the command line
-# parameters.
-#
# Whenever I write 'whitespace' I mean it can space '' or TAB '\t'.
#
# It is possible to include files like this:
use constant URL_ENCODE => '_URL_ENCODE';
use constant PATH => '_PATH';
use constant SPRINTF => '_SPRINTF';
-use constant DEBUG => '_LIST';
-use constant DEBUG_ALL => '_LIST_ALL';
-use constant DEBUG_TEXT => '_DEBUG';
# TODO more special functions
my %cfg;
+my @config_files;
+my @input_files;
+my @output_files;
+my $debug_enabled = 0;
+my $debug_all = 0;
+my $list = 0;
+my $list_all = 0;
+my $file_type = '';
+
$cfg{REPLACE_LINE()} = DEFAULT_REPLACE_LINE;
$cfg{REPLACE_KEYWORD()} = DEFAULT_REPLACE_KEYWORD;
$cfg{PATH_SEPARATOR()} = DEFAULT_PATH_SEPARATOR;
-my $debug_text = "DEBUG:\n";
-my $debug_enabled = 1;
foreach my $arg (@ARGV) {
- %cfg = parse_file($arg, 0, %cfg);
+ if ($arg =~ /^--(.*)$/) { # option
+ $arg = $1;
+ if ($arg =~ /^d(ebug)?$/) {
+ $debug_enabled = 1;
+ }
+ elsif ($arg =~ /^(da)|(debug_?all)$/) {
+ $debug_enabled = 1;
+ $debug_all = 1;
+ }
+ elsif ($arg =~ /^l(ist)?$/) {
+ $list = 1;
+ }
+ elsif ($arg =~ /^(la)|(list-?all)$/) {
+ $list = 1;
+ $list_all = 1;
+ }
+ elsif ($arg =~ /^i(n(put)?)?$/) {
+ $file_type = 'i';
+ }
+ elsif ($arg =~ /^o(ut(put)?)?$/) {
+ $file_type = 'o';
+ }
+ elsif ($arg eq '') {
+ $file_type = '';
+ }
+ }
+ elsif ($arg =~ /^([A-Za-z0-9_\-\.]+)=(.*)$/) { # predefined setting
+ $cfg{$1} = $2;
+ }
+ else { # file
+ if ($file_type eq 'i') {
+ push @input_files, $arg;
+ }
+ elsif ($file_type eq 'o') {
+ push @output_files, $arg;
+ }
+ else {
+ push @config_files, $arg;
+ }
+ }
+}
+
+foreach my $file (@config_files) {
+ %cfg = parse_file($file, 0, %cfg);
+}
+unless ($debug_all) {
+ $debug_enabled = 0;
}
-$debug_enabled = 0;
my %replace_line;
my %replace_keyword;
my $match_keyword;
foreach my $key (keys %cfg) {
- if ($debug_all ne ''){
- $debug_all .= "\n";
- }
- $debug_all .= "$key: $cfg{$key}";
+ my $print_this = $list_all;
unless((substr($key,0,1) eq '_') or ($key =~ /^[0-9]+$/)){
- if ($debug ne ''){
- $debug .= "\n";
- }
- $debug .= "$key: $cfg{$key}";
+ $print_this = ($list or $list_all);
$match_line = parse_pattern(REPLACE_LINE(), "($key)", 0, %cfg);
$match_keyword = parse_pattern(REPLACE_KEYWORD(), "($key)", 0, %cfg);
$replace_line{$match_line} = $cfg{$key};
$replace_keyword{$match_keyword} = $cfg{$key};
}
+ if ($print_this) {
+ print STDERR format_cfg($key, $cfg{$key});
+ }
+}
+
+if (@input_files == 0) {
+ push @input_files, '';
}
-$match_line = parse_pattern(REPLACE_LINE(), '('.DEBUG().')', 0, %cfg);
-$match_keyword = parse_pattern(REPLACE_KEYWORD(), '('.DEBUG().')', 0, %cfg);
-$replace_line{$match_line} = $debug;
-$replace_keyword{$match_keyword} = $debug;
-$match_line = parse_pattern(REPLACE_LINE(), '('.DEBUG_ALL().')', 0, %cfg);
-$match_keyword = parse_pattern(REPLACE_KEYWORD(), '('.DEBUG_ALL().')', 0, %cfg);
-$replace_line{$match_line} = $debug_all;
-$replace_keyword{$match_keyword} = $debug_all;
-$match_line = parse_pattern(REPLACE_LINE(), '('.DEBUG_TEXT().')', 0, %cfg);
-$match_keyword = parse_pattern(REPLACE_KEYWORD(), '('.DEBUG_TEXT().')', 0, %cfg);
-$replace_line{$match_line} = $debug_text;
-$replace_keyword{$match_keyword} = $debug_text;
-my $status;
-LINE: while (defined(my $line = <STDIN>)) {
- $line =~ s/[\r\n]//g;
- foreach my $key (keys %replace_line) {
- if (index($line, $key) >= 0) {
- print "$replace_line{$key}\n";
- next LINE;
- }
- }
- foreach my $key (keys %replace_keyword) {
- do {
- ($status, $line) = replace($line, $key, $replace_keyword{$key});
- } while ($status);
- }
- print "$line\n";
+
+while (@input_files > 0) {
+ my $in = shift @input_files;
+ my $out = shift @output_files;
+ convert_file($in, $out);
+}
+
+sub format_cfg {
+ (my $name, my $value) = @_;
+ $value =~ s/\n/\n /g;
+ return $name.': '.$value."\n";
}
# replace WITHOUT REGEXP
sub print_debug {
(my $depth, my $text) = @_;
if ($debug_enabled) {
- $debug_text .= (' 'x$depth).$text."\n";
+ # $debug_text .= (' 'x$depth).$text."\n";
+ print STDERR (' 'x$depth).$text."\n";
}
}
return %cfg;
}
+
+sub convert_file {
+ (my $in, my $out) = @_;
+
+ my $ref_in = ref($in);
+ my $ref_out = ref($out);
+
+ if ($in eq '') {
+ $in = \*STDIN;
+ $ref_in = 1;
+ }
+ if ($out eq '') {
+ $out = \*STDOUT;
+ $ref_out = 1;
+ }
+
+ unless ($ref_in) {
+ my $path = $in;
+ $in = undef;
+ unless (open $in, '<', $path) {
+ print STDERR "Cannot open input file $path.\n";
+ exit 2;
+ }
+ }
+ unless ($ref_out) {
+ my $path = $out;
+ $out = undef;
+ unless (open $out, '>', $path) {
+ print STDERR "Cannot open input file $path.\n";
+ unless ($ref_in) {
+ close($in)
+ }
+ exit 2;
+ }
+ }
+
+ my $status;
+ LINE: while (defined(my $line = <$in>)) {
+ $line =~ s/[\r\n]//g;
+ foreach my $key (keys %replace_line) {
+ if (index($line, $key) >= 0) {
+ print "$replace_line{$key}\n";
+ next LINE;
+ }
+ }
+ foreach my $key (keys %replace_keyword) {
+ do {
+ ($status, $line) = replace($line, $key, $replace_keyword{$key});
+ } while ($status);
+ }
+ print $out "$line\n";
+ }
+
+ unless ($ref_out) {
+ close($out);
+ }
+ unless ($ref_in) {
+ close($in);
+ }
+}