]> mj.ucw.cz Git - libucw.git/blob - build/genconf
Merge with git+ssh://git.ucw.cz/projects/sherlock/GIT/sherlock.git#v3.12
[libucw.git] / build / genconf
1 #!/usr/bin/perl
2 # Configuration file and script preprocessor
3 # (c) 2004--2007 Martin Mares <mj@ucw.cz>
4
5 use strict;
6 use warnings;
7
8 @ARGV == 3 or die "Usage: genconf <src> <dest> <config.mk>";
9
10 open CF, $ARGV[2] or die "Unable to open $ARGV[2]";
11 my %options = ();
12 my %vars = ();
13 sub opt {
14         my ($k,$v) = @_;
15         $vars{$k} = $v;
16         $options{$k} = 1 if ($k =~ /^CONFIG_/);
17 }
18 foreach my $k (keys %ENV) {
19         opt($k, $ENV{$k});
20 }
21 while (<CF>) {
22         chomp;
23         if (my ($k,$v) = /^(\w+)=(.*)/) {
24                 $v =~ s/\s+$//;
25                 opt($k, $v);
26         }
27 }
28 close CF;
29
30 sub eval_expr {
31         $_ = shift @_;
32         s/\b(CONFIG_\w+)\b/defined($options{$1}) ? 1 : 0/ge;
33         return eval $_;
34 }
35
36 open IN, $ARGV[0] or die "Unable to open $ARGV[0]";
37 open OUT, ">$ARGV[1]" or die "Unable to create $ARGV[1]";
38 my @ifs = ();   # stack of conditions, 1=satisfied, -1=unsatisfied, 0=shadowed
39 my $empty = 0;  # last line was empty
40 while (<IN>) {
41         if (/^#ifdef\s+(\w+)/) {
42                 push @ifs, (@ifs && $ifs[$#ifs] <= 0) ? 0 : (defined $options{$1}) ? 1 : -1;
43         } elsif (/^#ifndef\s+(\w+)/) {
44                 push @ifs, (@ifs && $ifs[$#ifs] <= 0) ? 0 : (defined $options{$1}) ? -1 : 1;
45         } elsif (/^#if\s(.*)$/) {
46                 push @ifs, (@ifs && $ifs[$#ifs] <= 0) ? 0 : (eval_expr $1) ? 1 : -1;
47         } elsif (/^#endif/) {
48                 defined pop @ifs || die "Improper nesting of conditionals";
49         } elsif (/^#else/) {
50                 my $x = pop @ifs;
51                 defined $x || die "Improper nesting of conditionals";
52                 push @ifs, $x >= 0 ? 0 : 1;
53         } elsif (/^#elsif\s(.*)$/) {
54                 my $x = pop @ifs;
55                 defined $x || die "Improper nesting of conditionals";
56                 push @ifs, $x >= 0 ? 0 : (eval_expr $1) ? 1 : -1;
57         } else {
58                 @ifs && $ifs[$#ifs] <= 0 && next;
59                 if (/^$/) {
60                         $empty && next;
61                         $empty = 1;
62                 } else { $empty = 0; }
63                 if (/^#pipe\s+(.+)/) {
64                         my $cmd = $1;
65                         my $val = `$cmd`;
66                         die "Piped command '$cmd' failed" if $?;
67                         print OUT `$1`;
68                 } else {
69                         sub repl ($) {
70                                 my $v = shift @_;
71                                 exists $vars{$v} or die "Cannot substitute $v: variable not set";
72                                 return $vars{$v};
73                         }
74                         s/@(\w+)@/repl($1)/ge;
75                         print OUT;
76                 }
77         }
78 }
79 @ifs && die "Unterminated #ifdef";
80 close IN;
81 close OUT;