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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
case $CONFIG in
'') . ./config.sh ;;
esac
echo "Extracting mkpro (with variable substitutions)"
$spitshell >mkpro <<!GROK!THIS!
#!$perlpath
#
# mkpro - make prototypes, appending them to the .h and .ih files
#
chdir "$src";
!GROK!THIS!
$spitshell >>mkpro <<'!NO!SUBS!'
$dont_line="/* DON'T EDIT BELOW THIS LINE OR YOUR CHANGES WILL BE LOST! */\n";
$changes = 0;
# We're looking for the following limited format:
#
# void
# function(arg1, arg2)
# char* arg1;
# int (*arg2) _((void));
# {
#
# Once we find the '{' on a line by itself, we scan backward, parsing
# the arguments until we find the function line, at which point we snag
# the return value and check for a preceding #if line.
#
# Public prototypes for foo.c are written to foo.h, while the private
# (i.e. static) ones are written to foo.ih. When updating the files,
# we generate foo.nh and foo.nih and discard any file that is not
# different from the original. If a file is different, the original
# is moved into the directory "sanity", and the new file renamed.
foreach $file (<*.c>) {
next if $file eq 'ndir.c' || $file eq 'parsedate.c';
next unless $file =~ s/\.c$//;
open(IN_C, "$file.c") || die "Can't open $file.c for input: $!\n";
# Copy everything in foo.h up to the "DON'T EDIT" line to foo.nh
if (!open(IN, "$file.h")) {
#print STDERR "Can't open $file.h -- skipping $file.c.\n";
next;
}
open(OUT_H, ">$file.nh") || die "Can't open $file.nh for output: $!\n";
while (<IN>) {
last if /DON'T EDIT BELOW/;
print OUT_H $_;
}
print OUT_H $dont_line . "\n";
close IN;
# Copy everything in foo.ih up to the "DON'T EDIT" line to foo.nih
open(OUT_I, ">$file.nih") || die "Can't open $file.nih for output: $!\n";
if (open(IN, "$file.ih")) {
while (<IN>) {
last if /DON'T EDIT BELOW/;
print OUT_I $_;
}
close IN;
$need_I = 1;
$new_I = '';
} else {
# If foo.ih doesn't yet exist, create a foo.nih anyway
print OUT_I "/* $file.ih\n */\n\n";
$need_I = 0;
$new_I = ' **NEW**';
}
print OUT_I $dont_line . "\n";
$cond_H = 'none';
$cond_I = 'none';
while (<IN_C>) {
# Limit the lines stack to 20 entries
shift @lines if $#lines >= 20;
push(@lines, $_);
next unless /^{\s*$/;
pop @lines;
undef @args;
undef $func;
# The default is to use the .h file unless we see a "static"
$out = OUT_H;
$cond = $cond_H;
while ($_ = pop @lines) {
s|\s*/\*.*\*/||; # trim any comment
if (/^(\S*).*;/) {
# A line with ';' is an argument
$arg = $1;
# Discard "register" prefix
if ($arg eq "register") {
/^register\s*(\S*)\s/;
$arg = $1;
}
# If the arg line has _((...)), remember that bit as well.
if (/(_\(\(.*\)\))/) {
$arg .= "(*) $1";
push(@args,$arg);
}
else {
# Append an extra '*' for arg[]
$arg .= '*' if /]/;
push(@args,$arg);
# We allow only one duplicate, e.g. int arg1, arg2
if (/,/) {
push(@args,$arg);
}
}
} elsif (/^(.*)\(/) {
# A line with '(' but without ';' is the function name.
$func = $1;
} elsif (/,/) {
# Any remaining line with a comma is a continuation-line
# of the function's arg-list, e.g. " arg8,arg9,arg10)"
} else {
chop;
$ret = $_;
if (/^static\s/) {
# A static function goes in .ih, not .h
$out = OUT_I;
$cond = $cond_I;
$need_I = 1;
}
# Pop the previous line (and another if empty)
$_ = pop @lines;
$_ = pop @lines if /^$/;
if (/^\#\s*if([^\/]*)/) {
# Remember conditional preceding function
$newcond = $1;
$newcond =~ s/\s*$//;
} elsif (/^\#\s*else/) {
# Discard a function after an #else -- it's a duplicate
last;
} else {
# No conditional -- turn it off
$newcond = 'none';
}
# Output conditional, but only if it's different.
if ($cond ne $newcond) {
# Out with the old...
if ($cond ne 'none') {
print $out "#endif\n";
}
# In with the new...
if ($newcond ne 'none') {
print $out "#if$newcond\n";
}
}
# At last, output the actual prototype.
print $out "$ret $func _((";
if ($_ = pop @args) {
print $out $_;
while ($_ = pop @args) {
print $out ",$_";
}
} else {
print $out "void";
}
# Some special processing for non-returning "finalize"
if ($func eq "finalize") {
print $out "))
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR >= 5)
__attribute__((noreturn))
#endif
;\n";
} else {
print $out "));\n";
}
# Remember the conditional state of the current .h|.ih file.
if ($ret =~ /^static\s/) {
$cond_I = $newcond;
} else {
$cond_H = $newcond;
}
last;
}
}
}
close IN_C;
# Close any dangling conditionals
if ($cond_H ne 'none') {
print OUT_H "#endif\n";
}
close OUT_H;
if ($cond_I ne 'none') {
print OUT_I "#endif\n";
}
close OUT_I;
# Check for any differences and update if changed.
if (system "diff $file.h $file.nh >/dev/null") {
print "Updating $file.h\n";
mkdir("sanity",0755) unless -d "sanity";
rename("$file.h","sanity/$file.h");
rename("$file.nh","$file.h");
$changes++;
} else {
unlink "$file.nh";
}
# The .ih file is a little different, in that it might not be needed.
if ($need_I) {
if ($new_I ne '') {
system "touch $file.ih";
}
if (system "diff $file.ih $file.nih >/dev/null") {
print "Updating $file.ih$new_I\n";
mkdir("sanity",0755) unless -d "sanity";
rename("$file.ih","sanity/$file.ih");
rename("$file.nih","$file.ih");
$changes++;
} else {
unlink "$file.nih";
}
} else {
unlink "$file.nih";
}
}
print "No changes to prototypes.\n" if !$changes;
!NO!SUBS!
$eunicefix mkpro
chmod 755 mkpro
|