Support basic #if 0 and #if 1 handling... not more complicated preprocessing.

This commit is contained in:
Mark VanderVoord
2026-06-29 16:48:31 -04:00
parent 2e76508412
commit 38dc454826
2 changed files with 158 additions and 0 deletions
+46
View File
@@ -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
+112
View File
@@ -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 =