3 #define BLOCK_START_MAYTHROW(X) \
4 CLEAR_MAYTHROW; int pos = get_stream_pos (X); SAVE_VAR (did_unwind, false);
5 #define BLOCK_END_MAYTHROW(X) \
6 if (TEST_MAYTHROW && did_unwind) { wipeout_unwind (X, pos); } RESTOR_VAR (did_unwind);
8 NormPtr
statement (OUTSTREAM
, NormPtr
);
10 static NormPtr
parenth_expression (OUTSTREAM o
, NormPtr p
)
13 if (CODE
[p
++] != '(')
14 parse_error (p
, "missing '(' after reserved keyword");
15 p
= parse_expression (p
, &E
, NORMAL_EXPR
);
16 if (!E
.ok
) parse_error (p
, "compilation stops here");
17 if (CODE
[p
++] != ')')
18 parse_error (p
, "missing ')' after reserved keyword");
19 outprintf (o
, '(', ISTR (E
.newExpr
), ')', -1);
24 static NormPtr
__asm___statement (OUTSTREAM o
, NormPtr p
)
27 if (CODE
[p
] == RESERVED_volatile
)
29 if (CODE
[p
++] != '(')
30 parse_error (p
, "__asm__ '('");
31 p
= skip_parenthesis (p
);
32 if (CODE
[p
++] != ';')
33 parse_error (p
, "missing ';' after __asm__");
34 outprintf (o
, RESERVED___asm__
, NSTRNEXT
, CODE
+ p2
, p
- p2
, ';', - 1);
38 static NormPtr
if_statement (OUTSTREAM o
, NormPtr p
)
40 output_itoken (o
, RESERVED_if
);
41 p
= statement (o
, parenth_expression (o
, p
));
42 // oh my god. this must be the horrible if-else ambiguity!
43 if (CODE
[p
] == RESERVED_else
) {
44 output_itoken (o
, RESERVED_else
);
45 p
= statement (o
, p
+ 1);
50 /* general statmenent at catchpoint which may catch longbreak/longcontinue */
51 static NormPtr
loop_body_statement (OUTSTREAM o
, NormPtr p
, int cp
)
54 OUTSTREAM t
= new_stream ();
58 rmv_catchpoint (&lbrk
, &lcnt
);
60 if (lcnt
|| lbrk
) output_itoken (o
, '{');
61 concate_streams (o
, t
);
62 if (lcnt
) outprintf (o
, lcnt
, ':', lbrk
? BLANKT
: ';', -1);
63 if (lbrk
) outprintf (o
, RESERVED_continue
, ';', lbrk
, ':', RESERVED_break
, ';', -1);
64 if (lcnt
|| lbrk
) output_itoken (o
, '}');
71 Token addr1
, dflt
, base
, array
;
74 static NormPtr
switch_statement (OUTSTREAM o
, NormPtr p
)
77 /* Feature: switch (declaration) */
78 if (dcl
= CODE
[p
] == '(' && is_dcl_start (CODE
[p
+ 1]) && CODE
[p
+ 2] != '.') {
80 p
= skip_parenthesis (p2
= p
+ 1) - 1;
83 output_itoken (o
, '{');
84 local_declaration (o
, p2
);
86 outprintf (o
, RESERVED_switch
, '(', recent_obj (), ')', -1);
87 /* ^^^^^^^^^^^^^^^^^^^^^^^ */
89 output_itoken (o
, RESERVED_switch
);
90 p
= parenth_expression (o
, p
);
93 /* Feature: gather switch label addresses */
95 if (CODE
[p
] == ':') {
96 if (!syntax_pattern (p
, ':', VERIFY_symbol
, ',', VERIFY_symbol
, '[', ']', -1))
97 parse_error (p
, "The syntax is 'switch () : name1, name2 []'");
98 outprintf (cl
.caselabels
= new_stream (), RESERVED_static
, RESERVED_const
,
99 RESERVED_int
, cl
.array
= CODE
[p
+ 3], '[', ']', '=', '{', -1);
100 cl
.base
= CODE
[p
+ 1];
103 /* :::::::::::::::::::::::::::::::::::::: */
105 p
= loop_body_statement (o
, p
, 1);
108 close_local_scope ();
109 output_itoken (o
, '}');
112 /* make label addresses */
114 Token
*dcl
= combine_output (cl
.caselabels
), v
= cl
.dflt
?: cl
.addr1
;
116 for (i
= 0; dcl
[i
] != -1; i
++)
117 if (dcl
[i
] == RESERVED_0
) dcl
[i
] = v
;
118 outprintf (o
, ISTR (dcl
), '}', ';', RESERVED_static
, RESERVED_void
,
119 '*', cl
.base
, '=', ANDAND
, v
, ';', -1);
120 enter_local_obj (cl
.array
, typeID_intP
);
121 enter_local_obj (cl
.base
, typeID_voidP
);
125 /* :::::::::::::::::::: */
130 static NormPtr
do_statement (OUTSTREAM o
, NormPtr p
)
132 OUTSTREAM S
= new_stream ();
134 p
= loop_body_statement (S
, p
, 2);
136 if (CODE
[p
] == RESERVED_while
) {
137 output_itoken (o
, RESERVED_do
);
138 concate_streams (o
, S
);
139 output_itoken (o
, RESERVED_while
);
140 p
= parenth_expression (o
, p
+ 1);
141 if (CODE
[p
++] != ';')
142 parse_error (p
, "this is special. You need a ';'");
143 output_itoken (o
, ';');
144 /* Feature: do without while */
146 outprintf (o
, RESERVED_for
, '(', ';', ';', ')', '{', - 1);
147 concate_streams (o
, S
);
148 outprintf (o
, RESERVED_break
, ';', '}', - 1);
150 /* ^^^^^^^^^^^^^^^^^^^^^^^^^ */
155 static NormPtr
for_statement (OUTSTREAM o
, NormPtr p
)
160 if (CODE
[p
++] != '(')
161 parse_error (p
, "for '('");
162 /* Feature: first part may be declaration */
163 if (first_dcl
= is_dcl_start (CODE
[p
])) {
164 output_itoken (o
, '{');
166 p
= local_declaration (o
, p
) - 1;
167 (E1
.newExpr
= mallocint (1)) [0] = -1;
169 } else p
= parse_expression (p
, &E1
, NORMAL_EXPR
);
170 if (CODE
[p
++] != ';')
171 parse_error (p
, "for (';'");
172 p
= parse_expression (p
, &E2
, NORMAL_EXPR
);
173 if (CODE
[p
++] != ';')
174 parse_error (p
, "for (;';'");
175 p
= parse_expression (p
, &E3
, NORMAL_EXPR
);
176 if (CODE
[p
++] != ')')
177 parse_error (p
, "for (;';')");
178 if (!(E1
.ok
&& E2
.ok
&& E3
.ok
))
179 parse_error (p
, "compilation halted at for()");
180 outprintf (o
, RESERVED_for
, '(', ISTR (E1
.newExpr
), ';',
181 ISTR (E2
.newExpr
), ';', ISTR (E3
.newExpr
), ')', -1);
186 p
= loop_body_statement (o
, p
, 2);
189 close_local_scope ();
190 output_itoken (o
, '}');
195 static NormPtr
while_statement (OUTSTREAM o
, NormPtr p
)
197 output_itoken (o
, RESERVED_while
);
198 p
= loop_body_statement (o
, parenth_expression (o
, p
), 2);
202 static NormPtr
return_statement (OUTSTREAM o
, NormPtr p
)
206 p
= parse_expression_retconv (p
, &E
, return_typeID
, NORMAL_EXPR
);
207 if (!E
.ok
) return p
+ 1;
209 /* Feature: a 'return;' in destructors, returns this */
210 if (!(he
= E
.newExpr
[0] != -1) && (he
= objective
.isdtor
))
211 sintprintf (frealloc (&E
.newExpr
, 2), RESERVED_this
, -1);
213 /* Feature: before return, call internal destruction */
214 if (objective
.isdtor
&& idtor (objective
.class)) {
215 Token
*t
= mallocint (intlen (E
.newExpr
) + 7);
216 sintprintf (t
, idtor (objective
.class), '(', RESERVED_this
, ')', ',',
217 ISTR (E
.newExpr
), -1);
222 /* Feature: destructors for all locals */
223 if (func_has_dtors ()) {
224 outprintf (o
, '{', -1);
225 if (he
) outprintf (o
, RESERVED___typeof__
, '(', ISTR (E
.newExpr
), ')',
226 internal_identifier1 (), '=', ISTR (E
.newExpr
), ';', -1);
227 gen_all_destructors (o
);
228 outprintf (o
, RESERVED_return
, he
? internal_identifier1 () : BLANKT
, ';', '}', -1);
230 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
231 outprintf (o
, RESERVED_return
, ISTR (E
.newExpr
), ';', -1);
234 parse_error (p
, "expecting ';' after return");
238 static NormPtr
case_statement (OUTSTREAM o
, NormPtr p
)
243 output_itoken (o
, RESERVED_case
);
244 p
= parse_expression (p
, &E
, NORMAL_EXPR
);
245 if (E
.ok
) outprintf (o
, ISTR (E
.newExpr
), -1);
249 v
= toktokcat (RESERVED_case
, E
.newExpr
[1] != -1 ?
250 internal_identifiern (uniq
++) : E
.newExpr
[0]);
251 if (!cl
.addr1
) cl
.addr1
= v
;
252 outprintf (cl
.caselabels
, '[', ISTR (E
.newExpr
), ']', '=',
253 ANDAND
, v
, '-', ANDAND
, RESERVED_0
, ',', -1);
257 /* extension '...' in case */
258 if (CODE
[p
] == ELLIPSIS
) {
259 if (v
) parse_error (p
, "Can't gather labels for '...' case");
260 p
= parse_expression (p
, &E
, NORMAL_EXPR
);
262 outprintf (o
, ELLIPSIS
, ISTR (E
.newExpr
), -1);
266 if (CODE
[p
] != ':') parse_error (p
, "case ':' error");
267 output_itoken (o
, ':');
269 if (v
) outprintf (o
, v
, ':', -1);
273 static NormPtr
expression_statement (OUTSTREAM o
, NormPtr p
)
276 p
= parse_expression (p
, &E
, NORMAL_EXPR
);
277 if (CODE
[p
++] != ';') parse_error (p
, "expression';'");
279 outprintf (o
, ISTR (E
.newExpr
), ';', -1);
285 static inline bool is_declaration (NormPtr p
)
287 return is_dcl_start (CODE
[p
]) && !(ISSYMBOL (CODE
[p
]) && CODE
[p
+ 1] == '.');
294 NormPtr
compound_statement (OUTSTREAM o
, NormPtr p
)
299 SAVE_VAR (special_debug
, CODE
[p
] == RESERVED_0
);
300 if (CODE
[p
] == RESERVED_0
) ++p
;
302 BLOCK_START_MAYTHROW (o
);
304 output_itoken (o
, '{');
305 while (CODE
[p
] != '}') {
306 noend
= in4 (CODE
[p
], RESERVED_return
, RESERVED_break
,
307 RESERVED_continue
, RESERVED_goto
);
308 p
= is_declaration (p
) ? local_declaration (o
, p
) : statement (o
, p
);
310 /* Feature: destructors of local objects */
311 if (scope_has_dtors () && !noend
)
312 gen_auto_destruction (o
, !may_throw
);
313 /* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
314 output_itoken (o
, '}');
315 close_local_scope ();
316 BLOCK_END_MAYTHROW (o
);
318 RESTOR_VAR (special_debug
);
323 static NormPtr
jump_statement (OUTSTREAM o
, NormPtr p
, Token t
)
325 int cont
= t
== RESERVED_continue
? 2 : 1;
328 /* Feature: break 2; */
329 int break_n
= ISVALUE (CODE
[p
]) ? eval_int (CODE
[p
++]) : 1;
330 /* ^^^^^^^^^^^^^^^^^ */
333 parse_error (p
, "break/continue ';'");
335 /* Feature: destructors of local objects */
336 if ((bhd
= break_has_dtors (cont
)) || break_n
!= 1) {
339 if (bhd
) output_itoken (o
, '{');
340 if (lbl
= gen_break_destructors (o
, cont
, break_n
))
341 outprintf (o
, RESERVED_goto
, lbl
, ';', -1);
342 else outprintf (o
, t
, ';', -1);
343 if (bhd
) output_itoken (o
, '}');
345 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
346 outprintf (o
, t
, ';', -1);
350 static NormPtr
goto_statement (OUTSTREAM o
, NormPtr p
)
352 /* GNUC: computed goto */
353 if (CODE
[p
] == '*') {
354 outprintf (o
, RESERVED_goto
, '*', -1);
355 return expression_statement (o
, p
+ 1);
357 /* Feature: goto (...) ? l1 : l2 */
358 if (CODE
[p
] == '(' && CODE
[skip_parenthesis (p
+ 1)] == '?') {
359 outprintf (o
, '{', RESERVED_if
, -1);
360 p
= parenth_expression (o
, p
);
361 syntax_pattern (p
, '?', VERIFY_symbol
, ':', VERIFY_symbol
, ';', -1);
362 outprintf (o
, RESERVED_goto
, CODE
[p
+ 1], ';',
363 RESERVED_goto
, CODE
[p
+ 3], ';', '}', -1);
367 if (!ISSYMBOL (CODE
[p
]) || CODE
[p
+ 1] != ';')
368 parse_error (p
, "'goto label;' only");
369 outprintf (o
, RESERVED_goto
, CODE
[p
], ';', -1);
373 NormPtr
statement (OUTSTREAM o
, NormPtr p
)
375 Token t
= CODE
[p
++];
377 if (ISSYMBOL (t
) && CODE
[p
] == ':') {
378 outprintf (o
, t
, CODE
[p
++], -1);
379 return CODE
[p
] == '}' ? p
: statement (o
, p
);
383 case '{': return compound_statement (o
, p
);
384 case RESERVED_case
: return case_statement (o
, p
);
385 case RESERVED_return
: return return_statement (o
, p
);
386 case RESERVED_while
: return while_statement (o
, p
);
387 case RESERVED_for
: return for_statement (o
, p
);
388 case RESERVED_do
: return do_statement (o
, p
);
389 case RESERVED_switch
: return switch_statement (o
, p
);
390 case RESERVED_if
: return if_statement (o
, p
);
391 case RESERVED_else
: parse_error (p
, "else without if");
392 case RESERVED_throw
: return throw_statement (o
, p
);
393 case RESERVED_try
: return try_statement (o
, p
);
394 case RESERVED___on_throw__
:
395 return on_throw_statement (o
, p
);
396 case RESERVED___asm__
: return __asm___statement (o
, p
);
397 case RESERVED_continue
:
398 case RESERVED_break
: return jump_statement (o
, p
, t
);
399 case RESERVED_goto
: return goto_statement (o
, p
);
400 default: return expression_statement (o
, p
- 1);
402 output_itoken (o
, ';');
404 case RESERVED_default
:
405 if (CODE
[p
] != ':') parse_error (p
, "default:");
406 outprintf (o
, RESERVED_default
, ':', -1);
408 cl
.dflt
= tokstrcat (RESERVED_default
, "_label");
409 outprintf (o
, cl
.dflt
, ':', -1);
415 /* This is a compound statement inside an expression */
416 Token
*rewrite_compound_statement (Token
*t
)
418 OUTSTREAM o
= new_stream ();
421 SAVE_VAR (last_location
, 0);
423 output_itoken (o
, '(');
424 compound_statement (o
, 0);
425 output_itoken (o
, ')');
428 RESTOR_VAR (last_location
);
430 return combine_output (o
);