From 500c30a5cef56c6eb27d48bdaf103078e5dd0efc Mon Sep 17 00:00:00 2001 From: mkarlesky Date: Thu, 14 May 2009 05:18:45 +0000 Subject: [PATCH] intermediate check in; integrating new parser and tests thereof yet in progress git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@93 bf332499-1b4d-0410-844d-d2d48d5cc64c --- lib/cmock.rb | 8 +- lib/cmock_header_parser.rb | 138 ++--- rakefile.rb | 4 - .../cmock_function_prototype_parser_test.rb | 28 +- test/unit/cmock_header_parser_test.rb | 524 ++++++------------ 5 files changed, 237 insertions(+), 465 deletions(-) diff --git a/lib/cmock.rb b/lib/cmock.rb index f4b829d..fa458e8 100644 --- a/lib/cmock.rb +++ b/lib/cmock.rb @@ -1,4 +1,10 @@ $here = File.dirname __FILE__ + +require 'rubygems' +require 'treetop' + +require "#{$here}/cmock_function_prototype_node_classes" +require "#{$here}/cmock_function_prototype_parser" require "#{$here}/cmock_header_parser" require "#{$here}/cmock_generator" require "#{$here}/cmock_file_writer" @@ -26,7 +32,7 @@ class CMock path = File.dirname(src) @cfg.set_path(path) - cm_parser = CMockHeaderParser.new(File.read(src), @cfg) + cm_parser = CMockHeaderParser.new(CMockFunctionPrototypeParser.new, File.read(src), @cfg) cm_unityhelper = CMockUnityHelperParser.new(@cfg) cm_writer = CMockFileWriter.new(@cfg) cm_gen_utils = CMockGeneratorUtils.new(@cfg, {:unity_helper => cm_unityhelper}) diff --git a/lib/cmock_header_parser.rb b/lib/cmock_header_parser.rb index ca10559..e4da088 100644 --- a/lib/cmock_header_parser.rb +++ b/lib/cmock_header_parser.rb @@ -1,23 +1,23 @@ + class CMockHeaderParser - attr_accessor :src_lines, :funcs, :c_attributes + attr_accessor :src_lines, :prototypes, :c_attributes - def initialize(source, cfg) - @funcs = [] + def initialize(parser, source, cfg) + @src_lines = [] + @prototypes = [] @c_attributes = cfg.attributes - @declaration_parse_matcher = /([\d\w\s\*\(\),]+??)\(([\d\w\s\*\(\),\.]*)\)$/m - + @prototype_parse_matcher = /([\d\w\s\*\(\),]+??)\(([\d\w\s\*\(\),\.]*)\)$/m + @parser = parser import_source(source) end def parse mod = {:includes => nil, :functions => []} - parse_functions - if !@funcs.nil? and @funcs.length > 0 - @funcs.each do |decl| - mod[:functions] << parse_declaration(decl) - end - end + # build prototype list + extract_prototypes + # parse all prototyes into hashes of components and add to array + @prototypes.each {|prototype| mod[:functions] << parse_prototype(prototype)} if (@prototypes.length > 0) return mod end @@ -27,7 +27,7 @@ class CMockHeaderParser # look for any edge cases of typedef'd void; # void must be void for cmock AndReturn calls to process properly. # to a certain extent, these replacements assume we're chewing on pre-processed header files - void_types = source.scan(/typedef\s+void\s+([\w\d]+)\s*;/) + void_types = source.scan(/typedef\s+(\(\s*)?void(\s*\))?\s+([\w\d]+)\s*;/) void_types.each {|type| source.gsub!(/#{type}/, 'void')} if void_types.size > 0 source.gsub!(/\s*\\\s*/m, ' ') # smush multiline into single line @@ -35,7 +35,10 @@ class CMockHeaderParser source.gsub!(/\/\/.*$/, '') # remove line comments source.gsub!(/#.*/, '') # remove preprocessor statements source.gsub!(/typedef.*/, '') # remove typedef statements - + source.gsub!(/^\s+/, '') # remove excessive white space + source.gsub!(/\s+$/, '') # remove excessive white space + source.gsub!(/\s+/, ' ') # remove excessive white space + @src_lines = source.split(/\s*;\s*/) # split source at end of statements (removing extra white space) @src_lines.delete_if {|line| line.strip.length == 0} # remove blank lines end @@ -45,96 +48,41 @@ class CMockHeaderParser @attribute_match = Regexp.compile(%|(#{@c_attributes.join('|')}\s+)*|) end - def parse_functions + def extract_prototypes @src_lines.each do |line| - @funcs << line.strip.gsub(/\s+/, ' ') if line =~ @declaration_parse_matcher - end - return @funcs - end - - def parse_args(arg_list) - args = [] - arg_list.split(',').each do |arg| - arg = arg.strip - return args if ((arg == '...') || (arg == 'void')) - arg_elements = arg.split - args << {:type => arg_elements[0..-2].join(' '), :name => arg_elements[-1]} - end - return args - end - - def clean_args(arg_list) - if ((arg_list.strip == 'void') or (arg_list.empty?)) - return 'void' - else - c=0 - arg_list.gsub!(/\s+\*/,'*') # remove space to place asterisks with type (where they belong) - arg_list.gsub!(/\*(\w)/,'* \1') # pull asterisks away from param to place asterisks with type (where they belong) - arg_list.split(/\s*,\s*/).map{|arg| (arg =~ /^(\w+|.+\*|.+\)|.+const)$/) ? "#{arg} cmock_arg#{c+=1}" : arg}.join(', ') - end - end - - def parse_declaration(declaration) - decl = {} - - regex_match = @declaration_parse_matcher.match(declaration) - raise "Failed parsing function declaration: '#{declaration}'" if regex_match.nil? - - # grab argument list - args = regex_match[2].strip - - # process function attributes, return type, and name - descriptors = regex_match[1] - descriptors.gsub!(/\s+\*/,'*') # remove space to place asterisks with return type (where they belong) - descriptors.gsub!(/\*(\w)/,'* \1') # pull asterisks away from function name to place asterisks with return type (where they belong) - descriptors = descriptors.split # array of all descriptor strings - - # grab name - decl[:name] = descriptors[-1] # snag name as last array item - - # build attribute and return type strings - decl[:modifier] = [] - decl[:rettype] = [] - descriptors[0..-2].each do |word| - if @c_attributes.include?(word) - decl[:modifier] << word - else - decl[:rettype] << word + # build array of function prototypes + if (line =~ @prototype_parse_matcher) + # (remove any default parameter statements from argument lists while scanning) + line.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, '') + @prototypes << line end end - decl[:modifier] = decl[:modifier].join(' ') - decl[:rettype] = decl[:rettype].join(' ') - - # remove default parameter statements from mock definitions - args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*\,/, ',') - args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, ' ') + return @prototypes + end + + def parse_prototype(prototype) + hash = {} - #check for var args - if (args =~ /\.\.\./) - decl[:var_arg] = args.match( /[\w\s]*\.\.\./ ).to_s.strip - if (args =~ /\,[\w\s]*\.\.\./) - args = args.gsub!(/\,[\w\s]*\.\.\./,'') - else - args = 'void' + modifiers = [] + @c_attributes.each do |attribute| + if (prototype =~ /#{attribute}\s+/i) + modifiers << attribute + prototype.gsub!(/#{attribute}\s+/i, '') end - else - decl[:var_arg] = nil end + hash[:modifier] = modifiers.join(' ') - args = clean_args(args) - decl[:args_string] = args - decl[:args] = parse_args(args) - - if decl[:rettype].nil? or decl[:name].nil? or decl[:args].nil? - raise "Declaration parse failed!\n" + - " declaration: #{declaration}\n" + - " modifier: #{decl[:modifier]}\n" + - " return: #{decl[:rettype]}\n" + - " function: #{decl[:name]}\n" + - " args:#{decl[:args]}\n" - end + parsed = @parser.parse(prototype) + + raise "Failed parsing function prototype: '#{prototype}'" if parsed.nil? - return decl + hash[:name] = parsed.get_function_name + hash[:args_string] = parsed.get_argument_list + hash[:args] = parsed.get_arguments + hash[:rettype] = parsed.get_return_type + hash[:var_arg] = parsed.get_var_arg + + return hash end end diff --git a/rakefile.rb b/rakefile.rb index 5b9a8ec..95fbd41 100644 --- a/rakefile.rb +++ b/rakefile.rb @@ -34,12 +34,9 @@ task :treetop do treetop_files.each do |file| compiler.compile(file) end - - #`vendor/gems/treetop-1.2.5/bin/tt lib/cmock_function_prototype_parser.treetop` end namespace :test do - desc "Run all unit and system tests" task :all => ['test:units', 'test:system'] @@ -55,5 +52,4 @@ namespace :test do tests_failed = run_systests(FileList['test/system/cases/*.yml']) raise "System tests failed." if (tests_failed > 0) end - end \ No newline at end of file diff --git a/test/unit/cmock_function_prototype_parser_test.rb b/test/unit/cmock_function_prototype_parser_test.rb index cfd99d9..20ac930 100644 --- a/test/unit/cmock_function_prototype_parser_test.rb +++ b/test/unit/cmock_function_prototype_parser_test.rb @@ -15,6 +15,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase def teardown end + should "parse simple void function prototypes" do parsed = @parser.parse("void foo_bar(void)") @@ -35,6 +36,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_nil(parsed.get_var_arg) end + should "fail to parse garbage, broken function prototypes, and strings that only appear to be prototypes" do assert_nil(@parser.parse("** !")) assert_nil(@parser.parse("ashjfhskdh")) @@ -51,6 +53,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_nil(@parser.parse("(parenthetical comment)")) end + should "parse and normalize white space" do parsed = @parser.parse("void foo_bar ( void )") assert_equal("void foo_bar(void)", parsed.get_declaration) @@ -74,6 +77,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_equal("float (*GetPtr( const char opCode ))( float, float )", parsed.get_declaration) end + should "parse out simple arguments from an argument list into an array of hashes" do # function pointers & var args tested elsewhere @@ -115,6 +119,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_nil(parsed.get_var_arg) end + should "fail to parse arguments that mix multiple custom types or a custom type and a primitive" do # parser can only recognize strings of primitves followed by optional name or # a single custom type followed by optional name; @@ -125,6 +130,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_nil(@parser.parse("void foo_bar(CUSTOM_TYPE1 CUSTOM_TYPE2 abc, CUSTOM_TYPE1 CUSTOM_TYPE2 xyz)")) end + should "parse out simple return types" do # function pointers tested elsewhere @@ -144,13 +150,14 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_equal('CUSTOM_TYPE', parsed.get_return_type) end + should "normalize pointer notation" do - parsed = @parser.parse("void * foo(unsigned int * a, char * *b, int* c, int (* func)(void))") + parsed = @parser.parse("void * foo(unsigned int * * * a, char * *b, int* c, int (* func)(void))") assert_equal('void*', parsed.get_return_type) - assert_equal('unsigned int* a, char** b, int* c, int (*func)(void)', parsed.get_argument_list) + assert_equal('unsigned int*** a, char** b, int* c, int (*func)(void)', parsed.get_argument_list) assert_equal([ - {:type => 'unsigned int*', :name => 'a'}, + {:type => 'unsigned int***', :name => 'a'}, {:type => 'char**', :name => 'b'}, {:type => 'int*', :name => 'c'}, {:type => 'int (*)(void)', :name => 'func'}], @@ -158,6 +165,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_nil(parsed.get_var_arg) end + should "specially process var args in preparation for mocking" do parsed = @parser.parse("void foo_bar(...)") assert_equal('void', parsed.get_argument_list) @@ -179,8 +187,12 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_nil(parsed.get_var_arg) # no var args for thing(), just for the function pointer param end + should "parse prototypes handling function pointers" do # function pointer prototypes in argument lists (i.e. no typedef) + + # handle this? --> "int slinkydog(bool thing, int (* const)(void));\n" + + parsed = @parser.parse("void thing(int (*func_ptr)(int, int))") assert_equal('int (*func_ptr)( int, int )', parsed.get_argument_list) assert_equal( @@ -211,6 +223,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase assert_equal('unsigned int* (*)( unsigned int a )', parsed.get_return_type) end + should "create unique typedefs for function pointer prototypes in argument lists and return types" do # function prototype argument list handling parsed = @parser.parse("void foo_bar(unsigned int a, void (*func)(int *, unsigned long int, ...))") @@ -246,13 +259,14 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase parsed.get_typedefs) end - should "insert unique names for top-level nameless arguments" do - parsed = @parser.parse("void foo_bar(int (*)(int, int), char, unsigned int c, CUSTOM_THING)") - assert_equal('int (*cmock_arg1)( int, int ), char cmock_arg2, unsigned int c, CUSTOM_THING cmock_arg4', parsed.get_argument_list) + should "insert unique names for top-level nameless arguments" do + parsed = @parser.parse("void foo_bar(int (*)(int, int), char* const, unsigned int c, CUSTOM_THING)") + + assert_equal('int (*cmock_arg1)( int, int ), char* const cmock_arg2, unsigned int c, CUSTOM_THING cmock_arg4', parsed.get_argument_list) assert_equal( [{:type => 'int (*)( int, int )', :name => 'cmock_arg1'}, - {:type => 'char', :name => 'cmock_arg2'}, + {:type => 'char* const', :name => 'cmock_arg2'}, {:type => 'unsigned int', :name => 'c'}, {:type => 'CUSTOM_THING', :name => 'cmock_arg4'}], parsed.get_arguments) diff --git a/test/unit/cmock_header_parser_test.rb b/test/unit/cmock_header_parser_test.rb index 09c0e90..8a9dd88 100644 --- a/test/unit/cmock_header_parser_test.rb +++ b/test/unit/cmock_header_parser_test.rb @@ -4,7 +4,7 @@ require 'cmock_header_parser' class CMockHeaderParserTest < Test::Unit::TestCase def setup - create_mocks :config + create_mocks :config, :prototype_parser, :parsed @config.expect.attributes.returns(['static', 'inline', '__ramfunc']) end @@ -12,8 +12,9 @@ class CMockHeaderParserTest < Test::Unit::TestCase end should "create and initialize variables to defaults appropriately" do - @parser = CMockHeaderParser.new("", @config) - assert_equal([], @parser.funcs) + @parser = CMockHeaderParser.new(@prototype_parser, "", @config) + assert_equal([], @parser.prototypes) + assert_equal([], @parser.src_lines) assert_equal(['static', 'inline', '__ramfunc'], @parser.c_attributes) end @@ -22,12 +23,12 @@ class CMockHeaderParserTest < Test::Unit::TestCase " abcd;\n" + "// hello;\n" + "who // is you\n" - @parser = CMockHeaderParser.new(source, @config) + @parser = CMockHeaderParser.new(@prototype_parser, source, @config) expected = [ - " abcd", - "who \n" + "abcd", + "who" ] assert_equal(expected, @parser.src_lines) @@ -39,12 +40,12 @@ class CMockHeaderParserTest < Test::Unit::TestCase "/* hello;*/\n" + "who /* is you\n" + "// embedded line comment */\n" - @parser = CMockHeaderParser.new(source, @config) + @parser = CMockHeaderParser.new(@prototype_parser, source, @config) expected = [ - " abcd", - "who \n" + "abcd", + "who" ] assert_equal(expected, @parser.src_lines) @@ -55,7 +56,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase "#when stuff_happens\n" + "#ifdef _TEST\n" + "#pragma stack_switch" - @parser = CMockHeaderParser.new(source, @config) + @parser = CMockHeaderParser.new(@prototype_parser, source, @config) expected = [] @@ -66,11 +67,11 @@ class CMockHeaderParserTest < Test::Unit::TestCase source = "hoo hah \\\n" + "when \\ \n" - @parser = CMockHeaderParser.new(source, @config) + @parser = CMockHeaderParser.new(@prototype_parser, source, @config) expected = [ - "hoo hah when " + "hoo hah when" ] assert_equal(expected, @parser.src_lines) @@ -83,11 +84,11 @@ class CMockHeaderParserTest < Test::Unit::TestCase "typedef who cares what really comes here \\\n" + # exercise multiline typedef " continuation\n" + "this should remain!" - @parser = CMockHeaderParser.new(source, @config) + @parser = CMockHeaderParser.new(@prototype_parser, source, @config) expected = [ - "\nwhack me? \n\nthis should remain!" + "whack me? this should remain!" ] assert_equal(expected, @parser.src_lines) @@ -100,12 +101,12 @@ class CMockHeaderParserTest < Test::Unit::TestCase "#DEFINE I JUST DON'T CARE\n" + "#deFINE\n" + "#define get_foo() \\\n ((Thing)foo.bar)" # exercise multiline define - - @parser = CMockHeaderParser.new(source, @config) + + @parser = CMockHeaderParser.new(@prototype_parser, source, @config) expected = [ - "\nvoid hello(void)", + "void hello(void)", ] assert_equal(expected, @parser.src_lines) @@ -115,360 +116,167 @@ class CMockHeaderParserTest < Test::Unit::TestCase source = "typedef void SILLY_VOID_TYPE1;\n" + - "typedef void SILLY_VOID_TYPE2 ;\n" + - "typedef void (*FUNCPTR)(void);\n\n" + # don't get fooled by function pointer typedef with void as return type + "typedef (void) SILLY_VOID_TYPE2 ;\n" + + "typedef ( void ) (*FUNCPTR)(void);\n\n" + # don't get fooled by function pointer typedef with void as return type "SILLY_VOID_TYPE2 Foo(int a, unsigned int b);\n" + "void\n shiz(SILLY_VOID_TYPE1 *);\n" + "void tat(FUNCPTR);\n" - @parser = CMockHeaderParser.new(source, @config) - parsed_stuff = @parser.parse - + @parser = CMockHeaderParser.new(@prototype_parser, source, @config) + expected = [ - { - :modifier => "", - :args_string => "int a, unsigned int b", - :rettype => "void", - :var_arg => nil, - :args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}], - :name => "Foo" - }, - - { - :modifier => "", - :args_string => "void* cmock_arg1", - :rettype => "void", - :var_arg => nil, - :args => [{:type => "void*", :name => "cmock_arg1"}], - :name => "shiz" - }, - - { - :modifier => "", - :args_string => "FUNCPTR cmock_arg1", - :rettype => "void", - :var_arg => nil, - :args => [{:type => "FUNCPTR", :name => "cmock_arg1"}], - :name => "tat" - } + "void Foo(int a, unsigned int b)", + "void shiz(void *)", + "void tat(FUNCPTR)" ] - assert_equal(expected, parsed_stuff[:functions]) + assert_equal(expected, @parser.src_lines) end - - should "extract and return function declarations" do + + should "raise upon prototype parsing failure" do source = "int Foo(int a, unsigned int b);\n" + - "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" + - # following lines should yield no function declarations: - "#define get_foo() \\\n (Thing)foo())\n" + - "ARRAY_TYPE array[((U8)10)];\n" + - "THINGER_MASK = (0x0001 << 5),\n" - - @parser = CMockHeaderParser.new(source, @config) - parsed_stuff = @parser.parse + "void bar \n(uint la, int de, bool da) ; \n" - expected = - [ - { - :modifier => "", - :args_string => "int a, unsigned int b", - :rettype => "int", - :var_arg => nil, - :args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}], - :name => "Foo" - }, - - { - :modifier => "", - :args_string => "uint la, int de, bool da", - :rettype => "void", - :var_arg => nil, - :args => - [ - {:type => "uint", :name => "la"}, - {:type => "int", :name => "de"}, - {:type => "bool", :name => "da"} - ], - :name => "bar" - }, - - { - :modifier => "", - :args_string => "uint la, int de, bool da", - :rettype => "void", - :var_arg => nil, - :args => - [ - {:type => "uint", :name => "la"}, - {:type => "int", :name => "de"}, - {:type => "bool", :name => "da"} - ], - :name => "FunkyChicken" - }, + @prototype_parser.expect.parse('int Foo(int a, unsigned int b)').returns(nil) + + @parser = CMockHeaderParser.new(@prototype_parser, source, @config) + + begin + @parser.parse + assert_fail('should have raised') + rescue + end + end - { - :modifier => "", - :args_string => "void", - :rettype => "void", - :var_arg => nil, - :args => [], - :name => "shiz" - }, - - { - :modifier => "", - :args_string => "void", - :rettype => "void", - :var_arg => nil, - :args => [], - :name => "tat" - } - ] - - assert_equal(expected, parsed_stuff[:functions]) - end - - should "extract and return function declarations with attributes" do - - source = - "static \tint \n Foo(int a, unsigned int b);\n" + - "inline\t bool bar \n(uint la, int de, bool da);\n" + - "inline static __ramfunc bool bar ( uint thinger );\n" - - @parser = CMockHeaderParser.new(source, @config) - parsed_stuff = @parser.parse - - expected = - [ - { - :modifier => "static", - :args_string => "int a, unsigned int b", - :rettype => "int", - :var_arg => nil, - :args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}], - :name => "Foo" - }, - - { - :modifier => "inline", - :args_string => "uint la, int de, bool da", - :rettype => "bool", - :var_arg => nil, - :args => - [ - {:type => "uint", :name => "la"}, - {:type => "int", :name => "de"}, - {:type => "bool", :name => "da"} - ], - :name => "bar" - }, - - { - :modifier => "inline static __ramfunc", - :args_string => "uint thinger", - :rettype => "bool", - :var_arg => nil, - :args => - [ - {:type => "uint", :name => "thinger"}, - ], - :name => "bar" - } - ] - - assert_equal(expected, parsed_stuff[:functions]) - end - - should "extract and return function declarations with variable argument lists" do - - source = - "\tint \n printf(char * const format, ...);\n" + - "bool bar \n(...);\n" - - @parser = CMockHeaderParser.new(source, @config) - parsed_stuff = @parser.parse - - expected = - [ - { - :modifier => "", - :args_string => "char* const format", - :rettype => "int", - :var_arg => "...", - :args => [{:type => "char* const", :name => "format"}], - :name => "printf" - }, - { - :modifier => "", - :args_string => "void", - :rettype => "bool", - :var_arg => "...", - :args => [], - :name => "bar" - } - ] - - assert_equal(expected, parsed_stuff[:functions]) - end - - should "attach * to type" do - - source = - "MY_STRUCT* HooWah(char *** format);\n" + - "bool* HotShot(HIS_STRUCT **p, unsigned int* pint);\n" + - "bool * HotDog(BOW_WOW *p, unsigned int* pint);\n" + - "bool ** HotDog(BOW_WOW* p, unsigned int* pint);\n" + - "static bool *HotToTrot(unsigned int * struttin);\n" + - "static bool ***HotToTrot(unsigned int ** struttin);\n" - - @parser = CMockHeaderParser.new(source, @config) - parsed_stuff = @parser.parse - - expected = - [ - { - :modifier => "", - :args_string => "char*** format", - :rettype => "MY_STRUCT*", - :var_arg => nil, - :args => [{:type => "char***", :name => "format"}], - :name => "HooWah" - }, - - { - :modifier => "", - :args_string => "HIS_STRUCT** p, unsigned int* pint", - :rettype => "bool*", - :var_arg => nil, - :args => - [ - {:type => "HIS_STRUCT**", :name => "p"}, - {:type => "unsigned int*", :name => "pint"} - ], - :name => "HotShot" - }, + # should "extract and return function declarations" do + # + # source = + # "int Foo(int a, unsigned int b);\n" + + # "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" + + # # following lines should yield no function declarations: + # "#define get_foo() \\\n (Thing)foo())\n" + + # "ARRAY_TYPE array[((U8)10)];\n" + + # "THINGER_MASK = (0x0001 << 5),\n" + # + # @parser = CMockHeaderParser.new(@prototype_parser, source, @config) + # parsed_stuff = @parser.parse + # + # expected = + # [ + # { + # :modifier => "", + # :args_string => "int a, unsigned int b", + # :rettype => "int", + # :var_arg => nil, + # :args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}], + # :name => "Foo" + # }, + # + # { + # :modifier => "", + # :args_string => "uint la, int de, bool da", + # :rettype => "void", + # :var_arg => nil, + # :args => + # [ + # {:type => "uint", :name => "la"}, + # {:type => "int", :name => "de"}, + # {:type => "bool", :name => "da"} + # ], + # :name => "bar" + # }, + # + # { + # :modifier => "", + # :args_string => "uint la, int de, bool da", + # :rettype => "void", + # :var_arg => nil, + # :args => + # [ + # {:type => "uint", :name => "la"}, + # {:type => "int", :name => "de"}, + # {:type => "bool", :name => "da"} + # ], + # :name => "FunkyChicken" + # }, + # + # { + # :modifier => "", + # :args_string => "void", + # :rettype => "void", + # :var_arg => nil, + # :args => [], + # :name => "shiz" + # }, + # + # { + # :modifier => "", + # :args_string => "void", + # :rettype => "void", + # :var_arg => nil, + # :args => [], + # :name => "tat" + # } + # ] + # + # assert_equal(expected, parsed_stuff[:functions]) + # end + # + # should "extract and return function declarations with attributes" do + # + # source = + # "static \tint \n Foo(int a, unsigned int b);\n" + + # "inline\t bool bar \n(uint la, int de, bool da);\n" + + # "inline static __ramfunc bool bar ( uint thinger );\n" + # + # @parser = CMockHeaderParser.new(@prototype_parser, source, @config) + # parsed_stuff = @parser.parse + # + # expected = + # [ + # { + # :modifier => "static", + # :args_string => "int a, unsigned int b", + # :rettype => "int", + # :var_arg => nil, + # :args => [{:type => "int", :name => "a"}, {:type => "unsigned int", :name => "b"}], + # :name => "Foo" + # }, + # + # { + # :modifier => "inline", + # :args_string => "uint la, int de, bool da", + # :rettype => "bool", + # :var_arg => nil, + # :args => + # [ + # {:type => "uint", :name => "la"}, + # {:type => "int", :name => "de"}, + # {:type => "bool", :name => "da"} + # ], + # :name => "bar" + # }, + # + # { + # :modifier => "inline static __ramfunc", + # :args_string => "uint thinger", + # :rettype => "bool", + # :var_arg => nil, + # :args => + # [ + # {:type => "uint", :name => "thinger"}, + # ], + # :name => "bar" + # } + # ] + # + # assert_equal(expected, parsed_stuff[:functions]) + # end - { - :modifier => "", - :args_string => "BOW_WOW* p, unsigned int* pint", - :rettype => "bool*", - :var_arg => nil, - :args => - [ - {:type => "BOW_WOW*", :name => "p"}, - {:type => "unsigned int*", :name => "pint"} - ], - :name => "HotDog" - }, - - { - :modifier => "", - :args_string => "BOW_WOW* p, unsigned int* pint", - :rettype => "bool**", - :var_arg => nil, - :args => - [ - {:type => "BOW_WOW*", :name => "p"}, - {:type => "unsigned int*", :name => "pint"} - ], - :name => "HotDog" - }, - - { - :modifier => "static", - :args_string => "unsigned int* struttin", - :rettype => "bool*", - :var_arg => nil, - :args => - [ - {:type => "unsigned int*", :name => "struttin"} - ], - :name => "HotToTrot" - }, - - { - :modifier => "static", - :args_string => "unsigned int** struttin", - :rettype => "bool***", - :var_arg => nil, - :args => - [ - {:type => "unsigned int**", :name => "struttin"} - ], - :name => "HotToTrot" - } - ] - - assert_equal(expected, parsed_stuff[:functions]) - end - - should "extract and return function declarations with just types (no argument names)" do - - source = - "int buzzlightyear(char*, bool);\n" + - "bool woody();\n" + - "int slinkydog(bool thing, int (* const)(void));\n" + - "int andy(int* const);\n" - - @parser = CMockHeaderParser.new(source, @config) - parsed_stuff = @parser.parse - - expected = - [ - { - :modifier => "", - :args_string => "char* cmock_arg1, bool cmock_arg2", - :rettype => "int", - :var_arg => nil, - :args => - [ - {:type => "char*", :name => "cmock_arg1"}, - {:type => "bool", :name => "cmock_arg2"} - ], - :name => "buzzlightyear" - }, - - { - :modifier => "", - :args_string => "void", - :rettype => "bool", - :var_arg => nil, - :args => [], - :name => "woody" - }, - - { - :modifier => "", - :args_string => "bool thing, int (* const)(void) cmock_arg1", - :rettype => "int", - :var_arg => nil, - :args => - [ - {:type => "bool", :name => "thing"}, - {:type => "int (* const)(void)", :name => "cmock_arg1"} - ], - :name => "slinkydog" - }, - - { - :modifier => "", - :args_string => "int* const cmock_arg1", - :rettype => "int", - :var_arg => nil, - :args => - [ - {:type => "int* const", :name => "cmock_arg1"}, - ], - :name => "andy" - } - ] - - assert_equal(expected, parsed_stuff[:functions]) - end end \ No newline at end of file