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

« back to all changes in this revision

Viewing changes to src/directs.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
 
/*   "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
 
/* ========================================================================= */