cast 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,45 +1,43 @@
1
- ###
2
- ### ##################################################################
3
- ###
4
- ### C.default_parser and the parse_* methods.
5
- ###
6
- ### Yeah, this could be so much faster.
7
- ###
8
- ### ##################################################################
9
- ###
1
+ ######################################################################
2
+ #
3
+ # C.default_parser and the parse_* methods.
4
+ #
5
+ # Yeah, this could be so much faster.
6
+ #
7
+ ######################################################################
10
8
 
11
9
  module C
12
10
  @@default_parser = Parser.new
13
11
  def self.default_parser
14
12
  @@default_parser
15
13
  end
16
- def self.default_parser= val
14
+ def self.default_parser=(val)
17
15
  @@default_parser = val
18
16
  end
19
17
 
20
18
  class Node
21
- ###
22
- ### Return true if `str' is parsed to something `==' to this Node.
23
- ### str is first converted to a String using #to_s, then given to
24
- ### self.class.parse (along with the optional `parser').
25
- ###
26
- def match? str, parser=nil
19
+ #
20
+ # Return true if `str' is parsed to something `==' to this Node.
21
+ # str is first converted to a String using #to_s, then given to
22
+ # self.class.parse (along with the optional `parser').
23
+ #
24
+ def match?(str, parser=nil)
27
25
  node = self.class.parse(str.to_s, parser) rescue (return false)
28
26
  self == node
29
27
  end
30
- ###
31
- ### Same as #match?.
32
- ###
33
- def =~ *args
34
- match? *args
28
+ #
29
+ # Same as #match?.
30
+ #
31
+ def =~(*args)
32
+ match?(*args)
35
33
  end
36
34
  private
37
35
  end
38
36
  class NodeList
39
- ###
40
- ### As defined in Node.
41
- ###
42
- def match? arr, parser=nil
37
+ #
38
+ # As defined in Node.
39
+ #
40
+ def match?(arr, parser=nil)
43
41
  arr = arr.to_a
44
42
  return false if arr.length != self.length
45
43
  each_with_index do |node, i|
@@ -49,19 +47,19 @@ module C
49
47
  end
50
48
  end
51
49
 
52
- def self.parse s, parser=nil
50
+ def self.parse(s, parser=nil)
53
51
  TranslationUnit.parse(s, parser)
54
52
  end
55
53
 
56
54
  class TranslationUnit
57
- def self.parse s, parser=nil
55
+ def self.parse(s, parser=nil)
58
56
  parser ||= C.default_parser
59
57
  parser.parse(s)
60
58
  end
61
59
  end
62
60
 
63
61
  class Declaration
64
- def self.parse s, parser=nil
62
+ def self.parse(s, parser=nil)
65
63
  parser ||= C.default_parser
66
64
  ents = parser.parse(s).entities
67
65
  if ents.length == 1 && # int i; int j;
@@ -74,7 +72,7 @@ module C
74
72
  end
75
73
 
76
74
  class Parameter
77
- def self.parse s, parser=nil
75
+ def self.parse(s, parser=nil)
78
76
  parser ||= C.default_parser
79
77
  ents = parser.parse("void f(#{s}) {}").entities
80
78
  if ents.length == 1 && # ) {} void (
@@ -94,20 +92,29 @@ module C
94
92
  end
95
93
 
96
94
  class Declarator
97
- def self.parse s, parser=nil
95
+ def self.parse(s, parser=nil)
98
96
  parser ||= C.default_parser
99
- ents = parser.parse("int #{s};").entities
100
- if ents.length == 1 && # f; int f;
101
- ents[0].declarators.length == 1 # i,j
102
- return ents[0].declarators[0].detach
97
+ # if there's a ':', declare in a struct so we can populate num_bits
98
+ if s =~ /:/
99
+ ents = parser.parse("struct {int #{s};};").entities
100
+ if ents.length == 1 && # i:1;}; struct {int i
101
+ ents[0].type.members.length == 1 && # i:1; int j
102
+ ents[0].type.members[0].declarators.length == 1 # i:1,j
103
+ return ents[0].type.members[0].declarators[0].detach
104
+ end
103
105
  else
104
- raise ParseError, "invalid Declarator"
106
+ ents = parser.parse("int #{s};").entities
107
+ if ents.length == 1 && # f; int f;
108
+ ents[0].declarators.length == 1 # i,j
109
+ return ents[0].declarators[0].detach
110
+ end
105
111
  end
112
+ raise ParseError, "invalid Declarator"
106
113
  end
107
114
  end
108
115
 
109
116
  class FunctionDef
110
- def self.parse s, parser=nil
117
+ def self.parse(s, parser=nil)
111
118
  parser ||= C.default_parser
112
119
  ents = parser.parse(s).entities
113
120
  if ents.length == 1 && # void f(); void g();
@@ -120,7 +127,7 @@ module C
120
127
  end
121
128
 
122
129
  class Enumerator
123
- def self.parse s, parser=nil
130
+ def self.parse(s, parser=nil)
124
131
  parser ||= C.default_parser
125
132
  ents = parser.parse("enum {#{s}};").entities
126
133
  if ents.length == 1 && # } enum {
@@ -134,7 +141,7 @@ module C
134
141
  end
135
142
 
136
143
  class MemberInit
137
- def self.parse s, parser=nil
144
+ def self.parse(s, parser=nil)
138
145
  parser ||= C.default_parser
139
146
  ents = parser.parse("int f() {struct s x = {#{s}};}").entities
140
147
  if ents.length == 1 && # } int f() {
@@ -149,16 +156,16 @@ module C
149
156
  end
150
157
 
151
158
  class Member
152
- def self.parse s, parser=nil
159
+ def self.parse(s, parser=nil)
153
160
  parser ||= C.default_parser
154
- ents = parser.parse("int f() {struct s x = {#{s} = 1;};}").entities
155
- if ents.length == 1 && # };} int f() {struct s x = {a
156
- ents[0].def.stmts.length == 1 && # }; x
157
- #ents[0].def.stmts[0].length == 1 && # 1}, x = {.a
158
- ents[0].def.stmts[0].declarators.length == 1 && # 1}, x = {.a
159
- ents[0].def.stmts[0].declarators[0].init.member_inits.length == 1 && # x = 1, y
160
- ents[0].def.stmts[0].declarators[0].init.member_inits[0].member.length == 1 && # .a .b
161
- ents[0].def.stmts[0].declarators[0].init.member_inits[0].member[0].is_a?(C::Member) # [0]
161
+ ents = parser.parse("int f() {struct s x = {.#{s} = 1};}").entities
162
+ if ents.length == 1 && # a = 1};} int f() {struct s x = {a
163
+ ents[0].def.stmts.length == 1 && # a = 1}; struct s y = {.a
164
+ #ents[0].def.stmts[0].length == 1 && # a = 1}, x = {.a
165
+ ents[0].def.stmts[0].declarators.length == 1 && # a = 1}, x = {.a
166
+ ents[0].def.stmts[0].declarators[0].init.member_inits.length == 1 && # x = 1, y
167
+ ents[0].def.stmts[0].declarators[0].init.member_inits[0].member && # 1
168
+ ents[0].def.stmts[0].declarators[0].init.member_inits[0].member.length == 1 # a .b
162
169
  return ents[0].def.stmts[0].declarators[0].init.member_inits[0].member[0].detach
163
170
  else
164
171
  raise ParseError, "invalid Member"
@@ -167,12 +174,12 @@ module C
167
174
  end
168
175
 
169
176
  class Statement
170
- def self.parse s, parser=nil
177
+ def self.parse(s, parser=nil)
171
178
  parser ||= C.default_parser
172
179
  ents = parser.parse("void f() {#{s}}").entities
173
- if ents.length == 1 && # } void f() {
180
+ if ents.length == 1 && # } void f() {
174
181
  ents[0].def.stmts.length == 1 && # ;;
175
- ents[0].def.stmts[0].is_a?(self) # int i;
182
+ ents[0].def.stmts[0].is_a?(self) # int i;
176
183
  return ents[0].def.stmts[0].detach
177
184
  else
178
185
  raise ParseError, "invalid #{self}"
@@ -181,10 +188,10 @@ module C
181
188
  end
182
189
 
183
190
  class Label
184
- def self.parse s, parser=nil
191
+ def self.parse(s, parser=nil)
185
192
  parser ||= C.default_parser
186
193
  ents = parser.parse("void f() {switch (0) #{s};}").entities
187
- if ents.length == 1 && # } void f() {
194
+ if ents.length == 1 && # } void f() {
188
195
  ents[0].def.stmts.length == 1 && # ;
189
196
  ents[0].def.stmts[0].stmt && #
190
197
  ents[0].def.stmts[0].stmt.labels.length == 1 && # x
@@ -197,25 +204,39 @@ module C
197
204
  end
198
205
 
199
206
  class Expression
200
- def self.parse s, parser=nil
207
+ def self.parse(s, parser=nil)
201
208
  parser ||= C.default_parser
202
- ents = parser.parse("void f() {#{s};}").entities
203
- if ents.length == 1 && # } void f() {
204
- ents[0].def.stmts.length == 1 && # ;
205
- ents[0].def.stmts[0].is_a?(ExpressionStatement) && # int i
206
- ents[0].def.stmts[0].expr.is_a?(self)
207
- return ents[0].def.stmts[0].expr.detach
209
+ if s =~ /\A(\s*(\/\*.*?\*\/)?)*\{/
210
+ # starts with a brace -- must be a CompoundLiteral. in this
211
+ # case, use a Declarator since only those can handle typeless
212
+ # CompoundLiterals.
213
+ ents = parser.parse("int i = #{s};").entities
214
+ if ents.length == 1 && # 1; int i = 1
215
+ ents[0].declarators.length == 1 && # 1, j = 2
216
+ ents[0].declarators[0].init.is_a?(self)
217
+ return ents[0].declarators[0].init.detach
218
+ else
219
+ raise ParseError, "invalid #{self}"
220
+ end
208
221
  else
209
- raise ParseError, "invalid #{self}"
222
+ ents = parser.parse("void f() {#{s};}").entities
223
+ if ents.length == 1 && # } void f() {
224
+ ents[0].def.stmts.length == 1 && # ;
225
+ ents[0].def.stmts[0].is_a?(ExpressionStatement) && # int i
226
+ ents[0].def.stmts[0].expr.is_a?(self)
227
+ return ents[0].def.stmts[0].expr.detach
228
+ else
229
+ raise ParseError, "invalid #{self}"
230
+ end
210
231
  end
211
232
  end
212
233
  end
213
234
 
214
235
  class Type
215
- def self.parse s, parser=nil
236
+ def self.parse(s, parser=nil)
216
237
  parser ||= C.default_parser
217
238
  ents = parser.parse("void f() {(#{s})x;}").entities
218
- if ents.length == 1 && # 1);} void f() {(int
239
+ if ents.length == 1 && # 1);} void f() {(int
219
240
  ents[0].def.stmts.length == 1 && # 1); (int
220
241
  ents[0].def.stmts[0].expr.type.is_a?(self)
221
242
  return ents[0].def.stmts[0].expr.type.detach
@@ -225,9 +246,9 @@ module C
225
246
  end
226
247
  end
227
248
 
228
- #### Make sure we didn't miss any
249
+ # Make sure we didn't miss any
229
250
  CORE_C_NODE_CLASSES.each do |c|
230
- c.methods.include? 'parse' or
231
- raise "#{c}#parse not defined"
251
+ c.respond_to? :parse or
252
+ raise "#{c}.parse not defined"
232
253
  end
233
254
  end
@@ -0,0 +1,72 @@
1
+ require 'rbconfig'
2
+
3
+ ######################################################################
4
+ #
5
+ # A C preprocessor that wraps the command in Config::CONFIG['CPP'].
6
+ #
7
+ # Assumes a POSIX-style cpp command line interface, in particular, -I
8
+ # and -D options.
9
+ #
10
+ ######################################################################
11
+
12
+ module C
13
+ class Preprocessor
14
+ class Error < StandardError
15
+ end
16
+
17
+ class << self
18
+ attr_accessor :command
19
+ end
20
+ self.command = (defined?(RbConfig) ? RbConfig : Config)::CONFIG['CPP']
21
+
22
+ attr_accessor :pwd, :include_path, :macros
23
+
24
+ def initialize
25
+ @include_path = []
26
+ @macros = {}
27
+ end
28
+ def preprocess(text)
29
+ filename = nil
30
+ Tempfile.open(['cast-preprocessor-input.', '.c'], File.expand_path(pwd || '.')) do |file|
31
+ filename = file.path
32
+ file.puts text
33
+ end
34
+ output = `#{full_command(filename)} 2>&1`
35
+ if $? == 0
36
+ return output
37
+ else
38
+ raise Error, output
39
+ end
40
+ end
41
+ def preprocess_file(file_name)
42
+ file_name = File.expand_path(file_name)
43
+ dir = File.dirname(file_name)
44
+ FileUtils.cd(dir) do
45
+ return preprocess(File.read(file_name))
46
+ end
47
+ end
48
+
49
+ private # -------------------------------------------------------
50
+
51
+ def shellquote(arg)
52
+ if arg !~ /[\"\'\\$&<>|\s]/
53
+ return arg
54
+ elsif arg !~ /\'/
55
+ return "'#{arg}'"
56
+ else
57
+ arg.gsub!(/([\"\\$&<>|])/, '\\\\\\1')
58
+ return "\"#{arg}\""
59
+ end
60
+ end
61
+ def full_command(filename)
62
+ include_args = include_path.map do |path|
63
+ "#{shellquote('-I'+path)}"
64
+ end.join(' ')
65
+ macro_args = macros.sort.map do |key, val|
66
+ shellquote("-D#{key}" + (val ? "=#{val}" : ''))
67
+ end.join(' ')
68
+ filename = shellquote(filename)
69
+ "#{Preprocessor.command} #{include_args} #{macro_args} #{filename}"
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,33 @@
1
+ ######################################################################
2
+ #
3
+ # Alternative to the standard ruby tempfile library, which lets you
4
+ # specify a filename suffix.
5
+ #
6
+ ######################################################################
7
+
8
+ require 'delegate'
9
+ require 'tmpdir'
10
+ require 'tempfile'
11
+
12
+ #
13
+ # Setting the extension of a temp file has only been possible since
14
+ # Ruby 1.8.7.
15
+ #
16
+ module C
17
+ if RUBY_VERSION >= '1.8.7'
18
+ Tempfile = ::Tempfile
19
+ else
20
+ class Tempfile < ::Tempfile
21
+ def initialize(basename, tmpdir=Dir::tmpdir)
22
+ if basename.is_a?(::Array)
23
+ basename, @suffix = *basename
24
+ end
25
+ super(basename, tmpdir)
26
+ end
27
+
28
+ def make_tmpname(basename, n)
29
+ sprintf('%s%d.%d%s', basename, $$, n, @suffix)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,26 +1,24 @@
1
- ###
2
- ### ##################################################################
3
- ###
4
- ### The Node#to_s methods.
5
- ###
6
- ### Yeah, this could be so so *SO* much faster.
7
- ###
8
- ### ##################################################################
9
- ###
1
+ ######################################################################
2
+ #
3
+ # The Node#to_s methods.
4
+ #
5
+ # Yeah, this could be so so *SO* much faster.
6
+ #
7
+ ######################################################################
10
8
 
11
9
  module C
12
- ## undef the #to_s methods so we can check that we didn't forget to
13
- ## define any
10
+ # undef the #to_s methods so we can check that we didn't forget to
11
+ # define any
14
12
  Node.send(:undef_method, :to_s)
15
13
 
16
14
  INDENT = ' '
17
15
  class Node
18
16
  private
19
- def indent s, levels=1
17
+ def indent(s, levels=1)
20
18
  s.gsub(/^/, INDENT*levels)
21
19
  end
22
- def hang stmt, cont=false
23
- if stmt.is_a? Block
20
+ def hang(stmt, cont=false)
21
+ if stmt.is_a?(Block) && stmt.labels.empty?
24
22
  return " #{stmt.to_s(:hanging)}" << (cont ? ' ' : '')
25
23
  else
26
24
  return "\n#{stmt.to_s}" << (cont ? "\n" : '')
@@ -58,7 +56,7 @@ module C
58
56
  static? and str << 'static '
59
57
  inline? and str << 'inline '
60
58
  if no_prototype?
61
- str << "#{type.to_s(name)}\n"
59
+ str << "#{type.to_s(name, true)}\n"
62
60
  type.params.each do |p|
63
61
  str << indent("#{p.to_s};\n")
64
62
  end
@@ -69,14 +67,17 @@ module C
69
67
  end
70
68
  end
71
69
 
72
- ### Statements
70
+ # ------------------------------------------------------------------
71
+ # Statements
72
+ # ------------------------------------------------------------------
73
+
73
74
  class Statement
74
- def label str
75
- labels.map{|s| "#{s}:\n"}.join + indent(str)
75
+ def label(str)
76
+ labels.map{|s| "#{s}\n"}.join + indent(str)
76
77
  end
77
78
  end
78
79
  class Block
79
- def to_s hanging=false
80
+ def to_s(hanging=false)
80
81
  str = stmts.map do |s|
81
82
  if s.is_a? Statement
82
83
  s.to_s
@@ -166,21 +167,24 @@ module C
166
167
 
167
168
  class PlainLabel
168
169
  def to_s
169
- name.to_s
170
+ "#{name}:"
170
171
  end
171
172
  end
172
173
  class Default
173
174
  def to_s
174
- 'default'
175
+ 'default:'
175
176
  end
176
177
  end
177
178
  class Case
178
179
  def to_s
179
- "case #{expr}"
180
+ "case #{expr}:"
180
181
  end
181
182
  end
182
183
 
183
- ### Expressions
184
+ # ------------------------------------------------------------------
185
+ # Expressions
186
+ # ------------------------------------------------------------------
187
+
184
188
  precedence_table = {}
185
189
  [[Comma],
186
190
  [Assign, MultiplyAssign, DivideAssign, ModAssign, AddAssign,
@@ -206,38 +210,40 @@ module C
206
210
  klass.send(:define_method, :to_s_precedence){|| prec}
207
211
  end
208
212
  end
209
- ## check all Expression classes have a precedence
213
+ # check all Expression classes have a precedence
210
214
  C::Expression.subclasses_recursive do |c|
211
215
  next if !C::Node.subclasses_recursive.include? c
212
216
  c.instance_methods.include? 'to_s_precedence' or
213
217
  raise "#{c}#to_s_precedence not defined"
214
218
  end
215
219
 
216
- ## PrefixExpressions
217
- [ [Cast , lambda{"(#{self.type})"}],
218
- [Address , lambda{"&" }],
219
- [Dereference, lambda{"*" }],
220
- [Positive , lambda{"+" }],
221
- [Negative , lambda{"-" }],
222
- [PreInc , lambda{"++" }],
223
- [PreDec , lambda{"--" }],
224
- [BitNot , lambda{"~" }],
225
- [Not , lambda{"!" }]
226
- ].each do |c, proc|
220
+ # PrefixExpressions
221
+ [ [Cast , proc{"(#{self.type})"}, false],
222
+ [Address , proc{"&" }, true ],
223
+ [Dereference, proc{"*" }, false],
224
+ [Positive , proc{"+" }, true ],
225
+ [Negative , proc{"-" }, true ],
226
+ [PreInc , proc{"++" }, false],
227
+ [PreDec , proc{"--" }, false],
228
+ [BitNot , proc{"~" }, false],
229
+ [Not , proc{"!" }, false]
230
+ ].each do |c, proc, space_needed|
227
231
  c.send(:define_method, :to_s) do | |
228
232
  if expr.to_s_precedence < self.to_s_precedence
229
233
  return "#{instance_eval(&proc)}(#{expr})"
234
+ elsif space_needed && expr.class == self.class
235
+ return "#{instance_eval(&proc)} #{expr}"
230
236
  else
231
237
  return "#{instance_eval(&proc)}#{expr}"
232
238
  end
233
239
  end
234
240
  end
235
- ## PostfixExpressions
236
- [ [Arrow , lambda{"->#{member}"}],
237
- [Dot , lambda{".#{member}" }],
238
- [Index , lambda{"[#{index}]" }],
239
- [PostInc , lambda{"++" }],
240
- [PostDec , lambda{"--" }]
241
+ # PostfixExpressions
242
+ [ [Arrow , proc{"->#{member}"}],
243
+ [Dot , proc{".#{member}" }],
244
+ [Index , proc{"[#{index}]" }],
245
+ [PostInc , proc{"++" }],
246
+ [PostDec , proc{"--" }]
241
247
  ].each do |c, proc|
242
248
  c.send(:define_method, :to_s) do | |
243
249
  if expr.to_s_precedence < self.to_s_precedence
@@ -247,7 +253,7 @@ module C
247
253
  end
248
254
  end
249
255
  end
250
- ## BinaryExpressions
256
+ # BinaryExpressions
251
257
  [ [Add , '+' ],
252
258
  [Subtract , '-' ],
253
259
  [Multiply , '*' ],
@@ -273,7 +279,7 @@ module C
273
279
  else
274
280
  str1 = "#{expr1}"
275
281
  end
276
- ## all binary expressions are left associative
282
+ # all binary expressions are left associative
277
283
  if expr2.to_s_precedence <= self.to_s_precedence
278
284
  str2 = "(#{expr2})"
279
285
  else
@@ -282,7 +288,7 @@ module C
282
288
  "#{str1} #{op} #{str2}"
283
289
  end
284
290
  end
285
- ## AssignmentExpressions
291
+ # AssignmentExpressions
286
292
  [ [Assign , '' ],
287
293
  [MultiplyAssign , '*' ],
288
294
  [DivideAssign , '/' ],
@@ -309,52 +315,44 @@ module C
309
315
  "#{lvalstr} #{op}= #{rvalstr}"
310
316
  end
311
317
  end
312
- ## Other Expressions
318
+ # Other Expressions
313
319
  class Sizeof
314
320
  def to_s
315
- if expr.is_a? Expression
316
- if expr.to_s_precedence < self.to_s_precedence
317
- return "sizeof(#{expr})"
318
- else
319
- return "sizeof #{expr}"
320
- end
321
- else
322
- return "sizeof(#{expr})"
323
- end
321
+ "sizeof(#{expr})"
324
322
  end
325
323
  end
326
- ## DirectTypes
324
+ # DirectTypes
327
325
  int_longnesses = ['short ', '', 'long ', 'long long ']
328
326
  float_longnesses = ['float', 'double', 'long double']
329
- [ [Struct, lambda do
327
+ [ [Struct, proc do
330
328
  str = 'struct'
331
329
  name and str << " #{name}"
332
330
  members and str << " {\n" << indent(members.join("\n")) << "\n}"
333
331
  str
334
332
  end],
335
- [Union, lambda do
333
+ [Union, proc do
336
334
  str = 'union'
337
335
  name and str << " #{name}"
338
336
  members and str << " {\n" << indent(members.join("\n")) << "\n}"
339
337
  str
340
338
  end],
341
- [Enum, lambda do
339
+ [Enum, proc do
342
340
  str = 'enum'
343
341
  name and str << " #{name}"
344
342
  members and str << " {\n" << indent(members.join(",\n")) << "\n}"
345
343
  str
346
344
  end],
347
- [CustomType, lambda{name.dup }],
348
- [Void , lambda{'void' }],
349
- [Int , lambda do
345
+ [CustomType, proc{name.dup }],
346
+ [Void , proc{'void' }],
347
+ [Int , proc do
350
348
  longness_str = int_longnesses[longness+1].dup
351
349
  "#{unsigned? ? 'unsigned ' : ''}#{longness_str}int"
352
350
  end],
353
- [Float , lambda{float_longnesses[longness].dup}],
354
- [Char , lambda{"#{unsigned? ? 'unsigned ' : ''}char"}],
355
- [Bool , lambda{'_Bool' }],
356
- [Complex , lambda{'_Complex' }],
357
- [Imaginary , lambda{'_Imaginary'}]
351
+ [Float , proc{float_longnesses[longness].dup}],
352
+ [Char , proc{"#{unsigned? ? 'unsigned ' : signed? ? 'signed ' : ''}char"}],
353
+ [Bool , proc{"_Bool" }],
354
+ [Complex , proc{"_Complex #{float_longnesses[longness]}"}],
355
+ [Imaginary , proc{"_Imaginary #{float_longnesses[longness]}"}]
358
356
  ].each do |c, x|
359
357
  c.send(:define_method, :to_s) do |*args|
360
358
  case args.length
@@ -394,7 +392,7 @@ module C
394
392
  def to_s
395
393
  strs = [:cond, :then, :else].map do |child|
396
394
  val = send(child)
397
- if val.to_s_precedence < self.to_s_precedence
395
+ if val.to_s_precedence <= self.to_s_precedence
398
396
  "(#{val})"
399
397
  else
400
398
  "#{val}"
@@ -422,9 +420,9 @@ module C
422
420
  end
423
421
  end
424
422
 
425
- ### IndirectTypes
423
+ ## IndirectTypes
426
424
  class Pointer
427
- def to_s name=nil
425
+ def to_s(name=nil)
428
426
  str = '*'
429
427
  const? and str << 'const '
430
428
  restrict? and str << 'restrict '
@@ -444,7 +442,7 @@ module C
444
442
  end
445
443
  end
446
444
  class Array
447
- def to_s name=nil
445
+ def to_s(name=nil)
448
446
  str = "#{name}[#{length}]"
449
447
  if type
450
448
  type.to_s(str)
@@ -454,14 +452,18 @@ module C
454
452
  end
455
453
  end
456
454
  class Function
457
- def to_s name=nil
455
+ def to_s(name=nil, no_types=false)
458
456
  str =
459
457
  if params.nil?
460
458
  paramstr = ''
461
459
  elsif params.empty?
462
460
  paramstr = 'void'
463
461
  else
464
- paramstr = params.join(', ')
462
+ if no_types
463
+ paramstr = params.map{|p| p.name}.join(', ')
464
+ else
465
+ paramstr = params.join(', ')
466
+ end
465
467
  end
466
468
  var_args? and paramstr << ', ...'
467
469
  str = "#{name}(#{paramstr})"
@@ -483,7 +485,7 @@ module C
483
485
  end
484
486
  end
485
487
 
486
- ### Literals
488
+ ## Literals
487
489
  class StringLiteral
488
490
  def to_s
489
491
  "\"#{val}\""
@@ -513,7 +515,7 @@ module C
513
515
  ".#{m}"
514
516
  end
515
517
  end
516
- str << member.join(' ') << ' = '
518
+ str << memberstr.join(' ') << ' = '
517
519
  end
518
520
  return str << init.to_s
519
521
  end
@@ -538,8 +540,14 @@ module C
538
540
  name.dup
539
541
  end
540
542
  end
543
+ class BlockExpression
544
+ def to_s
545
+ # note that the grammar does not allow the block to have a label
546
+ "(#{block.to_s(:hanging)})"
547
+ end
548
+ end
541
549
 
542
- ## check we didn't miss any
550
+ # check we didn't miss any
543
551
  CORE_C_NODE_CLASSES.each do |c|
544
552
  c.method_defined? :to_s or
545
553
  raise "#{c}#to_s not defined"