node/lib/metasm/metasm/parse_c.rb
# updates @type and @name, parses pointer/arrays/function declarations
# parses anonymous declarators (@name will be false)
# the caller is responsible for detecting redefinitions
# scope used only in CExpression.parse for array sizes and function prototype argument types
# rec for internal use only
updates @type and @name, parses pointer/arrays/function declarations
parses anonymous declarators (@name will be false)
the caller is responsible for detecting redefinitions
scope used only in CExpression.parse for array sizes and function prototype argument types
rec for internal use only
updates @type and @name parses pointer / arrays / function declarations parses anonymous declarators ( @name will be false ) the caller is responsible for detecting redefinitions scope used only in CExpression . parse for array sizes and function prototype argument types rec for internal use only
def parse_declarator(parser, scope, rec = false)
			parse_attributes(parser, true)
			tok = parser.skipspaces
			if tok and tok.type == :punct and tok.raw == '*'
				ptr = Pointer.new
				ptr.parse_attributes(parser)
				while ntok = parser.skipspaces and ntok.type == :string
					case ntok.raw
					when 'const', 'volatile'
						(ptr.qualifier ||= []) << ntok.raw.to_sym
						ptr.parse_attributes(parser)
					else break
					end
				end
				parser.unreadtok ntok
				parse_declarator(parser, scope, true)
				t = self
				t = t.type while t.type and (t.type.kind_of?(Pointer) or t.type.kind_of?(Function))
				ptr.type = t.type
				t.type = ptr
				if t.kind_of? Function and ptr.attributes
					@attributes ||= []
					@attributes |= ptr.attributes
					ptr.attributes = nil
				end
				return
			elsif tok and tok.type == :punct and tok.raw == '('
				parse_declarator(parser, scope, true)
				raise tok || parser, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
			elsif tok and tok.type == :string
				case tok.raw
				when 'const', 'volatile'
					(@type.qualifier ||= []) << tok.raw.to_sym
					return parse_declarator(parser, scope, rec)
				when 'register', 'auto', 'static', 'typedef', 'extern'
					raise tok, 'multiple storage class' if storage
					@storage = tok.raw.to_sym
					puts tok.exception('misplaced storage specifier').message if $VERBOSE
					return parse_declarator(parser, scope, rec)
				end
				raise tok if name or name == false
				raise tok, 'bad var name' if Keyword[tok.raw] or (?0..?9).include?(tok.raw[0])
				@name = tok.raw
				@backtrace = tok
				parse_attributes(parser, true)
			else
				raise tok || parser if name or name == false
				@name = false
				@backtrace = tok
				parser.unreadtok tok
				parse_attributes(parser, true)
			end
			parse_declarator_postfix(parser, scope)
			if not rec
				raise @backtrace, 'void type is invalid' if name and (t = @type.untypedef).kind_of? BaseType and
						t.name == :void and storage != :typedef
				raise @backtrace, "incomplete type #{@type.name}" if (@type.kind_of? Union or @type.kind_of? Enum) and
						not @type.members and storage != :typedef and storage != :extern	
			end
		end
def parse_declarator ( parser , scope , rec = false ) parse_attributes ( parser , true ) tok = parser . skipspaces if tok and tok . type == :punct and tok . raw == '*' ptr = Pointer . new ptr . parse_attributes ( parser ) while ntok = parser . skipspaces and ntok . type == :string case ntok . raw when 'const' , 'volatile' ( ptr . qualifier ||= [ ] ) << ntok . raw . to_sym ptr . parse_attributes ( parser ) else break end end parser . unreadtok ntok parse_declarator ( parser , scope , true ) t = self t = t . type while t . type and ( t . type . kind_of? ( Pointer ) or t . type . kind_of? ( Function ) ) ptr . type = t . type t . type = ptr if t . kind_of? Function and ptr . attributes @attributes ||= [ ] @attributes |= ptr . attributes ptr . attributes = nil end return elsif tok and tok . type == :punct and tok . raw == '(' parse_declarator ( parser , scope , true ) raise tok || parser , '")" expected' if not tok = parser . skipspaces or tok . type != :punct or tok . raw != ')' elsif tok and tok . type == :string case tok . raw when 'const' , 'volatile' ( @type . qualifier ||= [ ] ) << tok . raw . to_sym return parse_declarator ( parser , scope , rec ) when 'register' , 'auto' , 'static' , 'typedef' , 'extern' raise tok , 'multiple storage class' if storage @storage = tok . raw . to_sym puts tok . exception ( 'misplaced storage specifier' ) . message if $VERBOSE return parse_declarator ( parser , scope , rec ) end raise tok if name or name == false raise tok , 'bad var name' if Keyword [ tok . raw ] or ( ?0 .. ?9 ) . include? ( tok . raw [ 0 ] ) @name = tok . raw @backtrace = tok parse_attributes ( parser , true ) else raise tok || parser if name or name == false @name = false @backtrace = tok parser . unreadtok tok parse_attributes ( parser , true ) end parse_declarator_postfix ( parser , scope ) if not rec raise @backtrace , 'void type is invalid' if name and ( t = @type . untypedef ) . kind_of? BaseType and t . name == :void and storage != :typedef raise @backtrace , "incomplete type #{@type.name}" if ( @type . kind_of? Union or @type . kind_of? Enum ) and not @type . members and storage != :typedef and storage != :extern end end
updates @type and @name, parses pointer/arrays/function declarations
parses anonymous declarators (@name will be false)
the caller is responsible for detecting redefinitions
scope used only in CExpression.parse for array sizes and function prototype argument types
rec for internal use only
updates @type and @name parses pointer / arrays / function declarations parses anonymous declarators ( @name will be false ) the caller is responsible for detecting redefinitions scope used only in CExpression . parse for array sizes and function prototype argument types rec for internal use only
# read upto name # unnamed # gcc uses an undefined extern struct just to cast it later (_IO_FILE_plus)
parser
scope
rec