1#!/usr/bin/perl
2
3require 'getopts.pl';
4
5my $debug = 0;
6
7Getopts('dc:p:o:') || die "foo";
8
9if ($opt_d) {
10    $debug = 1;
11}
12
13die "missing arg" if (!defined $opt_c || !defined $opt_p || !defined $opt_o);
14
15my %defines;
16my $IN;
17my $OUT;
18
19print "parse config.h\n" if ($debug);
20
21open IN, $opt_c || die "failed open ${opt_c}";
22
23my @nesting;
24
25push @nesting, 1;
26
27while (<IN>) {
28    if (m/\s*#ifdef\s+(.*)/) {
29	my $var = $1;
30	if (defined $defines{$var}) {
31	    push @nesting, 1;
32	} else {
33	    push @nesting, 0;
34	}
35	next;
36    } elsif (m/\s*#ifndef\s+(.*)/) {
37	my $var = $1;
38	if (defined $defines{$var}) {
39	    push @nesting, 0;
40	} else {
41	    push @nesting, 1;
42	}
43	next;
44    } elsif (m/\s*#else/) {
45	my $var = pop @nesting;
46	$var = !$var;
47	push @nesting, $var;
48	next;
49    } elsif ($nesting[$#nesting] and m/\s*#define\s+(\w+)\s+(\S+)/) {
50	my $res = $2;
51	$res = 1 if (!defined $res);
52	$defines{$1} = $res;
53    }
54}
55
56close IN;
57
58if ($debug) {
59    foreach my $i (keys %defines) {
60	print "k: $i v: $defines{$i}\n";
61    }
62}
63
64open IN, "$opt_p" || die "failed open ${opt_p}";
65open OUT, ">$opt_o" || die "failed open ${opt_o}";
66
67print "parse roken.h.in\n" if ($debug);
68
69print OUT "/* This is an OS dependent, generated file */\n";
70print OUT "\n";
71print OUT "\n";
72print OUT "#ifndef __ROKEN_H__\n";
73print OUT "#define __ROKEN_H__\n";
74print OUT "\n";
75
76@nesting = (1);
77
78while (<IN>) {
79    if (m/\s*#ifdef\s+(.*)/) {
80	my $var = $1;
81	if (defined $defines{$var}) {
82	    push @nesting, 1;
83	} else {
84	    push @nesting, 0;
85	}
86	next;
87    } elsif (m/\s*#ifndef\s+(.*)/) {
88	my $var = $1;
89	if (defined $defines{$var}) {
90	    push @nesting, 0;
91	} else {
92	    push @nesting, 1;
93	}
94	next;
95    } elsif (m/\s*#if\s+(.*)/) {
96	my $res = parse_if($1);
97	print "line = $res: $1\n" if ($debug);
98	push @nesting, $res;
99	next;
100    } elsif (m/\s*#elif\s+(.*)/) {
101	my $res = pop @nesting;
102	if ($res gt 0) {
103	    $res = -1;
104	} else {
105	    my $res = parse_if($1);
106	}
107	push @nesting, $res;
108	next;
109    } elsif (m/\s*#else/) {
110	my $var = pop @nesting;
111	$var = !$var;
112	push @nesting, $var;
113	next;
114    } elsif (m/\s*#endif/) {
115	pop @nesting;
116	next;
117    }
118    print "line: $_\n"  if ($debug);
119    print "nesting dep $#{nesting}\n"  if ($debug);
120    my $i = 0, $t = 1;
121    while ($i le $#nesting) {
122	$t = 0 if ($nesting[$i] le 0);
123	print "nesting $i val $nesting[$i] -> $t\n" if ($debug);
124	$i++;
125    }
126    if ($t) {
127	print OUT;
128    }
129}
130
131print OUT "\n";
132print OUT "#endif /* __ROKEN_H__ */\n";
133
134
135close IN;
136
137exit 0;
138
139sub parse_if
140{
141    my ($neg, $var);
142
143    $_ = shift;
144
145    if (m/^\s*$/) {
146	print "end $_\n" if ($debug);
147	return 1;
148    } elsif (m/^([^&]+)\&\&(.*)$/) {
149	print "$1 and $2\n" if ($debug);
150	return parse_if($1) and parse_if($2);
151    } elsif (m/^([^\|]+)\|\|(.*)$/) {
152	print "$1 or $2\n" if ($debug);
153	return parse_if($1) or parse_if($2);
154    } elsif (m/^\s*(\!)?\s*defined\((\w+)\)/) {
155	($neg, $var) = ($1, $2);
156	print "def: ${neg}-defined(${var})\n" if ($debug);
157	my $res = defined $defines{$var};
158	if ($neg eq "!") {
159	    if ($res) {
160		$res = 0;
161	    } else {
162		$res = 1;
163	    }
164	}
165	print "res: $res\n" if ($debug);
166	return $res;
167    } elsif (m/^\s*(\!)?(\w+)/) {
168	($neg, $var) = ($1, $2);
169	print "var: $neg $var\n" if ($debug);
170	my $res;
171	if (defined $defines{$var}) {
172	    $res = $defines{$var};
173	} else {
174	    $res = 0;
175	}
176	$res = ! $res if ($neg =~ m/!/);
177	print "res: $res\n" if ($debug);
178	return $res;
179    }
180    die "failed parse: $_\n";
181}
182