summaryrefslogtreecommitdiff
path: root/cesar/common/tools/config-merge
blob: fff4702fd6c79f3a8ec9443981160094b2612270 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/perl
#
# Read a project configuration and modules configurations and merge them to
# stdout.
#
use strict;
use warnings;
use Getopt::Long qw(:config no_ignore_case bundling);

# Option parsing.
sub help
{
    die <<EOF;
$0 - merge project and modules configuration to stdout.
Syntax: $0 [options] build_type build_type_var project_config module_configs...

Options:
  -u, --ignore-unknown-identifier   do not stop on unknown identifier
EOF
}
my $help;
my $ignore_unknown_identifier = 0;
GetOptions (
    'help|h' => \$help,
    'ignore-unknown-identifier|u' => \$ignore_unknown_identifier,
) or help ();
help () if $help;
help () if @ARGV < 3;

sub type
{
    my $val = shift;
    $val =~ /^[yn]$/ and return 'yn';
    $val =~ /^[0-9]+$/ and return '09';
    $val =~ /^"[^"]*"$/ and return '""';
}

# All configuration items with default values or values from project config.
my %conf;
# Set to overridden level (0: globally set, 1: build type set).
my %conf_set;

# Get build type.
my $build_type = shift;
my $build_type_var = shift;

# Put project config at end of list.
my $proj = shift;
push @ARGV, $proj;

# First read modules configs and populate %conf.  Then read project config.
while (<>)
{
    chomp;
    next if /^\s*#/;
    next if /^$/;
    if (/^\s* ([A-Z0-9_]+) # Item identifier.
	\s* (?:\[([a-z0-9-]+)\])? # Optional build type selector.
	\s* =
	\s* ([yn]|[0-9]+|"[^"]*") # Value.
	\s*$/x)
    {
	my ($var, $selector, $val) = ($1, $2, $3);
	$var =~ /^CONFIG_[A-Z0-9_]*[A-Z0-9]$/
	    or die "$ARGV:$.:unaccepted identifier \"$var\"\n";
	if (scalar @ARGV == 0)
	{
	    # Project config.
	    defined $selector && $selector ne $build_type
		and next;
	    if (exists $conf{$var})
	    {
		type ($val) eq type ($conf{$var})
		    or die "$ARGV:$.:bad type for \"$var\"\n";
		my $overriden = defined $selector;
		!exists $conf_set{$var} || $conf_set{$var} < $overriden
		    or die "$ARGV:$.:\"$var\" already set\n";
		$conf_set{$var} = $overriden;
	    }
	    else
	    {
		$ignore_unknown_identifier
		    or die "$ARGV:$.:unknown identifier \"$var\"\n";
	    }
	}
	else
	{
	    # Module config.
	    defined $selector
		and die "$ARGV:$.:selector in module config\n";
	    !exists $conf{$var}
		or die "$ARGV:$.:duplicated identifier \"$var\"\n";
	}
	$conf{$var} = $val;
	next;
    }
    die "$ARGV:$.:unrecognized line\n";
} continue {
    close ARGV if eof;
}

# Output merged config.
print "${build_type_var}_$_ = $conf{$_}\n" for (sort keys %conf);

# Output config items list.
print "${build_type_var}_CONFIG_ITEMS = "
    . join (' ', sort keys %conf) . "\n";