mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-09-30 05:57:27 +00:00
Support basic #if 0 and #if 1 handling... not more complicated preprocessing.
This commit is contained in:
@@ -64,6 +64,48 @@ class CMockHeaderParser
|
||||
|
||||
private if $ThisIsOnlyATest.nil? ################
|
||||
|
||||
# Remove code disabled by basic preprocesser tags like #if 0, #if 1, etc.
|
||||
def remove_disabled_code_from_source(source)
|
||||
result = []
|
||||
emit = true
|
||||
# Stack entries: [restore_emit, else_emit, seen_else]
|
||||
# restore_emit: value to restore `emit` to after matching #endif
|
||||
# else_emit: value to set `emit` to after #else
|
||||
# seen_else: whether #else at this level has already been seen
|
||||
stack = []
|
||||
|
||||
source.each_line do |line|
|
||||
stripped = line.strip
|
||||
if stripped =~ /^#\s*if\s+0\s*$/
|
||||
stack.push([emit, emit, false])
|
||||
emit = false
|
||||
elsif stripped =~ /^#\s*if\s+1\s*$/
|
||||
stack.push([emit, false, false])
|
||||
# emit unchanged: keep the if-branch
|
||||
elsif stripped =~ /^#\s*if/
|
||||
stack.push([emit, emit, false])
|
||||
# emit unchanged: unknown condition, keep both branches
|
||||
elsif stripped =~ /^#\s*else\b/
|
||||
unless stack.empty?
|
||||
entry = stack.last
|
||||
unless entry[2]
|
||||
stack[-1] = [entry[0], entry[1], true]
|
||||
emit = entry[1]
|
||||
end
|
||||
end
|
||||
elsif stripped =~ /^#\s*endif\b/
|
||||
unless stack.empty?
|
||||
entry = stack.pop
|
||||
emit = entry[0]
|
||||
end
|
||||
elsif emit
|
||||
result << line
|
||||
end
|
||||
end
|
||||
|
||||
result.join
|
||||
end
|
||||
|
||||
# Remove C/C++ comments from a string
|
||||
# +source+:: String which will have the comments removed
|
||||
def remove_comments_from_source(source)
|
||||
@@ -248,6 +290,10 @@ class CMockHeaderParser
|
||||
|
||||
# remove preprocessor statements and extern "C"
|
||||
source.gsub!(/extern\s+"C"\s*\{/, '')
|
||||
|
||||
# handle basic literal preprocessor conditionals before stripping all directives
|
||||
source = remove_disabled_code_from_source(source)
|
||||
|
||||
source.gsub!(/^\s*#.*/, '')
|
||||
|
||||
# enums, unions, structs, and typedefs can all contain things (e.g. function pointers) that parse like function prototypes, so yank them
|
||||
|
||||
@@ -146,6 +146,118 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
assert_equal(expected, @parser.import_source(source, @test_project))
|
||||
end
|
||||
|
||||
it "remove code inside #if 0 blocks" do
|
||||
source =
|
||||
"void before(void);\n" +
|
||||
"#if 0\n" +
|
||||
"void hidden(void);\n" +
|
||||
"#endif\n" +
|
||||
"void after(void);\n"
|
||||
|
||||
expected = ["void before(void)", "void after(void)"]
|
||||
|
||||
assert_equal(expected, @parser.import_source(source, @test_project).map! { |s| s.strip })
|
||||
end
|
||||
|
||||
it "keep code inside #if 1 blocks" do
|
||||
source =
|
||||
"void before(void);\n" +
|
||||
"#if 1\n" +
|
||||
"void visible(void);\n" +
|
||||
"#endif\n" +
|
||||
"void after(void);\n"
|
||||
|
||||
expected = ["void before(void)", "void visible(void)", "void after(void)"]
|
||||
|
||||
assert_equal(expected, @parser.import_source(source, @test_project).map! { |s| s.strip })
|
||||
end
|
||||
|
||||
it "keep else branch of #if 0 blocks" do
|
||||
source =
|
||||
"void before(void);\n" +
|
||||
"#if 0\n" +
|
||||
"void hidden(void);\n" +
|
||||
"#else\n" +
|
||||
"void visible(void);\n" +
|
||||
"#endif\n" +
|
||||
"void after(void);\n"
|
||||
|
||||
expected = ["void before(void)", "void visible(void)", "void after(void)"]
|
||||
|
||||
assert_equal(expected, @parser.import_source(source, @test_project).map! { |s| s.strip })
|
||||
end
|
||||
|
||||
it "remove else branch of #if 1 blocks" do
|
||||
source =
|
||||
"void before(void);\n" +
|
||||
"#if 1\n" +
|
||||
"void visible(void);\n" +
|
||||
"#else\n" +
|
||||
"void hidden(void);\n" +
|
||||
"#endif\n" +
|
||||
"void after(void);\n"
|
||||
|
||||
expected = ["void before(void)", "void visible(void)", "void after(void)"]
|
||||
|
||||
assert_equal(expected, @parser.import_source(source, @test_project).map! { |s| s.strip })
|
||||
end
|
||||
|
||||
it "handle nested #if 1 blocks inside #if 0" do
|
||||
source =
|
||||
"void before(void);\n" +
|
||||
"#if 0\n" +
|
||||
"void hidden1(void);\n" +
|
||||
"#if 1\n" +
|
||||
"void hidden2(void);\n" +
|
||||
"#endif\n" +
|
||||
"void hidden3(void);\n" +
|
||||
"#endif\n" +
|
||||
"void after(void);\n"
|
||||
|
||||
expected = ["void before(void)", "void after(void)"]
|
||||
|
||||
assert_equal(expected, @parser.import_source(source, @test_project).map! { |s| s.strip })
|
||||
end
|
||||
|
||||
it "handle nested #if 0 blocks inside #if 1" do
|
||||
source =
|
||||
"void before(void);\n" +
|
||||
"#if 1\n" +
|
||||
"void visible1(void);\n" +
|
||||
"#if 0\n" +
|
||||
"void hidden1(void);\n" +
|
||||
"#endif\n" +
|
||||
"void visible2(void);\n" +
|
||||
"#endif\n" +
|
||||
"void after(void);\n"
|
||||
|
||||
expected = ["void before(void)", "void visible1(void)", "void visible2(void)", "void after(void)"]
|
||||
|
||||
assert_equal(expected, @parser.import_source(source, @test_project).map! { |s| s.strip })
|
||||
end
|
||||
|
||||
it "handle back to back #if 1 blocks and #if 0 blocks" do
|
||||
source =
|
||||
"void before(void);\n" +
|
||||
"#if 0\n" +
|
||||
"void hidden1(void);\n" +
|
||||
"#endif\n" +
|
||||
"#if 1\n" +
|
||||
"void visible1(void);\n" +
|
||||
"#endif\n" +
|
||||
"#if 0\n" +
|
||||
"void hidden2(void);\n" +
|
||||
"#endif\n" +
|
||||
"#if 1\n" +
|
||||
"void visible2(void);\n" +
|
||||
"#endif\n" +
|
||||
"void after(void);\n"
|
||||
|
||||
expected = ["void before(void)", "void visible1(void)", "void visible2(void)", "void after(void)"]
|
||||
|
||||
assert_equal(expected, @parser.import_source(source, @test_project).map! { |s| s.strip })
|
||||
end
|
||||
|
||||
|
||||
it "remove assembler pragma sections" do
|
||||
source =
|
||||
|
||||
Reference in New Issue
Block a user