PageRenderTime 84ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/metasm/metasm/parse_c.rb

https://github.com/Jonono2/metasploit-framework
Ruby | 4043 lines | 3600 code | 229 blank | 214 comment | 1162 complexity | c00ccb6d0a1677da4a9e23c86e7331a8 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, GPL-3.0, LGPL-2.1, GPL-2.0
  1. # This file is part of Metasm, the Ruby assembly manipulation suite
  2. # Copyright (C) 2006-2009 Yoann GUILLOT
  3. #
  4. # Licence is LGPL, see LICENCE in the top-level directory
  5. require 'metasm/main'
  6. require 'metasm/preprocessor'
  7. module Metasm
  8. # c parser
  9. # inspired from http://www.math.grin.edu/~stone/courses/languages/C-syntax.xhtml
  10. module C
  11. Keyword = %w[struct union enum if else for while do switch goto
  12. register extern auto static typedef const volatile
  13. void int float double char signed unsigned long short
  14. case continue break return default __attribute__
  15. asm __asm __asm__ sizeof typeof
  16. __declspec __cdecl __stdcall __fastcall __noreturn
  17. inline __inline __inline__ __volatile__
  18. __int8 __int16 __int32 __int64
  19. __builtin_offsetof
  20. ].inject({}) { |h, w| h.update w => true }
  21. class Statement
  22. end
  23. module Typed # allows quick testing whether an object is an CExpr or a Variable
  24. end
  25. class Block < Statement
  26. attr_accessor :symbol # hash name => Type/Variable/enum value
  27. attr_accessor :struct # hash name => Struct/Union/Enum
  28. attr_accessor :outer # parent block
  29. attr_accessor :statements # array of Statement/Declaration
  30. attr_accessor :anonymous_enums # array of anonymous Enum
  31. def initialize(outer, statements=[], symbol={}, struct={})
  32. @outer = outer
  33. @statements = statements
  34. @symbol = symbol
  35. @struct = struct
  36. end
  37. def struct_ancestors
  38. @outer ? @outer.struct_ancestors.merge(@struct) : @struct
  39. end
  40. def symbol_ancestors
  41. @outer ? @outer.symbol_ancestors.merge(@symbol) : @symbol
  42. end
  43. end
  44. module Attributes
  45. attr_accessor :attributes
  46. DECLSPECS = %w[cdecl stdcall fastcall inline naked thiscall noreturn]
  47. # parses a sequence of __attribute__((anything)) into self.attributes (array of string)
  48. def parse_attributes(parser, allow_declspec = false)
  49. while tok = parser.skipspaces and tok.type == :string
  50. case keyword = tok.raw
  51. when '__attribute__', '__declspec' # synonymous: __attribute__((foo)) == __declspec(foo)
  52. raise tok || parser if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '('
  53. raise tok || parser if keyword == '__attribute__' and (not tok = parser.skipspaces or tok.type != :punct or tok.raw != '(')
  54. nest = 0
  55. attrib = ''
  56. loop do
  57. raise parser if not tok = parser.skipspaces
  58. if tok.type == :punct and tok.raw == ')'
  59. if nest == 0
  60. raise tok || parser if keyword == '__attribute__' and (not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')')
  61. break
  62. else
  63. nest -= 1
  64. end
  65. elsif tok.type == :punct and tok.raw == '('
  66. nest += 1
  67. elsif nest == 0 and tok.type == :punct and tok.raw == ','
  68. raise tok || parser if not allow_declspec and DECLSPECS.include? attrib
  69. add_attribute attrib
  70. attrib = ''
  71. next
  72. end
  73. attrib << tok.raw
  74. end
  75. raise tok || parser, "attr #{attrib.inspect} not allowed here" if not allow_declspec and DECLSPECS.include? attrib
  76. else
  77. if allow_declspec and DECLSPECS.include? keyword.gsub('_', '')
  78. attrib = keyword.gsub('_', '')
  79. else break
  80. end
  81. end
  82. add_attribute(attrib)
  83. end
  84. parser.unreadtok tok
  85. end
  86. # checks if the object has an attribute in its attribute list
  87. def has_attribute(attr)
  88. attributes.to_a.include? attr
  89. end
  90. # adds an attribute to the object attribute list if it is not already in it
  91. def add_attribute(attr)
  92. (@attributes ||= []) << attr if not has_attribute(attr)
  93. end
  94. # checks if the object has an attributes a la __attribute__((attr(stuff))), returns 'stuff' (raw, no split on ',' or anything)
  95. def has_attribute_var(attr)
  96. $1 if attributes.to_a.find { |a| a =~ /^#{attr}\((.*)\)$/ }
  97. end
  98. end
  99. class Type
  100. include Attributes
  101. attr_accessor :qualifier # const volatile
  102. def pointer? ; false end
  103. def arithmetic? ; false end
  104. def integral? ; false end
  105. def float? ; false end
  106. def void? ; false end
  107. def base ; self end
  108. def untypedef ; self end
  109. def parse_initializer(parser, scope)
  110. raise parser, 'expr expected' if not ret = CExpression.parse(parser, scope, false)
  111. p, i = pointer?, integral?
  112. r = ret.reduce(parser) if p or i
  113. if (not p and not i) or (i and not r.kind_of? ::Integer) or (p and r != 0)
  114. parser.check_compatible_type(parser, ret.type, self)
  115. end
  116. ret
  117. end
  118. def parse_initializer_designator(parser, scope, value, idx, root=true)
  119. if not root and (not nt = parser.skipspaces or nt.type != :punct or nt.raw != '=')
  120. raise nt || parser, '"=" expected'
  121. end
  122. value[idx] = parse_initializer(parser, scope)
  123. idx + 1
  124. end
  125. end
  126. class BaseType < Type
  127. attr_accessor :name # :int :long :longlong :short :double :longdouble :float :char :void :__int8/16/32/64
  128. attr_accessor :specifier # sign specifier only
  129. def arithmetic? ; @name != :void end
  130. def integral? ; [:char, :short, :int, :long, :longlong, :ptr,
  131. :__int8, :__int16, :__int32, :__int64].include? @name end
  132. def signed? ; specifier != :unsigned end
  133. def float? ; [:float, :double, :longdouble].include? @name end
  134. def void? ; @name == :void end
  135. def align(parser) @name == :double ? 4 : parser.typesize[@name] end
  136. def initialize(name, *specs)
  137. @name = name
  138. specs.each { |s|
  139. case s
  140. when :const, :volatile; (@qualifier ||= []) << s
  141. when :signed, :unsigned; @specifier = s
  142. when nil
  143. else raise "internal error, got #{name.inspect} #{specs.inspect}"
  144. end
  145. }
  146. end
  147. def ==(o)
  148. o.object_id == self.object_id or
  149. (o.class == self.class and o.name == self.name and o.specifier == self.specifier and o.attributes == self.attributes)
  150. end
  151. end
  152. class TypeDef < Type
  153. attr_accessor :name
  154. attr_accessor :type
  155. attr_accessor :backtrace
  156. def initialize(name, type, backtrace)
  157. @name, @type, @backtrace = name, type, backtrace
  158. end
  159. def parse_initializer(parser, scope)
  160. @type.parse_initializer(parser, scope)
  161. end
  162. def pointer? ; @type.pointer? end
  163. def arithmetic? ; @type.arithmetic? end
  164. def integral? ; @type.integral? end
  165. def signed? ; @type.signed? end # relevant only if integral? returns true
  166. def float? ; @type.float? end
  167. def void? ; @type.void? end
  168. def untypedef ; @type.untypedef end
  169. def align(parser) @type.align(parser) end # XXX __attribute__ ?
  170. def pointed ; @type.pointed end
  171. end
  172. class Function < Type
  173. attr_accessor :type # return type
  174. attr_accessor :args # [name, Variable]
  175. attr_accessor :varargs # true/false
  176. def initialize(type=nil, args=nil)
  177. @type = type
  178. @args = args if args
  179. end
  180. def base ; @type.base ; end
  181. end
  182. class Union < Type
  183. attr_accessor :members # [Variable]
  184. attr_accessor :bits # [bits] or nil
  185. attr_accessor :name
  186. attr_accessor :backtrace
  187. attr_accessor :fldoffset, :fldbitoffset, :fldlist
  188. def align(parser) @members.to_a.map { |m| m.type.align(parser) }.max end
  189. # there is only one instance of a given named struct per parser
  190. # so we just compare struct names here
  191. # for comparison between parsers, see #compare_deep
  192. def ==(o)
  193. o.object_id == self.object_id or
  194. (o.class == self.class and o.name == self.name and ((o.name and true) or compare_deep(o)))
  195. end
  196. # compare to another structure, comparing members recursively (names and type)
  197. # returns true if the self is same as o
  198. def compare_deep(o, seen = [])
  199. return true if o.object_id == self.object_id
  200. return if o.class != self.class or o.name != self.name or o.attributes != self.attributes
  201. o.members.to_a.zip(self.members.to_a).each { |om, sm|
  202. return if om.name != sm.name
  203. return if om.type != sm.type
  204. if om.type.pointer?
  205. ot = om.type
  206. st = sm.type
  207. 500.times { # limit for selfpointers (shouldnt happen)
  208. break if not ot.pointer?
  209. ot = ot.pointed.untypedef
  210. st = st.pointed.untypedef
  211. }
  212. if ot.kind_of?(C::Union) and ot.name and not seen.include?(ot)
  213. return if not st.compare_deep(ot, seen+[ot])
  214. end
  215. end
  216. }
  217. true
  218. end
  219. def findmember(name, igncase=false)
  220. raise 'undefined structure' if not members
  221. return @fldlist[name] if fldlist and @fldlist[name]
  222. name = name.downcase if igncase
  223. if m = @members.find { |m_| (n = m_.name) and (igncase ? n.downcase : n) == name }
  224. return m
  225. else
  226. @members.each { |m_|
  227. if t = m_.type.untypedef and t.kind_of? Union and mm = t.findmember(name, igncase)
  228. return mm
  229. end
  230. }
  231. end
  232. nil
  233. end
  234. def offsetof(parser, name)
  235. raise parser, 'undefined structure' if not members
  236. update_member_cache(parser) if not fldlist
  237. return 0 if @fldlist[name]
  238. if name.kind_of?(Variable)
  239. return 0 if @members.include? name
  240. raise ParseError, 'unknown union member'
  241. end
  242. raise parser, 'unknown union member' if not findmember(name)
  243. @members.find { |m|
  244. m.type.untypedef.kind_of? Union and m.type.untypedef.findmember(name)
  245. }.type.untypedef.offsetof(parser, name)
  246. end
  247. def bitoffsetof(parser, name)
  248. raise parser, 'undefined structure' if not members
  249. update_member_cache(parser) if not fldlist
  250. return if @fldlist[name] or @members.include?(name)
  251. raise parser, 'undefined union' if not @members
  252. raise parser, 'unknown union member' if not findmember(name)
  253. @members.find { |m|
  254. m.type.untypedef.kind_of? Union and m.type.untypedef.findmember(name)
  255. }.type.untypedef.bitoffsetof(parser, name)
  256. end
  257. def parse_members(parser, scope)
  258. @fldlist = nil if fldlist # invalidate fld offset cache
  259. @members = []
  260. # parse struct/union members in definition
  261. loop do
  262. raise parser if not tok = parser.skipspaces
  263. break if tok.type == :punct and tok.raw == '}'
  264. parser.unreadtok tok
  265. raise tok, 'invalid struct member type' if not basetype = Variable.parse_type(parser, scope)
  266. loop do
  267. member = basetype.dup
  268. member.parse_declarator(parser, scope)
  269. member.type.length ||= 0 if member.type.kind_of?(Array) # struct { char blarg[]; };
  270. raise member.backtrace, 'member redefinition' if member.name and @members.find { |m| m.name == member.name }
  271. @members << member
  272. raise tok || parser if not tok = parser.skipspaces or tok.type != :punct
  273. if tok.raw == ':' # bits
  274. raise tok, 'bad type for bitslice' if not member.type.integral?
  275. bits = nil
  276. raise tok, "bad bit count #{bits.inspect}" if not bits = CExpression.parse(parser, scope, false) or
  277. not bits.constant? or !(bits = bits.reduce(parser)).kind_of? ::Integer
  278. #raise tok, 'need more bits' if bits > 8*parser.sizeof(member)
  279. # WORD wReserved:17; => yay windows.h
  280. (@bits ||= [])[@members.length-1] = bits
  281. raise tok || parser, '"," or ";" expected' if not tok = parser.skipspaces or tok.type != :punct
  282. end
  283. case tok.raw
  284. when ';'; break
  285. when ','
  286. when '}'; parser.unreadtok(tok); break
  287. else raise tok, '"," or ";" expected'
  288. end
  289. end
  290. end
  291. parse_attributes(parser)
  292. end
  293. # updates the @fldoffset / @fldbitoffset hash storing the offset of members
  294. def update_member_cache(parser)
  295. @fldlist = {}
  296. @members.to_a.each { |m|
  297. @fldlist[m.name] = m if m.name
  298. }
  299. end
  300. def parse_initializer(parser, scope)
  301. if tok = parser.skipspaces and tok.type == :punct and tok.raw == '{'
  302. # struct x toto = { 1, .4, .member[0][6].bla = 12 };
  303. raise tok, 'undefined struct' if not @members
  304. ret = []
  305. if tok = parser.skipspaces and (tok.type != :punct or tok.raw != '}')
  306. parser.unreadtok tok
  307. idx = 0
  308. loop do
  309. idx = parse_initializer_designator(parser, scope, ret, idx, true)
  310. raise tok || parser, '"," or "}" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != '}' and tok.raw != ',')
  311. break if tok.raw == '}'
  312. raise tok, 'struct is smaller than that' if idx >= @members.length
  313. end
  314. end
  315. ret
  316. else
  317. parser.unreadtok tok
  318. super(parser, scope)
  319. end
  320. end
  321. # parses a designator+initializer eg '.toto = 4' or '.tutu[42][12].bla = 16' or (root ? '4' : '=4')
  322. def parse_initializer_designator(parser, scope, value, idx, root=true)
  323. if nt = parser.skipspaces and nt.type == :punct and nt.raw == '.' and
  324. nnt = parser.skipspaces and nnt.type == :string and
  325. findmember(nnt.raw)
  326. raise nnt, 'unhandled indirect initializer' if not nidx = @members.index(@members.find { |m| m.name == nnt.raw }) # TODO
  327. if not root
  328. value[idx] ||= [] # AryRecorder may change [] to AryRec.new, can't do v = v[i] ||= []
  329. value = value[idx]
  330. end
  331. idx = nidx
  332. @members[idx].type.untypedef.parse_initializer_designator(parser, scope, value, idx, false)
  333. else
  334. parser.unreadtok nnt
  335. if root
  336. parser.unreadtok nt
  337. value[idx] = @members[idx].type.parse_initializer(parser, scope)
  338. else
  339. raise nt || parser, '"=" expected' if not nt or nt.type != :punct or nt.raw != '='
  340. value[idx] = parse_initializer(parser, scope)
  341. end
  342. end
  343. idx + 1
  344. end
  345. # resolve structptr + offset into 'str.membername'
  346. # handles 'var.substruct1.array[12].foo'
  347. # updates str
  348. # returns the final member type itself
  349. # works for Struct/Union/Array
  350. def expand_member_offset(c_parser, off, str)
  351. # XXX choose in members, check sizeof / prefer structs
  352. m = @members.first
  353. str << '.' << m.name if m.name
  354. if m.type.respond_to?(:expand_member_offset)
  355. m.type.expand_member_offset(c_parser, off, str)
  356. else
  357. m.type
  358. end
  359. end
  360. end
  361. class Struct < Union
  362. attr_accessor :pack
  363. def align(parser) [@members.to_a.map { |m| m.type.align(parser) }.max || 1, (pack || 8)].min end
  364. def offsetof(parser, name)
  365. raise parser, 'undefined structure' if not members
  366. update_member_cache(parser) if not fldlist
  367. return @fldoffset[name] if @fldoffset[name]
  368. return @fldoffset[name.name] if name.respond_to?(:name) and @fldoffset[name.name]
  369. # this is almost never reached, only for <struct>.offsetof(anonymoussubstructmembername)
  370. raise parser, 'unknown structure member' if (name.kind_of?(::String) ? !findmember(name) : !@members.include?(name))
  371. indirect = true if name.kind_of?(::String) and not @fldlist[name]
  372. al = align(parser)
  373. off = 0
  374. bit_off = 0
  375. isz = nil
  376. @members.each_with_index { |m, i|
  377. if bits and b = @bits[i]
  378. if not isz
  379. mal = [m.type.align(parser), al].min
  380. off = (off + mal - 1) / mal * mal
  381. end
  382. isz = parser.sizeof(m)
  383. if b == 0 or (bit_off > 0 and bit_off + b > 8*isz)
  384. bit_off = 0
  385. mal = [m.type.align(parser), al].min
  386. off = (off + isz + mal - 1) / mal * mal
  387. end
  388. break if m.name == name or m == name
  389. bit_off += b
  390. else
  391. if isz
  392. off += isz
  393. bit_off = 0
  394. isz = nil
  395. end
  396. mal = [m.type.align(parser), al].min
  397. off = (off + mal - 1) / mal * mal
  398. if m.name == name or m == name
  399. break
  400. elsif indirect and m.type.untypedef.kind_of? Union and m.type.untypedef.findmember(name)
  401. off += m.type.untypedef.offsetof(parser, name)
  402. break
  403. else
  404. off += parser.sizeof(m)
  405. end
  406. end
  407. }
  408. off
  409. end
  410. # returns the [bitoffset, bitlength] of the field if it is a bitfield
  411. # this should be added to the offsetof(field)
  412. def bitoffsetof(parser, name)
  413. raise parser, 'undefined structure' if not members
  414. update_member_cache(parser) if not fldlist
  415. return @fldbitoffset[name] if fldbitoffset and @fldbitoffset[name]
  416. return @fldbitoffset[name.name] if fldbitoffset and name.respond_to?(:name) and @fldbitoffset[name.name]
  417. return if @fldlist[name] or @members.include?(name)
  418. raise parser, 'undefined union' if not @members
  419. raise parser, 'unknown union member' if not findmember(name)
  420. @members.find { |m|
  421. m.type.untypedef.kind_of?(Union) and m.type.untypedef.findmember(name)
  422. }.type.untypedef.bitoffsetof(parser, name)
  423. end
  424. # returns the @member element that has offsetof(m) == off
  425. def findmember_atoffset(parser, off)
  426. return if not members
  427. update_member_cache(parser) if not fldlist
  428. if m = @fldoffset.index(off)
  429. @fldlist[m]
  430. end
  431. end
  432. def parse_members(parser, scope)
  433. super(parser, scope)
  434. if has_attribute 'packed'
  435. @pack = 1
  436. elsif p = has_attribute_var('pack')
  437. @pack = p[/\d+/].to_i
  438. raise parser, "illegal struct pack(#{p})" if @pack == 0
  439. end
  440. end
  441. # updates the @fldoffset / @fldbitoffset hash storing the offset of members
  442. def update_member_cache(parser)
  443. super(parser)
  444. @fldoffset = {}
  445. @fldbitoffset = {} if fldbitoffset
  446. al = align(parser)
  447. off = 0
  448. bit_off = 0
  449. isz = nil
  450. @members.each_with_index { |m, i|
  451. if bits and b = @bits[i]
  452. if not isz
  453. mal = [m.type.align(parser), al].min
  454. off = (off + mal - 1) / mal * mal
  455. end
  456. isz = parser.sizeof(m)
  457. if b == 0 or (bit_off > 0 and bit_off + b > 8*isz)
  458. bit_off = 0
  459. mal = [m.type.align(parser), al].min
  460. off = (off + isz + mal - 1) / mal * mal
  461. end
  462. if m.name
  463. @fldoffset[m.name] = off
  464. @fldbitoffset ||= {}
  465. @fldbitoffset[m.name] = [bit_off, b]
  466. end
  467. bit_off += b
  468. else
  469. if isz
  470. off += isz
  471. bit_off = 0
  472. isz = nil
  473. end
  474. mal = [m.type.align(parser), al].min
  475. off = (off + mal - 1) / mal * mal
  476. @fldoffset[m.name] = off if m.name
  477. off += parser.sizeof(m)
  478. end
  479. }
  480. end
  481. # see Union#expand_member_offset
  482. def expand_member_offset(c_parser, off, str)
  483. members.to_a.each { |m|
  484. mo = offsetof(c_parser, m)
  485. if mo == off or mo + c_parser.sizeof(m) > off
  486. if bitoffsetof(c_parser, m)
  487. # ignore bitfields
  488. str << "+#{off}" if off > 0
  489. return self
  490. end
  491. str << '.' << m.name if m.name
  492. if m.type.respond_to?(:expand_member_offset)
  493. return m.type.expand_member_offset(c_parser, off-mo, str)
  494. else
  495. return m.type
  496. end
  497. elsif mo > off
  498. break
  499. end
  500. }
  501. # XXX that works only for pointer-style str
  502. str << "+#{off}" if off > 0
  503. nil
  504. end
  505. end
  506. class Enum < Type
  507. # name => value
  508. attr_accessor :members
  509. attr_accessor :name
  510. attr_accessor :backtrace
  511. def align(parser) BaseType.new(:int).align(parser) end
  512. def arithmetic?; true end
  513. def integral?; true end
  514. def signed?; false end
  515. def parse_members(parser, scope)
  516. val = -1
  517. @members = {}
  518. loop do
  519. raise parser if not tok = parser.skipspaces
  520. break if tok.type == :punct and tok.raw == '}'
  521. name = tok.raw
  522. raise tok, 'bad enum name' if tok.type != :string or Keyword[name] or (?0..?9).include?(name[0])
  523. raise parser if not tok = parser.skipspaces
  524. if tok.type == :punct and tok.raw == '='
  525. raise tok || parser if not val = CExpression.parse(parser, scope, false) or not val = val.reduce(parser) or not tok = parser.skipspaces
  526. else
  527. val += 1
  528. end
  529. raise tok, "enum value #{name} redefinition" if scope.symbol[name] and scope.symbol[name] != val
  530. @members[name] = val
  531. scope.symbol[name] = val
  532. if tok.type == :punct and tok.raw == '}'
  533. break
  534. elsif tok.type == :punct and tok.raw == ','
  535. else raise tok, '"," or "}" expected'
  536. end
  537. end
  538. parse_attributes(parser)
  539. end
  540. def compare_deep(o)
  541. return true if o.object_id == self.object_id
  542. return if o.class != self.class or o.name != self.name or o.attributes != self.attributes
  543. members == o.members
  544. end
  545. end
  546. class Pointer < Type
  547. attr_accessor :type
  548. def initialize(type=nil)
  549. @type = type
  550. end
  551. def pointer? ; true ; end
  552. def arithmetic? ; true ; end
  553. def base ; @type.base ; end
  554. def align(parser) BaseType.new(:ptr).align(parser) end
  555. def pointed ; @type end
  556. def ==(o)
  557. o.class == self.class and o.type == self.type
  558. end
  559. end
  560. class Array < Pointer
  561. attr_accessor :length
  562. def initialize(type=nil, length=nil)
  563. super(type)
  564. @length = length if length
  565. end
  566. def align(parser) @type.align(parser) end
  567. def parse_initializer(parser, scope)
  568. raise parser, 'cannot initialize dynamic array' if @length.kind_of? CExpression
  569. if tok = parser.skipspaces and tok.type == :punct and tok.raw == '{'
  570. # struct x foo[] = { { 4 }, [12].tutu = 2 };
  571. ret = []
  572. if tok = parser.skipspaces and (tok.type != :punct or tok.raw != '}')
  573. parser.unreadtok tok
  574. idx = 0
  575. loop do
  576. idx = parse_initializer_designator(parser, scope, ret, idx, true)
  577. raise tok || parser, '"," or "}" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != '}' and tok.raw != ',')
  578. break if tok.raw == '}'
  579. # allow int x[] = {1, 2, 3, };
  580. break if tok = parser.skipspaces and tok.type == :punct and tok.raw == '}'
  581. parser.unreadtok tok
  582. raise tok, 'array is smaller than that' if length and idx >= @length
  583. end
  584. end
  585. ret
  586. else
  587. parser.unreadtok tok
  588. i = super(parser, scope)
  589. if i.kind_of? CExpression and not i.op and i.rexpr.kind_of? String and @length and i.rexpr.length > @length
  590. puts tok.exception("initializer is too long (#{i.rexpr.length} for #@length)").message if $VERBOSE
  591. i.rexpr = i.rexpr[0, @length]
  592. end
  593. i
  594. end
  595. end
  596. # this class is a hack to support [1 ... 4] array initializer
  597. # it stores the effects of subsequent initializers (eg [1 ... 4].toto[48].bla[2 ... 57] = 12)
  598. # which are later played back on the range
  599. class AryRecorder
  600. attr_accessor :log
  601. def initialize
  602. @log = []
  603. end
  604. def []=(idx, val)
  605. val = self.class.new if val == []
  606. @log[idx] = val
  607. end
  608. def [](idx)
  609. @log[idx]
  610. end
  611. def playback_idx(i)
  612. case v = @log[i]
  613. when self.class; v.playback
  614. else v
  615. end
  616. end
  617. def playback(ary=[])
  618. @log.each_with_index { |v, i| ary[i] = playback_idx(i) }
  619. ary
  620. end
  621. end
  622. # parses a designator+initializer eg '[12] = 4' or '[42].bla = 16' or '[3 ... 8] = 28'
  623. def parse_initializer_designator(parser, scope, value, idx, root=true)
  624. # root = true for 1st invocation (x = { 4 }) => immediate value allowed
  625. # or false for recursive invocations (x = { .y = 4 }) => need '=' sign before immediate
  626. if nt = parser.skipspaces and nt.type == :punct and nt.raw == '['
  627. if not root
  628. value[idx] ||= [] # AryRecorder may change [] to AryRec.new, can't do v = v[i] ||= []
  629. value = value[idx]
  630. end
  631. raise nt, 'const expected' if not idx = CExpression.parse(parser, scope) or not idx.constant? or not idx = idx.reduce(parser) or not idx.kind_of? ::Integer
  632. nt = parser.skipspaces
  633. if nt and nt.type == :punct and nt.raw == '.' # range
  634. raise nt || parser, '".." expected' if not nt = parser.skipspaces or nt.type != :punct or nt.raw != '.'
  635. raise nt || parser, '"." expected' if not nt = parser.skipspaces or nt.type != :punct or nt.raw != '.'
  636. raise nt, 'const expected' if not eidx = CExpression.parse(parser, scope) or not eidx.constant? or not eidx = eidx.reduce(parser) or not eidx.kind_of? ::Integer
  637. raise nt, 'bad range' if eidx < idx
  638. nt = parser.skipspaces
  639. realvalue = value
  640. value = AryRecorder.new
  641. end
  642. raise nt || parser, '"]" expected' if not nt or nt.type != :punct or nt.raw != ']'
  643. raise nt, 'array is smaller than that' if length and (eidx||idx) >= @length
  644. @type.untypedef.parse_initializer_designator(parser, scope, value, idx, false)
  645. if eidx
  646. (idx..eidx).each { |i| realvalue[i] = value.playback_idx(idx) }
  647. idx = eidx # next default value = eidx+1 (eg int x[] = { [1 ... 3] = 4, 5 } => x[4] = 5)
  648. end
  649. else
  650. if root
  651. parser.unreadtok nt
  652. value[idx] = @type.parse_initializer(parser, scope)
  653. else
  654. raise nt || parser, '"=" expected' if not nt or nt.type != :punct or nt.raw != '='
  655. value[idx] = parse_initializer(parser, scope)
  656. end
  657. end
  658. idx + 1
  659. end
  660. # see Union#expand_member_offset
  661. def expand_member_offset(c_parser, off, str)
  662. tsz = c_parser.sizeof(@type)
  663. str << "[#{off/tsz}]"
  664. if @type.respond_to?(:expand_member_offset)
  665. @type.expand_member_offset(c_parser, off%tsz, str)
  666. else
  667. @type
  668. end
  669. end
  670. end
  671. class Variable
  672. include Attributes
  673. include Typed
  674. attr_accessor :type
  675. attr_accessor :initializer # CExpr / Block (for Functions)
  676. attr_accessor :name
  677. attr_accessor :storage # auto register static extern typedef
  678. attr_accessor :backtrace # definition backtrace info (the name token)
  679. def initialize(name=nil, type=nil)
  680. @name, @type = name, type
  681. end
  682. end
  683. # found in a block's Statements, used to know the initialization order
  684. # eg { int i; i = 4; struct foo { int k; } toto = {i}; }
  685. class Declaration
  686. attr_accessor :var
  687. def initialize(var)
  688. @var = var
  689. end
  690. end
  691. class If < Statement
  692. attr_accessor :test # expression
  693. attr_accessor :bthen, :belse # statements
  694. def initialize(test, bthen, belse=nil)
  695. @test = test
  696. @bthen = bthen
  697. @belse = belse if belse
  698. end
  699. def self.parse(parser, scope, nest)
  700. tok = nil
  701. raise tok || self, '"(" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '('
  702. raise tok, 'expr expected' if not expr = CExpression.parse(parser, scope) or not expr.type.arithmetic?
  703. raise tok || self, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
  704. bthen = parser.parse_statement scope, nest
  705. if tok = parser.skipspaces and tok.type == :string and tok.raw == 'else'
  706. belse = parser.parse_statement scope, nest
  707. else
  708. parser.unreadtok tok
  709. end
  710. new expr, bthen, belse
  711. end
  712. end
  713. class For < Statement
  714. attr_accessor :init, :test, :iter # CExpressions, init may be Block
  715. attr_accessor :body
  716. def initialize(init, test, iter, body)
  717. @init, @test, @iter, @body = init, test, iter, body
  718. end
  719. def self.parse(parser, scope, nest)
  720. tok = nil
  721. raise tok || parser, '"(" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '('
  722. init = forscope = Block.new(scope)
  723. if not parser.parse_definition(forscope)
  724. forscope = scope
  725. init = CExpression.parse(parser, forscope)
  726. raise tok || parser, '";" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ';'
  727. end
  728. test = CExpression.parse(parser, forscope)
  729. raise tok || parser, '";" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ';'
  730. raise tok, 'bad test expression in for loop' if test and not test.type.arithmetic?
  731. iter = CExpression.parse(parser, forscope)
  732. raise tok || parser, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
  733. new init, test, iter, parser.parse_statement(forscope, nest + [:loop])
  734. end
  735. end
  736. class While < Statement
  737. attr_accessor :test
  738. attr_accessor :body
  739. def initialize(test, body)
  740. @test = test
  741. @body = body
  742. end
  743. def self.parse(parser, scope, nest)
  744. tok = nil
  745. raise tok || parser, '"(" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '('
  746. raise tok, 'expr expected' if not expr = CExpression.parse(parser, scope) or not expr.type.arithmetic?
  747. raise tok || parser, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
  748. new expr, parser.parse_statement(scope, nest + [:loop])
  749. end
  750. end
  751. class DoWhile < While
  752. def self.parse(parser, scope, nest)
  753. body = parser.parse_statement(scope, nest + [:loop])
  754. tok = nil
  755. raise tok || parser, '"while" expected' if not tok = parser.skipspaces or tok.type != :string or tok.raw != 'while'
  756. raise tok || parser, '"(" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '('
  757. raise tok, 'expr expected' if not expr = CExpression.parse(parser, scope) or not expr.type.arithmetic?
  758. raise tok || parser, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
  759. parser.checkstatementend(tok)
  760. new expr, body
  761. end
  762. end
  763. class Switch < Statement
  764. attr_accessor :test, :body
  765. def initialize(test, body)
  766. @test = test
  767. @body = body
  768. end
  769. def self.parse(parser, scope, nest)
  770. raise tok || parser, '"(" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '('
  771. raise tok, 'expr expected' if not expr = CExpression.parse(parser, scope) or not expr.type.integral?
  772. raise tok || parser, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
  773. new expr, parser.parse_statement(scope, nest + [:switch])
  774. end
  775. end
  776. class Continue < Statement
  777. end
  778. class Break < Statement
  779. end
  780. class Goto < Statement
  781. attr_accessor :target
  782. def initialize(target)
  783. @target = target
  784. end
  785. end
  786. class Return < Statement
  787. attr_accessor :value
  788. def initialize(value)
  789. @value = value
  790. end
  791. end
  792. class Label < Statement
  793. attr_accessor :name
  794. attr_accessor :statement
  795. def initialize(name, statement=nil)
  796. @name, @statement = name, statement
  797. end
  798. end
  799. class Case < Label
  800. attr_accessor :expr, :exprup # exprup if range, expr may be 'default'
  801. def initialize(expr, exprup, statement)
  802. @expr, @statement = expr, statement
  803. @exprup = exprup if exprup
  804. end
  805. def self.parse(parser, scope, nest)
  806. raise parser, 'invalid case' if not expr = CExpression.parse(parser, scope) or not expr.constant? or not expr.type.integral?
  807. raise tok || parser, '":" or "..." expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != ':' and tok.raw != '.')
  808. if tok.raw == '.'
  809. raise tok || parser, '".." expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '.'
  810. raise tok || parser, '"." expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '.'
  811. raise tok, 'invalid case range' if not exprup = CExpression.parse(parser, scope) or not exprup.constant? or not exprup.type.integral?
  812. raise tok || parser, '":" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ':'
  813. end
  814. body = parser.parse_statement scope, nest
  815. new expr, exprup, body
  816. end
  817. end
  818. # inline asm statement
  819. class Asm < Statement
  820. include Attributes
  821. attr_accessor :body # asm source (::String)
  822. attr_accessor :output, :input, :clobber # I/O, gcc-style (::Array)
  823. attr_accessor :backtrace # body Token
  824. attr_accessor :volatile
  825. def initialize(body, backtrace, output=nil, input=nil, clobber=nil, volatile=nil)
  826. @body, @backtrace, @output, @input, @clobber, @volatile = body, backtrace, output, input, clobber, volatile
  827. end
  828. def self.parse(parser, scope)
  829. if tok = parser.skipspaces and tok.type == :string and (tok.raw == 'volatile' or tok.raw == '__volatile__')
  830. volatile = true
  831. tok = parser.skipspaces
  832. end
  833. if not tok or tok.type != :punct or tok.raw != '('
  834. # detect MS-style inline asm: "__asm .* __asm .*" or "asm { [\s.]* }"
  835. ftok = tok
  836. body = ''
  837. if tok.type == :punct and tok.raw == '{'
  838. loop do
  839. raise ftok, 'unterminated asm block' if not tok = parser.lexer.readtok
  840. break if tok.type == :punct and tok.raw == '}'
  841. case tok.type
  842. when :space; body << ' '
  843. when :eol; body << "\n"
  844. when :punct; body << tok.raw
  845. when :quoted; body << CExpression.string_inspect(tok.value) # concat adjacent c strings
  846. when :string
  847. body << \
  848. case tok.raw
  849. when 'asm', '__asm', '__asm__'; "\n"
  850. when '_emit'; 'db'
  851. else tok.raw
  852. end
  853. end
  854. end
  855. # allow shell-style heredoc: asm <<EOS\n<asm>\nEOS
  856. elsif tok.type == :punct and tok.raw == '<'
  857. raise ftok, 'bad asm heredoc' if not tok = parser.lexer.readtok or tok.type != :punct or tok.raw != '<'
  858. delimiter = parser.lexer.readtok
  859. if delimiter.type == :punct and delimiter.raw == '-'
  860. skipspc = true
  861. delimiter = parser.lexer.readtok
  862. end
  863. raise ftok, 'bad asm heredoc delim' if delimiter.type != :string or not tok = parser.lexer.readtok or tok.type != :eol
  864. nl = true
  865. loop do
  866. raise ftok, 'unterminated heredoc' if not tok = parser.lexer.readtok
  867. break if nl and tok.raw == delimiter.raw
  868. raw = tok.raw
  869. raw = "\n" if skipspc and tok.type == :eol
  870. body << raw
  871. nl = (tok.type == :eol and (raw[-1] == ?\n or raw[-1] == ?\r))
  872. end
  873. # MS single-instr: asm inc eax;
  874. # also allow asm "foo bar\nbaz";
  875. else
  876. parser.lexer.unreadtok tok
  877. loop do
  878. break if not tok = parser.lexer.readtok or tok.type == :eol
  879. case tok.type
  880. when :space; body << ' '
  881. when :punct
  882. case tok.raw
  883. when '}'
  884. parser.lexer.unreadtok tok
  885. break
  886. else body << tok.raw
  887. end
  888. when :quoted; body << (body.empty? ? tok.value : CExpression.string_inspect(tok.value)) # asm "pop\nret" VS asm add al, 'z'
  889. when :string
  890. body << \
  891. case tok.raw
  892. when 'asm', '__asm', '__asm__'; "\n"
  893. when '_emit'; 'db'
  894. else tok.raw
  895. end
  896. end
  897. end
  898. end
  899. return new(body, ftok, nil, nil, nil, volatile)
  900. end
  901. raise tok || parser, '"(" expected' if not tok or tok.type != :punct or tok.raw != '('
  902. raise tok || parser, 'qstring expected' if not tok = parser.skipspaces or tok.type != :quoted
  903. body = tok
  904. ret = new body.value, body
  905. tok = parser.skipspaces
  906. raise tok || parser, '":" or ")" expected' if not tok or tok.type != :punct or (tok.raw != ':' and tok.raw != ')')
  907. if tok.raw == ':'
  908. ret.output = []
  909. raise parser if not tok = parser.skipspaces
  910. while tok.type == :quoted
  911. type = tok.value
  912. raise tok, 'expr expected' if not var = CExpression.parse_value(parser, scope)
  913. ret.output << [type, var]
  914. raise tok || parser, '":" or "," or ")" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != ',' and tok.raw != ')' and tok.raw != ':')
  915. break if tok.raw == ':' or tok.raw == ')'
  916. raise tok || parser, 'qstring expected' if not tok = parser.skipspaces or tok.type != :quoted
  917. end
  918. end
  919. if tok.raw == ':'
  920. ret.input = []
  921. raise parser if not tok = parser.skipspaces
  922. while tok.type == :quoted
  923. type = tok.value
  924. raise tok, 'expr expected' if not var = CExpression.parse_value(parser, scope)
  925. ret.input << [type, var]
  926. raise tok || parser, '":" or "," or ")" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != ',' and tok.raw != ')' and tok.raw != ':')
  927. break if tok.raw == ':' or tok.raw == ')'
  928. raise tok || parser, 'qstring expected' if not tok = parser.skipspaces or tok.type != :quoted
  929. end
  930. end
  931. if tok.raw == ':'
  932. ret.clobber = []
  933. raise parser if not tok = parser.skipspaces
  934. while tok.type == :quoted
  935. ret.clobber << tok.value
  936. raise tok || parser, '"," or ")" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != ',' and tok.raw != ')')
  937. break if tok.raw == ')'
  938. raise tok || parser, 'qstring expected' if not tok = parser.skipspaces or tok.type != :quoted
  939. end
  940. end
  941. raise tok || parser, '")" expected' if not tok or tok.type != :punct or tok.raw != ')'
  942. ret.parse_attributes(parser)
  943. parser.checkstatementend(tok)
  944. ret
  945. end
  946. end
  947. class CExpression < Statement
  948. include Typed
  949. # may be :,, :., :'->', :funcall (function, [arglist]), :[] (array indexing), nil (cast)
  950. attr_accessor :op
  951. # nil/CExpr/Variable/Label/::String( = :quoted/struct member name)/::Integer/::Float/Block
  952. attr_accessor :lexpr, :rexpr
  953. # a Type
  954. attr_accessor :type
  955. def initialize(l, o, r, t)
  956. raise "invalid CExpr #{[l, o, r, t].inspect}" if (o and not o.kind_of? ::Symbol) or not t.kind_of? Type
  957. @lexpr, @op, @rexpr, @type = l, o, r, t
  958. end
  959. # overwrites @lexpr @op @rexpr @type from the arg
  960. def replace(o)
  961. @lexpr, @op, @rexpr, @type = o.lexpr, o.op, o.rexpr, o.type
  962. self
  963. end
  964. # deep copy of the object
  965. # recurses only within CExpressions, anything else is copied by reference
  966. def deep_dup
  967. n = dup
  968. n.lexpr = n.lexpr.deep_dup if n.lexpr.kind_of? CExpression
  969. n.rexpr = n.rexpr.deep_dup if n.rexpr.kind_of? CExpression
  970. n.rexpr = n.rexpr.map { |e| e.kind_of?(CExpression) ? e.deep_dup : e } if n.rexpr.kind_of? ::Array
  971. n
  972. end
  973. # recursive constructor with automatic type inference
  974. # e.g. CExpression[foo, :+, [:*, bar]]
  975. # assumes root args are correctly typed (eg *foo => foo must be a pointer)
  976. # take care to use [int] with immediates, e.g. CExpression[foo, :+, [2]]
  977. # CExpr[some_cexpr] returns some_cexpr
  978. def self.[](*args)
  979. # sub-arrays in args are to be passed to self.[] recursively (syntaxic sugar)
  980. splat = lambda { |e| e.kind_of?(::Array) ? self[*e] : e }
  981. args.shift while args.first == nil # CExpr[nil, :&, bla] => CExpr[:&, bla]
  982. case args.length
  983. when 4
  984. op = args[1]
  985. if op == :funcall or op == :'?:'
  986. x2 = args[2].map { |a| splat[a] } if args[2]
  987. else
  988. x2 = splat[args[2]]
  989. end
  990. new(splat[args[0]], op, x2, args[3])
  991. when 3
  992. op = args[1]
  993. x1 = splat[args[0]]
  994. if op == :funcall or op == :'?:'
  995. x2 = args[2].map { |a| splat[a] } if args[2]
  996. else
  997. x2 = splat[args[2]]
  998. end
  999. case op
  1000. when :funcall
  1001. rt = x1.type.untypedef
  1002. rt = rt.type.untypedef if rt.pointer?
  1003. new(x1, op, x2, rt.type)
  1004. when :[]; new(x1, op, x2, x1.type.untypedef.type)
  1005. when :+; new(x1, op, x2, (x2.type.pointer? ? x2.type : x1.type))
  1006. when :-; new(x1, op, x2, ((x1.type.pointer? and x2.type.pointer?) ? BaseType.new(:int) : x2.type.pointer? ? x2.type : x1.type))
  1007. when :'&&', :'||', :==, :'!=', :>, :<, :<=, :>=; new(x1, op, x2, BaseType.new(:int))
  1008. when :'.', :'->'
  1009. t = x1.type.untypedef
  1010. t = t.type.untypedef if op == :'->' and x1.type.pointer?
  1011. raise "parse error: #{t} has no member #{x2}" if not t.kind_of? Union or not m = t.findmember(x2)
  1012. new(x1, op, x2, m.type)
  1013. when :'?:'; new(x1, op, x2, x2[0].type)
  1014. when :','; new(x1, op, x2, x2.type)
  1015. else new(x1, op, x2, x1.type)
  1016. end
  1017. when 2
  1018. x0 = splat[args[0]]
  1019. x1 = splat[args[1]]
  1020. x0, x1 = x1, x0 if x0.kind_of? Type
  1021. if x1.kind_of? Type; new(nil, nil, x0, x1) # (cast)r
  1022. elsif x0 == :*; new(nil, x0, x1, x1.type.untypedef.type) # *r
  1023. elsif x0 == :& and x1.kind_of? CExpression and x1.type.kind_of? C::Array; new(nil, nil, x1, Pointer.new(x1.type.type))
  1024. elsif x0 == :&; new(nil, x0, x1, Pointer.new(x1.type)) # &r
  1025. elsif x0 == :'!'; new(nil, x0, x1, BaseType.new(:int)) # &r
  1026. elsif x1.kind_of? ::Symbol; new(x0, x1, nil, x0.type) # l++
  1027. else new(nil, x0, x1, x1.type) # +r
  1028. end
  1029. when 1
  1030. x = splat[args[0]]
  1031. case x
  1032. when CExpression; x
  1033. when ::Integer; new(nil, nil, x, BaseType.new(:int)) # XXX range => __int64 ?
  1034. when ::Float; new(nil, nil, x, BaseType.new(:double))
  1035. when ::String; new(nil, nil, x, Pointer.new(BaseType.new(:char)))
  1036. else new(nil, nil, x, x.type)
  1037. end
  1038. else raise "parse error CExpr[*#{args.inspect}]"
  1039. end
  1040. end
  1041. end
  1042. class Parser
  1043. # creates a new CParser, parses all top-level statements
  1044. def self.parse(text)
  1045. new.parse text
  1046. end
  1047. # parses the current lexer content (or the text arg) for toplevel definitions
  1048. def parse(text=nil, filename='<unk>', lineno=1)
  1049. @lexer.feed text, filename, lineno if text
  1050. nil while not @lexer.eos? and (parse_definition(@toplevel) or parse_toplevel_statement(@toplevel))
  1051. raise @lexer.readtok || self, 'invalid definition' if not @lexer.eos?
  1052. sanity_checks
  1053. self
  1054. end
  1055. # parses a C file
  1056. def parse_file(file)
  1057. parse(File.read(file), file)
  1058. end
  1059. attr_accessor :lexer, :toplevel, :typesize, :pragma_pack
  1060. attr_accessor :endianness
  1061. attr_accessor :allow_bad_c
  1062. attr_accessor :program
  1063. # allowed arguments: ExeFormat, CPU, Preprocessor, Symbol (for the data model)
  1064. def initialize(*args)
  1065. model = args.grep(Symbol).first || :ilp32
  1066. lexer = args.grep(Preprocessor).first || Preprocessor.new
  1067. @program = args.grep(ExeFormat).first
  1068. cpu = args.grep(CPU).first
  1069. cpu ||= @program.cpu if @program
  1070. @lexer = lexer
  1071. @prev_pragma_callback = @lexer.pragma_callback
  1072. @lexer.pragma_callback = lambda { |tok| parse_pragma_callback(tok) }
  1073. @toplevel = Block.new(nil)
  1074. @unreadtoks = []
  1075. @endianness = cpu ? cpu.endianness : :big
  1076. @typesize = { :void => 1, :__int8 => 1, :__int16 => 2, :__int32 => 4, :__int64 => 8,
  1077. :char => 1, :float => 4, :double => 8, :longdouble => 12 }
  1078. send model
  1079. cpu.tune_cparser(self) if cpu
  1080. @program.tune_cparser(self) if @program
  1081. end
  1082. def ilp16
  1083. @typesize.update :short => 2, :ptr => 2,
  1084. :int => 2, :long => 4, :longlong => 4
  1085. end
  1086. def lp32
  1087. @typesize.update :short => 2, :ptr => 4,
  1088. :int => 2, :long => 4, :longlong => 8
  1089. end
  1090. def ilp32
  1091. @typesize.update :short => 2, :ptr => 4,
  1092. :int => 4, :long => 4, :longlong => 8
  1093. end
  1094. def llp64
  1095. @typesize.update :short => 2, :ptr => 8,
  1096. :int => 4, :long => 4, :longlong => 8
  1097. end
  1098. def lp64
  1099. @typesize.update :short => 2, :ptr => 8,
  1100. :int => 4, :long => 8, :longlong => 8
  1101. end
  1102. def ilp64
  1103. @typesize.update :short => 2, :ptr => 8,
  1104. :int => 8, :long => 8, :longlong => 8
  1105. end
  1106. def parse_pragma_callback(otok)
  1107. case otok.raw
  1108. when 'pack'
  1109. nil while lp = @lexer.readtok and lp.type == :space
  1110. nil while rp = @lexer.readtok and rp.type == :space
  1111. if not rp or rp.type != :punct or rp.raw != ')'
  1112. v1 = rp
  1113. nil while rp = @lexer.readtok and rp.type == :space
  1114. end
  1115. if rp and rp.type == :punct and rp.raw == ','
  1116. nil while v2 = @lexer.readtok and v2.type == :space
  1117. nil while rp = @lexer.readtok and rp.type == :space
  1118. end
  1119. raise otok if not rp or lp.type != :punct or rp.type != :punct or lp.raw != '(' or rp.raw != ')'
  1120. raise otok if (v1 and v1.type != :string) or (v2 and (v2.type != :string or v2.raw =~ /[^\d]/))
  1121. if not v1
  1122. @pragma_pack = nil
  1123. elsif v1.raw == 'push'
  1124. @pragma_pack_stack ||= []
  1125. @pragma_pack_stack << pragma_pack
  1126. @pragma_pack = v2.raw.to_i if v2
  1127. raise v2, 'bad pack value' if pragma_pack == 0
  1128. elsif v1.raw == 'pop'
  1129. @pragma_pack_stack ||= []
  1130. raise v1, 'pack stack empty' if @pragma_pack_stack.empty?
  1131. @pragma_pack = @pragma_pack_stack.pop
  1132. @pragma_pack = v2.raw.to_i if v2 and v2.raw # #pragma pack(pop, 4) => pop stack, but use 4 as pack value (imho)
  1133. raise v2, 'bad pack value' if @pragma_pack == 0
  1134. elsif v1.raw =~ /^\d+$/
  1135. raise v2, '2nd arg unexpected' if v2
  1136. @pragma_pack = v1.raw.to_i
  1137. raise v1, 'bad pack value' if @pragma_pack == 0
  1138. else raise otok
  1139. end
  1140. # the caller checks for :eol
  1141. when 'warning'
  1142. if $DEBUG
  1143. @prev_pragma_callback[otok]
  1144. else
  1145. # silent discard
  1146. nil while tok = @lexer.readtok_nopp and tok.type != :eol
  1147. @lexer.unreadtok tok
  1148. end
  1149. when 'prepare_visualstudio'
  1150. prepare_visualstudio
  1151. when 'prepare_gcc'
  1152. prepare_gcc
  1153. when 'data_model' # XXX use carefully, should be the very first thing parsed
  1154. nil while lp = @lexer.readtok and lp.type == :space
  1155. if lp.type != :string or lp.raw !~ /^s?[il]?lp(16|32|64)$/ or not respond_to? lp.raw
  1156. raise lp, "invalid data model (use lp32/lp64/llp64/ilp64)"
  1157. else
  1158. send lp.raw
  1159. end
  1160. else @prev_pragma_callback[otok]
  1161. end
  1162. end
  1163. def prepare_visualstudio
  1164. @lexer.define_weak('_WIN32')
  1165. @lexer.define_weak('_WIN32_WINNT', 0x500)
  1166. @lexer.define_weak('_INTEGRAL_MAX_BITS', 64)
  1167. @lexer.define_weak('__w64')
  1168. @lexer.define_weak('_cdecl', '__cdecl') # typo ? seen in winreg.h
  1169. @lexer.define_weak('_fastcall', '__fastcall') # typo ? seen in ntddk.h
  1170. @lexer.define_weak('_MSC_VER', 1300) # handle '#pragma once' and _declspec(noreturn)
  1171. @lexer.define_weak('__forceinline', '__inline')
  1172. @lexer.define_weak('__ptr32') # needed with msc_ver 1300, don't understand their use
  1173. @lexer.define_weak('__ptr64')
  1174. end
  1175. def prepare_gcc
  1176. @lexer.define_weak('__GNUC__', 2) # otherwise __attribute__ is defined to void..
  1177. @lexer.define_weak('__STDC__')
  1178. @lexer.define_weak('__const', 'const')
  1179. @lexer.define_weak('__signed', 'signed')
  1180. @lexer.define_weak('__signed__', 'signed')
  1181. @lexer.define_weak('__volatile', 'volatile')
  1182. if not @lexer.definition['__builtin_constant_p']
  1183. # magic macro to check if its arg is an immediate value
  1184. @lexer.define_weak('__builtin_constant_p', '0')
  1185. @lexer.definition['__builtin_constant_p'].args = [Preprocessor::Token.new([])]
  1186. end
  1187. @lexer.nodefine_strong('alloca') # TODO __builtin_alloca
  1188. @lexer.hooked_include['stddef.h'] = <<EOH
  1189. /* simplified, define all at first invocation. may break things... */
  1190. #undef __need_ptrdiff_t
  1191. #undef __need_size_t
  1192. #undef __need_wint_t
  1193. #undef __need_wchar_t
  1194. #undef __need_NULL
  1195. #undef NULL
  1196. #if !defined (_STDDEF_H)
  1197. #define _STDDEF_H
  1198. #define __PTRDIFF_TYPE__ long int
  1199. typedef __PTRDIFF_TYPE__ ptrdiff_t;
  1200. #define __SIZE_TYPE__ long unsigned int
  1201. typedef __SIZE_TYPE__ size_t;
  1202. #define __WINT_TYPE__ unsigned int
  1203. typedef __WINT_TYPE__ wint_t;
  1204. #define __WCHAR_TYPE__ int
  1205. typedef __WCHAR_TYPE__ wchar_t;
  1206. #define NULL 0
  1207. #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
  1208. #endif
  1209. EOH
  1210. # TODO va_args
  1211. @lexer.hooked_include['stdarg.h'] = <<EOH
  1212. // TODO
  1213. typedef void* __gnuc_va_list;
  1214. /*
  1215. typedef void* va_list;
  1216. #define va_start(v, l)
  1217. #define va_end(v)
  1218. #define va_arg(v, l)
  1219. #define va_copy(d, s)
  1220. */
  1221. EOH
  1222. @lexer.hooked_include['limits.h'] = <<EOH
  1223. #define CHAR_BIT 8
  1224. #define SCHAR_MIN (-128)
  1225. #define SCHAR_MAX 127
  1226. #define UCHAR_MAX 255
  1227. #ifdef __CHAR_UNSIGNED__
  1228. # define CHAR_MIN 0
  1229. # define CHAR_MAX UCHAR_MAX
  1230. #else
  1231. # define CHAR_MIN SCHAR_MIN
  1232. # define CHAR_MAX SCHAR_MAX
  1233. #endif
  1234. #define UINT_MAX #{(1 << (8*@typesize[:int]))-1}U
  1235. #define INT_MAX (UINT_MAX >> 1)
  1236. #define INT_MIN (-INT_MAX - 1)
  1237. #define ULONG_MAX #{(1 << (8*@typesize[:long]))-1}UL
  1238. #define LONG_MAX (ULONG_MAX >> 1L)
  1239. #define LONG_MIN (-LONG_MAX - 1L)
  1240. EOH
  1241. end
  1242. # C sanity checks
  1243. def sanity_checks
  1244. return if not $VERBOSE
  1245. # TODO
  1246. end
  1247. # checks that the types are compatible (variable predeclaration, function argument..)
  1248. # strict = false for func call/assignment (eg char compatible with int -- but int is incompatible with char)
  1249. # output warnings only
  1250. def check_compatible_type(tok, oldtype, newtype, strict = false, checked = [])
  1251. return if not $VERBOSE
  1252. oldtype = oldtype.untypedef
  1253. newtype = newtype.untypedef
  1254. oldtype = BaseType.new(:int) if oldtype.kind_of? Enum
  1255. newtype = BaseType.new(:int) if newtype.kind_of? Enum
  1256. puts tok.exception('type qualifier mismatch').message if oldtype.qualifier.to_a.uniq.length > newtype.qualifier.to_a.uniq.length
  1257. # avoid infinite recursion
  1258. return if checked.include? oldtype
  1259. checked = checked + [oldtype]
  1260. begin
  1261. case newtype
  1262. when Function
  1263. raise tok, 'type error' if not oldtype.kind_of? Function
  1264. check_compatible_type tok, oldtype.type, newtype.type, strict, checked
  1265. if oldtype.args and newtype.args
  1266. if oldtype.args.length != newtype.args.length or
  1267. oldtype.varargs != newtype.varargs
  1268. raise tok, 'type error'
  1269. end
  1270. oldtype.args.zip(newtype.args) { |oa, na|
  1271. # begin ; rescue ParseError: raise $!.message + "in parameter #{oa.name}" end
  1272. check_compatible_type tok, oa.type, na.type, strict, checked
  1273. }
  1274. end
  1275. when Pointer
  1276. if oldtype.kind_of? BaseType and oldtype.integral?
  1277. puts tok.exception('making pointer from integer without a cast').message
  1278. return
  1279. end
  1280. raise tok, 'type error' if not oldtype.kind_of? Pointer
  1281. hasvoid = true if (t = newtype.type.untypedef).kind_of? BaseType and t.name == :void
  1282. hasvoid = true if (t = oldtype.type.untypedef).kind_of? BaseType and t.name == :void # struct foo *f = NULL;
  1283. if strict and not hasvoid
  1284. check_compatible_type tok, oldtype.type, newtype.type, strict, checked
  1285. end
  1286. when Union
  1287. raise tok, 'type error' if not oldtype.class == newtype.class
  1288. if oldtype.members and newtype.members
  1289. if oldtype.members.length != newtype.members.length
  1290. raise tok, 'bad member count'
  1291. end
  1292. oldtype.members.zip(newtype.members) { |om, nm|
  1293. # raise tok if om.name and nm.name and om.name != nm.name # don't care
  1294. check_compatible_type tok, om.type, nm.type, strict, checked
  1295. }
  1296. end
  1297. when BaseType
  1298. raise tok, 'type error' if not oldtype.kind_of? BaseType
  1299. if strict
  1300. if oldtype.name != newtype.name or
  1301. oldtype.specifier != newtype.specifier
  1302. raise tok, 'type error'
  1303. end
  1304. else
  1305. raise tok, 'type error' if @typesize[newtype.name] == 0 and @typesize[oldtype.name] > 0
  1306. puts tok.exception('type size mismatch, may lose bits').message if @typesize[oldtype.name] > @typesize[newtype.name]
  1307. puts tok.exception('sign mismatch').message if oldtype.specifier != newtype.specifier and @typesize[newtype.name] == @typesize[oldtype.name]
  1308. end
  1309. end
  1310. rescue ParseError
  1311. raise $! if checked.length != 1 # bubble up
  1312. oname = (oldtype.to_s rescue oldtype.class.name)
  1313. nname = (newtype.to_s rescue newtype.class.name)
  1314. puts $!.message + " incompatible type #{oname} to #{nname}"
  1315. end
  1316. end
  1317. # allows 'raise self'
  1318. def exception(msg='EOF unexpected')
  1319. @lexer.exception msg
  1320. end
  1321. # reads a token, convert 'L"foo"' to a :quoted
  1322. def readtok_longstr
  1323. if t = @lexer.readtok and t.type == :string and t.raw == 'L' and
  1324. nt = @lexer.readtok and nt.type == :quoted and nt.raw[0] == ?"
  1325. nt.raw[0, 0] = 'L'
  1326. nt
  1327. elsif t and t.type == :punct and t.raw == '/' and
  1328. # nt has not been read
  1329. nt = @lexer.readtok and nt.type == :punct and nt.raw == '/'
  1330. # windows.h has a #define some_type_name /##/, and VS interprets this as a comment..
  1331. puts @lexer.exception('#defined //').message if $VERBOSE
  1332. t = @lexer.readtok while t and t.type != :eol
  1333. t
  1334. else
  1335. @lexer.unreadtok nt
  1336. t
  1337. end
  1338. end
  1339. private :readtok_longstr
  1340. # reads a token from self.lexer
  1341. # concatenates strings, merges spaces/eol to ' ', handles wchar strings, allows $@_ in :string
  1342. def readtok
  1343. if not t = @unreadtoks.pop
  1344. return if not t = readtok_longstr
  1345. case t.type
  1346. when :space, :eol
  1347. # merge consecutive :space/:eol
  1348. t = t.dup
  1349. t.type = :space
  1350. t.raw = ' '
  1351. nil while nt = @lexer.readtok and (nt.type == :eol or nt.type == :space)
  1352. @lexer.unreadtok nt
  1353. when :quoted
  1354. # merge consecutive :quoted
  1355. t = t.dup
  1356. while nt = readtok_longstr
  1357. case nt.type
  1358. when :quoted
  1359. if t.raw[0] == ?" and nt.raw[0, 2] == 'L"'
  1360. # ensure wide prefix is set
  1361. t.raw[0, 0] = 'L'
  1362. end
  1363. t.raw << ' ' << nt.raw
  1364. t.value << nt.value
  1365. when :space, :eol
  1366. else break
  1367. end
  1368. end
  1369. @lexer.unreadtok nt
  1370. else
  1371. if (t.type == :punct and (t.raw == '_' or t.raw == '@' or t.raw == '$')) or t.type == :string
  1372. t = t.dup
  1373. t.type = :string
  1374. nt = nil
  1375. t.raw << nt.raw while nt = @lexer.readtok and ((nt.type == :punct and (nt.raw == '_' or nt.raw == '@' or nt.raw == '$')) or nt.type == :string)
  1376. @lexer.unreadtok nt
  1377. end
  1378. end
  1379. end
  1380. t
  1381. end
  1382. def eos?
  1383. @unreadtoks.empty? and @lexer.eos?
  1384. end
  1385. def unreadtok(tok)
  1386. @unreadtoks << tok if tok
  1387. end
  1388. # returns the next non-space/non-eol token
  1389. def skipspaces
  1390. nil while t = readtok and t.type == :space
  1391. t
  1392. end
  1393. # checks that we are at the end of a statement, ie an ';' character (consumed), or a '}' (not consumed)
  1394. # otherwise, raise either the given token or self.
  1395. def checkstatementend(tok=nil)
  1396. raise tok || self, '";" expected' if not tok = skipspaces or tok.type != :punct or (tok.raw != ';' and tok.raw != '}')
  1397. unreadtok tok if tok.raw == '}'
  1398. end
  1399. # returns the size of a type in bytes
  1400. def sizeof(var, type=nil)
  1401. var, type = nil, var if var.kind_of? Type and not type
  1402. type ||= var.type
  1403. # XXX double-check class apparition order ('when' checks inheritance)
  1404. case type
  1405. when Array
  1406. case type.length
  1407. when nil
  1408. if var.kind_of? CExpression and not var.lexpr and not var.op and var.rexpr.kind_of? Variable
  1409. var = var.rexpr
  1410. end
  1411. raise self, 'unknown array size' if not var.kind_of? Variable or not var.initializer
  1412. init = var.initializer
  1413. init = init.rexpr if init.kind_of? C::CExpression and not init.op and init.rexpr.kind_of? ::String
  1414. case init
  1415. when ::String; sizeof(nil, type.type) * (init.length + 1)
  1416. when ::Array
  1417. v = init.compact.first
  1418. v ? (sizeof(nil, type.type) * init.length) : 0
  1419. else sizeof(init)
  1420. end
  1421. when ::Integer; type.length * sizeof(type.type)
  1422. when CExpression
  1423. len = type.length.reduce(self)
  1424. raise self, 'unknown array size' if not len.kind_of? ::Integer
  1425. len * sizeof(type)
  1426. else raise self, 'unknown array size'
  1427. end
  1428. when Pointer
  1429. if var.kind_of? CExpression and not var.op and var.rexpr.kind_of? ::String
  1430. # sizeof("lolz") => 5
  1431. sizeof(nil, type.type) * (var.rexpr.length + 1)
  1432. else
  1433. @typesize[:ptr]
  1434. end
  1435. when Function
  1436. # raise
  1437. 1 # gcc
  1438. when BaseType
  1439. @typesize[type.name]
  1440. when Enum
  1441. @typesize[:int]
  1442. when Struct
  1443. raise self, "unknown structure size #{type.name}" if not type.members
  1444. al = type.align(self)
  1445. al = 1 if (var.kind_of?(Attributes) and var.has_attribute('sizeof_packed')) or type.has_attribute('sizeof_packed')
  1446. lm = type.members.last
  1447. lm ? (type.offsetof(self, lm) + sizeof(lm) + al - 1) / al * al : 0
  1448. when Union
  1449. raise self, "unknown structure size #{type.name}" if not type.members
  1450. type.members.map { |m| sizeof(m) }.max || 0
  1451. when TypeDef
  1452. sizeof(var, type.type)
  1453. end
  1454. end
  1455. # parses variable/function definition/declaration/initialization
  1456. # populates scope.symbols and scope.struct
  1457. # raises on redefinitions
  1458. # returns false if no definition found
  1459. def parse_definition(scope)
  1460. return false if not basetype = Variable.parse_type(self, scope, true)
  1461. # check struct predeclaration
  1462. tok = skipspaces
  1463. if tok and tok.type == :punct and tok.raw == ';' and basetype.type and
  1464. (basetype.type.kind_of? Union or basetype.type.kind_of? Enum)
  1465. return true
  1466. else unreadtok tok
  1467. end
  1468. nofunc = false
  1469. loop do
  1470. var = basetype.dup
  1471. var.parse_declarator(self, scope)
  1472. raise var.backtrace if not var.name # barrel roll
  1473. if prev = scope.symbol[var.name]
  1474. if prev.kind_of? TypeDef and var.storage == :typedef
  1475. check_compatible_type(var.backtrace, prev.type, var.type, true)
  1476. # windows.h redefines many typedefs with the same definition
  1477. puts "redefining typedef #{var.name}" if $VERBOSE
  1478. var = prev
  1479. elsif not prev.kind_of?(Variable) or
  1480. prev.initializer or
  1481. (prev.storage != :extern and prev.storage != var.storage) or
  1482. (scope != @toplevel and prev.storage != :static)
  1483. if prev.kind_of? ::Integer # enum value
  1484. prev = (scope.struct.values.grep(Enum) + scope.anonymous_enums.to_a).find { |e| e.members.index(prev) }
  1485. end
  1486. raise var.backtrace, "redefinition, previous is #{prev.backtrace.exception(nil).message rescue :unknown}"
  1487. else
  1488. check_compatible_type var.backtrace, prev.type, var.type, true
  1489. (var.attributes ||= []).concat prev.attributes if prev.attributes
  1490. end
  1491. elsif var.storage == :typedef
  1492. attrs = var.attributes
  1493. var = TypeDef.new var.name, var.type, var.backtrace
  1494. var.attributes = attrs if attrs
  1495. end
  1496. scope.statements << Declaration.new(var) unless var.kind_of? TypeDef
  1497. raise tok || self, 'punctuation expected' if not tok = skipspaces or (tok.type != :punct and not %w[asm __asm __asm__].include? tok.raw)
  1498. case tok.raw
  1499. when '{'
  1500. # function body
  1501. raise tok if nofunc or not var.kind_of? Variable or not var.type.kind_of? Function
  1502. scope.symbol[var.name] = var
  1503. body = var.initializer = Block.new(scope)
  1504. var.type.args ||= []
  1505. var.type.args.each { |v|
  1506. # put func parameters in func body scope
  1507. # arg redefinition is checked in parse_declarator
  1508. if not v.name
  1509. puts "unnamed argument in definition of #{var.name}" if $DEBUG
  1510. next # should raise to be compliant
  1511. end
  1512. body.symbol[v.name] = v # XXX will need special check in stack allocator
  1513. }
  1514. loop do
  1515. raise tok || self, var.backtrace.exception('"}" expected for end of function') if not tok = skipspaces
  1516. break if tok.type == :punct and tok.raw == '}'
  1517. unreadtok tok
  1518. if not parse_definition(body)
  1519. body.statements << parse_statement(body, [var.type.type])
  1520. end
  1521. end
  1522. if $VERBOSE and not body.statements.last.kind_of? Return and not body.statements.last.kind_of? Asm
  1523. puts tok.exception('missing function return value').message if not var.type.type.untypedef.kind_of? BaseType or var.type.type.untypedef.name != :void
  1524. end
  1525. break
  1526. when 'asm', '__asm', '__asm__'
  1527. # GCC function redirection
  1528. # void foo(void) __asm__("bar"); => when code uses 'foo', silently redirect to 'bar' instead
  1529. raise tok if nofunc or not var.kind_of? Variable or not var.type.kind_of? Function
  1530. # most of the time, 'bar' is not defined anywhere, so we support it only
  1531. # to allow parsing of headers using it, hoping noone will actually use them
  1532. unused = Asm.parse(self, scope)
  1533. puts "unsupported gcc-style __asm__ function redirect #{var.name.inspect} => #{unused.body.inspect}" if $VERBOSE
  1534. break
  1535. when '='
  1536. # variable initialization
  1537. raise tok, '"{" or ";" expected' if var.type.kind_of? Function
  1538. raise tok, 'cannot initialize extern variable' if var.storage == :extern
  1539. scope.symbol[var.name] = var # allow initializer to reference var, eg 'void *ptr = &ptr;'
  1540. var.initializer = var.type.parse_initializer(self, scope)
  1541. if var.initializer.kind_of?(CExpression) and (scope == @toplevel or var.storage == :static)
  1542. raise tok, "initializer for static #{var.name} is not constant" if not var.initializer.constant?
  1543. end
  1544. reference_value = lambda { |e, v|
  1545. found = false
  1546. case e
  1547. when Variable; found = true if e == v
  1548. when CExpression; e.walk { |ee| found ||= reference_value[ee, v] } if e.op != :& or e.lexpr
  1549. end
  1550. found
  1551. }
  1552. raise tok, "initializer for #{var.name} is not constant (selfreference)" if reference_value[var.initializer, var]
  1553. raise tok || self, '"," or ";" expected' if not tok = skipspaces or tok.type != :punct
  1554. else
  1555. scope.symbol[var.name] = var
  1556. end
  1557. case tok.raw
  1558. when ','; nofunc = true
  1559. when ';'; break
  1560. when '}'; unreadtok(tok); break
  1561. else raise tok, '";" or "," expected'
  1562. end
  1563. end
  1564. true
  1565. end
  1566. # parses toplevel statements, return nil if none found
  1567. # toplevel statements are ';' and 'asm <..>'
  1568. def parse_toplevel_statement(scope)
  1569. if tok = skipspaces and tok.type == :punct and tok.raw == ';'
  1570. true
  1571. elsif tok and tok.type == :punct and tok.raw == '{'
  1572. raise tok || self, '"}" expected' if not tok = skipspaces or tok.type != :punct or tok.raw != '}'
  1573. true
  1574. elsif tok and tok.type == :string and %w[asm __asm __asm__].include? tok.raw
  1575. scope.statements << Asm.parse(self, scope)
  1576. true
  1577. end
  1578. end
  1579. # returns a statement or raise
  1580. def parse_statement(scope, nest)
  1581. raise self, 'statement expected' if not tok = skipspaces
  1582. if tok.type == :punct and tok.raw == '{'
  1583. body = Block.new scope
  1584. loop do
  1585. raise tok || self, '"}" expected' if not tok = skipspaces
  1586. break if tok.type == :punct and tok.raw == '}'
  1587. unreadtok tok
  1588. if not parse_definition(body)
  1589. body.statements << parse_statement(body, nest)
  1590. end
  1591. end
  1592. return body
  1593. elsif tok.type == :punct and tok.raw == ';'
  1594. return Block.new(scope)
  1595. elsif tok.type != :string
  1596. unreadtok tok
  1597. raise tok, 'expr expected' if not expr = CExpression.parse(self, scope)
  1598. checkstatementend(tok)
  1599. if $VERBOSE and not nest.include?(:expression) and (expr.op or not expr.type.untypedef.kind_of? BaseType or expr.type.untypedef.name != :void) and CExpression.constant?(expr)
  1600. puts tok.exception("statement with no effect : #{expr}").message
  1601. end
  1602. return expr
  1603. end
  1604. case tok.raw
  1605. when 'if'
  1606. If.parse self, scope, nest
  1607. when 'while'
  1608. While.parse self, scope, nest
  1609. when 'do'
  1610. DoWhile.parse self, scope, nest
  1611. when 'for'
  1612. For.parse self, scope, nest
  1613. when 'switch'
  1614. Switch.parse self, scope, nest
  1615. when 'goto'
  1616. raise tok || self, 'label expected' if not tok = skipspaces or tok.type != :string
  1617. name = tok.raw
  1618. checkstatementend(tok)
  1619. Goto.new name
  1620. when 'return'
  1621. expr = CExpression.parse(self, scope) # nil allowed
  1622. raise tok || self, "cannot return #{expr} in function returning void" if expr and nest[0].kind_of?(Type) and nest[0].void?
  1623. p, i = nest[0].pointer?, nest[0].integral? if expr
  1624. r = expr.reduce(self) if p or i
  1625. if (not p and not i) or (i and not r.kind_of? ::Integer) or (p and r != 0)
  1626. check_compatible_type(tok, (expr ? expr.type : BaseType.new(:void)), nest[0])
  1627. end
  1628. checkstatementend(tok)
  1629. Return.new expr
  1630. when 'case'
  1631. raise tok, 'case out of switch' if not nest.include? :switch
  1632. Case.parse self, scope, nest
  1633. when 'default'
  1634. raise tok || self, '":" expected' if not tok = skipspaces or tok.type != :punct or tok.raw != ':'
  1635. raise tok, 'case out of switch' if not nest.include? :switch
  1636. Case.new 'default', nil, parse_statement(scope, nest)
  1637. when 'continue'
  1638. checkstatementend(tok)
  1639. raise tok, 'continue out of loop' if not nest.include? :loop
  1640. Continue.new
  1641. when 'break'
  1642. checkstatementend(tok)
  1643. raise tok, 'break out of loop' if not nest.include? :loop and not nest.include? :switch
  1644. Break.new
  1645. when 'asm', '__asm', '__asm__'
  1646. Asm.parse self, scope
  1647. else
  1648. if ntok = skipspaces and ntok.type == :punct and ntok.raw == ':'
  1649. begin
  1650. st = parse_statement(scope, nest)
  1651. rescue ParseError
  1652. puts "label without statement, #{$!.message}" if $VERBOSE
  1653. end
  1654. Label.new tok.raw, st
  1655. else
  1656. unreadtok ntok
  1657. unreadtok tok
  1658. raise tok, 'expr expected' if not expr = CExpression.parse(self, scope)
  1659. checkstatementend(tok)
  1660. if $VERBOSE and not nest.include?(:expression) and (expr.op or not expr.type.untypedef.kind_of? BaseType or expr.type.untypedef.name != :void) and CExpression.constant?(expr)
  1661. puts tok.exception("statement with no effect : #{expr}").message
  1662. end
  1663. expr
  1664. end
  1665. end
  1666. end
  1667. # check if a macro definition has a numeric value
  1668. # returns this value or nil
  1669. def macro_numeric(m)
  1670. d = @lexer.definition[m]
  1671. return if not d.kind_of? Preprocessor::Macro or d.args or d.varargs
  1672. # filter metasm-defined vars (eg __PE__ / _M_IX86)
  1673. return if not d.name or not bt = d.name.backtrace or (bt[0][0] != ?" and bt[0][0] != ?<)
  1674. raise 'cannot macro_numeric with unparsed data' if not eos?
  1675. @lexer.feed m
  1676. if e = CExpression.parse(self, Block.new(@toplevel)) and eos?
  1677. v = e.reduce(self)
  1678. return v if v.kind_of? ::Numeric
  1679. end
  1680. readtok until eos?
  1681. nil
  1682. rescue ParseError
  1683. readtok until eos?
  1684. nil
  1685. end
  1686. # returns all numeric constants defined with their value, either macros or enums
  1687. # for enums, also return the enum name
  1688. def numeric_constants
  1689. ret = []
  1690. # macros
  1691. @lexer.definition.each_key { |k|
  1692. if v = macro_numeric(k)
  1693. ret << [k, v]
  1694. end
  1695. }
  1696. # enums
  1697. seen_enum = {}
  1698. @toplevel.struct.each { |k, v|
  1699. if v.kind_of?(Enum)
  1700. v.members.each { |kk, vv|
  1701. ret << [kk, vv, k]
  1702. seen_enum[kk] = true
  1703. }
  1704. end
  1705. }
  1706. @toplevel.symbol.each { |k, v|
  1707. ret << [k, v] if v.kind_of?(::Numeric) and not seen_enum[k]
  1708. }
  1709. ret
  1710. end
  1711. end
  1712. class Variable
  1713. # parses a variable basetype/qualifier/(storage if allow_value), returns a new variable of this type
  1714. # populates scope.struct
  1715. def self.parse_type(parser, scope, allow_value = false)
  1716. var = new
  1717. qualifier = []
  1718. tok = nil
  1719. loop do
  1720. var.parse_attributes(parser, true)
  1721. break if not tok = parser.skipspaces
  1722. if tok.type != :string
  1723. parser.unreadtok tok
  1724. break
  1725. end
  1726. case tok.raw
  1727. when 'const', 'volatile'
  1728. qualifier << tok.raw.to_sym
  1729. next
  1730. when 'register', 'auto', 'static', 'typedef', 'extern'
  1731. raise tok, 'storage specifier not allowed here' if not allow_value
  1732. raise tok, 'multiple storage class' if var.storage
  1733. var.storage = tok.raw.to_sym
  1734. next
  1735. when 'struct'
  1736. var.type = Struct.new
  1737. var.type.pack = parser.pragma_pack if parser.pragma_pack
  1738. var.parse_type_struct(parser, scope)
  1739. when 'union'
  1740. var.type = Union.new
  1741. var.parse_type_struct(parser, scope)
  1742. when 'enum'
  1743. var.type = Enum.new
  1744. var.parse_type_struct(parser, scope)
  1745. when 'typeof'
  1746. if ntok = parser.skipspaces and ntok.type == :punct and ntok.raw == '('
  1747. # check type
  1748. if v = parse_type(parser, scope)
  1749. v.parse_declarator(parser, scope)
  1750. raise tok if v.name != false
  1751. raise tok if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
  1752. else
  1753. raise tok, 'expr expected' if not v = CExpression.parse(parser, scope)
  1754. raise tok if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
  1755. end
  1756. else
  1757. parser.unreadtok ntok
  1758. raise tok, 'expr expected' if not v = CExpression.parse_value(parser, scope)
  1759. end
  1760. var.type = v.type # TypeDef.new('typeof', v.type, tok)
  1761. when 'long', 'short', 'signed', 'unsigned', 'int', 'char', 'float', 'double',
  1762. 'void', '__int8', '__int16', '__int32', '__int64',
  1763. 'intptr_t', 'uintptr_t'
  1764. parser.unreadtok tok
  1765. var.parse_type_base(parser, scope)
  1766. else
  1767. if type = scope.symbol_ancestors[tok.raw] and type.kind_of? TypeDef
  1768. var.type = type.dup
  1769. else
  1770. parser.unreadtok tok
  1771. end
  1772. end
  1773. break
  1774. end
  1775. if not var.type
  1776. raise tok || parser, 'bad type name' if not qualifier.empty? or var.storage
  1777. nil
  1778. else
  1779. var.type.qualifier = var.type.qualifier.to_a | qualifier if not qualifier.empty?
  1780. var.type.parse_attributes(parser, true)
  1781. var
  1782. end
  1783. end
  1784. # parses a structure/union/enum declaration
  1785. def parse_type_struct(parser, scope)
  1786. @type.parse_attributes(parser)
  1787. if tok = parser.skipspaces and tok.type == :punct and tok.raw == '{'
  1788. # anonymous struct, ok
  1789. @type.backtrace = tok
  1790. if @type.kind_of? Enum
  1791. (scope.anonymous_enums ||= []) << @type
  1792. end
  1793. elsif tok and tok.type == :string
  1794. name = tok.raw
  1795. raise tok, 'bad struct name' if Keyword[name] or (?0..?9).include?(name[0])
  1796. @type.backtrace = tok
  1797. @type.name = name
  1798. @type.parse_attributes(parser)
  1799. raise parser if not ntok = parser.skipspaces
  1800. if ntok.type != :punct or ntok.raw != '{'
  1801. raise tok, "struct/union confusion" if scope.struct[name] and scope.struct[name].class != @type.class
  1802. # variable declaration
  1803. parser.unreadtok ntok
  1804. if ntok.type == :punct and ntok.raw == ';'
  1805. # struct predeclaration
  1806. # allow redefinition
  1807. @type = scope.struct[name] ||= @type
  1808. else
  1809. # check that the structure exists
  1810. struct = scope.struct_ancestors[name]
  1811. # allow incomplete types, usage as var type will raise later
  1812. struct = scope.struct[name] = @type if not struct
  1813. raise tok, 'unknown struct' if struct.class != @type.class
  1814. (struct.attributes ||= []).concat @type.attributes if @type.attributes
  1815. (struct.qualifier ||= []).concat @type.qualifier if @type.qualifier # XXX const struct foo bar => bar is const, not foo...
  1816. @type = struct
  1817. end
  1818. return
  1819. end
  1820. if scope.struct[name] and scope.struct[name].members
  1821. # redefinition of an existing struct, save for later comparison
  1822. oldstruct = scope.struct[name]
  1823. raise tok, "struct/union confusion" if oldstruct.class != @type.class
  1824. elsif struct = scope.struct[name]
  1825. raise tok, "struct/union confusion" if struct.class != @type.class
  1826. (struct.attributes ||= []).concat @type.attributes if @type.attributes
  1827. (struct.qualifier ||= []).concat @type.qualifier if @type.qualifier
  1828. struct.backtrace = @type.backtrace
  1829. struct.name = @type.name
  1830. @type = struct
  1831. else
  1832. scope.struct[name] = @type
  1833. end
  1834. else
  1835. raise tok || parser, 'struct name or "{" expected'
  1836. end
  1837. @type.parse_members(parser, scope)
  1838. if oldstruct
  1839. if not @type.compare_deep(oldstruct)
  1840. raise tok, "conflicting struct redefinition (old at #{oldstruct.backtrace.exception(nil).message rescue :unknown})"
  1841. end
  1842. @type = oldstruct
  1843. end
  1844. end
  1845. # parses int/long int/long long/double etc
  1846. def parse_type_base(parser, scope)
  1847. specifier = []
  1848. qualifier = []
  1849. name = :int
  1850. tok = nil
  1851. loop do
  1852. if not tok = parser.skipspaces
  1853. raise parser if specifier.empty?
  1854. break
  1855. end
  1856. if tok.type != :string
  1857. parser.unreadtok tok
  1858. break
  1859. end
  1860. case tok.raw
  1861. when 'const', 'volatile'
  1862. qualifier << tok.raw.to_sym
  1863. when 'long', 'short', 'signed', 'unsigned'
  1864. specifier << tok.raw.to_sym
  1865. when 'int', 'char', 'void', 'float', 'double', '__int8', '__int16', '__int32', '__int64'
  1866. name = tok.raw.to_sym
  1867. break
  1868. when 'intptr_t', 'uintptr_t'
  1869. name = :ptr
  1870. specifier << :unsigned if tok.raw == 'uintptr_t'
  1871. break
  1872. else
  1873. parser.unreadtok tok
  1874. break
  1875. end
  1876. end
  1877. case name
  1878. when :double # long double
  1879. if specifier == [:long]
  1880. name = :longdouble
  1881. specifier.clear
  1882. elsif not specifier.empty?
  1883. raise tok || parser, 'invalid specifier list'
  1884. end
  1885. when :int # short, long, long long X signed, unsigned
  1886. # Array#count not available on old ruby (eg 1.8.4), so use ary.len - (ary-stuff).len
  1887. specifier = specifier - [:long] + [:longlong] if specifier.length - (specifier-[:long]).length == 2
  1888. if specifier.length - (specifier-[:signed, :unsigned]).length > 1 or specifier.length - (specifier-[:short, :long, :longlong]).length > 1
  1889. raise tok || parser, 'invalid specifier list'
  1890. else
  1891. name = (specifier & [:longlong, :long, :short])[0] || :int
  1892. specifier -= [:longlong, :long, :short]
  1893. end
  1894. specifier.delete :signed # default
  1895. when :char # signed, unsigned
  1896. # signed char != char and unsigned char != char
  1897. if (specifier & [:signed, :unsigned]).length > 1 or (specifier & [:short, :long]).length > 0
  1898. raise tok || parser, 'invalid specifier list'
  1899. end
  1900. when :__int8, :__int16, :__int32, :__int64, :ptr
  1901. if (specifier & [:signed, :unsigned]).length > 1 or (specifier & [:short, :long]).length > 0
  1902. raise tok || parser, 'invalid specifier list'
  1903. end
  1904. specifier.delete :signed # default
  1905. else # none
  1906. raise tok || parser, 'invalid type' if not specifier.empty?
  1907. end
  1908. @type = BaseType.new(name, *specifier)
  1909. @type.qualifier = qualifier if not qualifier.empty?
  1910. end
  1911. # updates @type and @name, parses pointer/arrays/function declarations
  1912. # parses anonymous declarators (@name will be false)
  1913. # the caller is responsible for detecting redefinitions
  1914. # scope used only in CExpression.parse for array sizes and function prototype argument types
  1915. # rec for internal use only
  1916. def parse_declarator(parser, scope, rec = false)
  1917. parse_attributes(parser, true)
  1918. tok = parser.skipspaces
  1919. # read upto name
  1920. if tok and tok.type == :punct and tok.raw == '*'
  1921. ptr = Pointer.new
  1922. ptr.parse_attributes(parser)
  1923. while ntok = parser.skipspaces and ntok.type == :string
  1924. case ntok.raw
  1925. when 'const', 'volatile'
  1926. (ptr.qualifier ||= []) << ntok.raw.to_sym
  1927. ptr.parse_attributes(parser)
  1928. else break
  1929. end
  1930. end
  1931. parser.unreadtok ntok
  1932. parse_declarator(parser, scope, true)
  1933. t = self
  1934. t = t.type while t.type and (t.type.kind_of?(Pointer) or t.type.kind_of?(Function))
  1935. ptr.type = t.type
  1936. t.type = ptr
  1937. if t.kind_of? Function and ptr.attributes
  1938. @attributes ||= []
  1939. @attributes |= ptr.attributes
  1940. ptr.attributes = nil
  1941. end
  1942. return
  1943. elsif tok and tok.type == :punct and tok.raw == '('
  1944. parse_declarator(parser, scope, true)
  1945. raise tok || parser, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
  1946. elsif tok and tok.type == :string
  1947. case tok.raw
  1948. when 'const', 'volatile'
  1949. (@type.qualifier ||= []) << tok.raw.to_sym
  1950. return parse_declarator(parser, scope, rec)
  1951. when 'register', 'auto', 'static', 'typedef', 'extern'
  1952. raise tok, 'multiple storage class' if storage
  1953. @storage = tok.raw.to_sym
  1954. puts tok.exception('misplaced storage specifier').message if $VERBOSE
  1955. return parse_declarator(parser, scope, rec)
  1956. end
  1957. raise tok if name or name == false
  1958. raise tok, 'bad var name' if Keyword[tok.raw] or (?0..?9).include?(tok.raw[0])
  1959. @name = tok.raw
  1960. @backtrace = tok
  1961. parse_attributes(parser, true)
  1962. else
  1963. # unnamed
  1964. raise tok || parser if name or name == false
  1965. @name = false
  1966. @backtrace = tok
  1967. parser.unreadtok tok
  1968. parse_attributes(parser, true)
  1969. end
  1970. parse_declarator_postfix(parser, scope)
  1971. if not rec
  1972. raise @backtrace, 'void type is invalid' if name and (t = @type.untypedef).kind_of? BaseType and
  1973. t.name == :void and storage != :typedef
  1974. raise @backtrace, "incomplete type #{@type.name}" if (@type.kind_of? Union or @type.kind_of? Enum) and
  1975. not @type.members and storage != :typedef and storage != :extern # gcc uses an undefined extern struct just to cast it later (_IO_FILE_plus)
  1976. end
  1977. end
  1978. # parses array/function type
  1979. def parse_declarator_postfix(parser, scope)
  1980. if tok = parser.skipspaces and tok.type == :punct and tok.raw == '['
  1981. # array indexing
  1982. idx = CExpression.parse(parser, scope) # may be nil
  1983. if idx and (scope == parser.toplevel or storage == :static)
  1984. raise tok, 'array size is not constant' if not idx.constant?
  1985. idx = idx.reduce(parser)
  1986. elsif idx and nidx = idx.reduce(parser) and nidx.kind_of? ::Integer
  1987. idx = nidx
  1988. end
  1989. t = self
  1990. t = t.type while t.type and (t.type.kind_of?(Pointer) or t.type.kind_of?(Function))
  1991. t.type = Array.new t.type
  1992. t.type.length = idx
  1993. raise tok || parser, '"]" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ']'
  1994. parse_attributes(parser) # should be type.attrs, but this is should be more compiler-compatible
  1995. elsif tok and tok.type == :punct and tok.raw == '('
  1996. # function prototype
  1997. # void __attribute__((noreturn)) func() => attribute belongs to func
  1998. if @type and @type.attributes
  1999. @attributes ||= []
  2000. @attributes |= @type.attributes
  2001. @type.attributes = nil
  2002. end
  2003. t = self
  2004. t = t.type while t.type and (t.type.kind_of?(Pointer) or t.type.kind_of?(Function))
  2005. t.type = Function.new t.type
  2006. if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
  2007. parser.unreadtok tok
  2008. t.type.args = []
  2009. oldstyle = false # int func(a, b) int a; double b; { stuff; }
  2010. loop do
  2011. raise parser if not tok = parser.skipspaces
  2012. if tok.type == :punct and tok.raw == '.' # variadic function
  2013. raise parser, '".." expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '.'
  2014. raise parser, '"." expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '.'
  2015. raise parser, '")" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ')'
  2016. t.type.varargs = true
  2017. break
  2018. elsif tok.type == :string and tok.raw == 'register'
  2019. storage = :register
  2020. else
  2021. parser.unreadtok tok
  2022. end
  2023. if oldstyle or not v = Variable.parse_type(parser, scope)
  2024. raise tok if not @name # no oldstyle in casts
  2025. tok = parser.skipspaces
  2026. oldstyle ||= [tok] # arg to raise() later
  2027. oldstyle << tok.raw
  2028. else
  2029. v.storage = storage if storage
  2030. v.parse_declarator(parser, scope)
  2031. v.type = Pointer.new(v.type.type) if v.type.kind_of? Array
  2032. v.type = Pointer.new(v.type) if v.type.kind_of? Function
  2033. t.type.args << v if not v.type.untypedef.kind_of? BaseType or v.type.untypedef.name != :void
  2034. end
  2035. if tok = parser.skipspaces and tok.type == :punct and tok.raw == ','
  2036. raise tok, '")" expected' if v and t.type.args.last != v # last arg of type :void
  2037. elsif tok and tok.type == :punct and tok.raw == ')'
  2038. break
  2039. else raise tok || parser, '"," or ")" expected'
  2040. end
  2041. end
  2042. if oldstyle
  2043. parse_attributes(parser, true)
  2044. ra = oldstyle.shift
  2045. while t.type.args.compact.length != oldstyle.length
  2046. raise ra, "invalid prototype" if not vb = Variable.parse_type(parser, scope)
  2047. loop do
  2048. v = vb.dup
  2049. v.parse_declarator(parser, scope)
  2050. v.type = Pointer.new(v.type.type) if v.type.kind_of? Array
  2051. v.type = Pointer.new(v.type) if v.type.kind_of? Function
  2052. raise parser, "unknown arg #{v.name.inspect}" if not i = oldstyle.index(v.name)
  2053. t.type.args[i] = v
  2054. raise parser, '"," or ";" expected' if not tok = parser.skipspaces or tok.type != :punct or (tok.raw != ';' and tok.raw != ',')
  2055. break if tok.raw == ';'
  2056. end
  2057. end
  2058. parse_attributes(parser, true)
  2059. raise parser, '"{" expected' if not tok = parser.skipspaces or tok.type != :punct or tok.raw != '{'
  2060. parser.unreadtok tok
  2061. end
  2062. namedargs = t.type.args.map { |a| a.name }.compact - [false]
  2063. raise tok, "duplicate argument name #{namedargs.find { |a| namedargs.index(a) != namedargs.rindex(a) }.inspect}" if namedargs.length != namedargs.uniq.length
  2064. end
  2065. parse_attributes(parser, true) # should be type.attrs, but this should be more existing-compiler-compatible
  2066. else
  2067. parser.unreadtok tok
  2068. return
  2069. end
  2070. parse_declarator_postfix(parser, scope)
  2071. end
  2072. end
  2073. class Variable
  2074. def ===(o)
  2075. self == o or (o.class == CExpression and not o.op and o.rexpr == self)
  2076. end
  2077. end
  2078. class CExpression
  2079. def self.lvalue?(e)
  2080. e.kind_of?(self) ? e.lvalue? : (e.kind_of? Variable and e.name)
  2081. end
  2082. def lvalue?
  2083. case @op
  2084. when :*; true if not @lexpr
  2085. when :'[]', :'.', :'->'; true
  2086. when nil # cast
  2087. CExpression.lvalue?(@rexpr)
  2088. else false
  2089. end
  2090. end
  2091. def self.constant?(e)
  2092. e.kind_of?(self) ? e.constant? : true
  2093. end
  2094. def constant?
  2095. # gcc considers '1, 2' not constant
  2096. if [:',', :funcall, :'=', :'--', :'++', :'+=', :'-=', :'*=', :'/=', :'>>=', :'<<=', :'&=', :'|=', :'^=', :'%=', :'->', :'[]'].include?(@op)
  2097. false
  2098. elsif @op == :'*' and not @lexpr; false
  2099. elsif not @lexpr and not @op and @rexpr.kind_of? Block; false
  2100. else
  2101. out = true
  2102. walk { |e| break out = false if not CExpression.constant?(e) }
  2103. out
  2104. end
  2105. end
  2106. def self.reduce(parser, e)
  2107. e.kind_of?(self) ? e.reduce(parser) : e
  2108. end
  2109. def reduce(parser)
  2110. # parser used for arithmetic overflows (need basic type sizes)
  2111. case @op
  2112. when :'&&'
  2113. case l = CExpression.reduce(parser, @lexpr)
  2114. when 0; 0
  2115. when ::Integer
  2116. case r = CExpression.reduce(parser, @rexpr)
  2117. when 0; 0
  2118. when ::Integer; 1
  2119. else CExpression.new(l, @op, r, @type)
  2120. end
  2121. else CExpression.new(l, @op, @rexpr, @type)
  2122. end
  2123. when :'||'
  2124. case l = CExpression.reduce(parser, @lexpr)
  2125. when 0
  2126. case r = CExpression.reduce(parser, @rexpr)
  2127. when 0; 0
  2128. when ::Integer; 1
  2129. else CExpression.new(l, @op, r, @type)
  2130. end
  2131. when ::Integer; 1
  2132. else CExpression.new(l, @op, @rexpr, @type)
  2133. end
  2134. when :'!'
  2135. case r = CExpression.reduce(parser, @rexpr)
  2136. when 0; 1
  2137. when ::Integer; 0
  2138. else CExpression.new(nil, @op, r, @type)
  2139. end
  2140. when :'!=', :'==', :'<', :'>', :'>=', :'<='
  2141. l = CExpression.reduce(parser, @lexpr)
  2142. r = CExpression.reduce(parser, @rexpr)
  2143. if l.kind_of?(::Integer) and r.kind_of?(::Integer)
  2144. if @op == :'!='; l != r ? 1 : 0
  2145. else l.send(@op, r) ? 1 : 0
  2146. end
  2147. else
  2148. l = CExpression.new(nil, nil, l, BaseType.new(:int)) if l.kind_of? ::Integer
  2149. r = CExpression.new(nil, nil, r, BaseType.new(:int)) if r.kind_of? ::Integer
  2150. CExpression.new(l, @op, r, @type)
  2151. end
  2152. when :'.'
  2153. le = CExpression.reduce(parser, @lexpr)
  2154. if le.kind_of? Variable and le.initializer.kind_of? ::Array
  2155. t = le.type.untypedef
  2156. midx = t.members.index(t.findmember(@rexpr))
  2157. CExpression.reduce(parser, le.initializer[midx] || 0)
  2158. else
  2159. CExpression.new(le, @op, @rexpr, @type)
  2160. end
  2161. when :'?:'
  2162. case c = CExpression.reduce(parser, @lexpr)
  2163. when 0; CExpression.reduce(parser, @rexpr[0])
  2164. when ::Integer; CExpression.reduce(parser, @rexpr[1])
  2165. else CExpression.new(c, @op, @rexpr, @type)
  2166. end
  2167. when :'+', :'-', :'*', :'/', :'^', :'%', :'&', :'|', :'>>', :'<<', :'~', nil
  2168. t = @type.untypedef
  2169. case t
  2170. when BaseType
  2171. when Pointer; return self if @op
  2172. else
  2173. return @rexpr if not @op and not @lexpr and @rexpr.kind_of? Variable and @rexpr.type == @type
  2174. return self # raise parser, 'not arithmetic type'
  2175. end
  2176. # compute value
  2177. r = CExpression.reduce(parser, @rexpr)
  2178. ret = \
  2179. if not @lexpr
  2180. # unary
  2181. case @op
  2182. when :'+', nil, :'-', :'~'
  2183. return CExpression.new(nil, @op, r, @type) if not r.kind_of? ::Numeric
  2184. case @op
  2185. when :'-'; -r
  2186. when :'~'; ~r
  2187. else r
  2188. end
  2189. else return CExpression.new(nil, @op, r, @type)
  2190. end
  2191. else
  2192. l = CExpression.reduce(parser, @lexpr)
  2193. if not l.kind_of?(::Numeric) or not r.kind_of?(::Numeric)
  2194. l = CExpression.new(nil, nil, l, BaseType.new(:int)) if l.kind_of? ::Integer
  2195. r = CExpression.new(nil, nil, r, BaseType.new(:int)) if r.kind_of? ::Integer
  2196. return CExpression.new(l, @op, r, @type)
  2197. end
  2198. l.send(@op, r)
  2199. end
  2200. # overflow
  2201. tn = (t.pointer? ? :ptr : t.name)
  2202. case tn
  2203. when :char, :short, :int, :long, :ptr, :longlong, :__int8, :__int16, :__int32, :__int64
  2204. max = 1 << (8*parser.typesize[tn])
  2205. ret = ret.to_i & (max-1)
  2206. if not t.pointer? and t.specifier != :unsigned and (ret & (max >> 1)) > 0 # char == unsigned char
  2207. ret - max
  2208. else
  2209. ret
  2210. end
  2211. when :float, :double, :longdouble
  2212. ret.to_f # TODO
  2213. end
  2214. when :funcall
  2215. l = CExpression.reduce(parser, @lexpr)
  2216. r = @rexpr.map { |rr|
  2217. rr = CExpression.reduce(parser, rr)
  2218. rr = CExpression.new(nil, nil, rr, BaseType.new(:int)) if rr.kind_of? ::Integer
  2219. rr
  2220. }
  2221. CExpression.new(l, @op, r, @type)
  2222. else
  2223. l = CExpression.reduce(parser, @lexpr) if @lexpr
  2224. r = CExpression.reduce(parser, @rexpr) if @rexpr
  2225. l = CExpression.new(nil, nil, l, BaseType.new(:int)) if l.kind_of? ::Integer
  2226. r = CExpression.new(nil, nil, r, BaseType.new(:int)) if r.kind_of? ::Integer
  2227. CExpression.new(l, @op, r, @type)
  2228. end
  2229. end
  2230. def ==(o)
  2231. o.object_id == self.object_id or
  2232. (self.class == o.class and op == o.op and lexpr == o.lexpr and rexpr == o.rexpr)
  2233. end
  2234. def ===(o)
  2235. (self.class == o.class and op == o.op and lexpr === o.lexpr and rexpr === o.rexpr) or
  2236. (o.class == Variable and not @op and @rexpr == o)
  2237. end
  2238. NegateOp = { :== => :'!=', :'!=' => :==, :> => :<=, :>= => :<, :< => :>=, :<= => :> }
  2239. # returns a CExpr negating this one (eg 'x' => '!x', 'a > b' => 'a <= b'...)
  2240. def self.negate(e)
  2241. e.kind_of?(self) ? e.negate : CExpression[:'!', e]
  2242. end
  2243. def negate
  2244. if @op == :'!'
  2245. CExpression[@rexpr]
  2246. elsif nop = NegateOp[@op]
  2247. if nop == :== and @rexpr.kind_of? CExpression and not @rexpr.op and @rexpr.rexpr == 0 and
  2248. @lexpr.kind_of? CExpression and [:==, :'!=', :>, :<, :>=, :<=, :'!'].include? @lexpr.op
  2249. # (a > b) != 0 => (a > b)
  2250. CExpression[@lexpr]
  2251. else
  2252. CExpression.new(@lexpr, nop, @rexpr, @type)
  2253. end
  2254. elsif nop = { :'||' => :'&&', :'&&' => :'||' }[@op]
  2255. CExpression.new(CExpression.negate(@lexpr), nop, CExpression.negate(@rexpr), @type)
  2256. else
  2257. CExpression[:'!', self]
  2258. end
  2259. end
  2260. def walk
  2261. case @op
  2262. when :funcall, :'?:'
  2263. yield @lexpr
  2264. @rexpr.each { |arg| yield arg }
  2265. when :'->', :'.'
  2266. yield @lexpr
  2267. else
  2268. yield @lexpr if @lexpr
  2269. yield @rexpr if @rexpr
  2270. end
  2271. end
  2272. def complexity
  2273. cx = 1
  2274. walk { |e| cx += e.complexity if e.kind_of?(CExpression) }
  2275. cx
  2276. end
  2277. RIGHTASSOC = [:'=', :'+=', :'-=', :'*=', :'/=', :'%=', :'&=',
  2278. :'|=', :'^=', :'<<=', :'>>=', :'?:'
  2279. ].inject({}) { |h, op| h.update op => true }
  2280. # key = operator, value = hash regrouping operators of lower precedence
  2281. # funcall/array index/member dereference/sizeof are handled in parse_value
  2282. OP_PRIO = [[:','], [:'?:'], [:'=', :'+=', :'-=', :'*=', :'/=',
  2283. :'%=', :'&=', :'|=', :'^=', :'<<=', :'>>='], [:'||'],
  2284. [:'&&'], [:|], [:^], [:&], [:'==', :'!='],
  2285. [:'<', :'>', :'<=', :'>='], [:<<, :>>], [:+, :-],
  2286. [:*, :/, :%], ].inject({}) { |h, oplist|
  2287. lessprio = h.keys.inject({}) { |hh, op| hh.update op => true }
  2288. oplist.each { |op| lessprio.update op => true } if RIGHTASSOC[oplist.first]
  2289. oplist.each { |op| h[op] = lessprio }
  2290. h }
  2291. class << self
  2292. # reads a binary operator from the parser, returns the corresponding symbol or nil
  2293. def readop(parser)
  2294. if not op = parser.skipspaces or op.type != :punct
  2295. parser.unreadtok op
  2296. return
  2297. end
  2298. case op.raw
  2299. when '>', '<', '|', '&' # << >> || &&
  2300. if ntok = parser.readtok and ntok.type == :punct and ntok.raw == op.raw
  2301. op.raw << ntok.raw
  2302. else
  2303. parser.unreadtok ntok
  2304. end
  2305. when '!' # != (mandatory)
  2306. if not ntok = parser.readtok or ntok.type != :punct and ntok.raw != '='
  2307. parser.unreadtok op
  2308. return
  2309. end
  2310. op.raw << ntok.raw
  2311. when '+', '-', '*', '/', '%', '^', '=', ',', '?', ':', '>>', '<<', '||', '&&',
  2312. '+=','-=','*=','/=','%=','^=','==','&=','|=','!=' # ok
  2313. else # bad
  2314. parser.unreadtok op
  2315. return
  2316. end
  2317. # may be followed by '='
  2318. case op.raw
  2319. when '+', '-', '*', '/', '%', '^', '&', '|', '>>', '<<', '<', '>', '='
  2320. if ntok = parser.readtok and ntok.type == :punct and ntok.raw == '='
  2321. op.raw << ntok.raw
  2322. else
  2323. parser.unreadtok ntok
  2324. end
  2325. end
  2326. op.value = op.raw.to_sym
  2327. op
  2328. end
  2329. # parse sizeof offsetof float immediate etc into tok.value
  2330. def parse_intfloat(parser, scope, tok)
  2331. if tok.type == :string and not tok.value
  2332. case tok.raw
  2333. when 'sizeof'
  2334. if ntok = parser.skipspaces and ntok.type == :punct and ntok.raw == '('
  2335. # check type
  2336. if v = Variable.parse_type(parser, scope)
  2337. v.parse_declarator(parser, scope)
  2338. raise tok if v.name != false
  2339. raise tok if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
  2340. else
  2341. raise tok, 'expr expected' if not v = parse(parser, scope)
  2342. raise tok if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
  2343. end
  2344. else
  2345. parser.unreadtok ntok
  2346. raise tok, 'expr expected' if not v = parse_value(parser, scope)
  2347. end
  2348. tok.value = parser.sizeof(v)
  2349. return
  2350. when '__builtin_offsetof'
  2351. raise tok if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != '('
  2352. raise tok if not ntok = parser.skipspaces or ntok.type != :string or ntok.raw != 'struct'
  2353. raise tok if not ntok = parser.skipspaces or ntok.type != :string
  2354. raise tok, 'unknown structure' if not struct = scope.struct_ancestors[ntok.raw] or not struct.kind_of? Union or not struct.members
  2355. raise tok if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ','
  2356. raise tok if not ntok = parser.skipspaces or ntok.type != :string
  2357. tok.value = struct.offsetof(parser, ntok.raw)
  2358. raise tok if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
  2359. return
  2360. end
  2361. end
  2362. Expression.parse_num_value(parser, tok)
  2363. end
  2364. # returns the next value from parser (parenthesised expression, immediate, variable, unary operators)
  2365. def parse_value(parser, scope)
  2366. return if not tok = parser.skipspaces
  2367. case tok.type
  2368. when :string
  2369. parse_intfloat(parser, scope, tok)
  2370. val = tok.value || tok.raw
  2371. if val.kind_of? ::String
  2372. raise tok, 'undefined variable' if not val = scope.symbol_ancestors[val]
  2373. end
  2374. case val
  2375. when Type
  2376. raise tok, 'invalid variable'
  2377. when Variable
  2378. val = parse_value_postfix(parser, scope, val)
  2379. when ::Float
  2380. # parse suffix
  2381. type = :double
  2382. if (?0..?9).include?(tok.raw[0])
  2383. case tok.raw.downcase[-1]
  2384. when ?l; type = :longdouble
  2385. when ?f; type = :float
  2386. end
  2387. end
  2388. val = CExpression[val, BaseType.new(type)]
  2389. when ::Integer
  2390. # parse suffix
  2391. # XXX 010h ?
  2392. type = :int
  2393. specifier = []
  2394. if (?0..?9).include?(tok.raw[0])
  2395. suffix = tok.raw.downcase[-3, 3] || tok.raw.downcase[-2, 2] || tok.raw.downcase[-1, 1] # short string
  2396. specifier << :unsigned if suffix.include?('u') # XXX or tok.raw.downcase[1] == ?x
  2397. type = :longlong if suffix.count('l') == 2
  2398. type = :long if suffix.count('l') == 1
  2399. end
  2400. val = CExpression[val, BaseType.new(type, *specifier)]
  2401. val = parse_value_postfix(parser, scope, val)
  2402. else raise parser, "internal error #{val.inspect}"
  2403. end
  2404. when :quoted
  2405. if tok.raw[0] == ?'
  2406. raise tok, 'invalid character constant' if not [1, 2, 4, 8].include? tok.value.length # TODO 0fill
  2407. val = CExpression[Expression.decode_imm(tok.value, tok.value.length, :big), BaseType.new(:int)]
  2408. val = parse_value_postfix(parser, scope, val)
  2409. else
  2410. val = CExpression[tok.value, Pointer.new(BaseType.new(tok.raw[0, 2] == 'L"' ? :short : :char))]
  2411. val = parse_value_postfix(parser, scope, val)
  2412. end
  2413. when :punct
  2414. case tok.raw
  2415. when '('
  2416. ntok = nil
  2417. # check type casting
  2418. if v = Variable.parse_type(parser, scope)
  2419. v.parse_declarator(parser, scope)
  2420. (v.type.attributes ||= []).concat v.attributes if v.attributes
  2421. raise tok, 'bad cast' if v.name != false
  2422. raise ntok || tok, 'no ")" found' if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
  2423. raise ntok, 'expr expected' if not val = parse_value(parser, scope) # parses postfix too
  2424. #raise ntok, 'unable to cast a struct' if val.type.untypedef.kind_of? Union
  2425. val = CExpression[[val], v.type]
  2426. # check compound statement expression
  2427. elsif ntok = parser.skipspaces and ntok.type == :punct and ntok.raw == '{'
  2428. parser.unreadtok ntok
  2429. blk = parser.parse_statement(scope, [:expression]) # XXX nesting ?
  2430. raise ntok || tok, 'no ")" found' if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
  2431. type = blk.statements.last.kind_of?(CExpression) ? blk.statements.last.type : BaseType.new(:void)
  2432. val = CExpression[blk, type]
  2433. else
  2434. parser.unreadtok ntok
  2435. if not val = parse(parser, scope)
  2436. parser.unreadtok tok
  2437. return
  2438. end
  2439. raise ntok || tok, 'no ")" found' if not ntok = parser.readtok or ntok.type != :punct or ntok.raw != ')'
  2440. val = parse_value_postfix(parser, scope, val)
  2441. end
  2442. when '.' # float
  2443. parse_intfloat(parser, scope, tok)
  2444. if not tok.value
  2445. parser.unreadtok tok
  2446. return
  2447. end
  2448. val = tok.value || tok.raw
  2449. type = :double
  2450. case tok.raw.downcase[-1]
  2451. when ?l; type = :longdouble
  2452. when ?f; type = :float
  2453. end
  2454. val = CExpression.new[val, BaseType.new(type)]
  2455. when '+', '-', '&', '!', '~', '*', '--', '++', '&&'
  2456. # unary prefix
  2457. # may have been read ahead
  2458. raise parser if not ntok = parser.readtok
  2459. # check for -- ++ &&
  2460. if ntok.type == :punct and ntok.raw == tok.raw and %w[+ - &].include?(tok.raw)
  2461. tok.raw << ntok.raw
  2462. else
  2463. parser.unreadtok ntok
  2464. end
  2465. case tok.raw
  2466. when '&'
  2467. val = parse_value(parser, scope)
  2468. if val.kind_of? CExpression and val.op == :& and not val.lexpr and
  2469. (val.rexpr.kind_of? Variable or val.rexpr.kind_of? CExpression) and val.rexpr.type.kind_of? Function
  2470. # &&function == &function
  2471. elsif (val.kind_of? CExpression or val.kind_of? Variable) and val.type.kind_of? Array
  2472. # &ary = ary
  2473. else
  2474. raise parser, "invalid lvalue #{val}" if not CExpression.lvalue?(val) and not parser.allow_bad_c
  2475. raise val.backtrace, 'cannot take addr of register' if val.kind_of? Variable and val.storage == :register and not parser.allow_bad_c
  2476. val = CExpression.new(nil, tok.raw.to_sym, val, Pointer.new(val.type))
  2477. end
  2478. when '++', '--'
  2479. val = parse_value(parser, scope)
  2480. raise parser, "invalid lvalue #{val}" if not CExpression.lvalue?(val) and not parser.allow_bad_c
  2481. val = CExpression.new(nil, tok.raw.to_sym, val, val.type)
  2482. when '&&'
  2483. raise tok, 'label name expected' if not val = parser.skipspaces or val.type != :string
  2484. val = CExpression.new(nil, nil, Label.new(val.raw, nil), Pointer.new(BaseType.new(:void)))
  2485. when '*'
  2486. raise tok, 'expr expected' if not val = parse_value(parser, scope)
  2487. raise tok, 'not a pointer' if not val.type.pointer? and not parser.allow_bad_c
  2488. newtype = val.type.pointer? ? val.type.pointed : BaseType.new(:int)
  2489. if not newtype.untypedef.kind_of? Function # *fptr == fptr
  2490. val = CExpression.new(nil, tok.raw.to_sym, val, newtype)
  2491. end
  2492. when '~', '!', '+', '-'
  2493. raise tok, 'expr expected' if not val = parse_value(parser, scope)
  2494. raise tok, 'type not arithmetic' if not val.type.arithmetic? and not parser.allow_bad_c
  2495. val = CExpression.new(nil, tok.raw.to_sym, val, val.type)
  2496. val.type = BaseType.new(:int) if tok.raw == '!'
  2497. else raise tok, 'internal error'
  2498. end
  2499. else
  2500. parser.unreadtok tok
  2501. return
  2502. end
  2503. else
  2504. parser.unreadtok tok
  2505. return
  2506. end
  2507. if val.kind_of? Variable and val.type.kind_of? Function
  2508. # void (*bla)() = printf; => ...= &printf;
  2509. val = CExpression[:&, val]
  2510. end
  2511. val
  2512. end
  2513. # parse postfix forms (postincrement, array index, struct member dereference)
  2514. def parse_value_postfix(parser, scope, val)
  2515. tok = parser.skipspaces
  2516. nval = \
  2517. if tok and tok.type == :punct
  2518. case tok.raw
  2519. when '+', '++', '-', '--', '->'
  2520. ntok = parser.readtok
  2521. if (tok.raw == '+' or tok.raw == '-') and ntok and ntok.type == :punct and
  2522. (ntok.raw == tok.raw or (tok.raw == '-' and ntok.raw == '>'))
  2523. tok.raw << ntok.raw
  2524. else
  2525. parser.unreadtok ntok
  2526. end
  2527. case tok.raw
  2528. when '+', '-'
  2529. nil
  2530. when '++', '--'
  2531. raise parser, "#{val}: invalid lvalue" if not CExpression.lvalue?(val)
  2532. CExpression.new(val, tok.raw.to_sym, nil, val.type)
  2533. when '->'
  2534. # XXX allow_bad_c..
  2535. raise tok, "#{val}: not a pointer" if not val.type.pointer?
  2536. type = val.type.pointed.untypedef
  2537. raise tok, "#{val}: bad pointer" if not type.kind_of? Union
  2538. raise tok, "#{val}: incomplete type" if not type.members
  2539. raise tok, "#{val}: invalid member" if not tok = parser.skipspaces or tok.type != :string or not m = type.findmember(tok.raw)
  2540. CExpression.new(val, :'->', tok.raw, m.type)
  2541. end
  2542. when '.'
  2543. type = val.type.untypedef
  2544. if not ntok = parser.skipspaces or ntok.type != :string or not type.kind_of? Union
  2545. parser.unreadtok ntok
  2546. nil
  2547. else
  2548. raise ntok, "#{val}: incomplete type" if not type.members
  2549. raise ntok, "#{val}: invalid member" if not m = type.findmember(ntok.raw)
  2550. CExpression.new(val, :'.', ntok.raw, m.type)
  2551. end
  2552. when '['
  2553. raise tok, "#{val}: index expected" if not idx = parse(parser, scope)
  2554. val, idx = idx, val if not val.type.pointer? # fake support of "4[tab]"
  2555. raise tok, "#{val}: not a pointer" if not val.type.pointer?
  2556. raise tok, "#{val}: invalid index" if not idx.type.integral?
  2557. raise tok, "#{val}: get perpendicular ! (elsewhere)" if idx.kind_of?(CExpression) and idx.op == :','
  2558. raise tok || parser, "']' expected" if not tok = parser.skipspaces or tok.type != :punct or tok.raw != ']'
  2559. type = val.type.untypedef.type
  2560. # TODO boundscheck (and become king of the universe)
  2561. CExpression.new(val, :'[]', idx, type)
  2562. when '('
  2563. type = val.type.untypedef
  2564. type = type.type.untypedef if type.kind_of? Pointer
  2565. raise tok, "#{val}: not a function" if not type.kind_of? Function
  2566. args = []
  2567. loop do
  2568. a = parse(parser, scope, false)
  2569. break if not a
  2570. args << a
  2571. if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ','
  2572. parser.unreadtok ntok
  2573. break
  2574. end
  2575. end
  2576. raise ntok || parser, "#{val}: ')' expected" if not ntok = parser.skipspaces or ntok.type != :punct or ntok.raw != ')'
  2577. type.args ||= []
  2578. raise tok, "#{val}: bad argument count: #{args.length} for #{type.args.length}" if (type.varargs ? (args.length < type.args.length) : (args.length != type.args.length))
  2579. type.args.zip(args) { |ta, a|
  2580. p, i = ta.type.pointer?, ta.type.integral?
  2581. r = a.reduce(parser) if p or i
  2582. if (not p and not i) or (i and not r.kind_of? ::Integer) or (p and r != 0)
  2583. tok = tok.dup ; tok.raw = a.to_s
  2584. parser.check_compatible_type(tok, a.type, ta.type)
  2585. end
  2586. }
  2587. CExpression.new(val, :funcall, args, type.type)
  2588. end
  2589. end
  2590. if nval
  2591. parse_value_postfix(parser, scope, nval)
  2592. else
  2593. parser.unreadtok tok
  2594. val
  2595. end
  2596. end
  2597. def parse_popstack(parser, stack, opstack)
  2598. r = stack.pop
  2599. l = stack.pop
  2600. case op = opstack.pop
  2601. when :'?:'
  2602. stack << CExpression.new(stack.pop, op, [l, r], l.type)
  2603. when :','
  2604. stack << CExpression.new(l, op, r, r.type)
  2605. when :'='
  2606. unless r.kind_of?(CExpression) and not r.lexpr and r.type.kind_of?(BaseType) and
  2607. ((not r.op and r.rexpr.kind_of?(Integer)) or
  2608. (r.op == :- and r.rexpr.kind_of?(CExpression) and not r.rexpr.op and not r.rexpr.lexpr and r.rexpr.rexpr.kind_of?(Integer))) and
  2609. l.kind_of?(Typed) and (l.type.untypedef.kind_of?(BaseType) or (l.type.untypedef.kind_of?(Pointer) and r.rexpr == 0))
  2610. # avoid useless warnings on unsigned foo = -1 / void *foo = 0
  2611. parser.check_compatible_type(parser, r.type, l.type)
  2612. end
  2613. if l.kind_of?(Typed) and (lt = l.type.untypedef).kind_of?(BaseType) and r.kind_of?(Typed) and (rt = r.type.untypedef).kind_of?(BaseType) and lt.specifier != :unsigned and rt.specifier == :unsigned and parser.typesize[lt.name] > parser.typesize[rt.name]
  2614. # (int32)i = (uchar)255 => 255, not -1
  2615. r = CExpression.new(nil, nil, r, BaseType.new(lt.name, :unsigned))
  2616. end
  2617. stack << CExpression.new(l, op, r, l.type)
  2618. when :'&&', :'||'
  2619. stack << CExpression.new(l, op, r, BaseType.new(:int))
  2620. else
  2621. # XXX struct == struct ?
  2622. raise parser, "invalid type #{l.type} #{l} for #{op.inspect}" if not l.type.arithmetic? and not parser.allow_bad_c
  2623. raise parser, "invalid type #{r.type} #{r} for #{op.inspect}" if not r.type.arithmetic? and not parser.allow_bad_c
  2624. if l.type.pointer? and r.type.pointer?
  2625. type = \
  2626. case op
  2627. when :'-'; BaseType.new(:long) # addr_t or sumthin ?
  2628. when :'-='; l.type
  2629. when :'>', :'>=', :'<', :'<=', :'==', :'!='; BaseType.new(:long)
  2630. else raise parser, "cannot do #{op.inspect} on pointers" unless parser.allow_bad_c ; l.type
  2631. end
  2632. elsif l.type.pointer? or r.type.pointer?
  2633. puts parser.exception("should not #{op.inspect} a pointer").message if $VERBOSE and not [:'+', :'-', :'=', :'+=', :'-=', :==, :'!='].include? op
  2634. type = l.type.pointer? ? l.type : r.type
  2635. elsif RIGHTASSOC[op] and op != :'?:' # += etc
  2636. type = l.type
  2637. else
  2638. # yay integer promotion
  2639. lt = l.type.untypedef
  2640. rt = r.type.untypedef
  2641. if (t = lt).name == :longdouble or (t = rt).name == :longdouble or
  2642. (t = lt).name == :double or (t = rt).name == :double or
  2643. (t = lt).name == :float or (t = rt).name == :float
  2644. # long double > double > float ...
  2645. type = t
  2646. elsif true
  2647. # custom integer rules based on type sizes
  2648. lts = parser.typesize[lt.name]
  2649. rts = parser.typesize[rt.name]
  2650. its = parser.typesize[:int]
  2651. if not lts or not rts
  2652. type = BaseType.new(:int)
  2653. elsif lts > rts and lts >= its
  2654. type = lt
  2655. elsif rts > lts and rts >= its
  2656. type = rt
  2657. elsif lts == rts and lts >= its
  2658. type = lt
  2659. type = rt if rt.specifier == :unsigned
  2660. else
  2661. type = BaseType.new(:int)
  2662. end
  2663. # end of custom rules
  2664. elsif ((t = lt).name == :long and t.specifier == :unsigned) or
  2665. ((t = rt).name == :long and t.specifier == :unsigned)
  2666. # ... ulong ...
  2667. type = t
  2668. elsif (lt.name == :long and rt.name == :int and rt.specifier == :unsigned) or
  2669. (rt.name == :long and lt.name == :int and lt.specifier == :unsigned)
  2670. # long+uint => ulong
  2671. type = BaseType.new(:long, :unsigned)
  2672. elsif (t = lt).name == :long or (t = rt).name == :long or
  2673. ((t = lt).name == :int and t.specifier == :unsigned) or
  2674. ((t = rt).name == :int and t.specifier == :unsigned)
  2675. # ... long > uint ...
  2676. type = t
  2677. else
  2678. # int
  2679. type = BaseType.new(:int)
  2680. end
  2681. end
  2682. case op
  2683. when :'>', :'>=', :'<', :'<=', :'==', :'!='
  2684. # cast both sides
  2685. l = CExpression[l, type] if l.type != type
  2686. r = CExpression[r, type] if r.type != type
  2687. stack << CExpression.new(l, op, r, BaseType.new(:int))
  2688. else
  2689. # promote result
  2690. stack << CExpression.new(l, op, r, type)
  2691. end
  2692. end
  2693. end
  2694. def parse(parser, scope, allow_coma = true)
  2695. opstack = []
  2696. stack = []
  2697. return if not e = parse_value(parser, scope)
  2698. stack << e
  2699. while op = readop(parser)
  2700. case op.value
  2701. when :'?'
  2702. # a, b ? c, d : e, f == a, (b ? (c, d) : e), f
  2703. until opstack.empty? or OP_PRIO[opstack.last][:'?:']
  2704. parse_popstack(parser, stack, opstack)
  2705. end
  2706. stack << parse(parser, scope)
  2707. raise op || parser, '":" expected' if not op = readop(parser) or op.value != :':'
  2708. op = op.dup
  2709. op.value = :'?:'
  2710. when :':'
  2711. parser.unreadtok op
  2712. break
  2713. else
  2714. if not allow_coma and op.value == :','
  2715. parser.unreadtok op
  2716. break
  2717. end
  2718. until opstack.empty? or OP_PRIO[op.value][opstack.last]
  2719. parse_popstack(parser, stack, opstack)
  2720. end
  2721. end
  2722. raise op, 'need rhs' if not e = parse_value(parser, scope)
  2723. stack << e
  2724. opstack << op.value
  2725. end
  2726. until opstack.empty?
  2727. parse_popstack(parser, stack, opstack)
  2728. end
  2729. CExpression[stack.first]
  2730. end
  2731. end
  2732. end
  2733. #
  2734. # AllocCStruct: ruby interpreter memory-mapped structure
  2735. #
  2736. # this maps a C structure from a C parser to a ruby String
  2737. # struct members are accessed through obj['fldname']
  2738. # obj.fldname is an alias
  2739. class AllocCStruct
  2740. # str is a reference to the underlying ruby String
  2741. # stroff is the offset from the start of this string (non-nul for nested structs)
  2742. # cp is a reference to the C::Parser
  2743. # struct to the C::Union/Struct/Array
  2744. # sizeof is the byte size of the C struct
  2745. attr_accessor :str, :stroff, :cp, :struct
  2746. attr_writer :sizeof
  2747. def initialize(cp, struct, str=nil, stroff=0)
  2748. @cp, @struct = cp, struct
  2749. @str = str || [0].pack('C')*sizeof
  2750. @stroff = stroff
  2751. end
  2752. def sizeof
  2753. @sizeof ||= @cp.sizeof(@struct)
  2754. end
  2755. def [](*a)
  2756. if @struct.kind_of? C::Array and a.length == 1 and @struct.length and a[0].kind_of? Integer
  2757. i = a[0]
  2758. raise "#{i} out of bounds 0...#{@struct.length}" if i < 0 or i >= @struct.length
  2759. off = @stroff + i*@cp.sizeof(@struct.type)
  2760. return @cp.decode_c_value(@str, @struct.type, off)
  2761. end
  2762. return @str[@stroff..-1][*a] if a.length != 1
  2763. a = a.first
  2764. return @str[@stroff..-1][a] if not a.kind_of? Symbol and not a.kind_of? String and not a.kind_of? C::Variable
  2765. f = a
  2766. raise "#{a.inspect} not a member" if not f.kind_of? C::Variable and not f = @struct.findmember(a.to_s, true)
  2767. a = f.name || f
  2768. off = @stroff + @struct.offsetof(@cp, a)
  2769. if bf = @struct.bitoffsetof(@cp, a)
  2770. ft = C::BaseType.new((bf[0] + bf[1] > 32) ? :__int64 : :__int32)
  2771. v = @cp.decode_c_value(@str, ft, off)
  2772. (v >> bf[0]) & ((1 << bf[1])-1)
  2773. else
  2774. @cp.decode_c_value(@str, f, off)
  2775. end
  2776. end
  2777. def []=(*a)
  2778. if @struct.kind_of? C::Array and a.length == 2 and @struct.length and a[0].kind_of? Integer
  2779. i = a[0]
  2780. raise "#{i} out of bounds 0...#{@struct.length}" if i < 0 or i >= @struct.length
  2781. off = @stroff + i*@cp.sizeof(@struct.type)
  2782. val = @cp.encode_c_value(@struct.type, a[1])
  2783. @str[off, val.length] = val
  2784. return
  2785. end
  2786. if not a.first.kind_of? Symbol and not a.first.kind_of? String and not a.first.kind_of? C::Variable
  2787. # patch @str[@stroff..-1] like a string
  2788. # so we must find the intended start offset, and add @stroff to it
  2789. if @stroff != 0
  2790. case a.first
  2791. when Range
  2792. if a.first.begin >= 0
  2793. a[0] = ::Range.new(a[0].begin+@stroff, a[0].end+@stroff, a[0].exclude_end?)
  2794. else raise 'no can do, use positive index'
  2795. end
  2796. when Integer
  2797. if a.first >= 0
  2798. a[0] += @stroff
  2799. else raise 'no can do, use positive index'
  2800. end
  2801. else raise 'no can do'
  2802. end
  2803. end
  2804. return @str.send(:'[]=', *a) # XXX *should* work...
  2805. end
  2806. a, val = a
  2807. f = a
  2808. raise "#{a.inspect} not a struct member" if not f.kind_of? C::Variable and not f = @struct.findmember(a.to_s, true)
  2809. a = f.name || f
  2810. val = sizeof if val == :size
  2811. off = @stroff + @struct.offsetof(@cp, a)
  2812. if bf = @struct.bitoffsetof(@cp, a)
  2813. raise "only Integers supported in bitfield #{a}, got #{val.inspect}" if not val.kind_of?(::Integer)
  2814. # struct { int i:8; }; => size 8 or 32 ?
  2815. ft = C::BaseType.new((bf[0] + bf[1] > 32) ? :__int64 : :__int32)
  2816. mask = ((1 << bf[1]) - 1) << bf[0]
  2817. preval = @cp.decode_c_value(@str, ft, off)
  2818. val = (preval & ~mask) | ((val << bf[0]) & mask)
  2819. f = ft
  2820. end
  2821. val = @cp.encode_c_value(f, val)
  2822. @str[off, val.length] = val
  2823. end
  2824. # virtual accessors to members
  2825. # struct.foo is aliased to struct['foo'],
  2826. # struct.foo = 42 aliased to struct['foo'] = 42
  2827. def method_missing(on, *a)
  2828. n = on.to_s
  2829. if n[-1] == ?=
  2830. send :[]=, n[0...-1], *a
  2831. else
  2832. super(on, *a) if not @struct.kind_of?(C::Union) or not @struct.findmember(n, true)
  2833. send :[], n, *a
  2834. end
  2835. end
  2836. def to_s(off=nil, maxdepth=500)
  2837. return '{ /* ... */ }' if maxdepth <= 0
  2838. str = ['']
  2839. if @struct.kind_of?(C::Array)
  2840. str.last << "#{@struct.type} x[#{@struct.length}] = " if not off
  2841. mlist = (0...@struct.length)
  2842. fldoff = mlist.inject({}) { |h, i| h.update i => i*@cp.sizeof(@struct.type) }
  2843. elsif @struct.kind_of?(C::Struct)
  2844. str.last << "struct #{@struct.name || '_'} x = " if not off
  2845. @struct.update_member_cache(@cp) if not @struct.fldlist
  2846. fldoff = @struct.fldoffset
  2847. mlist = @struct.members.map { |m| m.name || m }
  2848. else
  2849. str.last << "union #{@struct.name || '_'} x = " if not off
  2850. mlist = @struct.members.map { |m| m.name || m }
  2851. end
  2852. str.last << '{'
  2853. mlist.each { |k|
  2854. if k.kind_of? Variable # anonymous member
  2855. curoff = off.to_i + @struct.offsetof(@cp, k)
  2856. val = self[k]
  2857. k = '?'
  2858. else
  2859. curoff = off.to_i + (fldoff ? fldoff[k].to_i : 0)
  2860. val = self[k]
  2861. end
  2862. if val.kind_of?(::Integer)
  2863. if val >= 0x100
  2864. val = '0x%X, // +%x' % [val, curoff]
  2865. elsif val <= -0x100
  2866. val = '-0x%X, // +%x' % [-val, curoff]
  2867. else
  2868. val = '%d, // +%x' % [val, curoff]
  2869. end
  2870. elsif val.kind_of? AllocCStruct
  2871. val = val.to_s(curoff, maxdepth-1)
  2872. elsif not val
  2873. val = 'NULL, // +%x' % curoff # pointer with NULL value
  2874. else
  2875. val = val.to_s.sub(/$/, ', // +%x' % curoff)
  2876. end
  2877. val = val.gsub("\n", "\n\t")
  2878. str << "\t#{k.kind_of?(::Integer) ? "[#{k}]" : ".#{k}"} = #{val}"
  2879. }
  2880. str << '}'
  2881. str.last << (off ? ',' : ';')
  2882. str.join("\n")
  2883. end
  2884. def to_array
  2885. raise NoMethodError, "Not an Array" if not @struct.kind_of?(C::Array)
  2886. ary = []
  2887. @struct.length.times { |i| ary << self[i] }
  2888. ary
  2889. end
  2890. def to_strz
  2891. raise NoMethodError, "Not an Array" if not @struct.kind_of?(C::Array)
  2892. a = to_array
  2893. a[a.index(0)..-1] = [] if a.index(0)
  2894. a.pack('C*')
  2895. end
  2896. end
  2897. class Parser
  2898. # find a Struct/Union object from a struct name/typedef name
  2899. # raises if it cant find it
  2900. def find_c_struct(structname)
  2901. structname = structname.to_s if structname.kind_of?(::Symbol)
  2902. if structname.kind_of?(::String) and not struct = @toplevel.struct[structname]
  2903. struct = @toplevel.symbol[structname]
  2904. raise "unknown struct #{structname.inspect}" if not struct
  2905. struct = struct.type.untypedef
  2906. struct = struct.pointed while struct.pointer?
  2907. raise "unknown struct #{structname.inspect}" if not struct.kind_of? C::Union
  2908. end
  2909. struct = structname if structname.kind_of? C::Union
  2910. raise "unknown struct #{structname.inspect}" if not struct.kind_of? C::Union
  2911. struct
  2912. end
  2913. # find a C::Type (struct/union/typedef/basetype) from a string
  2914. def find_c_type(typename)
  2915. typename = typename.to_s if typename.kind_of? ::Symbol
  2916. if typename.kind_of?(::String) and not type = @toplevel.struct[typename]
  2917. if type = @toplevel.symbol[typename]
  2918. type = type.type.untypedef
  2919. else
  2920. begin
  2921. lexer.feed(typename)
  2922. b = C::Block.new(@toplevel)
  2923. var = Variable.parse_type(self, b)
  2924. var.parse_declarator(self, b)
  2925. type = var.type
  2926. rescue
  2927. end
  2928. end
  2929. end
  2930. type = typename if typename.kind_of?(C::Type)
  2931. raise "unknown type #{typename.inspect}" if not type.kind_of? C::Type
  2932. type
  2933. end
  2934. # allocate a new AllocCStruct from the struct/struct typedef name of the current toplevel
  2935. # optionally populate the fields using the 'values' hash
  2936. def alloc_c_struct(structname, values=nil)
  2937. struct = find_c_struct(structname)
  2938. st = AllocCStruct.new(self, struct)
  2939. values.each { |k, v| st[k] = v } if values
  2940. st
  2941. end
  2942. # parse a given String as an AllocCStruct
  2943. # offset is an optionnal offset from the string start
  2944. # modification to the structure will modify the underlying string
  2945. def decode_c_struct(structname, str, offset=0)
  2946. struct = find_c_struct(structname)
  2947. AllocCStruct.new(self, struct, str, offset)
  2948. end
  2949. # allocate an array of types
  2950. # init is either the length of the array, or an array of initial values
  2951. def alloc_c_ary(typename, init=1)
  2952. type = find_c_type(typename)
  2953. len = init.kind_of?(Integer) ? init : init.length
  2954. struct = C::Array.new(type, len)
  2955. st = AllocCStruct.new(self, struct)
  2956. if init.kind_of?(::Array)
  2957. init.each_with_index { |v, i|
  2958. st[i] = v
  2959. }
  2960. end
  2961. st
  2962. end
  2963. # "cast" a string to C::Array
  2964. def decode_c_ary(typename, len, str, offset=0)
  2965. type = find_c_type(typename)
  2966. struct = C::Array.new(type, len)
  2967. AllocCStruct.new(self, struct, str, offset)
  2968. end
  2969. # convert (pack) a ruby value into a C buffer
  2970. # packs integers, converts Strings to their C pointer (using DynLdr)
  2971. def encode_c_value(type, val)
  2972. type = type.type if type.kind_of? Variable
  2973. case val
  2974. when nil; val = 0
  2975. when ::Integer
  2976. when ::String
  2977. val = DynLdr.str_ptr(val)
  2978. when ::Hash
  2979. type = type.pointed while type.pointer?
  2980. raise "need a struct ptr for #{type} #{val.inspect}" if not type.kind_of? Union
  2981. buf = alloc_c_struct(type, val)
  2982. val.instance_variable_set('@rb2c', buf) # GC trick
  2983. val = buf
  2984. when ::Proc
  2985. val = DynLdr.convert_rb2c(type, val) # allocate a DynLdr callback
  2986. when AllocCStruct
  2987. val = DynLdr.str_ptr(val.str) + val.stroff
  2988. #when ::Float # TODO
  2989. else raise "TODO #{val.inspect}"
  2990. end
  2991. val = Expression.encode_immediate(val, sizeof(type), @endianness) if val.kind_of?(::Integer)
  2992. val
  2993. end
  2994. def decode_c_value(str, type, off=0)
  2995. type = type.type if type.kind_of? Variable
  2996. type = type.untypedef
  2997. if type.kind_of? C::Union or type.kind_of? C::Array
  2998. return AllocCStruct.new(self, type, str, off)
  2999. end
  3000. val = Expression.decode_immediate(str, sizeof(type), @endianness, off)
  3001. val = Expression.make_signed(val, sizeof(type)*8) if type.integral? and type.signed?
  3002. val = nil if val == 0 and type.pointer?
  3003. val
  3004. end
  3005. end
  3006. #
  3007. # Dumper : objects => C source
  3008. #
  3009. class Parser
  3010. # returns a big string containing all definitions from headers used in the source (including macros)
  3011. def factorize(*a)
  3012. factorize_init
  3013. parse(*a)
  3014. raise @lexer.readtok || self, 'eof expected' if not @lexer.eos?
  3015. factorize_final
  3016. end
  3017. def factorize_init
  3018. @lexer.traced_macros = []
  3019. end
  3020. def factorize_final
  3021. # now find all types/defs not coming from the standard headers
  3022. # all
  3023. all = @toplevel.struct.values + @toplevel.symbol.values
  3024. all -= all.grep(::Integer) # Enum values
  3025. # list of definitions of user-defined objects
  3026. userdefined = all.find_all { |t|
  3027. t.backtrace.backtrace.grep(::String).grep(/^</).empty?
  3028. }
  3029. @toplevel.statements.clear # don't want all Declarations
  3030. # a macro is fine too
  3031. @lexer.dump_macros(@lexer.traced_macros, false) + "\n\n" +
  3032. dump_definitions(userdefined, userdefined)
  3033. end
  3034. # returns a big string representing the definitions of all terms appearing in +list+, excluding +exclude+
  3035. # includes dependencies
  3036. def dump_definitions(list, exclude=[])
  3037. # recurse all dependencies
  3038. todo_rndr = {}
  3039. todo_deps = {}
  3040. list.each { |t|
  3041. todo_rndr[t], todo_deps[t] = t.dump_def(@toplevel)
  3042. }
  3043. # c.toplevel.anonymous_enums.to_a.each { |t| todo_rndr[t], todo_deps[t] = t.dump_def(c.toplevel) }
  3044. while !(ar = (todo_deps.values.flatten - todo_deps.keys)).empty?
  3045. ar.each { |t|
  3046. todo_rndr[t], todo_deps[t] = t.dump_def(@toplevel)
  3047. }
  3048. end
  3049. exclude.each { |t| todo_deps.delete t ; todo_rndr.delete t }
  3050. todo_deps.each_key { |t| todo_deps[t] -= exclude }
  3051. all = @toplevel.struct.values + @toplevel.symbol.values
  3052. all -= all.grep(::Integer) # Enum values
  3053. @toplevel.dump_reorder(all, todo_rndr, todo_deps)[0].join("\n")
  3054. end
  3055. # returns a string containing the C definition(s) of toplevel functions, with their dependencies
  3056. def dump_definition(*funcnames)
  3057. oldst = @toplevel.statements
  3058. @toplevel.statements = []
  3059. dump_definitions(funcnames.map { |f| @toplevel.symbol[f] })
  3060. ensure
  3061. @toplevel.statements = oldst
  3062. end
  3063. def to_s
  3064. @toplevel.dump(nil)[0].join("\n")
  3065. end
  3066. end
  3067. class Statement
  3068. def self.dump(e, scope, r=[''], dep=[])
  3069. case e
  3070. when nil; r.last << ';'
  3071. when Block
  3072. r.last << ' ' if not r.last.empty?
  3073. r.last << '{'
  3074. tr, dep = e.dump(scope, [''], dep)
  3075. tr.pop if tr.last.empty?
  3076. r.concat tr.map { |s| Case.dump_indent(s) }
  3077. (r.last[-1] == ?{ ? r.last : r) << '}'
  3078. else
  3079. tr, dep = e.dump(scope, [''], dep)
  3080. r.concat tr.map { |s| Case.dump_indent(s) }
  3081. end
  3082. [r, dep]
  3083. end
  3084. def to_s
  3085. dump(Block.new(nil))[0].join(' ')
  3086. end
  3087. end
  3088. class Block
  3089. def to_s() dump(nil)[0].join("\n") end
  3090. # return array of c source lines and array of dependencies (objects)
  3091. def dump(scp, r=[''], dep=[])
  3092. mydefs = @symbol.values.grep(TypeDef) + @struct.values + anonymous_enums.to_a
  3093. todo_rndr = {}
  3094. todo_deps = {}
  3095. mydefs.each { |t| # filter out Enum values
  3096. todo_rndr[t], todo_deps[t] = t.dump_def(self)
  3097. }
  3098. r, dep = dump_reorder(mydefs, todo_rndr, todo_deps, r, dep)
  3099. dep -= @symbol.values + @struct.values
  3100. [r, dep]
  3101. end
  3102. def dump_reorder(mydefs, todo_rndr, todo_deps, r=[''], dep=[])
  3103. val = todo_deps.values.flatten.uniq
  3104. dep |= val
  3105. dep -= mydefs | todo_deps.keys
  3106. todo_deps.each { |k, v| v.delete k }
  3107. ext = val - mydefs
  3108. if ext.length > todo_deps.length
  3109. todo_deps.each_key { |k| todo_deps[k] = todo_deps[k] & mydefs }
  3110. else
  3111. ext.each { |k| todo_deps.each_value { |v| v.delete k } }
  3112. end
  3113. # predeclare structs involved in cyclic dependencies
  3114. dep_cycle = lambda { |ary|
  3115. # sexyness inside (c)
  3116. deps = todo_deps[ary.last]
  3117. if deps.include? ary.first; ary
  3118. elsif (deps-ary).find { |d| deps = dep_cycle[ary + [d]] }; deps
  3119. end
  3120. }
  3121. todo_rndr.keys.grep(Union).find_all { |t| t.name }.sort_by { |t| t.name }.each { |t|
  3122. oldc = nil
  3123. while c = dep_cycle[[t]]
  3124. break if oldc == c
  3125. r << "#{t.kind_of?(Struct) ? 'struct' : 'union'} #{t.name};" if not oldc
  3126. oldc = c
  3127. c.each { |s|
  3128. # XXX struct z { struct a* }; struct a { void (*foo)(struct z); };
  3129. todo_deps[s].delete t unless s.kind_of? Union and
  3130. s.members.find { |sm| sm.type.untypedef == t }
  3131. }
  3132. end
  3133. }
  3134. loop do
  3135. break if todo_rndr.empty?
  3136. todo_now = todo_deps.keys.find_all { |k| todo_deps[k].empty? }
  3137. if todo_now.empty?
  3138. r << '// dependency problem, this may not compile'
  3139. todo_now = todo_deps.keys
  3140. end
  3141. todo_now.sort_by { |k| k.name || '0' }.each { |k|
  3142. if k.kind_of? Variable and k.type.kind_of? Function and k.initializer
  3143. r << ''
  3144. r.concat todo_rndr.delete(k)
  3145. else
  3146. r.pop if r.last == ''
  3147. r.concat todo_rndr.delete(k)
  3148. r.last << ';'
  3149. end
  3150. todo_deps.delete k
  3151. }
  3152. todo_deps.each_key { |k| todo_deps[k] -= todo_now }
  3153. r << '' << '' << ''
  3154. end
  3155. @statements.each { |s|
  3156. r << '' if not r.last.empty?
  3157. if s.kind_of? Block
  3158. r, dep = Statement.dump(s, self, r, dep)
  3159. else
  3160. r, dep = s.dump(self, r, dep)
  3161. end
  3162. }
  3163. [r, dep]
  3164. end
  3165. end
  3166. class Declaration
  3167. def dump(scope, r=[''], dep=[])
  3168. tr, dep = @var.dump_def(scope, [''], dep)
  3169. if @var.kind_of? Variable and @var.type.kind_of? Function and @var.initializer
  3170. r << ''
  3171. r.concat tr
  3172. else
  3173. r.pop if r.last == ''
  3174. r.concat tr
  3175. r.last << ';'
  3176. end
  3177. [r, dep]
  3178. end
  3179. def to_s
  3180. dump(Block.new(nil))[0].join(' ')
  3181. end
  3182. end
  3183. module Attributes
  3184. def dump_attributes
  3185. if attributes
  3186. (attributes - DECLSPECS).map { |a| " __attribute__((#{a}))" }.join
  3187. else ''
  3188. end
  3189. end
  3190. def dump_attributes_pre
  3191. if attributes
  3192. (attributes & DECLSPECS).map { |a| "__#{a} " }.join
  3193. else ''
  3194. end
  3195. end
  3196. end
  3197. class Variable
  3198. def dump(scope, r=[''], dep=[])
  3199. if name
  3200. dep |= [scope.symbol_ancestors[@name]]
  3201. r.last << @name
  3202. end
  3203. [r, dep]
  3204. end
  3205. def dump_def(scope, r=[''], dep=[], skiptype=false)
  3206. # int a=1, b=2;
  3207. r.last << dump_attributes_pre
  3208. if not skiptype
  3209. r.last << @storage.to_s << ' ' if storage
  3210. r, dep = @type.base.dump(scope, r, dep)
  3211. r.last << ' ' if name
  3212. end
  3213. r, dep = @type.dump_declarator([(name ? @name.dup : '') << dump_attributes], scope, r, dep)
  3214. if initializer
  3215. r.last << ' = ' if not @type.kind_of?(Function)
  3216. r, dep = @type.dump_initializer(@initializer, scope, r, dep)
  3217. end
  3218. [r, dep]
  3219. end
  3220. def to_s
  3221. dump(Block.new(nil))[0].join(' ')
  3222. end
  3223. end
  3224. class Type
  3225. def dump_initializer(init, scope, r=[''], dep=[])
  3226. case init
  3227. when ::Numeric
  3228. r.last << init.to_s
  3229. [r, dep]
  3230. when ::Array
  3231. r.last << init.inspect
  3232. [r, dep]
  3233. else init.dump_inner(scope, r, dep)
  3234. end
  3235. end
  3236. def dump_declarator(decl, scope, r=[''], dep=[])
  3237. r.last << decl.shift
  3238. r.concat decl
  3239. [r, dep]
  3240. end
  3241. def dump_def(*a)
  3242. dump(*a)
  3243. end
  3244. def dump_cast(scope, r=[''], dep=[])
  3245. r.last << '('
  3246. r.last << dump_attributes_pre if not kind_of? TypeDef
  3247. r, dep = base.dump(scope, r, dep)
  3248. r, dep = dump_declarator([kind_of?(TypeDef) ? '' : dump_attributes], scope, r, dep)
  3249. r.last << ')'
  3250. [r, dep]
  3251. end
  3252. def to_s
  3253. dump_cast(Block.new(nil))[0].join(' ')
  3254. end
  3255. end
  3256. class Pointer
  3257. def dump_declarator(decl, scope, r=[''], dep=[])
  3258. d = decl[0]
  3259. decl[0] = '*'
  3260. decl[0] << ' ' << @qualifier.map { |q| q.to_s }.join(' ') << ' ' if qualifier
  3261. decl[0] << d
  3262. if @type.kind_of? Function or @type.kind_of? Array
  3263. decl[0] = '(' << decl[0]
  3264. decl.last << ')'
  3265. end
  3266. @type.dump_declarator(decl, scope, r, dep)
  3267. end
  3268. end
  3269. class Array
  3270. def dump_declarator(decl, scope, r=[''], dep=[])
  3271. decl.last << '()' if decl.last.empty?
  3272. decl.last << '['
  3273. decl, dep = CExpression.dump(@length, scope, decl, dep) if length
  3274. decl.last << ']'
  3275. @type.dump_declarator(decl, scope, r, dep)
  3276. end
  3277. def dump_initializer(init, scope, r=[''], dep=[])
  3278. return super(init, scope, r, dep) if not init.kind_of? ::Array
  3279. r.last << '{ '
  3280. showname = false
  3281. init.each_with_index { |v, i|
  3282. if not v
  3283. showname = true
  3284. next
  3285. end
  3286. r.last << ', ' if r.last[-2, 2] != '{ '
  3287. rt = ['']
  3288. if showname
  3289. showname = false
  3290. rt << "[#{i}] = "
  3291. end
  3292. rt, dep = @type.dump_initializer(v, scope, rt, dep)
  3293. r.last << rt.shift
  3294. r.concat rt.map { |s| "\t" << s }
  3295. }
  3296. r.last << ' }'
  3297. [r, dep]
  3298. end
  3299. end
  3300. class Function
  3301. def dump_declarator(decl, scope, r=[''], dep=[])
  3302. decl.last << '()' if decl.last.empty?
  3303. decl.last << '('
  3304. if args
  3305. @args.each { |arg|
  3306. decl.last << ', ' if decl.last[-1] != ?(
  3307. decl, dep = arg.dump_def(scope, decl, dep)
  3308. }
  3309. if varargs
  3310. decl.last << ', ' if decl.last[-1] != ?(
  3311. decl.last << '...'
  3312. else
  3313. decl.last << 'void' if @args.empty?
  3314. end
  3315. end
  3316. decl.last << ')'
  3317. @type.dump_declarator(decl, scope, r, dep)
  3318. end
  3319. def dump_initializer(init, scope, r=[''], dep=[])
  3320. Statement.dump(init, scope, r << '', dep)
  3321. end
  3322. end
  3323. class BaseType
  3324. def dump(scope, r=[''], dep=[])
  3325. r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
  3326. r.last << @specifier.to_s << ' ' if specifier and @name != :ptr
  3327. r.last << case @name
  3328. when :longlong; 'long long'
  3329. when :longdouble; 'long double'
  3330. when :ptr; specifier == :unsigned ? 'uintptr_t' : 'intptr_t'
  3331. else @name.to_s
  3332. end
  3333. [r, dep]
  3334. end
  3335. end
  3336. class TypeDef
  3337. def dump(scope, r=[''], dep=[])
  3338. r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
  3339. r.last << @name
  3340. dep |= [scope.symbol_ancestors[@name]]
  3341. [r, dep]
  3342. end
  3343. def dump_def(scope, r=[''], dep=[])
  3344. r.last << 'typedef '
  3345. r.last << dump_attributes_pre
  3346. r, dep = @type.base.dump(scope, r, dep)
  3347. r.last << ' '
  3348. @type.dump_declarator([(name ? @name.dup : '') << dump_attributes], scope, r, dep)
  3349. end
  3350. def dump_initializer(init, scope, r=[''], dep=[])
  3351. @type.dump_initializer(init, scope, r, dep)
  3352. end
  3353. end
  3354. class Union
  3355. def dump(scope, r=[''], dep=[])
  3356. if name
  3357. r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
  3358. r.last << self.class.name.downcase[/(?:.*::)?(.*)/, 1] << ' ' << @name
  3359. dep |= [scope.struct_ancestors[@name]]
  3360. [r, dep]
  3361. else
  3362. dump_def(scope, r, dep)
  3363. end
  3364. end
  3365. def dump_def(scope, r=[''], dep=[])
  3366. r << ''
  3367. r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
  3368. r.last << self.class.name.downcase[/(?:.*::)?(.*)/, 1]
  3369. r.last << ' ' << @name if name
  3370. if members
  3371. r.last << ' {'
  3372. @members.each_with_index { |m,i|
  3373. tr, dep = m.dump_def(scope, [''], dep)
  3374. tr.last << ':' << @bits[i].to_s if bits and @bits[i]
  3375. tr.last << ';'
  3376. r.concat tr.map { |s| "\t" << s }
  3377. }
  3378. r << '}'
  3379. end
  3380. r.last << dump_attributes
  3381. [r, dep]
  3382. end
  3383. def dump_initializer(init, scope, r=[''], dep=[])
  3384. return super(init, scope, r, dep) if not init.kind_of? ::Array
  3385. r.last << '{ '
  3386. showname = false
  3387. @members.zip(init) { |m, i|
  3388. if not i
  3389. showname = true
  3390. next
  3391. end
  3392. r.last << ', ' if r.last[-2, 2] != '{ '
  3393. rt = ['']
  3394. if showname
  3395. showname = false
  3396. rt << ".#{m.name} = "
  3397. end
  3398. rt, dep = m.type.dump_initializer(i, scope, rt, dep)
  3399. r.last << rt.shift
  3400. r.concat rt.map { |s| "\t" << s }
  3401. }
  3402. r.last << ' }'
  3403. [r, dep]
  3404. end
  3405. end
  3406. class Struct
  3407. def dump_def(scope, r=[''], dep=[])
  3408. if pack
  3409. r, dep = super(scope, r, dep)
  3410. r.last <<
  3411. if @pack == 1; (has_attribute('packed') or has_attribute_var('pack')) ? '' : " __attribute__((packed))"
  3412. else has_attribute_var('pack') ? '' : " __attribute__((pack(#@pack)))"
  3413. end
  3414. [r, dep]
  3415. else
  3416. super(scope, r, dep)
  3417. end
  3418. end
  3419. end
  3420. class Enum
  3421. def dump(scope, r=[''], dep=[])
  3422. if name
  3423. r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
  3424. r.last << 'enum ' << @name
  3425. dep |= [scope.struct_ancestors[@name]]
  3426. [r, dep]
  3427. else
  3428. dump_def(scope, r, dep)
  3429. end
  3430. end
  3431. def dump_def(scope, r=[''], dep=[])
  3432. r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
  3433. r.last << 'enum'
  3434. r.last << ' ' << @name if name
  3435. if members
  3436. r.last << ' { '
  3437. val = -1
  3438. @members.sort_by { |m, v| v }.each { |m, v|
  3439. r.last << ', ' if r.last[-2, 2] != '{ '
  3440. r.last << m
  3441. if v != (val += 1)
  3442. val = v
  3443. r.last << ' = ' << val.to_s
  3444. end
  3445. }
  3446. r.last << ' }'
  3447. end
  3448. [r, dep]
  3449. end
  3450. def dump_initializer(init, scope, r=[''], dep=[])
  3451. if members and (
  3452. k = @members.index(init) or
  3453. (init.kind_of? CExpression and not init.op and k = @members.index(init.rexpr))
  3454. )
  3455. r.last << k
  3456. dep |= [scope.struct_ancestors[@name]]
  3457. [r, dep]
  3458. else super(init, scope, r, dep)
  3459. end
  3460. end
  3461. end
  3462. class If
  3463. def dump(scope, r=[''], dep=[])
  3464. r.last << 'if ('
  3465. r, dep = CExpression.dump(@test, scope, r, dep)
  3466. r.last << ')'
  3467. r, dep = Statement.dump(@bthen, scope, r, dep)
  3468. if belse
  3469. @bthen.kind_of?(Block) ? (r.last << ' else') : (r << 'else')
  3470. if @belse.kind_of? If
  3471. # skip indent
  3472. r.last << ' '
  3473. r, dep = @belse.dump(scope, r, dep)
  3474. else
  3475. r, dep = Statement.dump(@belse, scope, r, dep)
  3476. end
  3477. end
  3478. [r, dep]
  3479. end
  3480. end
  3481. class For
  3482. def dump(scope, r=[''], dep=[])
  3483. r.last << 'for ('
  3484. if @init.kind_of? Block
  3485. scope = @init
  3486. skiptype = false
  3487. @init.symbol.each_value { |s|
  3488. r.last << ', ' if skiptype
  3489. r, dep = s.dump_def(scope, r, dep, skiptype)
  3490. skiptype = true
  3491. }
  3492. else
  3493. r, dep = CExpression.dump(@init, scope, r, dep)
  3494. end
  3495. r.last << ' ' if @init
  3496. r.last << ';'
  3497. r.last << ' ' if @test
  3498. r, dep = CExpression.dump(@test, scope, r, dep)
  3499. r.last << ' ' if @test
  3500. r.last << ';'
  3501. r.last << ' ' if @iter
  3502. r, dep = CExpression.dump(@iter, scope, r, dep)
  3503. r.last << ')'
  3504. Statement.dump(@body, scope, r, dep)
  3505. end
  3506. end
  3507. class While
  3508. def dump(scope, r=[''], dep=[])
  3509. r.last << 'while ('
  3510. r, dep = CExpression.dump(@test, scope, r, dep)
  3511. r.last << ')'
  3512. Statement.dump(@body, scope, r, dep)
  3513. end
  3514. end
  3515. class DoWhile
  3516. def dump(scope, r=[''], dep=[])
  3517. r.last << 'do'
  3518. r, dep = Statement.dump(@body, scope, r, dep)
  3519. @body.kind_of?(Block) ? (r.last << ' while (') : (r << 'while (')
  3520. r, dep = CExpression.dump(@test, scope, r, dep)
  3521. r.last << ');'
  3522. [r, dep]
  3523. end
  3524. end
  3525. class Switch
  3526. def dump(scope, r=[''], dep=[])
  3527. r.last << 'switch ('
  3528. r, dep = CExpression.dump(@test, scope, r, dep)
  3529. r.last << ')'
  3530. r.last << ' {' if @body.kind_of? Block
  3531. tr, dep = @body.dump(scope, [''], dep)
  3532. r.concat tr.map { |s| Case.dump_indent(s, true) }
  3533. r << '}' if @body.kind_of? Block
  3534. [r, dep]
  3535. end
  3536. end
  3537. class Continue
  3538. def dump(scope, r=[''], dep=[])
  3539. r.last << 'continue;'
  3540. [r, dep]
  3541. end
  3542. end
  3543. class Break
  3544. def dump(scope, r=[''], dep=[])
  3545. r.last << 'break;'
  3546. [r, dep]
  3547. end
  3548. end
  3549. class Goto
  3550. def dump(scope, r=[''], dep=[])
  3551. r.last << "goto #@target;"
  3552. [r, dep]
  3553. end
  3554. end
  3555. class Return
  3556. def dump(scope, r=[''], dep=[])
  3557. r.last << 'return '
  3558. r, dep = CExpression.dump(@value, scope, r, dep)
  3559. r.last.chop! if r.last[-1] == ?\ # the space character
  3560. r.last << ';'
  3561. [r, dep]
  3562. end
  3563. end
  3564. class Case
  3565. def dump(scope, r=[''], dep=[])
  3566. case @expr
  3567. when 'default'
  3568. r.last << @expr
  3569. else
  3570. r.last << 'case '
  3571. r, dep = CExpression.dump(@expr, scope, r, dep)
  3572. if exprup
  3573. r.last << ' ... '
  3574. r, dep = CExpression.dump(@exprup, scope, r, dep)
  3575. end
  3576. end
  3577. r.last << ':'
  3578. dump_inner(scope, r, dep)
  3579. end
  3580. def self.dump_indent(s, short=false)
  3581. case s
  3582. when /^(case|default)\W/; (short ? ' ' : "\t") << s
  3583. when /^\s+(case|default)\W/; "\t" << s
  3584. when /:$/; s
  3585. else "\t" << s
  3586. end
  3587. end
  3588. end
  3589. class Label
  3590. def dump(scope, r=[''], dep=[])
  3591. r.last << @name << ':'
  3592. dump_inner(scope, r, dep)
  3593. end
  3594. def dump_inner(scope, r=[''], dep=[])
  3595. if not @statement; [r, dep]
  3596. elsif @statement.kind_of? Block; Statement.dump(@statement, scope, r, dep)
  3597. else @statement.dump(scope, r << '', dep)
  3598. end
  3599. end
  3600. end
  3601. class Asm
  3602. def dump(scope, r=[''], dep=[])
  3603. r.last << 'asm '
  3604. r.last << 'volatile ' if @volatile
  3605. r.last << '('
  3606. r.last << CExpression.string_inspect(@body)
  3607. if @output or @input or @clobber
  3608. if @output and @output != []
  3609. # TODO
  3610. r << ': /* todo */'
  3611. elsif (@input and @input != []) or (@clobber and @clobber != [])
  3612. r.last << ' :'
  3613. end
  3614. end
  3615. if @input or @clobber
  3616. if @input and @input != []
  3617. # TODO
  3618. r << ': /* todo */'
  3619. elsif @clobber and @clobber != []
  3620. r.last << ' :'
  3621. end
  3622. end
  3623. if @clobber and @clobber != []
  3624. r << (': ' << @clobber.map { |c| CExpression.string_inspect(c) }.join(', '))
  3625. end
  3626. r.last << ');'
  3627. [r, dep]
  3628. end
  3629. end
  3630. class CExpression
  3631. def self.string_inspect(s)
  3632. # keep all ascii printable except \ and "
  3633. '"' + s.gsub(/[^ !\x23-\x5b\x5d-\x7e]/) { |o| '\\x' + o.unpack('H*').first } + '"'
  3634. end
  3635. def self.dump(e, scope, r=[''], dep=[], brace = false)
  3636. if $DEBUG
  3637. brace = false
  3638. case e
  3639. when CExpression, Variable
  3640. r, dep = e.type.dump_cast(scope, r, dep)
  3641. end
  3642. r.last << '('
  3643. end
  3644. r, dep = \
  3645. case e
  3646. when ::Numeric; r.last << e.to_s ; [r, dep]
  3647. when ::String; r.last << string_inspect(e) ; [r, dep]
  3648. when CExpression; e.dump_inner(scope, r, dep, brace)
  3649. when Variable; e.dump(scope, r, dep)
  3650. when nil; [r, dep]
  3651. else raise 'wtf?' + e.inspect
  3652. end
  3653. if $DEBUG
  3654. r.last << ')'
  3655. end
  3656. [r, dep]
  3657. end
  3658. def dump(scope, r=[''], dep=[])
  3659. r, dep = dump_inner(scope, r, dep)
  3660. r.last << ';'
  3661. [r, dep]
  3662. end
  3663. def dump_inner(scope, r=[''], dep=[], brace = false)
  3664. r.last << '(' if brace and @op != :'->' and @op != :'.' and @op != :'[]' and (@op or @rexpr.kind_of? CExpression)
  3665. if not @lexpr
  3666. if not @op
  3667. case @rexpr
  3668. when ::Numeric
  3669. if @rexpr < 0
  3670. r.last << ?-
  3671. re = -@rexpr
  3672. else
  3673. re = @rexpr
  3674. end
  3675. if re >= 0x1000
  3676. r.last << ("0x%X" % re)
  3677. else
  3678. r.last << re.to_s
  3679. end
  3680. if @type.kind_of? BaseType
  3681. r.last << 'U' if @type.specifier == :unsigned
  3682. case @type.name
  3683. when :longlong, :__int64; r.last << 'LL'
  3684. when :long, :longdouble; r.last << 'L'
  3685. when :float; r.last << 'F'
  3686. end
  3687. end
  3688. when ::String
  3689. r.last << 'L' if @type.kind_of? Pointer and @type.type.kind_of? BaseType and @type.type.name == :short
  3690. r.last << CExpression.string_inspect(@rexpr)
  3691. when CExpression # cast
  3692. r, dep = @type.dump_cast(scope, r, dep)
  3693. r, dep = CExpression.dump(@rexpr, scope, r, dep, true)
  3694. when Variable
  3695. r, dep = @rexpr.dump(scope, r, dep)
  3696. when Block
  3697. r.last << '('
  3698. r, dep = Statement.dump(@rexpr, scope, r, dep)
  3699. r.last << ' )'
  3700. when Label
  3701. r.last << '&&' << @rexpr.name
  3702. else raise "wtf? #{inspect}"
  3703. end
  3704. else
  3705. r.last << @op.to_s
  3706. r, dep = CExpression.dump(@rexpr, scope, r, dep, (@rexpr.kind_of? C::CExpression and @rexpr.lexpr))
  3707. end
  3708. elsif not @rexpr
  3709. r, dep = CExpression.dump(@lexpr, scope, r, dep)
  3710. r.last << @op.to_s
  3711. else
  3712. case @op
  3713. when :'->', :'.'
  3714. r, dep = CExpression.dump(@lexpr, scope, r, dep, true)
  3715. r.last << @op.to_s << @rexpr
  3716. when :'[]'
  3717. r, dep = CExpression.dump(@lexpr, scope, r, dep, true)
  3718. r.last << '['
  3719. l = lexpr if lexpr.kind_of? Variable
  3720. l = lexpr.lexpr.type.untypedef.findmember(lexpr.rexpr) if lexpr.kind_of? CExpression and lexpr.op == :'.'
  3721. l = lexpr.lexpr.type.pointed.untypedef.findmember(lexpr.rexpr) if lexpr.kind_of? CExpression and lexpr.op == :'->'
  3722. # honor __attribute__((indexenum(enumname)))
  3723. if l and l.attributes and rexpr.kind_of? CExpression and not rexpr.op and rexpr.rexpr.kind_of? ::Integer and
  3724. n = l.has_attribute_var('indexenum') and enum = scope.struct_ancestors[n] and i = enum.members.index(rexpr.rexpr)
  3725. r.last << i
  3726. dep |= [enum]
  3727. else
  3728. r, dep = CExpression.dump(@rexpr, scope, r, dep)
  3729. end
  3730. r.last << ']'
  3731. when :funcall
  3732. r, dep = CExpression.dump(@lexpr, scope, r, dep, true)
  3733. r.last << '('
  3734. @rexpr.each { |arg|
  3735. r.last << ', ' if r.last[-1] != ?(
  3736. r, dep = CExpression.dump(arg, scope, r, dep)
  3737. }
  3738. r.last << ')'
  3739. when :'?:'
  3740. r, dep = CExpression.dump(@lexpr, scope, r, dep, true)
  3741. r.last << ' ? '
  3742. r, dep = CExpression.dump(@rexpr[0], scope, r, dep, true)
  3743. r.last << ' : '
  3744. r, dep = CExpression.dump(@rexpr[1], scope, r, dep, true)
  3745. else
  3746. r, dep = CExpression.dump(@lexpr, scope, r, dep, (@lexpr.kind_of? CExpression and @lexpr.lexpr and @lexpr.op != @op))
  3747. r.last << ' ' << @op.to_s << ' '
  3748. r, dep = CExpression.dump(@rexpr, scope, r, dep, (@rexpr.kind_of? CExpression and @rexpr.lexpr and @rexpr.op != @op and @rexpr.op != :funcall))
  3749. end
  3750. end
  3751. r.last << ')' if brace and @op != :'->' and @op != :'.' and @op != :'[]' and (@op or @rexpr.kind_of? CExpression)
  3752. [r, dep]
  3753. end
  3754. def to_s
  3755. dump_inner(Block.new(nil))[0].join(' ')
  3756. end
  3757. end
  3758. end
  3759. end