Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
7 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
7 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
7 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "version.h"
63
#include "c_types.h"
64
#include "exp_ops.h"
65
#include "hashid_ops.h"
66
#include "id_ops.h"
67
#include "error.h"
68
#include "tdf.h"
69
#include "basetype.h"
70
#include "capsule.h"
71
#include "check.h"
72
#include "compile.h"
73
#include "destroy.h"
74
#include "diag.h"
75
#include "encode.h"
76
#include "exp.h"
77
#include "init.h"
78
#include "redeclare.h"
79
#include "shape.h"
80
#include "statement.h"
81
#include "struct.h"
82
#include "stmt.h"
83
#include "syntax.h"
84
#include "throw.h"
85
#include "tok.h"
86
 
87
 
88
/*
89
    NUMBER OF PENDING DESTRUCTORS
90
 
91
    This variable keeps track of the number of destructors for local
92
    variables which are pending at any moment during the TDF generation.
93
    This includes such pseudo-destructors as for jump locations in
94
    try blocks.
95
*/
96
 
7 7u83 97
unsigned long no_destructors = 0;
2 7u83 98
 
99
 
100
/*
101
    TDF STATEMENT ENCODING ROUTINES
102
 
103
    The remaining routines are only included if TDF output is enabled.
104
*/
105
 
106
#if TDF_OUTPUT
107
 
108
 
109
/*
110
    FIND THE NUMBER OF COMPONENTS IN A STATEMENT
111
 
112
    This routine finds the number of components in the statement e,
113
    ignoring trivial statements and expanding compound statements
114
    recursively.  The result equals the number of statements added to
115
    the bitstream by enc_compound_stmt.
116
*/
117
 
7 7u83 118
unsigned
119
stmt_length(EXP e)
2 7u83 120
{
7 7u83 121
	if (!IS_NULL_exp(e)) {
122
		switch (TAG_exp(e)) {
123
		case exp_sequence_tag: {
124
			/* Compound statements */
125
			unsigned n = 0;
126
			LIST(EXP)p = DEREF_list(exp_sequence_first(e));
127
			while (!IS_NULL_list(p)) {
128
				EXP a = DEREF_exp(HEAD_list(p));
129
				if (!IS_NULL_exp(a)) {
130
					n += stmt_length(a);
131
				}
132
				p = TAIL_list(p);
133
			}
134
			return (n);
2 7u83 135
		}
7 7u83 136
		case exp_location_tag: {
137
			/* Location statements */
138
			EXP a = DEREF_exp(exp_location_arg(e));
139
			if (!IS_NULL_exp(a)) {
140
				if (is_diag_stmt(a)) {
141
					return (1);
142
				}
143
				return (stmt_length(a));
144
			}
145
			break;
2 7u83 146
		}
7 7u83 147
		case exp_reach_tag:
148
		case exp_unreach_tag: {
149
			/* Flow control statement */
150
			EXP a = DEREF_exp(exp_reach_etc_body(e));
151
			return (stmt_length(a));
152
		}
153
		case exp_set_tag:
154
		case exp_unused_tag: {
155
			/* Variable flow statements */
156
			break;
157
		}
158
		default : {
159
			/* Other statements */
160
			return (1);
161
		}
162
		}
2 7u83 163
	}
7 7u83 164
	return (0);
2 7u83 165
}
166
 
167
 
168
/*
169
    ENCODE A COMPOUND STATEMENT
170
 
171
    This routine adds the statement e to the bitstream bs, ignoring
172
    trivial statements and expanding compound statements recursively.
173
*/
174
 
7 7u83 175
BITSTREAM *
176
enc_compound_stmt(BITSTREAM *bs, EXP e)
2 7u83 177
{
7 7u83 178
	if (!IS_NULL_exp(e)) {
179
		switch (TAG_exp(e)) {
180
		case exp_sequence_tag: {
181
			/* Compound statements */
182
			LIST(EXP)p = DEREF_list(exp_sequence_first(e));
183
			while (!IS_NULL_list(p)) {
184
				EXP a = DEREF_exp(HEAD_list(p));
185
				if (!IS_NULL_exp(a)) {
186
					bs = enc_compound_stmt(bs, a);
187
				}
188
				p = TAIL_list(p);
189
			}
190
			break;
2 7u83 191
		}
7 7u83 192
		case exp_location_tag: {
193
			/* Location statements */
194
			EXP a = DEREF_exp(exp_location_arg(e));
195
			if (!IS_NULL_exp(a)) {
196
				if (is_diag_stmt(a)) {
197
					BITSTREAM *ts = enc_diag_begin(&bs);
198
					ts = enc_stmt(ts, a);
199
					bs = enc_diag_end(bs, ts, a, 1);
200
				} else {
201
					bs = enc_compound_stmt(bs, a);
202
				}
203
			}
204
			crt_enc_loc = exp_location_end(e);
205
			break;
2 7u83 206
		}
7 7u83 207
		case exp_reach_tag:
208
		case exp_unreach_tag: {
209
			/* Flow control statement */
210
			EXP a = DEREF_exp(exp_reach_etc_body(e));
211
			bs = enc_compound_stmt(bs, a);
212
			break;
213
		}
214
		case exp_set_tag:
215
		case exp_unused_tag: {
216
			/* Variable flow statements */
217
			break;
218
		}
219
		default: {
220
			/* Other statements */
221
			bs = enc_stmt(bs, e);
222
			break;
223
		}
224
		}
2 7u83 225
	}
7 7u83 226
	return (bs);
2 7u83 227
}
228
 
229
 
230
/*
231
    ENCODE A LIST OF DESTRUCTORS
232
 
233
    This routine adds all the destructors and pseudo-destructors called
234
    by a jump from e to d to the bitstream bs.
235
*/
236
 
7 7u83 237
static BITSTREAM *
238
enc_destructors(BITSTREAM *bs, EXP e, EXP d)
2 7u83 239
{
7 7u83 240
	unsigned long m = no_destructors;
241
	if (m && !unreached_code) {
242
		unsigned long n = 0;
243
		unsigned long extra = 0;
2 7u83 244
#if LANGUAGE_CPP
7 7u83 245
		unsigned ptag = null_tag;
2 7u83 246
#endif
7 7u83 247
		BITSTREAM *ts = start_bitstream(NIL(FILE), bs->link);
248
		while (!EQ_exp(e, d) && !IS_NULL_exp(e) && n < m) {
249
			unsigned tag = TAG_exp(e);
250
			if (tag == exp_decl_stmt_tag) {
251
				/* Jump out of variable scope */
252
				IDENTIFIER id = DEREF_id(exp_decl_stmt_id(e));
253
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
254
				if (ds & dspec_auto) {
255
					EXP a = DEREF_exp(id_variable_term(id));
256
					if (!IS_NULL_exp(a)) {
257
						/* Destructor found */
258
						ulong v;
259
						int var = 1;
260
						TYPE t = DEREF_type(id_variable_type(id));
261
						if (ds & dspec_explicit) {
262
							if (ds & dspec_temp) {
263
								var = 4;
264
							}
265
						}
266
						v = unit_no(ts, id, VAR_tag, 0);
267
						ts = enc_term_local(ts, v,
268
								    NULL_off,
269
								    0, t, a,
270
								    var);
271
						extra++;
272
						n++;
273
					}
274
				}
2 7u83 275
			}
7 7u83 276
#if LANGUAGE_CPP
277
			/* ... continued */
278
			else if (tag == exp_try_block_tag) {
279
				/* Jump out of try block */
280
				if (ptag != exp_handler_tag) {
281
					ulong ex =
282
					    DEREF_ulong(exp_try_block_no(e));
283
					ts = enc_try_end(ts, ex);
284
					n++;
285
				}
286
			} else if (tag == exp_handler_tag) {
287
				/* Jump out of exception handler */
288
				ts = enc_special(ts, TOK_except_end);
289
				n++;
290
			}
291
			ptag = tag;
292
#endif
293
			e = get_parent_stmt(e);
2 7u83 294
		}
7 7u83 295
 
296
		/* Check for exception specifications */
2 7u83 297
#if LANGUAGE_CPP
7 7u83 298
		if (IS_NULL_exp(e) && n < m && in_exception_spec) {
299
			ts = enc_try_end(ts, last_params[DUMMY_catch]);
300
			n++;
2 7u83 301
		}
302
#endif
303
 
7 7u83 304
		/* Add destructors to main list */
305
		if (n) {
306
			ENC_SEQUENCE(bs, n + extra);
307
		}
308
		bs = join_bitstreams(bs, ts);
2 7u83 309
	}
7 7u83 310
	return (bs);
2 7u83 311
}
312
 
313
 
314
/*
315
    ENCODE THE DESTRUCTOR FOR A CONDITION DECLARATION
316
 
317
    If a condition-declaration in a while or for loop has a destructor
318
    then this destructor needs to be called at the completion of the
319
    loop (this is the normal end-of-scope destructor) and just before
320
    the second and subsequent evaluations of the condition.  This
321
    routine adds the latter such destructors for the variable ids to
322
    the bitstream bs
323
*/
324
 
7 7u83 325
static BITSTREAM *
326
enc_while_destr(BITSTREAM *bs, LIST(IDENTIFIER)ids)
2 7u83 327
{
7 7u83 328
	while (!IS_NULL_list(ids)) {
329
		IDENTIFIER id = DEREF_id(HEAD_list(ids));
330
		EXP d = DEREF_exp(id_variable_term(id));
331
		if (!IS_NULL_exp(d)) {
332
			int var = 1;
333
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
334
			TYPE t = DEREF_type(id_variable_type(id));
335
			ulong n = unit_no(bs, id, VAR_tag, 0);
336
			ENC_SEQ_SMALL(bs, 2);
337
			if ((ds & dspec_explicit) && (ds & dspec_temp)) {
338
				var = 4;
339
			}
340
			bs = enc_term_local(bs, n, NULL_off, 0, t, d, var);
341
		}
342
		ids = TAIL_list(ids);
2 7u83 343
	}
7 7u83 344
	return (bs);
2 7u83 345
}
346
 
347
 
348
/*
349
    ENCODE A LABELLED STATEMENT
350
 
351
    This routine adds the labelled statement 'e' to the bitstream bs.
352
*/
353
 
7 7u83 354
static BITSTREAM *
355
enc_label_stmt(BITSTREAM *bs, EXP e)
2 7u83 356
{
7 7u83 357
	EXP a = DEREF_exp(exp_label_stmt_body(e));
358
	IDENTIFIER lab = DEREF_id(exp_label_stmt_label(e));
359
	IDENTIFIER flab = DEREF_id(id_alias(lab));
360
	if (EQ_id(lab, flab)) {
361
		/* Simple label */
362
		ulong n = DEREF_ulong(id_no(flab));
363
		if (n == LINK_NONE) {
364
			/* Label not previously output */
365
			DECL_SPEC info = DEREF_dspec(id_storage(flab));
366
			if (info & dspec_used) {
367
				n = unit_no(bs, flab, VAR_label, 1);
368
				ENC_repeat(bs);
369
				ENC_make_label(bs, n);
370
				ENC_make_top(bs);
371
				unreached_code = 0;
372
				bs = enc_stmt(bs, a);
373
				clear_no(flab);
374
			} else {
375
				bs = enc_stmt(bs, a);
376
			}
377
		} else {
378
			/* Label body output separately */
379
			ENC_goto(bs);
380
			ENC_make_label(bs, n);
381
			unreached_code = 1;
382
		}
2 7u83 383
	} else {
7 7u83 384
		/* Label alias */
385
		bs = enc_stmt(bs, a);
2 7u83 386
	}
7 7u83 387
	return (bs);
2 7u83 388
}
389
 
390
 
391
/*
392
    ADD A LABEL TO A LIST
393
 
394
    This routine adds the label lab to the list q if it has not been
395
    output in bitstream bs and is not already a member of the list.
396
*/
397
 
7 7u83 398
static LIST(IDENTIFIER)
399
add_label(BITSTREAM *bs, IDENTIFIER lab, LIST(IDENTIFIER)q)
2 7u83 400
{
7 7u83 401
	if (!IS_NULL_id(lab)) {
402
		IDENTIFIER flab = DEREF_id(id_alias(lab));
403
		ulong n = DEREF_ulong(id_no(flab));
404
		if (n == LINK_NONE) {
405
			/* Not previously output */
406
			IGNORE unit_no(bs, flab, VAR_label, 1);
407
			CONS_id(flab, q, q);
408
		}
2 7u83 409
	}
7 7u83 410
	return (q);
2 7u83 411
}
412
 
413
 
414
/*
415
    ADD A NUMBER OF LABELS TO A LIST
416
 
417
    This routine adds the those labels in the list p which have not been
418
    output in bitstream bs to the list q.
419
*/
420
 
7 7u83 421
static LIST(IDENTIFIER)
422
add_labels(BITSTREAM *bs, LIST(IDENTIFIER)p, LIST(IDENTIFIER)q)
2 7u83 423
{
7 7u83 424
	while (!IS_NULL_list(p)) {
425
		IDENTIFIER lab = DEREF_id(HEAD_list(p));
426
		q = add_label(bs, lab, q);
427
		p = TAIL_list(p);
428
	}
429
	return (q);
2 7u83 430
}
431
 
432
 
433
/*
434
    ENCODE THE START OF A LABELLED STATEMENT
435
 
436
    This routine adds the start of a labelled statement for the labels
437
    lbs to the bitstream bs.  This comprises outputting the list of
438
    labels.  vars gives a list of variable declarations which need to
439
    be moved outside the labelled statement.
440
*/
441
 
7 7u83 442
static BITSTREAM *
443
enc_labelled_start(BITSTREAM *bs, LIST(IDENTIFIER)lbs,
444
		   LIST(IDENTIFIER)vars)
2 7u83 445
{
7 7u83 446
	unsigned nl = LENGTH_list(lbs);
447
	while (!IS_NULL_list(vars)) {
448
		/* Declare variables */
449
		IDENTIFIER id = DEREF_id(HEAD_list(vars));
450
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
451
		if (!(ds & dspec_reserve) || !is_anon_member(id)) {
452
			int var = 2;
453
			EXP d = NULL_exp;
454
			if ((ds & dspec_explicit) && (ds & dspec_temp)) {
455
				var = 4;
456
			}
457
			bs = enc_variable(bs, id, var, &d, NULL_exp);
458
			if (!IS_NULL_exp(d)) {
459
				no_destructors++;
460
			}
461
		}
462
		vars = TAIL_list(vars);
2 7u83 463
	}
7 7u83 464
	if (nl == 0) {
465
		/* No labels */
466
		/* EMPTY */
467
	} else if (nl == 1) {
468
		/* Single label can be mapped to conditional */
469
		IDENTIFIER lab = DEREF_id(HEAD_list(lbs));
470
		ulong n = unit_no(bs, lab, VAR_label, 1);
471
		ENC_conditional(bs);
472
		ENC_make_label(bs, n);
473
	} else {
474
		/* Multiple labels require labelled */
475
		ENC_labelled(bs);
476
		ENC_LIST(bs, nl);
477
		while (!IS_NULL_list(lbs)) {
478
			IDENTIFIER lab = DEREF_id(HEAD_list(lbs));
479
			ulong n = unit_no(bs, lab, VAR_label, 1);
480
			ENC_make_label(bs, n);
481
			lbs = TAIL_list(lbs);
482
		}
2 7u83 483
	}
7 7u83 484
	return (bs);
2 7u83 485
}
486
 
487
 
488
/*
489
    ENCODE A BRANCH OF A LABELLED STATEMENT
490
 
491
    This routine adds the branch of the labelled statement d corresponding
492
    to the label lab to the bitstream bs.  Note that each such branch is
493
    terminated by a jump to an immediately following label, a jump to an
494
    enclosing break or continue label, or by falling through to the end
495
    of the labelled statement (see end_solve_branch).
496
*/
497
 
7 7u83 498
static BITSTREAM *
499
enc_labelled_branch(BITSTREAM *bs, IDENTIFIER lab, EXP d)
2 7u83 500
{
7 7u83 501
	ulong n;
502
	IDENTIFIER nlab;
503
	EXP e = DEREF_exp(id_label_stmt(lab));
504
	EXP f = e;
505
	EXP g = NULL_exp;
2 7u83 506
 
7 7u83 507
	/* Examine label type */
508
	int op = DEREF_int(id_label_op(lab));
509
	switch (op) {
2 7u83 510
 
7 7u83 511
	case lex_while:
512
	case lex_for: {
513
		/* While or for label */
514
		e = DEREF_exp(exp_label_stmt_parent(e));
515
		nlab = DEREF_id(exp_while_stmt_cont_lab(e));
516
		e = DEREF_exp(exp_while_stmt_body(e));
517
		if (is_diag_stmt(e)) {
518
			g = e;
519
		}
520
		break;
2 7u83 521
	}
522
 
7 7u83 523
	case lex_do: {
524
		/* Do label */
525
		e = DEREF_exp(exp_label_stmt_parent(e));
526
		nlab = DEREF_id(exp_do_stmt_cont_lab(e));
527
		e = DEREF_exp(exp_do_stmt_body(e));
528
		if (is_diag_stmt(e)) {
529
			g = e;
530
		}
531
		break;
2 7u83 532
	}
533
 
7 7u83 534
	case lex_if: {
535
		/* Conditional label */
536
		EXP c;
537
		int sw = 0;
538
		nlab = DEREF_id(exp_label_stmt_next(e));
539
		e = DEREF_exp(exp_label_stmt_parent(e));
540
		c = DEREF_exp(exp_if_stmt_cond(e));
541
		IGNORE simplify_cond(c, &sw);
542
		if (sw) {
543
			e = DEREF_exp(exp_if_stmt_true_code(e));
544
		} else {
545
			e = DEREF_exp(exp_if_stmt_false_code(e));
546
		}
547
		if (is_diag_stmt(e)) {
548
			g = e;
549
		}
550
		break;
2 7u83 551
	}
552
 
7 7u83 553
	case lex_continue: {
554
		/* Continue label */
555
		EXP c;
556
		unsigned m;
557
		IDENTIFIER rlab;
558
		LIST(IDENTIFIER)cids;
559
		EXP b = DEREF_exp(exp_label_stmt_body(e));
560
		e = DEREF_exp(exp_label_stmt_parent(e));
561
		if (IS_exp_while_stmt(e)) {
562
			c = DEREF_exp(exp_while_stmt_cond(e));
563
			rlab = DEREF_id(exp_while_stmt_loop_lab(e));
564
			nlab = DEREF_id(exp_while_stmt_break_lab(e));
565
			cids = DEREF_list(exp_while_stmt_cond_id(e));
566
		} else {
567
			c = DEREF_exp(exp_do_stmt_cond(e));
568
			rlab = DEREF_id(exp_do_stmt_loop_lab(e));
569
			nlab = DEREF_id(exp_do_stmt_break_lab(e));
570
			cids = NULL_list(IDENTIFIER);
571
		}
572
		m = stmt_length(b);
573
		ENC_SEQUENCE(bs, m + 1);
574
		if (m) {
575
			bs = enc_compound_stmt(bs, b);
576
		}
2 7u83 577
 
7 7u83 578
		/* Output conditional jump */
579
		n = unit_no(bs, rlab, VAR_label, 0);
580
		if (!IS_NULL_list(cids)) {
581
			bs = enc_while_destr(bs, cids);
582
		}
583
		bs = enc_condition(bs, c, LINK_NONE, n);
584
		n = unit_no(bs, nlab, VAR_label, 0);
585
		ENC_goto(bs);
586
		ENC_make_label(bs, n);
587
		unreached_code = 1;
588
		return (bs);
2 7u83 589
	}
590
 
591
	default : {
7 7u83 592
		/* Other labels */
593
		if (!IS_NULL_exp(e)) {
594
			if (is_diag_stmt(e)) {
595
				g = e;
596
			}
597
			nlab = DEREF_id(exp_label_stmt_next(e));
598
			e = DEREF_exp(exp_label_stmt_body(e));
599
		} else {
600
			nlab = NULL_id;
601
		}
602
		break;
2 7u83 603
	}
7 7u83 604
	}
2 7u83 605
 
7 7u83 606
	/* Output label body */
607
	if (IS_NULL_id(nlab)) {
608
		/* Fall through to end of labelled statement */
609
		if (no_destructors) {
610
			if (!IS_NULL_exp(e)) {
611
				ENC_SEQ_SMALL(bs, 1);
612
				if (!IS_NULL_exp(g)) {
613
					BITSTREAM *ts = enc_diag_begin(&bs);
614
					ts = enc_stmt(ts, e);
615
					bs = enc_diag_end(bs, ts, g, 1);
616
				} else {
617
					bs = enc_stmt(bs, e);
618
				}
619
			}
620
			bs = enc_destructors(bs, f, d);
621
			ENC_make_top(bs);
2 7u83 622
		} else {
7 7u83 623
			if (!IS_NULL_exp(g)) {
624
				BITSTREAM *ts = enc_diag_begin(&bs);
625
				ts = enc_stmt(ts, e);
626
				bs = enc_diag_end(bs, ts, g, 1);
627
			} else {
628
				bs = enc_stmt(bs, e);
629
			}
2 7u83 630
		}
631
	} else {
7 7u83 632
		/* Jump to following label */
633
		if (!IS_NULL_exp(e)) {
634
			ENC_SEQ_SMALL(bs, 1);
635
			if (!IS_NULL_exp(g)) {
636
				BITSTREAM *ts = enc_diag_begin(&bs);
637
				ts = enc_stmt(ts, e);
638
				bs = enc_diag_end(bs, ts, g, 1);
639
			} else {
640
				bs = enc_stmt(bs, e);
641
			}
642
		}
643
		op = DEREF_int(id_label_op(nlab));
644
		if (op == lex_break || op == lex_continue) {
645
			/* Need to call destructors for jump */
646
			EXP b = DEREF_exp(id_label_stmt(nlab));
647
			b = DEREF_exp(exp_label_stmt_parent(b));
648
			bs = enc_destructors(bs, f, b);
649
		}
650
		n = unit_no(bs, nlab, VAR_label, 0);
651
		ENC_goto(bs);
652
		ENC_make_label(bs, n);
653
		unreached_code = 1;
2 7u83 654
	}
7 7u83 655
	return (bs);
2 7u83 656
}
657
 
658
 
659
/*
660
    ENCODE THE END OF A LABELLED STATEMENT
661
 
662
    This routine adds the end of the labelled statement e to the bitstream
663
    bs.  This comprises outputting the list of label bodies for the labels
664
    lbs and then taking the labels and the variables vars out of scope.
665
*/
666
 
7 7u83 667
static BITSTREAM *
668
enc_labelled_end(BITSTREAM *bs, LIST(IDENTIFIER)lbs, LIST(IDENTIFIER)vars,
669
		 EXP e)
2 7u83 670
{
7 7u83 671
	int uc = unreached_code;
672
	unsigned nl = LENGTH_list(lbs);
673
	if (nl == 0) {
674
		/* No labels */
675
		/* EMPTY */
676
	} else if (nl == 1) {
677
		/* Single label */
678
		IDENTIFIER lab = DEREF_id(HEAD_list(lbs));
679
		unreached_code = 0;
680
		bs = enc_labelled_branch(bs, lab, e);
681
		if (!unreached_code) {
682
			uc = 0;
683
		}
684
		clear_no(lab);
685
	} else {
686
		/* Multiple labels */
687
		LIST(IDENTIFIER)p = lbs;
688
		ENC_LIST(bs, nl);
689
		while (!IS_NULL_list(p)) {
690
			IDENTIFIER lab = DEREF_id(HEAD_list(p));
691
			unreached_code = 0;
692
			bs = enc_labelled_branch(bs, lab, e);
693
			if (!unreached_code) {
694
				uc = 0;
695
			}
696
			p = TAIL_list(p);
697
		}
698
		p = lbs;
699
		while (!IS_NULL_list(p)) {
700
			IDENTIFIER lab = DEREF_id(HEAD_list(p));
701
			clear_no(lab);
702
			p = TAIL_list(p);
703
		}
2 7u83 704
	}
7 7u83 705
	while (!IS_NULL_list(vars)) {
706
		/* Take variables out of scope */
707
		IDENTIFIER id = DEREF_id(HEAD_list(vars));
708
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
709
		if (ds & dspec_auto) {
710
			clear_no(id);
711
		}
712
		vars = TAIL_list(vars);
2 7u83 713
	}
7 7u83 714
	unreached_code = uc;
715
	return (bs);
2 7u83 716
}
717
 
718
 
719
/*
720
    CURRENT ENCODING LOCATION
721
 
722
    This location is used to store the current location during the
723
    encoding of statements.
724
*/
725
 
7 7u83 726
PTR(LOCATION)crt_enc_loc = NULL_ptr(LOCATION);
2 7u83 727
 
728
 
729
/*
730
    ENCODE A DECLARATION STATEMENT
731
 
732
    This routine adds the declaration statement e to the bitstream bs.
733
*/
734
 
7 7u83 735
static BITSTREAM *
736
enc_decl_stmt(BITSTREAM *bs, EXP e)
2 7u83 737
{
7 7u83 738
	int var = 1;
739
	int scope = 0;
740
	BITSTREAM *ts;
741
	ulong nlabs = 0;
742
	EXP d = NULL_exp;
743
	int diag = output_diag;
744
	EXP a = DEREF_exp(exp_decl_stmt_body(e));
745
	IDENTIFIER id = DEREF_id(exp_decl_stmt_id(e));
746
	TYPE t = DEREF_type(id_variable_type(id));
747
	DECL_SPEC ds = DEREF_dspec(id_storage(id));
748
	if (!(ds & dspec_reserve) || !is_anon_member(id)) {
749
		EXP b = DEREF_exp(id_variable_init(id));
750
		if (IS_NULL_exp(b) || !output_diag) {
751
			/* Don't output diagnostics */
752
			e = NULL_exp;
753
		}
754
		if (ds & dspec_explicit) {
755
			/* Only declare explicitly initialised variables */
756
			if (ds & dspec_temp) {
757
				nlabs = no_labels(bs);
758
				e = NULL_exp;
759
				var = 4;
760
			} else {
761
				var = 3;
762
			}
763
		}
764
		if (ds & dspec_done) {
765
			/* Variable previously declared */
766
			int dummy = 0;
767
			EXP d1 = DEREF_exp(id_variable_term(id));
768
			if (!IS_NULL_exp(d1)) {
769
				/* Allow for terminator expressions */
770
				if (output_except) {
771
					while (IS_exp_nof(d1)) {
772
						d1 = DEREF_exp(exp_nof_pad(d1));
773
					}
774
					if (IS_NULL_exp(b) && var == 1) {
775
						/* Force initialisation */
776
						b = make_dummy_init(t);
777
						dummy = 1;
778
					}
779
				} else {
780
					d1 = NULL_exp;
781
				}
782
			}
783
			if (!IS_NULL_exp(b)) {
784
				ulong n = unit_no(bs, id, VAR_tag, 0);
785
				bs = enc_assign_local(bs, b, d1, n, t, e);
786
				if (IS_exp_thrown(b) && output_new_diag) {
787
					diag = 0;
788
				}
789
				if (dummy)free_exp(b, 1);
790
			}
791
		} else {
792
			/* Variable not previously declared */
793
			bs = enc_variable(bs, id, var, &d, e);
794
			if (ds & dspec_auto) {
795
				scope = 1;
796
			}
797
		}
2 7u83 798
	}
7 7u83 799
	if (diag && !(ds & dspec_temp)) {
800
		HASHID nm = DEREF_hashid(id_name(id));
801
		if (!IS_hashid_anon(nm)) {
802
			ts = start_bitstream(NIL(FILE), bs->link);
2 7u83 803
		} else {
7 7u83 804
			ts = bs;
805
			diag = 0;
2 7u83 806
		}
807
	} else {
7 7u83 808
		ts = bs;
809
		diag = 0;
2 7u83 810
	}
7 7u83 811
	if (IS_NULL_exp(d)) {
812
		ts = enc_stmt(ts, a);
2 7u83 813
	} else {
7 7u83 814
		unsigned seq = stmt_length(a) + 1;
815
		no_destructors++;
816
		ENC_SEQUENCE(ts, seq);
817
		ts = enc_compound_stmt(ts, a);
818
		if (unreached_code) {
819
			ENC_make_top(ts);
820
			ENC_make_top(ts);
821
		} else {
822
			ulong n = unit_no(ts, id, VAR_tag, 0);
823
			if (var == 4 && nlabs == no_labels(bs)) {
824
				var = 3;
825
			}
826
			ts = enc_term_local(ts, n, NULL_off, 0, t, d, var);
827
		}
828
		no_destructors--;
2 7u83 829
	}
7 7u83 830
	if (diag) {
831
		bs = enc_diag_local(bs, id, ts);
2 7u83 832
	} else {
7 7u83 833
		bs = ts;
2 7u83 834
	}
7 7u83 835
	if (scope) {
836
		/* Take variable out of scope */
837
		clear_no(id);
838
	}
839
	return (bs);
2 7u83 840
}
841
 
842
 
843
/*
844
    ENCODE A TDF BODY STATEMENT
845
 
846
    This routine is identical to enc_stmt except that it makes explicit
847
    provision for diagnostic information.
848
*/
849
 
7 7u83 850
static BITSTREAM *
851
enc_body_stmt(BITSTREAM *bs, EXP e)
2 7u83 852
{
7 7u83 853
	if (output_diag && is_diag_stmt(e)) {
854
		BITSTREAM *ts = enc_diag_begin(&bs);
855
		ts = enc_stmt(ts, e);
856
		bs = enc_diag_end(bs, ts, e, 1);
857
	} else {
858
		bs = enc_stmt(bs, e);
859
	}
860
	return (bs);
2 7u83 861
}
862
 
863
 
864
/*
865
    ENCODE A TDF STATEMENT
866
 
867
    This routine adds the statement e to the bitstream bs as a TDF EXP.
868
*/
869
 
7 7u83 870
BITSTREAM *
871
enc_stmt(BITSTREAM *bs, EXP e)
2 7u83 872
{
7 7u83 873
	if (IS_NULL_exp(e)) {
874
		/* Deal with null expressions */
875
		ENC_make_top(bs);
876
		return (bs);
877
	}
2 7u83 878
 
7 7u83 879
	/* Examine expression cases */
880
	switch (TAG_exp(e)) {
2 7u83 881
 
7 7u83 882
	case exp_sequence_tag: {
883
		/* Sequences of statements */
884
		unsigned n = stmt_length(e);
885
		if (n == 0) {
886
			ENC_make_top(bs);
887
		} else {
888
			if (n > 1) {
889
				ENC_SEQUENCE(bs, n - 1);
890
			}
891
			bs = enc_compound_stmt(bs, e);
892
		}
893
		break;
2 7u83 894
	}
895
 
7 7u83 896
	case exp_solve_stmt_tag: {
897
		/* Solve statements */
898
		LIST(IDENTIFIER)p;
899
		EXP a = DEREF_exp(exp_solve_stmt_body(e));
900
		p = DEREF_list(exp_solve_stmt_labels(e));
901
		if (IS_NULL_list(p)) {
902
			/* No labels */
903
			bs = enc_stmt(bs, a);
904
		} else {
905
			LIST(IDENTIFIER)lbs;
906
			LIST(IDENTIFIER)vars;
907
			ulong nd = no_destructors;
908
			lbs = add_labels(bs, p, NULL_list(IDENTIFIER));
909
			vars = DEREF_list(exp_solve_stmt_vars(e));
910
			bs = enc_labelled_start(bs, lbs, vars);
911
			bs = enc_stmt(bs, a);
912
			bs = enc_labelled_end(bs, lbs, vars, e);
913
			DESTROY_list(lbs, SIZE_id);
914
			no_destructors = nd;
915
		}
916
		break;
2 7u83 917
	}
918
 
7 7u83 919
	case exp_decl_stmt_tag: {
920
		/* Variable declarations */
921
		bs = enc_decl_stmt(bs, e);
922
		break;
2 7u83 923
	}
924
 
7 7u83 925
	case exp_while_stmt_tag: {
926
		/* 'while' and 'for' statements */
927
		EXP d;
928
		int uc;
929
		unsigned m;
930
		ulong an, bn;
931
		DECL_SPEC ds;
932
		LIST(IDENTIFIER)cids;
933
		EXP c = DEREF_exp(exp_while_stmt_cond(e));
934
		EXP a = DEREF_exp(exp_while_stmt_body(e));
935
		IDENTIFIER lab = DEREF_id(exp_while_stmt_break_lab(e));
936
		IDENTIFIER loop = DEREF_id(exp_while_stmt_loop_lab(e));
937
		cids = DEREF_list(exp_while_stmt_cond_id(e));
2 7u83 938
 
7 7u83 939
		/* Check for labelled statements */
940
		an = DEREF_ulong(id_no(loop));
941
		if (an != LINK_NONE) {
942
			bn = unit_no(bs, lab, VAR_label, 0);
943
			an = unit_no(bs, loop, VAR_label, 0);
944
			ENC_SEQ_SMALL(bs, 1);
945
			bs = enc_condition(bs, c, bn, LINK_NONE);
946
			ENC_goto(bs);
947
			ENC_make_label(bs, an);
948
			unreached_code = 1;
949
			break;
950
		}
2 7u83 951
 
7 7u83 952
		/* Encode the start of the loop */
953
		bn = unit_no(bs, lab, VAR_label, 1);
954
		an = unit_no(bs, loop, VAR_label, 1);
955
		ENC_conditional(bs);
956
		ENC_make_label(bs, bn);
957
		ENC_SEQ_SMALL(bs, 1);
958
		bs = enc_condition(bs, c, bn, LINK_NONE);
959
		ENC_repeat(bs);
960
		ENC_make_label(bs, an);
961
		ENC_make_top(bs);
962
		uc = unreached_code;
2 7u83 963
 
7 7u83 964
		/* Check for continue jump */
965
		ENC_SEQ_SMALL(bs, 1);
966
		lab = DEREF_id(exp_while_stmt_cont_lab(e));
967
		ds = DEREF_dspec(id_storage(lab));
968
		if (ds & dspec_used) {
969
			/* Body contains a continue jump */
970
			ulong cn = unit_no(bs, lab, VAR_label, 1);
971
			ENC_conditional(bs);
972
			ENC_make_label(bs, cn);
973
			bs = enc_body_stmt(bs, a);
974
			ENC_make_top(bs);
975
		} else {
976
			/* No continue jump */
977
			bs = enc_body_stmt(bs, a);
978
		}
2 7u83 979
 
7 7u83 980
		/* Encode end of label */
981
		d = DEREF_exp(id_label_stmt(lab));
982
		d = DEREF_exp(exp_label_stmt_body(d));
983
		m = stmt_length(d);
984
		if (m) {
985
			ENC_SEQUENCE(bs, m);
986
			bs = enc_compound_stmt(bs, d);
987
		}
988
		if (!IS_NULL_list(cids)) {
989
			bs = enc_while_destr(bs, cids);
990
		}
991
		bs = enc_condition(bs, c, LINK_NONE, an);
992
		ENC_make_top(bs);
993
		if (!uc) {
994
			unreached_code = 0;
995
		}
996
		clear_no(loop);
997
		clear_no(lab);
998
		break;
2 7u83 999
	}
1000
 
7 7u83 1001
	case exp_do_stmt_tag: {
1002
		/* 'do' statements */
1003
		ulong an;
1004
		DECL_SPEC ds;
1005
		int have_break = 0;
1006
		EXP c = DEREF_exp(exp_do_stmt_cond(e));
1007
		EXP a = DEREF_exp(exp_do_stmt_body(e));
1008
		IDENTIFIER lab = DEREF_id(exp_do_stmt_break_lab(e));
1009
		IDENTIFIER loop = DEREF_id(exp_do_stmt_loop_lab(e));
2 7u83 1010
 
7 7u83 1011
		/* Check for labelled statements */
1012
		an = DEREF_ulong(id_no(loop));
1013
		if (an != LINK_NONE) {
1014
			an = unit_no(bs, loop, VAR_label, 0);
1015
			ENC_goto(bs);
1016
			ENC_make_label(bs, an);
1017
			unreached_code = 1;
1018
			break;
1019
		}
2 7u83 1020
 
7 7u83 1021
		/* Check for break label */
1022
		ds = DEREF_dspec(id_storage(lab));
1023
		if (ds & dspec_used) {
1024
			ulong bn = unit_no(bs, lab, VAR_label, 1);
1025
			ENC_conditional(bs);
1026
			ENC_make_label(bs, bn);
1027
			have_break = 1;
1028
		}
2 7u83 1029
 
7 7u83 1030
		/* Encode the start of the loop */
1031
		an = unit_no(bs, loop, VAR_label, 1);
1032
		ENC_repeat(bs);
1033
		ENC_make_label(bs, an);
1034
		ENC_make_top(bs);
1035
		ENC_SEQ_SMALL(bs, 1);
2 7u83 1036
 
7 7u83 1037
		/* Check for continue label */
1038
		lab = DEREF_id(exp_do_stmt_cont_lab(e));
1039
		ds = DEREF_dspec(id_storage(lab));
1040
		if (ds & dspec_used) {
1041
			ulong cn = unit_no(bs, lab, VAR_label, 1);
1042
			ENC_conditional(bs);
1043
			ENC_make_label(bs, cn);
1044
			bs = enc_body_stmt(bs, a);
1045
			ENC_make_top(bs);
1046
		} else {
1047
			bs = enc_body_stmt(bs, a);
1048
		}
2 7u83 1049
 
7 7u83 1050
		/* Encode the end of the loop */
1051
		bs = enc_condition(bs, c, LINK_NONE, an);
1052
		if (have_break) {
1053
			ENC_make_top(bs);
1054
			unreached_code = 0;
1055
		}
1056
		clear_no(loop);
1057
		clear_no(lab);
1058
		break;
2 7u83 1059
	}
1060
 
7 7u83 1061
	case exp_switch_stmt_tag: {
1062
		/* 'switch' statements */
1063
		EXP a;
1064
		EXP b;
1065
		ulong n;
1066
		unsigned nc;
1067
		LIST(NAT)cns;
1068
		IDENTIFIER dl, bl;
1069
		LIST(IDENTIFIER)cls;
1070
		LIST(IDENTIFIER)lbs;
1071
		LIST(IDENTIFIER)els;
1072
		LIST(IDENTIFIER)vars;
1073
		unsigned long nd = no_destructors;
2 7u83 1074
 
7 7u83 1075
		/* Start labelled statement */
1076
		b = DEREF_exp(exp_switch_stmt_body(e));
1077
		cns = DEREF_list(exp_switch_stmt_cases(e));
1078
		cls = DEREF_list(exp_switch_stmt_case_labs(e));
1079
		dl = DEREF_id(exp_switch_stmt_default_lab(e));
1080
		bl = DEREF_id(exp_switch_stmt_break_lab(e));
1081
		els = DEREF_list(exp_solve_stmt_labels(b));
1082
		nc = LENGTH_list(cls);
2 7u83 1083
 
7 7u83 1084
		/* Create list of labels */
1085
		vars = DEREF_list(exp_solve_stmt_vars(b));
1086
		lbs = add_labels(bs, cls, NULL_list(IDENTIFIER));
1087
		lbs = add_label(bs, dl, lbs);
1088
		lbs = add_label(bs, bl, lbs);
1089
		lbs = add_labels(bs, els, lbs);
1090
		lbs = REVERSE_list(lbs);
1091
		bs = enc_labelled_start(bs, lbs, vars);
2 7u83 1092
 
7 7u83 1093
		/* Encode case jump */
1094
		ENC_SEQ_SMALL(bs, 1);
1095
		a = DEREF_exp(exp_switch_stmt_control(e));
1096
		if (IS_NULL_list(cls)) {
1097
			/* No cases */
1098
			bs = enc_exp(bs, a);
1099
		} else {
1100
			ENC_case(bs);
1101
			ENC_false(bs);
1102
			bs = enc_exp(bs, a);
1103
			ENC_LIST(bs, nc);
1104
			while (!IS_NULL_list(cls)) {
1105
				/* Encode case limbs */
1106
				NAT cn = DEREF_nat(HEAD_list(cns));
1107
				IDENTIFIER cl = DEREF_id(HEAD_list(cls));
1108
				n = unit_no(bs, cl, VAR_label, 0);
1109
				ENC_make_label(bs, n);
1110
				bs = enc_snat(bs, cn, 0, 1);
1111
				bs = enc_snat(bs, cn, 0, 1);
1112
				cns = TAIL_list(cns);
1113
				cls = TAIL_list(cls);
1114
			}
2 7u83 1115
		}
1116
 
7 7u83 1117
		/* Default or break jump */
1118
		if (IS_NULL_id(dl)) {
1119
			dl = bl;
1120
		}
1121
		n = unit_no(bs, dl, VAR_label, 0);
1122
		ENC_goto(bs);
1123
		ENC_make_label(bs, n);
1124
		unreached_code = 1;
2 7u83 1125
 
7 7u83 1126
		/* End labelled statement */
1127
		bs = enc_labelled_end(bs, lbs, vars, e);
1128
		DESTROY_list(lbs, SIZE_id);
1129
		no_destructors = nd;
1130
		break;
2 7u83 1131
	}
1132
 
7 7u83 1133
	case exp_return_stmt_tag: {
1134
		/* Return expressions */
1135
		ulong r = last_params[DUMMY_return];
1136
		EXP a = DEREF_exp(exp_return_stmt_value(e));
1137
		if (IS_NULL_exp(a)) {
1138
			/* Plain return */
1139
			bs = enc_destructors(bs, e, NULL_exp);
1140
			ENC_return(bs);
1141
			ENC_make_top(bs);
1142
		} else if (r != LINK_NONE) {
1143
			/* Reference return */
1144
			ENC_SEQ_SMALL(bs, 1);
1145
			if (r == LINK_ZERO) {
1146
				bs = enc_exp(bs, a);
1147
			} else {
1148
				OFFSET off = NULL_off;
1149
				TYPE t = DEREF_type(exp_type(a));
1150
				bs = enc_init_tag(bs, r, off, 1, t, a,
1151
						  NULL_exp, 0);
1152
			}
1153
			bs = enc_destructors(bs, e, NULL_exp);
1154
			ENC_return(bs);
1155
			ENC_make_top(bs);
2 7u83 1156
		} else {
7 7u83 1157
			if (no_destructors) {
1158
				/* Return with destructors */
1159
				if (is_const_exp(a, -1)) {
1160
					bs = enc_destructors(bs, e, NULL_exp);
1161
					ENC_return(bs);
1162
					bs = enc_exp(bs, a);
1163
				} else {
1164
					ulong n = unit_no(bs, NULL_id, VAR_tag, 1);
1165
					ENC_identify(bs);
1166
					bs = enc_access(bs, dspec_none);
1167
					ENC_make_tag(bs, n);
1168
					bs = enc_exp(bs, a);
1169
					bs = enc_destructors(bs, e, NULL_exp);
1170
					ENC_return(bs);
1171
					ENC_obtain_tag(bs);
1172
					ENC_make_tag(bs, n);
1173
				}
1174
			} else {
1175
				/* Simple return */
1176
				ENC_return(bs);
1177
				bs = enc_exp(bs, a);
1178
			}
2 7u83 1179
		}
7 7u83 1180
		unreached_code = 1;
1181
		break;
2 7u83 1182
	}
1183
 
7 7u83 1184
	case exp_goto_stmt_tag: {
1185
		/* Goto expressions */
1186
		EXP a = DEREF_exp(exp_goto_stmt_join(e));
1187
		IDENTIFIER lab = DEREF_id(exp_goto_stmt_label(e));
1188
		ulong n = unit_no(bs, lab, VAR_label, 0);
1189
		bs = enc_destructors(bs, e, a);
1190
		ENC_goto(bs);
1191
		ENC_make_label(bs, n);
1192
		unreached_code = 1;
1193
		break;
2 7u83 1194
	}
1195
 
7 7u83 1196
	case exp_label_stmt_tag: {
1197
		/* Labelled expressions */
1198
		if (is_diag_stmt(e)) {
1199
			IDENTIFIER lab = DEREF_id(exp_label_stmt_label(e));
1200
			ulong n = DEREF_ulong(id_no(lab));
1201
			if (n == LINK_NONE) {
1202
				BITSTREAM *ts = enc_diag_begin(&bs);
1203
				ts = enc_label_stmt(ts, e);
1204
				bs = enc_diag_end(bs, ts, e, 1);
1205
			} else {
1206
				bs = enc_label_stmt(bs, e);
1207
			}
2 7u83 1208
		} else {
7 7u83 1209
			bs = enc_label_stmt(bs, e);
2 7u83 1210
		}
7 7u83 1211
		break;
2 7u83 1212
	}
1213
 
1214
#if LANGUAGE_CPP
7 7u83 1215
	case exp_try_block_tag: {
1216
		/* Try block */
1217
		bs = enc_try(bs, e);
1218
		break;
2 7u83 1219
	}
1220
 
7 7u83 1221
	case exp_handler_tag: {
1222
		/* Exception handler */
1223
		BITSTREAM *ts;
1224
		EXP a = DEREF_exp(exp_handler_body(e));
1225
		IDENTIFIER id = DEREF_id(exp_handler_except(e));
1226
		if (!IS_NULL_id(id)) {
1227
			/* Declare exception variable */
1228
			EXP d = NULL_exp;
1229
			bs = enc_variable(bs, id, 2, &d, NULL_exp);
1230
			if (!IS_NULL_exp(d)) {
1231
				no_destructors++;
1232
			}
1233
		}
1234
		ts = enc_diag_begin(&bs);
1235
		ts = enc_stmt(ts, a);
1236
		bs = enc_diag_end(bs, ts, e, 1);
1237
		clear_no(id);
1238
		break;
2 7u83 1239
	}
1240
#endif
1241
 
7 7u83 1242
	case exp_location_tag: {
1243
		/* Location statement */
1244
		EXP a = DEREF_exp(exp_location_arg(e));
1245
		bs = enc_body_stmt(bs, a);
1246
		crt_enc_loc = exp_location_end(e);
1247
		break;
2 7u83 1248
	}
1249
 
7 7u83 1250
	case exp_reach_tag:
1251
	case exp_unreach_tag: {
1252
		/* Flow control statement */
1253
		EXP a = DEREF_exp(exp_reach_etc_body(e));
1254
		bs = enc_stmt(bs, a);
1255
		break;
2 7u83 1256
	}
1257
 
7 7u83 1258
	case exp_if_stmt_tag:
1259
	case exp_hash_if_tag:
1260
	default: {
1261
		/* Expression statements */
1262
		bs = enc_stmt_exp(bs, e, type_void, 0);
1263
		break;
2 7u83 1264
	}
7 7u83 1265
	}
1266
	return (bs);
2 7u83 1267
}
1268
 
1269
 
1270
/*
1271
    ENCODE A TDF EXPRESSION STATEMENT
1272
 
1273
    This routine adds the expression statement e to the bitstream bs as
1274
    a TDF EXP.  use indicates how the value of the expression is used.
1275
*/
1276
 
7 7u83 1277
BITSTREAM *
1278
enc_stmt_exp(BITSTREAM *bs, EXP e, TYPE t, int use)
2 7u83 1279
{
7 7u83 1280
	if (IS_NULL_exp(e)) {
1281
		/* Deal with null expressions */
1282
		ENC_make_top(bs);
1283
		return (bs);
1284
	}
2 7u83 1285
 
7 7u83 1286
	/* Examine expression cases */
1287
	switch (TAG_exp(e)) {
2 7u83 1288
 
7 7u83 1289
	case exp_solve_stmt_tag:
1290
	case exp_decl_stmt_tag:
1291
	case exp_while_stmt_tag:
1292
	case exp_do_stmt_tag:
1293
	case exp_switch_stmt_tag:
1294
	case exp_return_stmt_tag:
1295
	case exp_goto_stmt_tag:
1296
	case exp_label_stmt_tag:
1297
	case exp_try_block_tag:
1298
	case exp_handler_tag: {
1299
		/* Simple statements */
1300
		bs = enc_stmt(bs, e);
1301
		break;
2 7u83 1302
	}
1303
 
7 7u83 1304
	case exp_sequence_tag: {
1305
		/* Lexical blocks */
1306
		bs = enc_body_stmt(bs, e);
1307
		break;
2 7u83 1308
	}
1309
 
7 7u83 1310
	case exp_if_stmt_tag: {
1311
		/* Conditional statements */
1312
		ulong n;
1313
		int ua, ub;
1314
		int sw = 0;
1315
		int whole = 1;
1316
		ulong m = LINK_NONE;
1317
		EXP c = DEREF_exp(exp_if_stmt_cond(e));
1318
		EXP a = DEREF_exp(exp_if_stmt_true_code(e));
1319
		EXP b = DEREF_exp(exp_if_stmt_false_code(e));
2 7u83 1320
 
7 7u83 1321
		/* Check for labelled statements */
1322
		IDENTIFIER lab = DEREF_id(exp_if_stmt_label(e));
1323
		if (!IS_NULL_id(lab)) {
1324
			n = DEREF_ulong(id_no(lab));
1325
			if (n != LINK_NONE) {
1326
				whole = 0;
1327
			}
1328
		}
1329
		n = unit_no(bs, lab, VAR_label, whole);
1330
		if (whole) {
1331
			/* Introduce conditional label */
1332
			ENC_conditional(bs);
1333
			ENC_make_label(bs, n);
1334
		}
1335
		c = simplify_cond(c, &sw);
1336
		if (sw) {
1337
			/* Switch conditions */
1338
			EXP d = a;
1339
			a = b;
1340
			b = d;
1341
			m = n;
1342
			n = LINK_NONE;
1343
		}
1344
		if (!IS_NULL_exp(a)) {
1345
			ENC_SEQ_SMALL(bs, 1);
1346
		}
1347
		bs = enc_condition(bs, c, n, m);
1348
		ub = unreached_code;
1349
		if (!IS_NULL_exp(a)) {
1350
			bs = enc_stmt_exp(bs, a, t, use);
1351
		}
1352
		ua = unreached_code;
1353
		if (whole) {
1354
			/* Conditional label body */
1355
			unreached_code = ub;
1356
			bs = enc_stmt_exp(bs, b, t, use);
1357
			ub = unreached_code;
1358
			clear_no(lab);
1359
		}
1360
		unreached_code = (ua && ub);
1361
		break;
2 7u83 1362
	}
1363
 
7 7u83 1364
	case exp_hash_if_tag: {
1365
		/* Conditional compilations */
1366
		int ua, ub;
1367
		BITSTREAM *ts;
1368
		EXP c = DEREF_exp(exp_hash_if_cond(e));
1369
		EXP a = DEREF_exp(exp_hash_if_true_code(e));
1370
		EXP b = DEREF_exp(exp_hash_if_false_code(e));
1371
		ENC_exp_cond(bs);
1372
		bs = enc_exp(bs, c);
1373
		ts = start_bitstream(NIL(FILE), bs->link);
1374
		ub = unreached_code;
1375
		ts = enc_stmt_exp(ts, a, t, use);
1376
		ua = unreached_code;
1377
		bs = enc_bitstream(bs, ts);
1378
		ts = start_bitstream(NIL(FILE), bs->link);
1379
		unreached_code = ub;
1380
		ts = enc_stmt_exp(ts, b, t, use);
1381
		ub = unreached_code;
1382
		bs = enc_bitstream(bs, ts);
1383
		unreached_code = (ua && ub);
1384
		break;
2 7u83 1385
	}
1386
 
7 7u83 1387
	case exp_location_tag: {
1388
		/* Location statements */
1389
		EXP a = DEREF_exp(exp_location_arg(e));
1390
		BITSTREAM *ts = enc_diag_begin(&bs);
1391
		ts = enc_stmt_exp(ts, a, t, use);
1392
		crt_enc_loc = exp_location_end(e);
1393
		bs = enc_diag_end(bs, ts, a, 0);
1394
		break;
2 7u83 1395
	}
1396
 
7 7u83 1397
	case exp_comma_tag: {
1398
		/* Comma expressions */
1399
		EXP a;
1400
		LIST(EXP)p = DEREF_list(exp_comma_args(e));
1401
		unsigned m = LENGTH_list(p);
1402
		if (m > 1) {
1403
			ENC_SEQUENCE(bs, m - 1);
1404
		}
1405
		for (;;) {
1406
			a = DEREF_exp(HEAD_list(p));
1407
			p = TAIL_list(p);
1408
			if (IS_NULL_list(p)) {
1409
				break;
1410
			}
1411
			bs = enc_stmt_exp(bs, a, type_void, 0);
1412
		}
1413
		if (use != -1) {
1414
			bs = enc_stmt_exp(bs, a, t, use);
1415
		}
1416
		break;
2 7u83 1417
	}
1418
 
7 7u83 1419
	case exp_paren_tag:
1420
	case exp_copy_tag: {
1421
		/* Parenthesised expressions */
1422
		EXP a = DEREF_exp(exp_paren_etc_arg(e));
1423
		bs = enc_stmt_exp(bs, a, t, use);
1424
		break;
2 7u83 1425
	}
1426
 
7 7u83 1427
	case exp_contents_tag: {
1428
		/* Contents expressions */
1429
		if (use == 0) {
1430
			EXP a = DEREF_exp(exp_contents_ptr(e));
1431
			bs = enc_exp(bs, a);
1432
			break;
1433
		}
1434
		goto default_lab;
2 7u83 1435
	}
1436
 
7 7u83 1437
	default:
1438
default_lab: {
1439
		      /* Simple expressions */
1440
		      switch (use) {
1441
		      case 2: {
1442
			      bs = enc_addr_exp(bs, t, e);
1443
			      break;
1444
		      }
1445
		      case 3: {
1446
			      bs = enc_cont_exp(bs, t, e);
1447
			      break;
1448
		      }
1449
		      default : {
1450
			      bs = enc_exp(bs, e);
1451
			      break;
1452
		      }
1453
		      }
1454
		      break;
1455
	      }
2 7u83 1456
	}
7 7u83 1457
	return (bs);
2 7u83 1458
}
1459
 
1460
 
1461
#endif /* TDF_OUTPUT */