diff --git a/configure b/configure index 798e8aff..dc558195 100755 --- a/configure +++ b/configure @@ -638,6 +638,7 @@ LTLIBOBJS LIBOBJS INDENT CLANG_FORMAT +CLANG ASTYLE PERL_VERSION PERL @@ -807,6 +808,7 @@ CXXCPP PERL ASTYLE CLANG_FORMAT +CLANG INDENT' @@ -1475,6 +1477,7 @@ Some influential environment variables: ASTYLE `astyle' (Artistic Style) program CLANG_FORMAT `clang-format' (LLVM/Clang) program + CLANG `clang` program INDENT `indent' program Use these variables to override the choices made by `configure' or to help @@ -16603,6 +16606,53 @@ if test "x$CLANG_FORMAT" = "xno"; then : fi # +# Extract the first word of "clang", so it can be a program name with args. +set dummy clang; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CLANG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CLANG in + [\\/]* | ?:[\\/]*) + ac_cv_path_CLANG="$CLANG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_dummy="$LLVM_BINDIR:$PATH" +for as_dir in $as_dummy +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CLANG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CLANG" && ac_cv_path_CLANG="no" + ;; +esac +fi +CLANG=$ac_cv_path_CLANG +if test -n "$CLANG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CLANG" >&5 +$as_echo "$CLANG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$CLANG" = "xno"; then : + missing_required_runtime_prereq=yes +fi +# + for ac_prog in gindent indent do # Extract the first word of "$ac_prog", so it can be a program name with args. @@ -19206,6 +19256,13 @@ if test "x$CLANG_FORMAT" = "xno"; then : $as_echo "$as_me: WARNING: You must install \`clang-format' before running C-Reduce." >&2;} CLANG_FORMAT=clang-format +fi +if test "x$CLANG" = "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You must install \`clang' before running C-Reduce." >&5 +$as_echo "$as_me: WARNING: You must install \`clang' before running C-Reduce." >&2;} + CLANG=clang + fi if test "$missing_required_runtime_prereq" = "yes"; then : diff --git a/configure.ac b/configure.ac index cb7b4dd7..5aa5ae97 100644 --- a/configure.ac +++ b/configure.ac @@ -127,6 +127,10 @@ AC_ARG_VAR([CLANG_FORMAT], [`clang-format' (LLVM/Clang) program]) AC_PATH_PROG([CLANG_FORMAT], [clang-format], [no], [$LLVM_BINDIR:$PATH]) AS_IF([test "x$CLANG_FORMAT" = "xno"], [missing_required_runtime_prereq=yes]) # +AC_ARG_VAR([CLANG], [`clang' (LLVM/Clang) program]) +AC_PATH_PROG([CLANG], [clang], [no], [$LLVM_BINDIR:$PATH]) +AS_IF([test "x$CLANG" = "xno"], [missing_required_runtime_prereq=yes]) +# AC_ARG_VAR([INDENT], [`indent' program]) AC_PATH_PROGS([INDENT], [gindent indent], [no]) AS_IF([test "x$INDENT" = "xno"], [missing_optional_runtime_prereq=yes]) @@ -163,6 +167,11 @@ AS_IF([test "x$CLANG_FORMAT" = "xno"], AC_MSG_WARN([You must install `clang-format' before running C-Reduce.]) CLANG_FORMAT=clang-format ]) +AS_IF([test "x$CLANG" = "xno"], + [ + AC_MSG_WARN([You must install `clang' before running C-Reduce.]) + CLANG=clang + ]) AS_IF([test "$missing_required_runtime_prereq" = "yes"], AC_MSG_WARN([Read the INSTALL file for info about C-Reduce dependencies.])) diff --git a/creduce/CMakeLists.txt b/creduce/CMakeLists.txt index 7ada4459..c1fb3585 100644 --- a/creduce/CMakeLists.txt +++ b/creduce/CMakeLists.txt @@ -51,6 +51,15 @@ if(NOT CLANG_FORMAT) set(missing_required_runtime_prereq "yes") endif() +find_program(CLANG + "clang${CMAKE_EXECUTABLE_SUFFIX}" + PATHS "${LLVM_TOOLS_BINARY_DIR}" + ) +if(NOT CLANG) + message(STATUS "`clang${CMAKE_EXECUTABLE_SUFFIX}' was not found") + set(missing_required_runtime_prereq "yes") +endif() + find_program(INDENT NAMES "gindent${CMAKE_EXECUTABLE_SUFFIX}" @@ -143,6 +152,11 @@ if(NOT CLANG_FORMAT) set(CLANG_FORMAT "clang-format") endif() +if(NOT CLANG) + message("You must install `clang' before running C-Reduce.") + set(CLANG "clang") +endif() + if(missing_required_runtime_prereq STREQUAL "yes") message("Read the INSTALL file for info about C-Reduce dependencies.") endif() @@ -224,6 +238,8 @@ string(REPLACE "\@ASTYLE@" "${ASTYLE}" CREDUCE_CONTENT "${CREDUCE_CONTENT}") string(REPLACE "\@CLANG_FORMAT@" "${CLANG_FORMAT}" CREDUCE_CONTENT "${CREDUCE_CONTENT}") +string(REPLACE "\@CLANG@" "${CLANG}" + CREDUCE_CONTENT "${CREDUCE_CONTENT}") string(REPLACE "\@INDENT@" "${INDENT}" CREDUCE_CONTENT "${CREDUCE_CONTENT}") file(WRITE @@ -263,6 +279,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..3e69d550 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 \ @@ -87,6 +88,7 @@ creduce_config_edit = sed \ -e 's|@GIT_HASH[@]|$(GIT_HASH)|g' \ -e 's|@ASTYLE[@]|$(ASTYLE)|g' \ -e 's|@CLANG_FORMAT[@]|$(CLANG_FORMAT)|g' \ + -e 's|@CLANG[@]|$(CLANG)|g' \ -e 's|@INDENT[@]|$(INDENT)|g' creduce_config.pm: Makefile git_version.txt diff --git a/creduce/Makefile.in b/creduce/Makefile.in index a6002464..317f3e60 100644 --- a/creduce/Makefile.in +++ b/creduce/Makefile.in @@ -176,6 +176,7 @@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLANG_FORMAT = @CLANG_FORMAT@ +CLANG = @CLANG@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -315,6 +316,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 \ @@ -369,6 +371,7 @@ creduce_config_edit = sed \ -e 's|@GIT_HASH[@]|$(GIT_HASH)|g' \ -e 's|@ASTYLE[@]|$(ASTYLE)|g' \ -e 's|@CLANG_FORMAT[@]|$(CLANG_FORMAT)|g' \ + -e 's|@CLANG[@]|$(CLANG)|g' \ -e 's|@INDENT[@]|$(INDENT)|g' CLEANFILES = \ 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/creduce_config.pm.in b/creduce/creduce_config.pm.in index 07333cc6..150d3104 100644 --- a/creduce/creduce_config.pm.in +++ b/creduce/creduce_config.pm.in @@ -33,6 +33,7 @@ use constant { # ASTYLE => q{@ASTYLE@}, CLANG_FORMAT => q{@CLANG_FORMAT@}, + CLANG => q{@CLANG@}, INDENT => q{@INDENT@}, }; @@ -49,6 +50,7 @@ our @EXPORT_OK = qw( GIT_VERSION ASTYLE CLANG_FORMAT + CLANG INDENT ); our %EXPORT_TAGS = qw(); diff --git a/creduce/pass_defines.pm b/creduce/pass_defines.pm new file mode 100644 index 00000000..ea4d1f7f --- /dev/null +++ b/creduce/pass_defines.pm @@ -0,0 +1,148 @@ +## -*- 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 $clang; + +sub backslash_x ($) { + return sprintf("\\x%X", ord($_[0])); +} + +sub check_prereqs () { + $clang = + find_external_program(creduce_config::CLANG, "clang"); + return defined ($clang); +} + +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;