~ubuntu-branches/ubuntu/vivid/inform/vivid

« back to all changes in this revision

Viewing changes to src/states.c

  • Committer: Bazaar Package Importer
  • Author(s): Jan Christoph Nordholz
  • Date: 2008-05-26 22:09:44 UTC
  • mfrom: (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526220944-ba7phz0d1k4vo7wx
Tags: 6.31.1+dfsg-1
* Remove a considerable number of files from the package
  due to unacceptable licensing terms.
* Repair library symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* ------------------------------------------------------------------------- */
2
 
/*   "states" :  Statement translator                                        */
3
 
/*                                                                           */
4
 
/*   Part of Inform 6.30                                                     */
5
 
/*   copyright (c) Graham Nelson 1993 - 2004                                 */
6
 
/*                                                                           */
7
 
/* ------------------------------------------------------------------------- */
8
 
 
9
 
#include "header.h"
10
 
 
11
 
static int match_colon(void)
12
 
{   get_next_token();
13
 
    if (token_type == SEP_TT)
14
 
    {   if (token_value == SEMICOLON_SEP)
15
 
            warning("Unlike C, Inform uses ':' to divide parts \
16
 
of a 'for' loop specification: replacing ';' with ':'");
17
 
        else
18
 
        if (token_value != COLON_SEP)
19
 
        {   ebf_error("':'", token_text);
20
 
            panic_mode_error_recovery();
21
 
            return(FALSE);
22
 
        }
23
 
    }
24
 
    else
25
 
    {   ebf_error("':'", token_text);
26
 
        panic_mode_error_recovery();
27
 
        return(FALSE);
28
 
    }
29
 
    return(TRUE);
30
 
}
31
 
 
32
 
static void match_open_bracket(void)
33
 
{   get_next_token();
34
 
    if ((token_type == SEP_TT) && (token_value == OPENB_SEP)) return;
35
 
    put_token_back();
36
 
    ebf_error("'('", token_text);
37
 
}
38
 
 
39
 
extern void match_close_bracket(void)
40
 
{   get_next_token();
41
 
    if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP)) return;
42
 
    put_token_back();
43
 
    ebf_error("')'", token_text);
44
 
}
45
 
 
46
 
static void parse_action(void)
47
 
{   int level = 1, args = 0, codegen_action;
48
 
    assembly_operand AO, AO2, AO3, AO4;
49
 
 
50
 
    dont_enter_into_symbol_table = TRUE;
51
 
    get_next_token();
52
 
    if ((token_type == SEP_TT) && (token_value == LESS_SEP))
53
 
    {   level = 2; get_next_token();
54
 
    }
55
 
    dont_enter_into_symbol_table = FALSE;
56
 
 
57
 
    if ((token_type==SEP_TT) && (token_value==OPENB_SEP))
58
 
    {   put_token_back();
59
 
        AO2 = parse_expression(ACTION_Q_CONTEXT);
60
 
        codegen_action = TRUE;
61
 
    }
62
 
    else
63
 
    {   codegen_action = FALSE;
64
 
        AO2 = action_of_name(token_text);
65
 
    }
66
 
 
67
 
    get_next_token();
68
 
    if (!((token_type == SEP_TT) && (token_value == GREATER_SEP)))
69
 
    {   put_token_back();
70
 
        args = 1;
71
 
        AO3 = parse_expression(ACTION_Q_CONTEXT);
72
 
 
73
 
        get_next_token();
74
 
        if (!((token_type == SEP_TT) && (token_value == GREATER_SEP)))
75
 
        {   put_token_back();
76
 
            args = 2;
77
 
            AO4 = parse_expression(QUANTITY_CONTEXT);
78
 
            get_next_token();
79
 
        }
80
 
    }
81
 
    if (level == 2)
82
 
    {   get_next_token();
83
 
        if (!((token_type == SEP_TT) && (token_value == GREATER_SEP)))
84
 
        {   put_token_back();
85
 
            ebf_error("'>>'", token_text);
86
 
        }
87
 
    }
88
 
 
89
 
    if (!glulx_mode) {
90
 
 
91
 
      AO = veneer_routine(R_Process_VR);
92
 
 
93
 
      switch(args)
94
 
      {   case 0:
95
 
            if (codegen_action) AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
96
 
            if (version_number>=5)
97
 
                assemblez_2(call_2n_zc, AO, AO2);
98
 
            else
99
 
            if (version_number==4)
100
 
                assemblez_2_to(call_vs_zc, AO, AO2, temp_var1);
101
 
            else
102
 
                assemblez_2_to(call_zc, AO, AO2, temp_var1);
103
 
            break;
104
 
          case 1:
105
 
            AO3 = code_generate(AO3, QUANTITY_CONTEXT, -1);
106
 
            if (codegen_action) AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
107
 
            if (version_number>=5)
108
 
                assemblez_3(call_vn_zc, AO, AO2, AO3);
109
 
            else
110
 
            if (version_number==4)
111
 
                assemblez_3_to(call_vs_zc, AO, AO2, AO3, temp_var1);
112
 
            else
113
 
                assemblez_3_to(call_zc, AO, AO2, AO3, temp_var1);
114
 
            break;
115
 
          case 2:
116
 
            AO4 = code_generate(AO4, QUANTITY_CONTEXT, -1);
117
 
            AO3 = code_generate(AO3, QUANTITY_CONTEXT, -1);
118
 
            if (codegen_action) AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
119
 
            if (version_number>=5)
120
 
                assemblez_4(call_vn_zc, AO, AO2, AO3, AO4);
121
 
            else
122
 
            if (version_number==4)
123
 
                assemblez_4_to(call_vs_zc, AO, AO2, AO3, AO4, temp_var1);
124
 
            else
125
 
                assemblez_4(call_zc, AO, AO2, AO3, AO4);
126
 
            break;
127
 
      }
128
 
 
129
 
      if (level == 2) assemblez_0(rtrue_zc);
130
 
 
131
 
    }
132
 
    else {
133
 
 
134
 
      AO = veneer_routine(R_Process_VR);
135
 
 
136
 
      switch (args) {
137
 
 
138
 
      case 0:
139
 
        if (codegen_action) 
140
 
          AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
141
 
        assembleg_call_1(AO, AO2, zero_operand);
142
 
        break;
143
 
 
144
 
      case 1:
145
 
        AO3 = code_generate(AO3, QUANTITY_CONTEXT, -1);
146
 
        if (codegen_action)
147
 
          AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
148
 
        assembleg_call_2(AO, AO2, AO3, zero_operand);
149
 
        break;
150
 
 
151
 
      case 2:
152
 
        AO4 = code_generate(AO4, QUANTITY_CONTEXT, -1);
153
 
        AO3 = code_generate(AO3, QUANTITY_CONTEXT, -1);
154
 
        if (codegen_action) 
155
 
          AO2 = code_generate(AO2, QUANTITY_CONTEXT, -1);
156
 
        assembleg_call_3(AO, AO2, AO3, AO4, zero_operand);
157
 
        break;
158
 
      }
159
 
 
160
 
      if (level == 2) 
161
 
        assembleg_1(return_gc, one_operand);
162
 
 
163
 
    }
164
 
}
165
 
 
166
 
extern int parse_label(void)
167
 
{
168
 
    get_next_token();
169
 
 
170
 
    if ((token_type == SYMBOL_TT) &&
171
 
        (stypes[token_value] == LABEL_T))
172
 
    {   sflags[token_value] |= USED_SFLAG;
173
 
        return(svals[token_value]);
174
 
    }
175
 
 
176
 
    if ((token_type == SYMBOL_TT) && (sflags[token_value] & UNKNOWN_SFLAG))
177
 
    {   assign_symbol(token_value, next_label, LABEL_T);
178
 
        define_symbol_label(token_value);
179
 
        next_label++;
180
 
        sflags[token_value] |= CHANGE_SFLAG + USED_SFLAG;
181
 
        return(svals[token_value]);
182
 
    }
183
 
 
184
 
    ebf_error("label name", token_text);
185
 
    return 0;
186
 
}
187
 
 
188
 
static void parse_print_z(int finally_return)
189
 
{   int count = 0; assembly_operand AO;
190
 
 
191
 
    /*  print <printlist> -------------------------------------------------- */
192
 
    /*  print_ret <printlist> ---------------------------------------------- */
193
 
    /*  <literal-string> --------------------------------------------------- */
194
 
    /*                                                                       */
195
 
    /*  <printlist> is a comma-separated list of items:                      */
196
 
    /*                                                                       */
197
 
    /*       <literal-string>                                                */
198
 
    /*       <other-expression>                                              */
199
 
    /*       (char) <expression>                                             */
200
 
    /*       (address) <expression>                                          */
201
 
    /*       (string) <expression>                                           */
202
 
    /*       (a) <expression>                                                */
203
 
    /*       (the) <expression>                                              */
204
 
    /*       (The) <expression>                                              */
205
 
    /*       (name) <expression>                                             */
206
 
    /*       (number) <expression>                                           */
207
 
    /*       (property) <expression>                                         */
208
 
    /*       (<routine>) <expression>                                        */
209
 
    /*       (object) <expression>     (for use in low-level code only)      */
210
 
    /* --------------------------------------------------------------------- */
211
 
 
212
 
    do
213
 
    {   AI.text = token_text;
214
 
        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
215
 
        switch(token_type)
216
 
        {   case DQ_TT:
217
 
              if (strlen(token_text) > 32)
218
 
              {   AO.marker = STRING_MV;
219
 
                  AO.type   = LONG_CONSTANT_OT;
220
 
                  AO.value  = compile_string(token_text, FALSE, FALSE);
221
 
                  assemblez_1(print_paddr_zc, AO);
222
 
                  if (finally_return)
223
 
                  {   get_next_token();
224
 
                      if ((token_type == SEP_TT)
225
 
                          && (token_value == SEMICOLON_SEP))
226
 
                      {   assemblez_0(new_line_zc);
227
 
                          assemblez_0(rtrue_zc);
228
 
                          return;
229
 
                      }
230
 
                      put_token_back();
231
 
                  }
232
 
                  break;
233
 
              }
234
 
              if (finally_return)
235
 
              {   get_next_token();
236
 
                  if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
237
 
                  {   assemblez_0(print_ret_zc); return;
238
 
                  }
239
 
                  put_token_back();
240
 
              }
241
 
              assemblez_0(print_zc);
242
 
              break;
243
 
 
244
 
            case SEP_TT:
245
 
              if (token_value == OPENB_SEP)
246
 
              {   misc_keywords.enabled = TRUE;
247
 
                  get_next_token();
248
 
                  get_next_token();
249
 
                  if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
250
 
                  {   assembly_operand AO1;
251
 
 
252
 
                      put_token_back(); put_token_back();
253
 
                      local_variables.enabled = FALSE;
254
 
                      get_next_token();
255
 
                      misc_keywords.enabled = FALSE;
256
 
                      local_variables.enabled = TRUE;
257
 
 
258
 
                      if ((token_type == STATEMENT_TT)
259
 
                          &&(token_value == STRING_CODE))
260
 
                      {   token_type = MISC_KEYWORD_TT;
261
 
                          token_value = STRING_MK;
262
 
                      }
263
 
 
264
 
                      switch(token_type)
265
 
                      {
266
 
                        case MISC_KEYWORD_TT:
267
 
                          switch(token_value)
268
 
                          {   case CHAR_MK:
269
 
                                  if (runtime_error_checking_switch)
270
 
                                  {   AO = veneer_routine(RT__ChPrintC_VR);
271
 
                                      goto PrintByRoutine;
272
 
                                  }
273
 
                                  get_next_token();
274
 
                                  AO1 = code_generate(
275
 
                                      parse_expression(QUANTITY_CONTEXT),
276
 
                                      QUANTITY_CONTEXT, -1);
277
 
                                  assemblez_1(print_char_zc, AO1);
278
 
                                  goto PrintTermDone;
279
 
                              case ADDRESS_MK:
280
 
                                  if (runtime_error_checking_switch)
281
 
                                  {   AO = veneer_routine(RT__ChPrintA_VR);
282
 
                                      goto PrintByRoutine;
283
 
                                  }
284
 
                                  get_next_token();
285
 
                                  AO1 = code_generate(
286
 
                                      parse_expression(QUANTITY_CONTEXT),
287
 
                                      QUANTITY_CONTEXT, -1);
288
 
                                  assemblez_1(print_addr_zc, AO1);
289
 
                                  goto PrintTermDone;
290
 
                              case STRING_MK:
291
 
                                  if (runtime_error_checking_switch)
292
 
                                  {   AO = veneer_routine(RT__ChPrintS_VR);
293
 
                                      goto PrintByRoutine;
294
 
                                  }
295
 
                                  get_next_token();
296
 
                                  AO1 = code_generate(
297
 
                                      parse_expression(QUANTITY_CONTEXT),
298
 
                                      QUANTITY_CONTEXT, -1);
299
 
                                  assemblez_1(print_paddr_zc, AO1);
300
 
                                  goto PrintTermDone;
301
 
                              case OBJECT_MK:
302
 
                                  if (runtime_error_checking_switch)
303
 
                                  {   AO = veneer_routine(RT__ChPrintO_VR);
304
 
                                      goto PrintByRoutine;
305
 
                                  }
306
 
                                  get_next_token();
307
 
                                  AO1 = code_generate(
308
 
                                      parse_expression(QUANTITY_CONTEXT),
309
 
                                      QUANTITY_CONTEXT, -1);
310
 
                                  assemblez_1(print_obj_zc, AO1);
311
 
                                  goto PrintTermDone;
312
 
                              case THE_MK:
313
 
                                  AO = veneer_routine(DefArt_VR);
314
 
                                  goto PrintByRoutine;
315
 
                              case AN_MK:
316
 
                              case A_MK:
317
 
                                  AO = veneer_routine(InDefArt_VR);
318
 
                                  goto PrintByRoutine;
319
 
                              case CAP_THE_MK:
320
 
                                  AO = veneer_routine(CDefArt_VR);
321
 
                                  goto PrintByRoutine;
322
 
                              case CAP_A_MK:
323
 
                                  AO = veneer_routine(CInDefArt_VR);
324
 
                                  goto PrintByRoutine;
325
 
                              case NAME_MK:
326
 
                                  AO = veneer_routine(PrintShortName_VR);
327
 
                                  goto PrintByRoutine;
328
 
                              case NUMBER_MK:
329
 
                                  AO = veneer_routine(EnglishNumber_VR);
330
 
                                  goto PrintByRoutine;
331
 
                              case PROPERTY_MK:
332
 
                                  AO = veneer_routine(Print__Pname_VR);
333
 
                                  goto PrintByRoutine;
334
 
                              default:
335
 
               error_named("A reserved word was used as a print specification:",
336
 
                                      token_text);
337
 
                          }
338
 
                          break;
339
 
 
340
 
                        case SYMBOL_TT:
341
 
                          if (sflags[token_value] & UNKNOWN_SFLAG)
342
 
                          {   AO.type = LONG_CONSTANT_OT;
343
 
                              AO.value = token_value;
344
 
                              AO.marker = SYMBOL_MV;
345
 
                          }
346
 
                          else
347
 
                          {   AO.type = LONG_CONSTANT_OT;
348
 
                              AO.value = svals[token_value];
349
 
                              AO.marker = IROUTINE_MV;
350
 
                              if (stypes[token_value] != ROUTINE_T)
351
 
                                ebf_error("printing routine name", token_text);
352
 
                          }
353
 
                          sflags[token_value] |= USED_SFLAG;
354
 
 
355
 
                          PrintByRoutine:
356
 
 
357
 
                          get_next_token();
358
 
                          if (version_number >= 5)
359
 
                            assemblez_2(call_2n_zc, AO,
360
 
                              code_generate(parse_expression(QUANTITY_CONTEXT),
361
 
                                QUANTITY_CONTEXT, -1));
362
 
                          else if (version_number == 4)
363
 
                            assemblez_2_to(call_vs_zc, AO,
364
 
                              code_generate(parse_expression(QUANTITY_CONTEXT),
365
 
                                QUANTITY_CONTEXT, -1), temp_var1);
366
 
                          else
367
 
                            assemblez_2_to(call_zc, AO,
368
 
                              code_generate(parse_expression(QUANTITY_CONTEXT),
369
 
                                QUANTITY_CONTEXT, -1), temp_var1);
370
 
                          goto PrintTermDone;
371
 
 
372
 
                        default: ebf_error("print specification", token_text);
373
 
                          get_next_token();
374
 
                          assemblez_1(print_num_zc,
375
 
                          code_generate(parse_expression(QUANTITY_CONTEXT),
376
 
                                QUANTITY_CONTEXT, -1));
377
 
                          goto PrintTermDone;
378
 
                      }
379
 
                  }
380
 
                  put_token_back(); put_token_back(); put_token_back();
381
 
                  misc_keywords.enabled = FALSE;
382
 
                  assemblez_1(print_num_zc,
383
 
                      code_generate(parse_expression(QUANTITY_CONTEXT),
384
 
                          QUANTITY_CONTEXT, -1));
385
 
                  break;
386
 
              }
387
 
 
388
 
            default:
389
 
              put_token_back(); misc_keywords.enabled = FALSE;
390
 
              assemblez_1(print_num_zc,
391
 
                  code_generate(parse_expression(QUANTITY_CONTEXT),
392
 
                      QUANTITY_CONTEXT, -1));
393
 
              break;
394
 
        }
395
 
 
396
 
        PrintTermDone: misc_keywords.enabled = FALSE;
397
 
 
398
 
        count++;
399
 
        get_next_token();
400
 
        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
401
 
        if ((token_type != SEP_TT) || (token_value != COMMA_SEP))
402
 
        {   ebf_error("comma", token_text);
403
 
            panic_mode_error_recovery(); return;
404
 
        }
405
 
        else get_next_token();
406
 
    } while(TRUE);
407
 
 
408
 
    if (count == 0) ebf_error("something to print", token_text);
409
 
    if (finally_return)
410
 
    {   assemblez_0(new_line_zc);
411
 
        assemblez_0(rtrue_zc);
412
 
    }
413
 
}
414
 
 
415
 
static void parse_print_g(int finally_return)
416
 
{   int count = 0; assembly_operand AO, AO2;
417
 
 
418
 
    /*  print <printlist> -------------------------------------------------- */
419
 
    /*  print_ret <printlist> ---------------------------------------------- */
420
 
    /*  <literal-string> --------------------------------------------------- */
421
 
    /*                                                                       */
422
 
    /*  <printlist> is a comma-separated list of items:                      */
423
 
    /*                                                                       */
424
 
    /*       <literal-string>                                                */
425
 
    /*       <other-expression>                                              */
426
 
    /*       (char) <expression>                                             */
427
 
    /*       (address) <expression>                                          */
428
 
    /*       (string) <expression>                                           */
429
 
    /*       (a) <expression>                                                */
430
 
    /*       (A) <expression>                                                */
431
 
    /*       (the) <expression>                                              */
432
 
    /*       (The) <expression>                                              */
433
 
    /*       (name) <expression>                                             */
434
 
    /*       (number) <expression>                                           */
435
 
    /*       (property) <expression>                                         */
436
 
    /*       (<routine>) <expression>                                        */
437
 
    /*       (object) <expression>     (for use in low-level code only)      */
438
 
    /* --------------------------------------------------------------------- */
439
 
 
440
 
    do
441
 
    {   
442
 
        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
443
 
        switch(token_type)
444
 
        {   case DQ_TT:
445
 
              /* We can't compile a string into the instruction,
446
 
                 so this always goes into the string area. */
447
 
              {   AO.marker = STRING_MV;
448
 
                  AO.type   = CONSTANT_OT;
449
 
                  AO.value  = compile_string(token_text, FALSE, FALSE);
450
 
                  assembleg_1(streamstr_gc, AO);
451
 
                  if (finally_return)
452
 
                  {   get_next_token();
453
 
                      if ((token_type == SEP_TT)
454
 
                          && (token_value == SEMICOLON_SEP))
455
 
                      {   AO.type = BYTECONSTANT_OT; 
456
 
                          AO.value = 0x0A; AO.marker = 0;
457
 
                          assembleg_1(streamchar_gc, AO); 
458
 
                          AO.type = BYTECONSTANT_OT; 
459
 
                          AO.value = 1; AO.marker = 0;
460
 
                          assembleg_1(return_gc, AO); 
461
 
                          return;
462
 
                      }
463
 
                      put_token_back();
464
 
                  }
465
 
                  break;
466
 
              }
467
 
              break;
468
 
 
469
 
            case SEP_TT:
470
 
              if (token_value == OPENB_SEP)
471
 
              {   misc_keywords.enabled = TRUE;
472
 
                  get_next_token();
473
 
                  get_next_token();
474
 
                  if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
475
 
                  {   assembly_operand AO1;
476
 
 
477
 
                      put_token_back(); put_token_back();
478
 
                      local_variables.enabled = FALSE;
479
 
                      get_next_token();
480
 
                      misc_keywords.enabled = FALSE;
481
 
                      local_variables.enabled = TRUE;
482
 
 
483
 
                      if ((token_type == STATEMENT_TT)
484
 
                          &&(token_value == STRING_CODE))
485
 
                      {   token_type = MISC_KEYWORD_TT;
486
 
                          token_value = STRING_MK;
487
 
                      }
488
 
 
489
 
                      switch(token_type)
490
 
                      {
491
 
                        case MISC_KEYWORD_TT:
492
 
                          switch(token_value)
493
 
                          {   case CHAR_MK:
494
 
                                  if (runtime_error_checking_switch)
495
 
                                  {   AO = veneer_routine(RT__ChPrintC_VR);
496
 
                                      goto PrintByRoutine;
497
 
                                  }
498
 
                                  get_next_token();
499
 
                                  AO1 = code_generate(
500
 
                                      parse_expression(QUANTITY_CONTEXT),
501
 
                                      QUANTITY_CONTEXT, -1);
502
 
                                  assembleg_1(streamchar_gc, AO1);
503
 
                                  goto PrintTermDone;
504
 
                              case ADDRESS_MK:
505
 
                                  if (runtime_error_checking_switch)
506
 
                                      AO = veneer_routine(RT__ChPrintA_VR);
507
 
                                  else
508
 
                                      AO = veneer_routine(Print__Addr_VR);
509
 
                                  goto PrintByRoutine;
510
 
                              case STRING_MK:
511
 
                                  if (runtime_error_checking_switch)
512
 
                                  {   AO = veneer_routine(RT__ChPrintS_VR);
513
 
                                      goto PrintByRoutine;
514
 
                                  }
515
 
                                  get_next_token();
516
 
                                  AO1 = code_generate(
517
 
                                      parse_expression(QUANTITY_CONTEXT),
518
 
                                      QUANTITY_CONTEXT, -1);
519
 
                                  assembleg_1(streamstr_gc, AO1);
520
 
                                  goto PrintTermDone;
521
 
                              case OBJECT_MK:
522
 
                                  if (runtime_error_checking_switch)
523
 
                                  {   AO = veneer_routine(RT__ChPrintO_VR);
524
 
                                      goto PrintByRoutine;
525
 
                                  }
526
 
                                  get_next_token();
527
 
                                  AO1 = code_generate(
528
 
                                      parse_expression(QUANTITY_CONTEXT),
529
 
                                      QUANTITY_CONTEXT, -1);
530
 
                                  AO2.type = BYTECONSTANT_OT;
531
 
                                  AO2.value = 3;
532
 
                                  AO2.marker = 0;
533
 
                                  assembleg_3(aload_gc, AO1, AO2, 
534
 
                                    stack_pointer);
535
 
                                  assembleg_1(streamstr_gc, stack_pointer);
536
 
                                  goto PrintTermDone;
537
 
                              case THE_MK:
538
 
                                  AO = veneer_routine(DefArt_VR);
539
 
                                  goto PrintByRoutine;
540
 
                              case AN_MK:
541
 
                              case A_MK:
542
 
                                  AO = veneer_routine(InDefArt_VR);
543
 
                                  goto PrintByRoutine;
544
 
                              case CAP_THE_MK:
545
 
                                  AO = veneer_routine(CDefArt_VR);
546
 
                                  goto PrintByRoutine;
547
 
                              case CAP_A_MK:
548
 
                                  AO = veneer_routine(CInDefArt_VR);
549
 
                                  goto PrintByRoutine;
550
 
                              case NAME_MK:
551
 
                                  AO = veneer_routine(PrintShortName_VR);
552
 
                                  goto PrintByRoutine;
553
 
                              case NUMBER_MK:
554
 
                                  AO = veneer_routine(EnglishNumber_VR);
555
 
                                  goto PrintByRoutine;
556
 
                              case PROPERTY_MK:
557
 
                                  AO = veneer_routine(Print__Pname_VR);
558
 
                                  goto PrintByRoutine;
559
 
                              default:
560
 
               error_named("A reserved word was used as a print specification:",
561
 
                                      token_text);
562
 
                          }
563
 
                          break;
564
 
 
565
 
                        case SYMBOL_TT:
566
 
                          if (sflags[token_value] & UNKNOWN_SFLAG)
567
 
                          {   AO.type = CONSTANT_OT;
568
 
                              AO.value = token_value;
569
 
                              AO.marker = SYMBOL_MV;
570
 
                          }
571
 
                          else
572
 
                          {   AO.type = CONSTANT_OT;
573
 
                              AO.value = svals[token_value];
574
 
                              AO.marker = IROUTINE_MV;
575
 
                              if (stypes[token_value] != ROUTINE_T)
576
 
                                ebf_error("printing routine name", token_text);
577
 
                          }
578
 
                          sflags[token_value] |= USED_SFLAG;
579
 
 
580
 
                          PrintByRoutine:
581
 
 
582
 
                          get_next_token();
583
 
                          AO2.type = ZEROCONSTANT_OT;
584
 
                          AO2.value = 0; AO2.marker = 0;
585
 
                          assembleg_call_1(AO,
586
 
                            code_generate(parse_expression(QUANTITY_CONTEXT),
587
 
                              QUANTITY_CONTEXT, -1),
588
 
                            AO2);
589
 
                          goto PrintTermDone;
590
 
 
591
 
                        default: ebf_error("print specification", token_text);
592
 
                          get_next_token();
593
 
                          assembleg_1(streamnum_gc,
594
 
                          code_generate(parse_expression(QUANTITY_CONTEXT),
595
 
                                QUANTITY_CONTEXT, -1));
596
 
                          goto PrintTermDone;
597
 
                      }
598
 
                  }
599
 
                  put_token_back(); put_token_back(); put_token_back();
600
 
                  misc_keywords.enabled = FALSE;
601
 
                  assembleg_1(streamnum_gc,
602
 
                      code_generate(parse_expression(QUANTITY_CONTEXT),
603
 
                          QUANTITY_CONTEXT, -1));
604
 
                  break;
605
 
              }
606
 
 
607
 
            default:
608
 
              put_token_back(); misc_keywords.enabled = FALSE;
609
 
              assembleg_1(streamnum_gc,
610
 
                  code_generate(parse_expression(QUANTITY_CONTEXT),
611
 
                      QUANTITY_CONTEXT, -1));
612
 
              break;
613
 
        }
614
 
 
615
 
        PrintTermDone: misc_keywords.enabled = FALSE;
616
 
 
617
 
        count++;
618
 
        get_next_token();
619
 
        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break;
620
 
        if ((token_type != SEP_TT) || (token_value != COMMA_SEP))
621
 
        {   ebf_error("comma", token_text);
622
 
            panic_mode_error_recovery(); return;
623
 
        }
624
 
        else get_next_token();
625
 
    } while(TRUE);
626
 
 
627
 
    if (count == 0) ebf_error("something to print", token_text);
628
 
    if (finally_return)
629
 
    {
630
 
        AO.type = BYTECONSTANT_OT; AO.value = 0x0A; AO.marker = 0;
631
 
        assembleg_1(streamchar_gc, AO); 
632
 
        AO.type = BYTECONSTANT_OT; AO.value = 1; AO.marker = 0;
633
 
        assembleg_1(return_gc, AO); 
634
 
    }
635
 
}
636
 
 
637
 
static void parse_statement_z(int break_label, int continue_label)
638
 
{   int ln, ln2, ln3, ln4, flag;
639
 
    assembly_operand AO, AO2, AO3, AO4;
640
 
    dbgl spare_dbgl1, spare_dbgl2;
641
 
 
642
 
    ASSERT_ZCODE();
643
 
 
644
 
    if ((token_type == SEP_TT) && (token_value == PROPERTY_SEP))
645
 
    {   /*  That is, a full stop, signifying a label  */
646
 
 
647
 
        get_next_token();
648
 
        if (token_type == SYMBOL_TT)
649
 
        {
650
 
            if (sflags[token_value] & UNKNOWN_SFLAG)
651
 
            {   assign_symbol(token_value, next_label, LABEL_T);
652
 
                sflags[token_value] |= USED_SFLAG;
653
 
                assemble_label_no(next_label);
654
 
                define_symbol_label(token_value);
655
 
                next_label++;
656
 
            }
657
 
            else
658
 
            {   if (stypes[token_value] != LABEL_T) goto LabelError;
659
 
                if (sflags[token_value] & CHANGE_SFLAG)
660
 
                {   sflags[token_value] &= (~(CHANGE_SFLAG));
661
 
                    assemble_label_no(svals[token_value]);
662
 
                    define_symbol_label(token_value);
663
 
                }
664
 
                else error_named("Duplicate definition of label:", token_text);
665
 
            }
666
 
 
667
 
            get_next_token();
668
 
            if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
669
 
            {   ebf_error("';'", token_text);
670
 
                put_token_back(); return;
671
 
            }
672
 
 
673
 
            /*  Interesting point of Inform grammar: a statement can only
674
 
                consist solely of a label when it is immediately followed
675
 
                by a "}".                                                    */
676
 
 
677
 
            get_next_token();
678
 
            if ((token_type == SEP_TT) && (token_value == CLOSE_BRACE_SEP))
679
 
            {   put_token_back(); return;
680
 
            }
681
 
            parse_statement(break_label, continue_label);
682
 
            return;
683
 
        }
684
 
        LabelError: ebf_error("label name", token_text);
685
 
    }
686
 
 
687
 
    if ((token_type == SEP_TT) && (token_value == HASH_SEP))
688
 
    {   parse_directive(TRUE);
689
 
        parse_statement(break_label, continue_label); return;
690
 
    }
691
 
 
692
 
    if ((token_type == SEP_TT) && (token_value == AT_SEP))
693
 
    {   parse_assembly(); return;
694
 
    }
695
 
 
696
 
    if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) return;
697
 
 
698
 
    if (token_type == DQ_TT)
699
 
    {   parse_print_z(TRUE); return;
700
 
    }
701
 
 
702
 
    if ((token_type == SEP_TT) && (token_value == LESS_SEP))
703
 
    {   parse_action(); goto StatementTerminator; }
704
 
 
705
 
    if (token_type == EOF_TT)
706
 
    {   ebf_error("statement", token_text); return; }
707
 
 
708
 
    if (token_type != STATEMENT_TT)
709
 
    {   put_token_back();
710
 
        AO = parse_expression(VOID_CONTEXT);
711
 
        code_generate(AO, VOID_CONTEXT, -1);
712
 
        if (vivc_flag) { panic_mode_error_recovery(); return; }
713
 
        goto StatementTerminator;
714
 
    }
715
 
 
716
 
    statements.enabled = FALSE;
717
 
 
718
 
    switch(token_value)
719
 
    {
720
 
    /*  -------------------------------------------------------------------- */
721
 
    /*  box <string-1> ... <string-n> -------------------------------------- */
722
 
    /*  -------------------------------------------------------------------- */
723
 
 
724
 
        case BOX_CODE:
725
 
             if (version_number == 3)
726
 
             warning("The 'box' statement has no effect in a version 3 game");
727
 
                 AO3.type = LONG_CONSTANT_OT;
728
 
                 AO3.value = begin_table_array();
729
 
                 AO3.marker = ARRAY_MV;
730
 
                 ln = 0; ln2 = 0;
731
 
                 do
732
 
                 {   get_next_token();
733
 
                     if ((token_type==SEP_TT)&&(token_value==SEMICOLON_SEP))
734
 
                         break;
735
 
                     if (token_type != DQ_TT)
736
 
                         ebf_error("text of box line in double-quotes",
737
 
                             token_text);
738
 
                     {   int i, j;
739
 
                         for (i=0, j=0; token_text[i] != 0; j++)
740
 
                             if (token_text[i] == '@')
741
 
                             {   if (token_text[i+1] == '@')
742
 
                                 {   i = i + 2;
743
 
                                     while (isdigit(token_text[i])) i++;
744
 
                                 }
745
 
                                 else
746
 
                                 {   i++;
747
 
                                     if (token_text[i] != 0) i++;
748
 
                                     if (token_text[i] != 0) i++;
749
 
                                 }
750
 
                             }
751
 
                             else i++;
752
 
                         if (j > ln2) ln2 = j;
753
 
                     }
754
 
                     put_token_back();
755
 
                     array_entry(ln++,parse_expression(CONSTANT_CONTEXT));
756
 
                 } while (TRUE);
757
 
                 finish_array(ln);
758
 
                 if (ln == 0)
759
 
                     error("No lines of text given for 'box' display");
760
 
 
761
 
                 if (version_number == 3) return;
762
 
 
763
 
                 AO2.type = SHORT_CONSTANT_OT; AO2.value = ln2; AO2.marker = 0;
764
 
                 AO4.type = VARIABLE_OT; AO4.value = 255; AO4.marker = 0;
765
 
                 assemblez_3_to(call_vs_zc, veneer_routine(Box__Routine_VR),
766
 
                     AO2, AO3, AO4);
767
 
                 return;
768
 
 
769
 
    /*  -------------------------------------------------------------------- */
770
 
    /*  break -------------------------------------------------------------- */
771
 
    /*  -------------------------------------------------------------------- */
772
 
 
773
 
        case BREAK_CODE:
774
 
                 if (break_label == -1)
775
 
                 error("'break' can only be used in a loop or 'switch' block");
776
 
                 else
777
 
                     assemblez_jump(break_label);
778
 
                 break;
779
 
 
780
 
    /*  -------------------------------------------------------------------- */
781
 
    /*  continue ----------------------------------------------------------- */
782
 
    /*  -------------------------------------------------------------------- */
783
 
 
784
 
        case CONTINUE_CODE:
785
 
                 if (continue_label == -1)
786
 
                 error("'continue' can only be used in a loop block");
787
 
                 else
788
 
                     assemblez_jump(continue_label);
789
 
                 break;
790
 
 
791
 
    /*  -------------------------------------------------------------------- */
792
 
    /*  do <codeblock> until (<condition>) --------------------------------- */
793
 
    /*  -------------------------------------------------------------------- */
794
 
 
795
 
        case DO_CODE:
796
 
                 assemble_label_no(ln = next_label++);
797
 
                 ln2 = next_label++; ln3 = next_label++;
798
 
                 parse_code_block(ln3, ln2, 0);
799
 
                 statements.enabled = TRUE;
800
 
                 get_next_token();
801
 
                 if ((token_type == STATEMENT_TT)
802
 
                     && (token_value == UNTIL_CODE))
803
 
                 {   assemble_label_no(ln2);
804
 
                     match_open_bracket();
805
 
                     AO = parse_expression(CONDITION_CONTEXT);
806
 
                     match_close_bracket();
807
 
                     code_generate(AO, CONDITION_CONTEXT, ln);
808
 
                 }
809
 
                 else error("'do' without matching 'until'");
810
 
 
811
 
                 assemble_label_no(ln3);
812
 
                 break;
813
 
 
814
 
    /*  -------------------------------------------------------------------- */
815
 
    /*  font on/off -------------------------------------------------------- */
816
 
    /*  -------------------------------------------------------------------- */
817
 
 
818
 
        case FONT_CODE:
819
 
                 misc_keywords.enabled = TRUE;
820
 
                 get_next_token();
821
 
                 misc_keywords.enabled = FALSE;
822
 
                 if ((token_type != MISC_KEYWORD_TT)
823
 
                     || ((token_value != ON_MK)
824
 
                         && (token_value != OFF_MK)))
825
 
                 {   ebf_error("'on' or 'off'", token_text);
826
 
                     panic_mode_error_recovery();
827
 
                     break;
828
 
                 }
829
 
 
830
 
                 AO.type = SHORT_CONSTANT_OT;
831
 
                 AO.value = 0;
832
 
                 AO.marker = 0;
833
 
                 AO2.type = SHORT_CONSTANT_OT;
834
 
                 AO2.value = 8;
835
 
                 AO2.marker = 0;
836
 
                 AO3.type = VARIABLE_OT;
837
 
                 AO3.value = 255;
838
 
                 AO3.marker = 0;
839
 
                 assemblez_2_to(loadw_zc, AO, AO2, AO3);
840
 
 
841
 
                 if (token_value == ON_MK)
842
 
                 {   AO4.type = LONG_CONSTANT_OT;
843
 
                     AO4.value = 0xfffd;
844
 
                     AO4.marker = 0;
845
 
                     assemblez_2_to(and_zc, AO4, AO3, AO3);
846
 
                 }
847
 
                 else
848
 
                 {   AO4.type = SHORT_CONSTANT_OT;
849
 
                     AO4.value = 2;
850
 
                     AO4.marker = 0;
851
 
                     assemblez_2_to(or_zc, AO4, AO3, AO3);
852
 
                 }
853
 
 
854
 
                 assemblez_3(storew_zc, AO, AO2, AO3);
855
 
                 break;
856
 
 
857
 
    /*  -------------------------------------------------------------------- */
858
 
    /*  for (<initialisation> : <continue-condition> : <updating>) --------- */
859
 
    /*  -------------------------------------------------------------------- */
860
 
 
861
 
        /*  Note that it's legal for any or all of the three sections of a
862
 
            'for' specification to be empty.  This 'for' implementation
863
 
            often wastes 3 bytes with a redundant branch rather than keep
864
 
            expression parse trees for long periods (as previous versions
865
 
            of Inform did, somewhat crudely by simply storing the textual
866
 
            form of a 'for' loop).  It is adequate for now.                  */
867
 
 
868
 
        case FOR_CODE:
869
 
                 match_open_bracket();
870
 
                 get_next_token();
871
 
 
872
 
                 /*  Initialisation code  */
873
 
 
874
 
                 if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
875
 
                 {   put_token_back();
876
 
                     if (!((token_type==SEP_TT)&&(token_value==SUPERCLASS_SEP)))
877
 
                     {   sequence_point_follows = TRUE;
878
 
                         debug_line_ref = token_line_ref;
879
 
                         code_generate(parse_expression(FORINIT_CONTEXT),
880
 
                             VOID_CONTEXT, -1);
881
 
                     }
882
 
                     get_next_token();
883
 
                     if ((token_type==SEP_TT)&&(token_value == SUPERCLASS_SEP))
884
 
                     {   get_next_token();
885
 
                         if ((token_type==SEP_TT)&&(token_value == CLOSEB_SEP))
886
 
                         {   assemble_label_no(ln = next_label++);
887
 
                             ln2 = next_label++;
888
 
                             parse_code_block(ln2, ln, 0);
889
 
                             sequence_point_follows = FALSE;
890
 
                             if (!execution_never_reaches_here)
891
 
                                 assemblez_jump(ln);
892
 
                             assemble_label_no(ln2);
893
 
                             return;
894
 
                         }
895
 
                         AO.type = OMITTED_OT;
896
 
                         goto ParseUpdate;
897
 
                     }
898
 
                     put_token_back();
899
 
                     if (!match_colon()) break;
900
 
                 }
901
 
 
902
 
                 get_next_token();
903
 
                 AO.type = OMITTED_OT;
904
 
                 if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
905
 
                 {   put_token_back();
906
 
                     spare_dbgl1 = token_line_ref;
907
 
                     AO = parse_expression(CONDITION_CONTEXT);
908
 
                     if (!match_colon()) break;
909
 
                 }
910
 
                 get_next_token();
911
 
 
912
 
                 ParseUpdate:
913
 
                 AO2.type = OMITTED_OT; flag = 0;
914
 
                 if (!((token_type==SEP_TT)&&(token_value==CLOSEB_SEP)))
915
 
                 {   put_token_back();
916
 
                     spare_dbgl2 = token_line_ref;
917
 
                     AO2 = parse_expression(VOID_CONTEXT);
918
 
                     match_close_bracket();
919
 
                     flag = test_for_incdec(AO2);
920
 
                 }
921
 
 
922
 
                 ln = next_label++;
923
 
                 ln2 = next_label++;
924
 
                 ln3 = next_label++;
925
 
 
926
 
                 if ((AO2.type == OMITTED_OT) || (flag != 0))
927
 
                 {
928
 
                     assemble_label_no(ln);
929
 
                     if (flag==0) assemble_label_no(ln2);
930
 
 
931
 
                     /*  The "finished yet?" condition  */
932
 
 
933
 
                     if (AO.type != OMITTED_OT)
934
 
                     {   sequence_point_follows = TRUE;
935
 
                         debug_line_ref = spare_dbgl1;
936
 
                         code_generate(AO, CONDITION_CONTEXT, ln3);
937
 
                     }
938
 
 
939
 
                 }
940
 
                 else
941
 
                 {
942
 
                     /*  This is the jump which could be avoided with the aid
943
 
                         of long-term expression storage  */
944
 
 
945
 
                     sequence_point_follows = FALSE;
946
 
                     assemblez_jump(ln2);
947
 
 
948
 
                     /*  The "update" part  */
949
 
 
950
 
                     assemble_label_no(ln);
951
 
                     sequence_point_follows = TRUE;
952
 
                     debug_line_ref = spare_dbgl2;
953
 
                     code_generate(AO2, VOID_CONTEXT, -1);
954
 
 
955
 
                     assemble_label_no(ln2);
956
 
 
957
 
                     /*  The "finished yet?" condition  */
958
 
 
959
 
                     if (AO.type != OMITTED_OT)
960
 
                     {   sequence_point_follows = TRUE;
961
 
                         debug_line_ref = spare_dbgl1;
962
 
                         code_generate(AO, CONDITION_CONTEXT, ln3);
963
 
                     }
964
 
                 }
965
 
 
966
 
                 if (flag != 0)
967
 
                 {
968
 
                     /*  In this optimised case, update code is at the end
969
 
                         of the loop block, so "continue" goes there  */
970
 
 
971
 
                     parse_code_block(ln3, ln2, 0);
972
 
                     assemble_label_no(ln2);
973
 
 
974
 
                     sequence_point_follows = TRUE;
975
 
                     debug_line_ref = spare_dbgl2;
976
 
                     if (flag > 0)
977
 
                     {   AO3.type = SHORT_CONSTANT_OT;
978
 
                         AO3.value = flag;
979
 
                         if (module_switch
980
 
                             && (flag>=MAX_LOCAL_VARIABLES) && (flag<LOWEST_SYSTEM_VAR_NUMBER))
981
 
                             AO3.marker = VARIABLE_MV;
982
 
                         else AO3.marker = 0;
983
 
                         assemblez_1(inc_zc, AO3);
984
 
                     }
985
 
                     else
986
 
                     {   AO3.type = SHORT_CONSTANT_OT;
987
 
                         AO3.value = -flag;
988
 
                         if ((module_switch) && (flag>=MAX_LOCAL_VARIABLES)
989
 
                             && (flag<LOWEST_SYSTEM_VAR_NUMBER))
990
 
                             AO3.marker = VARIABLE_MV;
991
 
                         else AO3.marker = 0;
992
 
                         assemblez_1(dec_zc, AO3);
993
 
                     }
994
 
                     assemblez_jump(ln);
995
 
                 }
996
 
                 else
997
 
                 {
998
 
                     /*  In the unoptimised case, update code is at the
999
 
                         start of the loop block, so "continue" goes there  */
1000
 
 
1001
 
                     parse_code_block(ln3, ln, 0);
1002
 
                     if (!execution_never_reaches_here)
1003
 
                     {   sequence_point_follows = FALSE;
1004
 
                         assemblez_jump(ln);
1005
 
                     }
1006
 
                 }
1007
 
 
1008
 
                 assemble_label_no(ln3);
1009
 
                 return;
1010
 
 
1011
 
    /*  -------------------------------------------------------------------- */
1012
 
    /*  give <expression> [~]attr [, [~]attr [, ...]] ---------------------- */
1013
 
    /*  -------------------------------------------------------------------- */
1014
 
 
1015
 
        case GIVE_CODE:
1016
 
                 AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1017
 
                          QUANTITY_CONTEXT, -1);
1018
 
                 if ((AO.type == VARIABLE_OT) && (AO.value == 0))
1019
 
                 {   AO.value = 252;
1020
 
                     AO.marker = 0;
1021
 
                     AO.type = SHORT_CONSTANT_OT;
1022
 
                     if (version_number != 6) assemblez_1(pull_zc, AO);
1023
 
                     else assemblez_0_to(pull_zc, AO);
1024
 
                     AO.type = VARIABLE_OT;
1025
 
                 }
1026
 
 
1027
 
                 do
1028
 
                 {   get_next_token();
1029
 
                     if ((token_type == SEP_TT)&&(token_value == SEMICOLON_SEP))
1030
 
                         return;
1031
 
                     if ((token_type == SEP_TT)&&(token_value == ARTNOT_SEP))
1032
 
                         ln = clear_attr_zc;
1033
 
                     else
1034
 
                     {   if ((token_type == SYMBOL_TT)
1035
 
                             && (stypes[token_value] != ATTRIBUTE_T))
1036
 
                           warning_named("This is not a declared Attribute:",
1037
 
                             token_text);
1038
 
                         ln = set_attr_zc;
1039
 
                         put_token_back();
1040
 
                     }
1041
 
                     AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1042
 
                               QUANTITY_CONTEXT, -1);
1043
 
                     if (runtime_error_checking_switch)
1044
 
                     {   /* ln2 = next_label++;
1045
 
                         check_nonzero_at_runtime(AO, ln2, GIVE_RTE);
1046
 
                         assemblez_2(ln, AO, AO2);
1047
 
                         assemble_label_no(ln2); */
1048
 
                         ln2 = (ln==set_attr_zc)?RT__ChG_VR:RT__ChGt_VR;
1049
 
                         if (version_number >= 5)
1050
 
                             assemblez_3(call_vn_zc, veneer_routine(ln2),
1051
 
                             AO, AO2);
1052
 
                         else
1053
 
                         {   
1054
 
                             assemblez_3_to(call_zc, veneer_routine(ln2),
1055
 
                                 AO, AO2, temp_var1);
1056
 
                         }
1057
 
                     }
1058
 
                     else
1059
 
                         assemblez_2(ln, AO, AO2);
1060
 
                 } while(TRUE);
1061
 
 
1062
 
    /*  -------------------------------------------------------------------- */
1063
 
    /*  if (<condition>) <codeblock> [else <codeblock>] -------------------- */
1064
 
    /*  -------------------------------------------------------------------- */
1065
 
 
1066
 
        case IF_CODE:
1067
 
                 flag = FALSE;
1068
 
 
1069
 
                 match_open_bracket();
1070
 
                 AO = parse_expression(CONDITION_CONTEXT);
1071
 
                 match_close_bracket();
1072
 
 
1073
 
                 statements.enabled = TRUE;
1074
 
                 get_next_token();
1075
 
                 if ((token_type == STATEMENT_TT)&&(token_value == RTRUE_CODE))
1076
 
                     ln = -4;
1077
 
                 else
1078
 
                 if ((token_type == STATEMENT_TT)&&(token_value == RFALSE_CODE))
1079
 
                     ln = -3;
1080
 
                 else
1081
 
                 {   put_token_back();
1082
 
                     ln = next_label++;
1083
 
                 }
1084
 
 
1085
 
                 code_generate(AO, CONDITION_CONTEXT, ln);
1086
 
 
1087
 
                 if (ln >= 0) parse_code_block(break_label, continue_label, 0);
1088
 
                 else
1089
 
                 {   get_next_token();
1090
 
                     if ((token_type != SEP_TT)
1091
 
                         || (token_value != SEMICOLON_SEP))
1092
 
                     {   ebf_error("';'", token_text);
1093
 
                         put_token_back();
1094
 
                     }
1095
 
                 }
1096
 
 
1097
 
                 statements.enabled = TRUE;
1098
 
                 get_next_token();
1099
 
                 if ((token_type == STATEMENT_TT) && (token_value == ELSE_CODE))
1100
 
                 {   flag = TRUE;
1101
 
                     if (ln >= 0)
1102
 
                     {   ln2 = next_label++;
1103
 
                         if (!execution_never_reaches_here)
1104
 
                         {   sequence_point_follows = FALSE;
1105
 
                             assemblez_jump(ln2);
1106
 
                         }
1107
 
                     }
1108
 
                 }
1109
 
                 else put_token_back();
1110
 
 
1111
 
                 if (ln >= 0) assemble_label_no(ln);
1112
 
 
1113
 
                 if (flag)
1114
 
                 {   parse_code_block(break_label, continue_label, 0);
1115
 
                     if (ln >= 0) assemble_label_no(ln2);
1116
 
                 }
1117
 
 
1118
 
                 return;
1119
 
 
1120
 
    /*  -------------------------------------------------------------------- */
1121
 
    /*  inversion ---------------------------------------------------------- */
1122
 
    /*  -------------------------------------------------------------------- */
1123
 
 
1124
 
        case INVERSION_CODE:
1125
 
                 AO.marker = 0;
1126
 
                 AO.type   = SHORT_CONSTANT_OT;
1127
 
                 AO.value  = 0;
1128
 
 
1129
 
                 AO2.marker = 0;
1130
 
                 AO2.type   = SHORT_CONSTANT_OT;
1131
 
 
1132
 
                 AO2.value  = 60;
1133
 
                 assemblez_2_to(loadb_zc, AO, AO2, temp_var1);
1134
 
                 assemblez_1(print_char_zc, temp_var1);
1135
 
                 AO2.value  = 61;
1136
 
                 assemblez_2_to(loadb_zc, AO, AO2, temp_var1);
1137
 
                 assemblez_1(print_char_zc, temp_var1);
1138
 
                 AO2.value  = 62;
1139
 
                 assemblez_2_to(loadb_zc, AO, AO2, temp_var1);
1140
 
                 assemblez_1(print_char_zc, temp_var1);
1141
 
                 AO2.value  = 63;
1142
 
                 assemblez_2_to(loadb_zc, AO, AO2, temp_var1);
1143
 
                 assemblez_1(print_char_zc, temp_var1);
1144
 
                 break;
1145
 
 
1146
 
    /*  -------------------------------------------------------------------- */
1147
 
    /*  jump <label> ------------------------------------------------------- */
1148
 
    /*  -------------------------------------------------------------------- */
1149
 
 
1150
 
        case JUMP_CODE:
1151
 
                 assemblez_jump(parse_label());
1152
 
                 break;
1153
 
 
1154
 
    /*  -------------------------------------------------------------------- */
1155
 
    /*  move <expression> to <expression> ---------------------------------- */
1156
 
    /*  -------------------------------------------------------------------- */
1157
 
 
1158
 
        case MOVE_CODE:
1159
 
                 misc_keywords.enabled = TRUE;
1160
 
                 AO = parse_expression(QUANTITY_CONTEXT);
1161
 
 
1162
 
                 get_next_token();
1163
 
                 misc_keywords.enabled = FALSE;
1164
 
                 if ((token_type != MISC_KEYWORD_TT)
1165
 
                     || (token_value != TO_MK))
1166
 
                 {   ebf_error("'to'", token_text);
1167
 
                     panic_mode_error_recovery();
1168
 
                     return;
1169
 
                 }
1170
 
 
1171
 
                 AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1172
 
                     QUANTITY_CONTEXT, -1);
1173
 
                 AO = code_generate(AO, QUANTITY_CONTEXT, -1);
1174
 
                 if ((runtime_error_checking_switch) && (veneer_mode == FALSE))
1175
 
                 {   if (version_number >= 5)
1176
 
                         assemblez_3(call_vn_zc, veneer_routine(RT__ChT_VR),
1177
 
                             AO, AO2);
1178
 
                     else
1179
 
                     {   assemblez_3_to(call_zc, veneer_routine(RT__ChT_VR),
1180
 
                             AO, AO2, temp_var1);
1181
 
                     }
1182
 
                 }
1183
 
                 else
1184
 
                     assemblez_2(insert_obj_zc, AO, AO2);
1185
 
                 break;
1186
 
 
1187
 
    /*  -------------------------------------------------------------------- */
1188
 
    /*  new_line ----------------------------------------------------------- */
1189
 
    /*  -------------------------------------------------------------------- */
1190
 
 
1191
 
        case NEW_LINE_CODE:  assemblez_0(new_line_zc); break;
1192
 
 
1193
 
    /*  -------------------------------------------------------------------- */
1194
 
    /*  objectloop (<initialisation>) <codeblock> -------------------------- */
1195
 
    /*  -------------------------------------------------------------------- */
1196
 
 
1197
 
        case OBJECTLOOP_CODE:
1198
 
 
1199
 
                 match_open_bracket();
1200
 
                 get_next_token();
1201
 
                 if (token_type == LOCAL_VARIABLE_TT)
1202
 
                     AO.value = token_value;
1203
 
                 else
1204
 
                 if ((token_type == SYMBOL_TT) &&
1205
 
                     (stypes[token_value] == GLOBAL_VARIABLE_T))
1206
 
                     AO.value = svals[token_value];
1207
 
                 else
1208
 
                 {   ebf_error("'objectloop' variable", token_text);
1209
 
                     panic_mode_error_recovery(); break;
1210
 
                 }
1211
 
                 AO.type = VARIABLE_OT;
1212
 
                 if ((module_switch) && (AO.value >= MAX_LOCAL_VARIABLES)
1213
 
                     && (AO.value < LOWEST_SYSTEM_VAR_NUMBER))
1214
 
                     AO.marker = VARIABLE_MV;
1215
 
                 else AO.marker = 0;
1216
 
                 misc_keywords.enabled = TRUE;
1217
 
                 get_next_token(); flag = TRUE;
1218
 
                 misc_keywords.enabled = FALSE;
1219
 
                 if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
1220
 
                     flag = FALSE;
1221
 
 
1222
 
                 ln = 0;
1223
 
                 if ((token_type == MISC_KEYWORD_TT)
1224
 
                     && (token_value == NEAR_MK)) ln = 1;
1225
 
                 if ((token_type == MISC_KEYWORD_TT)
1226
 
                     && (token_value == FROM_MK)) ln = 2;
1227
 
                 if ((token_type == CND_TT) && (token_value == IN_COND))
1228
 
                 {   get_next_token();
1229
 
                     get_next_token();
1230
 
                     if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
1231
 
                         ln = 3;
1232
 
                     put_token_back();
1233
 
                     put_token_back();
1234
 
                 }
1235
 
 
1236
 
                 if (ln > 0)
1237
 
                 {   /*  Old style (Inform 5) objectloops: note that we
1238
 
                         implement objectloop (a in b) in the old way since
1239
 
                         this runs through objects in a different order from
1240
 
                         the new way, and there may be existing Inform code
1241
 
                         relying on this.                                    */
1242
 
                     assembly_operand AO4;
1243
 
 
1244
 
                     sequence_point_follows = TRUE;
1245
 
                     AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1246
 
                         QUANTITY_CONTEXT, -1);
1247
 
                     match_close_bracket();
1248
 
                     if (ln == 1)
1249
 
                     {   AO3.type = VARIABLE_OT; AO3.value = 0; AO3.marker = 0;
1250
 
                         if (runtime_error_checking_switch)
1251
 
                                 AO2 = check_nonzero_at_runtime(AO2, -1,
1252
 
                                     OBJECTLOOP_RTE);
1253
 
                         assemblez_1_to(get_parent_zc, AO2, AO3);
1254
 
                         assemblez_objcode(get_child_zc, AO3, AO3, -2, TRUE);
1255
 
                         AO2 = AO3;
1256
 
                     }
1257
 
                     if (ln == 3)
1258
 
                     {   AO3.type = VARIABLE_OT; AO3.value = 0; AO3.marker = 0;
1259
 
                         if (runtime_error_checking_switch)
1260
 
                         {   AO4 = AO2;
1261
 
                             AO2 = check_nonzero_at_runtime(AO2, -1,
1262
 
                                 CHILD_RTE);
1263
 
                         }
1264
 
                         assemblez_objcode(get_child_zc, AO2, AO3, -2, TRUE);
1265
 
                         AO2 = AO3;
1266
 
                     }
1267
 
                     assemblez_store(AO, AO2);
1268
 
                     assemblez_1_branch(jz_zc, AO, ln2 = next_label++, TRUE);
1269
 
                     assemble_label_no(ln4 = next_label++);
1270
 
                     parse_code_block(ln2, ln3 = next_label++, 0);
1271
 
                     sequence_point_follows = FALSE;
1272
 
                     assemble_label_no(ln3);
1273
 
                     if (runtime_error_checking_switch)
1274
 
                     {   AO2 = check_nonzero_at_runtime(AO, ln2,
1275
 
                              OBJECTLOOP2_RTE);
1276
 
                         if ((ln == 3)
1277
 
                             && ((AO4.type != VARIABLE_OT)||(AO4.value != 0))
1278
 
                             && ((AO4.type != VARIABLE_OT)
1279
 
                                 ||(AO4.value != AO.value)))
1280
 
                         {   assembly_operand en_ao;
1281
 
                             en_ao.value = OBJECTLOOP_BROKEN_RTE;
1282
 
                             en_ao.marker = 0;
1283
 
                             en_ao.type = SHORT_CONSTANT_OT;
1284
 
                             assemblez_2_branch(jin_zc, AO, AO4,
1285
 
                                 next_label, TRUE);
1286
 
                             assemblez_3(call_vn_zc, veneer_routine(RT__Err_VR),
1287
 
                                 en_ao, AO);
1288
 
                             assemblez_jump(ln2);
1289
 
                             assemble_label_no(next_label++);
1290
 
                         }
1291
 
                     }
1292
 
                     else AO2 = AO;
1293
 
                     assemblez_objcode(get_sibling_zc, AO2, AO, ln4, TRUE);
1294
 
                     assemble_label_no(ln2);
1295
 
                     return;
1296
 
                 }
1297
 
 
1298
 
                 sequence_point_follows = TRUE;
1299
 
                 AO2.type = SHORT_CONSTANT_OT; AO2.value = 1; AO2.marker = 0;
1300
 
                 assemblez_store(AO, AO2);
1301
 
 
1302
 
                 assemble_label_no(ln = next_label++);
1303
 
                 ln2 = next_label++;
1304
 
                 ln3 = next_label++;
1305
 
                 if (flag)
1306
 
                 {   put_token_back();
1307
 
                     put_token_back();
1308
 
                     sequence_point_follows = TRUE;
1309
 
                     code_generate(parse_expression(CONDITION_CONTEXT),
1310
 
                         CONDITION_CONTEXT, ln3);
1311
 
                     match_close_bracket();
1312
 
                 }
1313
 
                 parse_code_block(ln2, ln3, 0);
1314
 
 
1315
 
                 sequence_point_follows = FALSE;
1316
 
                 assemble_label_no(ln3);
1317
 
                 assemblez_inc(AO);
1318
 
                 AO2.type = LONG_CONSTANT_OT; AO2.value = no_objects;
1319
 
                 AO2.marker = NO_OBJS_MV;
1320
 
                 assemblez_2_branch(jg_zc, AO, AO2, ln2, TRUE);
1321
 
                 assemblez_jump(ln);
1322
 
                 assemble_label_no(ln2);
1323
 
                 return;
1324
 
 
1325
 
    /*  -------------------------------------------------------------------- */
1326
 
    /*  (see routine above) ------------------------------------------------ */
1327
 
    /*  -------------------------------------------------------------------- */
1328
 
 
1329
 
        case PRINT_CODE:
1330
 
            get_next_token();
1331
 
            parse_print_z(FALSE); return;
1332
 
        case PRINT_RET_CODE:
1333
 
            get_next_token();
1334
 
            parse_print_z(TRUE); return;
1335
 
 
1336
 
    /*  -------------------------------------------------------------------- */
1337
 
    /*  quit --------------------------------------------------------------- */
1338
 
    /*  -------------------------------------------------------------------- */
1339
 
 
1340
 
        case QUIT_CODE:      assemblez_0(quit_zc); break;
1341
 
 
1342
 
    /*  -------------------------------------------------------------------- */
1343
 
    /*  read <expression> <expression> [<Routine>] ------------------------- */
1344
 
    /*  -------------------------------------------------------------------- */
1345
 
 
1346
 
        case READ_CODE:
1347
 
                 AO.type = VARIABLE_OT; AO.value = 252; AO.marker = 0;
1348
 
                 assemblez_store(AO,
1349
 
                     code_generate(parse_expression(QUANTITY_CONTEXT),
1350
 
                                   QUANTITY_CONTEXT, -1));
1351
 
                 if (version_number > 3)
1352
 
                 {   AO3.type = SHORT_CONSTANT_OT; AO3.value = 1;AO3.marker = 0;
1353
 
                     AO4.type = SHORT_CONSTANT_OT; AO4.value = 0;AO4.marker = 0;
1354
 
                     assemblez_3(storeb_zc, AO, AO3, AO4);
1355
 
                 }
1356
 
                 AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1357
 
                           QUANTITY_CONTEXT, -1);
1358
 
 
1359
 
                 get_next_token();
1360
 
                 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
1361
 
                     put_token_back();
1362
 
                 else
1363
 
                 {   if (version_number == 3)
1364
 
                         error(
1365
 
"In Version 3 no status-line drawing routine can be given");
1366
 
                     else
1367
 
                     {   assembly_operand AO5;
1368
 
                         put_token_back();
1369
 
                         AO5 = parse_expression(CONSTANT_CONTEXT);
1370
 
 
1371
 
                         if (version_number >= 5)
1372
 
                             assemblez_1(call_1n_zc, AO5);
1373
 
                         else
1374
 
                             assemblez_1_to(call_zc, AO5, temp_var1);
1375
 
                     }
1376
 
                 }
1377
 
 
1378
 
                 if (version_number > 4)
1379
 
                 {   assemblez_2_to(aread_zc, AO, AO2, temp_var1);
1380
 
                 }
1381
 
                 else assemblez_2(sread_zc, AO, AO2);
1382
 
                 break;
1383
 
 
1384
 
    /*  -------------------------------------------------------------------- */
1385
 
    /*  remove <expression> ------------------------------------------------ */
1386
 
    /*  -------------------------------------------------------------------- */
1387
 
 
1388
 
        case REMOVE_CODE:
1389
 
                 AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1390
 
                     QUANTITY_CONTEXT, -1);
1391
 
                 if ((runtime_error_checking_switch) && (veneer_mode == FALSE))
1392
 
                 {   if (version_number >= 5)
1393
 
                         assemblez_2(call_2n_zc, veneer_routine(RT__ChR_VR),
1394
 
                             AO);
1395
 
                     else
1396
 
                     {   assemblez_2_to(call_zc, veneer_routine(RT__ChR_VR),
1397
 
                             AO, temp_var1);
1398
 
                     }
1399
 
                 }
1400
 
                 else
1401
 
                     assemblez_1(remove_obj_zc, AO);
1402
 
                 break;
1403
 
 
1404
 
    /*  -------------------------------------------------------------------- */
1405
 
    /*  restore <label> ---------------------------------------------------- */
1406
 
    /*  -------------------------------------------------------------------- */
1407
 
 
1408
 
        case RESTORE_CODE:
1409
 
                 if (version_number < 5)
1410
 
                     assemblez_0_branch(restore_zc, parse_label(), TRUE);
1411
 
                 else
1412
 
                 {   AO2.type = SHORT_CONSTANT_OT; AO2.value = 2;
1413
 
                     AO2.marker = 0;
1414
 
                     assemblez_0_to(restore_zc, temp_var1);
1415
 
                     assemblez_2_branch(je_zc, temp_var1, AO2, parse_label(), TRUE);
1416
 
                 }
1417
 
                 break;
1418
 
 
1419
 
    /*  -------------------------------------------------------------------- */
1420
 
    /*  return [<expression>] ---------------------------------------------- */
1421
 
    /*  -------------------------------------------------------------------- */
1422
 
 
1423
 
        case RETURN_CODE:
1424
 
                 get_next_token();
1425
 
                 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
1426
 
                 {   assemblez_0(rtrue_zc); return; }
1427
 
                 put_token_back();
1428
 
                 AO = code_generate(parse_expression(RETURN_Q_CONTEXT),
1429
 
                     QUANTITY_CONTEXT, -1);
1430
 
                 if ((AO.type == SHORT_CONSTANT_OT) && (AO.value == 0)
1431
 
                     && (AO.marker == 0))
1432
 
                 {   assemblez_0(rfalse_zc); break; }
1433
 
                 if ((AO.type == SHORT_CONSTANT_OT) && (AO.value == 1)
1434
 
                     && (AO.marker == 0))
1435
 
                 {   assemblez_0(rtrue_zc); break; }
1436
 
                 if ((AO.type == VARIABLE_OT) && (AO.value == 0))
1437
 
                 {   assemblez_0(ret_popped_zc); break; }
1438
 
                 assemblez_1(ret_zc, AO);
1439
 
                 break;
1440
 
 
1441
 
    /*  -------------------------------------------------------------------- */
1442
 
    /*  rfalse ------------------------------------------------------------- */
1443
 
    /*  -------------------------------------------------------------------- */
1444
 
 
1445
 
        case RFALSE_CODE:  assemblez_0(rfalse_zc); break;
1446
 
 
1447
 
    /*  -------------------------------------------------------------------- */
1448
 
    /*  rtrue -------------------------------------------------------------- */
1449
 
    /*  -------------------------------------------------------------------- */
1450
 
 
1451
 
        case RTRUE_CODE:   assemblez_0(rtrue_zc); break;
1452
 
 
1453
 
    /*  -------------------------------------------------------------------- */
1454
 
    /*  save <label> ------------------------------------------------------- */
1455
 
    /*  -------------------------------------------------------------------- */
1456
 
 
1457
 
        case SAVE_CODE:
1458
 
                 if (version_number < 5)
1459
 
                     assemblez_0_branch(save_zc, parse_label(), TRUE);
1460
 
                 else
1461
 
                 {   AO.type = VARIABLE_OT; AO.value = 255; AO.marker = 0;
1462
 
                     assemblez_0_to(save_zc, AO);
1463
 
                     assemblez_1_branch(jz_zc, AO, parse_label(), FALSE);
1464
 
                 }
1465
 
                 break;
1466
 
 
1467
 
    /*  -------------------------------------------------------------------- */
1468
 
    /*  spaces <expression> ------------------------------------------------ */
1469
 
    /*  -------------------------------------------------------------------- */
1470
 
 
1471
 
        case SPACES_CODE:
1472
 
                 AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1473
 
                     QUANTITY_CONTEXT, -1);
1474
 
                 AO2.type = VARIABLE_OT; AO2.value = 255; AO2.marker = 0;
1475
 
 
1476
 
                 assemblez_store(AO2, AO);
1477
 
 
1478
 
                 AO.type = SHORT_CONSTANT_OT; AO.value = 32; AO.marker = 0;
1479
 
                 AO3.type = SHORT_CONSTANT_OT; AO3.value = 1; AO3.marker = 0;
1480
 
 
1481
 
                 assemblez_2_branch(jl_zc, AO2, AO3, ln = next_label++, TRUE);
1482
 
                 assemble_label_no(ln2 = next_label++);
1483
 
                 assemblez_1(print_char_zc, AO);
1484
 
                 assemblez_dec(AO2);
1485
 
                 assemblez_1_branch(jz_zc, AO2, ln2, FALSE);
1486
 
                 assemble_label_no(ln);
1487
 
                 break;
1488
 
 
1489
 
    /*  -------------------------------------------------------------------- */
1490
 
    /*  string <expression> <literal-string> ------------------------------- */
1491
 
    /*  -------------------------------------------------------------------- */
1492
 
 
1493
 
        case STRING_CODE:
1494
 
                 AO.type = SHORT_CONSTANT_OT; AO.value = 0; AO.marker = 0;
1495
 
                 AO2.type = SHORT_CONSTANT_OT; AO2.value = 12; AO2.marker = 0;
1496
 
                 AO3.type = VARIABLE_OT; AO3.value = 252; AO3.marker = 0;
1497
 
                 assemblez_2_to(loadw_zc, AO, AO2, AO3);
1498
 
                 AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1499
 
                     QUANTITY_CONTEXT, -1);
1500
 
                 get_next_token();
1501
 
                 if (token_type == DQ_TT)
1502
 
                 {   AO4.value = compile_string(token_text, TRUE, TRUE);
1503
 
                     AO4.marker = 0;
1504
 
                     AO4.type = LONG_CONSTANT_OT;
1505
 
                 }
1506
 
                 else
1507
 
                 {   put_token_back();
1508
 
                     AO4 = parse_expression(CONSTANT_CONTEXT);
1509
 
                 }
1510
 
                 assemblez_3(storew_zc, AO3, AO2, AO4);
1511
 
                 break;
1512
 
 
1513
 
    /*  -------------------------------------------------------------------- */
1514
 
    /*  style roman/reverse/bold/underline/fixed --------------------------- */
1515
 
    /*  -------------------------------------------------------------------- */
1516
 
 
1517
 
        case STYLE_CODE:
1518
 
                 if (version_number==3)
1519
 
                 {   error(
1520
 
"The 'style' statement cannot be used for Version 3 games");
1521
 
                     panic_mode_error_recovery();
1522
 
                     break;
1523
 
                 }
1524
 
 
1525
 
                 misc_keywords.enabled = TRUE;
1526
 
                 get_next_token();
1527
 
                 misc_keywords.enabled = FALSE;
1528
 
                 if ((token_type != MISC_KEYWORD_TT)
1529
 
                     || ((token_value != ROMAN_MK)
1530
 
                         && (token_value != REVERSE_MK)
1531
 
                         && (token_value != BOLD_MK)
1532
 
                         && (token_value != UNDERLINE_MK)
1533
 
                         && (token_value != FIXED_MK)))
1534
 
                 {   ebf_error(
1535
 
"'roman', 'bold', 'underline', 'reverse' or 'fixed'",
1536
 
                         token_text);
1537
 
                     panic_mode_error_recovery();
1538
 
                     break;
1539
 
                 }
1540
 
 
1541
 
                 AO.type = SHORT_CONSTANT_OT; AO.marker = 0;
1542
 
                 switch(token_value)
1543
 
                 {   case ROMAN_MK: AO.value = 0; break;
1544
 
                     case REVERSE_MK: AO.value = 1; break;
1545
 
                     case BOLD_MK: AO.value = 2; break;
1546
 
                     case UNDERLINE_MK: AO.value = 4; break;
1547
 
                     case FIXED_MK: AO.value = 8; break;
1548
 
                 }
1549
 
                 assemblez_1(set_text_style_zc, AO); break;
1550
 
 
1551
 
    /*  -------------------------------------------------------------------- */
1552
 
    /*  switch (<expression>) <codeblock> ---------------------------------- */
1553
 
    /*  -------------------------------------------------------------------- */
1554
 
 
1555
 
        case SWITCH_CODE:
1556
 
                 match_open_bracket();
1557
 
                 AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1558
 
                     QUANTITY_CONTEXT, -1);
1559
 
                 match_close_bracket();
1560
 
 
1561
 
                 AO2.type = VARIABLE_OT; AO2.value = 255; AO2.marker =  0;
1562
 
                 assemblez_store(AO2, AO);
1563
 
 
1564
 
                 parse_code_block(ln = next_label++, continue_label, 1);
1565
 
                 assemble_label_no(ln);
1566
 
                 return;
1567
 
 
1568
 
    /*  -------------------------------------------------------------------- */
1569
 
    /*  while (<condition>) <codeblock> ------------------------------------ */
1570
 
    /*  -------------------------------------------------------------------- */
1571
 
 
1572
 
        case WHILE_CODE:
1573
 
                 assemble_label_no(ln = next_label++);
1574
 
                 match_open_bracket();
1575
 
 
1576
 
                 code_generate(parse_expression(CONDITION_CONTEXT),
1577
 
                     CONDITION_CONTEXT, ln2 = next_label++);
1578
 
                 match_close_bracket();
1579
 
 
1580
 
                 parse_code_block(ln2, ln, 0);
1581
 
                 sequence_point_follows = FALSE;
1582
 
                 assemblez_jump(ln);
1583
 
                 assemble_label_no(ln2);
1584
 
                 return;
1585
 
 
1586
 
    /*  -------------------------------------------------------------------- */
1587
 
 
1588
 
        case SDEFAULT_CODE:
1589
 
                 error("'default' without matching 'switch'"); break;
1590
 
        case ELSE_CODE:
1591
 
                 error("'else' without matching 'if'"); break;
1592
 
        case UNTIL_CODE:
1593
 
                 error("'until' without matching 'do'");
1594
 
                 panic_mode_error_recovery(); return;
1595
 
    }
1596
 
 
1597
 
    StatementTerminator:
1598
 
 
1599
 
    get_next_token();
1600
 
    if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
1601
 
    {   ebf_error("';'", token_text);
1602
 
        put_token_back();
1603
 
    }
1604
 
}
1605
 
 
1606
 
static void parse_statement_g(int break_label, int continue_label)
1607
 
{   int ln, ln2, ln3, ln4, flag, onstack;
1608
 
    assembly_operand AO, AO2, AO3, AO4;
1609
 
    dbgl spare_dbgl1, spare_dbgl2;
1610
 
 
1611
 
    ASSERT_GLULX();
1612
 
 
1613
 
    if ((token_type == SEP_TT) && (token_value == PROPERTY_SEP))
1614
 
    {   /*  That is, a full stop, signifying a label  */
1615
 
 
1616
 
        get_next_token();
1617
 
        if (token_type == SYMBOL_TT)
1618
 
        {
1619
 
            if (sflags[token_value] & UNKNOWN_SFLAG)
1620
 
            {   assign_symbol(token_value, next_label, LABEL_T);
1621
 
                sflags[token_value] |= USED_SFLAG;
1622
 
                assemble_label_no(next_label);
1623
 
                define_symbol_label(token_value);
1624
 
                next_label++;
1625
 
            }
1626
 
            else
1627
 
            {   if (stypes[token_value] != LABEL_T) goto LabelError;
1628
 
                if (sflags[token_value] & CHANGE_SFLAG)
1629
 
                {   sflags[token_value] &= (~(CHANGE_SFLAG));
1630
 
                    assemble_label_no(svals[token_value]);
1631
 
                    define_symbol_label(token_value);
1632
 
                }
1633
 
                else error_named("Duplicate definition of label:", token_text);
1634
 
            }
1635
 
 
1636
 
            get_next_token();
1637
 
            if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
1638
 
            {   ebf_error("';'", token_text);
1639
 
                put_token_back(); return;
1640
 
            }
1641
 
 
1642
 
            /*  Interesting point of Inform grammar: a statement can only
1643
 
                consist solely of a label when it is immediately followed
1644
 
                by a "}".                                                    */
1645
 
 
1646
 
            get_next_token();
1647
 
            if ((token_type == SEP_TT) && (token_value == CLOSE_BRACE_SEP))
1648
 
            {   put_token_back(); return;
1649
 
            }
1650
 
            parse_statement(break_label, continue_label);
1651
 
            return;
1652
 
        }
1653
 
        LabelError: ebf_error("label name", token_text);
1654
 
    }
1655
 
 
1656
 
    if ((token_type == SEP_TT) && (token_value == HASH_SEP))
1657
 
    {   parse_directive(TRUE);
1658
 
        parse_statement(break_label, continue_label); return;
1659
 
    }
1660
 
 
1661
 
    if ((token_type == SEP_TT) && (token_value == AT_SEP))
1662
 
    {   parse_assembly(); return;
1663
 
    }
1664
 
 
1665
 
    if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) return;
1666
 
 
1667
 
    if (token_type == DQ_TT)
1668
 
    {   parse_print_g(TRUE); return;
1669
 
    }
1670
 
 
1671
 
    if ((token_type == SEP_TT) && (token_value == LESS_SEP))
1672
 
    {   parse_action(); goto StatementTerminator; }
1673
 
 
1674
 
    if (token_type == EOF_TT)
1675
 
    {   ebf_error("statement", token_text); return; }
1676
 
 
1677
 
    if (token_type != STATEMENT_TT)
1678
 
    {   put_token_back();
1679
 
        AO = parse_expression(VOID_CONTEXT);
1680
 
        code_generate(AO, VOID_CONTEXT, -1);
1681
 
        if (vivc_flag) { panic_mode_error_recovery(); return; }
1682
 
        goto StatementTerminator;
1683
 
    }
1684
 
 
1685
 
    statements.enabled = FALSE;
1686
 
 
1687
 
    switch(token_value)
1688
 
    {
1689
 
 
1690
 
    /*  -------------------------------------------------------------------- */
1691
 
    /*  box <string-1> ... <string-n> -------------------------------------- */
1692
 
    /*  -------------------------------------------------------------------- */
1693
 
 
1694
 
        case BOX_CODE:
1695
 
                 AO3.type = CONSTANT_OT;
1696
 
                 AO3.value = begin_table_array();
1697
 
                 AO3.marker = ARRAY_MV;
1698
 
                 ln = 0; ln2 = 0;
1699
 
                 do
1700
 
                 {   get_next_token();
1701
 
                     if ((token_type==SEP_TT)&&(token_value==SEMICOLON_SEP))
1702
 
                         break;
1703
 
                     if (token_type != DQ_TT)
1704
 
                         ebf_error("text of box line in double-quotes",
1705
 
                             token_text);
1706
 
                     {   int i, j;
1707
 
                         for (i=0, j=0; token_text[i] != 0; j++)
1708
 
                             if (token_text[i] == '@')
1709
 
                             {   if (token_text[i+1] == '@')
1710
 
                                 {   i = i + 2;
1711
 
                                     while (isdigit(token_text[i])) i++;
1712
 
                                 }
1713
 
                                 else
1714
 
                                 {   i++;
1715
 
                                     if (token_text[i] != 0) i++;
1716
 
                                     if (token_text[i] != 0) i++;
1717
 
                                 }
1718
 
                             }
1719
 
                             else i++;
1720
 
                         if (j > ln2) ln2 = j;
1721
 
                     }
1722
 
                     put_token_back();
1723
 
                     array_entry(ln++,parse_expression(CONSTANT_CONTEXT));
1724
 
                 } while (TRUE);
1725
 
                 finish_array(ln);
1726
 
                 if (ln == 0)
1727
 
                     error("No lines of text given for 'box' display");
1728
 
 
1729
 
                 AO2.value = ln2; AO2.marker = 0; set_constant_ot(&AO2);
1730
 
                 assembleg_call_2(veneer_routine(Box__Routine_VR),
1731
 
                     AO2, AO3, zero_operand);
1732
 
                 return;
1733
 
 
1734
 
    /*  -------------------------------------------------------------------- */
1735
 
    /*  break -------------------------------------------------------------- */
1736
 
    /*  -------------------------------------------------------------------- */
1737
 
 
1738
 
        case BREAK_CODE:
1739
 
                 if (break_label == -1)
1740
 
                 error("'break' can only be used in a loop or 'switch' block");
1741
 
                 else
1742
 
                     assembleg_jump(break_label);
1743
 
                 break;
1744
 
 
1745
 
    /*  -------------------------------------------------------------------- */
1746
 
    /*  continue ----------------------------------------------------------- */
1747
 
    /*  -------------------------------------------------------------------- */
1748
 
 
1749
 
        case CONTINUE_CODE:
1750
 
                 if (continue_label == -1)
1751
 
                 error("'continue' can only be used in a loop block");
1752
 
                 else
1753
 
                     assembleg_jump(continue_label);
1754
 
                 break;
1755
 
 
1756
 
    /*  -------------------------------------------------------------------- */
1757
 
    /*  do <codeblock> until (<condition>) --------------------------------- */
1758
 
    /*  -------------------------------------------------------------------- */
1759
 
 
1760
 
        case DO_CODE:
1761
 
                 assemble_label_no(ln = next_label++);
1762
 
                 ln2 = next_label++; ln3 = next_label++;
1763
 
                 parse_code_block(ln3, ln2, 0);
1764
 
                 statements.enabled = TRUE;
1765
 
                 get_next_token();
1766
 
                 if ((token_type == STATEMENT_TT)
1767
 
                     && (token_value == UNTIL_CODE))
1768
 
                 {   assemble_label_no(ln2);
1769
 
                     match_open_bracket();
1770
 
                     AO = parse_expression(CONDITION_CONTEXT);
1771
 
                     match_close_bracket();
1772
 
                     code_generate(AO, CONDITION_CONTEXT, ln);
1773
 
                 }
1774
 
                 else error("'do' without matching 'until'");
1775
 
 
1776
 
                 assemble_label_no(ln3);
1777
 
                 break;
1778
 
 
1779
 
    /*  -------------------------------------------------------------------- */
1780
 
    /*  font on/off -------------------------------------------------------- */
1781
 
    /*  -------------------------------------------------------------------- */
1782
 
 
1783
 
        case FONT_CODE:
1784
 
                 misc_keywords.enabled = TRUE;
1785
 
                 get_next_token();
1786
 
                 misc_keywords.enabled = FALSE;
1787
 
                 if ((token_type != MISC_KEYWORD_TT)
1788
 
                     || ((token_value != ON_MK)
1789
 
                         && (token_value != OFF_MK)))
1790
 
                 {   ebf_error("'on' or 'off'", token_text);
1791
 
                     panic_mode_error_recovery();
1792
 
                     break;
1793
 
                 }
1794
 
 
1795
 
                 /* Call glk_set_style(normal or preformatted) */
1796
 
                 AO.value = 0x0086;
1797
 
                 AO.marker = 0;
1798
 
                 set_constant_ot(&AO);
1799
 
                 if (token_value == ON_MK)
1800
 
                   AO2 = zero_operand;
1801
 
                 else 
1802
 
                   AO2 = two_operand;
1803
 
                 assembleg_call_2(veneer_routine(Glk__Wrap_VR), 
1804
 
                   AO, AO2, zero_operand);
1805
 
                 break;
1806
 
 
1807
 
    /*  -------------------------------------------------------------------- */
1808
 
    /*  for (<initialisation> : <continue-condition> : <updating>) --------- */
1809
 
    /*  -------------------------------------------------------------------- */
1810
 
 
1811
 
        /*  Note that it's legal for any or all of the three sections of a
1812
 
            'for' specification to be empty.  This 'for' implementation
1813
 
            often wastes 3 bytes with a redundant branch rather than keep
1814
 
            expression parse trees for long periods (as previous versions
1815
 
            of Inform did, somewhat crudely by simply storing the textual
1816
 
            form of a 'for' loop).  It is adequate for now.                  */
1817
 
 
1818
 
        case FOR_CODE:
1819
 
                 match_open_bracket();
1820
 
                 get_next_token();
1821
 
 
1822
 
                 /*  Initialisation code  */
1823
 
 
1824
 
                 if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
1825
 
                 {   put_token_back();
1826
 
                     if (!((token_type==SEP_TT)&&(token_value==SUPERCLASS_SEP)))
1827
 
                     {   sequence_point_follows = TRUE;
1828
 
                         debug_line_ref = token_line_ref;
1829
 
                         code_generate(parse_expression(FORINIT_CONTEXT),
1830
 
                             VOID_CONTEXT, -1);
1831
 
                     }
1832
 
                     get_next_token();
1833
 
                     if ((token_type==SEP_TT)&&(token_value == SUPERCLASS_SEP))
1834
 
                     {   get_next_token();
1835
 
                         if ((token_type==SEP_TT)&&(token_value == CLOSEB_SEP))
1836
 
                         {   assemble_label_no(ln = next_label++);
1837
 
                             ln2 = next_label++;
1838
 
                             parse_code_block(ln2, ln, 0);
1839
 
                             sequence_point_follows = FALSE;
1840
 
                             if (!execution_never_reaches_here)
1841
 
                                 assembleg_jump(ln);
1842
 
                             assemble_label_no(ln2);
1843
 
                             return;
1844
 
                         }
1845
 
                         AO.type = OMITTED_OT;
1846
 
                         goto ParseUpdate;
1847
 
                     }
1848
 
                     put_token_back();
1849
 
                     if (!match_colon()) break;
1850
 
                 }
1851
 
 
1852
 
                 get_next_token();
1853
 
                 AO.type = OMITTED_OT;
1854
 
                 if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
1855
 
                 {   put_token_back();
1856
 
                     spare_dbgl1 = token_line_ref;
1857
 
                     AO = parse_expression(CONDITION_CONTEXT);
1858
 
                     if (!match_colon()) break;
1859
 
                 }
1860
 
                 get_next_token();
1861
 
 
1862
 
                 ParseUpdate:
1863
 
                 AO2.type = OMITTED_OT; flag = 0;
1864
 
                 if (!((token_type==SEP_TT)&&(token_value==CLOSEB_SEP)))
1865
 
                 {   put_token_back();
1866
 
                     spare_dbgl2 = token_line_ref;
1867
 
                     AO2 = parse_expression(VOID_CONTEXT);
1868
 
                     match_close_bracket();
1869
 
                     flag = test_for_incdec(AO2);
1870
 
                 }
1871
 
 
1872
 
                 ln = next_label++;
1873
 
                 ln2 = next_label++;
1874
 
                 ln3 = next_label++;
1875
 
 
1876
 
                 if ((AO2.type == OMITTED_OT) || (flag != 0))
1877
 
                 {
1878
 
                     assemble_label_no(ln);
1879
 
                     if (flag==0) assemble_label_no(ln2);
1880
 
 
1881
 
                     /*  The "finished yet?" condition  */
1882
 
 
1883
 
                     if (AO.type != OMITTED_OT)
1884
 
                     {   sequence_point_follows = TRUE;
1885
 
                         debug_line_ref = spare_dbgl1;
1886
 
                         code_generate(AO, CONDITION_CONTEXT, ln3);
1887
 
                     }
1888
 
 
1889
 
                 }
1890
 
                 else
1891
 
                 {
1892
 
                     /*  This is the jump which could be avoided with the aid
1893
 
                         of long-term expression storage  */
1894
 
 
1895
 
                     sequence_point_follows = FALSE;
1896
 
                     assembleg_jump(ln2);
1897
 
 
1898
 
                     /*  The "update" part  */
1899
 
 
1900
 
                     assemble_label_no(ln);
1901
 
                     sequence_point_follows = TRUE;
1902
 
                     debug_line_ref = spare_dbgl2;
1903
 
                     code_generate(AO2, VOID_CONTEXT, -1);
1904
 
 
1905
 
                     assemble_label_no(ln2);
1906
 
 
1907
 
                     /*  The "finished yet?" condition  */
1908
 
 
1909
 
                     if (AO.type != OMITTED_OT)
1910
 
                     {   sequence_point_follows = TRUE;
1911
 
                         debug_line_ref = spare_dbgl1;
1912
 
                         code_generate(AO, CONDITION_CONTEXT, ln3);
1913
 
                     }
1914
 
                 }
1915
 
 
1916
 
                 if (flag != 0)
1917
 
                 {
1918
 
                     /*  In this optimised case, update code is at the end
1919
 
                         of the loop block, so "continue" goes there  */
1920
 
 
1921
 
                     parse_code_block(ln3, ln2, 0);
1922
 
                     assemble_label_no(ln2);
1923
 
 
1924
 
                     sequence_point_follows = TRUE;
1925
 
                     debug_line_ref = spare_dbgl2;
1926
 
                     if (flag > 0)
1927
 
                     {   AO3.value = flag;
1928
 
                         if (AO3.value >= MAX_LOCAL_VARIABLES)
1929
 
                           AO3.type = GLOBALVAR_OT;
1930
 
                         else
1931
 
                           AO3.type = LOCALVAR_OT;
1932
 
                         AO3.marker = 0;
1933
 
                         assembleg_3(add_gc, AO3, one_operand, AO3);
1934
 
                     }
1935
 
                     else
1936
 
                     {   AO3.value = -flag;
1937
 
                         if (AO3.value >= MAX_LOCAL_VARIABLES)
1938
 
                           AO3.type = GLOBALVAR_OT;
1939
 
                         else
1940
 
                           AO3.type = LOCALVAR_OT;
1941
 
                         AO3.marker = 0;
1942
 
                         assembleg_3(sub_gc, AO3, one_operand, AO3);
1943
 
                     }
1944
 
                     assembleg_jump(ln);
1945
 
                 }
1946
 
                 else
1947
 
                 {
1948
 
                     /*  In the unoptimised case, update code is at the
1949
 
                         start of the loop block, so "continue" goes there  */
1950
 
 
1951
 
                     parse_code_block(ln3, ln, 0);
1952
 
                     if (!execution_never_reaches_here)
1953
 
                     {   sequence_point_follows = FALSE;
1954
 
                         assembleg_jump(ln);
1955
 
                     }
1956
 
                 }
1957
 
 
1958
 
                 assemble_label_no(ln3);
1959
 
                 return;
1960
 
 
1961
 
    /*  -------------------------------------------------------------------- */
1962
 
    /*  give <expression> [~]attr [, [~]attr [, ...]] ---------------------- */
1963
 
    /*  -------------------------------------------------------------------- */
1964
 
 
1965
 
        case GIVE_CODE:
1966
 
                 AO = code_generate(parse_expression(QUANTITY_CONTEXT),
1967
 
                          QUANTITY_CONTEXT, -1);
1968
 
                 if ((AO.type == LOCALVAR_OT) && (AO.value == 0))
1969
 
                     onstack = TRUE;
1970
 
                 else
1971
 
                     onstack = FALSE;
1972
 
 
1973
 
                 do
1974
 
                 {   get_next_token();
1975
 
                     if ((token_type == SEP_TT) 
1976
 
                       && (token_value == SEMICOLON_SEP)) {
1977
 
                         if (onstack) {
1978
 
                           assembleg_2(copy_gc, stack_pointer, zero_operand);
1979
 
                         }
1980
 
                         return;
1981
 
                     }
1982
 
                     if ((token_type == SEP_TT)&&(token_value == ARTNOT_SEP))
1983
 
                         ln = 0;
1984
 
                     else
1985
 
                     {   if ((token_type == SYMBOL_TT)
1986
 
                             && (stypes[token_value] != ATTRIBUTE_T))
1987
 
                           warning_named("This is not a declared Attribute:",
1988
 
                             token_text);
1989
 
                         ln = 1;
1990
 
                         put_token_back();
1991
 
                     }
1992
 
                     AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
1993
 
                               QUANTITY_CONTEXT, -1);
1994
 
                     if (runtime_error_checking_switch && (!veneer_mode))
1995
 
                     {   ln2 = (ln ? RT__ChG_VR : RT__ChGt_VR);
1996
 
                         if ((AO2.type == LOCALVAR_OT) && (AO2.value == 0)) {
1997
 
                           /* already on stack */
1998
 
                         }
1999
 
                         else {
2000
 
                           assembleg_store(stack_pointer, AO2);
2001
 
                         }
2002
 
                         if (onstack)
2003
 
                           assembleg_2(stkpeek_gc, one_operand, stack_pointer);
2004
 
                         else
2005
 
                           assembleg_store(stack_pointer, AO);
2006
 
                         assembleg_3(call_gc, veneer_routine(ln2), two_operand,
2007
 
                           zero_operand);
2008
 
                     }
2009
 
                     else {
2010
 
                         if (is_constant_ot(AO2.type) && AO2.marker == 0) {
2011
 
                           AO2.value += 8;
2012
 
                           set_constant_ot(&AO2);
2013
 
                         }
2014
 
                         else {
2015
 
                           AO3.value = 8;
2016
 
                           AO3.marker = 0;
2017
 
                           AO3.type = BYTECONSTANT_OT;
2018
 
                           assembleg_3(add_gc, AO2, AO3, stack_pointer);
2019
 
                           AO2 = stack_pointer;
2020
 
                         }
2021
 
                         if (onstack) {
2022
 
                           if ((AO2.type == LOCALVAR_OT) && (AO2.value == 0))
2023
 
                             assembleg_2(stkpeek_gc, one_operand, 
2024
 
                               stack_pointer);
2025
 
                           else
2026
 
                             assembleg_2(stkpeek_gc, zero_operand, 
2027
 
                               stack_pointer);
2028
 
                         }
2029
 
                         if (ln) 
2030
 
                           AO3 = one_operand;
2031
 
                         else
2032
 
                           AO3 = zero_operand;
2033
 
                         assembleg_3(astorebit_gc, AO, AO2, AO3);
2034
 
                     }
2035
 
                 } while(TRUE);
2036
 
 
2037
 
    /*  -------------------------------------------------------------------- */
2038
 
    /*  if (<condition>) <codeblock> [else <codeblock>] -------------------- */
2039
 
    /*  -------------------------------------------------------------------- */
2040
 
 
2041
 
        case IF_CODE:
2042
 
                 flag = FALSE;
2043
 
 
2044
 
                 match_open_bracket();
2045
 
                 AO = parse_expression(CONDITION_CONTEXT);
2046
 
                 match_close_bracket();
2047
 
 
2048
 
                 statements.enabled = TRUE;
2049
 
                 get_next_token();
2050
 
                 if ((token_type == STATEMENT_TT)&&(token_value == RTRUE_CODE))
2051
 
                     ln = -4;
2052
 
                 else
2053
 
                 if ((token_type == STATEMENT_TT)&&(token_value == RFALSE_CODE))
2054
 
                     ln = -3;
2055
 
                 else
2056
 
                 {   put_token_back();
2057
 
                     ln = next_label++;
2058
 
                 }
2059
 
 
2060
 
                 code_generate(AO, CONDITION_CONTEXT, ln);
2061
 
 
2062
 
                 if (ln >= 0) parse_code_block(break_label, continue_label, 0);
2063
 
                 else
2064
 
                 {   get_next_token();
2065
 
                     if ((token_type != SEP_TT)
2066
 
                         || (token_value != SEMICOLON_SEP))
2067
 
                     {   ebf_error("';'", token_text);
2068
 
                         put_token_back();
2069
 
                     }
2070
 
                 }
2071
 
 
2072
 
                 statements.enabled = TRUE;
2073
 
                 get_next_token();
2074
 
                 if ((token_type == STATEMENT_TT) && (token_value == ELSE_CODE))
2075
 
                 {   flag = TRUE;
2076
 
                     if (ln >= 0)
2077
 
                     {   ln2 = next_label++;
2078
 
                         if (!execution_never_reaches_here)
2079
 
                         {   sequence_point_follows = FALSE;
2080
 
                             assembleg_jump(ln2);
2081
 
                         }
2082
 
                     }
2083
 
                 }
2084
 
                 else put_token_back();
2085
 
 
2086
 
                 if (ln >= 0) assemble_label_no(ln);
2087
 
 
2088
 
                 if (flag)
2089
 
                 {   parse_code_block(break_label, continue_label, 0);
2090
 
                     if (ln >= 0) assemble_label_no(ln2);
2091
 
                 }
2092
 
 
2093
 
                 return;
2094
 
 
2095
 
    /*  -------------------------------------------------------------------- */
2096
 
    /*  inversion ---------------------------------------------------------- */
2097
 
    /*  -------------------------------------------------------------------- */
2098
 
 
2099
 
        case INVERSION_CODE:
2100
 
                 AO2.marker = 0;
2101
 
                 AO2.type   = DEREFERENCE_OT;
2102
 
                 AO2.value  = GLULX_HEADER_SIZE+8; 
2103
 
                 assembleg_2(copyb_gc, AO2, stack_pointer);
2104
 
                 assembleg_1(streamchar_gc, stack_pointer);
2105
 
                 AO2.value  = GLULX_HEADER_SIZE+9; 
2106
 
                 assembleg_2(copyb_gc, AO2, stack_pointer);
2107
 
                 assembleg_1(streamchar_gc, stack_pointer);
2108
 
                 AO2.value  = GLULX_HEADER_SIZE+10; 
2109
 
                 assembleg_2(copyb_gc, AO2, stack_pointer);
2110
 
                 assembleg_1(streamchar_gc, stack_pointer);
2111
 
                 AO2.value  = GLULX_HEADER_SIZE+11; 
2112
 
                 assembleg_2(copyb_gc, AO2, stack_pointer);
2113
 
                 assembleg_1(streamchar_gc, stack_pointer);
2114
 
 
2115
 
                 if (0) {
2116
 
                     AO.marker = 0;
2117
 
                     AO.value = '(';
2118
 
                     set_constant_ot(&AO);
2119
 
                     assembleg_1(streamchar_gc, AO);
2120
 
                     AO.value = 'G';
2121
 
                     set_constant_ot(&AO);
2122
 
                     assembleg_1(streamchar_gc, AO);
2123
 
 
2124
 
                     AO2.value  = GLULX_HEADER_SIZE+12; 
2125
 
                     assembleg_2(copyb_gc, AO2, stack_pointer);
2126
 
                     assembleg_1(streamchar_gc, stack_pointer);
2127
 
                     AO2.value  = GLULX_HEADER_SIZE+13; 
2128
 
                     assembleg_2(copyb_gc, AO2, stack_pointer);
2129
 
                     assembleg_1(streamchar_gc, stack_pointer);
2130
 
                     AO2.value  = GLULX_HEADER_SIZE+14; 
2131
 
                     assembleg_2(copyb_gc, AO2, stack_pointer);
2132
 
                     assembleg_1(streamchar_gc, stack_pointer);
2133
 
                     AO2.value  = GLULX_HEADER_SIZE+15; 
2134
 
                     assembleg_2(copyb_gc, AO2, stack_pointer);
2135
 
                     assembleg_1(streamchar_gc, stack_pointer);
2136
 
 
2137
 
                     AO.marker = 0;
2138
 
                     AO.value = ')';
2139
 
                     set_constant_ot(&AO);
2140
 
                     assembleg_1(streamchar_gc, AO);
2141
 
                 }
2142
 
 
2143
 
                 break;
2144
 
 
2145
 
    /*  -------------------------------------------------------------------- */
2146
 
    /*  jump <label> ------------------------------------------------------- */
2147
 
    /*  -------------------------------------------------------------------- */
2148
 
 
2149
 
        case JUMP_CODE:
2150
 
                 assembleg_jump(parse_label());
2151
 
                 break;
2152
 
 
2153
 
    /*  -------------------------------------------------------------------- */
2154
 
    /*  move <expression> to <expression> ---------------------------------- */
2155
 
    /*  -------------------------------------------------------------------- */
2156
 
 
2157
 
        case MOVE_CODE:
2158
 
                 misc_keywords.enabled = TRUE;
2159
 
                 AO = parse_expression(QUANTITY_CONTEXT);
2160
 
 
2161
 
                 get_next_token();
2162
 
                 misc_keywords.enabled = FALSE;
2163
 
                 if ((token_type != MISC_KEYWORD_TT)
2164
 
                     || (token_value != TO_MK))
2165
 
                 {   ebf_error("'to'", token_text);
2166
 
                     panic_mode_error_recovery();
2167
 
                     return;
2168
 
                 }
2169
 
 
2170
 
                 AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
2171
 
                     QUANTITY_CONTEXT, -1);
2172
 
                 AO = code_generate(AO, QUANTITY_CONTEXT, -1);
2173
 
                 if ((runtime_error_checking_switch) && (veneer_mode == FALSE))
2174
 
                     assembleg_call_2(veneer_routine(RT__ChT_VR), AO, AO2,
2175
 
                         zero_operand);
2176
 
                 else
2177
 
                     assembleg_call_2(veneer_routine(OB__Move_VR), AO, AO2,
2178
 
                         zero_operand);
2179
 
                 break;
2180
 
 
2181
 
    /*  -------------------------------------------------------------------- */
2182
 
    /*  new_line ----------------------------------------------------------- */
2183
 
    /*  -------------------------------------------------------------------- */
2184
 
 
2185
 
        case NEW_LINE_CODE:  
2186
 
              AO.type = BYTECONSTANT_OT; AO.value = 0x0A; AO.marker = 0;
2187
 
              assembleg_1(streamchar_gc, AO); 
2188
 
              break;
2189
 
 
2190
 
    /*  -------------------------------------------------------------------- */
2191
 
    /*  objectloop (<initialisation>) <codeblock> -------------------------- */
2192
 
    /*  -------------------------------------------------------------------- */
2193
 
 
2194
 
        case OBJECTLOOP_CODE:
2195
 
 
2196
 
                 match_open_bracket();
2197
 
                 get_next_token();
2198
 
                 if (token_type == LOCAL_VARIABLE_TT) {
2199
 
                     AO.value = token_value;
2200
 
                     AO.type = LOCALVAR_OT;
2201
 
                     AO.marker = 0;
2202
 
                 }
2203
 
                 else if ((token_type == SYMBOL_TT) &&
2204
 
                   (stypes[token_value] == GLOBAL_VARIABLE_T)) {
2205
 
                     AO.value = svals[token_value];  
2206
 
                     AO.type = GLOBALVAR_OT;
2207
 
                     AO.marker = 0;
2208
 
                 }
2209
 
                 else {
2210
 
                     ebf_error("'objectloop' variable", token_text);
2211
 
                     panic_mode_error_recovery(); 
2212
 
                     break;
2213
 
                 }
2214
 
                 /*if ((module_switch) 
2215
 
                     && (AO.value >= MAX_LOCAL_VARIABLES)
2216
 
                     && (AO.value < LOWEST_SYSTEM_VAR_NUMBER))
2217
 
                     AO.marker = VARIABLE_MV;
2218
 
                 else AO.marker = 0;*/
2219
 
                 misc_keywords.enabled = TRUE;
2220
 
                 get_next_token(); flag = TRUE;
2221
 
                 misc_keywords.enabled = FALSE;
2222
 
                 if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
2223
 
                     flag = FALSE;
2224
 
 
2225
 
                 ln = 0;
2226
 
                 if ((token_type == MISC_KEYWORD_TT)
2227
 
                     && (token_value == NEAR_MK)) ln = 1;
2228
 
                 if ((token_type == MISC_KEYWORD_TT)
2229
 
                     && (token_value == FROM_MK)) ln = 2;
2230
 
                 if ((token_type == CND_TT) && (token_value == IN_COND))
2231
 
                 {   get_next_token();
2232
 
                     get_next_token();
2233
 
                     if ((token_type == SEP_TT) && (token_value == CLOSEB_SEP))
2234
 
                         ln = 3;
2235
 
                     put_token_back();
2236
 
                     put_token_back();
2237
 
                 }
2238
 
 
2239
 
                 if (ln != 0) {
2240
 
                   /*  Old style (Inform 5) objectloops: note that we
2241
 
                       implement objectloop (a in b) in the old way since
2242
 
                       this runs through objects in a different order from
2243
 
                       the new way, and there may be existing Inform code
2244
 
                       relying on this.                                    */
2245
 
                     assembly_operand AO4, AO5;
2246
 
 
2247
 
                     sequence_point_follows = TRUE;
2248
 
                     AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
2249
 
                         QUANTITY_CONTEXT, -1);
2250
 
                     match_close_bracket();
2251
 
                     if (ln == 1) {
2252
 
                         if (runtime_error_checking_switch)
2253
 
                             AO2 = check_nonzero_at_runtime(AO2, -1,
2254
 
                                 OBJECTLOOP_RTE);
2255
 
                         AO4.type = BYTECONSTANT_OT;
2256
 
                         AO4.value = 5; /* parent */
2257
 
                         AO4.marker = 0;
2258
 
                         assembleg_3(aload_gc, AO2, AO4, stack_pointer);
2259
 
                         AO4.type = BYTECONSTANT_OT;
2260
 
                         AO4.value = 7; /* child */
2261
 
                         AO4.marker = 0;
2262
 
                         assembleg_3(aload_gc, stack_pointer, AO4, stack_pointer);
2263
 
                         AO2 = stack_pointer;
2264
 
                     }
2265
 
                     else if (ln == 3) {
2266
 
                         if (runtime_error_checking_switch) {
2267
 
                             AO5 = AO2;
2268
 
                             AO2 = check_nonzero_at_runtime(AO2, -1,
2269
 
                                 CHILD_RTE);
2270
 
                         }
2271
 
                         AO4.type = BYTECONSTANT_OT;
2272
 
                         AO4.value = 7; /* child */
2273
 
                         AO4.marker = 0;
2274
 
                         assembleg_3(aload_gc, AO2, AO4, stack_pointer);
2275
 
                         AO2 = stack_pointer;
2276
 
                     }
2277
 
                     else {
2278
 
                         /* do nothing */
2279
 
                     }
2280
 
                     assembleg_store(AO, AO2);
2281
 
                     assembleg_1_branch(jz_gc, AO, ln2 = next_label++);
2282
 
                     assemble_label_no(ln4 = next_label++);
2283
 
                     parse_code_block(ln2, ln3 = next_label++, 0);
2284
 
                     sequence_point_follows = FALSE;
2285
 
                     assemble_label_no(ln3);
2286
 
                     if (runtime_error_checking_switch) {
2287
 
                         AO2 = check_nonzero_at_runtime(AO, ln2,
2288
 
                              OBJECTLOOP2_RTE);
2289
 
                         if ((ln == 3)
2290
 
                             && ((AO5.type != LOCALVAR_OT)||(AO5.value != 0))
2291
 
                             && ((AO5.type != LOCALVAR_OT)||(AO5.value != AO.value)))
2292
 
                         {   assembly_operand en_ao;
2293
 
                             en_ao.value = OBJECTLOOP_BROKEN_RTE;
2294
 
                             en_ao.marker = 0;
2295
 
                             set_constant_ot(&en_ao);
2296
 
                             AO4.type = BYTECONSTANT_OT;
2297
 
                             AO4.value = 5; /* parent */
2298
 
                             AO4.marker = 0;
2299
 
                             assembleg_3(aload_gc, AO, AO4, stack_pointer);
2300
 
                             assembleg_2_branch(jeq_gc, stack_pointer, AO5, 
2301
 
                                 next_label);
2302
 
                             assembleg_call_2(veneer_routine(RT__Err_VR),
2303
 
                                 en_ao, AO, zero_operand);
2304
 
                             assembleg_jump(ln2);
2305
 
                             assemble_label_no(next_label++);
2306
 
                         }
2307
 
                     }
2308
 
                     else {
2309
 
                         AO2 = AO;
2310
 
                     }
2311
 
                     AO4.type = BYTECONSTANT_OT;
2312
 
                     AO4.value = 6; /* sibling */
2313
 
                     AO4.marker = 0;
2314
 
                     assembleg_3(aload_gc, AO2, AO4, AO);
2315
 
                     assembleg_1_branch(jnz_gc, AO, ln4);
2316
 
                     assemble_label_no(ln2);
2317
 
                     return;
2318
 
                 }
2319
 
 
2320
 
                 sequence_point_follows = TRUE;
2321
 
                 ln = symbol_index("Class", -1);
2322
 
                 AO2.value = svals[ln];
2323
 
                 AO2.marker = OBJECT_MV;
2324
 
                 AO2.type = CONSTANT_OT;
2325
 
                 assembleg_store(AO, AO2);
2326
 
 
2327
 
                 assemble_label_no(ln = next_label++);
2328
 
                 ln2 = next_label++;
2329
 
                 ln3 = next_label++;
2330
 
                 if (flag)
2331
 
                 {   put_token_back();
2332
 
                     put_token_back();
2333
 
                     sequence_point_follows = TRUE;
2334
 
                     code_generate(parse_expression(CONDITION_CONTEXT),
2335
 
                         CONDITION_CONTEXT, ln3);
2336
 
                     match_close_bracket();
2337
 
                 }
2338
 
                 parse_code_block(ln2, ln3, 0);
2339
 
 
2340
 
                 sequence_point_follows = FALSE;
2341
 
                 assemble_label_no(ln3);
2342
 
                 assembleg_3(aload_gc, AO, two_operand, AO);
2343
 
                 assembleg_1_branch(jnz_gc, AO, ln);
2344
 
                 assemble_label_no(ln2);
2345
 
                 return;
2346
 
 
2347
 
    /*  -------------------------------------------------------------------- */
2348
 
    /*  (see routine above) ------------------------------------------------ */
2349
 
    /*  -------------------------------------------------------------------- */
2350
 
 
2351
 
        case PRINT_CODE:
2352
 
            get_next_token();
2353
 
            parse_print_g(FALSE); return;
2354
 
        case PRINT_RET_CODE:
2355
 
            get_next_token();
2356
 
            parse_print_g(TRUE); return;
2357
 
 
2358
 
    /*  -------------------------------------------------------------------- */
2359
 
    /*  quit --------------------------------------------------------------- */
2360
 
    /*  -------------------------------------------------------------------- */
2361
 
 
2362
 
        case QUIT_CODE:
2363
 
                 assembleg_0(quit_gc); break;
2364
 
 
2365
 
    /*  -------------------------------------------------------------------- */
2366
 
    /*  remove <expression> ------------------------------------------------ */
2367
 
    /*  -------------------------------------------------------------------- */
2368
 
 
2369
 
        case REMOVE_CODE:
2370
 
                 AO = code_generate(parse_expression(QUANTITY_CONTEXT),
2371
 
                     QUANTITY_CONTEXT, -1);
2372
 
                 if ((runtime_error_checking_switch) && (veneer_mode == FALSE))
2373
 
                     assembleg_call_1(veneer_routine(RT__ChR_VR), AO,
2374
 
                         zero_operand);
2375
 
                 else
2376
 
                     assembleg_call_1(veneer_routine(OB__Remove_VR), AO,
2377
 
                         zero_operand);
2378
 
                 break;
2379
 
 
2380
 
    /*  -------------------------------------------------------------------- */
2381
 
    /*  return [<expression>] ---------------------------------------------- */
2382
 
    /*  -------------------------------------------------------------------- */
2383
 
 
2384
 
        case RETURN_CODE:
2385
 
          get_next_token();
2386
 
          if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) {
2387
 
            AO.type = BYTECONSTANT_OT; AO.value = 1; AO.marker = 0;
2388
 
            assembleg_1(return_gc, AO); 
2389
 
            return; 
2390
 
          }
2391
 
          put_token_back();
2392
 
          AO = code_generate(parse_expression(RETURN_Q_CONTEXT),
2393
 
            QUANTITY_CONTEXT, -1);
2394
 
          assembleg_1(return_gc, AO);
2395
 
          break;
2396
 
 
2397
 
    /*  -------------------------------------------------------------------- */
2398
 
    /*  rfalse ------------------------------------------------------------- */
2399
 
    /*  -------------------------------------------------------------------- */
2400
 
 
2401
 
        case RFALSE_CODE:   
2402
 
          assembleg_1(return_gc, zero_operand); 
2403
 
          break;
2404
 
 
2405
 
    /*  -------------------------------------------------------------------- */
2406
 
    /*  rtrue -------------------------------------------------------------- */
2407
 
    /*  -------------------------------------------------------------------- */
2408
 
 
2409
 
        case RTRUE_CODE:   
2410
 
          assembleg_1(return_gc, one_operand); 
2411
 
          break;
2412
 
 
2413
 
    /*  -------------------------------------------------------------------- */
2414
 
    /*  spaces <expression> ------------------------------------------------ */
2415
 
    /*  -------------------------------------------------------------------- */
2416
 
 
2417
 
        case SPACES_CODE:
2418
 
                 AO = code_generate(parse_expression(QUANTITY_CONTEXT),
2419
 
                     QUANTITY_CONTEXT, -1);
2420
 
 
2421
 
                 assembleg_store(temp_var1, AO);
2422
 
 
2423
 
                 AO.value = 32; AO.marker = 0; set_constant_ot(&AO);
2424
 
 
2425
 
                 assembleg_2_branch(jlt_gc, temp_var1, one_operand, 
2426
 
                     ln = next_label++);
2427
 
                 assemble_label_no(ln2 = next_label++);
2428
 
                 assembleg_1(streamchar_gc, AO);
2429
 
                 assembleg_dec(temp_var1);
2430
 
                 assembleg_1_branch(jnz_gc, temp_var1, ln2);
2431
 
                 assemble_label_no(ln);
2432
 
                 break;
2433
 
 
2434
 
    /*  -------------------------------------------------------------------- */
2435
 
    /*  string <expression> <literal-string> ------------------------------- */
2436
 
    /*  -------------------------------------------------------------------- */
2437
 
 
2438
 
        case STRING_CODE:
2439
 
                 AO2 = code_generate(parse_expression(QUANTITY_CONTEXT),
2440
 
                     QUANTITY_CONTEXT, -1);
2441
 
                 get_next_token();
2442
 
                 if (token_type == DQ_TT)
2443
 
                 {   AO4.value = compile_string(token_text, TRUE, TRUE);
2444
 
                     AO4.marker = STRING_MV;
2445
 
                     AO4.type = CONSTANT_OT;
2446
 
                 }
2447
 
                 else
2448
 
                 {   put_token_back();
2449
 
                     AO4 = parse_expression(CONSTANT_CONTEXT);
2450
 
                 }
2451
 
                 assembleg_call_2(veneer_routine(Dynam__String_VR),
2452
 
                   AO2, AO4, zero_operand);
2453
 
                 break;
2454
 
 
2455
 
    /*  -------------------------------------------------------------------- */
2456
 
    /*  style roman/reverse/bold/underline/fixed --------------------------- */
2457
 
    /*  -------------------------------------------------------------------- */
2458
 
 
2459
 
        case STYLE_CODE:
2460
 
                 misc_keywords.enabled = TRUE;
2461
 
                 get_next_token();
2462
 
                 misc_keywords.enabled = FALSE;
2463
 
                 if ((token_type != MISC_KEYWORD_TT)
2464
 
                     || ((token_value != ROMAN_MK)
2465
 
                         && (token_value != REVERSE_MK)
2466
 
                         && (token_value != BOLD_MK)
2467
 
                         && (token_value != UNDERLINE_MK)
2468
 
                         && (token_value != FIXED_MK)))
2469
 
                 {   ebf_error(
2470
 
"'roman', 'bold', 'underline', 'reverse' or 'fixed'",
2471
 
                         token_text);
2472
 
                     panic_mode_error_recovery();
2473
 
                     break;
2474
 
                 }
2475
 
 
2476
 
                 /* Call glk_set_style() */
2477
 
 
2478
 
                 AO.value = 0x0086;
2479
 
                 AO.marker = 0;
2480
 
                 set_constant_ot(&AO);
2481
 
                 switch(token_value)
2482
 
                 {   case ROMAN_MK: 
2483
 
                         AO2 = zero_operand; /* normal */
2484
 
                         break;
2485
 
                     case REVERSE_MK: 
2486
 
                         AO2.value = 5; /* alert */
2487
 
                         AO2.marker = 0;
2488
 
                         set_constant_ot(&AO2);
2489
 
                         break;
2490
 
                     case BOLD_MK: 
2491
 
                         AO2.value = 4; /* subheader */
2492
 
                         AO2.marker = 0;
2493
 
                         set_constant_ot(&AO2);
2494
 
                         break;
2495
 
                     case UNDERLINE_MK: 
2496
 
                         AO2 = one_operand; /* emphasized */
2497
 
                         break;
2498
 
                     case FIXED_MK: 
2499
 
                         AO2 = two_operand; /* preformatted */
2500
 
                         break;
2501
 
                 }
2502
 
                 assembleg_call_2(veneer_routine(Glk__Wrap_VR), 
2503
 
                   AO, AO2, zero_operand);
2504
 
                 break;
2505
 
 
2506
 
    /*  -------------------------------------------------------------------- */
2507
 
    /*  switch (<expression>) <codeblock> ---------------------------------- */
2508
 
    /*  -------------------------------------------------------------------- */
2509
 
 
2510
 
        case SWITCH_CODE:
2511
 
                 match_open_bracket();
2512
 
                 AO = code_generate(parse_expression(QUANTITY_CONTEXT),
2513
 
                     QUANTITY_CONTEXT, -1);
2514
 
                 match_close_bracket();
2515
 
 
2516
 
                 assembleg_store(temp_var1, AO); 
2517
 
 
2518
 
                 parse_code_block(ln = next_label++, continue_label, 1);
2519
 
                 assemble_label_no(ln);
2520
 
                 return;
2521
 
 
2522
 
    /*  -------------------------------------------------------------------- */
2523
 
    /*  while (<condition>) <codeblock> ------------------------------------ */
2524
 
    /*  -------------------------------------------------------------------- */
2525
 
 
2526
 
        case WHILE_CODE:
2527
 
                 assemble_label_no(ln = next_label++);
2528
 
                 match_open_bracket();
2529
 
 
2530
 
                 code_generate(parse_expression(CONDITION_CONTEXT),
2531
 
                     CONDITION_CONTEXT, ln2 = next_label++);
2532
 
                 match_close_bracket();
2533
 
 
2534
 
                 parse_code_block(ln2, ln, 0);
2535
 
                 sequence_point_follows = FALSE;
2536
 
                 assembleg_jump(ln);
2537
 
                 assemble_label_no(ln2);
2538
 
                 return;
2539
 
 
2540
 
    /*  -------------------------------------------------------------------- */
2541
 
 
2542
 
        case SDEFAULT_CODE:
2543
 
                 error("'default' without matching 'switch'"); break;
2544
 
        case ELSE_CODE:
2545
 
                 error("'else' without matching 'if'"); break;
2546
 
        case UNTIL_CODE:
2547
 
                 error("'until' without matching 'do'");
2548
 
                 panic_mode_error_recovery(); return;
2549
 
 
2550
 
    /*  -------------------------------------------------------------------- */
2551
 
 
2552
 
    /* And a useful default, which will never be triggered in a complete
2553
 
       Inform compiler, but which is important in development. */
2554
 
 
2555
 
        default:
2556
 
          error("*** Statement code gen: Can't generate yet ***\n");
2557
 
          panic_mode_error_recovery(); return;
2558
 
    }
2559
 
 
2560
 
    StatementTerminator:
2561
 
 
2562
 
    get_next_token();
2563
 
    if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
2564
 
    {   ebf_error("';'", token_text);
2565
 
        put_token_back();
2566
 
    }
2567
 
}
2568
 
 
2569
 
extern void parse_statement(int break_label, int continue_label)
2570
 
{
2571
 
  if (!glulx_mode)
2572
 
    parse_statement_z(break_label, continue_label);
2573
 
  else
2574
 
    parse_statement_g(break_label, continue_label);
2575
 
}
2576
 
 
2577
 
/* ========================================================================= */
2578
 
/*   Data structure management routines                                      */
2579
 
/* ------------------------------------------------------------------------- */
2580
 
 
2581
 
extern void init_states_vars(void)
2582
 
{
2583
 
}
2584
 
 
2585
 
extern void states_begin_pass(void)
2586
 
{
2587
 
}
2588
 
 
2589
 
extern void states_allocate_arrays(void)
2590
 
{
2591
 
}
2592
 
 
2593
 
extern void states_free_arrays(void)
2594
 
{
2595
 
}
2596
 
 
2597
 
/* ========================================================================= */