-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathgen-xfakes.sh
executable file
·235 lines (183 loc) · 5.33 KB
/
gen-xfakes.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#!/bin/bash
FAKES_BASENAME=tmp-xfakes
preambleCFakes()
{
cat > $1 <<- EOM
/*
Fakes generated from: $2
Generated file to help to quickly stub C-linkage unresolved external references
* When EXPLODING_FAKE_FOR is executed, a message is printed and the test run is existed
* You could customize EXPLODING_FAKE_FOR to only fail the test
* Add this file to your test build.
* Do not include the header files for the referenced functions. The C-linker does not care.
Note: a EXPLODING_FAKE_FOR() is generated for global variables too.
* They will explode upon write :-)
* You might want to resolve these a different way.
*/
#include <stdio.h>
#include <stdlib.h>
#define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__)
#define EXPLODING_FAKE_FOR(f) void f(void); void f(void) { BOOM_MESSAGE; exit(1); }
#define NULL_VOID_FAKE_FOR(f) void f(void); void f(void) {}
#define NULL_VALUE_FAKE_FOR(value_type, f, result) value_type f(void); value_type f(void) { return result; }
EOM
}
preambleCppFakes()
{
cat > $1 <<- EOM
/*
Fakes generated from: $2
Generated file to help to quickly stub C++ undefined external functions.
* Add this file to your test build.
* One at a time
* Uncomment an exploing fake function definition.
* Add needed the include file.
* Modify non-void function return types and provide a return value.
* Fix errors.
* Work carefully. Use the compiler and link error output to test your changes.
* You could customize the BOOM macros to only fail the test, rather than exit the
test runner.
*/
#include <stdio.h>
#include <stdlib.h>
#define BOOM_MESSAGE printf("BOOM! time to write a better fake for %s\n", __func__)
#define BOOM_VOID_CPP BOOM_MESSAGE; exit(1);
#define BOOM_VALUE_CPP(result) BOOM_MESSAGE; exit(1); return result;
/*
* Production code header files
*/
// #include "your.h"
EOM
}
preambleCppGlobalFakes()
{
cat > $1 <<- EOM
/*
Fakes generated from: $2
Generated file to help to quickly stub C++ undefined external globals.
* One at a time
* Add the file containing the global definition to your build or
add the global data definition (and its declaratiob) to this file.
Adding the global to this file is probably not sustainable, but a
pragmatic choice until you decide how to better organioze your global
data.
* Add include files as neededd.
* Work carefully. Use the compiler and link error output to test your changes.
*/
EOM
}
# linkErrorClang()
# {
# grep ", referenced from:"
# }
# isolateUndefinedSymbolsClang()
# {
# linkErrorClang | sed -e's/^ *"//' -e's/".*//' -e's/^_//'
# }
# linkErrorGcc()
# {
# grep ": undefined reference to "
# }
# isolateUndefinedSymbolsGcc()
# {
# linkErrorGcc | sed -e's/.*`//' -e"s/'$//"
# }
# linkErrorVS_C()
# {
# grep "LNK2019.*symbol _"
# }
# linkErrorVS_Cpp()
# {
# grep "LNK2019\|LNK2001" | grep ".*symbol \""
# }
# isolateUndefinedSymbolsVS_C()
# {
# linkErrorVS_C | sed -e's/^.*symbol _/__C__/' -e's/ referenced.*//' -e's/__C__//'
# }
# isolateUndefinedSymbolsVS_Cpp()
# {
# linkErrorVS_Cpp | sed -e's/^.*symbol "/__CPP__/' -e's/" .*//' -e's/__CPP__//'
# }
usage()
{
echo "usage $0 linker-error-output.txt out-file-basename"
exit 1
}
must_exist()
{
if [ ! -e $1 ]; then
echo "Input file does not exist: $1"
exit 1
fi
}
cant_exist()
{
if [ -e $1 ]; then
echo "Output file exists: $1"
exit 1
fi
}
makeFakes()
{
cant_exist $4
preamble$3Fakes $4 $1
cat $2 | make$3Fakes >> $4
}
makeCFakes()
{
grep -v "::\|vtable" | grep -v "(.*)" | grep -v "typeinfo" | sed -e's/^/EXPLODING_FAKE_FOR(/' -e's/$/)/'
}
makeCppFakes()
{
# grep "vtable" | sed -e's|vtable for \(.*$\)|// ~\1::\1|' -e's/$/ { BOOM_VOID_CPP }/'
grep "(.*)\|vtable" | sed -e's|^|// void |' -e's/$/ { BOOM_VOID_CPP }/' -e's/void vtable for/missing destructor/'
}
makeCppGlobalFakes()
{
grep -v "(.*)" | grep "::" | sed -e's|^|// cpp-global |' -e's/$/;&/'
}
show_fakes_stats_for()
{
echo "$1 has $(grep -v "#define" $1 |grep -c "$2" | sed -e's/:/ generated /' -e's/$/ exploding fakes/')"
}
show_fakes_stats()
{
show_fakes_stats_for ${FAKES_BASENAME}-c.c "^EXPLODING"
show_fakes_stats_for ${FAKES_BASENAME}-cpp.cpp "^//.*BOOM"
show_fakes_stats_for ${FAKES_BASENAME}-cpp-globals.cpp "// cpp-global"
}
usage()
{
echo "usage $0 sorted-undefined-symbols-file"
exit 1
}
gen_xfakes()
{
input_file=$1
must_exist $input_file
sorted_undefines=$SORTED_UNDEFINES
must_exist $sorted_undefines
fakes_c=$3-c.c
fakes_cpp=$3-cpp.cpp
fakes_cpp_globals=$3-cpp-globals.cpp
makeFakes $input_file $sorted_undefines C $fakes_c
makeFakes $input_file $sorted_undefines Cpp $fakes_cpp
makeFakes $input_file $sorted_undefines CppGlobal $fakes_cpp_globals
}
generate_fakes()
{
if [[ "$#" != "1" ]]; then
usage
fi
[ ! -e $SORTED_UNDEFINES ] && return 0
echo "Removing earlier generated fakes "
rm -f ${FAKES_BASENAME}-*.*
echo "Generating fakes"
gen_xfakes $ERROR_FILE $SORTED_UNDEFINES $FAKES_BASENAME
echo "Review generated fakes, and incrementally add them to the build:"
show_fakes_stats
return 0
}
if [[ "$0" = "$BASH_SOURCE" ]]; then
generate_fakes $@
fi