Skip to content

Commit 9a8ddb6

Browse files
committed
add the crangler tool
This is a command-line utility that makes changes to a preprocessed C file that are prescribed in a JSON configuration file. The initial set of transformations is as follows. * add a contract (pre/post/assigns) to a named C function * add a loop invariant to a loop identified by the name of the function its in and a loop number * remove the 'static' storage classifier from a function The resulting source file is written into the directory of the original file using the file extension ".i".
1 parent 268a0d0 commit 9a8ddb6

26 files changed

+1763
-0
lines changed

regression/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# listed with decreasing runtimes (i.e. longest running at the top)
44
DIRS = cbmc \
55
cbmc-library \
6+
crangler \
67
goto-analyzer \
78
ansi-c \
89
goto-instrument \

regression/crangler/Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
default: tests.log
2+
3+
include ../../src/config.inc
4+
include ../../src/common
5+
6+
test:
7+
@../test.pl -e -p -c '../../../src/crangler/crangler'
8+
9+
tests.log:
10+
@../test.pl -e -p -c '../../../src/crangler/crangler'
11+
12+
clean:
13+
@for dir in *; do \
14+
$(RM) tests.log; \
15+
if [ -d "$$dir" ]; then \
16+
cd "$$dir"; \
17+
$(RM) *.out *.gb; \
18+
cd ..; \
19+
fi \
20+
done
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
int foo()
2+
{
3+
return 0;
4+
}
5+
6+
int bar();
7+
8+
static void foobar1()
9+
{
10+
}
11+
12+
void static foobar2()
13+
{
14+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
remove_static1.json
3+
4+
^ void foobar1\(\)$
5+
^void foobar2\(\)$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"sources": [
3+
"remove_static1.c"
4+
],
5+
"functions": {
6+
"foobar1": [
7+
"remove static"
8+
],
9+
"foobar2": [
10+
"remove static"
11+
]
12+
},
13+
"output": "stdout"
14+
}

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ add_subdirectory(statement-list)
106106
add_subdirectory(util)
107107

108108
add_subdirectory(cbmc)
109+
add_subdirectory(crangler)
109110
add_subdirectory(goto-cc)
110111
add_subdirectory(goto-instrument)
111112
add_subdirectory(goto-analyzer)

src/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ DIRS = analyses \
44
big-int \
55
cbmc \
66
cpp \
7+
crangler \
78
goto-analyzer \
89
goto-cc \
910
goto-checker \
@@ -27,6 +28,7 @@ DIRS = analyses \
2728
# Empty last line
2829

2930
all: cbmc.dir \
31+
crangler.dir \
3032
goto-analyzer.dir \
3133
goto-cc.dir \
3234
goto-diff.dir \
@@ -59,6 +61,8 @@ $(patsubst %, %.dir, $(filter-out big-int util, $(DIRS))): util.dir
5961

6062
cpp.dir: ansi-c.dir linking.dir
6163

64+
crangler.dir: util.dir json.dir
65+
6266
languages: util.dir langapi.dir \
6367
cpp.dir ansi-c.dir xmllang.dir assembler.dir \
6468
jsil.dir json.dir json-symtab-language.dir statement-list.dir

src/crangler/CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
generic_flex(c)
3+
4+
# Library
5+
file(GLOB_RECURSE sources "*.cpp" "*.h")
6+
list(REMOVE_ITEM sources
7+
${CMAKE_CURRENT_SOURCE_DIR}/crangler_main.cpp
8+
)
9+
10+
add_library(crangler-lib
11+
${sources}
12+
${BISON_parser_OUTPUTS}
13+
)
14+
15+
generic_includes(crangler-lib)
16+
17+
target_link_libraries(crangler-lib
18+
big-int
19+
util
20+
json
21+
)
22+
23+
# Executable
24+
add_executable(crangler crangler_main.cpp)
25+
target_link_libraries(crangler crangler-lib)
26+
27+
install(TARGETS crangler DESTINATION ${CMAKE_INSTALL_BINDIR})
28+

src/crangler/Makefile

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
SRC = c_defines.cpp \
2+
c_lex.yy.cpp \
3+
c_wrangler.cpp \
4+
crangler_main.cpp \
5+
crangler_parse_options.cpp \
6+
cscanner.cpp \
7+
ctokenit.cpp \
8+
mini_c_parser.cpp \
9+
# Empty last line
10+
11+
OBJ += ../big-int/big-int$(LIBEXT) \
12+
../json/json$(LIBEXT) \
13+
../util/util$(LIBEXT)
14+
15+
INCLUDES= -I ..
16+
17+
include ../config.inc
18+
include ../../$(CPROVER_DIR)/src/common
19+
20+
CLEANFILES = crangler$(LIBEXT)
21+
22+
all: crangler$(EXEEXT)
23+
24+
###############################################################################
25+
26+
c_lex.yy.cpp: scanner.l
27+
$(LEX) -Pyyc -o$@ scanner.l
28+
29+
###############################################################################
30+
31+
generated_files: c_lex.yy.cpp
32+
33+
###############################################################################
34+
35+
crangler$(EXEEXT): $(OBJ)
36+
$(LINKBIN)

src/crangler/c_defines.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*******************************************************************\
2+
3+
Module: C Defines
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// c_defines
11+
12+
#include "c_defines.h"
13+
14+
#include "cscanner.h"
15+
16+
#include <util/prefix.h>
17+
#include <util/string_utils.h>
18+
19+
#include <sstream>
20+
21+
void c_definest::parse(const std::string &src)
22+
{
23+
const auto lines = split_string(src, '\n');
24+
for(const auto &line : lines)
25+
{
26+
// #define __x86_64__ 1
27+
// #define getc_unlocked(fp) __sgetc(fp)
28+
if(!has_prefix(line, "#define "))
29+
continue;
30+
31+
auto space_pos = line.find(' ', 8);
32+
if(space_pos == std::string::npos)
33+
continue;
34+
35+
auto id = line.substr(8, space_pos - 8);
36+
auto value = line.substr(space_pos + 1, std::string::npos);
37+
map[id].value = value;
38+
}
39+
}
40+
41+
std::string c_definest::operator()(const std::string &src) const
42+
{
43+
// tokenize
44+
std::istringstream in(src);
45+
cscannert cscanner(in);
46+
const auto tokens = cscanner.get_tokens();
47+
48+
// output
49+
std::ostringstream out;
50+
for(auto &t : tokens)
51+
{
52+
if(is_identifier(t))
53+
{
54+
auto m_it = map.find(t.text);
55+
if(m_it != map.end())
56+
{
57+
out << m_it->second.value;
58+
}
59+
else
60+
out << t.text;
61+
}
62+
else
63+
out << t.text;
64+
}
65+
66+
return out.str();
67+
}

src/crangler/c_defines.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*******************************************************************\
2+
3+
Module: C Defines
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// c_defines
11+
12+
#ifndef CPROVER_CRANGLER_C_DEFINES_H
13+
#define CPROVER_CRANGLER_C_DEFINES_H
14+
15+
#include <util/optional.h>
16+
17+
#include <string>
18+
#include <unordered_map>
19+
#include <vector>
20+
21+
/// This class maintains a representation of one assignment to the
22+
/// preprocessor macros in a C program.
23+
class c_definest
24+
{
25+
public:
26+
struct definet
27+
{
28+
optionalt<std::vector<std::string>> parameters;
29+
std::string value;
30+
};
31+
32+
using mapt = std::unordered_map<std::string, definet>;
33+
mapt map;
34+
35+
void parse(const std::string &);
36+
std::string operator()(const std::string &) const;
37+
};
38+
39+
#endif // CPROVER_CRANGLER_C_DEFINES_H

0 commit comments

Comments
 (0)