summaryrefslogtreecommitdiff
path: root/graphics/sam2p/ccdep.pl
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/sam2p/ccdep.pl
Initial commit
Diffstat (limited to 'graphics/sam2p/ccdep.pl')
-rw-r--r--graphics/sam2p/ccdep.pl397
1 files changed, 397 insertions, 0 deletions
diff --git a/graphics/sam2p/ccdep.pl b/graphics/sam2p/ccdep.pl
new file mode 100644
index 0000000000..987951aadc
--- /dev/null
+++ b/graphics/sam2p/ccdep.pl
@@ -0,0 +1,397 @@
+#! /bin/sh --
+eval '(exit $?0)' && eval 'PERL_BADLANG=x;export PERL_BADLANG;: \
+;exec perl -T -S -- "$0" ${1+"$@"};#'if 0;
+eval 'setenv PERL_BADLANG x;exec perl -x -S -- "$0" $argv:q;#'.q
+#!perl -w
++($0=~/(.*)/s);do$1;die$@if$@;__END__+if 0;
+# Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header
+#
+# ccdep.pl v0.32 -- semiautomatic dependency discovery for C/C++ programs
+# by pts@math.bme.hu at Fri May 31 13:36:29 CEST 2002
+# 0.31 by pts@math.bme.hu at Sat Jun 1 15:19:55 CEST 2002
+# 0.32 by pts@math.bme.hu at Tue Sep 3 19:12:20 CEST 2002
+# 0.33 by pts@math.bme.hu at Thu Oct 31 09:47:25 CET 2002
+#
+# Dat: no -T (tainting checks) anymore, does bad to our readpipe()
+# OK : emit `TARGETS_yes = ...'
+# Imp: make #warning etc. in *.h files work as expected
+# OK : generated.h
+# Imp: add external libraries (-L...)
+# Imp: abort if gcc command not found...
+# Imp: abort if not all .o are mentioned in gcc output
+# Imp: avoid $ etc. in Makefile
+# OK : all 8 combinations of PROVIDES|REQUIRES|CONFLICTS
+#
+BEGIN { eval { require integer; import integer } }
+BEGIN { eval { require strict ; import strict } }
+
+# Typical invocation: ccdep.pl --FAL=assert,no,yes,checker $(CXX)
+my @FAL=();
+if (@ARGV and $ARGV[0]=~/\A--FAL=(.*)/s) { @FAL=split/\W+/,$1; shift@ARGV }
+my $GCCP; # 'g++' or 'gcc': C/C++ preproc with `-E -MG' switches
+$GCCP="@ARGV";
+$GCCP="gcc" if $GCCP!~y/ \t//c;
+
+# Make sure we get English error messages from gcc.
+delete $ENV{LANG};
+delete $ENV{LANGUAGE};
+$ENV{LC_ALL} = "C";
+
+# ---
+
+# Returns true iff the passed filename is a C or C++ source file (and not .o
+# or .h or anything else).
+sub is_ds($) {
+ my $FN = $_[0];
+ return $FN =~ /\.(c(|c|xx|pp|[+][+])|C)\Z(?!\n)/;
+}
+
+sub find_ds() {
+ #** @return a list of .ds file in the current directory
+ my @L; my $E;
+ die unless opendir DIR, '.';
+ while (defined($E=readdir DIR)) {
+ push @L, $E if is_ds($E) and -f $E;
+ }
+ @L
+}
+
+sub expand_glob($$ $) {
+ #** @param $_[0] string containing globs (? and *)
+ #** @param $_[1] listref of names
+ #** @param $_[2] dest listref
+ my $S=quotemeta($_[0]);
+ if (0==($S=~s@\\([?*])@.$1@g)) { push @{$_[2]}, $_[0]; return }
+ my $RE=eval"+sub{\$_[0]=~/$S/}";
+ die$@if$@;
+ for my $E (@{$_[1]}) { push @{$_[2]}, $E if $RE->($E) }
+}
+
+sub mustbe_subset_of($$ $$) {
+ #** A must be a subset (sublist) of B
+ #** @param $_[0] caption A
+ #** @param $_[1] ref(array(string)) A
+ #** @param $_[2] caption B
+ #** @param $_[3] ref(array(string)) B
+ my @A=sort @{$_[1]};
+ my @B=sort @{$_[3]};
+ my($AV,$BV);
+ while (defined($AV=pop@A)) {
+ 1 while defined($BV=pop@B) and $BV gt $AV;
+ if (!defined($BV) or $BV ne $AV) {
+ print STDERR "$0: $_[0] are: @{$_[1]}\n";
+ print STDERR "$0: $_[2] are: @{$_[3]}\n";
+ die "$0: $_[0] must be a subset of $_[2]\n";
+ }
+ }
+}
+
+# ---
+
+print "$0: running.\n";
+
+sub unix_shq($) {
+ my $S=$_[0];
+ $S=~s@'@'\\''@g;
+ "'$S'"
+}
+
+sub shq($) {
+ my $S=$_[0];
+ return $S if $S!~/[^\w.-]/;
+ if ($^O =~ /(?:win32|win64|windows)/i) { # $^O eq 'MSWin32'
+ # assume the called program is CygWin/Ming32; see later
+ # Arguments are delimited by white space, which is either a space or a tab.
+ # . A string surrounded by double quotation marks is interpreted as a
+ # single argument, regardless of white space contained within. A quoted
+ # string can be embedded in an argument. Note that the caret (^) is not
+ # recognized as an escape character or delimiter.
+ # . A double quotation mark preceded by a backslash, \", is interpreted as
+ # a literal double quotation mark (").
+ # . Backslashes are interpreted literally, unless they immediately precede
+ # a double quotation mark.
+ # . If an even number of backslashes is followed by a double quotation
+ # mark, then one backslash (\) is placed in the argv array for every pair
+ # of backslashes (\\), and the double quotation mark (") is interpreted as
+ # a string delimiter.
+ # . If an odd number of backslashes is followed by a double quotation
+ # mark, then one backslash (\) is placed in the argv array for every pair
+ # of backslashes (\\) and the double quotation mark is interpreted as an
+ # escape sequence by the remaining backslash, causing a literal double
+ # quotation mark (") to be placed in argv.
+ $S =~ s@(\\+)(?="|\Z(?!\n))@$1$1@;
+ $S=~s@"@\\"@g; return qq{"$S"}
+ } else {
+ $S=~s@'@'\\''@g; return qq{'$S'}
+ }
+}
+#die shq(q{foo\b"ar\\}) eq q{"foo\b\"ar\\\\"}; # For Win32.
+
+sub backtick(@) {
+ my $S=$_[0];
+ if ($^O eq 'MSWin32') {
+ # assume the called program is CygWin/Ming32; and we have proper /bin/sh
+ $S="sh -c ".unix_shq($S); # /bin/sh can handle IO-redirections such as `2>&1' right
+ } else {
+ # assume UNIX
+ }
+ print "+ $S\n";
+ #die unless $ENV{PATH}=~/(.*)/s; # Dat: untaint()
+ #$ENV{PATH}=$1;
+ #die "$ENV{PATH}";
+ # Dat: if `.' is part of $ENV{PATH}, `Insecure directory...' is reported
+ #die unless $S=~/(.*)/s; # Dat: untaint()
+ readpipe $S # `` qx``
+}
+
+my @DS=find_ds();
+my @DSQ=map{shq$_}@DS;
+# g++-4.6 has it, clang++-3.4 doesn't but we don't care to rerun.
+my $DIAG = "";
+my $Q="$GCCP -DOBJDEP$DIAG -M -MG -E 2>&1 @DSQ";
+my $R=backtick($Q);
+
+if ($R!~/#\s*warning\s/) {
+ # config2.h:314:4: warning: #warning REQUIRES: c_lgcc3.o
+ # Dat: g++-3.3 and g++-4.8 omit #warning (implicit -w) with -M -MG -E.
+ # clang++-3.4 still emits warnings, so no need to rerun here.
+ $R.="\n".backtick("$GCCP -DOBJDEP$DIAG -E 2>&1 >/dev/null @DSQ");
+}
+
+$R =~ s@\\\n@@g; # Merge line continuations emitted by `gcc -M -MG'.
+
+#** $idep{"x.ds"} contains the .h and .ds dependency line for x.ds
+my %idep;
+#** $odep{"x.o"} is "x.ds"
+my %odep;
+my $included_from;
+
+my @instructions;
+
+while ($R=~/\G(.*)\n?/g) {
+ my $S=$1;
+
+ if ($S=~/\AIn file included from (?:[.]\/)*([^:]+)/) {
+ # If foo.cpp includes foo.hpp, which includes bar.hpp, then
+ # clang++-3.4 emits these in a row: foo.cpp, ./foo.hpp, and no bar.hpp.
+ # We want to keep only foo.cpp, hence we check
+ # `if !defined($included_from)'.
+ $included_from=$1 if !defined($included_from);
+ # Bottommost includer.
+ } elsif ($S=~/\A\s{3,}from (?:[.]\/)*([^:]+)/) { # From gcc-3.2.
+ $included_from=$1; # Higher includer, we override the previous one, because we need the topmost one.
+ } elsif ($S=~/\A(?:[.]\/)*([^:]+):\d+:(\d+:)? warning: (?:#warning )?([A-Z][-A-Z]{2,}):(.*)\Z/) {
+ # ^^^ (\d+:)? added for gcc-3.1
+ # ^^^ clang: appliers.cpp:554:6: warning: REQUIRES: out_gif.o [-W#warnings]
+ my($DS,$B,$features)=($1, $3, $4); # $B is e.g. 'PROVIDES'.
+ if (defined $included_from) { $DS=$included_from; undef $included_from }
+ die "$0: #include detection broken: expected non-header source file, got $DS in line: $S\n" if
+ not is_ds($DS);
+ die "$0: unknown dependency verb $B in line: $S\n" if
+ $B !~ m@\A(NULL-PROVIDES|PROVIDES|CONFLICTS|REQUIRES)\Z(?!\n)@;
+ for my $feature (split ' ',$features) {
+ if ($feature !~ m@\A\[-W@) { # g++-4.8 generates extra [-Wcpp] lines.
+ #print "INSTR $DS $B $feature\n";
+ push @instructions, [$DS, $B, $feature];
+ }
+ }
+ } elsif ($S=~/\A([^: ]+)\.o:( ([^: ]+?)\.([^ \n]+).*)\Z/s and $1 eq $3) {
+ # Dependency output of `gcc -M -MG'.
+
+ # $O: The .o file.
+ # $B: All the source dependencies (.cpp, .cxx, .cc, .C, .c, .ci etc.).
+ # $DS: The .ds file: the source file corresponding to the .o file, e.g.
+ # $O is 'encoder.o', $DS is 'encoder.cpp'.
+ my($O,$B,$DS)=("$1.o",$2,"$3.$4");
+ # ^^^ Dat: maybe both t.c and t.cxx
+ $B =~ s@ /[^ ]+@@g; # remove absolute pathnames
+ $B =~ s@\s+@ @g; $B =~ s@\A\s*@ @; $B =~ s@\s*\Z(?!\n)@ @;
+ die "$0: .o file in sources for $DS: $B" if $B =~ m@ [.]o @;
+ # Example reason: foo.c and foo.cpp both present as source files.
+ die "$0: .o file generated from multiple sources: $O and $odep{$O}" if
+ exists $odep{$O};
+ die if exists $idep{$DS}; # Shouldn't happen, $odep{$O} would exist first.
+ $odep{$O}=$DS;
+ $idep{$DS}=$B;
+ push @instructions, [$DS, 'PROVIDES', $O];
+ undef $included_from;
+ } elsif ($S=~/: (?:warning|error|fatal error|fatal):/) {
+ undef $included_from;
+ } else {
+ # Be resilient, and just ignore every other possible message here. This is
+ # for future compatibility with compilers. The infamous `invalid depret'
+ # error by ccdep.pl used to be here, but now it's gone.
+ }
+}
+undef $included_from; # Save memory.
+%odep=(); # Save memory.
+
+#** $pro{"x.ds"} is the list of features provided by "x.ds"; multiplicity
+my %pro;
+#** $req{"x.ds"} is the list of features required by "x.ds"; multiplicity
+my %req;
+#** $con{"x.ds"} is the list of features conflicted by "x.ds"; multiplicity
+my %con;
+#** $repro{"feature"} is a hash=>1 of .ds that provide "feature"
+my %repro;
+#** $mapro{"executable"} eq "x.ds" if "x.ds" provides main() for "executable".
+#** It looks like values are never used.
+my %mapro;
+#** hash=>1 of "feature"s of NULL-PROVIDES
+my %nullpro;
+for my $instruction (@instructions) {
+ my($DS, $verb, $feature) = @$instruction;
+ if ($verb eq 'NULL-PROVIDES') {
+ $nullpro{$feature} = 1;
+ } elsif ($verb eq 'PROVIDES') {
+ push @{$pro{$DS}}, $feature;
+ push @{$con{$DS}}, $feature;
+ $repro{$feature}{$DS}=1;
+ if ($feature=~/\A(.*)_main\Z/) { $mapro{$1}=$DS }
+ } elsif ($verb eq 'REQUIRES') {
+ push @{$req{$DS}}, $feature;
+ } elsif ($verb eq 'CONFLICTS') {
+ push @{$con{$DS}}, $feature;
+ } else {
+ die "$0: unknown verb in instruction: @$instruction\n"; # Never happens.
+ }
+}
+@instructions=(); # Save memory.
+
+mustbe_subset_of "providers"=>[sort keys(%pro)], "dep_sources"=>[sort keys(%idep)];
+mustbe_subset_of "dep_sources"=>[sort keys(%idep)], "sources"=>\@DS;
+
+{ my @K=keys %repro;
+ for my $DS (sort keys%con) {
+ my $L = $con{$DS};
+ my @R=();
+ for my $feature (@$L) { expand_glob $feature, \@K, \@R }
+ # ^^^ multiplicity remains
+ $con{$DS}=\@R;
+ }
+}
+
+my $outfn = "Makedep";
+die unless open MD, "> $outfn";
+die unless print MD '
+ifndef CCALL
+CCALL=$(CC) $(CFLAGS) $(CFLAGSB) $(CPPFLAGS) $(INCLUDES)
+endif
+ifndef CXXALL
+CXXALL=$(CXX) $(CXXFLAGS) $(CXXFLAGSB) $(CPPFLAGS) $(INCLUDES)
+endif
+ifndef LDALL
+LDALL=$(LDY) $(LDFLAGS) $(LIBS)
+endif
+ifndef CC
+CC=gcc
+endif
+ifndef CXX
+CXX=g++
+endif
+ifndef LD
+LD=$(CC) -s
+endif
+ifndef LDXX
+LDXX=$(CXX) -s
+endif
+ifndef LDY
+LDY=$(LD)
+endif
+ifndef CFLAGS
+CFLAGS=-O2 -W -Wall -fsigned-char
+endif
+ifndef CXXFLAGS
+CXXFLAGS=-O2 -W -Wall -fsigned-char
+endif
+ifndef GLOBFILES
+GLOBFILES=Makefile $outfn
+endif
+';
+
+die unless print MD "ALL +=", join(' ',sort keys%mapro), "\n";
+die unless print MD "TARGETS =", join(' ',sort keys%mapro), "\n";
+
+# vvv Thu Oct 31 09:49:02 CET 2002
+# (not required)
+#my %targets_fal;
+#for my $FA (@FAL) { $targets_fal{$FA}="TARGETS_$FA =" }
+
+for my $EXE (sort keys%mapro) {
+ print "exe $EXE\n";
+ my @REQO = (); # Will be list of .o files required by $EXE.
+ my @REQDS = (); # Will be list of .ds files required $EXE.
+ my @REQH = (); # Will be list of .h files required $EXE.
+
+ # Find the transitive dependencies of $EXE, save to @REQO, @REQDS, @REQH.
+ {
+ my %CON=(); # hash=>1 of features already conflicted
+ my %PRO=%nullpro; # hash=>1 of features already provided
+ my $feature;
+ my @features_to_analyze=("${EXE}_main");
+ while (defined($feature=pop@features_to_analyze)) {
+ next if exists $PRO{$feature};
+ #print "feat $feature (@features_to_analyze)\n"; ##
+ # vvv Dat: r.b.e == required by executable
+ die "$0: feature $feature r.b.e $EXE conflicts\n" if exists $CON{$feature};
+ my @L=sort keys%{$repro{$feature}};
+ die "$0: feature $feature r.b.e $EXE unprovided\n" if!@L;
+ die "$0: feature $feature r.b.e $EXE overprovided: @L\n" if$#L>=1;
+ # Now: $L[0] is a .ds providing the feature
+ push @REQDS, $L[0];
+ my $O=$L[0]; $O=~s@\.[^.]+\Z@.o@;
+ push @REQO, $O;
+
+ $PRO{$feature}=1;
+ for my $feature2 (@{$pro{$L[0]}}) {
+ die "$0: extra feature $feature2 r.b.e $EXE conflicts\n" if exists $CON{$feature2} and not exists $PRO{$feature2};
+ $PRO{$feature2}=1;
+ }
+ for my $feature2 (@{$req{$L[0]}}) {
+ push @features_to_analyze, $feature2 if!exists $PRO{$feature2}
+ }
+ for my $feature2 (@{$con{$L[0]}}) { $CON{$feature2}=1 }
+ # die if! exists $PRO{$feature}; # assert
+ }
+ my %REQH;
+ for my $DS (@REQDS) {
+ for my $HDS (split' ', $idep{$DS}) {
+ $REQH{$HDS} = 1 if !is_ds($HDS);
+ }
+ }
+ push @REQH, sort keys %REQH;
+ }
+
+ die unless print MD "${EXE}_DS=@REQDS\n${EXE}_H=@REQH\n".
+ "$EXE: \$(GLOBFILES) @REQO\n\t\$(LDALL) @REQO -o $EXE\n\t".
+ q!@echo "Created executable file: !.$EXE.
+ q! (size: `perl -e 'print -s "!.$EXE.q!"'`)."!. "\n";
+ # vvv Sat Jun 1 15:40:19 CEST 2002
+ for my $FA (@FAL) {
+ die unless print MD
+ "$EXE.$FA: \$(GLOBFILES) \$(${EXE}_DS) \$(${EXE}_H)\n\t".
+ "\$(CXD_$FA) \$(CXDFAL) \$(${EXE}_DS) -o $EXE.$FA\n";
+ # $targets_fal{$FA}.=" $EXE.$FA";
+ }
+}
+print MD "\n";
+
+# vvv Thu Oct 31 09:49:02 CET 2002
+# (not required)
+# for my $FA (@FAL) { print MD "$targets_fal{$FA}\n" }
+# print MD "\n";
+
+for my $K (sort keys%idep) {
+ my $V = $idep{$K};
+ my $O=$K; $O=~s@\.([^.]+)\Z@.o@; my $srcext = $1;
+ my @V = sort split' ', $V;
+ my $compiler = $srcext eq'c'?"CC":"CXX";
+ print MD "$O: \$(GLOBFILES) @V\n\t\$(${compiler}ALL) -c $K\n"
+}
+print MD "\n";
+
+die unless close MD;
+
+print "$0: done, created $outfn\n";
+
+__END__