diff --git a/creduce/CMakeLists.txt b/creduce/CMakeLists.txt index 7ada4459..05da8e57 100644 --- a/creduce/CMakeLists.txt +++ b/creduce/CMakeLists.txt @@ -263,6 +263,9 @@ add_custom_target(Modules ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_SOURCE_DIR}/pass_comments.pm ${PROJECT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${PROJECT_SOURCE_DIR}/pass_defines.pm + ${PROJECT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_SOURCE_DIR}/pass_include_includes.pm ${PROJECT_BINARY_DIR} diff --git a/creduce/Makefile.am b/creduce/Makefile.am index d845bfa1..ab94245b 100644 --- a/creduce/Makefile.am +++ b/creduce/Makefile.am @@ -24,6 +24,7 @@ dist_perllib_DATA = \ pass_clang_binsrch.pm \ pass_clex.pm \ pass_comments.pm \ + pass_defines.pm \ pass_include_includes.pm \ pass_includes.pm \ pass_indent.pm \ diff --git a/creduce/Makefile.in b/creduce/Makefile.in index a6002464..370a7497 100644 --- a/creduce/Makefile.in +++ b/creduce/Makefile.in @@ -315,6 +315,7 @@ dist_perllib_DATA = \ pass_clang_binsrch.pm \ pass_clex.pm \ pass_comments.pm \ + pass_defines.pm \ pass_include_includes.pm \ pass_includes.pm \ pass_indent.pm \ diff --git a/creduce/creduce.in b/creduce/creduce.in index ee86f24d..3da3831a 100644 --- a/creduce/creduce.in +++ b/creduce/creduce.in @@ -755,8 +755,9 @@ my @all_methods = ( { "name" => "pass_include_includes", "arg" => "0", "pri" => 100, }, { "name" => "pass_includes", "arg" => "0", "first_pass_pri" => 0, }, - { "name" => "pass_unifdef", "arg" => "0", "pri" => 450, "first_pass_pri" => 0, }, - { "name" => "pass_comments", "arg" => "0", "pri" => 451, "first_pass_pri" => 0, }, + { "name" => "pass_defines", "arg" => "0", "pri" => 450, "first_pass_pri" => 0, }, + { "name" => "pass_unifdef", "arg" => "0", "pri" => 451, "first_pass_pri" => 0, }, + { "name" => "pass_comments", "arg" => "0", "pri" => 452, "first_pass_pri" => 0, }, { "name" => "pass_blank", "arg" => "0", "first_pass_pri" => 1, }, { "name" => "pass_clang_binsrch", "arg" => "replace-function-def-with-decl", "first_pass_pri" => 2, }, { "name" => "pass_clang_binsrch", "arg" => "remove-unused-function", "first_pass_pri" => 3, }, diff --git a/creduce/pass_defines.pm b/creduce/pass_defines.pm new file mode 100644 index 00000000..f3095645 --- /dev/null +++ b/creduce/pass_defines.pm @@ -0,0 +1,146 @@ +## -*- mode: Perl -*- +## +## Copyright (c) 2016 The University of Utah +## Copyright (c) 2016 Ori Brostovski , +## Copyright (c) 2016 Ceemple Software Ltd +## +## All rights reserved. +## +## This file is distributed under the University of Illinois Open Source +## License. See the file COPYING for details. + +############################################################################### +# test run with: creduce --no-cache --n 1 --no-default-passes --add-pass pass_defines 0 0 `which true` bubu + +package pass_defines; + +use strict; +use warnings; + +use File::Compare; +use creduce_utils; + +my $missing_env_warn = 0; + +sub backslash_x ($) { + return sprintf("\\x%X", ord($_[0])); +} + +sub check_prereqs () { + return 1; +} + +sub new ($$) { + my $flag = 0; + return \$flag; +} + +sub advance ($$$) { + (my $cfile, my $arg, my $state) = @_; + my $flag = ${$state}; + $flag = 1; + return \$flag; +} + +sub advance_on_success ($$$) { + (my $cfile, my $arg, my $state) = @_; + return $state; +} +sub addI ($) { + return "-I" . $_[0]; +}; + +sub do_transform ($) { + (my $cfile) = @_; + my $suffix = substr($cfile,rindex($cfile,".")); + + open INF, "<$cfile" or die; + my $tmpfile1 = File::Temp::tmpnam() . $suffix; + open TF1, ">$tmpfile1" or die; + my $tmpfile2 = File::Temp::tmpnam() . $suffix; + my $tmpfile3 = File::Temp::tmpnam() . $suffix; + my $index = 0; + + while (my $line = ) { + if ($line =~ m/^\s*#\s*include/) { + my $sline = $line; + $sline =~ s/([^a-zA-Z0-9])/backslash_x($1)/ge; + print TF1 "char *__creduce_before_include_" . $index . " = \"$sline\";\n"; + print TF1 $line; + print TF1 "char *__creduce_after_include_" . $index . " = \"$sline\";\n"; + } else { + print TF1 $line; + } + } + close TF1; + close INF; + + my $iargs = ""; + if (exists $ENV{CREDUCE_INCLUDE_PATH}) { + my @args = split(/:/,$ENV{CREDUCE_INCLUDE_PATH}); + $iargs = ""; + foreach my $iarg (@args) { + $iargs = $iargs . " -I" . $iarg; + } + } + my $lang_arg = ""; + if (exists $ENV{CREDUCE_LANG}) { + if ($ENV{CREDUCE_LANG} eq "CXX") { + $lang_arg = "-x c++"; + } elsif ($ENV{CREDUCE_LANG} eq "C") { + $lang_arg = "-x c" + } + } + system("clang -Wno-pragma-system-header-outside-header -E $lang_arg " . + "$iargs $tmpfile1 -o $tmpfile2"); + + unless (open TF2, "<$tmpfile2") { + return 0; + } + open OUTF, ">$tmpfile3" or die; + my $in_include = 0; + while (my $line = ) { + if ($in_include) { + if ($line =~ m/^char \*__creduce_after_include/) { + $in_include = 0; + } + } else { + if ($line =~ m/^char \*__creduce_before_include.*= \"(.*)\"/) { + my $value = $1; + $value =~ s/\\xA$/\n/; + $value =~ s/\\x(..)/chr(hex($1))/ge; + print OUTF $value; + $in_include = 1; + } elsif ($line !~ /^# /) { + print OUTF $line; + } + } + } + close OUTF; + close TF2; + + unlink $tmpfile1; + unlink $tmpfile2; + + if (compare($tmpfile3, $cfile)) { + File::Copy::move($tmpfile3, $cfile); + return 1; + } else { + unlink $tmpfile3; + return 0; + } +} + +sub transform($$$) { + (my $cfile, my $arg, my $state) = @_; + my $flag = ${$state}; + + if ($flag) { + return ($STOP, \$flag); + } + + my $success = do_transform($cfile); + return ($success ? $OK : $STOP, \$flag); +} + +1;