~ubuntu-branches/ubuntu/gutsy/inform/gutsy

« back to all changes in this revision

Viewing changes to src/directs.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Baker
  • Date: 2004-03-29 23:52:44 UTC
  • Revision ID: james.westby@ubuntu.com-20040329235244-fox1z1yv7d6vojoo
Tags: upstream-6.30
ImportĀ upstreamĀ versionĀ 6.30

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ------------------------------------------------------------------------- */
 
2
/*   "directs" : Directives (# commands)                                     */
 
3
/*                                                                           */
 
4
/*   Part of Inform 6.30                                                     */
 
5
/*   copyright (c) Graham Nelson 1993 - 2004                                 */
 
6
/*                                                                           */
 
7
/* ------------------------------------------------------------------------- */
 
8
 
 
9
#include "header.h"
 
10
 
 
11
int no_routines,                   /* Number of routines compiled so far     */
 
12
    no_named_routines,             /* Number not embedded in objects         */
 
13
    no_locals,                     /* Number of locals in current routine    */
 
14
    no_termcs;                     /* Number of terminating characters       */
 
15
int terminating_characters[32];
 
16
 
 
17
int32 routine_starts_line;         /* Source code line on which the current
 
18
                                      routine starts.  (Useful for reporting
 
19
                                      "unused variable" warnings on the start
 
20
                                      line rather than the end line.)        */
 
21
 
 
22
static int constant_made_yet;      /* Have any constants been defined yet?   */
 
23
 
 
24
static int ifdef_stack[32], ifdef_sp;
 
25
 
 
26
/* ------------------------------------------------------------------------- */
 
27
 
 
28
extern int parse_given_directive(void)
 
29
{   int *trace_level; int32 i, j, k, n, flag;
 
30
 
 
31
    switch(token_value)
 
32
    {
 
33
 
 
34
    /* --------------------------------------------------------------------- */
 
35
    /*   Abbreviate "string1" ["string2" ...]                                */
 
36
    /* --------------------------------------------------------------------- */
 
37
 
 
38
    case ABBREVIATE_CODE:
 
39
 
 
40
        do
 
41
        {  get_next_token();
 
42
           if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
 
43
               return FALSE;
 
44
 
 
45
           /* Glulx doesn't have a 64-abbrev limit */
 
46
           if (!glulx_mode && MAX_ABBREVS==64)
 
47
           {   if (no_abbreviations==64)
 
48
                   error("All 64 abbreviations already declared");
 
49
           }
 
50
           else
 
51
           {   if (no_abbreviations==MAX_ABBREVS)
 
52
                   memoryerror("MAX_ABBREVS", MAX_ABBREVS);
 
53
           }
 
54
 
 
55
           if (abbrevs_lookup_table_made)
 
56
           {   error("All abbreviations must be declared together");
 
57
               break;
 
58
           }
 
59
           if (token_type != DQ_TT)
 
60
               ebf_error("abbreviation string", token_text);
 
61
           else
 
62
           if (strlen(token_text)<2)
 
63
           {   error_named("It's not worth abbreviating", token_text);
 
64
               break;
 
65
           }
 
66
           make_abbreviation(token_text);
 
67
        } while (TRUE);
 
68
 
 
69
    /* --------------------------------------------------------------------- */
 
70
    /*   Array arrayname array...                                            */
 
71
    /* --------------------------------------------------------------------- */
 
72
 
 
73
    case ARRAY_CODE: make_global(TRUE, FALSE); break;      /* See "tables.c" */
 
74
 
 
75
    /* --------------------------------------------------------------------- */
 
76
    /*   Attribute newname [alias oldname]                                   */
 
77
    /* --------------------------------------------------------------------- */
 
78
 
 
79
    case ATTRIBUTE_CODE:
 
80
        make_attribute(); break;                          /* See "objects.c" */
 
81
 
 
82
    /* --------------------------------------------------------------------- */
 
83
    /*   Class classname ...                                                 */
 
84
    /* --------------------------------------------------------------------- */
 
85
 
 
86
    case CLASS_CODE: make_class(NULL); return FALSE;       /* See "tables.c" */
 
87
 
 
88
    /* --------------------------------------------------------------------- */
 
89
    /*   Constant newname [[=] value] [, ...]                                */
 
90
    /* --------------------------------------------------------------------- */
 
91
 
 
92
    case CONSTANT_CODE:
 
93
        constant_made_yet=TRUE;
 
94
 
 
95
      ParseConstantSpec:
 
96
        get_next_token(); i = token_value;
 
97
 
 
98
        if ((token_type != SYMBOL_TT)
 
99
            || (!(sflags[i] & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG))))
 
100
        {   ebf_error("new constant name", token_text);
 
101
            panic_mode_error_recovery(); break;
 
102
        }
 
103
 
 
104
        assign_symbol(i, 0, CONSTANT_T);
 
105
 
 
106
        get_next_token();
 
107
 
 
108
        if ((token_type == SEP_TT) && (token_value == COMMA_SEP))
 
109
            goto ParseConstantSpec;
 
110
 
 
111
        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
 
112
            return FALSE;
 
113
 
 
114
        if (!((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)))
 
115
            put_token_back();
 
116
 
 
117
        {   assembly_operand AO = parse_expression(CONSTANT_CONTEXT);
 
118
            if (AO.marker != 0)
 
119
            {   assign_marked_symbol(i, AO.marker, AO.value,
 
120
                    CONSTANT_T);
 
121
                sflags[i] |= CHANGE_SFLAG;
 
122
                if (i == grammar_version_symbol)
 
123
                    error(
 
124
                "Grammar__Version must be given an explicit constant value");
 
125
            }
 
126
            else
 
127
            {   assign_symbol(i, AO.value, CONSTANT_T);
 
128
                if (i == grammar_version_symbol)
 
129
                {   if ((grammar_version_number != AO.value)
 
130
                        && (no_fake_actions > 0))
 
131
                        error(
 
132
                "Once a fake action has been defined it is too late to \
 
133
change the grammar version. (If you are using the library, move any \
 
134
Fake_Action directives to a point after the inclusion of \"Parser\".)");
 
135
                    grammar_version_number = AO.value;
 
136
                }
 
137
            }
 
138
        }
 
139
        get_next_token();
 
140
        if ((token_type == SEP_TT) && (token_value == COMMA_SEP))
 
141
            goto ParseConstantSpec;
 
142
        put_token_back();
 
143
        break;
 
144
 
 
145
    /* --------------------------------------------------------------------- */
 
146
    /*   Default constantname integer                                        */
 
147
    /* --------------------------------------------------------------------- */
 
148
 
 
149
    case DEFAULT_CODE:
 
150
        if (module_switch)
 
151
        {   error("'Default' cannot be used in -M (Module) mode");
 
152
            break;
 
153
        }
 
154
 
 
155
        get_next_token();
 
156
        if (token_type != SYMBOL_TT)
 
157
        {   ebf_error("name", token_text);
 
158
            panic_mode_error_recovery(); break;
 
159
        }
 
160
 
 
161
        i = -1;
 
162
        if (sflags[token_value] & UNKNOWN_SFLAG)
 
163
        {   i = token_value;
 
164
            sflags[i] |= DEFCON_SFLAG;
 
165
        }
 
166
 
 
167
        get_next_token();
 
168
        if (!((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)))
 
169
            put_token_back();
 
170
 
 
171
        {   assembly_operand AO;
 
172
            AO = parse_expression(CONSTANT_CONTEXT);
 
173
            if (i != -1)
 
174
            {   if (AO.marker != 0)
 
175
                {   assign_marked_symbol(i, AO.marker, AO.value,
 
176
                        CONSTANT_T);
 
177
                    sflags[i] |= CHANGE_SFLAG;
 
178
                }
 
179
                else assign_symbol(i, AO.value, CONSTANT_T);
 
180
            }
 
181
        }
 
182
 
 
183
        break;
 
184
 
 
185
    /* --------------------------------------------------------------------- */
 
186
    /*   Dictionary constantname "word"                                      */
 
187
    /* --------------------------------------------------------------------- */
 
188
 
 
189
    case DICTIONARY_CODE:
 
190
        obsolete_warning("use 'word' as a constant dictionary address");
 
191
        goto ParseConstantSpec;
 
192
 
 
193
    /* --------------------------------------------------------------------- */
 
194
    /*   End                                                                 */
 
195
    /* --------------------------------------------------------------------- */
 
196
 
 
197
    case END_CODE: return(TRUE);
 
198
 
 
199
    case ENDIF_CODE:
 
200
        if (ifdef_sp == 0) error("'Endif' without matching 'If...'");
 
201
        else ifdef_sp--;
 
202
        break;
 
203
 
 
204
    /* --------------------------------------------------------------------- */
 
205
    /*   Extend ...                                                          */
 
206
    /* --------------------------------------------------------------------- */
 
207
 
 
208
    case EXTEND_CODE: extend_verb(); return FALSE;         /* see "tables.c" */
 
209
 
 
210
    /* --------------------------------------------------------------------- */
 
211
    /*   Fake_Action name                                                    */
 
212
    /* --------------------------------------------------------------------- */
 
213
 
 
214
    case FAKE_ACTION_CODE:
 
215
        make_fake_action(); break;                         /* see "tables.c" */
 
216
 
 
217
    /* --------------------------------------------------------------------- */
 
218
    /*   Global variable [= value / array...]                                */
 
219
    /* --------------------------------------------------------------------- */
 
220
 
 
221
    case GLOBAL_CODE: make_global(FALSE, FALSE); break;    /* See "tables.c" */
 
222
 
 
223
    /* --------------------------------------------------------------------- */
 
224
    /*   If...                                                               */
 
225
    /*                                                                       */
 
226
    /*   Note that each time Inform tests an If... condition, it stacks the  */
 
227
    /*   result (TRUE or FALSE) on ifdef_stack: thus, the top of this stack  */
 
228
    /*   reveals what clause of the current If... is being compiled:         */
 
229
    /*                                                                       */
 
230
    /*               If...;  ...  Ifnot;  ...  Endif;                        */
 
231
    /*   top of stack:       TRUE        FALSE                               */
 
232
    /*                                                                       */
 
233
    /*   This is used to detect "two Ifnots in same If" errors.              */
 
234
    /* --------------------------------------------------------------------- */
 
235
 
 
236
    case IFDEF_CODE:
 
237
        flag = TRUE;
 
238
        goto DefCondition;
 
239
    case IFNDEF_CODE:
 
240
        flag = FALSE;
 
241
 
 
242
      DefCondition:
 
243
        get_next_token();
 
244
        if (token_type != SYMBOL_TT)
 
245
        {   ebf_error("symbol name", token_text);
 
246
            break;
 
247
        }
 
248
 
 
249
        if ((token_text[0] == 'V')
 
250
            && (token_text[1] == 'N')
 
251
            && (token_text[2] == '_')
 
252
            && (strlen(token_text)==7))
 
253
        {   i = atoi(token_text+3);
 
254
            if (VNUMBER < i) flag = (flag)?FALSE:TRUE;
 
255
            goto HashIfCondition;
 
256
        }
 
257
 
 
258
        if (sflags[token_value] & UNKNOWN_SFLAG) flag = (flag)?FALSE:TRUE;
 
259
        else sflags[token_value] |= USED_SFLAG;
 
260
        goto HashIfCondition;
 
261
 
 
262
    case IFNOT_CODE:
 
263
        if (ifdef_sp == 0)
 
264
            error("'Ifnot' without matching 'If...'");
 
265
        else
 
266
        if (!(ifdef_stack[ifdef_sp-1]))
 
267
            error("Second 'Ifnot' for the same 'If...' condition");
 
268
        else
 
269
        {   dont_enter_into_symbol_table = -2; n = 1;
 
270
            directives.enabled = TRUE;
 
271
            do
 
272
            {   get_next_token();
 
273
                if (token_type == EOF_TT)
 
274
                {   error("End of file reached in code 'If...'d out");
 
275
                    directives.enabled = FALSE;
 
276
                    return TRUE;
 
277
                }
 
278
                if (token_type == DIRECTIVE_TT)
 
279
                {   switch(token_value)
 
280
                    {   case ENDIF_CODE:
 
281
                            n--; break;
 
282
                        case IFV3_CODE:
 
283
                        case IFV5_CODE:
 
284
                        case IFDEF_CODE:
 
285
                        case IFNDEF_CODE:
 
286
                        case IFTRUE_CODE:
 
287
                        case IFFALSE_CODE:
 
288
                            n++; break;
 
289
                        case IFNOT_CODE:
 
290
                            if (n == 1)
 
291
                            {   error(
 
292
                              "Second 'Ifnot' for the same 'If...' condition");
 
293
                                break;
 
294
                            }
 
295
                    }
 
296
                }
 
297
            } while (n > 0);
 
298
            ifdef_sp--; 
 
299
            dont_enter_into_symbol_table = FALSE;
 
300
            directives.enabled = FALSE;
 
301
        }
 
302
        break;
 
303
 
 
304
    case IFV3_CODE:
 
305
        flag = FALSE; if (version_number == 3) flag = TRUE;
 
306
        goto HashIfCondition;
 
307
 
 
308
    case IFV5_CODE:
 
309
        flag = TRUE; if (version_number == 3) flag = FALSE;
 
310
        goto HashIfCondition;
 
311
 
 
312
    case IFTRUE_CODE:
 
313
        {   assembly_operand AO;
 
314
            AO = parse_expression(CONSTANT_CONTEXT);
 
315
            if (module_switch && (AO.marker != 0))
 
316
            {   error("This condition can't be determined");
 
317
                flag = 0;
 
318
            }
 
319
            else flag = (AO.value != 0);
 
320
        }
 
321
        goto HashIfCondition;
 
322
 
 
323
    case IFFALSE_CODE:
 
324
        {   assembly_operand AO;
 
325
            AO = parse_expression(CONSTANT_CONTEXT);
 
326
            if (module_switch && (AO.marker != 0))
 
327
            {   error("This condition can't be determined");
 
328
                flag = 1;
 
329
            }
 
330
            else flag = (AO.value == 0);
 
331
        }
 
332
        goto HashIfCondition;
 
333
 
 
334
    HashIfCondition:
 
335
        get_next_token();
 
336
        if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
 
337
        {   ebf_error("semicolon after 'If...' condition", token_text);
 
338
            break;
 
339
        }
 
340
 
 
341
        if (flag)
 
342
        {   ifdef_stack[ifdef_sp++] = TRUE; return FALSE; }
 
343
        else
 
344
        {   dont_enter_into_symbol_table = -2; n = 1;
 
345
            directives.enabled = TRUE;
 
346
            do
 
347
            {   get_next_token();
 
348
                if (token_type == EOF_TT)
 
349
                {   error("End of file reached in code 'If...'d out");
 
350
                    directives.enabled = FALSE;
 
351
                    return TRUE;
 
352
                }
 
353
                if (token_type == DIRECTIVE_TT)
 
354
                {
 
355
                    switch(token_value)
 
356
                    {   case ENDIF_CODE:
 
357
                            n--; break;
 
358
                        case IFV3_CODE:
 
359
                        case IFV5_CODE:
 
360
                        case IFDEF_CODE:
 
361
                        case IFNDEF_CODE:
 
362
                        case IFTRUE_CODE:
 
363
                        case IFFALSE_CODE:
 
364
                            n++; break;
 
365
                        case IFNOT_CODE:
 
366
                            if (n == 1)
 
367
                            {   ifdef_stack[ifdef_sp++] = FALSE;
 
368
                                n--; break;
 
369
                            }
 
370
                    }
 
371
                }
 
372
            } while (n > 0);
 
373
            directives.enabled = FALSE;
 
374
            dont_enter_into_symbol_table = FALSE;
 
375
        }
 
376
        break;
 
377
 
 
378
    /* --------------------------------------------------------------------- */
 
379
    /*   Import global <varname> [, ...]                                     */
 
380
    /*                                                                       */
 
381
    /* (Further imported goods may be allowed later.)                        */
 
382
    /* --------------------------------------------------------------------- */
 
383
 
 
384
    case IMPORT_CODE:
 
385
        if (!module_switch)
 
386
        {   error("'Import' can only be used in -M (Module) mode");
 
387
            break;
 
388
        }
 
389
        directives.enabled = TRUE;
 
390
        do
 
391
        {   get_next_token();
 
392
            if ((token_type == DIRECTIVE_TT) && (token_value == GLOBAL_CODE))
 
393
                 make_global(FALSE, TRUE);
 
394
            else error_named("'Import' cannot import things of this type:",
 
395
                 token_text);
 
396
            get_next_token();
 
397
        } while ((token_type == SEP_TT) && (token_value == COMMA_SEP));
 
398
        put_token_back();
 
399
        directives.enabled = FALSE;
 
400
        break;
 
401
 
 
402
    /* --------------------------------------------------------------------- */
 
403
    /*   Include "[>]filename"                                               */
 
404
    /* --------------------------------------------------------------------- */
 
405
 
 
406
    case INCLUDE_CODE:
 
407
        get_next_token();
 
408
        if (token_type != DQ_TT)
 
409
        {   ebf_error("filename in double-quotes", token_text);
 
410
            panic_mode_error_recovery(); return FALSE;
 
411
        }
 
412
 
 
413
        {   char *name = token_text;
 
414
 
 
415
            get_next_token();
 
416
            if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
 
417
                ebf_error("semicolon ';' after Include filename", token_text);
 
418
 
 
419
            if (strcmp(name, "language__") == 0)
 
420
                 load_sourcefile(Language_Name, 0);
 
421
            else if (name[0] == '>')
 
422
                 load_sourcefile(name+1, 1);
 
423
            else load_sourcefile(name, 0);
 
424
            return FALSE;
 
425
        }
 
426
 
 
427
    /* --------------------------------------------------------------------- */
 
428
    /*   Link "filename"                                                     */
 
429
    /* --------------------------------------------------------------------- */
 
430
 
 
431
    case LINK_CODE:
 
432
        get_next_token();
 
433
        if (token_type != DQ_TT)
 
434
        {   ebf_error("filename in double-quotes", token_text);
 
435
            panic_mode_error_recovery(); return FALSE;
 
436
        }
 
437
        link_module(token_text);                           /* See "linker.c" */
 
438
        break;
 
439
 
 
440
    /* --------------------------------------------------------------------- */
 
441
    /*   Lowstring constantname "text of string"                             */
 
442
    /* --------------------------------------------------------------------- */
 
443
    /* Unlike most constant creations, these do not require backpatching:    */
 
444
    /* the low strings always occupy a table at a fixed offset in the        */
 
445
    /* Z-machine (after the abbreviations table has finished, at 0x100).     */
 
446
    /* --------------------------------------------------------------------- */
 
447
 
 
448
    case LOWSTRING_CODE:
 
449
        if (module_switch)
 
450
        {   error("'LowString' cannot be used in -M (Module) mode"); break;
 
451
        }
 
452
        get_next_token(); i = token_value;
 
453
        if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG)))
 
454
        {   ebf_error("new low string name", token_text);
 
455
            panic_mode_error_recovery(); return FALSE;
 
456
        }
 
457
 
 
458
        get_next_token();
 
459
        if (token_type != DQ_TT)
 
460
        {   ebf_error("literal string in double-quotes", token_text);
 
461
            panic_mode_error_recovery(); return FALSE;
 
462
        }
 
463
 
 
464
        assign_symbol(i, compile_string(token_text, TRUE, TRUE), CONSTANT_T);
 
465
        break;
 
466
 
 
467
    /* --------------------------------------------------------------------- */
 
468
    /*   Message | "information"                                             */
 
469
    /*           | error "error message"                                     */
 
470
    /*           | fatalerror "fatal error message"                          */
 
471
    /*           | warning "warning message"                                 */
 
472
    /* --------------------------------------------------------------------- */
 
473
 
 
474
    case MESSAGE_CODE:
 
475
        directive_keywords.enabled = TRUE;
 
476
        get_next_token();
 
477
        directive_keywords.enabled = FALSE;
 
478
        if (token_type == DQ_TT)
 
479
        {   int i;
 
480
            if (hash_printed_since_newline) printf("\n");
 
481
            for (i=0; token_text[i]!=0; i++)
 
482
            {   if (token_text[i] == '^') printf("\n");
 
483
                else
 
484
                if (token_text[i] == '~') printf("\"");
 
485
                else printf("%c", token_text[i]);
 
486
            }
 
487
            printf("\n");
 
488
            break;
 
489
        }
 
490
        if ((token_type == DIR_KEYWORD_TT) && (token_value == ERROR_DK))
 
491
        {   get_next_token();
 
492
            if (token_type != DQ_TT)
 
493
            {   ebf_error("error message in double-quotes", token_text);
 
494
            }
 
495
            error(token_text); break;
 
496
        }
 
497
        if ((token_type == DIR_KEYWORD_TT) && (token_value == FATALERROR_DK))
 
498
        {   get_next_token();
 
499
            if (token_type != DQ_TT)
 
500
            {   ebf_error("fatal error message in double-quotes", token_text);
 
501
            }
 
502
            fatalerror(token_text); break;
 
503
        }
 
504
        if ((token_type == DIR_KEYWORD_TT) && (token_value == WARNING_DK))
 
505
        {   get_next_token();
 
506
            if (token_type != DQ_TT)
 
507
            {   ebf_error("warning message in double-quotes", token_text);
 
508
            }
 
509
            warning(token_text); break;
 
510
        }
 
511
        ebf_error("a message in double-quotes, 'error', 'fatalerror' or 'warning'",
 
512
            token_text);
 
513
        break;
 
514
 
 
515
    /* --------------------------------------------------------------------- */
 
516
    /*   Nearby objname "short name" ...                                     */
 
517
    /* --------------------------------------------------------------------- */
 
518
 
 
519
    case NEARBY_CODE: make_object(TRUE, NULL, -1, -1, -1);
 
520
        return FALSE;                                     /* See "objects.c" */
 
521
 
 
522
    /* --------------------------------------------------------------------- */
 
523
    /*   Object objname "short name" ...                                     */
 
524
    /* --------------------------------------------------------------------- */
 
525
 
 
526
    case OBJECT_CODE: make_object(FALSE, NULL, -1, -1, -1);
 
527
        return FALSE;                                     /* See "objects.c" */
 
528
 
 
529
    /* --------------------------------------------------------------------- */
 
530
    /*   Property [long] [additive] name [alias oldname]                     */
 
531
    /* --------------------------------------------------------------------- */
 
532
 
 
533
    case PROPERTY_CODE: make_property(); break;           /* See "objects.c" */
 
534
 
 
535
    /* --------------------------------------------------------------------- */
 
536
    /*   Release <number>                                                    */
 
537
    /* --------------------------------------------------------------------- */
 
538
 
 
539
    case RELEASE_CODE:
 
540
        {   assembly_operand AO;
 
541
            AO = parse_expression(CONSTANT_CONTEXT);
 
542
            if (module_switch && (AO.marker != 0))
 
543
                error("A definite value must be given as release number");
 
544
            else
 
545
                release_number = AO.value;
 
546
        }
 
547
        break;
 
548
 
 
549
    /* --------------------------------------------------------------------- */
 
550
    /*   Replace routine                                                     */
 
551
    /* --------------------------------------------------------------------- */
 
552
 
 
553
    case REPLACE_CODE:
 
554
        /* You can also replace system functions normally implemented in     */
 
555
        /* the "hardware" of the Z-machine, like "random()":                 */
 
556
 
 
557
        system_functions.enabled = TRUE;
 
558
        directives.enabled = FALSE;
 
559
        directive_keywords.enabled = FALSE;
 
560
 
 
561
        get_next_token();
 
562
        if (token_type == SYSFUN_TT)
 
563
        {   if (system_function_usage[token_value] == 1)
 
564
                error("You can't 'Replace' a system function already used");
 
565
            else system_function_usage[token_value] = 2;
 
566
            break;
 
567
        }
 
568
 
 
569
        if (token_type != SYMBOL_TT)
 
570
        {   ebf_error("name of routine to replace", token_text);
 
571
            break;
 
572
        }
 
573
 
 
574
        if (!(sflags[token_value] & UNKNOWN_SFLAG))
 
575
        {   ebf_error("name of routine not yet defined", token_text);
 
576
            break;
 
577
        }
 
578
        sflags[token_value] |= REPLACE_SFLAG;
 
579
 
 
580
        break;
 
581
 
 
582
    /* --------------------------------------------------------------------- */
 
583
    /*   Serial "yymmdd"                                                     */
 
584
    /* --------------------------------------------------------------------- */
 
585
 
 
586
    case SERIAL_CODE:
 
587
        get_next_token();
 
588
        if ((token_type != DQ_TT) || (strlen(token_text)!=6))
 
589
        {   error("The serial number must be a 6-digit date in double-quotes");
 
590
            break;
 
591
        }
 
592
        for (i=0; i<6; i++) if (isdigit(token_text[i])==0)
 
593
        {   error("The serial number must be a 6-digit date in double-quotes");
 
594
            break;
 
595
        }
 
596
        strcpy(serial_code_buffer, token_text);
 
597
        serial_code_given_in_program = TRUE;
 
598
        break;
 
599
 
 
600
    /* --------------------------------------------------------------------- */
 
601
    /*   Statusline score/time                                               */
 
602
    /* --------------------------------------------------------------------- */
 
603
 
 
604
    case STATUSLINE_CODE:
 
605
        if (module_switch)
 
606
            warning("This does not set the final game's statusline");
 
607
 
 
608
        directive_keywords.enabled = TRUE;
 
609
        get_next_token();
 
610
        directive_keywords.enabled = FALSE;
 
611
        if ((token_type != DIR_KEYWORD_TT)
 
612
            || ((token_value != SCORE_DK) && (token_value != TIME_DK)))
 
613
        {   ebf_error("'score' or 'time' after 'statusline'", token_text);
 
614
            break;
 
615
        }
 
616
        if (token_value == SCORE_DK) statusline_flag = SCORE_STYLE;
 
617
        else statusline_flag = TIME_STYLE;
 
618
        break;
 
619
 
 
620
    /* --------------------------------------------------------------------- */
 
621
    /*   Stub routinename number-of-locals                                   */
 
622
    /* --------------------------------------------------------------------- */
 
623
 
 
624
    case STUB_CODE:
 
625
 
 
626
        get_next_token();
 
627
        if (token_type != SYMBOL_TT)
 
628
        {   ebf_error("routine name to stub", token_text);
 
629
            panic_mode_error_recovery(); return FALSE;
 
630
        }
 
631
 
 
632
        i = token_value; flag = FALSE;
 
633
 
 
634
        if (sflags[i] & UNKNOWN_SFLAG)
 
635
        {   sflags[i] |= STUB_SFLAG;
 
636
            flag = TRUE;
 
637
        }
 
638
 
 
639
        get_next_token(); k = token_value;
 
640
        if (token_type != NUMBER_TT)
 
641
        {   ebf_error("number of local variables", token_text);
 
642
            k = 0;
 
643
        }
 
644
        if ((k>4) || (k<0))
 
645
        {   error("Must specify 0 to 4 local variables for 'Stub' routine");
 
646
            k = 0;
 
647
        }
 
648
 
 
649
        if (flag)
 
650
        {
 
651
            /*  Give these parameter-receiving local variables names
 
652
                for the benefit of the debugging information file,
 
653
                and for assembly tracing to look sensible.                   */
 
654
 
 
655
            local_variable_texts[0] = "dummy1";
 
656
            local_variable_texts[1] = "dummy2";
 
657
            local_variable_texts[2] = "dummy3";
 
658
            local_variable_texts[3] = "dummy4";
 
659
 
 
660
            assign_symbol(i,
 
661
                assemble_routine_header(k, FALSE, (char *) symbs[i],
 
662
                    &token_line_ref, FALSE, i),
 
663
                ROUTINE_T);
 
664
 
 
665
            /*  Ensure the return value of a stubbed routine is false,
 
666
                since this is necessary to make the library work properly    */
 
667
 
 
668
            if (!glulx_mode)
 
669
                assemblez_0(rfalse_zc);
 
670
            else
 
671
                assembleg_1(return_gc, zero_operand);
 
672
 
 
673
            /*  Inhibit "local variable unused" warnings  */
 
674
 
 
675
            for (i=1; i<=k; i++) variable_usage[i] = 1;
 
676
            sequence_point_follows = FALSE;
 
677
            assemble_routine_end(FALSE, &token_line_ref);
 
678
        }
 
679
        break;
 
680
 
 
681
    /* --------------------------------------------------------------------- */
 
682
    /*   Switches switchblock                                                */
 
683
    /* (this directive is ignored if the -i switch was set at command line)  */
 
684
    /* --------------------------------------------------------------------- */
 
685
 
 
686
    case SWITCHES_CODE:
 
687
        dont_enter_into_symbol_table = TRUE;
 
688
        get_next_token();
 
689
        dont_enter_into_symbol_table = FALSE;
 
690
        if (token_type != DQ_TT)
 
691
        {   ebf_error("string of switches", token_text);
 
692
            break;
 
693
        }
 
694
        if (!ignore_switches_switch)
 
695
        {   if (constant_made_yet)
 
696
                error("A 'Switches' directive must must come before \
 
697
the first constant definition");
 
698
            switches(token_text, 0);                       /* see "inform.c" */
 
699
        }
 
700
        break;
 
701
 
 
702
    /* --------------------------------------------------------------------- */
 
703
    /*   System_file                                                         */
 
704
    /*                                                                       */
 
705
    /* Some files are declared as "system files": this information is used   */
 
706
    /* by Inform only to skip the definition of a routine X if the designer  */
 
707
    /* has indicated his intention to Replace X.                             */
 
708
    /* --------------------------------------------------------------------- */
 
709
 
 
710
    case SYSTEM_CODE:
 
711
        declare_systemfile(); break;                        /* see "files.c" */
 
712
 
 
713
    /* --------------------------------------------------------------------- */
 
714
    /*   Trace dictionary                                                    */
 
715
    /*         objects                                                       */
 
716
    /*         symbols                                                       */
 
717
    /*         verbs                                                         */
 
718
    /*                      [on/off]                                         */
 
719
    /*         assembly     [on/off]                                         */
 
720
    /*         expressions  [on/off]                                         */
 
721
    /*         lines        [on/off]                                         */
 
722
    /* --------------------------------------------------------------------- */
 
723
 
 
724
    case TRACE_CODE:
 
725
        directives.enabled = FALSE;
 
726
        trace_keywords.enabled = TRUE;
 
727
        get_next_token();
 
728
        trace_keywords.enabled = FALSE;
 
729
        directives.enabled = TRUE;
 
730
        if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
 
731
        {   asm_trace_level = 1; return FALSE; }
 
732
 
 
733
        if (token_type != TRACE_KEYWORD_TT)
 
734
        {   ebf_error("debugging keyword", token_text);
 
735
            panic_mode_error_recovery(); return FALSE;
 
736
        }
 
737
 
 
738
        trace_keywords.enabled = TRUE;
 
739
 
 
740
        i = token_value; j = 0;
 
741
        switch(i)
 
742
        {   case DICTIONARY_TK: break;
 
743
            case OBJECTS_TK:    break;
 
744
            case VERBS_TK:      break;
 
745
            default:
 
746
                switch(token_value)
 
747
                {   case ASSEMBLY_TK:
 
748
                        trace_level = &asm_trace_level;  break;
 
749
                    case EXPRESSIONS_TK:
 
750
                        trace_level = &expr_trace_level; break;
 
751
                    case LINES_TK:
 
752
                        trace_level = &line_trace_level; break;
 
753
                    case TOKENS_TK:
 
754
                        trace_level = &tokens_trace_level; break;
 
755
                    case LINKER_TK:
 
756
                        trace_level = &linker_trace_level; break;
 
757
                    case SYMBOLS_TK:
 
758
                        trace_level = NULL; break;
 
759
                    default:
 
760
                        put_token_back();
 
761
                        trace_level = &asm_trace_level; break;
 
762
                }
 
763
                j = 1;
 
764
                get_next_token();
 
765
                if ((token_type == SEP_TT) &&
 
766
                    (token_value == SEMICOLON_SEP))
 
767
                {   put_token_back(); break;
 
768
                }
 
769
                if (token_type == NUMBER_TT)
 
770
                {   j = token_value; break; }
 
771
                if ((token_type == TRACE_KEYWORD_TT) && (token_value == ON_TK))
 
772
                {   j = 1; break; }
 
773
                if ((token_type == TRACE_KEYWORD_TT) && (token_value == OFF_TK))
 
774
                {   j = 0; break; }
 
775
                put_token_back(); break;
 
776
        }
 
777
 
 
778
        switch(i)
 
779
        {   case DICTIONARY_TK: show_dictionary();  break;
 
780
            case OBJECTS_TK:    list_object_tree(); break;
 
781
            case SYMBOLS_TK:    list_symbols(j);     break;
 
782
            case VERBS_TK:      list_verb_table();  break;
 
783
            default:
 
784
                *trace_level = j;
 
785
                break;
 
786
        }
 
787
        trace_keywords.enabled = FALSE;
 
788
        break;
 
789
 
 
790
    /* --------------------------------------------------------------------- */
 
791
    /*   Verb ...                                                            */
 
792
    /* --------------------------------------------------------------------- */
 
793
 
 
794
    case VERB_CODE: make_verb(); return FALSE;             /* see "tables.c" */
 
795
 
 
796
    /* --------------------------------------------------------------------- */
 
797
    /*   Version <number>                                                    */
 
798
    /* --------------------------------------------------------------------- */
 
799
 
 
800
    case VERSION_CODE:
 
801
 
 
802
        /* Ignore this if a version has already been set on the command line */
 
803
        if (version_set_switch) break;
 
804
 
 
805
        {   assembly_operand AO;
 
806
            AO = parse_expression(CONSTANT_CONTEXT);
 
807
            if (module_switch && (AO.marker != 0))
 
808
                error("A definite value must be given as version number");
 
809
            else
 
810
            {   i = AO.value;
 
811
                if ((i<3) || (i>8))
 
812
                {   error("The version number must be in the range 3 to 8");
 
813
                    break;
 
814
                }
 
815
                select_version(i);
 
816
            }
 
817
        }
 
818
        break;                                             /* see "inform.c" */
 
819
 
 
820
    /* --------------------------------------------------------------------- */
 
821
    /*   Zcharacter table <num> ...                                          */
 
822
    /*   Zcharacter table + <num> ...                                        */
 
823
    /*   Zcharacter <string> <string> <string>                               */
 
824
    /*   Zcharacter <char>                                                   */
 
825
    /* --------------------------------------------------------------------- */
 
826
 
 
827
    case ZCHARACTER_CODE:
 
828
 
 
829
        if (glulx_mode) {
 
830
            error("Glulx Inform does not handle Unicode yet.");
 
831
            break;
 
832
        }
 
833
 
 
834
        directive_keywords.enabled = TRUE;
 
835
        get_next_token();
 
836
        directive_keywords.enabled = FALSE;
 
837
 
 
838
        switch(token_type)
 
839
        {   case DQ_TT:
 
840
                new_alphabet(token_text, 0);
 
841
                get_next_token();
 
842
                if (token_type != DQ_TT)
 
843
                    ebf_error("double-quoted alphabet string", token_text);
 
844
                else new_alphabet(token_text, 1);
 
845
                get_next_token();
 
846
                if (token_type != DQ_TT)
 
847
                    ebf_error("double-quoted alphabet string", token_text);
 
848
                else new_alphabet(token_text, 2);
 
849
            break;
 
850
 
 
851
            case SQ_TT:
 
852
                map_new_zchar(text_to_unicode(token_text));
 
853
                if (token_text[textual_form_length] != 0)
 
854
                    ebf_error("single character value", token_text);
 
855
            break;
 
856
 
 
857
            case DIR_KEYWORD_TT:
 
858
            switch(token_value)
 
859
            {   case TABLE_DK:
 
860
                {   int plus_flag = FALSE;
 
861
                    get_next_token();
 
862
                    if ((token_type == SEP_TT) && (token_value == PLUS_SEP))
 
863
                    {   plus_flag = TRUE;
 
864
                        get_next_token();
 
865
                    }
 
866
                    while ((token_type!=SEP_TT) || (token_value!=SEMICOLON_SEP))
 
867
                    {   switch(token_type)
 
868
                        {   case NUMBER_TT:
 
869
                                new_zscii_character(token_value, plus_flag);
 
870
                                plus_flag = TRUE; break;
 
871
                            case SQ_TT:
 
872
                                new_zscii_character(text_to_unicode(token_text),
 
873
                                    plus_flag);
 
874
                                if (token_text[textual_form_length] != 0)
 
875
                                    ebf_error("single character value",
 
876
                                        token_text);
 
877
                                plus_flag = TRUE;
 
878
                                break;
 
879
                            default:
 
880
                                ebf_error("character or Unicode number",
 
881
                                    token_text); break;
 
882
                        }
 
883
                        get_next_token();
 
884
                    }
 
885
                    if (plus_flag) new_zscii_finished();
 
886
                    put_token_back();
 
887
                }
 
888
                    break;
 
889
                case TERMINATING_DK:
 
890
                    get_next_token();
 
891
                    while ((token_type!=SEP_TT) || (token_value!=SEMICOLON_SEP))
 
892
                    {   switch(token_type)
 
893
                        {   case NUMBER_TT:
 
894
                                terminating_characters[no_termcs++]
 
895
                                    = token_value;
 
896
                                break;
 
897
                            default:
 
898
                                ebf_error("ZSCII number", token_text); break;
 
899
                        }
 
900
                        get_next_token();
 
901
                    }
 
902
                    put_token_back();
 
903
                    break;
 
904
                default:
 
905
                    ebf_error("'table', 'terminating', a string or a constant",
 
906
                        token_text);
 
907
            }
 
908
                break;
 
909
            default:
 
910
                ebf_error("three alphabet strings, a 'table' or 'terminating' \
 
911
command or a single character", token_text);
 
912
            break;
 
913
        }
 
914
        break;
 
915
 
 
916
    /* ===================================================================== */
 
917
 
 
918
    }
 
919
    get_next_token();
 
920
    if ((token_type != SEP_TT) || (token_value != SEMICOLON_SEP))
 
921
    {   ebf_error("';'", token_text);
 
922
        put_token_back();
 
923
    }
 
924
    return FALSE;
 
925
}
 
926
 
 
927
/* ========================================================================= */
 
928
/*   Data structure management routines                                      */
 
929
/* ------------------------------------------------------------------------- */
 
930
 
 
931
extern void init_directs_vars(void)
 
932
{
 
933
}
 
934
 
 
935
extern void directs_begin_pass(void)
 
936
{   no_routines = 0;
 
937
    no_named_routines = 0;
 
938
    no_locals = 0;
 
939
    no_termcs = 0;
 
940
    constant_made_yet = FALSE;
 
941
    ifdef_sp = 0;
 
942
}
 
943
 
 
944
extern void directs_allocate_arrays(void)
 
945
{
 
946
}
 
947
 
 
948
extern void directs_free_arrays(void)
 
949
{
 
950
}
 
951
 
 
952
/* ========================================================================= */