4 # read embed.fnc and regen/opcodes, needed by regen/embed.pl and makedef.pl
6 require 5.004; # keep this compatible, an old perl is all we may have before
9 # Records the current pre-processor state:
11 # Nested structure to group functions by the pre-processor conditions that
12 # control when they are compiled:
17 # Nested #if blocks are effectively &&ed together
18 # For embed.fnc, ordering within the && isn't relevant, so we can
19 # sort them to try to group more functions together.
20 foreach (sort @state) {
22 $group = $group->{$_};
24 return $group->{''} ||= [];
28 my ($level, $indent, $wanted) = @_;
29 my $funcs = $level->{''};
32 if (!defined $wanted) {
37 push @entries, $_ if $wanted eq 'A';
38 } elsif ($_->[0] =~ /E/) {
39 push @entries, $_ if $wanted eq 'E';
41 push @entries, $_ if $wanted eq '';
45 @entries = sort {$a->[2] cmp $b->[2]} @entries;
47 foreach (sort grep {length $_} keys %$level) {
48 my @conditional = add_level($level->{$_}, $indent . ' ', $wanted);
50 ["#${indent}if $_"], @conditional, ["#${indent}endif"]
57 my $prefix = shift || '';
58 open IN, $prefix . 'embed.fnc' or die $!;
76 @args = split /\s*\|\s*/, $_;
78 if (@args == 1 && $args[0] !~ /^#\s*(?:if|ifdef|ifndef|else|endif)/) {
79 die "Illegal line $. '$args[0]' in embed.fnc";
84 close IN or die "Problem reading embed.fnc: $!";
86 open IN, $prefix . 'regen/opcodes' or die $!;
94 my $check = (split /\t+/, $_)[2];
95 next if $syms{$check}++;
97 # These are all indirectly referenced by globals.c.
98 push @embed, ['pR', 'OP *', $check, 'NN OP *o'];
101 close IN or die "Problem reading regen/opcodes: $!";
103 # Cluster entries in embed.fnc that have the same #ifdef guards.
104 # Also, split out at the top level the three classes of functions.
105 # Output structure is actually the same as input structure - an
106 # (ordered) list of array references, where the elements in the
107 # reference determine what it is - a reference to a 1-element array is a
108 # pre-processor directive, a reference to 2+ element array is a function.
110 my $current = current_group();
117 $_->[0] =~ s/^#\s+/#/;
119 $_->[0] =~ s/^#ifdef\s+(\S+)/#if defined($1)/;
120 $_->[0] =~ s/^#ifndef\s+(\S+)/#if !defined($1)/;
121 if ($_->[0] =~ /^#if\s*(.*)/) {
123 } elsif ($_->[0] =~ /^#else\s*$/) {
124 die "Unmatched #else in embed.fnc" unless @state;
125 $state[-1] = "!($state[-1])";
126 } elsif ($_->[0] =~ m!^#endif\s*(?:/\*.*\*/)?$!) {
127 die "Unmatched #endif in embed.fnc" unless @state;
130 die "Unhandled pre-processor directive '$_->[0]' in embed.fnc";
132 $current = current_group();
135 return ([add_level(\%groups, '')],
136 [add_level(\%groups, '', '')], # core
137 [add_level(\%groups, '', 'E')], # ext
138 [add_level(\%groups, '', 'A')]); # api