diff -Nru cvise-1.6.0/build_and_test.sh cvise-2.3.0/build_and_test.sh --- cvise-1.6.0/build_and_test.sh 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/build_and_test.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -#!/usr/bin/bash - -BUILD_TYPE=$1 - -rm -rf objdir -mkdir objdir -cd objdir -cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -make -j`nproc` VERBOSE=1 - -if [ "$BUILD_TYPE" = "COVERAGE" ]; then -pytest --cov=./ -CODECOV_TOKEN="7c181327-be77-41de-aa6e-ca7187b14376" codecov -else -pytest -fi diff -Nru cvise-1.6.0/clang_delta/ClangDelta.cpp cvise-2.3.0/clang_delta/ClangDelta.cpp --- cvise-1.6.0/clang_delta/ClangDelta.cpp 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/ClangDelta.cpp 2021-03-09 08:18:13.000000000 +0000 @@ -78,6 +78,11 @@ llvm::outs() << "\"string\". Currently, this option works only with "; llvm::outs() << "transformation expression-detector.\n"; + llvm::outs() << " --preserve-routine=: "; + llvm::outs() << "only modify routines that do not match \"string\". "; + llvm::outs() << "Note that currently only replace-function-def-with-decl"; + llvm::outs() << "supports this feature.\n"; + llvm::outs() << " --check-reference=: "; llvm::outs() << "insert code to check if the candidate designated by the "; llvm::outs() << "counter equals to the reference value or not. Currently, "; @@ -169,6 +174,9 @@ else if (!ArgName.compare("replacement")) { TransMgr->setReplacement(ArgValue); } + else if (!ArgName.compare("preserve-routine")) { + TransMgr->setPreserveRoutine(ArgValue); + } else if (!ArgName.compare("check-reference")) { TransMgr->setReferenceValue(ArgValue); } diff -Nru cvise-1.6.0/clang_delta/CMakeLists.txt cvise-2.3.0/clang_delta/CMakeLists.txt --- cvise-1.6.0/clang_delta/CMakeLists.txt 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/CMakeLists.txt 2021-03-09 08:18:13.000000000 +0000 @@ -34,16 +34,16 @@ "/tests/aggregate-to-scalar/cast.output" "/tests/aggregate-to-scalar/test1.c" "/tests/aggregate-to-scalar/test1.output" - "/tests/aggregate-to-scalar/test1.cc" - "/tests/aggregate-to-scalar/test1.output" "/tests/aggregate-to-scalar/test2.c" "/tests/aggregate-to-scalar/test2.output" - "/tests/aggregate-to-scalar/test2.cc" - "/tests/aggregate-to-scalar/test2.output" "/tests/aggregate-to-scalar/test3.c" "/tests/aggregate-to-scalar/test3.output" "/tests/aggregate-to-scalar/test4.c" "/tests/aggregate-to-scalar/test4.output" + "/tests/aggregate-to-scalar/test5.cc" + "/tests/aggregate-to-scalar/test5.output" + "/tests/aggregate-to-scalar/test6.cc" + "/tests/aggregate-to-scalar/test6.output" "/tests/callexpr-to-value/macro1.c" "/tests/callexpr-to-value/macro1.output" "/tests/callexpr-to-value/macro2.c" @@ -306,10 +306,12 @@ "/tests/replace-function-def-with-decl/macro1.output" "/tests/replace-function-def-with-decl/macro2.c" "/tests/replace-function-def-with-decl/macro2.output" + "/tests/replace-function-def-with-decl/simple.cpp" + "/tests/replace-function-def-with-decl/simple.cpp.preserve_foo.output" + "/tests/replace-function-def-with-decl/simple.cpp.preserve_missing.output" + "/tests/replace-function-def-with-decl/simple.cpp.preserve_quack.output" "/tests/return-void/test1.c" "/tests/return-void/test1.output" - "/tests/return-void/test1.cc" - "/tests/return-void/test1.output" "/tests/return-void/test2.c" "/tests/return-void/test2.output" "/tests/return-void/test3.c" @@ -320,6 +322,8 @@ "/tests/return-void/test5.output" "/tests/return-void/test6.c" "/tests/return-void/test6.output" + "/tests/return-void/test7.cc" + "/tests/return-void/test7.output" "/tests/simplify-callexpr/macro.c" "/tests/simplify-callexpr/macro.output" "/tests/simplify-callexpr/test.c" diff -Nru cvise-1.6.0/clang_delta/RemoveUnusedFunction.cpp cvise-2.3.0/clang_delta/RemoveUnusedFunction.cpp --- cvise-1.6.0/clang_delta/RemoveUnusedFunction.cpp 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/RemoveUnusedFunction.cpp 2021-03-09 08:18:13.000000000 +0000 @@ -643,7 +643,13 @@ const FunctionDecl *ParentFD = UsingParentFDs[(*I).first]; if (ParentFD && RemovedFDs.count(ParentFD->getCanonicalDecl())) continue; - RewriteHelper->removeDecl((*I).first); + const UsingDecl *UD = (*I).first; + SourceRange Range = UD->getSourceRange(); + if (Range.getBegin().isMacroID()) { + TheRewriter.RemoveText(SrcManager->getExpansionRange(Range)); + } else { + RewriteHelper->removeDecl((*I).first); + } } } diff -Nru cvise-1.6.0/clang_delta/ReplaceFunctionDefWithDecl.cpp cvise-2.3.0/clang_delta/ReplaceFunctionDefWithDecl.cpp --- cvise-1.6.0/clang_delta/ReplaceFunctionDefWithDecl.cpp 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/ReplaceFunctionDefWithDecl.cpp 2021-03-09 08:18:13.000000000 +0000 @@ -314,6 +314,11 @@ void ReplaceFunctionDefWithDecl::addOneFunctionDef(const FunctionDecl *FD) { + // If DoPreserveRoutine is set, and our current routine is the one we're + // preserving, then skip it + if (DoPreserveRoutine && FD->getQualifiedNameAsString() == PreserveRoutine) + return; + ValidInstanceNum++; if (ToCounter > 0) { AllValidFunctionDefs.push_back(FD); diff -Nru cvise-1.6.0/clang_delta/RewriteUtils.cpp cvise-2.3.0/clang_delta/RewriteUtils.cpp --- cvise-1.6.0/clang_delta/RewriteUtils.cpp 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/RewriteUtils.cpp 2021-03-09 08:18:13.000000000 +0000 @@ -736,9 +736,15 @@ StringRef MB = SrcManager->getBufferData(FID); unsigned lineNo = SrcManager->getLineNumber(FID, StartOffset) - 1; +#if LLVM_VERSION_MAJOR >= 12 + const SrcMgr::ContentCache& + Content = SrcManager->getSLocEntry(FID).getFile().getContentCache(); + unsigned lineOffs = Content.SourceLineCache[lineNo]; +#else const SrcMgr::ContentCache * Content = SrcManager->getSLocEntry(FID).getFile().getContentCache(); unsigned lineOffs = Content->SourceLineCache[lineNo]; +#endif // Find the whitespace at the start of the line. StringRef indentSpace; diff -Nru cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test1.cc cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test1.cc --- cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test1.cc 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test1.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -extern "C" { - extern char *gnu_optarg; -} - -char foo() { - return gnu_optarg[0]; -} diff -Nru cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test1.output cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test1.output --- cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test1.output 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test1.output 2021-03-09 08:18:13.000000000 +0000 @@ -1,8 +1,5 @@ -extern "C" { - extern char *gnu_optarg; -char gnu_optarg_0; -} - -char foo() { - return gnu_optarg_0; +int a[1], b; +int a_0; +int foo(void) { + return a_0; } diff -Nru cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test2.cc cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test2.cc --- cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test2.cc 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test2.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -struct S { - int **f1; -}; - -void foo() { - int *a[16]; - struct S s = { a }; - s.f1[0] = 0; -} diff -Nru cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test2.output cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test2.output --- cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test2.output 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test2.output 2021-03-09 08:18:13.000000000 +0000 @@ -1,10 +1,9 @@ struct S { - int **f1; -}; + int f1; +} a, b[1]; +int a_0; -void foo() { - int *a[16]; - struct S s = { a }; - int *s_0_0; - s_0_0 = 0; +int foo() +{ + return a_0 + b[0].f1; } diff -Nru cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test5.cc cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test5.cc --- cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test5.cc 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test5.cc 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,7 @@ +extern "C" { + extern char *gnu_optarg; +} + +char foo() { + return gnu_optarg[0]; +} diff -Nru cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test5.output cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test5.output --- cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test5.output 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test5.output 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,8 @@ +extern "C" { + extern char *gnu_optarg; +char gnu_optarg_0; +} + +char foo() { + return gnu_optarg_0; +} diff -Nru cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test6.cc cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test6.cc --- cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test6.cc 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test6.cc 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,9 @@ +struct S { + int **f1; +}; + +void foo() { + int *a[16]; + struct S s = { a }; + s.f1[0] = 0; +} diff -Nru cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test6.output cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test6.output --- cvise-1.6.0/clang_delta/tests/aggregate-to-scalar/test6.output 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/aggregate-to-scalar/test6.output 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,10 @@ +struct S { + int **f1; +}; + +void foo() { + int *a[16]; + struct S s = { a }; + int *s_0_0; + s_0_0 = 0; +} diff -Nru cvise-1.6.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp cvise-2.3.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp --- cvise-1.6.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,10 @@ +class Moo { +public: + static int foo() { return 10; } + static int bar() { return 10; } +}; + +void quack(void) { + if (Moo::foo()) + ; +} diff -Nru cvise-1.6.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_foo.output cvise-2.3.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_foo.output --- cvise-1.6.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_foo.output 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_foo.output 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,7 @@ +class Moo { +public: + static int foo() { return 10; } + static int bar() ; +}; + +void quack(void) ; diff -Nru cvise-1.6.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_missing.output cvise-2.3.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_missing.output --- cvise-1.6.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_missing.output 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_missing.output 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,7 @@ +class Moo { +public: + static int foo() ; + static int bar() ; +}; + +void quack(void) ; diff -Nru cvise-1.6.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_quack.output cvise-2.3.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_quack.output --- cvise-1.6.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_quack.output 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/replace-function-def-with-decl/simple.cpp.preserve_quack.output 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,10 @@ +class Moo { +public: + static int foo() ; + static int bar() ; +}; + +void quack(void) { + if (Moo::foo()) + ; +} diff -Nru cvise-1.6.0/clang_delta/tests/return-void/test1.cc cvise-2.3.0/clang_delta/tests/return-void/test1.cc --- cvise-1.6.0/clang_delta/tests/return-void/test1.cc 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/return-void/test1.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -extern "C" extern "C" - -int foo (); - -int main_res; -main () { - foo (); -} diff -Nru cvise-1.6.0/clang_delta/tests/return-void/test1.output cvise-2.3.0/clang_delta/tests/return-void/test1.output --- cvise-1.6.0/clang_delta/tests/return-void/test1.output 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/return-void/test1.output 2021-03-09 08:18:13.000000000 +0000 @@ -1,8 +1 @@ -extern "C" extern "C" - -void foo (); - -int main_res; -main () { - foo (); -} +void foo(int i); diff -Nru cvise-1.6.0/clang_delta/tests/return-void/test7.cc cvise-2.3.0/clang_delta/tests/return-void/test7.cc --- cvise-1.6.0/clang_delta/tests/return-void/test7.cc 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/return-void/test7.cc 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,8 @@ +extern "C" extern "C" + +int foo (); + +int main_res; +main () { + foo (); +} diff -Nru cvise-1.6.0/clang_delta/tests/return-void/test7.output cvise-2.3.0/clang_delta/tests/return-void/test7.output --- cvise-1.6.0/clang_delta/tests/return-void/test7.output 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/return-void/test7.output 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,8 @@ +extern "C" extern "C" + +void foo (); + +int main_res; +main () { + foo (); +} diff -Nru cvise-1.6.0/clang_delta/tests/test_clang_delta.py cvise-2.3.0/clang_delta/tests/test_clang_delta.py --- cvise-1.6.0/clang_delta/tests/test_clang_delta.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/tests/test_clang_delta.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,6 +1,7 @@ import os -import unittest import subprocess +import unittest + class TestClangDelta(unittest.TestCase): @@ -39,21 +40,21 @@ def test_aggregate_to_scalar_test1(self): self.check_clang_delta('aggregate-to-scalar/test1.c', '--transformation=aggregate-to-scalar --counter=1') - def test_aggregate_to_scalar_test1(self): - self.check_clang_delta('aggregate-to-scalar/test1.cc', '--transformation=aggregate-to-scalar --counter=1') - def test_aggregate_to_scalar_test2(self): self.check_clang_delta('aggregate-to-scalar/test2.c', '--transformation=aggregate-to-scalar --counter=1') - def test_aggregate_to_scalar_test2(self): - self.check_clang_delta('aggregate-to-scalar/test2.cc', '--transformation=aggregate-to-scalar --counter=1') - def test_aggregate_to_scalar_test3(self): self.check_clang_delta('aggregate-to-scalar/test3.c', '--transformation=aggregate-to-scalar --counter=1') def test_aggregate_to_scalar_test4(self): self.check_clang_delta('aggregate-to-scalar/test4.c', '--transformation=aggregate-to-scalar --counter=1') + def test_aggregate_to_scalar_test5(self): + self.check_clang_delta('aggregate-to-scalar/test5.cc', '--transformation=aggregate-to-scalar --counter=1') + + def test_aggregate_to_scalar_test6(self): + self.check_clang_delta('aggregate-to-scalar/test6.cc', '--transformation=aggregate-to-scalar --counter=1') + def test_callexpr_to_value_macro1(self): self.check_clang_delta('callexpr-to-value/macro1.c', '--transformation=callexpr-to-value --counter=1') @@ -117,7 +118,7 @@ def test_instantiate_template_param_default_test3(self): self.check_query_instances('instantiate-template-param/test3.cc', '--query-instances=instantiate-template-param', - 'Available transformation instances: 0') + 'Available transformation instances: 0') def test_local_to_global_macro(self): self.check_clang_delta('local-to-global/macro.c', '--transformation=local-to-global --counter=1') @@ -149,32 +150,32 @@ def test_remove_namespace_macro(self): self.check_clang_delta('remove-namespace/macro.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/macro.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/macro.output2') + 'remove-namespace/macro.output2') self.check_clang_delta('remove-namespace/macro.cpp', '--transformation=remove-namespace --counter=3', - 'remove-namespace/macro.output3') + 'remove-namespace/macro.output3') self.check_clang_delta('remove-namespace/macro.cpp', '--transformation=remove-namespace --counter=4', - 'remove-namespace/macro.output4') + 'remove-namespace/macro.output4') self.check_clang_delta('remove-namespace/macro.cpp', '--transformation=remove-namespace --counter=5', - 'remove-namespace/macro.output5') + 'remove-namespace/macro.output5') def test_remove_namespace(self): self.check_clang_delta('remove-namespace/namespace.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace.output2') + 'remove-namespace/namespace.output2') self.check_clang_delta('remove-namespace/namespace.cpp', '--transformation=remove-namespace --counter=3', - 'remove-namespace/namespace.output3') + 'remove-namespace/namespace.output3') def test_remove_namespace2(self): self.check_clang_delta('remove-namespace/namespace2.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace2.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace2.output2') + 'remove-namespace/namespace2.output2') def test_remove_namespace3(self): self.check_clang_delta('remove-namespace/namespace3.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace3.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace3.output2') + 'remove-namespace/namespace3.output2') self.check_clang_delta('remove-namespace/namespace3.cpp', '--transformation=remove-namespace --counter=3', - 'remove-namespace/namespace3.output3') + 'remove-namespace/namespace3.output3') def test_remove_namespace4(self): self.check_clang_delta('remove-namespace/namespace4.cpp', '--transformation=remove-namespace --counter=1') @@ -182,28 +183,28 @@ def test_remove_namespace5(self): self.check_clang_delta('remove-namespace/namespace5.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace5.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace5.output2') + 'remove-namespace/namespace5.output2') self.check_clang_delta('remove-namespace/namespace5.cpp', '--transformation=remove-namespace --counter=3', - 'remove-namespace/namespace5.output3') + 'remove-namespace/namespace5.output3') self.check_clang_delta('remove-namespace/namespace5.cpp', '--transformation=remove-namespace --counter=4', - 'remove-namespace/namespace5.output4') + 'remove-namespace/namespace5.output4') def test_remove_namespace6(self): self.check_clang_delta('remove-namespace/namespace6.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace6.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace6.output2') + 'remove-namespace/namespace6.output2') def test_remove_namespace7(self): self.check_clang_delta('remove-namespace/namespace7.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace7.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace7.output2') + 'remove-namespace/namespace7.output2') self.check_clang_delta('remove-namespace/namespace7.cpp', '--transformation=remove-namespace --counter=3', - 'remove-namespace/namespace7.output3') + 'remove-namespace/namespace7.output3') def test_remove_namespace8(self): self.check_clang_delta('remove-namespace/namespace8.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace8.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace8.output2') + 'remove-namespace/namespace8.output2') def test_remove_namespace9(self): self.check_clang_delta('remove-namespace/namespace9.cpp', '--transformation=remove-namespace --counter=1') @@ -211,24 +212,24 @@ def test_remove_namespace10(self): self.check_clang_delta('remove-namespace/namespace10.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace10.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace10.output2') + 'remove-namespace/namespace10.output2') def test_remove_namespace11(self): self.check_clang_delta('remove-namespace/namespace11.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace11.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace11.output2') + 'remove-namespace/namespace11.output2') def test_remove_namespace12(self): self.check_clang_delta('remove-namespace/namespace12.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace12.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace12.output2') + 'remove-namespace/namespace12.output2') self.check_clang_delta('remove-namespace/namespace12.cpp', '--transformation=remove-namespace --counter=3', - 'remove-namespace/namespace12.output3') + 'remove-namespace/namespace12.output3') def test_remove_namespace13(self): self.check_clang_delta('remove-namespace/namespace13.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace13.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace13.output2') + 'remove-namespace/namespace13.output2') def test_remove_namespace14(self): self.check_clang_delta('remove-namespace/namespace14.cpp', '--transformation=remove-namespace --counter=1') @@ -236,9 +237,9 @@ def test_remove_namespace15(self): self.check_clang_delta('remove-namespace/namespace15.cpp', '--transformation=remove-namespace --counter=1') self.check_clang_delta('remove-namespace/namespace15.cpp', '--transformation=remove-namespace --counter=2', - 'remove-namespace/namespace15.output2') + 'remove-namespace/namespace15.output2') self.check_clang_delta('remove-namespace/namespace15.cpp', '--transformation=remove-namespace --counter=3', - 'remove-namespace/namespace15.output3') + 'remove-namespace/namespace15.output3') def test_remove_nested_function_remove_nested_func1(self): self.check_clang_delta('remove-nested-function/remove_nested_func1.cc', '--transformation=remove-nested-function --counter=1') @@ -279,12 +280,12 @@ def test_remove_unused_function_const(self): self.check_clang_delta('remove-unused-function/const.cc', '--transformation=remove-unused-function --counter=1') self.check_clang_delta('remove-unused-function/const.cc', '--transformation=remove-unused-function --counter=2', - 'remove-unused-function/const.output2') + 'remove-unused-function/const.output2') def test_remove_unused_function_default(self): self.check_clang_delta('remove-unused-function/default.cc', '--transformation=remove-unused-function --counter=1') self.check_clang_delta('remove-unused-function/default.cc', '--transformation=remove-unused-function --counter=2', - 'remove-unused-function/default.output2') + 'remove-unused-function/default.output2') def test_remove_unused_function_delete(self): self.check_clang_delta('remove-unused-function/delete.cc', '--transformation=remove-unused-function --counter=1') @@ -292,15 +293,15 @@ def test_remove_unused_function_delete2(self): self.check_clang_delta('remove-unused-function/delete2.cc', '--transformation=remove-unused-function --counter=1') self.check_clang_delta('remove-unused-function/delete2.cc', '--transformation=remove-unused-function --counter=2', - 'remove-unused-function/delete2.output2') + 'remove-unused-function/delete2.output2') self.check_clang_delta('remove-unused-function/delete2.cc', '--transformation=remove-unused-function --counter=3', - 'remove-unused-function/delete2.output3') + 'remove-unused-function/delete2.output3') self.check_clang_delta('remove-unused-function/delete2.cc', '--transformation=remove-unused-function --counter=4', - 'remove-unused-function/delete2.output4') + 'remove-unused-function/delete2.output4') def test_remove_unused_function_inline_ns(self): self.check_query_instances('remove-unused-function/inline_ns.cc', '--query-instances=remove-unused-function', - 'Available transformation instances: 0') + 'Available transformation instances: 0') def test_remove_unused_function_macro1(self): self.check_clang_delta('remove-unused-function/macro1.cc', '--transformation=remove-unused-function --counter=1') @@ -467,11 +468,23 @@ def test_replace_function_def_with_decl_macro2(self): self.check_clang_delta('replace-function-def-with-decl/macro2.c', '--transformation=replace-function-def-with-decl --counter=1 --to-counter=2') - def test_return_void_test1(self): - self.check_clang_delta('return-void/test1.c', '--transformation=return-void --counter=1') + def test_replace_function_def_with_decl_simple_preserve_missing(self): + self.check_clang_delta('replace-function-def-with-decl/simple.cpp', + '--transformation=replace-function-def-with-decl --preserve-routine=blahblahblah --counter=1 --to-counter=3', + output_file='replace-function-def-with-decl/simple.cpp.preserve_missing.output') + + def test_replace_function_def_with_decl_simple_preserve_quack(self): + self.check_clang_delta('replace-function-def-with-decl/simple.cpp', + '--transformation=replace-function-def-with-decl --preserve-routine=quack --counter=1 --to-counter=2', + output_file='replace-function-def-with-decl/simple.cpp.preserve_quack.output') + + def test_replace_function_def_with_decl_simple_preserve_foo(self): + self.check_clang_delta('replace-function-def-with-decl/simple.cpp', + '--transformation=replace-function-def-with-decl --preserve-routine=Moo::foo --counter=1 --to-counter=9999 --warn-on-counter-out-of-bounds', + output_file='replace-function-def-with-decl/simple.cpp.preserve_foo.output') def test_return_void_test1(self): - self.check_clang_delta('return-void/test1.cc', '--transformation=return-void --counter=1') + self.check_clang_delta('return-void/test1.c', '--transformation=return-void --counter=1') def test_return_void_test2(self): self.check_clang_delta('return-void/test2.c', '--transformation=return-void --counter=1') @@ -488,6 +501,9 @@ def test_return_void_test6(self): self.check_clang_delta('return-void/test6.c', '--transformation=return-void --counter=1') + def test_return_void_test7(self): + self.check_clang_delta('return-void/test7.cc', '--transformation=return-void --counter=1') + def test_simplify_callexpr_macro(self): self.check_clang_delta('simplify-callexpr/macro.c', '--transformation=simplify-callexpr --counter=1') @@ -505,7 +521,7 @@ def test_template_arg_to_int_not_valid_5(self): self.check_query_instances('template-arg-to-int/not_valid5.cc', '--query-instances=template-arg-to-int', - 'Available transformation instances: 0') + 'Available transformation instances: 0') def test_union_to_struct_union1(self): self.check_clang_delta('union-to-struct/union1.c', '--transformation=union-to-struct --counter=1') @@ -520,7 +536,7 @@ current = os.path.dirname(__file__) binary = os.path.join(current, '../clang_delta') cmd = '%s %s %s' % (binary, os.path.join(current, 'remove-unused-function/macro2.cc'), - '--transformation=remove-unused-function --counter=111 --to-counter=222 --warn-on-counter-out-of-bounds --report-instances-count') + '--transformation=remove-unused-function --counter=111 --to-counter=222 --warn-on-counter-out-of-bounds --report-instances-count') run = subprocess.run(cmd, shell=True, encoding='utf8', stderr=subprocess.PIPE, stdout=subprocess.PIPE) assert 'Available transformation instances: 1' in run.stderr assert 'Warning: number of transformation instances exceeded' in run.stderr diff -Nru cvise-1.6.0/clang_delta/Transformation.cpp cvise-2.3.0/clang_delta/Transformation.cpp --- cvise-1.6.0/clang_delta/Transformation.cpp 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/Transformation.cpp 2021-03-09 08:18:13.000000000 +0000 @@ -108,7 +108,12 @@ void Transformation::outputOriginalSource(llvm::raw_ostream &OutStream) { FileID MainFileID = SrcManager->getMainFileID(); +#if LLVM_VERSION_MAJOR >= 12 + llvm::Optional MainBuf = + SrcManager->getBufferOrNone(MainFileID); +#else const llvm::MemoryBuffer *MainBuf = SrcManager->getBuffer(MainFileID); +#endif TransAssert(MainBuf && "Empty MainBuf!"); OutStream << MainBuf->getBufferStart(); OutStream.flush(); diff -Nru cvise-1.6.0/clang_delta/Transformation.h cvise-2.3.0/clang_delta/Transformation.h --- cvise-1.6.0/clang_delta/Transformation.h 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/Transformation.h 2021-03-09 08:18:13.000000000 +0000 @@ -84,6 +84,7 @@ MultipleRewrites(false), ToCounter(-1), DoReplacement(false), + DoPreserveRoutine(false), CheckReference(false), WarnOnCounterOutOfBounds(false) { @@ -106,6 +107,7 @@ MultipleRewrites(MultipleRewritesFlag), ToCounter(-1), DoReplacement(false), + DoPreserveRoutine(false), CheckReference(false), WarnOnCounterOutOfBounds(false) { @@ -144,6 +146,11 @@ DoReplacement = true; } + void setPreserveRoutine(const std::string &Str) { + PreserveRoutine = Str; + DoPreserveRoutine = true; + } + void setReferenceValue(const std::string &Str) { ReferenceValue = Str; CheckReference = true; @@ -343,6 +350,10 @@ std::string Replacement; + bool DoPreserveRoutine; + + std::string PreserveRoutine; + bool CheckReference; std::string ReferenceValue; diff -Nru cvise-1.6.0/clang_delta/TransformationManager.cpp cvise-2.3.0/clang_delta/TransformationManager.cpp --- cvise-1.6.0/clang_delta/TransformationManager.cpp 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/TransformationManager.cpp 2021-03-09 08:18:13.000000000 +0000 @@ -95,7 +95,9 @@ ClangInstance->createDiagnostics(); TargetOptions &TargetOpts = ClangInstance->getTargetOpts(); +#if LLVM_VERSION_MAJOR < 12 PreprocessorOptions &PPOpts = ClangInstance->getPreprocessorOpts(); +#endif if (const char *env = getenv("CVISE_TARGET_TRIPLE")) { TargetOpts.Triple = std::string(env); } else { @@ -138,7 +140,7 @@ Invocation.setLangDefaults(ClangInstance->getLangOpts(), InputKind::CXX, T, PPOpts, LSTD); } else if(IK.getLanguage() == InputKind::OpenCL) { -#else +#elif LLVM_VERSION_MAJOR < 12 if (IK.getLanguage() == Language::C) { Invocation.setLangDefaults(ClangInstance->getLangOpts(), InputKind(Language::C), T, PPOpts); } @@ -149,6 +151,18 @@ Invocation.setLangDefaults(ClangInstance->getLangOpts(), InputKind(Language::CXX), T, PPOpts, LSTD); } else if(IK.getLanguage() == Language::OpenCL) { +#else + vector includes; + if (IK.getLanguage() == Language::C) { + Invocation.setLangDefaults(ClangInstance->getLangOpts(), InputKind(Language::C), T, includes); + } + else if (IK.getLanguage() == Language::CXX) { + // ISSUE: it might cause some problems when building AST + // for a function which has a non-declared callee, e.g., + // It results an empty AST for the caller. + Invocation.setLangDefaults(ClangInstance->getLangOpts(), InputKind(Language::CXX), T, includes, LSTD); + } + else if(IK.getLanguage() == Language::OpenCL) { #endif //Commandline parameters std::vector Args; @@ -183,7 +197,12 @@ #else InputKind::OpenCL, #endif + +#if LLVM_VERSION_MAJOR < 12 T, PPOpts); +#else + T, includes); +#endif } else { ErrorMsg = "Unsupported file type!"; @@ -225,6 +244,8 @@ // is invoked through ClangInstance->setASTConsumer. if (DoReplacement) CurrentTransformationImpl->setReplacement(Replacement); + if (DoPreserveRoutine) + CurrentTransformationImpl->setPreserveRoutine(PreserveRoutine); if (CheckReference) CurrentTransformationImpl->setReferenceValue(ReferenceValue); @@ -422,6 +443,8 @@ QueryInstanceOnly(false), DoReplacement(false), Replacement(""), + DoPreserveRoutine(false), + PreserveRoutine(""), CheckReference(false), ReferenceValue(""), SetCXXStandard(false), diff -Nru cvise-1.6.0/clang_delta/TransformationManager.h cvise-2.3.0/clang_delta/TransformationManager.h --- cvise-1.6.0/clang_delta/TransformationManager.h 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/clang_delta/TransformationManager.h 2021-03-09 08:18:13.000000000 +0000 @@ -80,6 +80,11 @@ DoReplacement = true; } + void setPreserveRoutine(const std::string &Str) { + PreserveRoutine = Str; + DoPreserveRoutine = true; + } + void setReferenceValue(const std::string &Str) { ReferenceValue = Str; CheckReference = true; @@ -156,6 +161,10 @@ std::string Replacement; + bool DoPreserveRoutine; + + std::string PreserveRoutine; + bool CheckReference; std::string ReferenceValue; diff -Nru cvise-1.6.0/CMakeLists.txt cvise-2.3.0/CMakeLists.txt --- cvise-1.6.0/CMakeLists.txt 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/CMakeLists.txt 2021-03-09 08:18:13.000000000 +0000 @@ -88,7 +88,7 @@ # `git archive' inserts the abbreviated hash of the archive's commit into this # file. (See the `.gitattributes' file.) # -set(GIT_HASH "1b1be7c") +set(GIT_HASH "3f80c31") if(GIT_HASH MATCHES "^\\$") ## METHOD 2: The source tree is a git repository. get_git_head_revision(GIT_REFSPEC GIT_HASH) @@ -122,11 +122,11 @@ set(cvise_PACKAGE "cvise") set(cvise_PACKAGE_BUGREPORT "https://github.com/marxin/cvise/issues") set(cvise_PACKAGE_NAME "cvise") -set(cvise_PACKAGE_STRING "cvise 1.6.0") +set(cvise_PACKAGE_STRING "cvise 2.3.0") set(cvise_PACKAGE_TARNAME "cvise") set(cvise_PACKAGE_URL "https://github.com/marxin/cvise/") -set(cvise_PACKAGE_VERSION "1.6.0") -set(cvise_VERSION "1.6.0") +set(cvise_PACKAGE_VERSION "2.3.0") +set(cvise_VERSION "2.3.0") set(cvise_LLVM_VERSION "${LLVM_PACKAGE_VERSION}") configure_file("cmake_config.h.in" "${PROJECT_BINARY_DIR}/config.h") @@ -187,6 +187,24 @@ @ONLY ) +configure_file( + "${PROJECT_SOURCE_DIR}/tests/test_cvise.py" + "${PROJECT_BINARY_DIR}/tests/test_cvise.py" + COPYONLY +) + +configure_file( + "${PROJECT_SOURCE_DIR}/tests/sources/blocksort-part.c" + "${PROJECT_BINARY_DIR}/tests/sources/blocksort-part.c" + COPYONLY +) + +configure_file( + "${PROJECT_SOURCE_DIR}/setup.cfg" + "${PROJECT_BINARY_DIR}/setup.cfg" + COPYONLY +) + install(PROGRAMS "${PROJECT_BINARY_DIR}/cvise.py" DESTINATION "${CMAKE_INSTALL_BINDIR}" RENAME "cvise" diff -Nru cvise-1.6.0/codecov.yml cvise-2.3.0/codecov.yml --- cvise-1.6.0/codecov.yml 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/codecov.yml 2021-03-09 08:18:13.000000000 +0000 @@ -2,11 +2,11 @@ disable_default_path_fixes: no fixes: - - "/usr/src/cvise/objdir/usr/src/cvise/objdir::" - - "/usr/src/cvise/objdir/usr/src/cvise::" + - "/__w/cvise/cvise/objdir::" + - "/__w/cvise/cvise/::" ignore: - "**/include" - "cvise/tests" - - "/usr/src/cvise/objdir/delta/topformflat.c" - - "/usr/src/cvise/objdir/clex/strlex.c" - - "/usr/src/cvise/objdir/clex/clex.c" + - "/__w/cvise/cvise/objdir/delta/topformflat.c" + - "/__w/cvise/cvise/objdir/clex/strlex.c" + - "/__w/cvise/cvise/objdir/clex/clex.c" diff -Nru cvise-1.6.0/CREDUCE_MERGE cvise-2.3.0/CREDUCE_MERGE --- cvise-1.6.0/CREDUCE_MERGE 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/CREDUCE_MERGE 2021-03-09 08:18:13.000000000 +0000 @@ -1,2 +1,2 @@ Last cherry-picked git revision: -274e1fe5210b379fbfdca9a565715d2db1df2d04 +c32c5c327758a047ae10e55a2465ba54293dfff9 diff -Nru cvise-1.6.0/cvise/cvise.py cvise-2.3.0/cvise/cvise.py --- cvise-1.6.0/cvise/cvise.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/cvise.py 2021-03-09 08:18:13.000000000 +0000 @@ -3,40 +3,56 @@ import os from cvise.passes.abstract import AbstractPass -from . import passes -from .utils.error import CViseError -from .utils.error import PassOptionError +from cvise.passes.balanced import BalancedPass +from cvise.passes.blank import BlankPass +from cvise.passes.clang import ClangPass +from cvise.passes.clangbinarysearch import ClangBinarySearchPass +from cvise.passes.clex import ClexPass +from cvise.passes.comments import CommentsPass +from cvise.passes.ifs import IfPass +from cvise.passes.includeincludes import IncludeIncludesPass +from cvise.passes.includes import IncludesPass +from cvise.passes.indent import IndentPass +from cvise.passes.ints import IntsPass +from cvise.passes.line_markers import LineMarkersPass +from cvise.passes.lines import LinesPass +from cvise.passes.peep import PeepPass +from cvise.passes.special import SpecialPass +from cvise.passes.ternary import TernaryPass +from cvise.passes.unifdef import UnIfDefPass +from cvise.utils.error import CViseError, PassOptionError + class CVise: class Info: - PACKAGE_BUGREPORT = "@cvise_PACKAGE_BUGREPORT@" - PACKAGE_NAME = "@cvise_PACKAGE_NAME@" - PACKAGE_STRING = "@cvise_PACKAGE_STRING@" - PACKAGE_URL = "@cvise_PACKAGE_URL@" - PACKAGE_VERSION = "@cvise_PACKAGE_VERSION@" - - VERSION = "@cvise_VERSION@" - GIT_VERSION = "@GIT_HASH@" - LLVM_VERSION = "@LLVM_VERSION@" + PACKAGE_BUGREPORT = '@cvise_PACKAGE_BUGREPORT@' + PACKAGE_NAME = '@cvise_PACKAGE_NAME@' + PACKAGE_STRING = '@cvise_PACKAGE_STRING@' + PACKAGE_URL = '@cvise_PACKAGE_URL@' + PACKAGE_VERSION = '@cvise_PACKAGE_VERSION@' + + VERSION = '@cvise_VERSION@' + GIT_VERSION = '@GIT_HASH@' + LLVM_VERSION = '@LLVM_VERSION@' pass_name_mapping = { - "balanced": passes.BalancedPass, - "blank": passes.BlankPass, - "clang": passes.ClangPass, - "clangbinarysearch": passes.ClangBinarySearchPass, - "clex": passes.ClexPass, - "comments": passes.CommentsPass, - "ifs": passes.IfPass, - "includeincludes": passes.IncludeIncludesPass, - "includes": passes.IncludesPass, - "indent": passes.IndentPass, - "ints": passes.IntsPass, - "line_markers": passes.LineMarkersPass, - "lines": passes.LinesPass, - "peep": passes.PeepPass, - "special": passes.SpecialPass, - "ternary": passes.TernaryPass, - "unifdef": passes.UnIfDefPass, + 'balanced': BalancedPass, + 'blank': BlankPass, + 'clang': ClangPass, + 'clangbinarysearch': ClangBinarySearchPass, + 'clex': ClexPass, + 'comments': CommentsPass, + 'ifs': IfPass, + 'includeincludes': IncludeIncludesPass, + 'includes': IncludesPass, + 'indent': IndentPass, + 'ints': IntsPass, + 'line_markers': LineMarkersPass, + 'lines': LinesPass, + 'peep': PeepPass, + 'special': SpecialPass, + 'ternary': TernaryPass, + 'unifdef': UnIfDefPass, } def __init__(self, test_manager): @@ -49,15 +65,15 @@ try: pass_group_dict = json.load(pass_group_file) except json.JSONDecodeError: - raise CViseError("Not valid JSON.") + raise CViseError('Not valid JSON.') return pass_group_dict @classmethod def parse_pass_group_dict(cls, pass_group_dict, pass_options, external_programs, remove_pass, - clang_delta_std, not_c, no_renaming): + clang_delta_std, clang_delta_preserve_routine, not_c, renaming): pass_group = {} - removed_passes = set(remove_pass.split(",")) if remove_pass else set() + removed_passes = set(remove_pass.split(',')) if remove_pass else set() def parse_options(options): valid_options = set() @@ -71,12 +87,12 @@ return valid_options def include_pass(pass_dict, options): - return ((("include" not in pass_dict) or bool(parse_options(pass_dict["include"]) & options)) and - (("exclude" not in pass_dict) or not bool(parse_options(pass_dict["exclude"]) & options))) + return ((('include' not in pass_dict) or bool(parse_options(pass_dict['include']) & options)) and + (('exclude' not in pass_dict) or not bool(parse_options(pass_dict['exclude']) & options))) - for category in ["first", "main", "last"]: + for category in ['first', 'main', 'last']: if category not in pass_group_dict: - raise CViseError("Missing category {}".format(category)) + raise CViseError('Missing category {}'.format(category)) pass_group[category] = [] @@ -84,50 +100,51 @@ if not include_pass(pass_dict, pass_options): continue - if "pass" not in pass_dict: - raise CViseError("Invalid pass in category {}".format(category)) + if 'pass' not in pass_dict: + raise CViseError('Invalid pass in category {}'.format(category)) try: - pass_class = cls.pass_name_mapping[pass_dict["pass"]] - except KeyValueError: - raise CViseError("Unkown pass {}".format(pass_dict["pass"])) + pass_class = cls.pass_name_mapping[pass_dict['pass']] + except KeyError: + raise CViseError('Unkown pass {}'.format(pass_dict['pass'])) - pass_instance = pass_class(pass_dict.get("arg"), external_programs) + pass_instance = pass_class(pass_dict.get('arg'), external_programs) if str(pass_instance) in removed_passes: continue - if not_c and "c" in pass_dict and pass_dict["c"]: + if not_c and 'c' in pass_dict and pass_dict['c']: continue - elif no_renaming and "renaming" in pass_dict and pass_dict["renaming"]: + elif not renaming and 'renaming' in pass_dict and pass_dict['renaming']: continue pass_instance.clang_delta_std = clang_delta_std + pass_instance.clang_delta_preserve_routine = clang_delta_preserve_routine pass_group[category].append(pass_instance) return pass_group - def reduce(self, pass_group, skip_initial=False): + def reduce(self, pass_group, skip_initial): self._check_prerequisites(pass_group) - self.test_manager.check_sanity() + self.test_manager.check_sanity(True) - logging.info("===< {} >===".format(os.getpid())) - logging.info("running {} interestingness test{} in parallel".format(self.test_manager.parallel_tests, - "" if self.test_manager.parallel_tests == 1 else "s")) + logging.info('===< {} >==='.format(os.getpid())) + logging.info('running {} interestingness test{} in parallel'.format(self.test_manager.parallel_tests, + '' if self.test_manager.parallel_tests == 1 else 's')) if not self.tidy: self.test_manager.backup_test_cases() if not skip_initial: - logging.info("INITIAL PASSES") - self._run_additional_passes(pass_group["first"]) + logging.info('INITIAL PASSES') + self._run_additional_passes(pass_group['first']) - logging.info("MAIN PASSES") - self._run_main_passes(pass_group["main"]) + logging.info('MAIN PASSES') + self._run_main_passes(pass_group['main']) - logging.info("CLEANUP PASSES") - self._run_additional_passes(pass_group["last"]) + logging.info('CLEANUP PASSES') + self._run_additional_passes(pass_group['last']) - logging.info("===================== done ====================") + logging.info('===================== done ====================') return True @staticmethod @@ -135,12 +152,12 @@ for category in pass_group: for p in pass_group[category]: if not p.check_prerequisites(): - logging.error("Prereqs not found for pass {}".format(p)) + logging.error('Prereqs not found for pass {}'.format(p)) def _run_additional_passes(self, passes): for p in passes: if not p.check_prerequisites(): - logging.error("Skipping {}".format(p)) + logging.error('Skipping {}'.format(p)) else: self.test_manager.run_pass(p) @@ -150,11 +167,11 @@ for p in passes: if not p.check_prerequisites(): - logging.error("Skipping pass {}".format(p)) + logging.error('Skipping pass {}'.format(p)) else: self.test_manager.run_pass(p) - logging.info("Termination check: size was {}; now {}".format(total_file_size, self.test_manager.total_file_size)) + logging.info('Termination check: size was {}; now {}'.format(total_file_size, self.test_manager.total_file_size)) - if self.test_manager.total_file_size >= total_file_size: + if self.test_manager.total_file_size >= total_file_size: break diff -Nru cvise-1.6.0/cvise/__init__.py cvise-2.3.0/cvise/__init__.py --- cvise-1.6.0/cvise/__init__.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/__init__.py 2021-03-09 08:18:13.000000000 +0000 @@ -1 +0,0 @@ -from .cvise import CVise diff -Nru cvise-1.6.0/cvise/passes/abstract.py cvise-2.3.0/cvise/passes/abstract.py --- cvise-1.6.0/cvise/passes/abstract.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/abstract.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,9 +1,9 @@ -import logging import copy +from enum import auto, Enum, unique +import logging import shutil import subprocess -from enum import Enum, auto, unique @unique class PassResult(Enum): @@ -12,6 +12,7 @@ STOP = auto() ERROR = auto() + class BinaryState: def __init__(self): pass @@ -46,10 +47,10 @@ self.chunk = int(self.chunk / 2) if self.chunk < 1: return None - logging.debug("granularity reduced to {}".format(self.chunk)) + logging.debug('granularity reduced to {}'.format(self.chunk)) self.index = 0 else: - logging.debug("***ADVANCE*** from {} to {} with chunk {}".format(original_index, self.index, self.chunk)) + logging.debug('***ADVANCE*** from {} to {} with chunk {}'.format(original_index, self.index, self.chunk)) return self def advance_on_success(self, instances): @@ -61,11 +62,12 @@ else: return self + class AbstractPass: @unique class Option(Enum): - slow = "slow" - windows = "windows" + slow = 'slow' + windows = 'windows' def __init__(self, arg=None, external_programs=None): self.external_programs = external_programs @@ -73,9 +75,9 @@ def __repr__(self): if self.arg is not None: - return "{}::{}".format(type(self).__name__, self.arg) + return '{}::{}'.format(type(self).__name__, self.arg) else: - return "{}".format(type(self).__name__) + return '{}'.format(type(self).__name__) def check_external_program(self, name): program = self.external_programs[name] @@ -83,13 +85,13 @@ return False result = shutil.which(program) is not None if not result: - logging.error("cannot find external program {}".format(name)) + logging.error('cannot find external program {}'.format(name)) return result def check_prerequisites(self): raise NotImplementedError("Class {} has not implemented 'check_prerequisites'!".format(type(self).__name__)) - def new(self, test_case): + def new(self, test_case, check_sanity): raise NotImplementedError("Class {} has not implemented 'new'!".format(type(self).__name__)) def advance(self, test_case, state): @@ -101,16 +103,19 @@ def transform(self, test_case, state, process_event_notifier): raise NotImplementedError("Class {} has not implemented 'transform'!".format(type(self).__name__)) + @unique class ProcessEventType(Enum): STARTED = auto() FINISHED = auto() + class ProcessEvent: def __init__(self, pid, event_type): self.pid = pid self.type = event_type + class ProcessEventNotifier: def __init__(self, pid_queue): self.pid_queue = pid_queue diff -Nru cvise-1.6.0/cvise/passes/balanced.py cvise-2.3.0/cvise/passes/balanced.py --- cvise-1.6.0/cvise/passes/balanced.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/balanced.py 2021-03-09 08:18:13.000000000 +0000 @@ -2,20 +2,21 @@ from cvise.utils import nestedmatcher from cvise.utils.error import UnknownArgumentError + class BalancedPass(AbstractPass): def check_prerequisites(self): return True def __get_next_match(self, test_case, pos): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() config = self.__get_config() - m = nestedmatcher.find(config["search"], prog, pos=pos, prefix=config["prefix"]) + m = nestedmatcher.find(config['search'], prog, pos=pos, prefix=config['prefix']) return m - def new(self, test_case): + def new(self, test_case, _=None): return self.__get_next_match(test_case, pos=0) def advance(self, test_case, state): @@ -25,10 +26,10 @@ return self.__get_next_match(test_case, pos=state[0]) def __get_config(self): - config = {"search": None, - "replace_fn": None, - "prefix": "", - } + config = {'search': None, + 'replace_fn': None, + 'prefix': '', + } def replace_all(string, match): return string[0:match[0]] + string[match[1]:] @@ -39,59 +40,59 @@ def replace_inside(string, match): return string[0:(match[0] + 1)] + string[(match[1] - 1):] - if self.arg == "square-inside": - config["search"] = nestedmatcher.BalancedExpr.squares - config["replace_fn"] = replace_inside - elif self.arg == "angles-inside": - config["search"] = nestedmatcher.BalancedExpr.angles - config["replace_fn"] = replace_inside - elif self.arg == "parens-inside": - config["search"] = nestedmatcher.BalancedExpr.parens - config["replace_fn"] = replace_inside - elif self.arg == "curly-inside": - config["search"] = nestedmatcher.BalancedExpr.curlies - config["replace_fn"] = replace_inside - elif self.arg == "square": - config["search"] = nestedmatcher.BalancedExpr.squares - config["replace_fn"] = replace_all - elif self.arg == "angles": - config["search"] = nestedmatcher.BalancedExpr.angles - config["replace_fn"] = replace_all - elif self.arg == "parens-to-zero": - config["search"] = nestedmatcher.BalancedExpr.parens - config["replace_fn"] = lambda string, match: string[0:match[0]] + "0" + string[match[1]:] - elif self.arg == "parens": - config["search"] = nestedmatcher.BalancedExpr.parens - config["replace_fn"] = replace_all - elif self.arg == "curly": - config["search"] = nestedmatcher.BalancedExpr.curlies - config["replace_fn"] = replace_all - elif self.arg == "curly2": - config["search"] = nestedmatcher.BalancedExpr.curlies - config["replace_fn"] = lambda string, match: string[0:match[0]] + ";" + string[match[1]:] - elif self.arg == "curly3": - config["search"] = nestedmatcher.BalancedExpr.curlies - config["replace_fn"] = replace_all - config["prefix"] = "=\\s*" - elif self.arg == "parens-only": - config["search"] = nestedmatcher.BalancedExpr.parens - config["replace_fn"] = replace_only - elif self.arg == "curly-only": - config["search"] = nestedmatcher.BalancedExpr.curlies - config["replace_fn"] = replace_only - elif self.arg == "angles-only": - config["search"] = nestedmatcher.BalancedExpr.angles - config["replace_fn"] = replace_only - elif self.arg == "square-only": - config["search"] = nestedmatcher.BalancedExpr.squares - config["replace_fn"] = replace_only + if self.arg == 'square-inside': + config['search'] = nestedmatcher.BalancedExpr.squares + config['replace_fn'] = replace_inside + elif self.arg == 'angles-inside': + config['search'] = nestedmatcher.BalancedExpr.angles + config['replace_fn'] = replace_inside + elif self.arg == 'parens-inside': + config['search'] = nestedmatcher.BalancedExpr.parens + config['replace_fn'] = replace_inside + elif self.arg == 'curly-inside': + config['search'] = nestedmatcher.BalancedExpr.curlies + config['replace_fn'] = replace_inside + elif self.arg == 'square': + config['search'] = nestedmatcher.BalancedExpr.squares + config['replace_fn'] = replace_all + elif self.arg == 'angles': + config['search'] = nestedmatcher.BalancedExpr.angles + config['replace_fn'] = replace_all + elif self.arg == 'parens-to-zero': + config['search'] = nestedmatcher.BalancedExpr.parens + config['replace_fn'] = lambda string, match: string[0:match[0]] + '0' + string[match[1]:] + elif self.arg == 'parens': + config['search'] = nestedmatcher.BalancedExpr.parens + config['replace_fn'] = replace_all + elif self.arg == 'curly': + config['search'] = nestedmatcher.BalancedExpr.curlies + config['replace_fn'] = replace_all + elif self.arg == 'curly2': + config['search'] = nestedmatcher.BalancedExpr.curlies + config['replace_fn'] = lambda string, match: string[0:match[0]] + ';' + string[match[1]:] + elif self.arg == 'curly3': + config['search'] = nestedmatcher.BalancedExpr.curlies + config['replace_fn'] = replace_all + config['prefix'] = '=\\s*' + elif self.arg == 'parens-only': + config['search'] = nestedmatcher.BalancedExpr.parens + config['replace_fn'] = replace_only + elif self.arg == 'curly-only': + config['search'] = nestedmatcher.BalancedExpr.curlies + config['replace_fn'] = replace_only + elif self.arg == 'angles-only': + config['search'] = nestedmatcher.BalancedExpr.angles + config['replace_fn'] = replace_only + elif self.arg == 'square-only': + config['search'] = nestedmatcher.BalancedExpr.squares + config['replace_fn'] = replace_only else: raise UnknownArgumentError(self.__class__.__name__, self.arg) return config def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() prog2 = prog @@ -101,10 +102,10 @@ if state is None: return (PassResult.STOP, state) else: - prog2 = config["replace_fn"](prog2, state) + prog2 = config['replace_fn'](prog2, state) if prog != prog2: - with open(test_case, "w") as out_file: + with open(test_case, 'w') as out_file: out_file.write(prog2) return (PassResult.OK, state) diff -Nru cvise-1.6.0/cvise/passes/blank.py cvise-2.3.0/cvise/passes/blank.py --- cvise-1.6.0/cvise/passes/blank.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/blank.py 2021-03-09 08:18:13.000000000 +0000 @@ -5,11 +5,12 @@ from cvise.passes.abstract import AbstractPass, PassResult + class BlankPass(AbstractPass): def check_prerequisites(self): return True - def new(self, test_case): + def new(self, test_case, _=None): return 0 def advance(self, test_case, state): @@ -21,15 +22,15 @@ @staticmethod def __transform(test_case, pattern): tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w+", delete=False, dir=tmp) as tmp_file: - with open(test_case, "r") as in_file: + with tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) as tmp_file: + with open(test_case, 'r') as in_file: matched = False - for l in in_file: - if re.match(pattern, l) is not None: + for line in in_file: + if re.match(pattern, line) is not None: matched = True else: - tmp_file.write(l) + tmp_file.write(line) if matched: shutil.move(tmp_file.name, test_case) @@ -39,7 +40,7 @@ return matched def transform(self, test_case, state, process_event_notifier): - patterns = [r"^\s*$", r"^#"] + patterns = [r'^\s*$', r'^#'] if state >= len(patterns): return (PassResult.STOP, state) diff -Nru cvise-1.6.0/cvise/passes/clangbinarysearch.py cvise-2.3.0/cvise/passes/clangbinarysearch.py --- cvise-1.6.0/cvise/passes/clangbinarysearch.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/clangbinarysearch.py 2021-03-09 08:18:13.000000000 +0000 @@ -8,9 +8,10 @@ from cvise.passes.abstract import AbstractPass, BinaryState, PassResult + class ClangBinarySearchPass(AbstractPass): def check_prerequisites(self): - return self.check_external_program("clang_delta") + return self.check_external_program('clang_delta') def detect_best_standard(self, test_case): best = None @@ -24,12 +25,13 @@ if instances > best_count: best = std best_count = instances - logging.debug('available instances for %s: %d, took: %.2f s' % (std, instances, took)) - logging.info('using C++ standard: %s with %d instances' % (best, best_count)) + logging.debug('available transformation opportunities for %s: %d, took: %.2f s' % (std, instances, took)) + logging.info('using C++ standard: %s with %d transformation opportunities' % (best, best_count)) self.clang_delta_std = best - def new(self, test_case): - self.detect_best_standard(test_case) + def new(self, test_case, _=None): + if not self.clang_delta_std: + self.detect_best_standard(test_case) return BinaryState.create(self.count_instances(test_case)) def advance(self, test_case, state): @@ -43,17 +45,23 @@ return state def count_instances(self, test_case): - args = [self.external_programs["clang_delta"], "--query-instances={}".format(self.arg)] + args = [self.external_programs['clang_delta'], '--query-instances={}'.format(self.arg)] if self.clang_delta_std: args.append('--std={}'.format(self.clang_delta_std)) + if self.clang_delta_preserve_routine: + args.append(f'--preserve-routine="{self.clang_delta_preserve_routine}"') cmd = args + [test_case] try: proc = subprocess.run(cmd, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except subprocess.SubprocessError: + except subprocess.SubprocessError as e: + logging.warning(f'clang_delta --query-instances failed: {e}') return 0 - m = re.match("Available transformation instances: ([0-9]+)$", proc.stdout) + if proc.returncode != 0: + logging.warning(f'clang_delta --query-instances failed with exit code {proc.returncode}: {proc.stderr.strip()}') + + m = re.match('Available transformation instances: ([0-9]+)$', proc.stdout) if m is None: return 0 @@ -70,16 +78,18 @@ pass def transform(self, test_case, state, process_event_notifier): - logging.debug("TRANSFORM: index = {}, chunk = {}, instances = {}".format(state.index, state.chunk, state.instances)) + logging.debug('TRANSFORM: index = {}, chunk = {}, instances = {}'.format(state.index, state.chunk, state.instances)) tmp = os.path.dirname(test_case) with tempfile.NamedTemporaryFile(mode='w', delete=False, dir=tmp) as tmp_file: - args = ["--transformation={}".format(self.arg), "--counter={}".format(state.index + 1), "--to-counter={}".format(state.end()), - "--warn-on-counter-out-of-bounds", "--report-instances-count"] + args = ['--transformation={}'.format(self.arg), '--counter={}'.format(state.index + 1), '--to-counter={}'.format(state.end()), + '--warn-on-counter-out-of-bounds', '--report-instances-count'] if self.clang_delta_std: args.append('--std={}'.format(self.clang_delta_std)) - cmd = [self.external_programs["clang_delta"]] + args + [test_case] - logging.debug(" ".join(cmd)) + if self.clang_delta_preserve_routine: + args.append(f'--preserve-routine="{self.clang_delta_preserve_routine}"') + cmd = [self.external_programs['clang_delta']] + args + [test_case] + logging.debug(' '.join(cmd)) stdout, stderr, returncode = process_event_notifier.run_process(cmd) self.parse_stderr(state, stderr) diff -Nru cvise-1.6.0/cvise/passes/clang.py cvise-2.3.0/cvise/passes/clang.py --- cvise-1.6.0/cvise/passes/clang.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/clang.py 2021-03-09 08:18:13.000000000 +0000 @@ -5,11 +5,12 @@ from cvise.passes.abstract import AbstractPass, PassResult + class ClangPass(AbstractPass): def check_prerequisites(self): - return self.check_external_program("clang_delta") + return self.check_external_program('clang_delta') - def new(self, test_case): + def new(self, test_case, _=None): return 1 def advance(self, test_case, state): @@ -20,13 +21,13 @@ def transform(self, test_case, state, process_event_notifier): tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w", delete=False, dir=tmp) as tmp_file: - args = [self.external_programs["clang_delta"], "--transformation={}".format(self.arg), "--counter={}".format(state)] + with tempfile.NamedTemporaryFile(mode='w', delete=False, dir=tmp) as tmp_file: + args = [self.external_programs['clang_delta'], '--transformation={}'.format(self.arg), '--counter={}'.format(state)] if self.clang_delta_std: args.append('--std={}'.format(self.clang_delta_std)) cmd = args + [test_case] - logging.debug(" ".join(cmd)) + logging.debug(' '.join(cmd)) stdout, stderr, returncode = process_event_notifier.run_process(cmd) if returncode == 0: diff -Nru cvise-1.6.0/cvise/passes/clex.py cvise-2.3.0/cvise/passes/clex.py --- cvise-1.6.0/cvise/passes/clex.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/clex.py 2021-03-09 08:18:13.000000000 +0000 @@ -4,11 +4,12 @@ from cvise.passes.abstract import AbstractPass, PassResult + class ClexPass(AbstractPass): def check_prerequisites(self): - return self.check_external_program("clex") + return self.check_external_program('clex') - def new(self, test_case): + def new(self, test_case, _=None): return 0 def advance(self, test_case, state): @@ -19,8 +20,8 @@ def transform(self, test_case, state, process_event_notifier): tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w", delete=False, dir=tmp) as tmp_file: - cmd = [self.external_programs["clex"], str(self.arg), str(state), test_case] + with tempfile.NamedTemporaryFile(mode='w', delete=False, dir=tmp) as tmp_file: + cmd = [self.external_programs['clex'], str(self.arg), str(state), test_case] stdout, stderr, returncode = process_event_notifier.run_process(cmd) if returncode == 51: tmp_file.write(stdout) diff -Nru cvise-1.6.0/cvise/passes/comments.py cvise-2.3.0/cvise/passes/comments.py --- cvise-1.6.0/cvise/passes/comments.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/comments.py 2021-03-09 08:18:13.000000000 +0000 @@ -2,11 +2,12 @@ from cvise.passes.abstract import AbstractPass, PassResult + class CommentsPass(AbstractPass): def check_prerequisites(self): return True - def new(self, test_case): + def new(self, test_case, _=None): return -2 def advance(self, test_case, state): @@ -16,24 +17,24 @@ return state def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() prog2 = prog while True: - #TODO: remove only the nth comment + # TODO: remove only the nth comment if state == -2: # Remove all multiline comments # Replace /* any number of * if not followed by / or anything but * */ - prog2 = re.sub(r"/\*(?:\*(?!/)|[^*])*\*/", "", prog2, flags=re.DOTALL) + prog2 = re.sub(r'/\*(?:\*(?!/)|[^*])*\*/', '', prog2, flags=re.DOTALL) elif state == -1: # Remove all single line comments - prog2 = re.sub(r"//.*$", "", prog2, flags=re.MULTILINE) + prog2 = re.sub(r'//.*$', '', prog2, flags=re.MULTILINE) else: return (PassResult.STOP, state) if prog != prog2: - with open(test_case, "w") as out_file: + with open(test_case, 'w') as out_file: out_file.write(prog2) return (PassResult.OK, state) diff -Nru cvise-1.6.0/cvise/passes/ifs.py cvise-2.3.0/cvise/passes/ifs.py --- cvise-1.6.0/cvise/passes/ifs.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/ifs.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,14 +1,15 @@ import os -import tempfile import re +import tempfile from cvise.passes.abstract import AbstractPass, BinaryState, PassResult + class IfPass(AbstractPass): line_regex = re.compile('^\\s*#\\s*if') def check_prerequisites(self): - return self.check_external_program("unifdef") + return self.check_external_program('unifdef') @staticmethod def __macro_continues(line): @@ -17,7 +18,7 @@ def __count_instances(self, test_case): count = 0 in_multiline = False - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: for line in in_file.readlines(): if in_multiline: if self.__macro_continues(line): @@ -31,7 +32,7 @@ in_multiline = True return count - def new(self, test_case): + def new(self, test_case, _=None): bs = BinaryState.create(self.__count_instances(test_case)) if bs: bs.value = 0 @@ -39,10 +40,12 @@ def advance(self, test_case, state): if state.value == 0: + state = state.copy() state.value = 1 else: - state.advance() - state.value = 0 + state = state.advance() + if state: + state.value = 0 return state def advance_on_success(self, test_case, state): @@ -50,8 +53,8 @@ def transform(self, test_case, state, process_event_notifier): tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w+", delete=False, dir=tmp) as tmp_file: - with open(test_case, "r") as in_file: + with tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) as tmp_file: + with open(test_case, 'r') as in_file: i = 0 in_multiline = False for line in in_file.readlines(): @@ -63,14 +66,13 @@ if self.line_regex.search(line): if state.index <= i and i < state.end(): - tmp_file.write('#if {0}\n'.format(state.value)) + if self.__macro_continues(line): + in_multiline = True + line = '#if {0}\n'.format(state.value) i += 1 - if self.__macro_continues(line): - in_multiline = True - else: - tmp_file.write(line) + tmp_file.write(line) - cmd = [self.external_programs["unifdef"], "-B", "-x", "2", "-k", "-o", test_case, tmp_file.name] + cmd = [self.external_programs['unifdef'], '-B', '-x', '2', '-k', '-o', test_case, tmp_file.name] stdout, stderr, returncode = process_event_notifier.run_process(cmd) if returncode != 0: return (PassResult.ERROR, state) diff -Nru cvise-1.6.0/cvise/passes/includeincludes.py cvise-2.3.0/cvise/passes/includeincludes.py --- cvise-1.6.0/cvise/passes/includeincludes.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/includeincludes.py 2021-03-09 08:18:13.000000000 +0000 @@ -5,11 +5,12 @@ from cvise.passes.abstract import AbstractPass, PassResult + class IncludeIncludesPass(AbstractPass): def check_prerequisites(self): return True - def new(self, test_case): + def new(self, test_case, _=None): return 1 def advance(self, test_case, state): @@ -19,21 +20,21 @@ return state def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w+", delete=False, dir=tmp) as tmp_file: + with tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) as tmp_file: includes = 0 matched = False for line in in_file: - include_match = re.match(r'\s*#\s*include\s*"(.*?)"', line) + include_match = re.match(r"\s*#\s*include\s*'(.*?)'", line) if include_match is not None: includes += 1 if includes == state: try: - with open(include_match.group(1), "r") as inc_file: + with open(include_match.group(1), 'r') as inc_file: matched = True tmp_file.write(inc_file.read()) # Go to next include diff -Nru cvise-1.6.0/cvise/passes/includes.py cvise-2.3.0/cvise/passes/includes.py --- cvise-1.6.0/cvise/passes/includes.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/includes.py 2021-03-09 08:18:13.000000000 +0000 @@ -5,11 +5,12 @@ from cvise.passes.abstract import AbstractPass, PassResult + class IncludesPass(AbstractPass): def check_prerequisites(self): return True - def new(self, test_case): + def new(self, test_case, _=None): return 1 def advance(self, test_case, state): @@ -20,13 +21,13 @@ def transform(self, test_case, state, process_event_notifier): tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w+", delete=False, dir=tmp) as tmp_file: - with open(test_case, "r") as in_file: + with tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) as tmp_file: + with open(test_case, 'r') as in_file: includes = 0 matched = False for line in in_file: - include_match = re.match(r"\s*#\s*include", line) + include_match = re.match(r'\s*#\s*include', line) if include_match is not None: includes += 1 diff -Nru cvise-1.6.0/cvise/passes/indent.py cvise-2.3.0/cvise/passes/indent.py --- cvise-1.6.0/cvise/passes/indent.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/indent.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,11 +1,12 @@ from cvise.passes.abstract import AbstractPass, PassResult from cvise.utils.error import UnknownArgumentError + class IndentPass(AbstractPass): def check_prerequisites(self): - return self.check_external_program("clang-format") + return self.check_external_program('clang-format') - def new(self, test_case): + def new(self, test_case, _=None): return 0 def advance(self, test_case, state): @@ -15,17 +16,17 @@ return state + 1 def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: old = in_file.read() if state != 0: return (PassResult.STOP, state) - cmd = [self.external_programs["clang-format"], "-i"] + cmd = [self.external_programs['clang-format'], '-i'] - if self.arg == "regular": - cmd.extend(["-style", "{SpacesInAngles: true}", test_case]) - elif self.arg == "final": + if self.arg == 'regular': + cmd.extend(['-style', '{SpacesInAngles: true}', test_case]) + elif self.arg == 'final': cmd.append(test_case) else: raise UnknownArgumentError(self.__class__.__name__, self.arg) @@ -34,7 +35,7 @@ if returncode != 0: return (PassResult.ERROR, state) - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: new = in_file.read() if old == new: diff -Nru cvise-1.6.0/cvise/passes/__init__.py cvise-2.3.0/cvise/passes/__init__.py --- cvise-1.6.0/cvise/passes/__init__.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/__init__.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,17 +0,0 @@ -from .balanced import BalancedPass -from .blank import BlankPass -from .clang import ClangPass -from .clangbinarysearch import ClangBinarySearchPass -from .clex import ClexPass -from .comments import CommentsPass -from .ifs import IfPass -from .includeincludes import IncludeIncludesPass -from .includes import IncludesPass -from .indent import IndentPass -from .ints import IntsPass -from .line_markers import LineMarkersPass -from .lines import LinesPass -from .peep import PeepPass -from .special import SpecialPass -from .ternary import TernaryPass -from .unifdef import UnIfDefPass diff -Nru cvise-1.6.0/cvise/passes/ints.py cvise-2.3.0/cvise/passes/ints.py --- cvise-1.6.0/cvise/passes/ints.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/ints.py 2021-03-09 08:18:13.000000000 +0000 @@ -3,61 +3,62 @@ from cvise.passes.abstract import AbstractPass, PassResult from cvise.utils.error import UnknownArgumentError + class IntsPass(AbstractPass): - border_or_space = r"(?:(?:[*,:;{}[\]()])|\s)" + border_or_space = r'(?:(?:[*,:;{}[\]()])|\s)' def check_prerequisites(self): return True def __get_config(self): - config = {"search": None, - "replace_fn": None, - } + config = {'search': None, + 'replace_fn': None, + } - if self.arg == "a": + if self.arg == 'a': # Delete first digit def replace_fn(m): - return m.group("pref") + m.group("numpart") + m.group("suf") + return m.group('pref') + m.group('numpart') + m.group('suf') - config["search"] = r"(?P" + self.border_or_space + r"[+-]?(?:0|(?:0[xX]))?)[0-9a-fA-F](?P[0-9a-fA-F]+)(?P[ULul]*" + self.border_or_space + r")" - elif self.arg == "b": + config['search'] = r'(?P' + self.border_or_space + r'[+-]?(?:0|(?:0[xX]))?)[0-9a-fA-F](?P[0-9a-fA-F]+)(?P[ULul]*' + self.border_or_space + r')' + elif self.arg == 'b': # Delete prefix def replace_fn(m): - return m.group("del") + m.group("numpart") + m.group("suf") + return m.group('del') + m.group('numpart') + m.group('suf') - config["search"] = r"(?P" + self.border_or_space + r")(?P[+-]?(?:0|(?:0[xX])))(?P[0-9a-fA-F]+)(?P[ULul]*" + self.border_or_space + r")" - elif self.arg == "c": + config['search'] = r'(?P' + self.border_or_space + r')(?P[+-]?(?:0|(?:0[xX])))(?P[0-9a-fA-F]+)(?P[ULul]*' + self.border_or_space + r')' + elif self.arg == 'c': # Delete suffix def replace_fn(m): - return m.group("pref") + m.group("numpart") + m.group("del") + return m.group('pref') + m.group('numpart') + m.group('del') - config["search"] = r"(?P" + self.border_or_space + r"[+-]?(?:0|(?:0[xX]))?)(?P[0-9a-fA-F]+)[ULul]+(?P" + self.border_or_space + r")" - elif self.arg == "d": + config['search'] = r'(?P' + self.border_or_space + r'[+-]?(?:0|(?:0[xX]))?)(?P[0-9a-fA-F]+)[ULul]+(?P' + self.border_or_space + r')' + elif self.arg == 'd': # Hex to dec def replace_fn(m): - return m.group("pref") + str(int(m.group("numpart"), 16)) + m.group("suf") + return m.group('pref') + str(int(m.group('numpart'), 16)) + m.group('suf') - config["search"] = r"(?P" + self.border_or_space + r")(?P0[Xx][0-9a-fA-F]+)(?P[ULul]*" + self.border_or_space + r")" + config['search'] = r'(?P' + self.border_or_space + r')(?P0[Xx][0-9a-fA-F]+)(?P[ULul]*' + self.border_or_space + r')' else: raise UnknownArgumentError(self.__class__.__name__, self.arg) - config["replace_fn"] = replace_fn + config['replace_fn'] = replace_fn return config - def new(self, test_case): + def new(self, test_case, _=None): config = self.__get_config() - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() - regex = re.compile(config["search"], flags=re.DOTALL) - modifications = list(reversed([(m.span(), config["replace_fn"](m)) for m in regex.finditer(prog)])) + regex = re.compile(config['search'], flags=re.DOTALL) + modifications = list(reversed([(m.span(), config['replace_fn'](m)) for m in regex.finditer(prog)])) if not modifications: return None - return {"modifications": modifications, "index": 0} + return {'modifications': modifications, 'index': 0} def advance(self, test_case, state): state = state.copy() - state["index"] += 1 - if state["index"] >= len(state["modifications"]): + state['index'] += 1 + if state['index'] >= len(state['modifications']): return None return state @@ -65,11 +66,11 @@ return self.new(test_case) def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: data = in_file.read() - index = state["index"] - ((start, end), replacement) = state["modifications"][index] + index = state['index'] + ((start, end), replacement) = state['modifications'][index] new_data = data[:start] + replacement + data[end:] - with open(test_case, "w") as out_file: + with open(test_case, 'w') as out_file: out_file.write(new_data) return (PassResult.OK, state) diff -Nru cvise-1.6.0/cvise/passes/line_markers.py cvise-2.3.0/cvise/passes/line_markers.py --- cvise-1.6.0/cvise/passes/line_markers.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/line_markers.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,10 +1,11 @@ +import os +import re import shutil import tempfile -import re -import os from cvise.passes.abstract import AbstractPass, BinaryState, PassResult + class LineMarkersPass(AbstractPass): line_regex = re.compile('^\\s*#\\s*[0-9]+') @@ -13,13 +14,13 @@ def __count_instances(self, test_case): count = 0 - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: for line in in_file.readlines(): if self.line_regex.search(line): count += 1 return count - def new(self, test_case): + def new(self, test_case, _=None): return BinaryState.create(self.__count_instances(test_case)) def advance(self, test_case, state): @@ -30,8 +31,8 @@ def transform(self, test_case, state, process_event_notifier): tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w+", delete=False, dir=tmp) as tmp_file: - with open(test_case, "r") as in_file: + with tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) as tmp_file: + with open(test_case, 'r') as in_file: i = 0 for line in in_file.readlines(): if self.line_regex.search(line): diff -Nru cvise-1.6.0/cvise/passes/lines.py cvise-2.3.0/cvise/passes/lines.py --- cvise-1.6.0/cvise/passes/lines.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/lines.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,39 +1,60 @@ +import logging +import os import shutil import subprocess import tempfile -import os from cvise.passes.abstract import AbstractPass, BinaryState, PassResult +from cvise.utils.error import InsaneTestCaseError + class LinesPass(AbstractPass): def check_prerequisites(self): - return self.check_external_program("topformflat") + return self.check_external_program('topformflat') - def __format(self, test_case): + def __format(self, test_case, check_sanity): tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w+", delete=False, dir=tmp) as tmp_file: - with open(test_case, "r") as in_file: + with tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) as tmp_file: + with open(test_case, 'r') as in_file: try: - cmd = [self.external_programs["topformflat"], self.arg] + cmd = [self.external_programs['topformflat'], self.arg] proc = subprocess.run(cmd, stdin=in_file, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) except subprocess.SubprocessError: - return (PassResult.ERROR, new_state) + return - for l in proc.stdout.splitlines(keepends=True): - if not l.isspace(): - tmp_file.write(l) - - shutil.move(tmp_file.name, test_case) + for line in proc.stdout.splitlines(keepends=True): + if not line.isspace(): + tmp_file.write(line) + + # we need to check that sanity check is still fine + if check_sanity: + backup = tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) + shutil.copyfile(test_case, backup.name) + shutil.move(tmp_file.name, test_case) + try: + check_sanity() + os.unlink(backup.name) + except InsaneTestCaseError: + shutil.move(backup.name, test_case) + # if we are not the first lines pass, we should bail out + if self.arg != '0': + self.bailout = True + else: + shutil.move(tmp_file.name, test_case) def __count_instances(self, test_case): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: lines = in_file.readlines() return len(lines) - def new(self, test_case): + def new(self, test_case, check_sanity=None): + self.bailout = False # None means no topformflat if self.arg != 'None': - self.__format(test_case) + self.__format(test_case, check_sanity) + if self.bailout: + logging.warning('Skipping pass as sanity check fails for topformflat output') + return None instances = self.__count_instances(test_case) return BinaryState.create(instances) @@ -44,7 +65,7 @@ return state.advance_on_success(self.__count_instances(test_case)) def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: data = in_file.readlines() old_len = len(data) @@ -52,7 +73,7 @@ assert len(data) < old_len tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w+", delete=False, dir=tmp) as tmp_file: + with tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) as tmp_file: tmp_file.writelines(data) shutil.move(tmp_file.name, test_case) diff -Nru cvise-1.6.0/cvise/passes/peep.py cvise-2.3.0/cvise/passes/peep.py --- cvise-1.6.0/cvise/passes/peep.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/peep.py 2021-03-09 08:18:13.000000000 +0000 @@ -2,152 +2,153 @@ from cvise.passes.abstract import AbstractPass, PassResult from cvise.utils import nestedmatcher +from cvise.utils.error import UnknownArgumentError + class PeepPass(AbstractPass): - border = r"[*{([:,})\];]" - border_or_space = r"(?:(?:" + border + r")|\s)" - border_or_space_optional = r"(?:(?:" + border + r")|\s)?" + border = r'[*{([:,})\];]' + border_or_space = r'(?:(?:' + border + r')|\s)' + border_or_space_optional = r'(?:(?:' + border + r')|\s)?' border_or_space_pattern = nestedmatcher.RegExPattern(border_or_space) border_or_space_optional_pattern = nestedmatcher.RegExPattern(border_or_space_optional) - varnum = r"(?:[-+]?[0-9a-zA-Z\_]+)" + varnum = r'(?:[-+]?[0-9a-zA-Z\_]+)' varnum_pattern = nestedmatcher.RegExPattern(varnum) balanced_parens_pattern = nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens) varnumexp_pattern = nestedmatcher.OrPattern(varnum_pattern, balanced_parens_pattern) - call_parts = [varnum_pattern, nestedmatcher.RegExPattern(r"\s*"), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens)] + call_parts = [varnum_pattern, nestedmatcher.RegExPattern(r'\s*'), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens)] - field = r"\.(?:" + varnum + r")" - index = r"\[(?:" + varnum + r")\]" - fullvar = [nestedmatcher.RegExPattern(r"[&*]*"), varnumexp_pattern, nestedmatcher.RegExPattern(r"(?:(?:" + field + r")|(?:" + index + r"))*")] - arith = r"\+|-|%|/|\*" - comp = r"<=|>=|<|>|==|!=|=" - logic = r"&&|\|\|" - bit = r"\||&|\^|<<|>>" - binop = [nestedmatcher.RegExPattern(r"(?:" + arith + r")|(?:" + comp + r")|(?:" + logic + r")|(?:" + bit + r")|->")] + field = r'\.(?:' + varnum + r')' + index = r'\[(?:' + varnum + r')\]' + fullvar = [nestedmatcher.RegExPattern(r'[&*]*'), varnumexp_pattern, nestedmatcher.RegExPattern(r'(?:(?:' + field + r')|(?:' + index + r'))*')] + arith = r'\+|-|%|/|\*' + comp = r'<=|>=|<|>|==|!=|=' + logic = r'&&|\|\|' + bit = r'\||&|\^|<<|>>' + binop = [nestedmatcher.RegExPattern(r'(?:' + arith + r')|(?:' + comp + r')|(?:' + logic + r')|(?:' + bit + r')|->')] regexes_to_replace = [ - ([nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.angles)], ""), - ([nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens)], ""), - ([nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ""), - ([nestedmatcher.RegExPattern(r"namespace[^{]*"), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ""), - ([nestedmatcher.RegExPattern(r"=\s*"), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ""), - ([nestedmatcher.RegExPattern(r":\s*[0-9]+\s*;")], ";"), - ([nestedmatcher.RegExPattern(r";")], ""), - ([nestedmatcher.RegExPattern(r"\^=")], "="), - ([nestedmatcher.RegExPattern(r"\|=")], "="), - ([nestedmatcher.RegExPattern(r"\+=\s*1")], "++"), - ([nestedmatcher.RegExPattern(r"-=\s*1")], "--"), - ([nestedmatcher.RegExPattern(r"&=")], "="), - ([nestedmatcher.RegExPattern(r'".*"')], ""), - ([nestedmatcher.RegExPattern(r"checksum = ")], ""), - ([nestedmatcher.RegExPattern(r"'.*'")], ""), - ([nestedmatcher.RegExPattern(r"&=")], "="), - ([nestedmatcher.RegExPattern(r"\+=")], "="), - ([nestedmatcher.RegExPattern(r"-=")], "="), - ([nestedmatcher.RegExPattern(r"\*=")], "="), - ([nestedmatcher.RegExPattern(r"/=")], "="), - ([nestedmatcher.RegExPattern(r"%=")], "="), - ([nestedmatcher.RegExPattern(r"<<=")], "="), - ([nestedmatcher.RegExPattern(r">>=")], "="), - ([nestedmatcher.RegExPattern(r"\+")], ""), - ([nestedmatcher.RegExPattern(r"-")], ""), - ([nestedmatcher.RegExPattern(r":")], ""), - ([nestedmatcher.RegExPattern(r",")], ""), - ([nestedmatcher.RegExPattern(r"::")], ""), - ([nestedmatcher.RegExPattern(r"!")], ""), - ([nestedmatcher.RegExPattern(r"~")], ""), - ([nestedmatcher.RegExPattern(r"while")], "if"), - ([nestedmatcher.RegExPattern(r'"[^"]*"')], ""), - ([nestedmatcher.RegExPattern(r'"[^"]*",')], ""), - ([nestedmatcher.RegExPattern(r"struct\s*[^{]*\s*"), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ""), - ([nestedmatcher.RegExPattern(r"union\s*[^{]*\s*"), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ""), - ([nestedmatcher.RegExPattern(r"enum\s*[^{]*\s*"), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ""), - ([nestedmatcher.RegExPattern(r"if\s*"), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens)], ""), + ([nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.angles)], ''), + ([nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens)], ''), + ([nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ''), + ([nestedmatcher.RegExPattern(r'namespace[^{]*'), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ''), + ([nestedmatcher.RegExPattern(r'=\s*'), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ''), + ([nestedmatcher.RegExPattern(r':\s*[0-9]+\s*;')], ';'), + ([nestedmatcher.RegExPattern(r';')], ''), + ([nestedmatcher.RegExPattern(r'\^=')], '='), + ([nestedmatcher.RegExPattern(r'\|=')], '='), + ([nestedmatcher.RegExPattern(r'\+=\s*1')], '++'), + ([nestedmatcher.RegExPattern(r'-=\s*1')], '--'), + ([nestedmatcher.RegExPattern(r'&=')], '='), + ([nestedmatcher.RegExPattern(r"'.*'")], ''), + ([nestedmatcher.RegExPattern(r'checksum = ')], ''), + ([nestedmatcher.RegExPattern(r"'.*'")], ''), + ([nestedmatcher.RegExPattern(r'&=')], '='), + ([nestedmatcher.RegExPattern(r'\+=')], '='), + ([nestedmatcher.RegExPattern(r'-=')], '='), + ([nestedmatcher.RegExPattern(r'\*=')], '='), + ([nestedmatcher.RegExPattern(r'/=')], '='), + ([nestedmatcher.RegExPattern(r'%=')], '='), + ([nestedmatcher.RegExPattern(r'<<=')], '='), + ([nestedmatcher.RegExPattern(r'>>=')], '='), + ([nestedmatcher.RegExPattern(r'\+')], ''), + ([nestedmatcher.RegExPattern(r'-')], ''), + ([nestedmatcher.RegExPattern(r':')], ''), + ([nestedmatcher.RegExPattern(r',')], ''), + ([nestedmatcher.RegExPattern(r'::')], ''), + ([nestedmatcher.RegExPattern(r'!')], ''), + ([nestedmatcher.RegExPattern(r'~')], ''), + ([nestedmatcher.RegExPattern(r'while')], 'if'), + ([nestedmatcher.RegExPattern(r"'[^']*'")], ''), + ([nestedmatcher.RegExPattern(r"'[^']*',")], ''), + ([nestedmatcher.RegExPattern(r'struct\s*[^{]*\s*'), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ''), + ([nestedmatcher.RegExPattern(r'union\s*[^{]*\s*'), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ''), + ([nestedmatcher.RegExPattern(r'enum\s*[^{]*\s*'), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies)], ''), + ([nestedmatcher.RegExPattern(r'if\s*'), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens)], ''), ] # these match when preceded and followed by border_or_space delimited_regexes_to_replace = [ - ([varnumexp_pattern, nestedmatcher.RegExPattern(r"\s*:")], ""), - ([varnumexp_pattern, nestedmatcher.RegExPattern(r"\s*:")], ""), - ([nestedmatcher.RegExPattern(r"goto\s+(?:" + varnum + r");")], ""), - ([nestedmatcher.RegExPattern(r"class")], "struct"), - ([nestedmatcher.RegExPattern(r"char")], "int"), - ([nestedmatcher.RegExPattern(r"short")], "int"), - ([nestedmatcher.RegExPattern(r"long")], "int"), - ([nestedmatcher.RegExPattern(r"signed")], "int"), - ([nestedmatcher.RegExPattern(r"unsigned")], "int"), - ([nestedmatcher.RegExPattern(r"float")], "int"), - ([nestedmatcher.RegExPattern(r"double")], "int"), - ([nestedmatcher.RegExPattern(r"wchar_t")], "int"), - ([nestedmatcher.RegExPattern(r"bool")], "int"), - ([nestedmatcher.RegExPattern(r"typeof\s+(?:" + varnum + r")")], "int"), - ([nestedmatcher.RegExPattern(r"__typeof__\s+(?:" + varnum + r")")], "int"), - ([nestedmatcher.RegExPattern(r"int\s+argc\s*,\s*.*\s*\*argv\[\]")], "void"), - ([nestedmatcher.RegExPattern(r"int\s+argc\s*,\s*.*\s*\*\s*\*argv")], "void"), - ([nestedmatcher.RegExPattern(r"int[^;]*;")], ""), - ([nestedmatcher.RegExPattern(r"for")], ""), - ([nestedmatcher.RegExPattern(r'".*"')], ""), - ([nestedmatcher.RegExPattern(r"'.*'")], ""), - ([nestedmatcher.RegExPattern(r'"[^"]*"')], ""), - ([nestedmatcher.RegExPattern(r"'[^']*'")], ""), - ([nestedmatcher.RegExPattern(r'""')], "0"), - (call_parts + [nestedmatcher.RegExPattern(r",")], "0"), - (call_parts + [nestedmatcher.RegExPattern(r",")], ""), - (call_parts, "0"), - (call_parts, ""), - ] + ([varnumexp_pattern, nestedmatcher.RegExPattern(r'\s*:')], ''), + ([varnumexp_pattern, nestedmatcher.RegExPattern(r'\s*:')], ''), + ([nestedmatcher.RegExPattern(r'goto\s+(?:' + varnum + r');')], ''), + ([nestedmatcher.RegExPattern(r'class')], 'struct'), + ([nestedmatcher.RegExPattern(r'char')], 'int'), + ([nestedmatcher.RegExPattern(r'short')], 'int'), + ([nestedmatcher.RegExPattern(r'long')], 'int'), + ([nestedmatcher.RegExPattern(r'signed')], 'int'), + ([nestedmatcher.RegExPattern(r'unsigned')], 'int'), + ([nestedmatcher.RegExPattern(r'float')], 'int'), + ([nestedmatcher.RegExPattern(r'double')], 'int'), + ([nestedmatcher.RegExPattern(r'wchar_t')], 'int'), + ([nestedmatcher.RegExPattern(r'bool')], 'int'), + ([nestedmatcher.RegExPattern(r'typeof\s+(?:' + varnum + r')')], 'int'), + ([nestedmatcher.RegExPattern(r'__typeof__\s+(?:' + varnum + r')')], 'int'), + ([nestedmatcher.RegExPattern(r'int\s+argc\s*,\s*.*\s*\*argv\[\]')], 'void'), + ([nestedmatcher.RegExPattern(r'int\s+argc\s*,\s*.*\s*\*\s*\*argv')], 'void'), + ([nestedmatcher.RegExPattern(r'int[^;]*;')], ''), + ([nestedmatcher.RegExPattern(r'for')], ''), + ([nestedmatcher.RegExPattern(r"'.*'")], ''), + ([nestedmatcher.RegExPattern(r"'.*'")], ''), + ([nestedmatcher.RegExPattern(r"'[^']*'")], ''), + ([nestedmatcher.RegExPattern(r"'[^']*'")], ''), + ([nestedmatcher.RegExPattern(r"''")], '0'), + (call_parts + [nestedmatcher.RegExPattern(r',')], '0'), + (call_parts + [nestedmatcher.RegExPattern(r',')], ''), + (call_parts, '0'), + (call_parts, '')] __subexprs = [ - fullvar + [nestedmatcher.RegExPattern(r"\s*")] + binop + [nestedmatcher.RegExPattern(r"\s*")] + fullvar, - fullvar + [nestedmatcher.RegExPattern(r"\s*")] + binop, - binop + [nestedmatcher.RegExPattern(r"\s*")] + fullvar, + fullvar + [nestedmatcher.RegExPattern(r'\s*')] + binop + [nestedmatcher.RegExPattern(r'\s*')] + fullvar, + fullvar + [nestedmatcher.RegExPattern(r'\s*')] + binop, + binop + [nestedmatcher.RegExPattern(r'\s*')] + fullvar, fullvar, - [nestedmatcher.RegExPattern(r":\s*")] + fullvar, - [nestedmatcher.RegExPattern(r"::\s*")] + fullvar, - fullvar + [nestedmatcher.RegExPattern(r"\s*:")], - fullvar + [nestedmatcher.RegExPattern(r"\s*::")], - fullvar + [nestedmatcher.RegExPattern(r"\s*\?\s*")] + fullvar + [nestedmatcher.RegExPattern(r"\s*:\s*")] + fullvar, + [nestedmatcher.RegExPattern(r':\s*')] + fullvar, + [nestedmatcher.RegExPattern(r'::\s*')] + fullvar, + fullvar + [nestedmatcher.RegExPattern(r'\s*:')], + fullvar + [nestedmatcher.RegExPattern(r'\s*::')], + fullvar + [nestedmatcher.RegExPattern(r'\s*\?\s*')] + fullvar + [nestedmatcher.RegExPattern(r'\s*:\s*')] + fullvar, ] for x in __subexprs: - delimited_regexes_to_replace.append((x, "0")) - delimited_regexes_to_replace.append((x, "1")) - delimited_regexes_to_replace.append((x, "")) - delimited_regexes_to_replace.append((x + [nestedmatcher.RegExPattern(r"\s*,")], "0")) - delimited_regexes_to_replace.append((x + [nestedmatcher.RegExPattern(r"\s*,")], "1")) - delimited_regexes_to_replace.append((x + [nestedmatcher.RegExPattern(r"\s*,")], "")) - delimited_regexes_to_replace.append(([nestedmatcher.RegExPattern(r",\s*")] + x, "0")) - delimited_regexes_to_replace.append(([nestedmatcher.RegExPattern(r",\s*")] + x, "1")) - delimited_regexes_to_replace.append(([nestedmatcher.RegExPattern(r",\s*")] + x, "")) + delimited_regexes_to_replace.append((x, '0')) + delimited_regexes_to_replace.append((x, '1')) + delimited_regexes_to_replace.append((x, '')) + delimited_regexes_to_replace.append((x + [nestedmatcher.RegExPattern(r'\s*,')], '0')) + delimited_regexes_to_replace.append((x + [nestedmatcher.RegExPattern(r'\s*,')], '1')) + delimited_regexes_to_replace.append((x + [nestedmatcher.RegExPattern(r'\s*,')], '')) + delimited_regexes_to_replace.append(([nestedmatcher.RegExPattern(r',\s*')] + x, '0')) + delimited_regexes_to_replace.append(([nestedmatcher.RegExPattern(r',\s*')] + x, '1')) + delimited_regexes_to_replace.append(([nestedmatcher.RegExPattern(r',\s*')] + x, '')) def check_prerequisites(self): return True - def new(self, test_case): - return {"pos" : 0, "regex" : 0} + def new(self, test_case, _=None): + return {'pos': 0, 'regex': 0} def advance(self, test_case, state): new_state = state.copy() - if self.arg == "a": + if self.arg == 'a': lim = len(self.regexes_to_replace) - elif self.arg == "b": - lim = len(self.delimited_regexes_to_replace); - elif self.arg == "c": + elif self.arg == 'b': + lim = len(self.delimited_regexes_to_replace) + elif self.arg == 'c': lim = 1 else: raise UnknownArgumentError(self.__class__.__name__, self.arg) - new_state["regex"] += 1 + new_state['regex'] += 1 - if new_state["regex"] >= lim: - new_state["regex"] = 0 - new_state["pos"] += 1 + if new_state['regex'] >= lim: + new_state['regex'] = 0 + new_state['pos'] += 1 - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: length = len(in_file.read()) - if new_state["pos"] >= length: + if new_state['pos'] >= length: return None return new_state @@ -156,70 +157,70 @@ return state def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() prog2 = prog - if state["pos"] > len(prog): + if state['pos'] > len(prog): return (PassResult.STOP, state) - if self.arg == "a": - l = self.regexes_to_replace[state["regex"]] - search = l[0]; - replace = l[1]; + if self.arg == 'a': + item = self.regexes_to_replace[state['regex']] + search = item[0] + replace = item[1] - m = nestedmatcher.search(search, prog2, pos=state["pos"], search=False) + m = nestedmatcher.search(search, prog2, pos=state['pos'], search=False) if m is not None: - prog2 = prog2[0:m["all"][0]] + replace + prog2[m["all"][1]:] + prog2 = prog2[0:m['all'][0]] + replace + prog2[m['all'][1]:] if prog != prog2: - with open(test_case, "w") as out_file: + with open(test_case, 'w') as out_file: out_file.write(prog2) return (PassResult.OK, state) - elif self.arg == "b": - l = self.delimited_regexes_to_replace[state["regex"]] - search = l[0] - replace = l[1] + elif self.arg == 'b': + item = self.delimited_regexes_to_replace[state['regex']] + search = item[0] + replace = item[1] - if prog2.startswith(","): - front = (self.border_or_space_optional_pattern, "delim1") + if prog2.startswith(','): + front = (self.border_or_space_optional_pattern, 'delim1') else: - front = (self.border_or_space_pattern, "delim1") + front = (self.border_or_space_pattern, 'delim1') - if prog2.endswith(","): - back = (self.border_or_space_optional_pattern, "delim2") + if prog2.endswith(','): + back = (self.border_or_space_optional_pattern, 'delim2') else: - back = (self.border_or_space_pattern, "delim2") + back = (self.border_or_space_pattern, 'delim2') search = [front] + search + [back] - m = nestedmatcher.search(search, prog2, pos=state["pos"], search=False) + m = nestedmatcher.search(search, prog2, pos=state['pos'], search=False) if m is not None: - prog2 = prog2[0:m["delim1"][1]] + replace + prog2[m["delim2"][0]:] + prog2 = prog2[0:m['delim1'][1]] + replace + prog2[m['delim2'][0]:] if prog != prog2: - with open(test_case, "w") as out_file: + with open(test_case, 'w') as out_file: out_file.write(prog2) return (PassResult.OK, state) - elif self.arg == "c": - search = [nestedmatcher.RegExPattern(r"^while\s*"), + elif self.arg == 'c': + search = [nestedmatcher.RegExPattern(r'^while\s*'), nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens), - nestedmatcher.RegExPattern(r"\s*"), - (nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies), "body")] + nestedmatcher.RegExPattern(r'\s*'), + (nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.curlies), 'body')] - m = nestedmatcher.search(search, prog2, pos=state["pos"], search=False) + m = nestedmatcher.search(search, prog2, pos=state['pos'], search=False) if m is not None: - body = prog2[m["body"][0]:m["body"][1]] - body = re.sub(r"break\s*;", "", body) - prog2 = prog2[0:m["all"][0]] + body + prog2[m["all"][1]:] + body = prog2[m['body'][0]:m['body'][1]] + body = re.sub(r'break\s*;', '', body) + prog2 = prog2[0:m['all'][0]] + body + prog2[m['all'][1]:] if prog != prog2: - with open(test_case, "w") as out_file: + with open(test_case, 'w') as out_file: out_file.write(prog2) return (PassResult.OK, state) diff -Nru cvise-1.6.0/cvise/passes/special.py cvise-2.3.0/cvise/passes/special.py --- cvise-1.6.0/cvise/passes/special.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/special.py 2021-03-09 08:18:13.000000000 +0000 @@ -3,59 +3,60 @@ from cvise.passes.abstract import AbstractPass, PassResult from cvise.utils.error import UnknownArgumentError + class SpecialPass(AbstractPass): def check_prerequisites(self): return True def __get_config(self): - config = {"search": None, - "replace_fn": None, - } + config = {'search': None, + 'replace_fn': None, + } def replace_printf(m): - return r'printf("%d\n", (int){})'.format(m.group("list").split(",")[0]) + return r"printf('%d\n', (int){})".format(m.group('list').split(',')[0]) def replace_empty(m): - return "" + return '' - if self.arg == "a": - config["search"] = r"transparent_crc\s*\((?P[^)]*)\)" - config["replace_fn"] = replace_printf - elif self.arg == "b": - config["search"] = r'extern "C"' - config["replace_fn"] = replace_empty - elif self.arg == "c": - config["search"] = r'extern "C\+\+"' - config["replace_fn"] = replace_empty + if self.arg == 'a': + config['search'] = r'transparent_crc\s*\((?P[^)]*)\)' + config['replace_fn'] = replace_printf + elif self.arg == 'b': + config['search'] = r"extern 'C'" + config['replace_fn'] = replace_empty + elif self.arg == 'c': + config['search'] = r"extern 'C\+\+'" + config['replace_fn'] = replace_empty else: raise UnknownArgumentError(self.__class__.__name__, self.arg) return config def __get_next_match(self, test_case, pos): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() config = self.__get_config() - regex = re.compile(config["search"], flags=re.DOTALL) + regex = re.compile(config['search'], flags=re.DOTALL) m = regex.search(prog, pos=pos) return m - def new(self, test_case): + def new(self, test_case, _=None): config = self.__get_config() - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() - regex = re.compile(config["search"], flags=re.DOTALL) - modifications = list(reversed([(m.span(), config["replace_fn"](m)) for m in regex.finditer(prog)])) + regex = re.compile(config['search'], flags=re.DOTALL) + modifications = list(reversed([(m.span(), config['replace_fn'](m)) for m in regex.finditer(prog)])) if not modifications: return None - return {"modifications": modifications, "index": 0} + return {'modifications': modifications, 'index': 0} def advance(self, test_case, state): state = state.copy() - state["index"] += 1 - if state["index"] >= len(state["modifications"]): + state['index'] += 1 + if state['index'] >= len(state['modifications']): return None return state @@ -63,11 +64,11 @@ return self.new(test_case) def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: data = in_file.read() - index = state["index"] - ((start, end), replacement) = state["modifications"][index] + index = state['index'] + ((start, end), replacement) = state['modifications'][index] new_data = data[:start] + replacement + data[end:] - with open(test_case, "w") as out_file: + with open(test_case, 'w') as out_file: out_file.write(new_data) return (PassResult.OK, state) diff -Nru cvise-1.6.0/cvise/passes/ternary.py cvise-2.3.0/cvise/passes/ternary.py --- cvise-1.6.0/cvise/passes/ternary.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/ternary.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,46 +1,47 @@ from cvise.passes.abstract import AbstractPass, PassResult -from cvise.utils.error import UnknownArgumentError from cvise.utils import nestedmatcher +from cvise.utils.error import UnknownArgumentError + class TernaryPass(AbstractPass): - varnum = r"(?:[-+]?[0-9a-zA-Z\_]+)" - border = r"[*{([:,})\];]" - border_or_space = r"(?:(?:" + border + r")|\s)" + varnum = r'(?:[-+]?[0-9a-zA-Z\_]+)' + border = r'[*{([:,})\];]' + border_or_space = r'(?:(?:' + border + r')|\s)' border_or_space_pattern = nestedmatcher.RegExPattern(border_or_space) varnum_pattern = nestedmatcher.RegExPattern(varnum) balanced_parens_pattern = nestedmatcher.BalancedPattern(nestedmatcher.BalancedExpr.parens) varnumexp_pattern = nestedmatcher.OrPattern(varnum_pattern, balanced_parens_pattern) - parts = [(border_or_space_pattern, "del1"), + parts = [(border_or_space_pattern, 'del1'), varnumexp_pattern, - nestedmatcher.RegExPattern(r"\s*\?\s*"), - (varnumexp_pattern, "b"), - nestedmatcher.RegExPattern(r"\s*:\s*"), - (varnumexp_pattern, "c"), - (border_or_space_pattern, "del2")] + nestedmatcher.RegExPattern(r'\s*\?\s*'), + (varnumexp_pattern, 'b'), + nestedmatcher.RegExPattern(r'\s*:\s*'), + (varnumexp_pattern, 'c'), + (border_or_space_pattern, 'del2')] def check_prerequisites(self): return True def __get_next_match(self, test_case, pos): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() m = nestedmatcher.search(self.parts, prog, pos=pos) return m - def new(self, test_case): + def new(self, test_case, _=None): return self.__get_next_match(test_case, pos=0) def advance(self, test_case, state): - return self.__get_next_match(test_case, pos=state["all"][0] + 1) + return self.__get_next_match(test_case, pos=state['all'][0] + 1) def advance_on_success(self, test_case, state): - return self.__get_next_match(test_case, pos=state["all"][0]) + return self.__get_next_match(test_case, pos=state['all'][0]) def transform(self, test_case, state, process_event_notifier): - with open(test_case, "r") as in_file: + with open(test_case, 'r') as in_file: prog = in_file.read() prog2 = prog @@ -48,13 +49,13 @@ if state is None: return (PassResult.STOP, state) else: - if self.arg not in ["b", "c"]: + if self.arg not in ['b', 'c']: raise UnknownArgumentError(self.__class__.__name__, self.arg) - prog2 = prog2[0:state["del1"][1]] + prog2[state[self.arg][0]:state[self.arg][1]] + prog2[state["del2"][0]:] + prog2 = prog2[0:state['del1'][1]] + prog2[state[self.arg][0]:state[self.arg][1]] + prog2[state['del2'][0]:] if prog != prog2: - with open(test_case, "w") as out_file: + with open(test_case, 'w') as out_file: out_file.write(prog2) return (PassResult.OK, state) diff -Nru cvise-1.6.0/cvise/passes/unifdef.py cvise-2.3.0/cvise/passes/unifdef.py --- cvise-1.6.0/cvise/passes/unifdef.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/passes/unifdef.py 2021-03-09 08:18:13.000000000 +0000 @@ -6,11 +6,12 @@ from cvise.passes.abstract import AbstractPass, PassResult + class UnIfDefPass(AbstractPass): def check_prerequisites(self): - return self.check_external_program("unifdef") + return self.check_external_program('unifdef') - def new(self, test_case): + def new(self, test_case, _=None): return 0 def advance(self, test_case, state): @@ -21,22 +22,22 @@ def transform(self, test_case, state, process_event_notifier): try: - cmd = [self.external_programs["unifdef"], "-s", test_case] + cmd = [self.external_programs['unifdef'], '-s', test_case] proc = subprocess.run(cmd, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except subprocess.SubprocessError: return (PassResult.ERROR, state) defs = {} - for l in proc.stdout.splitlines(): - defs[l] = 1 + for line in proc.stdout.splitlines(): + defs[line] = 1 - deflist = list(sorted(defs.keys())) + deflist = sorted(defs.keys()) tmp = os.path.dirname(test_case) - with tempfile.NamedTemporaryFile(mode="w+", delete=False, dir=tmp) as tmp_file: + with tempfile.NamedTemporaryFile(mode='w+', delete=False, dir=tmp) as tmp_file: while True: - du = "-D" if state % 2 == 0 else "-U" + du = '-D' if state % 2 == 0 else '-U' n_index = int(state / 2) if n_index >= len(deflist): @@ -45,7 +46,7 @@ def_ = deflist[n_index] - cmd = [self.external_programs["unifdef"], "-B", "-x", "2", "{}{}".format(du, def_), "-o", tmp_file.name, test_case] + cmd = [self.external_programs['unifdef'], '-B', '-x', '2', '{}{}'.format(du, def_), '-o', tmp_file.name, test_case] stdout, stderr, returncode = process_event_notifier.run_process(cmd) if returncode != 0: return (PassResult.ERROR, state) diff -Nru cvise-1.6.0/cvise/tests/testabstract.py cvise-2.3.0/cvise/tests/testabstract.py --- cvise-1.6.0/cvise/tests/testabstract.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/testabstract.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,8 +1,9 @@ from cvise.passes.abstract import PassResult, ProcessEventNotifier + def iterate_pass(current_pass, path): state = current_pass.new(path) - while state != None: + while state is not None: (result, state) = current_pass.transform(path, state, ProcessEventNotifier(None)) if result == PassResult.OK: state = current_pass.advance_on_success(path, state) diff -Nru cvise-1.6.0/cvise/tests/test_balanced.py cvise-2.3.0/cvise/tests/test_balanced.py --- cvise-1.6.0/cvise/tests/test_balanced.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_balanced.py 2021-03-09 08:18:13.000000000 +0000 @@ -3,15 +3,16 @@ import unittest from cvise.passes.abstract import PassResult -from ..passes import BalancedPass +from cvise.passes.balanced import BalancedPass + class BalancedParensTestCase(unittest.TestCase): def setUp(self): - self.pass_ = BalancedPass("parens") + self.pass_ = BalancedPass('parens') def test_parens_no_match(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This is a simple test!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This is a simple test!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -21,11 +22,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This is a simple test!\n") + self.assertEqual(variant, 'This is a simple test!\n') def test_parens_simple(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This is a (simple) test!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This is a (simple) test!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -35,11 +36,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This is a test!\n") + self.assertEqual(variant, 'This is a test!\n') def test_parens_nested_outer(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This (is a (simple) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This (is a (simple) test)!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -49,11 +50,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This !\n") + self.assertEqual(variant, 'This !\n') def test_parens_nested_inner(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This (is a (simple) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This (is a (simple) test)!\n') state = self.pass_.new(tmp_file.name) # Transform failed @@ -65,15 +66,16 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This (is a test)!\n") + self.assertEqual(variant, 'This (is a test)!\n') + class BalancedParensOnlyTestCase(unittest.TestCase): def setUp(self): - self.pass_ = BalancedPass("parens-only") + self.pass_ = BalancedPass('parens-only') def test_parens_no_match(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This is a simple test!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This is a simple test!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -83,11 +85,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This is a simple test!\n") + self.assertEqual(variant, 'This is a simple test!\n') def test_parens_simple(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This is a (simple) test!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This is a (simple) test!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -97,11 +99,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This is a simple test!\n") + self.assertEqual(variant, 'This is a simple test!\n') def test_parens_nested_outer(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This (is a (simple) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This (is a (simple) test)!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -111,11 +113,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This is a (simple) test!\n") + self.assertEqual(variant, 'This is a (simple) test!\n') def test_parens_nested_inner(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This (is a (simple) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This (is a (simple) test)!\n') state = self.pass_.new(tmp_file.name) # Transform failed @@ -127,11 +129,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This (is a simple test)!\n") + self.assertEqual(variant, 'This (is a simple test)!\n') def test_parens_nested_both(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This (is a (simple) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This (is a (simple) test)!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -143,11 +145,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This is a simple test!\n") + self.assertEqual(variant, 'This is a simple test!\n') def test_parens_nested_all(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("(This) (is a (((more)) complex) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('(This) (is a (((more)) complex) test)!\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -165,11 +167,11 @@ os.unlink(tmp_file.name) self.assertEqual(iteration, 5) - self.assertEqual(variant, "This is a more complex test!\n") + self.assertEqual(variant, 'This is a more complex test!\n') def test_parens_nested_no_success(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("(This) (is a (((more)) complex) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('(This) (is a (((more)) complex) test)!\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -177,8 +179,8 @@ iteration = 0 while result == PassResult.OK and iteration < 7: - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("(This) (is a (((more)) complex) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('(This) (is a (((more)) complex) test)!\n') state = self.pass_.advance(tmp_file.name, state) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -188,13 +190,14 @@ self.assertEqual(iteration, 5) + class BalancedParensInsideTestCase(unittest.TestCase): def setUp(self): - self.pass_ = BalancedPass("parens-inside") + self.pass_ = BalancedPass('parens-inside') def test_parens_no_match(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This is a simple test!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This is a simple test!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -204,11 +207,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This is a simple test!\n") + self.assertEqual(variant, 'This is a simple test!\n') def test_parens_simple(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This is a (simple) test!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This is a (simple) test!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -218,11 +221,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This is a () test!\n") + self.assertEqual(variant, 'This is a () test!\n') def test_parens_nested_outer(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This (is a (simple) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This (is a (simple) test)!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -232,11 +235,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This ()!\n") + self.assertEqual(variant, 'This ()!\n') def test_parens_nested_inner(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This (is a (simple) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This (is a (simple) test)!\n') state = self.pass_.new(tmp_file.name) # Transform failed @@ -248,11 +251,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This (is a () test)!\n") + self.assertEqual(variant, 'This (is a () test)!\n') def test_parens_nested_both(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This (is a (simple) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This (is a (simple) test)!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -264,11 +267,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This ()!\n") + self.assertEqual(variant, 'This ()!\n') def test_parens_nested_all(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("(This) (is a (((more)) complex) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('(This) (is a (((more)) complex) test)!\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -286,11 +289,11 @@ os.unlink(tmp_file.name) self.assertEqual(iteration, 2) - self.assertEqual(variant, "() ()!\n") + self.assertEqual(variant, '() ()!\n') def test_parens_nested_no_success(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("(This) (is a (((more)) complex) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('(This) (is a (((more)) complex) test)!\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -298,8 +301,8 @@ iteration = 0 while result == PassResult.OK and iteration < 7: - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("(This) (is a (((more)) complex) test)!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('(This) (is a (((more)) complex) test)!\n') state = self.pass_.advance(tmp_file.name, state) (result, state) = self.pass_.transform(tmp_file.name, state, None) diff -Nru cvise-1.6.0/cvise/tests/test_comments.py cvise-2.3.0/cvise/tests/test_comments.py --- cvise-1.6.0/cvise/tests/test_comments.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_comments.py 2021-03-09 08:18:13.000000000 +0000 @@ -3,15 +3,16 @@ import unittest from cvise.passes.abstract import PassResult -from ..passes import CommentsPass +from cvise.passes.comments import CommentsPass + class CommentsTestCase(unittest.TestCase): def setUp(self): - self.pass_ = CommentsPass("0") + self.pass_ = CommentsPass('0') def test_block(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This /* contains *** /* two */ /*comments*/!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This /* contains *** /* two */ /*comments*/!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -21,11 +22,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This !\n") + self.assertEqual(variant, 'This !\n') def test_line(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("This ///contains //two\n //comments\n!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('This ///contains //two\n //comments\n!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -35,11 +36,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "This \n \n!\n") + self.assertEqual(variant, 'This \n \n!\n') def test_success(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("/*This*/ ///contains //two\n //comments\n!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('/*This*/ ///contains //two\n //comments\n!\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -57,11 +58,11 @@ os.unlink(tmp_file.name) self.assertEqual(iteration, 2) - self.assertEqual(variant, " \n \n!\n") + self.assertEqual(variant, ' \n \n!\n') def test_no_success(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("/*This*/ ///contains //two\n //comments\n!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('/*This*/ ///contains //two\n //comments\n!\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -69,8 +70,8 @@ iteration = 0 while result == PassResult.OK and iteration < 4: - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("/*This*/ ///contains //two\n //comments\n!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('/*This*/ ///contains //two\n //comments\n!\n') state = self.pass_.advance(tmp_file.name, state) (result, state) = self.pass_.transform(tmp_file.name, state, None) diff -Nru cvise-1.6.0/cvise/tests/test_ifs.py cvise-2.3.0/cvise/tests/test_ifs.py --- cvise-1.6.0/cvise/tests/test_ifs.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_ifs.py 2021-03-09 08:18:13.000000000 +0000 @@ -3,15 +3,16 @@ import unittest from cvise.passes.abstract import ProcessEventNotifier -from ..passes import IfPass +from cvise.passes.ifs import IfPass + class LineMarkersTestCase(unittest.TestCase): def setUp(self): - self.pass_ = IfPass(external_programs = {'unifdef': 'unifdef'}) - self.process_event_notifier = ProcessEventNotifier(None) + self.pass_ = IfPass(external_programs={'unifdef': 'unifdef'}) + self.process_event_notifier = ProcessEventNotifier(None) def test_all(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: tmp_file.write('#if FOO\nint a = 2;\n#endif') state = self.pass_.new(tmp_file.name) @@ -24,4 +25,52 @@ variant = variant_file.read() os.unlink(tmp_file.name) - self.assertEqual(variant, "int a = 2;\n") + self.assertEqual(variant, 'int a = 2;\n') + + def test_two_steps(self): + self.maxDiff = None + in_contents = ( + '#if FOO\nint foo = 1;\n#else\nint foo = 0;\n#endif\n' + + '#if BAR\nint bar = 1;\n#else\nint bar = 0;\n#endif\n' + ) + expected_outs = [ + # ix val chunk contents + # FOO=0 BAR=0 + (0, 0, 2, 'int foo = 0;\nint bar = 0;\n'), + # FOO=1 BAR=1 + (0, 1, 2, 'int foo = 1;\nint bar = 1;\n'), + + # FOO=0 + (0, 0, 1, ('int foo = 0;\n' + + '#if BAR\nint bar = 1;\n#else\nint bar = 0;\n#endif\n')), + # FOO=1 + (0, 1, 1, ('int foo = 1;\n' + + '#if BAR\nint bar = 1;\n#else\nint bar = 0;\n#endif\n')), + # BAR=0 + (1, 0, 1, ('#if FOO\nint foo = 1;\n#else\nint foo = 0;\n#endif\n' + + 'int bar = 0;\n')), + # BAR=1 + (1, 1, 1, ('#if FOO\nint foo = 1;\n#else\nint foo = 0;\n#endif\n' + + 'int bar = 1;\n')), + ] + + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tf: + tf.write(in_contents) + + outs = [] + + # perform all iterations. They should iterate through FOO/!FOO x BAR/!BAR. + state = self.pass_.new(tf.name) + while state: + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write(in_contents) + + (_, state) = self.pass_.transform(tmp_file.name, state, self.process_event_notifier) + with open(tmp_file.name) as variant_file: + variant = variant_file.read() + outs.append((state.index, state.value, state.chunk, variant)) + os.unlink(tmp_file.name) + state = self.pass_.advance(tmp_file.name, state) + + os.unlink(tf.name) + self.assertEqual(expected_outs, outs) diff -Nru cvise-1.6.0/cvise/tests/test_ints.py cvise-2.3.0/cvise/tests/test_ints.py --- cvise-1.6.0/cvise/tests/test_ints.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_ints.py 2021-03-09 08:18:13.000000000 +0000 @@ -2,16 +2,17 @@ import tempfile import unittest -from cvise.passes.abstract import PassResult, ProcessEventNotifier -from ..passes import IntsPass +from cvise.passes.abstract import PassResult +from cvise.passes.ints import IntsPass + class IntsATestCase(unittest.TestCase): def setUp(self): - self.pass_ = IntsPass("a") + self.pass_ = IntsPass('a') def test_a(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("Compute 123L + 0x456 + 0789!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('Compute 123L + 0x456 + 0789!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -21,11 +22,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "Compute 123L + 0x56 + 0789!\n") + self.assertEqual(variant, 'Compute 123L + 0x56 + 0789!\n') def test_success_a(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("Compute 123L + 0x456 + 0789!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('Compute 123L + 0x456 + 0789!\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -33,7 +34,7 @@ iteration = 1 while result == PassResult.OK and iteration < 10: state = self.pass_.advance_on_success(tmp_file.name, state) - if state == None: + if state is None: break (result, state) = self.pass_.transform(tmp_file.name, state, None) iteration += 1 @@ -44,11 +45,11 @@ os.unlink(tmp_file.name) self.assertEqual(iteration, 4) - self.assertEqual(variant, "Compute 3L + 0x6 + 0789!\n") + self.assertEqual(variant, 'Compute 3L + 0x6 + 0789!\n') def test_no_success_a(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("Compute 123L + 0x456 + 0789!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('Compute 123L + 0x456 + 0789!\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -56,11 +57,11 @@ iteration = 1 while result == PassResult.OK and iteration < 10: - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("Compute 123L + 0x456 + 0789!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('Compute 123L + 0x456 + 0789!\n') state = self.pass_.advance(tmp_file.name, state) - if state == None: + if state is None: break (result, state) = self.pass_.transform(tmp_file.name, state, None) iteration += 1 @@ -69,13 +70,14 @@ self.assertEqual(iteration, 2) + class IntsBTestCase(unittest.TestCase): def setUp(self): - self.pass_ = IntsPass("b") + self.pass_ = IntsPass('b') def test_b(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("Compute 123L + 0x456 + 0789!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('Compute 123L + 0x456 + 0789!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -85,15 +87,16 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "Compute 123L + 456 + 0789!\n") + self.assertEqual(variant, 'Compute 123L + 456 + 0789!\n') + class IntsCTestCase(unittest.TestCase): def setUp(self): - self.pass_ = IntsPass("c") + self.pass_ = IntsPass('c') def test_c(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("Compute 123L + 0x456 + 0789!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('Compute 123L + 0x456 + 0789!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -103,15 +106,16 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "Compute 123 + 0x456 + 0789!\n") + self.assertEqual(variant, 'Compute 123 + 0x456 + 0789!\n') + class IntsDTestCase(unittest.TestCase): def setUp(self): - self.pass_ = IntsPass("d") + self.pass_ = IntsPass('d') def test_d(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("Compute 123L + 0x456 + 0789!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('Compute 123L + 0x456 + 0789!\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -121,4 +125,4 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "Compute 123L + 1110 + 0789!\n") + self.assertEqual(variant, 'Compute 123L + 1110 + 0789!\n') diff -Nru cvise-1.6.0/cvise/tests/test_line_markers.py cvise-2.3.0/cvise/tests/test_line_markers.py --- cvise-1.6.0/cvise/tests/test_line_markers.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_line_markers.py 2021-03-09 08:18:13.000000000 +0000 @@ -2,16 +2,16 @@ import tempfile import unittest -from cvise.passes.abstract import ProcessEventNotifier -from ..passes import LineMarkersPass +from cvise.passes.line_markers import LineMarkersPass + class LineMarkersTestCase(unittest.TestCase): def setUp(self): self.pass_ = LineMarkersPass() def test_all(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write('# 1 "foo.h"\n# 2 "bar.h"\n#4 "x.h"') + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write("# 1 'foo.h'\n# 2 'bar.h'\n#4 'x.h'") state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -22,11 +22,11 @@ variant = variant_file.read() os.unlink(tmp_file.name) - self.assertEqual(variant, "") + self.assertEqual(variant, '') def test_only_last(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write('# 1 "foo.h"\n# 2 "bar.h"\n#4 "x.h\nint x = 2;') + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write("# 1 'foo.h'\n# 2 'bar.h'\n#4 'x.h\nint x = 2;") state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -35,4 +35,4 @@ variant = variant_file.read() os.unlink(tmp_file.name) - self.assertEqual(variant, "int x = 2;") + self.assertEqual(variant, 'int x = 2;') diff -Nru cvise-1.6.0/cvise/tests/test_nestedmatcher.py cvise-2.3.0/cvise/tests/test_nestedmatcher.py --- cvise-1.6.0/cvise/tests/test_nestedmatcher.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_nestedmatcher.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,86 +1,88 @@ import unittest -from ..utils.nestedmatcher import find, search, BalancedExpr, RegExPattern, BalancedPattern, OrPattern +from cvise.utils.nestedmatcher import BalancedExpr, BalancedPattern, find, OrPattern, RegExPattern, search + class SimpleParensTest(unittest.TestCase): def test_1(self): - m = find(BalancedExpr.parens, "No match in this string!") + m = find(BalancedExpr.parens, 'No match in this string!') self.assertIsNone(m) def test_2(self): - m = find(BalancedExpr.parens, "No match in this string!", pos=500) + m = find(BalancedExpr.parens, 'No match in this string!', pos=500) self.assertIsNone(m) def test_3(self): - m = find(BalancedExpr.parens, "No match in this string!", pos=500) + m = find(BalancedExpr.parens, 'No match in this string!', pos=500) self.assertIsNone(m) def test_4(self): - m = find(BalancedExpr.parens, "No match in this string!", pos=-1) + m = find(BalancedExpr.parens, 'No match in this string!', pos=-1) self.assertIsNone(m) def test_5(self): - m = find(BalancedExpr.parens, "This string contains a (simple match)!") + m = find(BalancedExpr.parens, 'This string contains a (simple match)!') self.assertEqual(m, (23, 37)) def test_6(self): - m = find(BalancedExpr.parens, "This string contains a (simple match at the end!)") + m = find(BalancedExpr.parens, 'This string contains a (simple match at the end!)') self.assertEqual(m, (23, 49)) def test_7(self): - m = find(BalancedExpr.parens, "(This string contains) a simple match at the beginning!") + m = find(BalancedExpr.parens, '(This string contains) a simple match at the beginning!') self.assertEqual(m, (0, 22)) def test_8(self): - m = find(BalancedExpr.parens, "(This string contains) two (simple matches)!") + m = find(BalancedExpr.parens, '(This string contains) two (simple matches)!') self.assertEqual(m, (0, 22)) def test_9(self): - m = find(BalancedExpr.parens, "(This (string) contains) two nested matches!") + m = find(BalancedExpr.parens, '(This (string) contains) two nested matches!') self.assertEqual(m, (0, 24)) def test_10(self): - m = find(BalancedExpr.parens, "(This (string) contains) two nested matches!", pos=1) + m = find(BalancedExpr.parens, '(This (string) contains) two nested matches!', pos=1) self.assertEqual(m, (6, 14)) def test_11(self): - m = find(BalancedExpr.parens, "(This (string) contains) two nested matches!", prefix="This ") + m = find(BalancedExpr.parens, '(This (string) contains) two nested matches!', prefix='This ') self.assertEqual(m, (1, 14)) + class ComplexParensTest(unittest.TestCase): def test_1(self): - parts = [RegExPattern(r"This\s"), (BalancedPattern(BalancedExpr.parens), "nested")] - m = search(parts, "(This (string) contains) two nested matches!") - self.assertEqual(m, {"all" : (1, 14), "nested" : (6, 14)}) + parts = [RegExPattern(r'This\s'), (BalancedPattern(BalancedExpr.parens), 'nested')] + m = search(parts, '(This (string) contains) two nested matches!') + self.assertEqual(m, {'all': (1, 14), 'nested': (6, 14)}) def test_2(self): - parts = [RegExPattern(r"This\s"), - (BalancedPattern(BalancedExpr.parens), "nested"), - RegExPattern(r"[^(]*"), - (BalancedPattern(BalancedExpr.parens), "nested2")] - m = search(parts, "(This (string) contains) two (nested) matches!") - self.assertEqual(m, {"all" : (1, 37), "nested" : (6, 14), "nested2" : (29, 37)}) + parts = [RegExPattern(r'This\s'), + (BalancedPattern(BalancedExpr.parens), 'nested'), + RegExPattern(r'[^(]*'), + (BalancedPattern(BalancedExpr.parens), 'nested2')] + m = search(parts, '(This (string) contains) two (nested) matches!') + self.assertEqual(m, {'all': (1, 37), 'nested': (6, 14), 'nested2': (29, 37)}) def test_3(self): - parts = [RegExPattern(r"[Tt]his\s"), - (BalancedPattern(BalancedExpr.parens), "nested"), - RegExPattern(r"[^(]*"), - (BalancedPattern(BalancedExpr.parens), "nested2")] - m = search(parts, "(This string this (contains)) two (nested) matches!") - self.assertEqual(m, {"all" : (13, 42), "nested" : (18, 28), "nested2" : (34, 42)}) + parts = [RegExPattern(r'[Tt]his\s'), + (BalancedPattern(BalancedExpr.parens), 'nested'), + RegExPattern(r'[^(]*'), + (BalancedPattern(BalancedExpr.parens), 'nested2')] + m = search(parts, '(This string this (contains)) two (nested) matches!') + self.assertEqual(m, {'all': (13, 42), 'nested': (18, 28), 'nested2': (34, 42)}) def test_4(self): - parts = [RegExPattern(r"[Tt]his\s"), - (BalancedPattern(BalancedExpr.parens), "nested"), - RegExPattern(r"[^(]*"), # consumes also "two" - (OrPattern(BalancedPattern(BalancedExpr.parens), RegExPattern("two")), "nested2")] - m = search(parts, "(This string this (contains)) two (nested) matches!") - self.assertEqual(m, {"all" : (13, 42), "nested" : (18, 28), "nested2" : (34, 42)}) + parts = [RegExPattern(r'[Tt]his\s'), + (BalancedPattern(BalancedExpr.parens), 'nested'), + RegExPattern(r'[^(]*'), # consumes also 'two' + (OrPattern(BalancedPattern(BalancedExpr.parens), RegExPattern('two')), 'nested2')] + m = search(parts, '(This string this (contains)) two (nested) matches!') + self.assertEqual(m, {'all': (13, 42), 'nested': (18, 28), 'nested2': (34, 42)}) def test_5(self): - parts = [RegExPattern(r"[Tt]his\s"), - (BalancedPattern(BalancedExpr.parens), "nested"), - RegExPattern(r"[^(t]*"), - (OrPattern(BalancedPattern(BalancedExpr.parens), RegExPattern("two")), "nested2")] - m = search(parts, "(This string this (contains)) two (nested) matches!") - self.assertEqual(m, {"all" : (13, 33), "nested" : (18, 28), "nested2" : (30, 33)}) + parts = [RegExPattern(r'[Tt]his\s'), + (BalancedPattern(BalancedExpr.parens), 'nested'), + RegExPattern(r'[^(t]*'), + (OrPattern(BalancedPattern(BalancedExpr.parens), RegExPattern('two')), 'nested2')] + m = search(parts, '(This string this (contains)) two (nested) matches!') + self.assertEqual(m, {'all': (13, 33), 'nested': (18, 28), 'nested2': (30, 33)}) diff -Nru cvise-1.6.0/cvise/tests/test_peep.py cvise-2.3.0/cvise/tests/test_peep.py --- cvise-1.6.0/cvise/tests/test_peep.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_peep.py 2021-03-09 08:18:13.000000000 +0000 @@ -2,16 +2,16 @@ import tempfile import unittest +from cvise.passes.peep import PeepPass from cvise.tests.testabstract import iterate_pass -from cvise.passes.abstract import PassResult -from ..passes import PeepPass + class PeepATestCase(unittest.TestCase): def setUp(self): - self.pass_ = PeepPass("a") + self.pass_ = PeepPass('a') def test_a_1(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: tmp_file.write(" whether the transformation works!\n") iterate_pass(self.pass_, tmp_file.name) @@ -21,10 +21,10 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, " whether the transformation works\n") + self.assertEqual(variant, ' whether the transformation works\n') def test_a_2(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: tmp_file.write("{That's a small test} whether the transformation works!\n") iterate_pass(self.pass_, tmp_file.name) @@ -34,11 +34,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, " whether the transformation works\n") + self.assertEqual(variant, ' whether the transformation works\n') def test_a_3(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("namespace cvise {Some more content} which is not interesting!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('namespace cvise {Some more content} which is not interesting!\n') iterate_pass(self.pass_, tmp_file.name) @@ -47,11 +47,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, " which is not interesting\n") + self.assertEqual(variant, ' which is not interesting\n') def test_a_4(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("namespace {Some more content} which is not interesting!\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('namespace {Some more content} which is not interesting!\n') iterate_pass(self.pass_, tmp_file.name) @@ -60,11 +60,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, " which is not interesting\n") + self.assertEqual(variant, ' which is not interesting\n') def test_a_5(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("struct test_t {} test;\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('struct test_t {} test;\n') iterate_pass(self.pass_, tmp_file.name) @@ -73,11 +73,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, " test\n") + self.assertEqual(variant, ' test\n') def test_success_a(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("struct test_t {int a;} foo = {1};\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('struct test_t {int a;} foo = {1};\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -89,15 +89,16 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, " foo \n") + self.assertEqual(variant, ' foo \n') + class PeepBTestCase(unittest.TestCase): def setUp(self): - self.pass_ = PeepPass("b") + self.pass_ = PeepPass('b') def test_b_1(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("struct test_t {} test;\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('struct test_t {} test;\n') iterate_pass(self.pass_, tmp_file.name) @@ -106,11 +107,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "struct {} ;\n") + self.assertEqual(variant, 'struct {} ;\n') def test_success_b(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("struct test_t {int a;} foo = {1};\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('struct test_t {int a;} foo = {1};\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -122,11 +123,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "struct { ;} = {};\n") + self.assertEqual(variant, 'struct { ;} = {};\n') def test_infinite_loop(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write(",0,") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write(',0,') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -138,15 +139,16 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, ",,") + self.assertEqual(variant, ',,') + class PeepCTestCase(unittest.TestCase): def setUp(self): - self.pass_ = PeepPass("c") + self.pass_ = PeepPass('c') def test_c_1(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("while (a == b)\n{\n int a = 4;\n short b = 5;\n break;\n}\n\nulong c = 18;\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('while (a == b)\n{\n int a = 4;\n short b = 5;\n break;\n}\n\nulong c = 18;\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -156,5 +158,4 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "{\n int a = 4;\n short b = 5;\n \n}\n\nulong c = 18;\n") - + self.assertEqual(variant, '{\n int a = 4;\n short b = 5;\n \n}\n\nulong c = 18;\n') diff -Nru cvise-1.6.0/cvise/tests/test_special.py cvise-2.3.0/cvise/tests/test_special.py --- cvise-1.6.0/cvise/tests/test_special.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_special.py 2021-03-09 08:18:13.000000000 +0000 @@ -2,17 +2,17 @@ import tempfile import unittest +from cvise.passes.special import SpecialPass from cvise.tests.testabstract import iterate_pass -from cvise.passes.abstract import PassResult -from ..passes import SpecialPass + class SpecialATestCase(unittest.TestCase): def setUp(self): - self.pass_ = SpecialPass("a") + self.pass_ = SpecialPass('a') def test_a(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write('// Useless comment\ntransparent_crc(g_376.f0, "g_376.f0", print_hash_value);\ntransparent_crc(g_1194[i].f0, "g_1194[i].f0", print_hash_value);\nint a = 9;') + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write("// Useless comment\ntransparent_crc(g_376.f0, 'g_376.f0', print_hash_value);\ntransparent_crc(g_1194[i].f0, 'g_1194[i].f0', print_hash_value);\nint a = 9;") iterate_pass(self.pass_, tmp_file.name) @@ -21,11 +21,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, '// Useless comment\nprintf("%d\\n", (int)g_376.f0);\nprintf("%d\\n", (int)g_1194[i].f0);\nint a = 9;') + self.assertEqual(variant, "// Useless comment\nprintf('%d\\n', (int)g_376.f0);\nprintf('%d\\n', (int)g_1194[i].f0);\nint a = 9;") def test_success_a(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write('// Useless comment\ntransparent_crc(g_376.f0, "g_376.f0", print_hash_value);\ntransparent_crc(g_1194[i].f0, "g_1194[i].f0", print_hash_value);\nint a = 9;') + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write("// Useless comment\ntransparent_crc(g_376.f0, 'g_376.f0', print_hash_value);\ntransparent_crc(g_1194[i].f0, 'g_1194[i].f0', print_hash_value);\nint a = 9;") state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -37,15 +37,16 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, '// Useless comment\nprintf("%d\\n", (int)g_376.f0);\nprintf("%d\\n", (int)g_1194[i].f0);\nint a = 9;') + self.assertEqual(variant, "// Useless comment\nprintf('%d\\n', (int)g_376.f0);\nprintf('%d\\n', (int)g_1194[i].f0);\nint a = 9;") + class SpecialBTestCase(unittest.TestCase): def setUp(self): - self.pass_ = SpecialPass("b") + self.pass_ = SpecialPass('b') def test_b(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write('void foo(){} extern "C" {int a;}; a = 9;\n') + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write("void foo(){} extern 'C' {int a;}; a = 9;\n") state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -55,15 +56,16 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "void foo(){} {int a;}; a = 9;\n") + self.assertEqual(variant, 'void foo(){} {int a;}; a = 9;\n') + class SpecialCTestCase(unittest.TestCase): def setUp(self): - self.pass_ = SpecialPass("c") + self.pass_ = SpecialPass('c') def test_c(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write('void foo(){} extern "C++" {int a;}; a = 9;\n') + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write("void foo(){} extern 'C++' {int a;}; a = 9;\n") state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -73,4 +75,4 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "void foo(){} {int a;}; a = 9;\n") + self.assertEqual(variant, 'void foo(){} {int a;}; a = 9;\n') diff -Nru cvise-1.6.0/cvise/tests/test_ternary.py cvise-2.3.0/cvise/tests/test_ternary.py --- cvise-1.6.0/cvise/tests/test_ternary.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/tests/test_ternary.py 2021-03-09 08:18:13.000000000 +0000 @@ -3,15 +3,16 @@ import unittest from cvise.passes.abstract import PassResult -from ..passes import TernaryPass +from cvise.passes.ternary import TernaryPass + class TernaryBTestCase(unittest.TestCase): def setUp(self): - self.pass_ = TernaryPass("b") + self.pass_ = TernaryPass('b') def test_b(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("int res = a ? b : c;\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('int res = a ? b : c;\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -21,11 +22,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "int res = b;\n") + self.assertEqual(variant, 'int res = b;\n') def test_parens(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("int res = (a != 0) ? (b + 5) : c;\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('int res = (a != 0) ? (b + 5) : c;\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -35,11 +36,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "int res = (b + 5);\n") + self.assertEqual(variant, 'int res = (b + 5);\n') def test_all_b(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("// no ? match :\nint res = a ? (ba ? bb : bc) : c\nint sec = t ? u : v\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('// no ? match :\nint res = a ? (ba ? bb : bc) : c\nint sec = t ? u : v\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -53,11 +54,11 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "// match res = (bb)\nint sec = u\n") + self.assertEqual(variant, '// match res = (bb)\nint sec = u\n') def test_all_b_2(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("// no ? match :!\nint res = a ? (ba ? bb : bc) : c\nint sec = t ? u : v\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('// no ? match :!\nint res = a ? (ba ? bb : bc) : c\nint sec = t ? u : v\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -75,11 +76,11 @@ os.unlink(tmp_file.name) self.assertEqual(iteration, 3) - self.assertEqual(variant, "// no ? match :!\nint res = (bb)\nint sec = u\n") + self.assertEqual(variant, '// no ? match :!\nint res = (bb)\nint sec = u\n') def test_no_success(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("// no ? match :\nint res = a ? (ba ? bb : bc) : c\nint sec = t ? u : v\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('// no ? match :\nint res = a ? (ba ? bb : bc) : c\nint sec = t ? u : v\n') state = self.pass_.new(tmp_file.name) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -87,8 +88,8 @@ iteration = 0 while result == PassResult.OK and iteration < 6: - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("// no ? match :\nint res = a ? (ba ? bb : bc) : c\nint sec = t ? u : v\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('// no ? match :\nint res = a ? (ba ? bb : bc) : c\nint sec = t ? u : v\n') state = self.pass_.advance(tmp_file.name, state) (result, state) = self.pass_.transform(tmp_file.name, state, None) @@ -98,13 +99,14 @@ self.assertEqual(iteration, 4) + class TernaryCTestCase(unittest.TestCase): def setUp(self): - self.pass_ = TernaryPass("c") + self.pass_ = TernaryPass('c') def test_c(self): - with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: - tmp_file.write("int res = a ? b : c;\n") + with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_file: + tmp_file.write('int res = a ? b : c;\n') state = self.pass_.new(tmp_file.name) (_, state) = self.pass_.transform(tmp_file.name, state, None) @@ -114,4 +116,4 @@ os.unlink(tmp_file.name) - self.assertEqual(variant, "int res = c;\n") + self.assertEqual(variant, 'int res = c;\n') diff -Nru cvise-1.6.0/cvise/utils/error.py cvise-2.3.0/cvise/utils/error.py --- cvise-1.6.0/cvise/utils/error.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/utils/error.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,14 +1,17 @@ import os + class CViseError(Exception): pass + class PrerequisitesNotFoundError(CViseError): def __init__(self, missing): self.missing = missing def __str__(self): - return "Missing prerequisites for passes {}!".format(", ".join(self.missing)) + return 'Missing prerequisites for passes {}!'.format(', '.join(self.missing)) + class UnknownArgumentError(CViseError): def __init__(self, pass_, arg): @@ -18,6 +21,7 @@ def __str__(self): return "The argument '{}' is not valid for pass '{}'!".format(self.arg, self.pass_.__name__) + class InvalidFileError(CViseError): def __init__(self, path, error): self.path = path @@ -25,21 +29,31 @@ def _get_error_name(self): if self.error == os.R_OK: - return "read" + return 'read' elif self.error == os.W_OK: - return "written" + return 'written' elif self.error == os.X_OK: - return "executed" + return 'executed' elif self.error == os.F_OK: - return "accessed" + return 'accessed' def __str__(self): return "The specified file '{}' cannot be {}!".format(self.path, self._get_error_name()) + class InvalidTestCaseError(InvalidFileError): def __str__(self): return "The specified test case '{}' cannot be {}!".format(self.path, self._get_error_name()) + +class FolderInPathTestCaseError(CViseError): + def __init__(self, path): + self.path = path + + def __str__(self): + return f"Test case cannot contain a folder in path: '{self.path}'!" + + class InvalidInterestingnessTestError(InvalidFileError): def __init__(self, path): super().__init__(path, None) @@ -47,6 +61,7 @@ def __str__(self): return "The specified interestingness test '{}' cannot be executed!".format(self.path) + class ZeroSizeError(CViseError): def __init__(self, test_cases): super().__init__() @@ -54,9 +69,9 @@ def __str__(self): if len(self.test_cases) == 1: - message = "The file being reduced has reached zero size; " + message = 'The file being reduced has reached zero size; ' else: - message = "All files being reduced have reached zero size; " + message = 'All files being reduced have reached zero size; ' message += """our work here is done. @@ -65,12 +80,15 @@ this to be interesting.""" return message + class PassOptionError(CViseError): pass + class MissingPassGroupsError(CViseError): def __str__(self): - return "Could not find a directory with definitions for pass groups!" + return 'Could not find a directory with definitions for pass groups!' + class PassBugError(CViseError): MSG = """*************************************************** @@ -95,6 +113,7 @@ def __str__(self): return self.MSG.format(self.current_pass, self.problem, self.state, self.crash_dir) + class InsaneTestCaseError(CViseError): def __init__(self, test_cases, test): super().__init__() @@ -114,9 +133,9 @@ {test} echo $? -should result in "0" being echoed to the terminal. +should result in '0' being echoed to the terminal. Please ensure that the test script takes no arguments; it should be hard-coded to refer to the same file that is passed as an argument to C-Vise. -See "cvise.py --help" for more information.""".format(test_cases=" ".join(self.test_cases), test=self.test) +See 'cvise.py --help' for more information.""".format(test_cases=' '.join(self.test_cases), test=self.test) return message diff -Nru cvise-1.6.0/cvise/utils/nestedmatcher.py cvise-2.3.0/cvise/utils/nestedmatcher.py --- cvise-1.6.0/cvise/utils/nestedmatcher.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/utils/nestedmatcher.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,22 +1,26 @@ import enum import re + @enum.unique class BalancedExpr(enum.Enum): - angles = ("<", ">") - curlies = ("{", "}") - parens = ("(", ")") - squares = ("[", "]") + angles = ('<', '>') + curlies = ('{', '}') + parens = ('(', ')') + squares = ('[', ']') + class Pattern: pass + class RegExPattern(Pattern): def __init__(self, expr): self.expr = expr def __repr__(self): - return "(expr={})".format(self.expr) + return '(expr={})'.format(self.expr) + class BalancedPattern(Pattern): def __init__(self, expr): @@ -24,7 +28,8 @@ self.end = expr.value[1] def __repr__(self): - return "(start={}, end={})".format(self.start, self.end) + return '(start={}, end={})'.format(self.start, self.end) + class OrPattern(Pattern): def __init__(self, left, right): @@ -32,7 +37,8 @@ self.right = right def __repr__(self): - return "(left={}, right={})".format(self.left, self.right) + return '(left={}, right={})'.format(self.left, self.right) + def __get_regex_match(pattern, string, pos=0, search=False): regex = re.compile(pattern.expr, flags=re.DOTALL) @@ -47,6 +53,7 @@ else: return None + def __get_balanced_match(pattern, string, pos=0, search=False): if pos < 0 or pos >= len(string): return None @@ -92,6 +99,7 @@ return __match_helper(pattern, string, pos) + def __get_leftmost_match(matches): matches = filter(lambda m: m is not None, matches) @@ -104,6 +112,7 @@ return leftmost + def __match_pattern(pattern, string, pos=0, search=False): if isinstance(pattern, OrPattern): left_match = __match_pattern(pattern.left, string, pos=pos, search=search) @@ -119,13 +128,15 @@ return match + def __unify_part(part): if not isinstance(part, tuple): part = (part, None) return part -def find(expr, string, pos=0, prefix=""): + +def find(expr, string, pos=0, prefix=''): parts = [] if prefix: @@ -136,10 +147,11 @@ matches = search(parts, string, pos) if matches: - return matches["all"] + return matches['all'] else: return None + def search(parts, string, pos=0, search=True): if not parts or pos < 0 or pos >= len(string): return None @@ -177,7 +189,7 @@ pos += match[1] - match[0] if found_complete_match: - matches["all"] = (start_pos, pos) + matches['all'] = (start_pos, pos) return matches else: return None diff -Nru cvise-1.6.0/cvise/utils/readkey.py cvise-2.3.0/cvise/utils/readkey.py --- cvise-1.6.0/cvise/utils/readkey.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/utils/readkey.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,33 +1,38 @@ import sys -if sys.platform == "win32": +if sys.platform == 'win32': import msvcrt else: import termios import select import weakref + class KeyLogger: def __init__(self): - if sys.platform != "win32": - fd = sys.stdin.fileno() - new_term = termios.tcgetattr(fd) - old_term = termios.tcgetattr(fd) - - self._finalizer = weakref.finalize(self, termios.tcsetattr, fd, termios.TCSAFLUSH, old_term) - - # New terminal setting unbuffered - new_term[3] = new_term[3] & ~termios.ICANON & ~termios.ECHO - termios.tcsetattr(fd, termios.TCSAFLUSH, new_term) + if sys.platform != 'win32': + try: + fd = sys.stdin.fileno() + new_term = termios.tcgetattr(fd) + old_term = termios.tcgetattr(fd) + + self._finalizer = weakref.finalize(self, termios.tcsetattr, fd, termios.TCSAFLUSH, old_term) + + # New terminal setting unbuffered + new_term[3] = new_term[3] & ~termios.ICANON & ~termios.ECHO + termios.tcsetattr(fd, termios.TCSAFLUSH, new_term) + except termios.error: + # this happens when run in pytest + pass def _getch(self): - if sys.platform == "win32": - return msvcrt.getch().decode("utf-8") + if sys.platform == 'win32': + return msvcrt.getch().decode('utf-8') else: return sys.stdin.read(1) def _kbhit(self): - if sys.platform == "win32": + if sys.platform == 'win32': return msvcrt.kbhit() else: (dr, dw, de) = select.select([sys.stdin], [], [], 0) diff -Nru cvise-1.6.0/cvise/utils/statistics.py cvise-2.3.0/cvise/utils/statistics.py --- cvise-1.6.0/cvise/utils/statistics.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/utils/statistics.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,5 +1,6 @@ import time + class SinglePassStatistic: def __init__(self, pass_name): self.pass_name = pass_name @@ -8,6 +9,7 @@ self.failed = 0 self.totally_executed = 0 + class PassStatistic: def __init__(self): self.stats = {} diff -Nru cvise-1.6.0/cvise/utils/testing.py cvise-2.3.0/cvise/utils/testing.py --- cvise-1.6.0/cvise/utils/testing.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise/utils/testing.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,39 +1,32 @@ -import asyncio +from concurrent.futures import FIRST_COMPLETED, TimeoutError, wait import difflib import filecmp -import importlib.util import logging import math -import multiprocessing +from multiprocessing import Manager import os import os.path -import pebble import platform import shutil -import signal -import subprocess -import sys import tempfile -import weakref import traceback -import concurrent.futures -from concurrent.futures import wait, FIRST_COMPLETED, TimeoutError -from multiprocessing import Queue, Manager - -from .. import CVise -from cvise.passes.abstract import * - -from . import readkey -from .error import InsaneTestCaseError -from .error import InvalidInterestingnessTestError -from .error import InvalidTestCaseError -from .error import PassBugError -from .error import ZeroSizeError +from cvise.cvise import CVise +from cvise.passes.abstract import PassResult, ProcessEventNotifier, ProcessEventType +from cvise.utils.error import FolderInPathTestCaseError +from cvise.utils.error import InsaneTestCaseError +from cvise.utils.error import InvalidInterestingnessTestError +from cvise.utils.error import InvalidTestCaseError +from cvise.utils.error import PassBugError +from cvise.utils.error import ZeroSizeError +from cvise.utils.readkey import KeyLogger +import pebble +import psutil # change default Pebble sleep unit for faster response pebble.common.SLEEP_UNIT = 0.01 + def rmfolder(name): assert 'cvise' in name try: @@ -41,9 +34,10 @@ except OSError: pass + class TestEnvironment: def __init__(self, state, order, test_script, folder, test_case, - additional_files, transform, pid_queue=None): + additional_files, transform, pid_queue=None): self.test_case = None self.additional_files = set() self.state = state @@ -100,47 +94,50 @@ try: # transform by state (result, self.state) = self.transform(self.test_case_path, self.state, - ProcessEventNotifier(self.pid_queue)) + ProcessEventNotifier(self.pid_queue)) self.result = result if self.result != PassResult.OK: return self # run test script - self.exitcode = self.run_test() + self.exitcode = self.run_test(False) return self - except OSError as e: + except OSError: # this can happen when we clean up temporary files for cancelled processes - pass + return self except Exception as e: print('Unexpected TestEnvironment::run failure: ' + str(e)) traceback.print_exc() - finally: return self - def run_test(self): + def run_test(self, verbose): try: os.chdir(self.folder) - _, _, returncode = ProcessEventNotifier(self.pid_queue).run_process(self.test_script, shell=True, - stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + stdout, stderr, returncode = ProcessEventNotifier(self.pid_queue).run_process(self.test_script, shell=True) + if verbose and returncode != 0: + logging.debug('stdout:\n' + stdout) + logging.debug('stderr:\n' + stderr) finally: os.chdir(self.pwd) return returncode + class TestManager: GIVEUP_CONSTANT = 50000 MAX_TIMEOUTS = 20 MAX_CRASH_DIRS = 10 MAX_EXTRA_DIRS = 25000 - TEMP_PREFIX = "cvise-" + TEMP_PREFIX = 'cvise-' def __init__(self, pass_statistic, test_script, timeout, save_temps, test_cases, parallel_tests, - no_cache, skip_key_off, silent_pass_bug, die_on_pass_bug, print_diff, max_improvement, - no_give_up, also_interesting): + no_cache, skip_key_off, silent_pass_bug, die_on_pass_bug, print_diff, max_improvement, + no_give_up, also_interesting, start_with_pass): self.test_script = os.path.abspath(test_script) self.timeout = timeout self.save_temps = save_temps self.pass_statistic = pass_statistic self.test_cases = set() + self.test_cases_modes = {} self.parallel_tests = parallel_tests self.no_cache = no_cache self.skip_key_off = skip_key_off @@ -150,10 +147,15 @@ self.max_improvement = max_improvement self.no_give_up = no_give_up self.also_interesting = also_interesting + self.start_with_pass = start_with_pass for test_case in test_cases: self.check_file_permissions(test_case, [os.F_OK, os.R_OK, os.W_OK], InvalidTestCaseError) - self.test_cases.add(os.path.abspath(test_case)) + if os.path.split(test_case)[0]: + raise FolderInPathTestCaseError(test_case) + fullpath = os.path.abspath(test_case) + self.test_cases.add(fullpath) + self.test_cases_modes[fullpath] = os.stat(fullpath).st_mode self.orig_total_file_size = self.total_file_size self.cache = {} @@ -170,6 +172,10 @@ if not self.save_temps: rmfolder(self.root) + def restore_mode(self): + for test_case in self.test_cases: + os.chmod(test_case, self.test_cases_modes[test_case]) + @classmethod def is_valid_test(cls, test_script): for mode in {os.F_OK, os.X_OK}: @@ -183,15 +189,27 @@ @property def sorted_test_cases(self): - return sorted(self.test_cases, key=os.path.getsize) + return sorted(self.test_cases, key=os.path.getsize, reverse=True) @staticmethod def get_file_size(files): return sum(os.path.getsize(f) for f in files) + @property + def total_line_count(self): + return self.get_line_count(self.test_cases) + + @staticmethod + def get_line_count(files): + lines = 0 + for file in files: + with open(file) as f: + lines += len([line for line in f.readlines() if line and not line.isspace()]) + return lines + def backup_test_cases(self): for f in self.test_cases: - orig_file = "{}.orig".format(f) + orig_file = '{}.orig'.format(f) if not os.path.exists(orig_file): # Copy file and preserve attributes @@ -212,7 +230,7 @@ def get_extra_dir(prefix, max_number): for i in range(0, max_number + 1): digits = int(round(math.log10(max_number), 0)) - extra_dir = ("{0}{1:0" + str(digits) + "d}").format(prefix, i) + extra_dir = ('{0}{1:0' + str(digits) + 'd}').format(prefix, i) if not os.path.exists(extra_dir): break @@ -226,24 +244,24 @@ def report_pass_bug(self, test_env, problem): if not self.die_on_pass_bug: - logging.warning("{} has encountered a non fatal bug: {}".format(self.current_pass, problem)) + logging.warning('{} has encountered a non fatal bug: {}'.format(self.current_pass, problem)) - crash_dir = self.get_extra_dir("cvise_bug_", self.MAX_CRASH_DIRS) + crash_dir = self.get_extra_dir('cvise_bug_', self.MAX_CRASH_DIRS) - if crash_dir == None: + if crash_dir is None: return os.mkdir(crash_dir) test_env.dump(crash_dir) if not self.die_on_pass_bug: - logging.debug("Please consider tarring up {} and creating an issue at https://github.com/marxin/cvise/issues and we will try to fix the bug.".format(crash_dir)) + logging.debug('Please consider tarring up {} and creating an issue at https://github.com/marxin/cvise/issues and we will try to fix the bug.'.format(crash_dir)) - with open(os.path.join(crash_dir, "PASS_BUG_INFO.TXT"), mode="w") as info_file: - info_file.write("Package: %s\n" % CVise.Info.PACKAGE_STRING) - info_file.write("Git version: %s\n" % CVise.Info.GIT_VERSION) - info_file.write("LLVM version: %s\n" % CVise.Info.LLVM_VERSION) - info_file.write("System: %s\n" % str(platform.uname())) + with open(os.path.join(crash_dir, 'PASS_BUG_INFO.TXT'), mode='w') as info_file: + info_file.write('Package: %s\n' % CVise.Info.PACKAGE_STRING) + info_file.write('Git version: %s\n' % CVise.Info.GIT_VERSION) + info_file.write('LLVM version: %s\n' % CVise.Info.LLVM_VERSION) + info_file.write('System: %s\n' % str(platform.uname())) info_file.write(PassBugError.MSG.format(self.current_pass, problem, test_env.state, crash_dir)) if self.die_on_pass_bug: @@ -259,20 +277,22 @@ diffed_lines = difflib.unified_diff(orig_file_lines, changed_file_lines, orig_file, changed_file) - return "".join(diffed_lines) + return ''.join(diffed_lines) - def check_sanity(self): - logging.debug("perform sanity check... ") + def check_sanity(self, verbose=False): + logging.debug('perform sanity check... ') folder = tempfile.mkdtemp(prefix=self.TEMP_PREFIX) test_env = TestEnvironment(None, 0, self.test_script, folder, None, self.test_cases, None) - logging.debug("sanity check tmpdir = {}".format(test_env.folder)) + logging.debug('sanity check tmpdir = {}'.format(test_env.folder)) - returncode = test_env.run_test() - rmfolder(folder) + returncode = test_env.run_test(verbose) if returncode == 0: - logging.debug("sanity check successful") + rmfolder(folder) + logging.debug('sanity check successful') else: + if not self.save_temps: + rmfolder(folder) raise InsaneTestCaseError(self.test_cases, self.test_script) def release_folder(self, future): @@ -287,7 +307,7 @@ @classmethod def log_key_event(cls, event): - logging.info("****** %s ******" % event) + logging.info('****** %s ******' % event) def kill_pid_queue(self): active_pids = set() @@ -299,14 +319,28 @@ active_pids.add(event.pid) for pid in active_pids: try: - os.kill(pid, signal.SIGTERM) - except ProcessLookupError: + process = psutil.Process(pid) + children = process.children(recursive=True) + children.append(process) + for child in children: + try: + child.terminate() + except psutil.NoSuchProcess: + pass + except psutil.NoSuchProcess: pass def release_future(self, future): self.futures.remove(future) self.release_folder(future) + def save_extra_dir(self, test_case_path): + extra_dir = self.get_extra_dir('cvise_extra_', self.MAX_EXTRA_DIRS) + if extra_dir is not None: + os.mkdir(extra_dir) + shutil.move(test_case_path, extra_dir) + logging.info('Created extra directory {} for you to look at later'.format(extra_dir)) + def process_done_futures(self): quit_loop = False new_futures = set() @@ -320,9 +354,10 @@ if future.exception(): if type(future.exception()) is TimeoutError: self.timeout_count += 1 - logging.debug("Test timed out!") + logging.warning('Test timed out.') + self.save_extra_dir(self.temporary_folders[future]) if self.timeout_count >= self.MAX_TIMEOUTS: - logging.warning("Maximum number of timeout were reached: %d" % self.MAX_TIMEOUTS) + logging.warning('Maximum number of timeout were reached: %d' % self.MAX_TIMEOUTS) quit_loop = True continue else: @@ -331,13 +366,13 @@ test_env = future.result() if test_env.success: if (self.max_improvement is not None and - test_env.size_improvement > self.max_improvement): - logging.debug("Too large improvement: {} B".format(test_env.size_improvement)) + test_env.size_improvement > self.max_improvement): + logging.debug('Too large improvement: {} B'.format(test_env.size_improvement)) else: # Report bug if transform did not change the file if filecmp.cmp(self.current_test_case, test_env.test_case_path): if not self.silent_pass_bug: - self.report_pass_bug(test_env, "pass failed to modify the variant") + self.report_pass_bug(test_env, 'pass failed to modify the variant') else: quit_loop = True new_futures.add(future) @@ -346,32 +381,28 @@ if test_env.result == PassResult.OK: assert test_env.exitcode if (self.also_interesting is not None and - test_env.exitcode == self.also_interesting): - extra_dir = self.get_extra_dir("cvise_extra_", self.MAX_EXTRA_DIRS) - if extra_dir != None: - os.mkdir(extra_dir) - shutil.move(test_env.test_case_path, extra_dir) - logging.info("Created extra directory {} for you to look at later".format(extra_dir)) + test_env.exitcode == self.also_interesting): + self.save_extra_dir(test_env.test_case_path) elif test_env.result == PassResult.STOP: quit_loop = True elif test_env.result == PassResult.ERROR: if not self.silent_pass_bug: - self.report_pass_bug(test_env, "pass error") + self.report_pass_bug(test_env, 'pass error') quit_loop = True if not self.no_give_up and test_env.order > self.GIVEUP_CONSTANT: - self.report_pass_bug(test_env, "pass got stuck") + self.report_pass_bug(test_env, 'pass got stuck') quit_loop = True else: new_futures.add(future) - removed_futures = [f for f in self.futures if not f in new_futures] + removed_futures = [f for f in self.futures if f not in new_futures] for f in removed_futures: self.release_future(f) return quit_loop def wait_for_first_success(self): - for i, future in enumerate(self.futures): + for future in self.futures: try: test_env = future.result() if test_env.success: @@ -391,7 +422,7 @@ with pebble.ProcessPool(max_workers=self.parallel_tests) as pool: order = 1 self.timeout_count = 0 - while self.state != None: + while self.state is not None: # do not create too many states if len(self.futures) >= self.parallel_tests: wait(self.futures, return_when=FIRST_COMPLETED) @@ -404,8 +435,8 @@ folder = tempfile.mkdtemp(prefix=self.TEMP_PREFIX, dir=self.root) test_env = TestEnvironment(self.state, order, self.test_script, folder, - self.current_test_case, self.test_cases ^ {self.current_test_case}, - self.current_pass.transform, self.pid_queue) + self.current_test_case, self.test_cases ^ {self.current_test_case}, + self.current_pass.transform, self.pid_queue) future = pool.schedule(test_env.run, timeout=self.timeout) self.temporary_folders[future] = folder self.futures.append(future) @@ -413,7 +444,7 @@ order += 1 state = self.current_pass.advance(self.current_test_case, self.state) # we are at the end of enumeration - if state == None: + if state is None: success = self.wait_for_first_success() self.terminate_all(pool) return success @@ -421,6 +452,12 @@ self.state = state def run_pass(self, pass_): + if self.start_with_pass: + if self.start_with_pass == str(pass_): + self.start_with_pass = None + else: + return + self.current_pass = pass_ self.futures = [] self.temporary_folders = {} @@ -429,46 +466,46 @@ self.create_root() pass_key = repr(self.current_pass) - logging.info("===< {} >===".format(self.current_pass)) + logging.info('===< {} >==='.format(self.current_pass)) if self.total_file_size == 0: raise ZeroSizeError(self.test_cases) self.pass_statistic.start(self.current_pass) if not self.skip_key_off: - logger = readkey.KeyLogger() + logger = KeyLogger() - for test_case in self.test_cases: + for test_case in self.sorted_test_cases: self.current_test_case = test_case if self.get_file_size([test_case]) == 0: continue if not self.no_cache: - with open(test_case, mode="r+") as tmp_file: + with open(test_case, mode='r+') as tmp_file: test_case_before_pass = tmp_file.read() if (pass_key in self.cache and - test_case_before_pass in self.cache[pass_key]): + test_case_before_pass in self.cache[pass_key]): tmp_file.seek(0) tmp_file.truncate(0) tmp_file.write(self.cache[pass_key][test_case_before_pass]) - logging.info("cache hit for {}".format(test_case)) + logging.info('cache hit for {}'.format(test_case)) continue # create initial state - self.state = self.current_pass.new(self.current_test_case) + self.state = self.current_pass.new(self.current_test_case, self.check_sanity) self.skip = False - while self.state != None and not self.skip: + while self.state is not None and not self.skip: # Ignore more key presses after skip has been detected if not self.skip_key_off and not self.skip: key = logger.pressed_key() - if key == "s": + if key == 's': self.skip = True - self.log_key_event("skipping the rest of this pass") - elif key == "d": - self.log_key_event("toggle print diff") + self.log_key_event('skipping the rest of this pass') + elif key == 'd': + self.log_key_event('toggle print diff') self.print_diff = not self.print_diff success_env = self.run_parallel_tests() @@ -483,12 +520,13 @@ # Cache result of this pass if not self.no_cache: - with open(test_case, mode="r") as tmp_file: + with open(test_case, mode='r') as tmp_file: if pass_key not in self.cache: self.cache[pass_key] = {} self.cache[pass_key][test_case_before_pass] = tmp_file.read() + self.restore_mode() self.remove_root() self.pass_statistic.stop(self.current_pass) @@ -503,4 +541,4 @@ self.pass_statistic.add_success(self.current_pass) pct = 100 - (self.total_file_size * 100.0 / self.orig_total_file_size) - logging.info("({}%, {} bytes)".format(round(pct, 1), self.total_file_size)) + logging.info('({}%, {} bytes, {} lines)'.format(round(pct, 1), self.total_file_size, self.total_line_count)) diff -Nru cvise-1.6.0/cvise.py cvise-2.3.0/cvise.py --- cvise-1.6.0/cvise.py 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/cvise.py 2021-03-09 08:18:13.000000000 +0000 @@ -1,71 +1,75 @@ #!/usr/bin/env python3 import argparse +import datetime +import importlib.util import logging import os import os.path +import platform import shutil import sys -import time -import datetime -import psutil -import platform import tempfile - -import importlib.util - -destdir = os.getenv("DESTDIR", "") +import time # If the cvise modules cannot be found # add the known install location to the path -if importlib.util.find_spec("cvise") is None: - sys.path.append("@CMAKE_INSTALL_FULL_DATADIR@") - sys.path.append(destdir + "@CMAKE_INSTALL_FULL_DATADIR@") - -from cvise import CVise -from cvise.passes.abstract import AbstractPass -from cvise.utils.error import CViseError -from cvise.utils.error import MissingPassGroupsError -from cvise.utils import testing -from cvise.utils import statistics +destdir = os.getenv('DESTDIR', '') +if importlib.util.find_spec('cvise') is None: + sys.path.append('@CMAKE_INSTALL_FULL_DATADIR@') + sys.path.append(destdir + '@CMAKE_INSTALL_FULL_DATADIR@') + +from cvise.cvise import CVise # noqa: E402 +from cvise.passes.abstract import AbstractPass # noqa: E402 +from cvise.utils import statistics # noqa: E402 +from cvise.utils import testing # noqa: E402 +from cvise.utils.error import CViseError # noqa: E402 +from cvise.utils.error import MissingPassGroupsError # noqa: E402 +import psutil # noqa: E402 + class DeltaTimeFormatter(logging.Formatter): - def format(self, record): - duration = datetime.datetime.utcfromtimestamp(record.relativeCreated / 1000) - record.delta = duration.strftime("%H:%M:%S") + def format(self, record): # noqa: A003 + record.delta = str(datetime.timedelta(seconds=int(record.relativeCreated / 1000))) + # pad with one more zero + if record.delta[1] == ':': + record.delta = '0' + record.delta return super().format(record) + script_path = os.path.dirname(os.path.realpath(__file__)) + def get_share_dir(): # Test all known locations for the cvise directory share_dirs = [ - os.path.join("@CMAKE_INSTALL_FULL_DATADIR@", "@cvise_PACKAGE@"), - destdir + os.path.join("@CMAKE_INSTALL_FULL_DATADIR@", "@cvise_PACKAGE@"), - os.path.join(script_path, "cvise") - ] + os.path.join('@CMAKE_INSTALL_FULL_DATADIR@', '@cvise_PACKAGE@'), + destdir + os.path.join('@CMAKE_INSTALL_FULL_DATADIR@', '@cvise_PACKAGE@'), + os.path.join(script_path, 'cvise') + ] for d in share_dirs: if os.path.isdir(d): return d - raise CViseError("Cannot find cvise module directory!") + raise CViseError('Cannot find cvise module directory!') + def find_external_programs(): programs = { - "clang_delta" : "clang_delta", - "clex" : "clex", - "topformflat" : "delta" , - "unifdef" : None, - } + 'clang_delta': 'clang_delta', + 'clex': 'clex', + 'topformflat': 'delta', + 'unifdef': None, + } for prog, local_folder in programs.items(): path = None if local_folder: local_folder = os.path.join(script_path, local_folder) - if platform.system() == "Windows": - for configuration in ["Debug", "Release"]: + if platform.system() == 'Windows': + for configuration in ['Debug', 'Release']: new_local_folder = os.path.join(local_folder, configuration) if os.path.exists(new_local_folder): local_folder = new_local_folder @@ -74,10 +78,10 @@ path = shutil.which(prog, path=local_folder) if not path: - search = os.path.join("@CMAKE_INSTALL_FULL_LIBEXECDIR@", "@cvise_PACKAGE@") + search = os.path.join('@CMAKE_INSTALL_FULL_LIBEXECDIR@', '@cvise_PACKAGE@') path = shutil.which(prog, path=search) if not path: - search = destdir + os.path.join("@CMAKE_INSTALL_FULL_LIBEXECDIR@", "@cvise_PACKAGE@") + search = destdir + os.path.join('@CMAKE_INSTALL_FULL_LIBEXECDIR@', '@cvise_PACKAGE@') path = shutil.which(prog, path=search) if not path: @@ -87,15 +91,17 @@ programs[prog] = path # Special case for clang-format - programs["clang-format"] = "@CLANG_FORMAT_PATH@" + programs['clang-format'] = '@CLANG_FORMAT_PATH@' return programs + def get_pass_group_path(name): - return os.path.join(get_share_dir(), "pass_groups", name + ".json") + return os.path.join(get_share_dir(), 'pass_groups', name + '.json') + def get_available_pass_groups(): - pass_group_dir = os.path.join(get_share_dir(), "pass_groups") + pass_group_dir = os.path.join(get_share_dir(), 'pass_groups') if not os.path.isdir(pass_group_dir): raise MissingPassGroupsError() @@ -110,15 +116,16 @@ try: pass_group_dict = CVise.load_pass_group_file(path) - CVise.parse_pass_group_dict(pass_group_dict, set(), None, None, None, None, None) + CVise.parse_pass_group_dict(pass_group_dict, set(), None, None, None, None, None, None) except MissingPassGroupsError: - logging.warning("Skipping file {}. Not valid pass group.".format(path)) + logging.warning('Skipping file {}. Not valid pass group.'.format(path)) else: (name, _) = os.path.splitext(entry) group_names.append(name) return group_names + EPILOG_TEXT = """ available shortcuts: S - skip execution of the current pass @@ -128,70 +135,76 @@ %s """ % CVise.Info.PACKAGE_URL -if __name__ == "__main__": +if __name__ == '__main__': try: # try to detect only physical cores, ignore HyperThreading # in order to speed up parallel execution core_count = psutil.cpu_count(logical=False) if not core_count: - psutil.cpu_count(logical=True) + core_count = psutil.cpu_count(logical=True) # respect affinity affinity = len(psutil.Process().cpu_affinity()) - core_count = min(core_count, affinity) + assert affinity >= 1 + if core_count: + core_count = min(core_count, affinity) + else: + core_count = affinity except NotImplementedError: core_count = 1 - parser = argparse.ArgumentParser(description="C-Vise", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=EPILOG_TEXT) - parser.add_argument("--n", "-n", type=int, default=core_count, help="Number of cores to use; C-Vise tries to automatically pick a good setting but its choice may be too low or high for your situation") - parser.add_argument("--tidy", action="store_true", default=False, help="Do not make a backup copy of each file to reduce as file.orig") - parser.add_argument("--shaddap", action="store_true", default=False, help="Suppress output about non-fatal internal errors") - parser.add_argument("--die-on-pass-bug", action="store_true", default=False, help="Terminate C-Vise if a pass encounters an otherwise non-fatal problem") - parser.add_argument("--sllooww", action="store_true", default=False, help="Try harder to reduce, but perhaps take a long time to do so") - parser.add_argument("--also-interesting", metavar="EXIT_CODE", type=int, help="A process exit code (somewhere in the range 64-113 would be usual) that, when returned by the interestingness test, will cause C-Vise to save a copy of the variant") - parser.add_argument("--debug", action="store_true", default=False, help="Print debug information") - parser.add_argument("--log-level", type=str, choices=["INFO", "DEBUG", "WARNING", "ERROR"], default="INFO", help="Define the verbosity of the logged events") - parser.add_argument("--log-file", type=str, help="Log events into LOG_FILE instead of stderr. New events are appended to the end of the file") - parser.add_argument("--no-give-up", action="store_true", default=False, help="Don't give up on a pass that hasn't made progress for {} iterations".format(testing.TestManager.GIVEUP_CONSTANT)) - parser.add_argument("--print-diff", action="store_true", default=False, help="Show changes made by transformations, for debugging") - parser.add_argument("--save-temps", action="store_true", default=False, help="Don't delete /tmp/cvise-xxxxxx directories on termination") - parser.add_argument("--skip-initial-passes", action="store_true", default=False, help="Skip initial passes (useful if input is already partially reduced)") - parser.add_argument("--remove-pass", help="Remove all instances of the specified passes from the schedule (comma-separated)") - parser.add_argument("--no-timing", action="store_true", default=False, help="Do not print timestamps about reduction progress") - parser.add_argument("--timestamp", action="store_true", default=False, help="Print timestamps instead of relative time from a reduction start") - parser.add_argument("--timeout", type=int, nargs="?", const=300, help="Interestingness test timeout in seconds") - parser.add_argument("--no-cache", action="store_true", default=False, help="Don't cache behavior of passes") - parser.add_argument("--skip-key-off", action="store_true", default=False, help="Disable skipping the rest of the current pass when \"s\" is pressed") - parser.add_argument("--max-improvement", metavar="BYTES", type=int, help="Largest improvement in file size from a single transformation that C-Vise should accept (useful only to slow C-Vise down)") + parser = argparse.ArgumentParser(description='C-Vise', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=EPILOG_TEXT) + parser.add_argument('--n', '-n', type=int, default=core_count, help='Number of cores to use; C-Vise tries to automatically pick a good setting but its choice may be too low or high for your situation') + parser.add_argument('--tidy', action='store_true', default=False, help='Do not make a backup copy of each file to reduce as file.orig') + parser.add_argument('--shaddap', action='store_true', default=False, help='Suppress output about non-fatal internal errors') + parser.add_argument('--die-on-pass-bug', action='store_true', default=False, help='Terminate C-Vise if a pass encounters an otherwise non-fatal problem') + parser.add_argument('--sllooww', action='store_true', default=False, help='Try harder to reduce, but perhaps take a long time to do so') + parser.add_argument('--also-interesting', metavar='EXIT_CODE', type=int, help='A process exit code (somewhere in the range 64-113 would be usual) that, when returned by the interestingness test, will cause C-Vise to save a copy of the variant') + parser.add_argument('--debug', action='store_true', default=False, help='Print debug information (alias for --log-level=DEBUG)') + parser.add_argument('--log-level', type=str, choices=['INFO', 'DEBUG', 'WARNING', 'ERROR'], default='INFO', help='Define the verbosity of the logged events') + parser.add_argument('--log-file', type=str, help='Log events into LOG_FILE instead of stderr. New events are appended to the end of the file') + parser.add_argument('--no-give-up', action='store_true', default=False, help="Don't give up on a pass that hasn't made progress for {} iterations".format(testing.TestManager.GIVEUP_CONSTANT)) + parser.add_argument('--print-diff', action='store_true', default=False, help='Show changes made by transformations, for debugging') + parser.add_argument('--save-temps', action='store_true', default=False, help="Don't delete /tmp/cvise-xxxxxx directories on termination") + parser.add_argument('--skip-initial-passes', action='store_true', default=False, help='Skip initial passes (useful if input is already partially reduced)') + parser.add_argument('--remove-pass', help='Remove all instances of the specified passes from the schedule (comma-separated)') + parser.add_argument('--start-with-pass', help='Start with the specified pass') + parser.add_argument('--no-timing', action='store_true', default=False, help='Do not print timestamps about reduction progress') + parser.add_argument('--timestamp', action='store_true', default=False, help='Print timestamps instead of relative time from a reduction start') + parser.add_argument('--timeout', type=int, nargs='?', default=300, help='Interestingness test timeout in seconds') + parser.add_argument('--no-cache', action='store_true', default=False, help="Don't cache behavior of passes") + parser.add_argument('--skip-key-off', action='store_true', default=False, help="Disable skipping the rest of the current pass when 's' is pressed") + parser.add_argument('--max-improvement', metavar='BYTES', type=int, help='Largest improvement in file size from a single transformation that C-Vise should accept (useful only to slow C-Vise down)') passes_group = parser.add_mutually_exclusive_group() - passes_group.add_argument("--pass-group", type=str, choices=get_available_pass_groups(), help="Set of passes used during the reduction") - passes_group.add_argument("--pass-group-file", type=str, help="JSON file defining a custom pass group") - parser.add_argument("--clang-delta-std", type=str, choices=["c++98", "c++11", "c++14", "c++17", "c++20"], help="Specify clang_delta C++ standard, it can rapidly speed up all clang_delta passes") - parser.add_argument("--not-c", action="store_true", help="Don't run passes that are specific to C and C++, use this mode for reducing other languages") - parser.add_argument("--no-renaming", action="store_true", help="Skip all renaming passes") - parser.add_argument("--list-passes", action="store_true", help="Print all available passes and exit") - parser.add_argument("--version", action="version", version=CVise.Info.PACKAGE_STRING + (' (%s)' % CVise.Info.GIT_VERSION if CVise.Info.GIT_VERSION != 'unknown' else '')) - parser.add_argument("--commands", "-c", help="Use bash commands instead of an interestingness test case") - parser.add_argument("interestingness_test", metavar="INTERESTINGNESS_TEST", nargs="?", help="Executable to check interestingness of test cases") - parser.add_argument("test_cases", metavar="TEST_CASE", nargs="+", help="Test cases") + passes_group.add_argument('--pass-group', type=str, choices=get_available_pass_groups(), help='Set of passes used during the reduction') + passes_group.add_argument('--pass-group-file', type=str, help='JSON file defining a custom pass group') + parser.add_argument('--clang-delta-std', type=str, choices=['c++98', 'c++11', 'c++14', 'c++17', 'c++20'], help='Specify clang_delta C++ standard, it can rapidly speed up all clang_delta passes') + parser.add_argument('--clang-delta-preserve-routine', type=str, help='Preserve the given function in replace-function-def-with-decl clang delta pass') + parser.add_argument('--not-c', action='store_true', help="Don't run passes that are specific to C and C++, use this mode for reducing other languages") + parser.add_argument('--renaming', action='store_true', help='Enable all renaming passes (that are disabled by default)') + parser.add_argument('--list-passes', action='store_true', help='Print all available passes and exit') + parser.add_argument('--version', action='version', version=CVise.Info.PACKAGE_STRING + (' (%s)' % CVise.Info.GIT_VERSION if CVise.Info.GIT_VERSION != 'unknown' else '')) + parser.add_argument('--commands', '-c', help='Use bash commands instead of an interestingness test case') + parser.add_argument('interestingness_test', metavar='INTERESTINGNESS_TEST', nargs='?', help='Executable to check interestingness of test cases') + parser.add_argument('test_cases', metavar='TEST_CASE', nargs='+', help='Test cases') args = parser.parse_args() log_config = {} - log_format = "%(levelname)s %(message)s" + log_format = '%(levelname)s %(message)s' if not args.no_timing: if args.timestamp: - log_format = "%(asctime)s " + log_format + log_format = '%(asctime)s ' + log_format else: - log_format = "%(delta)s " + log_format + log_format = '%(delta)s ' + log_format if args.debug: - log_config["level"] = logging.DEBUG + log_config['level'] = logging.DEBUG else: - log_config["level"] = getattr(logging, args.log_level.upper()) + log_config['level'] = getattr(logging, args.log_level.upper()) if args.log_file is not None: - log_config["filename"] = args.log_file + log_config['filename'] = args.log_file logging.basicConfig(**log_config) syslog = logging.StreamHandler() @@ -202,7 +215,7 @@ pass_options = set() - if sys.platform == "win32": + if sys.platform == 'win32': pass_options.add(AbstractPass.Option.windows) if args.sllooww: @@ -213,23 +226,24 @@ elif args.pass_group_file is not None: pass_group_file = args.pass_group_file else: - pass_group_file = get_pass_group_path("all") + pass_group_file = get_pass_group_path('all') external_programs = find_external_programs() pass_group_dict = CVise.load_pass_group_file(pass_group_file) pass_group = CVise.parse_pass_group_dict(pass_group_dict, pass_options, external_programs, - args.remove_pass, args.clang_delta_std, args.not_c, args.no_renaming) + args.remove_pass, args.clang_delta_std, + args.clang_delta_preserve_routine, args.not_c, args.renaming) if args.list_passes: logging.info('Available passes:') logging.info('INITIAL PASSES') - for p in pass_group["first"]: + for p in pass_group['first']: logging.info(str(p)) logging.info('MAIN PASSES') - for p in pass_group["main"]: + for p in pass_group['main']: logging.info(str(p)) logging.info('CLEANUP PASSES') - for p in pass_group["last"]: + for p in pass_group['last']: logging.info(str(p)) sys.exit(0) @@ -241,9 +255,14 @@ print('Either INTERESTINGNESS_TEST or --commands must be used!') exit(1) + # shift interestingness_test if --commands is used + if args.interestingness_test and args.commands: + args.test_cases.insert(0, args.interestingness_test) + args.interestingness_test = None + script = None if args.commands: - with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".sh") as script: + with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.sh') as script: script.write('#!/bin/bash\n\n') script.write(args.commands + '\n') os.chmod(script.name, 0o744) @@ -251,8 +270,9 @@ args.interestingness_test = script.name test_manager = testing.TestManager(pass_statistic, args.interestingness_test, args.timeout, - args.save_temps, args.test_cases, args.n, args.no_cache, args.skip_key_off, args.shaddap, - args.die_on_pass_bug, args.print_diff, args.max_improvement, args.no_give_up, args.also_interesting) + args.save_temps, args.test_cases, args.n, args.no_cache, args.skip_key_off, args.shaddap, + args.die_on_pass_bug, args.print_diff, args.max_improvement, args.no_give_up, args.also_interesting, + args.start_with_pass) reducer = CVise(test_manager) @@ -268,24 +288,25 @@ print(err) else: time_stop = time.monotonic() - print("===< PASS statistics >===") - print(" %-54s %8s %8s %8s %8s %15s" % ("pass name", "time (s)", "time (%)", "worked", - "failed", "total executed")) + print('===< PASS statistics >===') + print(' %-54s %8s %8s %8s %8s %15s' % ('pass name', 'time (s)', 'time (%)', 'worked', + 'failed', 'total executed')) for pass_name, pass_data in pass_statistic.sorted_results: - print(" %-54s %8.2f %8.2f %8d %8d %15d" % (pass_name, pass_data.total_seconds, - 100.0 * pass_data.total_seconds / (time_stop - time_start), + print(' %-54s %8.2f %8.2f %8d %8d %15d' % (pass_name, pass_data.total_seconds, + 100.0 * pass_data.total_seconds / (time_stop - time_start), pass_data.worked, pass_data.failed, pass_data.totally_executed)) print() if not args.no_timing: - print("Runtime: {} seconds".format(round((time_stop - time_start)))) + print('Runtime: {} seconds'.format(round((time_stop - time_start)))) print('Reduced test-cases:\n') - for test_case in test_manager.sorted_test_cases: + for test_case in sorted(test_manager.test_cases): + print(f'--- {test_case} ---') with open(test_case) as test_case_file: print(test_case_file.read()) if script: - os.remove(script.name) + os.unlink(script.name) logging.shutdown() diff -Nru cvise-1.6.0/debian/changelog cvise-2.3.0/debian/changelog --- cvise-1.6.0/debian/changelog 2020-09-29 14:55:47.000000000 +0000 +++ cvise-2.3.0/debian/changelog 2021-03-24 17:32:22.000000000 +0000 @@ -1,8 +1,78 @@ -cvise (1.6.0-3~18.04) bionic-proposed; urgency=medium +cvise (2.3.0-0ubuntu1~18.04) bionic-proposed; urgency=medium - * SRU: LP: #1895971. Backport cvise to the LTS releases. + * SRU: LP: #1921105. Backport cvise. + * Build using LLVM 9. + * Disable the flake tests, pytest-flake8 not available. - -- Matthias Klose Tue, 29 Sep 2020 16:55:47 +0200 + -- Matthias Klose Wed, 24 Mar 2021 18:32:22 +0100 + +cvise (2.3.0-0ubuntu1) hirsute; urgency=medium + + * New upstream version. + * Build using LLVM 12. + + -- Matthias Klose Tue, 16 Mar 2021 11:11:13 +0100 + +cvise (2.2.0-2) unstable; urgency=medium + + * Fix issue #47, remove temporary files in working directory. + + -- Matthias Klose Mon, 08 Mar 2021 16:41:40 +0100 + +cvise (2.2.0-1) unstable; urgency=medium + + * New upstream version. + + -- Matthias Klose Fri, 05 Mar 2021 18:25:42 +0100 + +cvise (2.1.0-1) unstable; urgency=medium + + * New upstream version. + + -- Matthias Klose Tue, 12 Jan 2021 19:21:35 +0100 + +cvise (2.0.0-4) unstable; urgency=medium + + * Update to the branch 20210108. + * Build using LLVM 9 on armel, armhf. See #979495. + * Bump debhelper version. + + -- Matthias Klose Fri, 08 Jan 2021 14:02:42 +0100 + +cvise (2.0.0-3) unstable; urgency=medium + + * Update to the branch 20201126. + - Handle using declarations declared with macros. + * Bump standards version. + + -- Matthias Klose Sun, 13 Dec 2020 12:37:58 +0100 + +cvise (2.0.0-2) unstable; urgency=medium + + * New upstream version. + * Updates up to 7c303ae036e18be10ab4014724b9e14d4a1245d6. + + -- Matthias Klose Tue, 17 Nov 2020 14:09:28 +0100 + +cvise (1.9.0-1) unstable; urgency=medium + + * New upstream version. + * Updates up to a000f9eefce217576ac3095a443fcd9bb7b95953. + + -- Matthias Klose Tue, 10 Nov 2020 12:03:35 +0100 + +cvise (1.8.0-1) unstable; urgency=medium + + * New upstream version. + * Build using LLVM 11. + + -- Matthias Klose Thu, 22 Oct 2020 13:17:58 +0200 + +cvise (1.7.0-1) unstable; urgency=medium + + * New upstream version. + + -- Matthias Klose Tue, 06 Oct 2020 14:00:36 +0200 cvise (1.6.0-3) unstable; urgency=medium diff -Nru cvise-1.6.0/debian/compat cvise-2.3.0/debian/compat --- cvise-1.6.0/debian/compat 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/debian/compat 2021-03-24 12:14:53.000000000 +0000 @@ -0,0 +1 @@ +11 diff -Nru cvise-1.6.0/debian/control cvise-2.3.0/debian/control --- cvise-1.6.0/debian/control 2020-07-22 16:58:21.000000000 +0000 +++ cvise-2.3.0/debian/control 2021-03-24 13:16:56.000000000 +0000 @@ -3,7 +3,7 @@ Priority: optional Maintainer: Debian GCC Maintainers Uploaders: Matthias Klose -Build-Depends: debhelper-compat (= 11), +Build-Depends: debhelper (>= 11), dh-python, chrpath, cmake, @@ -11,16 +11,16 @@ python3, python3-pebble, python3-psutil, - python3-pytest, - llvm-10-dev, libclang-10-dev, clang-10, clang-format-10, + python3-pytest , + llvm-9-dev, libclang-9-dev, clang-9, clang-format-9, unifdef, -Standards-Version: 4.5.0 +Standards-Version: 4.5.1 Homepage: https://github.com/marxin/cvise Package: cvise Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${python3:Depends}, - clang-format-10, + clang-format-9, python3, python3-pebble, python3-psutil, diff -Nru cvise-1.6.0/debian/cvise.1 cvise-2.3.0/debian/cvise.1 --- cvise-1.6.0/debian/cvise.1 2020-08-02 11:25:41.000000000 +0000 +++ cvise-2.3.0/debian/cvise.1 2021-03-16 10:11:13.000000000 +0000 @@ -1,5 +1,5 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.16. -.TH CVISE "1" "August 2020" "cvise 1.6.0" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. +.TH CVISE "1" "March 2021" "cvise 2.3.0" "User Commands" .SH NAME cvise \- super-parallel Python port of the C-Reduce project .SH DESCRIPTION @@ -8,12 +8,15 @@ [\-\-also\-interesting EXIT_CODE] [\-\-debug] [\-\-log\-level {INFO,DEBUG,WARNING,ERROR}] [\-\-log\-file LOG_FILE] [\-\-no\-give\-up] [\-\-print\-diff] [\-\-save\-temps] -[\-\-skip\-initial\-passes] [\-\-remove\-pass REMOVE_PASS] [\-\-no\-timing] -[\-\-timestamp] [\-\-timeout [TIMEOUT]] [\-\-no\-cache] [\-\-skip\-key\-off] +[\-\-skip\-initial\-passes] [\-\-remove\-pass REMOVE_PASS] +[\-\-start\-with\-pass START_WITH_PASS] [\-\-no\-timing] [\-\-timestamp] +[\-\-timeout [TIMEOUT]] [\-\-no\-cache] [\-\-skip\-key\-off] [\-\-max\-improvement BYTES] [\-\-pass\-group {opencl\-120,delta,all} | \fB\-\-pass\-group\-file\fR PASS_GROUP_FILE] -[\-\-clang\-delta\-std {c++98,c++11,c++14,c++17,c++20}] [\-\-not\-c] -[\-\-no\-renaming] [\-\-list\-passes] [\-\-version] [\-\-commands COMMANDS] +[\-\-clang\-delta\-std {c++98,c++11,c++14,c++17,c++20}] +[\-\-clang\-delta\-preserve\-routine CLANG_DELTA_PRESERVE_ROUTINE] +[\-\-not\-c] [\-\-renaming] [\-\-list\-passes] [\-\-version] +[\-\-commands COMMANDS] [INTERESTINGNESS_TEST] TEST_CASE [TEST_CASE ...] .PP C\-Vise @@ -56,7 +59,7 @@ of the variant .TP \fB\-\-debug\fR -Print debug information +Print debug information (alias for \fB\-\-log\-level\fR=\fI\,DEBUG\/\fR) .TP \fB\-\-log\-level\fR {INFO,DEBUG,WARNING,ERROR} Define the verbosity of the logged events @@ -84,6 +87,9 @@ Remove all instances of the specified passes from the schedule (comma\-separated) .TP +\fB\-\-start\-with\-pass\fR START_WITH_PASS +Start with the specified pass +.TP \fB\-\-no\-timing\fR Do not print timestamps about reduction progress .TP @@ -98,7 +104,7 @@ Don't cache behavior of passes .TP \fB\-\-skip\-key\-off\fR -Disable skipping the rest of the current pass when "s" +Disable skipping the rest of the current pass when 's' is pressed .TP \fB\-\-max\-improvement\fR BYTES @@ -116,12 +122,16 @@ Specify clang_delta C++ standard, it can rapidly speed up all clang_delta passes .TP +\fB\-\-clang\-delta\-preserve\-routine\fR CLANG_DELTA_PRESERVE_ROUTINE +Preserve the given function in replace\-function\-defwith\-decl clang delta pass +.TP \fB\-\-not\-c\fR Don't run passes that are specific to C and C++, use this mode for reducing other languages .TP -\fB\-\-no\-renaming\fR -Skip all renaming passes +\fB\-\-renaming\fR +Enable all renaming passes (that are disabled by +default) .TP \fB\-\-list\-passes\fR Print all available passes and exit diff -Nru cvise-1.6.0/debian/patches/git-updates.diff cvise-2.3.0/debian/patches/git-updates.diff --- cvise-1.6.0/debian/patches/git-updates.diff 2020-09-29 14:37:35.000000000 +0000 +++ cvise-2.3.0/debian/patches/git-updates.diff 2021-01-12 18:22:02.000000000 +0000 @@ -1,1004 +1,2 @@ -# git diff 1b1be7cbd031bbaf9890ded1f6469751dbcb6f1b a12db897b505dce499064f99313991f7037bd77f +git diff cfdc48293830e30782091b98e7da7316482f4c2c 1a9f47f5303705f3138816679d20c85d365d11d8 -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 0308d32..306ff08 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -187,6 +187,19 @@ configure_file( - @ONLY - ) - -+configure_file( -+ "${PROJECT_SOURCE_DIR}/tests/test_cvise.py" -+ "${PROJECT_BINARY_DIR}/tests/test_cvise.py" -+ @COPYONLY -+) -+ -+configure_file( -+ "${PROJECT_SOURCE_DIR}/tests/sources/blocksort-part.c" -+ "${PROJECT_BINARY_DIR}/tests/sources/blocksort-part.c" -+ @COPYONLY -+) -+ -+ - install(PROGRAMS "${PROJECT_BINARY_DIR}/cvise.py" - DESTINATION "${CMAKE_INSTALL_BINDIR}" - RENAME "cvise" -diff --git a/CREDUCE_MERGE b/CREDUCE_MERGE -index 82125fe..2beaa51 100644 ---- a/CREDUCE_MERGE -+++ b/CREDUCE_MERGE -@@ -1,2 +1,2 @@ - Last cherry-picked git revision: --274e1fe5210b379fbfdca9a565715d2db1df2d04 -+c32c5c327758a047ae10e55a2465ba54293dfff9 -diff --git a/Docker/Dockerfile-fedora32-llvm9 b/Docker/Dockerfile-fedora32-llvm9 -index c37778e..eaf77d3 100644 ---- a/Docker/Dockerfile-fedora32-llvm9 -+++ b/Docker/Dockerfile-fedora32-llvm9 -@@ -1,6 +1,6 @@ - FROM fedora:31 - --RUN dnf install -y python3-pip python3-pytest llvm-devel clang-devel cmake make flex unifdef -+RUN dnf install -y python3-pip python3-pytest python3-psutil llvm-devel clang-devel cmake make flex unifdef - RUN pip3 install Pebble - - WORKDIR /usr/src/cvise -diff --git a/Docker/Dockerfile-fedoradev-llvm10 b/Docker/Dockerfile-fedoradev-llvm10 -index 4a22183..654eddf 100644 ---- a/Docker/Dockerfile-fedoradev-llvm10 -+++ b/Docker/Dockerfile-fedoradev-llvm10 -@@ -1,6 +1,6 @@ - FROM fedora:rawhide - --RUN dnf install -y python3-pip python3-pytest llvm-devel clang-devel cmake make flex unifdef -+RUN dnf install -y python3-pip python3-pytest python3-psutil llvm-devel clang-devel cmake make flex unifdef - RUN pip3 install Pebble - - WORKDIR /usr/src/cvise -diff --git a/Docker/Dockerfile-opensusetw-llvm10 b/Docker/Dockerfile-opensusetw-llvm10 -index ee8ae05..af4af6e 100644 ---- a/Docker/Dockerfile-opensusetw-llvm10 -+++ b/Docker/Dockerfile-opensusetw-llvm10 -@@ -1,7 +1,7 @@ - FROM opensuse/tumbleweed - - RUN zypper -n install \ -- binutils clang10-devel cmake flex gcc-c++ llvm10-devel python3-Pebble python3-pytest4 unifdef python3-pip sqlite-devel git python3 -+ binutils clang10-devel cmake flex gcc-c++ llvm10-devel python3-Pebble python3-pytest4 unifdef python3-pip python3-psutil sqlite-devel git python3 - RUN pip install codecov pytest-cov - ENV LSAN_OPTIONS="detect_leaks=0" - -diff --git a/Docker/Dockerfile-opensusetw-llvm9 b/Docker/Dockerfile-opensusetw-llvm9 -index 99e8c50..8b96d6b 100644 ---- a/Docker/Dockerfile-opensusetw-llvm9 -+++ b/Docker/Dockerfile-opensusetw-llvm9 -@@ -1,7 +1,7 @@ - FROM opensuse/tumbleweed - - RUN zypper -n install \ -- binutils clang9-devel cmake flex gcc-c++ llvm9-devel python3-Pebble python3-pytest unifdef -+ binutils clang9-devel cmake flex gcc-c++ llvm9-devel python3-Pebble python3-pytest python3-psutil unifdef - ENV LSAN_OPTIONS="detect_leaks=0" - - WORKDIR /usr/src/cvise -diff --git a/INSTALL.md b/INSTALL.md -index cb66f36..71e40fa 100644 ---- a/INSTALL.md -+++ b/INSTALL.md -@@ -3,7 +3,7 @@ - ## Using a Package Manager - - Before compiling C-Vise yourself, you might want to see if your OS --comes with a precompiled package for C-Vise. -+comes with a pre-compiled package for C-Vise. - - ### openSUSE Tumbleweed - -diff --git a/README.md b/README.md -index 9bbb9d8..2ed58d1 100644 ---- a/README.md -+++ b/README.md -@@ -1,5 +1,6 @@ - # C-Vise - -+[![OBS master](https://build.opensuse.org/assets/favicon-ac48595b97f38c2425d7ea77739a63d771fcda9f73cc8c474b66461c0836fc2a.ico)](https://build.opensuse.org/package/show/home:marxin:cvise-github/cvise) - [![Travis Build Status](https://travis-ci.com/marxin/cvise.svg?branch=master)](https://travis-ci.com/marxin/cvise) - [![Total alerts](https://img.shields.io/lgtm/alerts/g/marxin/cvise.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/marxin/cvise/alerts/) - [![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/marxin/cvise.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/marxin/cvise/context:python) -diff --git a/build_and_test.sh b/build_and_test.sh -index 95c1539..f2aef81 100755 ---- a/build_and_test.sh -+++ b/build_and_test.sh -@@ -1,4 +1,4 @@ --#!/usr/bin/bash -+#!/usr/bin/env bash - - BUILD_TYPE=$1 - -diff --git a/cvise.py b/cvise.py -index cba8367..a72d758 100755 ---- a/cvise.py -+++ b/cvise.py -@@ -134,10 +134,14 @@ if __name__ == "__main__": - # in order to speed up parallel execution - core_count = psutil.cpu_count(logical=False) - if not core_count: -- psutil.cpu_count(logical=True) -+ core_count = psutil.cpu_count(logical=True) - # respect affinity - affinity = len(psutil.Process().cpu_affinity()) -- core_count = min(core_count, affinity) -+ assert affinity >= 1 -+ if core_count: -+ core_count = min(core_count, affinity) -+ else: -+ core_count = affinity - except NotImplementedError: - core_count = 1 - -diff --git a/cvise/passes/ifs.py b/cvise/passes/ifs.py -index f68a111..b21557c 100644 ---- a/cvise/passes/ifs.py -+++ b/cvise/passes/ifs.py -@@ -39,10 +39,12 @@ class IfPass(AbstractPass): - - def advance(self, test_case, state): - if state.value == 0: -+ state = state.copy() - state.value = 1 - else: -- state.advance() -- state.value = 0 -+ state = state.advance() -+ if state: -+ state.value = 0 - return state - - def advance_on_success(self, test_case, state): -@@ -63,12 +65,11 @@ class IfPass(AbstractPass): - - if self.line_regex.search(line): - if state.index <= i and i < state.end(): -- tmp_file.write('#if {0}\n'.format(state.value)) -+ if self.__macro_continues(line): -+ in_multiline = True -+ line = '#if {0}\n'.format(state.value) - i += 1 -- if self.__macro_continues(line): -- in_multiline = True -- else: -- tmp_file.write(line) -+ tmp_file.write(line) - - cmd = [self.external_programs["unifdef"], "-B", "-x", "2", "-k", "-o", test_case, tmp_file.name] - stdout, stderr, returncode = process_event_notifier.run_process(cmd) -diff --git a/cvise/tests/test_ifs.py b/cvise/tests/test_ifs.py -index 855ad4f..15d8cdd 100644 ---- a/cvise/tests/test_ifs.py -+++ b/cvise/tests/test_ifs.py -@@ -25,3 +25,51 @@ class LineMarkersTestCase(unittest.TestCase): - - os.unlink(tmp_file.name) - self.assertEqual(variant, "int a = 2;\n") -+ -+ def test_two_steps(self): -+ self.maxDiff = None -+ in_contents = ( -+ "#if FOO\nint foo = 1;\n#else\nint foo = 0;\n#endif\n" + -+ "#if BAR\nint bar = 1;\n#else\nint bar = 0;\n#endif\n" -+ ) -+ expected_outs = [ -+ # ix val chunk contents -+ # FOO=0 BAR=0 -+ (0, 0, 2, 'int foo = 0;\nint bar = 0;\n'), -+ # FOO=1 BAR=1 -+ (0, 1, 2, 'int foo = 1;\nint bar = 1;\n'), -+ -+ # FOO=0 -+ (0, 0, 1, ('int foo = 0;\n' + -+ '#if BAR\nint bar = 1;\n#else\nint bar = 0;\n#endif\n')), -+ # FOO=1 -+ (0, 1, 1, ('int foo = 1;\n' + -+ '#if BAR\nint bar = 1;\n#else\nint bar = 0;\n#endif\n')), -+ # BAR=0 -+ (1, 0, 1, ('#if FOO\nint foo = 1;\n#else\nint foo = 0;\n#endif\n' + -+ 'int bar = 0;\n')), -+ # BAR=1 -+ (1, 1, 1, ('#if FOO\nint foo = 1;\n#else\nint foo = 0;\n#endif\n' + -+ 'int bar = 1;\n')), -+ ] -+ -+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as tf: -+ tf.write(in_contents) -+ -+ outs = [] -+ -+ # perform all iterations. They should iterate through FOO/!FOO x BAR/!BAR. -+ state = self.pass_.new(tf.name) -+ while state: -+ with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file: -+ tmp_file.write(in_contents) -+ -+ (_, state) = self.pass_.transform(tmp_file.name, state, self.process_event_notifier) -+ with open(tmp_file.name) as variant_file: -+ variant = variant_file.read() -+ outs.append(tuple([state.index, state.value, state.chunk, variant])) -+ os.unlink(tmp_file.name) -+ state = self.pass_.advance(tmp_file.name, state) -+ -+ os.unlink(tf.name) -+ self.assertEqual(expected_outs, outs) -diff --git a/cvise/utils/readkey.py b/cvise/utils/readkey.py -index 02e9b09..9e41b46 100644 ---- a/cvise/utils/readkey.py -+++ b/cvise/utils/readkey.py -@@ -10,15 +10,19 @@ else: - class KeyLogger: - def __init__(self): - if sys.platform != "win32": -- fd = sys.stdin.fileno() -- new_term = termios.tcgetattr(fd) -- old_term = termios.tcgetattr(fd) -+ try: -+ fd = sys.stdin.fileno() -+ new_term = termios.tcgetattr(fd) -+ old_term = termios.tcgetattr(fd) - -- self._finalizer = weakref.finalize(self, termios.tcsetattr, fd, termios.TCSAFLUSH, old_term) -+ self._finalizer = weakref.finalize(self, termios.tcsetattr, fd, termios.TCSAFLUSH, old_term) - -- # New terminal setting unbuffered -- new_term[3] = new_term[3] & ~termios.ICANON & ~termios.ECHO -- termios.tcsetattr(fd, termios.TCSAFLUSH, new_term) -+ # New terminal setting unbuffered -+ new_term[3] = new_term[3] & ~termios.ICANON & ~termios.ECHO -+ termios.tcsetattr(fd, termios.TCSAFLUSH, new_term) -+ except termios.error: -+ # this happens when run in pytest -+ pass - - def _getch(self): - if sys.platform == "win32": -diff --git a/tests/sources/blocksort-part.c b/tests/sources/blocksort-part.c -new file mode 100644 -index 0000000..1e67787 ---- /dev/null -+++ b/tests/sources/blocksort-part.c -@@ -0,0 +1,712 @@ -+/* { dg-skip-if "AArch64 does not support these bounds." { aarch64*-*-* } { "--param stack-clash-protection-*" } } */ -+ -+/*-------------------------------------------------------------*/ -+/*--- Block sorting machinery ---*/ -+/*--- blocksort.c ---*/ -+/*-------------------------------------------------------------*/ -+ -+/* ------------------------------------------------------------------ -+ This file is part of bzip2/libbzip2, a program and library for -+ lossless, block-sorting data compression. -+ -+ bzip2/libbzip2 version 1.0.6 of 6 September 2010 -+ Copyright (C) 1996-2010 Julian Seward -+ -+ Please read the WARNING, DISCLAIMER and PATENTS sections in the -+ README file. -+ -+ This program is released under the terms of the license contained -+ in the file LICENSE. -+ ------------------------------------------------------------------ */ -+ -+typedef char Char; -+typedef unsigned char Bool; -+typedef unsigned char UChar; -+#if __SIZEOF_INT__ == 2 -+typedef long Int32; -+typedef unsigned long UInt32; -+#else -+typedef int Int32; -+typedef unsigned int UInt32; -+#endif -+typedef short Int16; -+typedef unsigned short UInt16; -+ -+#define True ((Bool)1) -+#define False ((Bool)0) -+ -+#define BZ_M_IDLE 1 -+#define BZ_M_RUNNING 2 -+#define BZ_M_FLUSHING 3 -+#define BZ_M_FINISHING 4 -+ -+#define BZ_S_OUTPUT 1 -+#define BZ_S_INPUT 2 -+ -+#define BZ_N_RADIX 2 -+#define BZ_N_QSORT 12 -+#define BZ_N_SHELL 18 -+#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2) -+ -+/*---------------------------------------------*/ -+/*--- Fallback O(N log(N)^2) sorting ---*/ -+/*--- algorithm, for repetitive blocks ---*/ -+/*---------------------------------------------*/ -+ -+/*---------------------------------------------*/ -+void fallbackSimpleSort ( UInt32* fmap, -+ UInt32* eclass, -+ Int32 lo, -+ Int32 hi ) -+{ -+ Int32 i, j, tmp; -+ UInt32 ec_tmp; -+ -+ if (lo == hi) return; -+ -+ if (hi - lo > 3) { -+ for ( i = hi-4; i >= lo; i-- ) { -+ tmp = fmap[i]; -+ ec_tmp = eclass[tmp]; -+ for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) -+ fmap[j-4] = fmap[j]; -+ fmap[j-4] = tmp; -+ } -+ } -+ -+ for ( i = hi-1; i >= lo; i-- ) { -+ tmp = fmap[i]; -+ ec_tmp = eclass[tmp]; -+ for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) -+ fmap[j-1] = fmap[j]; -+ fmap[j-1] = tmp; -+ } -+} -+ -+ -+/*---------------------------------------------*/ -+#define fswap(zz1, zz2) \ -+ { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } -+ -+#define fvswap(zzp1, zzp2, zzn) \ -+{ \ -+ Int32 yyp1 = (zzp1); \ -+ Int32 yyp2 = (zzp2); \ -+ Int32 yyn = (zzn); \ -+ while (yyn > 0) { \ -+ fswap(fmap[yyp1], fmap[yyp2]); \ -+ yyp1++; yyp2++; yyn--; \ -+ } \ -+} -+ -+ -+#define fmin(a,b) ((a) < (b)) ? (a) : (b) -+ -+#define fpush(lz,hz) { stackLo[sp] = lz; \ -+ stackHi[sp] = hz; \ -+ sp++; } -+ -+#define fpop(lz,hz) { sp--; \ -+ lz = stackLo[sp]; \ -+ hz = stackHi[sp]; } -+ -+#define FALLBACK_QSORT_SMALL_THRESH 10 -+#define FALLBACK_QSORT_STACK_SIZE 100 -+ -+ -+void fallbackQSort3 ( UInt32* fmap, -+ UInt32* eclass, -+ Int32 loSt, -+ Int32 hiSt ) -+{ -+ Int32 unLo, unHi, ltLo, gtHi, n, m; -+ Int32 sp, lo, hi; -+ UInt32 med, r, r3; -+ Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; -+ Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; -+ -+ r = 0; -+ -+ sp = 0; -+ fpush ( loSt, hiSt ); -+ -+ while (sp > 0) { -+ -+ fpop ( lo, hi ); -+ if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { -+ fallbackSimpleSort ( fmap, eclass, lo, hi ); -+ continue; -+ } -+ -+ /* Random partitioning. Median of 3 sometimes fails to -+ avoid bad cases. Median of 9 seems to help but -+ looks rather expensive. This too seems to work but -+ is cheaper. Guidance for the magic constants -+ 7621 and 32768 is taken from Sedgewick's algorithms -+ book, chapter 35. -+ */ -+ r = ((r * 7621) + 1) % 32768; -+ r3 = r % 3; -+ if (r3 == 0) med = eclass[fmap[lo]]; else -+ if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else -+ med = eclass[fmap[hi]]; -+ -+ unLo = ltLo = lo; -+ unHi = gtHi = hi; -+ -+ while (1) { -+ while (1) { -+ if (unLo > unHi) break; -+ n = (Int32)eclass[fmap[unLo]] - (Int32)med; -+ if (n == 0) { -+ fswap(fmap[unLo], fmap[ltLo]); -+ ltLo++; unLo++; -+ continue; -+ }; -+ if (n > 0) break; -+ unLo++; -+ } -+ while (1) { -+ if (unLo > unHi) break; -+ n = (Int32)eclass[fmap[unHi]] - (Int32)med; -+ if (n == 0) { -+ fswap(fmap[unHi], fmap[gtHi]); -+ gtHi--; unHi--; -+ continue; -+ }; -+ if (n < 0) break; -+ unHi--; -+ } -+ if (unLo > unHi) break; -+ fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; -+ } -+ -+ if (gtHi < ltLo) continue; -+ -+ n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); -+ m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); -+ -+ n = lo + unLo - ltLo - 1; -+ m = hi - (gtHi - unHi) + 1; -+ -+ if (n - lo > hi - m) { -+ fpush ( lo, n ); -+ fpush ( m, hi ); -+ } else { -+ fpush ( m, hi ); -+ fpush ( lo, n ); -+ } -+ } -+} -+ -+#undef fmin -+#undef fpush -+#undef fpop -+#undef fswap -+#undef fvswap -+#undef FALLBACK_QSORT_SMALL_THRESH -+#undef FALLBACK_QSORT_STACK_SIZE -+ -+ -+/*---------------------------------------------*/ -+/* Pre: -+ nblock > 0 -+ eclass exists for [0 .. nblock-1] -+ ((UChar*)eclass) [0 .. nblock-1] holds block -+ ptr exists for [0 .. nblock-1] -+ -+ Post: -+ ((UChar*)eclass) [0 .. nblock-1] holds block -+ All other areas of eclass destroyed -+ fmap [0 .. nblock-1] holds sorted order -+ bhtab [ 0 .. 2+(nblock/32) ] destroyed -+*/ -+ -+#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) -+#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) -+#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) -+#define WORD_BH(zz) bhtab[(zz) >> 5] -+#define UNALIGNED_BH(zz) ((zz) & 0x01f) -+ -+void fallbackSort ( UInt32* fmap, -+ UInt32* eclass, -+ UInt32* bhtab, -+ Int32 nblock, -+ Int32 verb ) -+{ -+ Int32 ftab[257]; -+ Int32 ftabCopy[256]; -+ Int32 H, i, j, k, l, r, cc, cc1; -+ Int32 nNotDone; -+ Int32 nBhtab; -+ UChar* eclass8 = (UChar*)eclass; -+ -+ /*-- -+ Initial 1-char radix sort to generate -+ initial fmap and initial BH bits. -+ --*/ -+ for (i = 0; i < 257; i++) ftab[i] = 0; -+ for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; -+ for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; -+ for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; -+ -+ for (i = 0; i < nblock; i++) { -+ j = eclass8[i]; -+ k = ftab[j] - 1; -+ ftab[j] = k; -+ fmap[k] = i; -+ } -+ -+ nBhtab = 2 + (nblock / 32); -+ for (i = 0; i < nBhtab; i++) bhtab[i] = 0; -+ for (i = 0; i < 256; i++) SET_BH(ftab[i]); -+ -+ /*-- -+ Inductively refine the buckets. Kind-of an -+ "exponential radix sort" (!), inspired by the -+ Manber-Myers suffix array construction algorithm. -+ --*/ -+ -+ /*-- set sentinel bits for block-end detection --*/ -+ for (i = 0; i < 32; i++) { -+ SET_BH(nblock + 2*i); -+ CLEAR_BH(nblock + 2*i + 1); -+ } -+ -+ /*-- the log(N) loop --*/ -+ H = 1; -+ while (1) { -+ -+ -+ j = 0; -+ for (i = 0; i < nblock; i++) { -+ if (ISSET_BH(i)) j = i; -+ k = fmap[i] - H; if (k < 0) k += nblock; -+ eclass[k] = j; -+ } -+ -+ nNotDone = 0; -+ r = -1; -+ while (1) { -+ -+ /*-- find the next non-singleton bucket --*/ -+ k = r + 1; -+ while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; -+ if (ISSET_BH(k)) { -+ while (WORD_BH(k) == 0xffffffff) k += 32; -+ while (ISSET_BH(k)) k++; -+ } -+ l = k - 1; -+ if (l >= nblock) break; -+ while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; -+ if (!ISSET_BH(k)) { -+ while (WORD_BH(k) == 0x00000000) k += 32; -+ while (!ISSET_BH(k)) k++; -+ } -+ r = k - 1; -+ if (r >= nblock) break; -+ -+ /*-- now [l, r] bracket current bucket --*/ -+ if (r > l) { -+ nNotDone += (r - l + 1); -+ fallbackQSort3 ( fmap, eclass, l, r ); -+ -+ /*-- scan bucket and generate header bits-- */ -+ cc = -1; -+ for (i = l; i <= r; i++) { -+ cc1 = eclass[fmap[i]]; -+ if (cc != cc1) { SET_BH(i); cc = cc1; }; -+ } -+ } -+ } -+ -+ H *= 2; -+ if (H > nblock || nNotDone == 0) break; -+ } -+ -+ /*-- -+ Reconstruct the original block in -+ eclass8 [0 .. nblock-1], since the -+ previous phase destroyed it. -+ --*/ -+ j = 0; -+ for (i = 0; i < nblock; i++) { -+ while (ftabCopy[j] == 0) j++; -+ ftabCopy[j]--; -+ eclass8[fmap[i]] = (UChar)j; -+ } -+} -+ -+#undef SET_BH -+#undef CLEAR_BH -+#undef ISSET_BH -+#undef WORD_BH -+#undef UNALIGNED_BH -+ -+ -+/*---------------------------------------------*/ -+/*--- The main, O(N^2 log(N)) sorting ---*/ -+/*--- algorithm. Faster for "normal" ---*/ -+/*--- non-repetitive blocks. ---*/ -+/*---------------------------------------------*/ -+ -+/*---------------------------------------------*/ -+Bool mainGtU ( UInt32 i1, -+ UInt32 i2, -+ UChar* block, -+ UInt16* quadrant, -+ UInt32 nblock, -+ Int32* budget ) -+{ -+ Int32 k; -+ UChar c1, c2; -+ UInt16 s1, s2; -+ -+ /* 1 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 2 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 3 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 4 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 5 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 6 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 7 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 8 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 9 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 10 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 11 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ /* 12 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ i1++; i2++; -+ -+ k = nblock + 8; -+ -+ do { -+ /* 1 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ s1 = quadrant[i1]; s2 = quadrant[i2]; -+ if (s1 != s2) return (s1 > s2); -+ i1++; i2++; -+ /* 2 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ s1 = quadrant[i1]; s2 = quadrant[i2]; -+ if (s1 != s2) return (s1 > s2); -+ i1++; i2++; -+ /* 3 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ s1 = quadrant[i1]; s2 = quadrant[i2]; -+ if (s1 != s2) return (s1 > s2); -+ i1++; i2++; -+ /* 4 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ s1 = quadrant[i1]; s2 = quadrant[i2]; -+ if (s1 != s2) return (s1 > s2); -+ i1++; i2++; -+ /* 5 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ s1 = quadrant[i1]; s2 = quadrant[i2]; -+ if (s1 != s2) return (s1 > s2); -+ i1++; i2++; -+ /* 6 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ s1 = quadrant[i1]; s2 = quadrant[i2]; -+ if (s1 != s2) return (s1 > s2); -+ i1++; i2++; -+ /* 7 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ s1 = quadrant[i1]; s2 = quadrant[i2]; -+ if (s1 != s2) return (s1 > s2); -+ i1++; i2++; -+ /* 8 */ -+ c1 = block[i1]; c2 = block[i2]; -+ if (c1 != c2) return (c1 > c2); -+ s1 = quadrant[i1]; s2 = quadrant[i2]; -+ if (s1 != s2) return (s1 > s2); -+ i1++; i2++; -+ -+ if (i1 >= nblock) i1 -= nblock; -+ if (i2 >= nblock) i2 -= nblock; -+ -+ k -= 8; -+ (*budget)--; -+ } -+ while (k >= 0); -+ -+ return False; -+} -+ -+ -+/*---------------------------------------------*/ -+/*-- -+ Knuth's increments seem to work better -+ than Incerpi-Sedgewick here. Possibly -+ because the number of elems to sort is -+ usually small, typically <= 20. -+--*/ -+Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, -+ 9841, 29524, 88573, 265720, -+ 797161, 2391484 }; -+ -+void mainSimpleSort ( UInt32* ptr, -+ UChar* block, -+ UInt16* quadrant, -+ Int32 nblock, -+ Int32 lo, -+ Int32 hi, -+ Int32 d, -+ Int32* budget ) -+{ -+ Int32 i, j, h, bigN, hp; -+ UInt32 v; -+ -+ bigN = hi - lo + 1; -+ if (bigN < 2) return; -+ -+ hp = 0; -+ while (incs[hp] < bigN) hp++; -+ hp--; -+ -+ for (; hp >= 0; hp--) { -+ h = incs[hp]; -+ -+ i = lo + h; -+ while (True) { -+ -+ /*-- copy 1 --*/ -+ if (i > hi) break; -+ v = ptr[i]; -+ j = i; -+ while ( mainGtU ( -+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget -+ ) ) { -+ ptr[j] = ptr[j-h]; -+ j = j - h; -+ if (j <= (lo + h - 1)) break; -+ } -+ ptr[j] = v; -+ i++; -+ -+ /*-- copy 2 --*/ -+ if (i > hi) break; -+ v = ptr[i]; -+ j = i; -+ while ( mainGtU ( -+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget -+ ) ) { -+ ptr[j] = ptr[j-h]; -+ j = j - h; -+ if (j <= (lo + h - 1)) break; -+ } -+ ptr[j] = v; -+ i++; -+ -+ /*-- copy 3 --*/ -+ if (i > hi) break; -+ v = ptr[i]; -+ j = i; -+ while ( mainGtU ( -+ ptr[j-h]+d, v+d, block, quadrant, nblock, budget -+ ) ) { -+ ptr[j] = ptr[j-h]; -+ j = j - h; -+ if (j <= (lo + h - 1)) break; -+ } -+ ptr[j] = v; -+ i++; -+ -+ if (*budget < 0) return; -+ } -+ } -+} -+ -+ -+/*---------------------------------------------*/ -+/*-- -+ The following is an implementation of -+ an elegant 3-way quicksort for strings, -+ described in a paper "Fast Algorithms for -+ Sorting and Searching Strings", by Robert -+ Sedgewick and Jon L. Bentley. -+--*/ -+ -+#define mswap(zz1, zz2) \ -+ { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } -+ -+#define mvswap(zzp1, zzp2, zzn) \ -+{ \ -+ Int32 yyp1 = (zzp1); \ -+ Int32 yyp2 = (zzp2); \ -+ Int32 yyn = (zzn); \ -+ while (yyn > 0) { \ -+ mswap(ptr[yyp1], ptr[yyp2]); \ -+ yyp1++; yyp2++; yyn--; \ -+ } \ -+} -+ -+UChar mmed3 ( UChar a, UChar b, UChar c ) -+{ -+ UChar t; -+ if (a > b) { t = a; a = b; b = t; }; -+ if (b > c) { -+ b = c; -+ if (a > b) b = a; -+ } -+ return b; -+} -+ -+#define mmin(a,b) ((a) < (b)) ? (a) : (b) -+ -+#define mpush(lz,hz,dz) { stackLo[sp] = lz; \ -+ stackHi[sp] = hz; \ -+ stackD [sp] = dz; \ -+ sp++; } -+ -+#define mpop(lz,hz,dz) { sp--; \ -+ lz = stackLo[sp]; \ -+ hz = stackHi[sp]; \ -+ dz = stackD [sp]; } -+ -+ -+#define mnextsize(az) (nextHi[az]-nextLo[az]) -+ -+#define mnextswap(az,bz) \ -+ { Int32 tz; \ -+ tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ -+ tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ -+ tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } -+ -+ -+#define MAIN_QSORT_SMALL_THRESH 20 -+#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) -+#define MAIN_QSORT_STACK_SIZE 100 -+ -+void mainQSort3 ( UInt32* ptr, -+ UChar* block, -+ UInt16* quadrant, -+ Int32 nblock, -+ Int32 loSt, -+ Int32 hiSt, -+ Int32 dSt, -+ Int32* budget ) -+{ -+ Int32 unLo, unHi, ltLo, gtHi, n, m, med; -+ Int32 sp, lo, hi, d; -+ -+ Int32 stackLo[MAIN_QSORT_STACK_SIZE]; -+ Int32 stackHi[MAIN_QSORT_STACK_SIZE]; -+ Int32 stackD [MAIN_QSORT_STACK_SIZE]; -+ -+ Int32 nextLo[3]; -+ Int32 nextHi[3]; -+ Int32 nextD [3]; -+ -+ sp = 0; -+ mpush ( loSt, hiSt, dSt ); -+ -+ while (sp > 0) { -+ -+ mpop ( lo, hi, d ); -+ if (hi - lo < MAIN_QSORT_SMALL_THRESH || -+ d > MAIN_QSORT_DEPTH_THRESH) { -+ mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); -+ if (*budget < 0) return; -+ continue; -+ } -+ -+ med = (Int32) -+ mmed3 ( block[ptr[ lo ]+d], -+ block[ptr[ hi ]+d], -+ block[ptr[ (lo+hi)>>1 ]+d] ); -+ -+ unLo = ltLo = lo; -+ unHi = gtHi = hi; -+ -+ while (True) { -+ while (True) { -+ if (unLo > unHi) break; -+ n = ((Int32)block[ptr[unLo]+d]) - med; -+ if (n == 0) { -+ mswap(ptr[unLo], ptr[ltLo]); -+ ltLo++; unLo++; continue; -+ }; -+ if (n > 0) break; -+ unLo++; -+ } -+ while (True) { -+ if (unLo > unHi) break; -+ n = ((Int32)block[ptr[unHi]+d]) - med; -+ if (n == 0) { -+ mswap(ptr[unHi], ptr[gtHi]); -+ gtHi--; unHi--; continue; -+ }; -+ if (n < 0) break; -+ unHi--; -+ } -+ if (unLo > unHi) break; -+ mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; -+ } -+ -+ if (gtHi < ltLo) { -+ mpush(lo, hi, d+1 ); -+ continue; -+ } -+ -+ n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); -+ m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); -+ -+ n = lo + unLo - ltLo - 1; -+ m = hi - (gtHi - unHi) + 1; -+ -+ nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; -+ nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; -+ nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; -+ -+ if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); -+ if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); -+ if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); -+ -+ -+ mpush (nextLo[0], nextHi[0], nextD[0]); -+ mpush (nextLo[1], nextHi[1], nextD[1]); -+ mpush (nextLo[2], nextHi[2], nextD[2]); -+ } -+} -diff --git a/tests/test_cvise.py b/tests/test_cvise.py -new file mode 100644 -index 0000000..2bca59a ---- /dev/null -+++ b/tests/test_cvise.py -@@ -0,0 +1,18 @@ -+import os -+import unittest -+import subprocess -+import shutil -+ -+class TestCvise(unittest.TestCase): -+ -+ @classmethod -+ def check_cvise(cls, testcase, arguments, expected): -+ current = os.path.dirname(__file__) -+ binary = os.path.join(current, '../cvise.py') -+ shutil.copy(os.path.join(current, 'sources', testcase), '.') -+ cmd = '%s %s %s' % (binary, testcase, arguments) -+ output = subprocess.check_output(cmd, shell=True, encoding='utf8') -+ assert open(testcase).read() == expected -+ -+ def test_simple_reduction(self): -+ self.check_cvise('blocksort-part.c', '-c "gcc -c blocksort-part.c && grep nextHi blocksort-part.c"', '#define nextHi') diff -Nru cvise-1.6.0/debian/patches/no-flake8.diff cvise-2.3.0/debian/patches/no-flake8.diff --- cvise-1.6.0/debian/patches/no-flake8.diff 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/debian/patches/no-flake8.diff 2021-03-24 13:15:23.000000000 +0000 @@ -0,0 +1,9 @@ +--- a/setup.cfg ++++ b/setup.cfg +@@ -2,6 +2,3 @@ + ignore = E501,W503,W504 + import-order-style = google + exclude = objdir +- +-[tool:pytest] +-addopts = -vv --flake8 diff -Nru cvise-1.6.0/debian/patches/series cvise-2.3.0/debian/patches/series --- cvise-1.6.0/debian/patches/series 2020-09-17 11:42:12.000000000 +0000 +++ cvise-2.3.0/debian/patches/series 2021-03-24 13:14:30.000000000 +0000 @@ -1 +1,2 @@ -git-updates.diff +# git-updates.diff +no-flake8.diff diff -Nru cvise-1.6.0/debian/rules cvise-2.3.0/debian/rules --- cvise-1.6.0/debian/rules 2020-07-22 16:47:01.000000000 +0000 +++ cvise-2.3.0/debian/rules 2021-03-24 11:18:22.000000000 +0000 @@ -3,7 +3,7 @@ DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) -CLANG_V=10 +CLANG_V=9 V=$(shell dpkg-parsechangelog -S Version | sed 's/-.*$$//') %: diff -Nru cvise-1.6.0/Docker/Dockerfile-fedora32-llvm9 cvise-2.3.0/Docker/Dockerfile-fedora32-llvm9 --- cvise-1.6.0/Docker/Dockerfile-fedora32-llvm9 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/Docker/Dockerfile-fedora32-llvm9 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -FROM fedora:31 - -RUN dnf install -y python3-pip python3-pytest llvm-devel clang-devel cmake make flex unifdef -RUN pip3 install Pebble - -WORKDIR /usr/src/cvise -VOLUME /usr/src/cvise diff -Nru cvise-1.6.0/Docker/Dockerfile-fedoradev-llvm10 cvise-2.3.0/Docker/Dockerfile-fedoradev-llvm10 --- cvise-1.6.0/Docker/Dockerfile-fedoradev-llvm10 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/Docker/Dockerfile-fedoradev-llvm10 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -FROM fedora:rawhide - -RUN dnf install -y python3-pip python3-pytest llvm-devel clang-devel cmake make flex unifdef -RUN pip3 install Pebble - -WORKDIR /usr/src/cvise -VOLUME /usr/src/cvise diff -Nru cvise-1.6.0/Docker/Dockerfile-opensusetw-llvm10 cvise-2.3.0/Docker/Dockerfile-opensusetw-llvm10 --- cvise-1.6.0/Docker/Dockerfile-opensusetw-llvm10 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/Docker/Dockerfile-opensusetw-llvm10 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -FROM opensuse/tumbleweed - -RUN zypper -n install \ - binutils clang10-devel cmake flex gcc-c++ llvm10-devel python3-Pebble python3-pytest4 unifdef python3-pip sqlite-devel git python3 -RUN pip install codecov pytest-cov -ENV LSAN_OPTIONS="detect_leaks=0" - -WORKDIR /usr/src/cvise -VOLUME /usr/src/cvise diff -Nru cvise-1.6.0/Docker/Dockerfile-opensusetw-llvm9 cvise-2.3.0/Docker/Dockerfile-opensusetw-llvm9 --- cvise-1.6.0/Docker/Dockerfile-opensusetw-llvm9 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/Docker/Dockerfile-opensusetw-llvm9 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -FROM opensuse/tumbleweed - -RUN zypper -n install \ - binutils clang9-devel cmake flex gcc-c++ llvm9-devel python3-Pebble python3-pytest unifdef -ENV LSAN_OPTIONS="detect_leaks=0" - -WORKDIR /usr/src/cvise -VOLUME /usr/src/cvise diff -Nru cvise-1.6.0/.github/workflows/build.yml cvise-2.3.0/.github/workflows/build.yml --- cvise-1.6.0/.github/workflows/build.yml 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/.github/workflows/build.yml 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,66 @@ +name: Build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build_and_test: + runs-on: ubuntu-latest + + strategy: + matrix: + llvm: [9, 10, 11] + build-type: [DEBUG] + docker: [opensuse/tumbleweed] + include: + - llvm: 11 + build-type: ASAN + docker: opensuse/tumbleweed + - llvm: 11 + build-type: UBSAN + docker: opensuse/tumbleweed + - llvm: 11 + build-type: COVERAGE + docker: opensuse/tumbleweed + - llvm: 9 + build-type: DEBUG + docker: opensuse/leap + fail-fast: false + + container: ${{ matrix.docker }} + + steps: + - run: zypper -n install + binutils clang${{ matrix.llvm }}-devel cmake flex gcc-c++ llvm${{ matrix.llvm }}-devel python3-Pebble python3-pytest unifdef python3-psutil curl git + python3-pytest-flake8 + python3-flake8 + python3-flake8-builtins + python3-flake8-bugbear + python3-flake8-import-order + python3-flake8-quotes + - run: zypper -n install python3-pip python3-flake8-comprehensions python3 sqlite-devel + if: matrix.docker == 'opensuse/tumbleweed' + - run: pip install codecov pytest-cov + if: matrix.docker == 'opensuse/tumbleweed' + - uses: actions/checkout@v2 + - run: nproc + - name: build + run: | + mkdir objdir + cd objdir + cmake .. -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} + make -j`nproc` VERBOSE=1 + - name: test + run: | + cd objdir + pytest + if: matrix.build-type != 'COVERAGE' + - name: test with coverage + run: | + cd objdir + pytest --cov=./ + codecov + if: matrix.build-type == 'COVERAGE' diff -Nru cvise-1.6.0/INSTALL.md cvise-2.3.0/INSTALL.md --- cvise-1.6.0/INSTALL.md 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/INSTALL.md 2021-03-09 08:18:13.000000000 +0000 @@ -3,7 +3,7 @@ ## Using a Package Manager Before compiling C-Vise yourself, you might want to see if your OS -comes with a precompiled package for C-Vise. +comes with a pre-compiled package for C-Vise. ### openSUSE Tumbleweed diff -Nru cvise-1.6.0/README.md cvise-2.3.0/README.md --- cvise-1.6.0/README.md 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/README.md 2021-03-09 08:18:13.000000000 +0000 @@ -1,6 +1,7 @@ # C-Vise -[![Travis Build Status](https://travis-ci.com/marxin/cvise.svg?branch=master)](https://travis-ci.com/marxin/cvise) +[![OBS master](https://build.opensuse.org/assets/favicon-ac48595b97f38c2425d7ea77739a63d771fcda9f73cc8c474b66461c0836fc2a.ico)](https://build.opensuse.org/package/show/home:marxin:cvise-github/cvise) +![GitHub Actions](https://github.com/marxin/cvise/workflows/Build/badge.svg) [![Total alerts](https://img.shields.io/lgtm/alerts/g/marxin/cvise.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/marxin/cvise/alerts/) [![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/marxin/cvise.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/marxin/cvise/context:python) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/marxin/cvise.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/marxin/cvise/context:cpp) diff -Nru cvise-1.6.0/setup.cfg cvise-2.3.0/setup.cfg --- cvise-1.6.0/setup.cfg 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/setup.cfg 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,7 @@ +[flake8] +ignore = E501,W503,W504 +import-order-style = google +exclude = objdir + +[tool:pytest] +addopts = -vv --flake8 diff -Nru cvise-1.6.0/tests/sources/blocksort-part.c cvise-2.3.0/tests/sources/blocksort-part.c --- cvise-1.6.0/tests/sources/blocksort-part.c 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/tests/sources/blocksort-part.c 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,712 @@ +/* { dg-skip-if "AArch64 does not support these bounds." { aarch64*-*-* } { "--param stack-clash-protection-*" } } */ + +/*-------------------------------------------------------------*/ +/*--- Block sorting machinery ---*/ +/*--- blocksort.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +#if __SIZEOF_INT__ == 2 +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif +typedef short Int16; +typedef unsigned short UInt16; + +#define True ((Bool)1) +#define False ((Bool)0) + +#define BZ_M_IDLE 1 +#define BZ_M_RUNNING 2 +#define BZ_M_FLUSHING 3 +#define BZ_M_FINISHING 4 + +#define BZ_S_OUTPUT 1 +#define BZ_S_INPUT 2 + +#define BZ_N_RADIX 2 +#define BZ_N_QSORT 12 +#define BZ_N_SHELL 18 +#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2) + +/*---------------------------------------------*/ +/*--- Fallback O(N log(N)^2) sorting ---*/ +/*--- algorithm, for repetitive blocks ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +void fallbackSimpleSort ( UInt32* fmap, + UInt32* eclass, + Int32 lo, + Int32 hi ) +{ + Int32 i, j, tmp; + UInt32 ec_tmp; + + if (lo == hi) return; + + if (hi - lo > 3) { + for ( i = hi-4; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) + fmap[j-4] = fmap[j]; + fmap[j-4] = tmp; + } + } + + for ( i = hi-1; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) + fmap[j-1] = fmap[j]; + fmap[j-1] = tmp; + } +} + + +/*---------------------------------------------*/ +#define fswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define fvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + fswap(fmap[yyp1], fmap[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + + +#define fmin(a,b) ((a) < (b)) ? (a) : (b) + +#define fpush(lz,hz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + sp++; } + +#define fpop(lz,hz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; } + +#define FALLBACK_QSORT_SMALL_THRESH 10 +#define FALLBACK_QSORT_STACK_SIZE 100 + + +void fallbackQSort3 ( UInt32* fmap, + UInt32* eclass, + Int32 loSt, + Int32 hiSt ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m; + Int32 sp, lo, hi; + UInt32 med, r, r3; + Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; + Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; + + r = 0; + + sp = 0; + fpush ( loSt, hiSt ); + + while (sp > 0) { + + fpop ( lo, hi ); + if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { + fallbackSimpleSort ( fmap, eclass, lo, hi ); + continue; + } + + /* Random partitioning. Median of 3 sometimes fails to + avoid bad cases. Median of 9 seems to help but + looks rather expensive. This too seems to work but + is cheaper. Guidance for the magic constants + 7621 and 32768 is taken from Sedgewick's algorithms + book, chapter 35. + */ + r = ((r * 7621) + 1) % 32768; + r3 = r % 3; + if (r3 == 0) med = eclass[fmap[lo]]; else + if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else + med = eclass[fmap[hi]]; + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (1) { + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unLo]] - (Int32)med; + if (n == 0) { + fswap(fmap[unLo], fmap[ltLo]); + ltLo++; unLo++; + continue; + }; + if (n > 0) break; + unLo++; + } + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unHi]] - (Int32)med; + if (n == 0) { + fswap(fmap[unHi], fmap[gtHi]); + gtHi--; unHi--; + continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; + } + + if (gtHi < ltLo) continue; + + n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); + m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + if (n - lo > hi - m) { + fpush ( lo, n ); + fpush ( m, hi ); + } else { + fpush ( m, hi ); + fpush ( lo, n ); + } + } +} + +#undef fmin +#undef fpush +#undef fpop +#undef fswap +#undef fvswap +#undef FALLBACK_QSORT_SMALL_THRESH +#undef FALLBACK_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + eclass exists for [0 .. nblock-1] + ((UChar*)eclass) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)eclass) [0 .. nblock-1] holds block + All other areas of eclass destroyed + fmap [0 .. nblock-1] holds sorted order + bhtab [ 0 .. 2+(nblock/32) ] destroyed +*/ + +#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) +#define WORD_BH(zz) bhtab[(zz) >> 5] +#define UNALIGNED_BH(zz) ((zz) & 0x01f) + +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + UInt32* bhtab, + Int32 nblock, + Int32 verb ) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + /*-- + Initial 1-char radix sort to generate + initial fmap and initial BH bits. + --*/ + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i]; + k = ftab[j] - 1; + ftab[j] = k; + fmap[k] = i; + } + + nBhtab = 2 + (nblock / 32); + for (i = 0; i < nBhtab; i++) bhtab[i] = 0; + for (i = 0; i < 256; i++) SET_BH(ftab[i]); + + /*-- + Inductively refine the buckets. Kind-of an + "exponential radix sort" (!), inspired by the + Manber-Myers suffix array construction algorithm. + --*/ + + /*-- set sentinel bits for block-end detection --*/ + for (i = 0; i < 32; i++) { + SET_BH(nblock + 2*i); + CLEAR_BH(nblock + 2*i + 1); + } + + /*-- the log(N) loop --*/ + H = 1; + while (1) { + + + j = 0; + for (i = 0; i < nblock; i++) { + if (ISSET_BH(i)) j = i; + k = fmap[i] - H; if (k < 0) k += nblock; + eclass[k] = j; + } + + nNotDone = 0; + r = -1; + while (1) { + + /*-- find the next non-singleton bucket --*/ + k = r + 1; + while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (ISSET_BH(k)) { + while (WORD_BH(k) == 0xffffffff) k += 32; + while (ISSET_BH(k)) k++; + } + l = k - 1; + if (l >= nblock) break; + while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (!ISSET_BH(k)) { + while (WORD_BH(k) == 0x00000000) k += 32; + while (!ISSET_BH(k)) k++; + } + r = k - 1; + if (r >= nblock) break; + + /*-- now [l, r] bracket current bucket --*/ + if (r > l) { + nNotDone += (r - l + 1); + fallbackQSort3 ( fmap, eclass, l, r ); + + /*-- scan bucket and generate header bits-- */ + cc = -1; + for (i = l; i <= r; i++) { + cc1 = eclass[fmap[i]]; + if (cc != cc1) { SET_BH(i); cc = cc1; }; + } + } + } + + H *= 2; + if (H > nblock || nNotDone == 0) break; + } + + /*-- + Reconstruct the original block in + eclass8 [0 .. nblock-1], since the + previous phase destroyed it. + --*/ + j = 0; + for (i = 0; i < nblock; i++) { + while (ftabCopy[j] == 0) j++; + ftabCopy[j]--; + eclass8[fmap[i]] = (UChar)j; + } +} + +#undef SET_BH +#undef CLEAR_BH +#undef ISSET_BH +#undef WORD_BH +#undef UNALIGNED_BH + + +/*---------------------------------------------*/ +/*--- The main, O(N^2 log(N)) sorting ---*/ +/*--- algorithm. Faster for "normal" ---*/ +/*--- non-repetitive blocks. ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +Bool mainGtU ( UInt32 i1, + UInt32 i2, + UChar* block, + UInt16* quadrant, + UInt32 nblock, + Int32* budget ) +{ + Int32 k; + UChar c1, c2; + UInt16 s1, s2; + + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 9 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 10 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 11 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 12 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + + k = nblock + 8; + + do { + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + + if (i1 >= nblock) i1 -= nblock; + if (i2 >= nblock) i2 -= nblock; + + k -= 8; + (*budget)--; + } + while (k >= 0); + + return False; +} + + +/*---------------------------------------------*/ +/*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. +--*/ +Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 }; + +void mainSimpleSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 lo, + Int32 hi, + Int32 d, + Int32* budget ) +{ + Int32 i, j, h, bigN, hp; + UInt32 v; + + bigN = hi - lo + 1; + if (bigN < 2) return; + + hp = 0; + while (incs[hp] < bigN) hp++; + hp--; + + for (; hp >= 0; hp--) { + h = incs[hp]; + + i = lo + h; + while (True) { + + /*-- copy 1 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + if (*budget < 0) return; + } + } +} + + +/*---------------------------------------------*/ +/*-- + The following is an implementation of + an elegant 3-way quicksort for strings, + described in a paper "Fast Algorithms for + Sorting and Searching Strings", by Robert + Sedgewick and Jon L. Bentley. +--*/ + +#define mswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define mvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + mswap(ptr[yyp1], ptr[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + +UChar mmed3 ( UChar a, UChar b, UChar c ) +{ + UChar t; + if (a > b) { t = a; a = b; b = t; }; + if (b > c) { + b = c; + if (a > b) b = a; + } + return b; +} + +#define mmin(a,b) ((a) < (b)) ? (a) : (b) + +#define mpush(lz,hz,dz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + stackD [sp] = dz; \ + sp++; } + +#define mpop(lz,hz,dz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; \ + dz = stackD [sp]; } + + +#define mnextsize(az) (nextHi[az]-nextLo[az]) + +#define mnextswap(az,bz) \ + { Int32 tz; \ + tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ + tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ + tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } + + +#define MAIN_QSORT_SMALL_THRESH 20 +#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) +#define MAIN_QSORT_STACK_SIZE 100 + +void mainQSort3 ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 loSt, + Int32 hiSt, + Int32 dSt, + Int32* budget ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m, med; + Int32 sp, lo, hi, d; + + Int32 stackLo[MAIN_QSORT_STACK_SIZE]; + Int32 stackHi[MAIN_QSORT_STACK_SIZE]; + Int32 stackD [MAIN_QSORT_STACK_SIZE]; + + Int32 nextLo[3]; + Int32 nextHi[3]; + Int32 nextD [3]; + + sp = 0; + mpush ( loSt, hiSt, dSt ); + + while (sp > 0) { + + mpop ( lo, hi, d ); + if (hi - lo < MAIN_QSORT_SMALL_THRESH || + d > MAIN_QSORT_DEPTH_THRESH) { + mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); + if (*budget < 0) return; + continue; + } + + med = (Int32) + mmed3 ( block[ptr[ lo ]+d], + block[ptr[ hi ]+d], + block[ptr[ (lo+hi)>>1 ]+d] ); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (True) { + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unLo]+d]) - med; + if (n == 0) { + mswap(ptr[unLo], ptr[ltLo]); + ltLo++; unLo++; continue; + }; + if (n > 0) break; + unLo++; + } + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unHi]+d]) - med; + if (n == 0) { + mswap(ptr[unHi], ptr[gtHi]); + gtHi--; unHi--; continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; + } + + if (gtHi < ltLo) { + mpush(lo, hi, d+1 ); + continue; + } + + n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); + m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; + nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; + nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; + + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + + + mpush (nextLo[0], nextHi[0], nextD[0]); + mpush (nextLo[1], nextHi[1], nextD[1]); + mpush (nextLo[2], nextHi[2], nextD[2]); + } +} diff -Nru cvise-1.6.0/tests/test_cvise.py cvise-2.3.0/tests/test_cvise.py --- cvise-1.6.0/tests/test_cvise.py 1970-01-01 00:00:00.000000000 +0000 +++ cvise-2.3.0/tests/test_cvise.py 2021-03-09 08:18:13.000000000 +0000 @@ -0,0 +1,22 @@ +import os +import shutil +import stat +import subprocess +import unittest + + +class TestCvise(unittest.TestCase): + + @classmethod + def check_cvise(cls, testcase, arguments, expected): + current = os.path.dirname(__file__) + binary = os.path.join(current, '../cvise.py') + shutil.copy(os.path.join(current, 'sources', testcase), '.') + os.chmod(testcase, 0o644) + cmd = '%s %s %s' % (binary, testcase, arguments) + subprocess.check_output(cmd, shell=True, encoding='utf8') + assert open(testcase).read() == expected + assert stat.filemode(os.stat(testcase).st_mode) == '-rw-r--r--' + + def test_simple_reduction(self): + self.check_cvise('blocksort-part.c', '-c "gcc -c blocksort-part.c && grep nextHi blocksort-part.c"', '#define nextHi') diff -Nru cvise-1.6.0/.travis.yml cvise-2.3.0/.travis.yml --- cvise-1.6.0/.travis.yml 2020-07-26 13:30:16.000000000 +0000 +++ cvise-2.3.0/.travis.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -## -## Copyright (c) 2015, 2016, 2017, 2018, 2019 The University of Utah -## Copyright (c) 2015 Tamir Duberstein -## All rights reserved. -## -## This file is distributed under the University of Illinois Open Source -## License. See the file COPYING for details. -## - -############################################################################### - -sudo: required -dist: bionic -language: cpp - -stages: - - build - -# podman is currently not in Ubuntu -addons: - apt: - update: true - sources: - - sourceline: "ppa:projectatomic/ppa" - packages: - - podman slirp4netns - -matrix: - - include: - - name: DEBUG build (LLVM 9) - stage: build - env: - - BUILD_TYPE=DEBUG - - DIST=opensusetw-llvm9 - - - name: DEBUG build (LLVM 10) - stage: build - env: - - BUILD_TYPE=DEBUG - - DIST=opensusetw-llvm10 - - - name: COVERAGE build (LLVM 10) - stage: build - env: - - BUILD_TYPE=COVERAGE - - DIST=opensusetw-llvm10 - - - name: UBSAN build (LLVM 10) - stage: build - env: - - BUILD_TYPE=UBSAN - - DIST=opensusetw-llvm10 - - - name: ASAN build (LLVM 10) - stage: build - env: - - BUILD_TYPE=ASAN - - DIST=opensusetw-llvm10 - - - name: Fedora 32 DEBUG build (LLVM 9) - stage: build - env: - - BUILD_TYPE=DEBUG - - DIST=fedora32-llvm9 - - - name: Fedora dev DEBUG build (LLVM 10) - stage: build - env: - - BUILD_TYPE=DEBUG - - DIST=fedoradev-llvm10 - -before_install: - # podman needs a basic register set up (packaging bug in the ppa) - - sudo mkdir -p /etc/containers - - echo -e "[registries.search]\nregistries = ['docker.io']" | sudo tee /etc/containers/registries.conf - # we need to register travis to allow subuid/gid for the rootless execution - - echo "travis:110000:65535" | sudo tee /etc/subuid - - echo "travis:110000:65535" | sudo tee /etc/subgid - -script: - - podman build -t $DIST -f Docker/Dockerfile-$DIST . - - podman run -v $(pwd):/usr/src/cvise $DIST ./build_and_test.sh $BUILD_TYPE - -############################################################################### - -## End of file.