File Coverage

/home/pjcj/g/Test-Smoke/perl-current-gcov/regen/embed_lib.pl
Criterion Covered Total %
statement 72 74 97.3
branch 42 50 84.0
condition 7 9 77.8
subroutine 4 4 100.0
total 125 137 91.2


line stmt bran cond sub time code
1           #!/usr/bin/perl -w
2 1     1 7 use strict;
  1       3  
  1       1678  
3            
4           # read embed.fnc and regen/opcodes, needed by regen/embed.pl and makedef.pl
5            
6           require 5.004; # keep this compatible, an old perl is all we may have before
7           # we build the new one
8            
9           # Records the current pre-processor state:
10           my @state;
11           # Nested structure to group functions by the pre-processor conditions that
12           # control when they are compiled:
13           my %groups;
14            
15           sub current_group {
16 312     312 559 my $group = \%groups;
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 312       863 foreach (sort @state) {
21 213   100   1057 $group->{$_} ||= {};
22 213       693 $group = $group->{$_};
23           }
24 312   100   1708 return $group->{''} ||= [];
25           }
26            
27           sub add_level {
28 504     504 943 my ($level, $indent, $wanted) = @_;
29 504       917 my $funcs = $level->{''};
30 504       686 my @entries;
31 504 100     1181 if ($funcs) {
32 456 100     1062 if (!defined $wanted) {
33 114       452 @entries = @$funcs;
34           } else {
35 342       647 foreach (@$funcs) {
36 4896 100     15541 if ($_->[0] =~ /A/) {
    100        
37 2697 100     7423 push @entries, $_ if $wanted eq 'A';
38           } elsif ($_->[0] =~ /E/) {
39 393 100     1172 push @entries, $_ if $wanted eq 'E';
40           } else {
41 1806 100     5238 push @entries, $_ if $wanted eq '';
42           }
43           }
44           }
45 456       1030 @entries = sort {$a->[2] cmp $b->[2]} @entries;
  15300       26448  
46           }
47 504       1395 foreach (sort grep {length $_} keys %$level) {
  956       2536  
48 500       1647 my @conditional = add_level($level->{$_}, $indent . ' ', $wanted);
49 500 100     2825 push @entries,
50           ["#${indent}if $_"], @conditional, ["#${indent}endif"]
51           if @conditional;
52           }
53 504       3000 return @entries;
54           }
55            
56           sub setup_embed {
57 1   50 1 10 my $prefix = shift || '';
58 1 50     20 open IN, $prefix . 'embed.fnc' or die $!;
59            
60 1       3 my @embed;
61            
62 1       859 while () {
63 2283       3713 chomp;
64 2283 100     6996 next if /^:/;
65 1980 100     5872 next if /^$/;
66 1899       6174 while (s|\\$||) {
67 391       1367 $_ .= ;
68 391       1620 chomp;
69           }
70 1899       6732 s/\s+$//;
71 1899       2492 my @args;
72 1899 100     5946 if (/^\s*(#|$)/) {
73 311       851 @args = $_;
74           }
75           else {
76 1588       17264 @args = split /\s*\|\s*/, $_;
77           }
78 1899 50 66   7437 if (@args == 1 && $args[0] !~ /^#\s*(?:if|ifdef|ifndef|else|endif)/) {
79 0       0 die "Illegal line $. '$args[0]' in embed.fnc";
80           }
81 1899       10391 push @embed, \@args;
82           }
83            
84 1 50     24 close IN or die "Problem reading embed.fnc: $!";
85            
86 1 50     70 open IN, $prefix . 'regen/opcodes' or die $!;
87           {
88 1       4 my %syms;
  1       4  
89            
90 1       1015 while () {
91 553       910 chomp;
92 553 100     1375 next unless $_;
93 446 100     1330 next if /^#/;
94 377       2381 my $check = (split /\t+/, $_)[2];
95 377 100     1870 next if $syms{$check}++;
96            
97           # These are all indirectly referenced by globals.c.
98 44       248 push @embed, ['pR', 'OP *', $check, 'NN OP *o'];
99           }
100           }
101 1 50     14 close IN or die "Problem reading regen/opcodes: $!";
102            
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.
109            
110 1       8 my $current = current_group();
111            
112 1       5 foreach (@embed) {
113 1943 100     4979 if (@$_ > 1) {
114 1632       3028 push @$current, $_;
115 1632       2951 next;
116           }
117 311       1235 $_->[0] =~ s/^#\s+/#/;
118 311       881 $_->[0] =~ /^\S*/;
119 311       767 $_->[0] =~ s/^#ifdef\s+(\S+)/#if defined($1)/;
120 311       616 $_->[0] =~ s/^#ifndef\s+(\S+)/#if !defined($1)/;
121 311 100     1613 if ($_->[0] =~ /^#if\s*(.*)/) {
    100        
    50        
122 151       479 push @state, $1;
123           } elsif ($_->[0] =~ /^#else\s*$/) {
124 9 50     25 die "Unmatched #else in embed.fnc" unless @state;
125 9       27 $state[-1] = "!($state[-1])";
126           } elsif ($_->[0] =~ m!^#endif\s*(?:/\*.*\*/)?$!) {
127 151 50     389 die "Unmatched #endif in embed.fnc" unless @state;
128 151       258 pop @state;
129           } else {
130 0       0 die "Unhandled pre-processor directive '$_->[0]' in embed.fnc";
131           }
132 311       721 $current = current_group();
133           }
134            
135 1       8 return ([add_level(\%groups, '')],
136           [add_level(\%groups, '', '')], # core
137           [add_level(\%groups, '', 'E')], # ext
138           [add_level(\%groups, '', 'A')]); # api
139           }
140            
141           1;