added support: 'struct' qualifiers for pointers in argument lists, const function pointers, added more type tests

git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@97 bf332499-1b4d-0410-844d-d2d48d5cc64c
This commit is contained in:
mkarlesky
2009-05-15 00:57:26 +00:00
parent f63c2b4fc8
commit 153b8b9000
7 changed files with 380 additions and 195 deletions
+1 -2
View File
@@ -1,4 +1,3 @@
ROOT_PATH = File.expand_path(File.dirname(__FILE__) + "/../")
# Setup our load path:
[
@@ -6,7 +5,7 @@ ROOT_PATH = File.expand_path(File.dirname(__FILE__) + "/../")
'vendor/gems/polyglot-0.2.5/lib/',
'vendor/gems/treetop-1.2.5/lib/',
].each do |dir|
$LOAD_PATH.unshift(File.join(ROOT_PATH, dir))
$LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__) + "/../"), dir) )
end
require 'rubygems'
+1 -2
View File
@@ -1,4 +1,3 @@
ROOT_PATH = File.expand_path(File.dirname(__FILE__) + "/../")
# Setup our load path:
[
@@ -10,5 +9,5 @@ ROOT_PATH = File.expand_path(File.dirname(__FILE__) + "/../")
'vendor/gems/treetop-1.2.5/lib/',
'test/system/'
].each do |dir|
$LOAD_PATH.unshift(File.join(ROOT_PATH, dir))
$LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__) + "/../"), dir) )
end
+31 -5
View File
@@ -47,10 +47,12 @@ module CMockFunctionPrototype
class FunctionPrototypeFunctionPointerReturnNode < Treetop::Runtime::SyntaxNode
def get_declaration
return "#{return_type.text_value} (* const #{get_function_name}#{function_arglist.normalized_argument_list})#{function_return_arglist.normalized_argument_list}" if not (const.text_value.blank?)
return "#{return_type.text_value} (*#{get_function_name}#{function_arglist.normalized_argument_list})#{function_return_arglist.normalized_argument_list}"
end
def get_return_type
return "#{return_type.text_value} (* const)#{function_return_arglist.normalized_argument_list}" if not (const.text_value.blank?)
return "#{return_type.text_value} (*)#{function_return_arglist.normalized_argument_list}"
end
@@ -72,10 +74,18 @@ module CMockFunctionPrototype
def get_typedefs
type_name = "FUNC_PTR_#{get_function_name.upcase}_RETURN_T"
if (const.text_value.blank?)
return [
{ :type => get_return_type,
:typename => type_name,
:typedef => "typedef #{return_type.text_value} (*#{type_name})#{function_return_arglist.normalized_argument_list};" }]
end
return [
{ :type => get_return_type,
:typename => type_name,
:typedef => "typedef #{return_type.text_value} (*#{type_name})#{function_return_arglist.normalized_argument_list};" }]
:typedef => "typedef #{return_type.text_value} (* const #{type_name})#{function_return_arglist.normalized_argument_list};" }]
end
end
@@ -168,6 +178,7 @@ module CMockFunctionPrototype
include FunctionPrototypeUtils
def text_value
return "#{return_type.text_value} (* const #{name.text_value})#{argument_list.normalized_argument_list}" if not (const.text_value.blank?)
return "#{return_type.text_value} (*#{name.text_value})#{argument_list.normalized_argument_list}"
end
@@ -178,11 +189,18 @@ module CMockFunctionPrototype
func_ptr_name = make_cmock_arg_name(arg_list_index)
end
return "#{return_type.text_value} (* const #{func_ptr_name})#{argument_list.normalized_argument_list}" if not (const.text_value.blank?)
return "#{return_type.text_value} (*#{func_ptr_name})#{argument_list.normalized_argument_list}"
end
def type_and_name_token_hash(arg_list_index, function_name)
type = "#{return_type.text_value} (*)#{argument_list.normalized_argument_list}"
type = ''
if (const.text_value.blank?)
type = "#{return_type.text_value} (*)#{argument_list.normalized_argument_list}"
else
type = "#{return_type.text_value} (* const)#{argument_list.normalized_argument_list}"
end
return { :type => type, :name => make_cmock_arg_name(arg_list_index) } if (name.text_value.blank?)
return { :type => type, :name => name.text_value }
@@ -190,10 +208,18 @@ module CMockFunctionPrototype
def typedef_hash(arg_list_index, function_name)
typename = "FUNC_PTR_#{function_name.upcase}_PARAM_#{arg_list_index+1}_T"
type = "#{return_type.text_value} (*)#{argument_list.normalized_argument_list}"
typedef = "typedef #{return_type.text_value} (*#{typename})#{argument_list.normalized_argument_list};"
return { :type => type, :typename => typename, :typedef => typedef }
if (const.text_value.blank?)
type = "#{return_type.text_value} (*)#{argument_list.normalized_argument_list}"
typedef = "typedef #{return_type.text_value} (*#{typename})#{argument_list.normalized_argument_list};"
return { :type => type, :typename => typename, :typedef => typedef }
end
type = "#{return_type.text_value} (* const)#{argument_list.normalized_argument_list}"
typedef = "typedef #{return_type.text_value} (* const #{typename})#{argument_list.normalized_argument_list};"
return { :type => type, :typename => typename, :typedef => typedef }
end
end
+292 -168
View File
@@ -91,21 +91,25 @@ module CMockFunctionPrototype
elements[2]
end
def name
def const
elements[3]
end
def function_arglist
def name
elements[4]
end
def right_paren
def function_arglist
elements[5]
end
def function_return_arglist
def right_paren
elements[6]
end
def function_return_arglist
elements[7]
end
end
def _nt_function_prototype_function_pointer_return
@@ -126,17 +130,26 @@ module CMockFunctionPrototype
r3 = _nt_asterisk
s0 << r3
if r3
r4 = _nt_name
r5 = _nt_const
if r5
r4 = r5
else
r4 = instantiate_node(SyntaxNode,input, index...index)
end
s0 << r4
if r4
r5 = _nt_argument_list
s0 << r5
if r5
r6 = _nt_right_paren
s0 << r6
if r6
r7 = _nt_argument_list
s0 << r7
r6 = _nt_name
s0 << r6
if r6
r7 = _nt_argument_list
s0 << r7
if r7
r8 = _nt_right_paren
s0 << r8
if r8
r9 = _nt_argument_list
s0 << r9
end
end
end
end
@@ -353,17 +366,21 @@ module CMockFunctionPrototype
elements[2]
end
def name
def const
elements[3]
end
def right_paren
def name
elements[4]
end
def argument_list
def right_paren
elements[5]
end
def argument_list
elements[6]
end
end
def _nt_func_ptr_prototype
@@ -384,7 +401,7 @@ module CMockFunctionPrototype
r3 = _nt_asterisk
s0 << r3
if r3
r5 = _nt_name
r5 = _nt_const
if r5
r4 = r5
else
@@ -392,11 +409,20 @@ module CMockFunctionPrototype
end
s0 << r4
if r4
r6 = _nt_right_paren
r7 = _nt_name
if r7
r6 = r7
else
r6 = instantiate_node(SyntaxNode,input, index...index)
end
s0 << r6
if r6
r7 = _nt_argument_list
s0 << r7
r8 = _nt_right_paren
s0 << r8
if r8
r9 = _nt_argument_list
s0 << r9
end
end
end
end
@@ -491,9 +517,30 @@ module CMockFunctionPrototype
def space
elements[1]
end
def name
elements[2]
end
end
module Type1
def space
elements[1]
end
end
module Type2
end
module Type3
def name
elements[0]
end
end
module Type4
end
def _nt_type
@@ -514,173 +561,250 @@ module CMockFunctionPrototype
s0 << r1
if r1
i3 = index
s4, i4 = [], index
loop do
i5, s5 = index, []
i6 = index
if input.index('void', index) == index
r7 = instantiate_node(SyntaxNode,input, index...(index + 4))
@index += 4
else
terminal_parse_failure('void')
r7 = nil
end
if r7
r6 = r7
else
if input.index('unsigned', index) == index
r8 = instantiate_node(SyntaxNode,input, index...(index + 8))
@index += 8
else
terminal_parse_failure('unsigned')
r8 = nil
end
if r8
r6 = r8
else
if input.index('signed', index) == index
r9 = instantiate_node(SyntaxNode,input, index...(index + 6))
@index += 6
else
terminal_parse_failure('signed')
r9 = nil
end
if r9
r6 = r9
else
if input.index('long', index) == index
r10 = instantiate_node(SyntaxNode,input, index...(index + 4))
@index += 4
else
terminal_parse_failure('long')
r10 = nil
end
if r10
r6 = r10
else
if input.index('int', index) == index
r11 = instantiate_node(SyntaxNode,input, index...(index + 3))
@index += 3
else
terminal_parse_failure('int')
r11 = nil
end
if r11
r6 = r11
else
if input.index('short', index) == index
r12 = instantiate_node(SyntaxNode,input, index...(index + 5))
@index += 5
else
terminal_parse_failure('short')
r12 = nil
end
if r12
r6 = r12
else
if input.index('char', index) == index
r13 = instantiate_node(SyntaxNode,input, index...(index + 4))
@index += 4
else
terminal_parse_failure('char')
r13 = nil
end
if r13
r6 = r13
else
if input.index('float', index) == index
r14 = instantiate_node(SyntaxNode,input, index...(index + 5))
@index += 5
else
terminal_parse_failure('float')
r14 = nil
end
if r14
r6 = r14
else
if input.index('double', index) == index
r15 = instantiate_node(SyntaxNode,input, index...(index + 6))
@index += 6
else
terminal_parse_failure('double')
r15 = nil
end
if r15
r6 = r15
else
self.index = i6
r6 = nil
end
end
end
end
end
end
end
end
end
s5 << r6
i4, s4 = index, []
if input.index('struct', index) == index
r5 = instantiate_node(SyntaxNode,input, index...(index + 6))
@index += 6
else
terminal_parse_failure('struct')
r5 = nil
end
s4 << r5
if r5
r6 = _nt_space
s4 << r6
if r6
r16 = _nt_space
s5 << r16
end
if s5.last
r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
r5.extend(Type0)
else
self.index = i5
r5 = nil
end
if r5
s4 << r5
else
break
r7 = _nt_name
s4 << r7
if r7
s8, i8 = [], index
loop do
r9 = _nt_asterisk
if r9
s8 << r9
else
break
end
end
if s8.empty?
self.index = i8
r8 = nil
else
r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
end
s4 << r8
end
end
end
if s4.empty?
if s4.last
r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
r4.extend(Type0)
else
self.index = i4
r4 = nil
else
r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
end
if r4
r3 = r4
else
r17 = _nt_name
if r17
r3 = r17
else
self.index = i3
r3 = nil
end
end
s0 << r3
if r3
s18, i18 = [], index
i10, s10 = index, []
s11, i11 = [], index
loop do
r19 = _nt_asterisk
if r19
s18 << r19
i12, s12 = index, []
i13 = index
if input.index('void', index) == index
r14 = instantiate_node(SyntaxNode,input, index...(index + 4))
@index += 4
else
terminal_parse_failure('void')
r14 = nil
end
if r14
r13 = r14
else
if input.index('unsigned', index) == index
r15 = instantiate_node(SyntaxNode,input, index...(index + 8))
@index += 8
else
terminal_parse_failure('unsigned')
r15 = nil
end
if r15
r13 = r15
else
if input.index('signed', index) == index
r16 = instantiate_node(SyntaxNode,input, index...(index + 6))
@index += 6
else
terminal_parse_failure('signed')
r16 = nil
end
if r16
r13 = r16
else
if input.index('long', index) == index
r17 = instantiate_node(SyntaxNode,input, index...(index + 4))
@index += 4
else
terminal_parse_failure('long')
r17 = nil
end
if r17
r13 = r17
else
if input.index('int', index) == index
r18 = instantiate_node(SyntaxNode,input, index...(index + 3))
@index += 3
else
terminal_parse_failure('int')
r18 = nil
end
if r18
r13 = r18
else
if input.index('short', index) == index
r19 = instantiate_node(SyntaxNode,input, index...(index + 5))
@index += 5
else
terminal_parse_failure('short')
r19 = nil
end
if r19
r13 = r19
else
if input.index('char', index) == index
r20 = instantiate_node(SyntaxNode,input, index...(index + 4))
@index += 4
else
terminal_parse_failure('char')
r20 = nil
end
if r20
r13 = r20
else
if input.index('float', index) == index
r21 = instantiate_node(SyntaxNode,input, index...(index + 5))
@index += 5
else
terminal_parse_failure('float')
r21 = nil
end
if r21
r13 = r21
else
if input.index('double', index) == index
r22 = instantiate_node(SyntaxNode,input, index...(index + 6))
@index += 6
else
terminal_parse_failure('double')
r22 = nil
end
if r22
r13 = r22
else
self.index = i13
r13 = nil
end
end
end
end
end
end
end
end
end
s12 << r13
if r13
r23 = _nt_space
s12 << r23
end
if s12.last
r12 = instantiate_node(SyntaxNode,input, i12...index, s12)
r12.extend(Type1)
else
self.index = i12
r12 = nil
end
if r12
s11 << r12
else
break
end
end
r18 = instantiate_node(SyntaxNode,input, i18...index, s18)
s0 << r18
if r18
r21 = _nt_const
if r21
r20 = r21
else
r20 = instantiate_node(SyntaxNode,input, index...index)
end
s0 << r20
if s11.empty?
self.index = i11
r11 = nil
else
r11 = instantiate_node(SyntaxNode,input, i11...index, s11)
end
s10 << r11
if r11
s24, i24 = [], index
loop do
r25 = _nt_asterisk
if r25
s24 << r25
else
break
end
end
r24 = instantiate_node(SyntaxNode,input, i24...index, s24)
s10 << r24
end
if s10.last
r10 = instantiate_node(SyntaxNode,input, i10...index, s10)
r10.extend(Type2)
else
self.index = i10
r10 = nil
end
if r10
r3 = r10
else
i26, s26 = index, []
r27 = _nt_name
s26 << r27
if r27
s28, i28 = [], index
loop do
r29 = _nt_asterisk
if r29
s28 << r29
else
break
end
end
r28 = instantiate_node(SyntaxNode,input, i28...index, s28)
s26 << r28
end
if s26.last
r26 = instantiate_node(SyntaxNode,input, i26...index, s26)
r26.extend(Type3)
else
self.index = i26
r26 = nil
end
if r26
r3 = r26
else
self.index = i3
r3 = nil
end
end
end
s0 << r3
if r3
r31 = _nt_const
if r31
r30 = r31
else
r30 = instantiate_node(SyntaxNode,input, index...index)
end
s0 << r30
end
end
if s0.last
r0 = instantiate_node(TypeNode,input, i0...index, s0)
r0.extend(Type1)
r0.extend(Type4)
else
self.index = i0
r0 = nil
+11 -4
View File
@@ -10,10 +10,12 @@ grammar CMockFunctionPrototype
rule function_prototype_function_pointer_return
# ex. float (*GetPtr(const char opCode))(float, float)
return_type left_paren asterisk name function_arglist:argument_list right_paren function_return_arglist:argument_list <FunctionPrototypeFunctionPointerReturnNode>
# const: tag so we can always access its nodes in programming even if blank.
return_type left_paren asterisk const:const? name function_arglist:argument_list right_paren function_return_arglist:argument_list <FunctionPrototypeFunctionPointerReturnNode>
end
rule return_type
# void is different than the type possibility 'void*'
void / type
end
@@ -35,8 +37,8 @@ grammar CMockFunctionPrototype
rule func_ptr_prototype
# ex. int (*funcPtr)(float, char, char)
# add name: tag to name? so we can always access it in programming even if blank.
return_type left_paren asterisk name:name? right_paren argument_list <FunctionPointerNode>
# const: & name: tags so we can always access their nodes in programming even if blank.
return_type left_paren asterisk const:const? name:name? right_paren argument_list <FunctionPointerNode>
end
rule type_and_name
@@ -47,7 +49,12 @@ grammar CMockFunctionPrototype
end
rule type
const? ((('void' / 'unsigned' / 'signed' / 'long' / 'int' / 'short' / 'char' / 'float' / 'double') space)+ / name) (asterisk)* const? <TypeNode>
# be careful in here with parens; placement and grouping is important
const?
(('struct' space name asterisk+) /
((('void' / 'unsigned' / 'signed' / 'long' / 'int' / 'short' / 'char' / 'float' / 'double') space)+ asterisk*) /
(name asterisk*))
const? <TypeNode>
end
rule name
+3 -2
View File
@@ -1,6 +1,5 @@
require 'yaml'
require 'fileutils'
require 'cmock'
require 'generate_test_runner'
require 'unity_test_summary'
require 'systest_generator'
@@ -164,7 +163,9 @@ module RakefileHelpers
summary.run
end
def run_systests(test_case_files)
def run_systests(test_case_files)
require 'cmock'
SystemTestGenerator.new.generate_files(test_case_files)
test_files = FileList.new(SYSTEST_GENERATED_FILES_PATH + 'test*.c')
@@ -78,7 +78,7 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
end
should "parse out simple arguments from an argument list into an array of hashes" do
should "parse out arguments from an argument list into an array of hashes" do
# function pointers & var args tested elsewhere
# void is a special argument that yields no params to mock
@@ -101,7 +101,23 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
{:type => 'unsigned int', :name => 'b'}],
parsed.get_arguments)
assert_nil(parsed.get_var_arg)
parsed = @parser.parse("void foo_bar(double a, float b, unsigned short c)")
assert_equal('double a, float b, unsigned short c', parsed.get_argument_list)
assert_equal([
{:type => 'double', :name => 'a'},
{:type => 'float', :name => 'b'},
{:type => 'unsigned short', :name => 'c'}],
parsed.get_arguments)
assert_nil(parsed.get_var_arg)
parsed = @parser.parse("void foo_bar(struct THINGER * a)")
assert_equal('struct THINGER* a', parsed.get_argument_list)
assert_equal([
{:type => 'struct THINGER*', :name => 'a'}],
parsed.get_arguments)
assert_nil(parsed.get_var_arg)
parsed = @parser.parse("void foo_bar(unsigned char * abc, const unsigned long int xyz_123)")
assert_equal('unsigned char* abc, const unsigned long int xyz_123', parsed.get_argument_list)
assert_equal([
@@ -194,43 +210,56 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
# handle this? --> "int slinkydog(bool thing, int (* const)(void));\n" +
parsed = @parser.parse("void thing(int (*func_ptr)(int, int))")
assert_equal('void thing( int (*func_ptr)( int, int ) )', parsed.get_declaration)
assert_equal('int (*func_ptr)( int, int )', parsed.get_argument_list)
assert_equal(
[{:type => 'int (*)( int, int )', :name => 'func_ptr'}],
parsed.get_arguments)
parsed = @parser.parse("void foo(int (* const func_ptr)(int, int))")
assert_equal('void foo( int (* const func_ptr)( int, int ) )', parsed.get_declaration)
assert_equal('int (* const func_ptr)( int, int )', parsed.get_argument_list)
assert_equal(
[{:type => 'int (* const)( int, int )', :name => 'func_ptr'}],
parsed.get_arguments)
parsed = @parser.parse("void foo_bar(void * (*func)(int *, unsigned long int, ...))")
assert_equal('void foo_bar( void* (*func)( int*, unsigned long int, ... ) )', parsed.get_declaration)
assert_equal('void* (*func)( int*, unsigned long int, ... )', parsed.get_argument_list)
assert_equal(
[{:type => 'void* (*)( int*, unsigned long int, ... )', :name => 'func'}],
parsed.get_arguments)
parsed = @parser.parse("void foo_bar(int (* func1)(int a, char b), void (*func2)(void))")
assert_equal('int (*func1)( int a, char b ), void (*func2)(void)', parsed.get_argument_list)
parsed = @parser.parse("void foo_bar(int (* func1)(int, char), void (*func2)(void))")
assert_equal('void foo_bar( int (*func1)( int, char ), void (*func2)(void) )', parsed.get_declaration)
assert_equal('int (*func1)( int, char ), void (*func2)(void)', parsed.get_argument_list)
assert_equal(
[{:type => 'int (*)( int a, char b )', :name => 'func1'},
[{:type => 'int (*)( int, char )', :name => 'func1'},
{:type => 'void (*)(void)', :name => 'func2'}],
parsed.get_arguments)
# directly returning function pointers (i.e. no typedef)
parsed = @parser.parse("float (*func(const char opCode))(float, float)")
assert_equal('float (*func( const char opCode ))( float, float )', parsed.get_declaration)
assert_equal('float (*)( float, float )', parsed.get_return_type)
parsed = @parser.parse("void (*func (void))(void)")
assert_equal('void (*)(void)', parsed.get_return_type)
parsed = @parser.parse("void (* const func (void))(void)")
assert_equal('void (* const func(void))(void)', parsed.get_declaration)
assert_equal('void (* const)(void)', parsed.get_return_type)
parsed = @parser.parse("unsigned int * (* func(double foo, THING bar))(unsigned int a)")
assert_equal('unsigned int* (*func( double foo, THING bar ))( unsigned int a )', parsed.get_declaration)
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, ...))")
parsed = @parser.parse("void foo_bar(unsigned int a, void (* const func)(int *, unsigned long int, ...))")
assert_equal(
[{:type => 'void (*)( int*, unsigned long int, ... )',
[{:type => 'void (* const)( int*, unsigned long int, ... )',
:typename => 'FUNC_PTR_FOO_BAR_PARAM_2_T',
:typedef => 'typedef void (*FUNC_PTR_FOO_BAR_PARAM_2_T)( int*, unsigned long int, ... );'}],
:typedef => 'typedef void (* const FUNC_PTR_FOO_BAR_PARAM_2_T)( int*, unsigned long int, ... );'}],
parsed.get_typedefs)
parsed = @parser.parse("void test_func(void (*)(int, char), unsigned int (*)(void))")
@@ -244,11 +273,11 @@ class CMockFunctionPrototypeParserTest < Test::Unit::TestCase
parsed.get_typedefs)
# function prototype return type handling
parsed = @parser.parse("void (*func (void))(void)")
parsed = @parser.parse("void (* const func (void))(void)")
assert_equal(
[{:type => 'void (*)(void)',
[{:type => 'void (* const)(void)',
:typename => 'FUNC_PTR_FUNC_RETURN_T',
:typedef => 'typedef void (*FUNC_PTR_FUNC_RETURN_T)(void);'}],
:typedef => 'typedef void (* const FUNC_PTR_FUNC_RETURN_T)(void);'}],
parsed.get_typedefs)
parsed = @parser.parse("unsigned int * (* func(double foo, THING bar))(unsigned int, ...)")