161 lines
4.6 KiB
Perl
Executable File
161 lines
4.6 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
eval 'exec perl -S $0 "$@"'
|
|
if $runnning_under_some_shell;
|
|
|
|
# $Id: fixcpp.SH 19 2007-08-13 12:14:08Z rmanfredi $
|
|
#
|
|
# Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi
|
|
#
|
|
# You may redistribute only under the terms of the Artistic Licence,
|
|
# as specified in the README file that comes with the distribution.
|
|
# You may reuse parts of this distribution only within the terms of
|
|
# that same Artistic Licence; a copy of which may be found at the root
|
|
# of the source tree for dist 4.0.
|
|
#
|
|
# $Log: fixcpp.SH,v $
|
|
# Revision 3.0.1.1 1995/03/21 08:35:37 ram
|
|
# patch52: created
|
|
#
|
|
|
|
# Thank you HP-UX for having a cpp that strips trailing backslashes in the
|
|
# text. As of today, you are the only reason for this program to exist.
|
|
# People designing such things should have their hands cut off to prevent
|
|
# them from doing further damage :-)
|
|
#
|
|
# This program is meant to be called from jmake. All it does is pre-process
|
|
# the file it is given as argument, focusing on #include directives and
|
|
# resolving them as cpp would (but without the #line stuff since we don't
|
|
# really care about it), escaping all the trailing \ into '\ ^A'. The resulting
|
|
# temporary file is then handed off to the real cpp for macro processing, and
|
|
# the output is printed on stdout, after restoration of any original trailing \.
|
|
# Again, thanks HP-UX for making this so challenging and exciting... :-)
|
|
#
|
|
# Note that we MUST leave alone all the trailing @!\ or @@\, since those appear
|
|
# in macros and must go away some way or the other. Also trailing backslashes
|
|
# on #define lines are really continuations and are left un-escaped.
|
|
|
|
$cpp = '/usr/bin/cpp -traditional';
|
|
$version = '3.5';
|
|
$patchlevel = '27';
|
|
|
|
while ($ARGV[0] =~ /^-/) {
|
|
$_ = shift;
|
|
last if /--/;
|
|
$cpp_opt .= "$_ ";
|
|
next unless s/-I//;
|
|
push(@lookpath, $_);
|
|
}
|
|
|
|
($file) = @ARGV;
|
|
$counter = 0; # Counter for temporary files
|
|
|
|
$SIG{'INT'} = 'PLUMBER'; # Install cleaner in case of an interrupt...
|
|
|
|
$result = &process($file); # Process file, result in a temporary
|
|
&cpp($result); # Pass resulting file with escaped \ to cpp
|
|
unlink $result;
|
|
exit 0;
|
|
|
|
# Cleanup any temporary files...
|
|
sub PLUMBER {
|
|
warn "Could not cleanup all temporaries.\n" if @tmps != unlink(@tmps);
|
|
exit 1;
|
|
}
|
|
|
|
# Compute a suitable temporary file name
|
|
sub mktmp {
|
|
$counter++;
|
|
local($tmp) = "/tmp/jmk.$counter.$$";
|
|
push(@tmps, $tmp); # Keep track of them for &PLUMBER...
|
|
$tmp;
|
|
}
|
|
|
|
# Process a given file, returning the name of the temporary file into which
|
|
# the result is left over.
|
|
# This routine is recursively called to process nested include directives.
|
|
sub process {
|
|
local($file) = @_;
|
|
local(*FILE, *TMP);
|
|
open(FILE, $file) || die "Can't read $file: $!\n";
|
|
local($tmpfile) = &mktmp;
|
|
open(TMP, ">$tmpfile") || die "Can't create $tmpfile: $!\n";
|
|
local($here, $include);
|
|
local($_);
|
|
while (<FILE>) {
|
|
if (s/^#\s*include\s*//) { # Ah, we found a #include something...
|
|
chop;
|
|
if (/"(\S+)"/) {
|
|
($include, $here) = ($1, 1);
|
|
} elsif (/<(\S+)\>/) {
|
|
($include, $here) = ($1, 0);
|
|
} else {
|
|
warn "Ignoring unkown include directive $_.\n";
|
|
next;
|
|
}
|
|
local($incfile) = &lookup($include, $here);
|
|
unless (defined $incfile) {
|
|
warn "Can't locate include file $include.\n";
|
|
next;
|
|
}
|
|
$include = &process($incfile); # Recursively process this file
|
|
&append($include, 'TMP'); # Append result to current tmp file
|
|
unlink $include;
|
|
} else {
|
|
&escape;
|
|
print TMP;
|
|
}
|
|
}
|
|
close FILE;
|
|
close TMP;
|
|
$tmpfile; # Return name of file where results has been left over
|
|
}
|
|
|
|
# Perform necessary escaping work on current line.
|
|
sub escape {
|
|
# Don't escape trailing backslashes in macro definition or cpp
|
|
# won't see them as macro continuation any longer, and also within
|
|
# macro definitions, all those @@ or @! continuations...
|
|
s/\\$/\\ \001/ unless /\@[!@]\\$/ || /^#define/;
|
|
}
|
|
|
|
# Append file to given (opened) file descriptor
|
|
sub append {
|
|
local($file, $fd) = @_;
|
|
local(*FILE);
|
|
open(FILE, $file) || die "Can't re-open $file: $!\n";
|
|
local($_);
|
|
while (<FILE>) {
|
|
&escape;
|
|
print $fd $_;
|
|
}
|
|
close FILE;
|
|
}
|
|
|
|
# Lookup file, returning its located name or undef if not found.
|
|
sub lookup {
|
|
local($file, $here) = @_;
|
|
unless ($here) {
|
|
foreach $dir (@lookpath) {
|
|
if (-r "$dir/$file") { # Use -r instead of -f for symlinks
|
|
$file = "$dir/$file";
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
return undef unless -r $file;
|
|
$file;
|
|
}
|
|
|
|
# This is the final cpp processing. The output from cpp is filtered to un-escape
|
|
# all the trailing backslashes.
|
|
sub cpp {
|
|
local($file) = @_;
|
|
open(CPP, "$cpp $cpp_opt $file |") || die "Can't fork: $!\n";
|
|
while (<CPP>) {
|
|
s/\\ \001$/\\/; # Un-escape trailing \
|
|
print STDOUT;
|
|
}
|
|
close CPP;
|
|
}
|
|
|