node/lib/metasm/metasm/parse_c.rb
# checks that the types are compatible (variable predeclaration, function argument..)
# strict = false for func call/assignment (eg char compatible with int -- but int is incompatible with char)
# output warnings only
checks that the types are compatible (variable predeclaration, function argument..)
strict = false for func call/assignment
output warnings only
checks that the types are compatible ( variable predeclaration function argument .. ) strict = false for func call / assignment output warnings only
def check_compatible_type(tok, oldtype, newtype, strict = false, checked = [])
			return if not $VERBOSE
			oldtype = oldtype.untypedef
			newtype = newtype.untypedef
			oldtype = BaseType.new(:int) if oldtype.kind_of? Enum
			newtype = BaseType.new(:int) if newtype.kind_of? Enum
			puts tok.exception('type qualifier mismatch').message if oldtype.qualifier.to_a.uniq.length > newtype.qualifier.to_a.uniq.length
			return if checked.include? oldtype
			checked = checked + [oldtype]
		    begin
			case newtype
			when Function
				raise tok, 'type error' if not oldtype.kind_of? Function
				check_compatible_type tok, oldtype.type, newtype.type, strict, checked
				if oldtype.args and newtype.args
					if oldtype.args.length != newtype.args.length or
							oldtype.varargs != newtype.varargs
						raise tok, 'type error'
					end
					oldtype.args.zip(newtype.args) { |oa, na|
						check_compatible_type tok, oa.type, na.type, strict, checked
					}
				end
			when Pointer
				if oldtype.kind_of? BaseType and oldtype.integral?
					puts tok.exception('making pointer from integer without a cast').message
					return
				end
				raise tok, 'type error' if not oldtype.kind_of? Pointer
				hasvoid = true if (t = newtype.type.untypedef).kind_of? BaseType and t.name == :void
				hasvoid = true if (t = oldtype.type.untypedef).kind_of? BaseType and t.name == :void	
				if strict and not hasvoid
					check_compatible_type tok, oldtype.type, newtype.type, strict, checked
				end
			when Union
				raise tok, 'type error' if not oldtype.class == newtype.class
				if oldtype.members and newtype.members
					if oldtype.members.length != newtype.members.length
						raise tok, 'bad member count'
					end
					oldtype.members.zip(newtype.members) { |om, nm|
						check_compatible_type tok, om.type, nm.type, strict, checked
					}
				end
			when BaseType
				raise tok, 'type error' if not oldtype.kind_of? BaseType
				if strict
					if oldtype.name != newtype.name or
					oldtype.specifier != newtype.specifier
						raise tok, 'type error'
					end
				else
					raise tok, 'type error' if @typesize[newtype.name] == 0 and @typesize[oldtype.name] > 0
					puts tok.exception('type size mismatch, may lose bits').message if @typesize[oldtype.name] > @typesize[newtype.name]
					puts tok.exception('sign mismatch').message if oldtype.specifier != newtype.specifier and @typesize[newtype.name] == @typesize[oldtype.name]
				end
			end
		    rescue ParseError
			raise $! if checked.length != 1	
			oname = (oldtype.to_s rescue oldtype.class.name)
			nname = (newtype.to_s rescue newtype.class.name)
			puts $!.message + " incompatible type #{oname} to #{nname}"
		    end
		end
def check_compatible_type ( tok , oldtype , newtype , strict = false , checked = [ ] ) return if not $VERBOSE oldtype = oldtype . untypedef newtype = newtype . untypedef oldtype = BaseType . new ( :int ) if oldtype . kind_of? Enum newtype = BaseType . new ( :int ) if newtype . kind_of? Enum puts tok . exception ( 'type qualifier mismatch' ) . message if oldtype . qualifier . to_a . uniq . length > newtype . qualifier . to_a . uniq . length return if checked . include? oldtype checked = checked + [ oldtype ] begin case newtype when Function raise tok , 'type error' if not oldtype . kind_of? Function check_compatible_type tok , oldtype . type , newtype . type , strict , checked if oldtype . args and newtype . args if oldtype . args . length != newtype . args . length or oldtype . varargs != newtype . varargs raise tok , 'type error' end oldtype . args . zip ( newtype . args ) { | oa , na | check_compatible_type tok , oa . type , na . type , strict , checked } end when Pointer if oldtype . kind_of? BaseType and oldtype . integral? puts tok . exception ( 'making pointer from integer without a cast' ) . message return end raise tok , 'type error' if not oldtype . kind_of? Pointer hasvoid = true if ( t = newtype . type . untypedef ) . kind_of? BaseType and t . name == :void hasvoid = true if ( t = oldtype . type . untypedef ) . kind_of? BaseType and t . name == :void if strict and not hasvoid check_compatible_type tok , oldtype . type , newtype . type , strict , checked end when Union raise tok , 'type error' if not oldtype . class == newtype . class if oldtype . members and newtype . members if oldtype . members . length != newtype . members . length raise tok , 'bad member count' end oldtype . members . zip ( newtype . members ) { | om , nm | check_compatible_type tok , om . type , nm . type , strict , checked } end when BaseType raise tok , 'type error' if not oldtype . kind_of? BaseType if strict if oldtype . name != newtype . name or oldtype . specifier != newtype . specifier raise tok , 'type error' end else raise tok , 'type error' if @typesize [ newtype . name ] == 0 and @typesize [ oldtype . name ] > 0 puts tok . exception ( 'type size mismatch, may lose bits' ) . message if @typesize [ oldtype . name ] > @typesize [ newtype . name ] puts tok . exception ( 'sign mismatch' ) . message if oldtype . specifier != newtype . specifier and @typesize [ newtype . name ] == @typesize [ oldtype . name ] end end rescue ParseError raise $! if checked . length != 1 oname = ( oldtype . to_s rescue oldtype . class . name ) nname = ( newtype . to_s rescue newtype . class . name ) puts $! . message + " incompatible type #{oname} to #{nname}" end end
checks that the types are compatible (variable predeclaration, function argument..)
strict = false for func call/assignment (eg char compatible with int -- but int is incompatible with char)
output warnings only
checks that the types are compatible ( variable predeclaration function argument .. ) strict = false for func call / assignment ( eg char compatible with int -- but int is incompatible with char ) output warnings only
# avoid infinite recursion # begin ; rescue ParseError: raise $!.message + "in parameter #{oa.name}" end # struct foo *f = NULL; # raise tok if om.name and nm.name and om.name != nm.name # don't care # bubble up
tok
oldtype
newtype
strict
checked