mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-10-25 18:13:34 +00:00
fixed multiline handling; removed several bits of vestigial code from old cmock versions; made parsing much more readable
git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@84 bf332499-1b4d-0410-844d-d2d48d5cc64c
This commit is contained in:
@@ -33,7 +33,7 @@ class CMockGenerator
|
||||
|
||||
def create_mock_source_file(parsed_stuff)
|
||||
@file_writer.create_file(@mock_name + ".c") do |file, filename|
|
||||
create_source_header_section(file, filename, parsed_stuff[:includes])
|
||||
create_source_header_section(file, filename)
|
||||
create_instance_structure(file, parsed_stuff[:functions])
|
||||
create_extern_declarations(file)
|
||||
create_mock_verify_function(file, parsed_stuff[:functions])
|
||||
@@ -62,7 +62,7 @@ class CMockGenerator
|
||||
header << "\n#endif\n"
|
||||
end
|
||||
|
||||
def create_source_header_section(file, filename, include_files)
|
||||
def create_source_header_section(file, filename)
|
||||
header_file = filename.gsub(".c",".h")
|
||||
file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
|
||||
file << "#include <string.h>\n"
|
||||
@@ -71,7 +71,6 @@ class CMockGenerator
|
||||
file << "#include \"unity.h\"\n"
|
||||
file << @plugins.run(:include_files)
|
||||
|
||||
#(@config.includes + include_files).uniq.each {|include| file << "#include \"#{include}\"\n"} #### This is what the comments said in original version, but it wasnt actually doing this
|
||||
@config.includes.each {|include| file << "#include \"#{include}\"\n"}
|
||||
file << "#include \"#{header_file}\"\n\n"
|
||||
end
|
||||
|
||||
+14
-44
@@ -1,18 +1,16 @@
|
||||
class CMockHeaderParser
|
||||
|
||||
attr_accessor :src_lines, :funcs, :c_attributes, :included
|
||||
attr_accessor :src_lines, :funcs, :c_attributes
|
||||
|
||||
def initialize(source, cfg)
|
||||
import_source(source)
|
||||
@funcs = nil
|
||||
@funcs = []
|
||||
@c_attributes = cfg.attributes
|
||||
@declaration_parse_matcher = /(.*??)\((.*)\)/m
|
||||
@included = nil
|
||||
@declaration_parse_matcher = /(.+??)\((.*)\)/m
|
||||
end
|
||||
|
||||
def parse
|
||||
mod = {:includes => nil, :functions => []}
|
||||
mod[:includes] = included_files
|
||||
parse_functions
|
||||
if !@funcs.nil? and @funcs.length > 0
|
||||
@funcs.each do |decl|
|
||||
@@ -25,14 +23,14 @@ class CMockHeaderParser
|
||||
private
|
||||
|
||||
def import_source(source)
|
||||
source = source.gsub(/\/\/.*$/, '') #remove line comments
|
||||
source = source.gsub(/\/\*.*?\*\//m, '') #remove block comments
|
||||
@src_lines = source.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line
|
||||
| (;|\{|\}) /x) # Match ;, {, and } as end of lines
|
||||
@src_lines.delete_if {|line| line.length < 1}
|
||||
@src_lines.delete_if {|line| line =~ /\\\n/} #ignore lines that contain continuation lines
|
||||
@src_lines.delete_if {|line| line =~ /typedef/i} #ignore lines that contain typedef statements
|
||||
@src_lines.delete_if {|line| line =~ /\#define/i} #remove defines
|
||||
source = source.gsub(/\s*\\\s*/m, ' ') # smush multiline into single line
|
||||
source = source.gsub(/\/\/.*$/, '') # remove line comments
|
||||
source = source.gsub(/\/\*.*?\*\//m, '') # remove block comments
|
||||
source = source.gsub(/#.*/, '') # remove preprocessor statements
|
||||
source = source.gsub(/typedef.*/i, '') # remove typedef statements
|
||||
|
||||
@src_lines = source.split(/;/)
|
||||
@src_lines.delete_if {|line| line.strip.length == 0} # remove blank lines
|
||||
end
|
||||
|
||||
def c_attributes=(value)
|
||||
@@ -40,40 +38,12 @@ class CMockHeaderParser
|
||||
@attribute_match = Regexp.compile(%|(#{@c_attributes.join('|')}\s+)*|)
|
||||
end
|
||||
|
||||
def included_files
|
||||
if @included.nil?
|
||||
@included = []
|
||||
if !@src_lines.nil? and @src_lines.length > 0
|
||||
@src_lines.each do |line|
|
||||
if line =~ /#include\s+"(.*)"/
|
||||
@included << $1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return @included
|
||||
end
|
||||
|
||||
def parse_functions
|
||||
if @funcs.nil?
|
||||
@funcs = []
|
||||
depth = 0
|
||||
@src_lines.each do |line|
|
||||
if depth.zero? && line =~ @declaration_parse_matcher
|
||||
@funcs << line.strip.gsub(/\s+/, ' ')
|
||||
end
|
||||
if line =~ /\{/
|
||||
depth += 1
|
||||
end
|
||||
if line =~ /\}/
|
||||
depth -= 1
|
||||
end
|
||||
@src_lines.each do |line|
|
||||
if line =~ @declaration_parse_matcher
|
||||
@funcs << line.strip.gsub(/\s+/, ' ')
|
||||
end
|
||||
end
|
||||
#eliminate define functions
|
||||
@funcs ||= @funcs.reject do |func|
|
||||
func =~ /\bdefine\b/
|
||||
end
|
||||
return @funcs
|
||||
end
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ class CMockGeneratorTest < Test::Unit::TestCase
|
||||
@plugins.expect.run(:include_files).returns("#include \"PluginRequiredHeader.h\"\n")
|
||||
@config.expect.includes.returns(["ConfigRequiredHeader1.h","ConfigRequiredHeader2.h"])
|
||||
|
||||
@cmock_generator.create_source_header_section(output, "MockPoutPoutFish.c", [])
|
||||
@cmock_generator.create_source_header_section(output, "MockPoutPoutFish.c")
|
||||
|
||||
assert_equal(expected, output)
|
||||
end
|
||||
|
||||
@@ -13,9 +13,8 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
|
||||
should "create and initialize variables to defaults appropriately" do
|
||||
@parser = CMockHeaderParser.new("", @config)
|
||||
assert_nil(@parser.funcs)
|
||||
assert_equal([], @parser.funcs)
|
||||
assert_equal(['static', 'inline', '__ramfunc'], @parser.c_attributes)
|
||||
assert_nil(@parser.included)
|
||||
end
|
||||
|
||||
should "strip out line comments" do
|
||||
@@ -28,7 +27,6 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
expected =
|
||||
[
|
||||
" abcd",
|
||||
";",
|
||||
"\n\nwho \n"
|
||||
]
|
||||
|
||||
@@ -47,7 +45,6 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
expected =
|
||||
[
|
||||
" abcd",
|
||||
";",
|
||||
"\n\nwho \n"
|
||||
]
|
||||
|
||||
@@ -62,40 +59,12 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
"#pragma stack_switch"
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
"#when stuff_happens",
|
||||
"\n",
|
||||
"#ifdef _TEST",
|
||||
"\n",
|
||||
"#pragma stack_switch"
|
||||
]
|
||||
expected = []
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
end
|
||||
|
||||
should "Match ; { and } as end of line characters" do
|
||||
source =
|
||||
" i like ice cream; and i can eat { vanilla, chocolate } when I want to; so there!"
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
" i like ice cream",
|
||||
";",
|
||||
" and i can eat ",
|
||||
"{",
|
||||
" vanilla, chocolate ",
|
||||
"}",
|
||||
" when I want to",
|
||||
";",
|
||||
" so there!"
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
end
|
||||
|
||||
should "ignore lines that contain continuation characters" do
|
||||
should "smush lines together that contain continuation characters" do
|
||||
source =
|
||||
"hoo hah \\\n" +
|
||||
"when \\ \n"
|
||||
@@ -103,22 +72,24 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
|
||||
expected =
|
||||
[
|
||||
"hoo hah when "
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
end
|
||||
|
||||
should "ignore lines that contain typedef statements" do
|
||||
should "remove typedef statements" do
|
||||
source =
|
||||
"#typedef uint32 (unsigned int)\n" +
|
||||
"whack me? #typedef int INT\n" +
|
||||
"#typedef who cares what really comes here\n" +
|
||||
"typedef uint32 (unsigned int)\n" +
|
||||
"whack me? typedef int INT\n" +
|
||||
"typedef who cares what really comes here \\\n" + # exercise multiline typedef
|
||||
" continuation\n" +
|
||||
"this should remain!"
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
"\nthis should remain!"
|
||||
"\nwhack me? \n\nthis should remain!"
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
@@ -126,46 +97,22 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
|
||||
should "remove defines" do
|
||||
source =
|
||||
"hello;\n" +
|
||||
"#define whatever you feel like defining\n" +
|
||||
"void hello(void);\n" +
|
||||
"#DEFINE I JUST DON'T CARE\n" +
|
||||
"#deFINE\n"
|
||||
"#deFINE\n" +
|
||||
"#define get_foo() \\\n ((Thing)foo.bar)" # exercise multiline define
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
|
||||
expected =
|
||||
[
|
||||
"hello",
|
||||
";",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n"
|
||||
"\nvoid hello(void)",
|
||||
]
|
||||
|
||||
assert_equal(expected, @parser.src_lines)
|
||||
end
|
||||
|
||||
should "extract and return included files" do
|
||||
source =
|
||||
"int Foo(int a, unsigned int b);" +
|
||||
"hello;\n" +
|
||||
"#define whatever you feel like defining\n" +
|
||||
"#include \"myheader.h\"\n" +
|
||||
"#include \t \"os.h\"\n"
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
parsed_stuff = @parser.parse
|
||||
|
||||
expected =
|
||||
[
|
||||
"myheader.h",
|
||||
"os.h"
|
||||
]
|
||||
|
||||
assert_equal(expected, parsed_stuff[:includes])
|
||||
end
|
||||
|
||||
should "extract and return function declarations" do
|
||||
|
||||
source =
|
||||
@@ -173,7 +120,8 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
"void bar \n(uint la, int de, bool da);\n" +
|
||||
"void FunkyChicken (\n uint la,\n int de,\n bool da);\n" +
|
||||
"void\n shiz(void);\n" +
|
||||
"void tat();\n"
|
||||
"void tat();\n" +
|
||||
"#define get_foo() \\\n (Thing)foo())" # should extract no function declarations
|
||||
|
||||
@parser = CMockHeaderParser.new(source, @config)
|
||||
parsed_stuff = @parser.parse
|
||||
|
||||
Reference in New Issue
Block a user