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

« back to all changes in this revision

Viewing changes to inform-6.31.1/src/inform.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
/*   "inform" :  The top level of Inform: switches, pathnames, filenaming    */
 
3
/*               conventions, ICL (Inform Command Line) files, main          */
 
4
/*                                                                           */
 
5
/*   Part of Inform 6.31                                                     */
 
6
/*   copyright (c) Graham Nelson 1993 - 2006                                 */
 
7
/*                                                                           */
 
8
/* ------------------------------------------------------------------------- */
 
9
 
 
10
#define MAIN_INFORM_FILE
 
11
#include "header.h"
 
12
 
 
13
/* ------------------------------------------------------------------------- */
 
14
/*   Compiler progress                                                       */
 
15
/* ------------------------------------------------------------------------- */
 
16
 
 
17
static int no_compilations;
 
18
 
 
19
int endofpass_flag;      /* set to TRUE when an "end" directive is reached
 
20
                            (the inputs routines insert one into the stream
 
21
                            if necessary)                                    */
 
22
 
 
23
/* ------------------------------------------------------------------------- */
 
24
/*   Version control                                                         */
 
25
/* ------------------------------------------------------------------------- */
 
26
 
 
27
/* This stuff is Z-code only, for now. It might handle multiple Glulx
 
28
   versions someday, if needed. */
 
29
 
 
30
int version_number,      /* 3 to 8                                           */
 
31
    instruction_set_number,
 
32
                         /* 3 to 6: versions 7 and 8 use instruction set of
 
33
                            version 5                                        */
 
34
    extend_memory_map;   /* extend using function- and string-offsets        */
 
35
int32 scale_factor,      /* packed address multiplier                        */
 
36
    length_scale_factor; /* length-in-header multiplier                      */
 
37
 
 
38
extern void select_version(int vn)
 
39
{   version_number = vn;
 
40
    extend_memory_map = FALSE;
 
41
    if ((version_number==6)||(version_number==7)) extend_memory_map = TRUE;
 
42
 
 
43
    scale_factor = 4;
 
44
    if (version_number==3) scale_factor = 2;
 
45
    if (version_number==8) scale_factor = 8;
 
46
 
 
47
    length_scale_factor = scale_factor;
 
48
    if ((version_number==6)||(version_number==7)) length_scale_factor = 8;
 
49
 
 
50
    instruction_set_number = version_number;
 
51
    if ((version_number==7)||(version_number==8)) instruction_set_number = 5;
 
52
}
 
53
 
 
54
/* ------------------------------------------------------------------------- */
 
55
/*   Target: variables which vary between the Z-machine and Glulx            */
 
56
/* ------------------------------------------------------------------------- */
 
57
 
 
58
int   WORDSIZE;            /* Size of a machine word: 2 or 4 */
 
59
int32 MAXINTWORD;          /* 0x7FFF or 0x7FFFFFFF */
 
60
 
 
61
/* The first property number which is an individual property. The
 
62
   eight class-system i-props (create, recreate, ... print_to_array)
 
63
   are numbered from INDIV_PROP_START to INDIV_PROP_START+7.
 
64
*/
 
65
int INDIV_PROP_START;
 
66
 
 
67
/* The length of an object, as written in tables.c. It's easier to define
 
68
   it here than to repeat the same expression all over the source code.
 
69
   Not used in Z-code. 
 
70
*/
 
71
int OBJECT_BYTE_LENGTH;
 
72
 
 
73
static void select_target(int targ)
 
74
{
 
75
  if (!targ) {
 
76
    /* Z-machine */
 
77
    WORDSIZE = 2;
 
78
    MAXINTWORD = 0x7FFF;
 
79
    INDIV_PROP_START = 64;
 
80
    OBJECT_BYTE_LENGTH = 0; /* not used */
 
81
 
 
82
    if (DICT_WORD_SIZE != 6) {
 
83
      DICT_WORD_SIZE = 6;
 
84
      warning("You cannot change DICT_WORD_SIZE in Z-code; resetting to 6");
 
85
    }
 
86
    if (NUM_ATTR_BYTES != 6) {
 
87
      NUM_ATTR_BYTES = 6;
 
88
      warning("You cannot change NUM_ATTR_BYTES in Z-code; resetting to 6");
 
89
    }
 
90
    if (MAX_LOCAL_VARIABLES != 16) {
 
91
      MAX_LOCAL_VARIABLES = 16;
 
92
      warning("You cannot change MAX_LOCAL_VARIABLES in Z-code; resetting to 16");
 
93
    }
 
94
    if (MAX_GLOBAL_VARIABLES != 240) {
 
95
      MAX_GLOBAL_VARIABLES = 240;
 
96
      warning("You cannot change MAX_GLOBAL_VARIABLES in Z-code; resetting to 240");
 
97
    }
 
98
  }
 
99
  else {
 
100
    /* Glulx */
 
101
    WORDSIZE = 4;
 
102
    MAXINTWORD = 0x7FFFFFFF;
 
103
    INDIV_PROP_START = 256; /* This could be a memory setting */
 
104
    scale_factor = 0; /* It should never even get used in Glulx */
 
105
 
 
106
    if (NUM_ATTR_BYTES % 4 != 3) {
 
107
      NUM_ATTR_BYTES += (3 - (NUM_ATTR_BYTES % 4)); 
 
108
      warning_numbered("NUM_ATTR_BYTES must be a multiple of four, plus three. Increasing to", NUM_ATTR_BYTES);
 
109
    }
 
110
 
 
111
    OBJECT_BYTE_LENGTH = (1 + (NUM_ATTR_BYTES) + 6*4);
 
112
  }
 
113
 
 
114
  if (MAX_LOCAL_VARIABLES >= 120) {
 
115
    MAX_LOCAL_VARIABLES = 119;
 
116
    warning("MAX_LOCAL_VARIABLES cannot exceed 119; resetting to 119");
 
117
    /* This is because the keyword table in the lexer only has 120
 
118
       entries. */
 
119
  }
 
120
  if (DICT_WORD_SIZE > MAX_DICT_WORD_SIZE) {
 
121
    DICT_WORD_SIZE = MAX_DICT_WORD_SIZE;
 
122
    warning_numbered(
 
123
      "DICT_WORD_SIZE cannot exceed MAX_DICT_WORD_SIZE; resetting", 
 
124
      MAX_DICT_WORD_SIZE);
 
125
    /* MAX_DICT_WORD_SIZE can be increased in header.h without fear. */
 
126
  }
 
127
  if (NUM_ATTR_BYTES > MAX_NUM_ATTR_BYTES) {
 
128
    NUM_ATTR_BYTES = MAX_NUM_ATTR_BYTES;
 
129
    warning_numbered(
 
130
      "NUM_ATTR_BYTES cannot exceed MAX_NUM_ATTR_BYTES; resetting",
 
131
      MAX_NUM_ATTR_BYTES);
 
132
    /* MAX_NUM_ATTR_BYTES can be increased in header.h without fear. */
 
133
  }
 
134
}
 
135
 
 
136
/* ------------------------------------------------------------------------- */
 
137
/*   Tracery: output control variables                                       */
 
138
/* ------------------------------------------------------------------------- */
 
139
 
 
140
int asm_trace_level,     /* trace assembly: 0 for off, 1 for assembly
 
141
                            only, 2 for full assembly tracing with hex dumps */
 
142
    line_trace_level,    /* line tracing: 0 off, 1 on                        */
 
143
    expr_trace_level,    /* expression tracing: 0 off, 1 full, 2 brief       */
 
144
    linker_trace_level,  /* set by -y: 0 to 4 levels of tracing              */
 
145
    tokens_trace_level;  /* lexer output tracing: 0 off, 1 on                */
 
146
 
 
147
/* ------------------------------------------------------------------------- */
 
148
/*   On/off switch variables (by default all FALSE); other switch settings   */
 
149
/* ------------------------------------------------------------------------- */
 
150
 
 
151
int bothpasses_switch,              /* -b */
 
152
    concise_switch,                 /* -c */
 
153
    economy_switch,                 /* -e */
 
154
    frequencies_switch,             /* -f */
 
155
    ignore_switches_switch,         /* -i */
 
156
    listobjects_switch,             /* -j */
 
157
    debugfile_switch,               /* -k */
 
158
    listing_switch,                 /* -l */
 
159
    memout_switch,                  /* -m */
 
160
    printprops_switch,              /* -n */
 
161
    offsets_switch,                 /* -o */
 
162
    percentages_switch,             /* -p */
 
163
    obsolete_switch,                /* -q */
 
164
    transcript_switch,              /* -r */
 
165
    statistics_switch,              /* -s */
 
166
    optimise_switch,                /* -u */
 
167
    version_set_switch,             /* -v */
 
168
    nowarnings_switch,              /* -w */
 
169
    hash_switch,                    /* -x */
 
170
    memory_map_switch,              /* -z */
 
171
    oddeven_packing_switch,         /* -B */
 
172
    define_DEBUG_switch,            /* -D */
 
173
    temporary_files_switch,         /* -F */
 
174
    module_switch,                  /* -M */
 
175
    runtime_error_checking_switch,  /* -S */
 
176
    define_USE_MODULES_switch,      /* -U */
 
177
    define_INFIX_switch;            /* -X */
 
178
#ifdef ARC_THROWBACK
 
179
int throwback_switch;               /* -T */
 
180
#endif
 
181
#ifdef ARCHIMEDES
 
182
int riscos_file_type_format;        /* set by -R */
 
183
#endif
 
184
int compression_switch;             /* set by -H */
 
185
int character_set_setting,          /* set by -C */
 
186
    error_format,                   /* set by -E */
 
187
    asm_trace_setting,              /* set by -a and -t: value of
 
188
                                       asm_trace_level to use when tracing */
 
189
    double_space_setting,           /* set by -d: 0, 1 or 2 */
 
190
    trace_fns_setting,              /* set by -g: 0, 1 or 2 */
 
191
    linker_trace_setting,           /* set by -y: ditto for linker_... */
 
192
    header_ext_setting,             /* set by -W */
 
193
    store_the_text;                 /* when set, record game text to a chunk
 
194
                                       of memory (used by both -r & -k) */
 
195
static int r_e_c_s_set;             /* has -S been explicitly set? */
 
196
 
 
197
int glulx_mode;                     /* -G */
 
198
 
 
199
static void reset_switch_settings(void)
 
200
{   asm_trace_setting=0;
 
201
    linker_trace_level=0;
 
202
    tokens_trace_level=0;
 
203
 
 
204
    store_the_text = FALSE;
 
205
 
 
206
    bothpasses_switch = FALSE;
 
207
    concise_switch = FALSE;
 
208
    double_space_setting = 0;
 
209
    economy_switch = FALSE;
 
210
    frequencies_switch = FALSE;
 
211
    trace_fns_setting = 0;
 
212
    ignore_switches_switch = FALSE;
 
213
    listobjects_switch = FALSE;
 
214
    debugfile_switch = FALSE;
 
215
    listing_switch = FALSE;
 
216
    memout_switch = FALSE;
 
217
    printprops_switch = FALSE;
 
218
    offsets_switch = FALSE;
 
219
    percentages_switch = FALSE;
 
220
    obsolete_switch = FALSE;
 
221
    transcript_switch = FALSE;
 
222
    statistics_switch = FALSE;
 
223
    optimise_switch = FALSE;
 
224
    version_set_switch = FALSE;
 
225
    nowarnings_switch = FALSE;
 
226
    hash_switch = FALSE;
 
227
    memory_map_switch = FALSE;
 
228
    oddeven_packing_switch = FALSE;
 
229
    define_DEBUG_switch = FALSE;
 
230
#ifdef USE_TEMPORARY_FILES
 
231
    temporary_files_switch = TRUE;
 
232
#else
 
233
    temporary_files_switch = FALSE;
 
234
#endif
 
235
    define_USE_MODULES_switch = FALSE;
 
236
    module_switch = FALSE;
 
237
#ifdef ARC_THROWBACK
 
238
    throwback_switch = FALSE;
 
239
#endif
 
240
    runtime_error_checking_switch = TRUE;
 
241
    r_e_c_s_set = FALSE;
 
242
    define_INFIX_switch = FALSE;
 
243
#ifdef ARCHIMEDES
 
244
    riscos_file_type_format = 0;
 
245
#endif
 
246
    error_format=DEFAULT_ERROR_FORMAT;
 
247
 
 
248
    character_set_setting = 1;                     /* Default is ISO Latin-1 */
 
249
    header_ext_setting = 0;
 
250
 
 
251
    compression_switch = TRUE;
 
252
    glulx_mode = FALSE;
 
253
}
 
254
 
 
255
/* ------------------------------------------------------------------------- */
 
256
/*   Number of files given as command line parameters (0, 1 or 2)            */
 
257
/* ------------------------------------------------------------------------- */
 
258
 
 
259
static int cli_files_specified,
 
260
           convert_filename_flag;
 
261
 
 
262
char Source_Name[PATHLEN];             /* Processed name of first input file */
 
263
char Code_Name[PATHLEN];               /* Processed name of output file      */
 
264
 
 
265
static char *cli_file1, *cli_file2;    /* Unprocessed (and unsafe to alter)  */
 
266
 
 
267
/* ========================================================================= */
 
268
/*   Data structure management routines                                      */
 
269
/* ------------------------------------------------------------------------- */
 
270
 
 
271
static void init_vars(void)
 
272
{
 
273
    init_arrays_vars();
 
274
    init_asm_vars();
 
275
    init_bpatch_vars();
 
276
    init_chars_vars();
 
277
    init_directs_vars();
 
278
    init_errors_vars();
 
279
    init_expressc_vars();
 
280
    init_expressp_vars();
 
281
    init_files_vars();
 
282
    init_lexer_vars();
 
283
    init_linker_vars();
 
284
    init_memory_vars();
 
285
    init_objects_vars();
 
286
    init_states_vars();
 
287
    init_symbols_vars();
 
288
    init_syntax_vars();
 
289
    init_tables_vars();
 
290
    init_text_vars();
 
291
    init_veneer_vars();
 
292
    init_verbs_vars();
 
293
}
 
294
 
 
295
static void begin_pass(void)
 
296
{
 
297
    arrays_begin_pass();
 
298
    asm_begin_pass();
 
299
    bpatch_begin_pass();
 
300
    chars_begin_pass();
 
301
    directs_begin_pass();
 
302
    errors_begin_pass();
 
303
    expressc_begin_pass();
 
304
    expressp_begin_pass();
 
305
    files_begin_pass();
 
306
 
 
307
    endofpass_flag = FALSE;
 
308
    line_trace_level = 0; expr_trace_level = 0;
 
309
    asm_trace_level = asm_trace_setting;
 
310
    linker_trace_level = linker_trace_setting;
 
311
    if (listing_switch) line_trace_level=1;
 
312
 
 
313
    lexer_begin_pass();
 
314
    linker_begin_pass();
 
315
    memory_begin_pass();
 
316
    objects_begin_pass();
 
317
    states_begin_pass();
 
318
    symbols_begin_pass();
 
319
    syntax_begin_pass();
 
320
    tables_begin_pass();
 
321
    text_begin_pass();
 
322
    veneer_begin_pass();
 
323
    verbs_begin_pass();
 
324
 
 
325
    if (!module_switch)
 
326
    {
 
327
        /*  Compile a Main__ routine (see "veneer.c")  */
 
328
 
 
329
        compile_initial_routine();
 
330
 
 
331
        /*  Make the four metaclasses: Class must be object number 1, so
 
332
            it must come first  */
 
333
 
 
334
        veneer_mode = TRUE;
 
335
 
 
336
        make_class("Class");
 
337
        make_class("Object");
 
338
        make_class("Routine");
 
339
        make_class("String");
 
340
 
 
341
        veneer_mode = FALSE;
 
342
    }
 
343
}
 
344
 
 
345
extern void allocate_arrays(void)
 
346
{
 
347
    arrays_allocate_arrays();
 
348
    asm_allocate_arrays();
 
349
    bpatch_allocate_arrays();
 
350
    chars_allocate_arrays();
 
351
    directs_allocate_arrays();
 
352
    errors_allocate_arrays();
 
353
    expressc_allocate_arrays();
 
354
    expressp_allocate_arrays();
 
355
    files_allocate_arrays();
 
356
 
 
357
    lexer_allocate_arrays();
 
358
    linker_allocate_arrays();
 
359
    memory_allocate_arrays();
 
360
    objects_allocate_arrays();
 
361
    states_allocate_arrays();
 
362
    symbols_allocate_arrays();
 
363
    syntax_allocate_arrays();
 
364
    tables_allocate_arrays();
 
365
    text_allocate_arrays();
 
366
    veneer_allocate_arrays();
 
367
    verbs_allocate_arrays();
 
368
}
 
369
 
 
370
extern void free_arrays(void)
 
371
{
 
372
    /*  One array may survive this routine, all_the_text (used to hold
 
373
        game text until the abbreviations optimiser begins work on it): this
 
374
        array (if it was ever allocated) is freed at the top level.          */
 
375
 
 
376
    arrays_free_arrays();
 
377
    asm_free_arrays();
 
378
    bpatch_free_arrays();
 
379
    chars_free_arrays();
 
380
    directs_free_arrays();
 
381
    errors_free_arrays();
 
382
    expressc_free_arrays();
 
383
    expressp_free_arrays();
 
384
    files_free_arrays();
 
385
 
 
386
    lexer_free_arrays();
 
387
    linker_free_arrays();
 
388
    memory_free_arrays();
 
389
    objects_free_arrays();
 
390
    states_free_arrays();
 
391
    symbols_free_arrays();
 
392
    syntax_free_arrays();
 
393
    tables_free_arrays();
 
394
    text_free_arrays();
 
395
    veneer_free_arrays();
 
396
    verbs_free_arrays();
 
397
}
 
398
 
 
399
/* ------------------------------------------------------------------------- */
 
400
/*    Name translation code for filenames                                    */
 
401
/* ------------------------------------------------------------------------- */
 
402
 
 
403
static char Source_Path[PATHLEN];
 
404
static char Include_Path[PATHLEN];
 
405
static char Code_Path[PATHLEN];
 
406
static char Module_Path[PATHLEN];
 
407
static char Temporary_Path[PATHLEN];
 
408
static char current_source_path[PATHLEN];
 
409
       char Debugging_Name[PATHLEN];
 
410
       char Transcript_Name[PATHLEN];
 
411
       char Language_Name[PATHLEN];
 
412
       char Charset_Map[PATHLEN];
 
413
static char ICL_Path[PATHLEN];
 
414
 
 
415
static void set_path_value(char *path, char *value)
 
416
{   int i, j;
 
417
 
 
418
    for (i=0, j=0;;)
 
419
    {   if ((value[j] == FN_ALT) || (value[j] == 0))
 
420
        {   if ((value[j] == FN_ALT)
 
421
                && (path != Source_Path) && (path != Include_Path)
 
422
                && (path != ICL_Path) && (path != Module_Path))
 
423
            {   printf("The character '%c' is used to divide entries in a list \
 
424
of possible locations, and can only be used in the Include_Path, Source_Path, \
 
425
Module_Path or ICL_Path variables. Other paths are for output only.", FN_ALT);
 
426
                exit(1);
 
427
            }
 
428
            if ((path != Debugging_Name) && (path != Transcript_Name)
 
429
                 && (path != Language_Name) && (path != Charset_Map)
 
430
                 && (i>0) && (isalnum(path[i-1]))) path[i++] = FN_SEP;
 
431
            path[i++] = value[j++];
 
432
            if (i == PATHLEN-1) {
 
433
                printf("A specified path is longer than %d characters.\n",
 
434
                    PATHLEN-1);
 
435
                exit(1);
 
436
            }
 
437
            if (value[j-1] == 0) return;
 
438
        }
 
439
        else path[i++] = value[j++];
 
440
    }
 
441
}
 
442
 
 
443
static void set_default_paths(void)
 
444
{
 
445
    set_path_value(Source_Path,     Source_Directory);
 
446
    set_path_value(Include_Path,    Include_Directory);
 
447
    set_path_value(Code_Path,       Code_Directory);
 
448
    set_path_value(Module_Path,     Module_Directory);
 
449
    set_path_value(ICL_Path,        ICL_Directory);
 
450
    set_path_value(Temporary_Path,  Temporary_Directory);
 
451
    set_path_value(Debugging_Name,  Debugging_File);
 
452
    set_path_value(Transcript_Name, Transcript_File);
 
453
    set_path_value(Language_Name,   "English");
 
454
    set_path_value(Charset_Map,     "");
 
455
}
 
456
 
 
457
static void set_path_command(char *command)
 
458
{   int i, j; char *path_to_set = NULL, *new_value;
 
459
    for (i=0; (command[i]!=0) && (command[i]!='=');i++) ;
 
460
 
 
461
    if (command[i]==0) { new_value=command; path_to_set=Include_Path; }
 
462
    else
 
463
    {   char pathname[PATHLEN];
 
464
        if (i>=PATHLEN) i=PATHLEN-1;
 
465
        new_value = command+i+1;
 
466
        for (j=0;j<i;j++)
 
467
            if (isupper(command[j])) pathname[j]=tolower(command[j]);
 
468
            else pathname[j]=command[j];
 
469
        pathname[j]=0;
 
470
 
 
471
        if (strcmp(pathname, "source_path")==0)  path_to_set=Source_Path;
 
472
        if (strcmp(pathname, "include_path")==0) path_to_set=Include_Path;
 
473
        if (strcmp(pathname, "code_path")==0)    path_to_set=Code_Path;
 
474
        if (strcmp(pathname, "module_path")==0)  path_to_set=Module_Path;
 
475
        if (strcmp(pathname, "icl_path")==0)     path_to_set=ICL_Path;
 
476
        if (strcmp(pathname, "temporary_path")==0) path_to_set=Temporary_Path;
 
477
        if (strcmp(pathname, "debugging_name")==0) path_to_set=Debugging_Name;
 
478
        if (strcmp(pathname, "transcript_name")==0) path_to_set=Transcript_Name;
 
479
        if (strcmp(pathname, "language_name")==0) path_to_set=Language_Name;
 
480
        if (strcmp(pathname, "charset_map")==0) path_to_set=Charset_Map;
 
481
 
 
482
        if (path_to_set == NULL)
 
483
        {   printf("No such path setting as \"%s\"\n", pathname);
 
484
            exit(1);
 
485
        }
 
486
    }
 
487
 
 
488
    set_path_value(path_to_set, new_value);
 
489
}
 
490
 
 
491
static int contains_separator(char *name)
 
492
{   int i;
 
493
    for (i=0; name[i]!=0; i++)
 
494
        if (name[i] == FN_SEP) return 1;
 
495
    return 0;
 
496
}
 
497
 
 
498
static int write_translated_name(char *new_name, char *old_name,
 
499
                                 char *prefix_path, int start_pos,
 
500
                                 char *extension)
 
501
{   int x;
 
502
    if (strlen(old_name)+strlen(extension) >= PATHLEN) {
 
503
        printf("One of your filenames is longer than %d characters.\n", PATHLEN);
 
504
        exit(1);
 
505
    }
 
506
    if (prefix_path == NULL)
 
507
    {   sprintf(new_name,"%s%s", old_name, extension);
 
508
        return 0;
 
509
    }
 
510
    strcpy(new_name, prefix_path + start_pos);
 
511
    for (x=0; (new_name[x]!=0) && (new_name[x]!=FN_ALT); x++) ;
 
512
    if (new_name[x] == 0) start_pos = 0; else start_pos += x+1;
 
513
    if (x+strlen(old_name)+strlen(extension) >= PATHLEN) {
 
514
        printf("One of your pathnames is longer than %d characters.\n", PATHLEN);
 
515
        exit(1);
 
516
    }
 
517
    sprintf(new_name + x, "%s%s", old_name, extension);
 
518
    return start_pos;
 
519
}
 
520
 
 
521
#ifdef FILE_EXTENSIONS
 
522
static char *check_extension(char *name, char *extension)
 
523
{   int i;
 
524
 
 
525
    /* If a filename ends in '.', remove the dot and add no file extension: */
 
526
    i = strlen(name)-1;
 
527
    if (name[i] == '.') { name[i]=0; return ""; }
 
528
 
 
529
    /* Remove the new extension if it's already got one: */
 
530
 
 
531
    for (; (i>=0) && (name[i]!=FN_SEP); i--)
 
532
        if (name[i] == '.') return "";
 
533
    return extension;
 
534
}
 
535
#endif
 
536
 
 
537
/* ------------------------------------------------------------------------- */
 
538
/*    Three translation routines have to deal with path variables which may  */
 
539
/*    contain alternative locations separated by the FN_ALT character.       */
 
540
/*    These have the protocol:                                               */
 
541
/*                                                                           */
 
542
/*        int translate_*_filename(int last_value, ...)                      */
 
543
/*                                                                           */
 
544
/*    and should first be called with last_value equal to 0.  If the         */
 
545
/*    translated filename works, fine.  Otherwise, if the returned integer   */
 
546
/*    was zero, the caller knows that no filename works and can issue an     */
 
547
/*    error message.  If it was non-zero, the caller should pass it on as    */
 
548
/*    the last_value again.                                                  */
 
549
/*                                                                           */
 
550
/*    As implemented below, last_value is the position in the path variable  */
 
551
/*    string at which the next directory name to try begins.                 */
 
552
/* ------------------------------------------------------------------------- */
 
553
 
 
554
extern int translate_in_filename(int last_value,
 
555
    char *new_name, char *old_name,
 
556
    int same_directory_flag, int command_line_flag)
 
557
{   char *prefix_path = NULL;
 
558
    char *extension;
 
559
    int add_path_flag = 1;
 
560
    int i;
 
561
 
 
562
    if ((same_directory_flag==0)
 
563
        && (contains_separator(old_name)==1)) add_path_flag=0;
 
564
 
 
565
    if (add_path_flag==1)
 
566
    {   if (command_line_flag == 0)
 
567
        {   /* File is opened as a result of an Include directive */
 
568
 
 
569
            if (same_directory_flag==1)
 
570
                prefix_path = current_source_path;
 
571
            else
 
572
                if (Include_Path[0]!=0) prefix_path = Include_Path;
 
573
        }
 
574
        /* Main file being opened from the command line */
 
575
 
 
576
        else if (Source_Path[0]!=0) prefix_path = Source_Path;
 
577
    }
 
578
 
 
579
#ifdef FILE_EXTENSIONS
 
580
    /* Which file extension is expected? */
 
581
 
 
582
    if ((command_line_flag==1)||(same_directory_flag==1))
 
583
        extension = Source_Extension;
 
584
    else
 
585
        extension = Include_Extension;
 
586
 
 
587
    extension = check_extension(old_name, extension);
 
588
#else
 
589
    extension = "";
 
590
#endif
 
591
 
 
592
    last_value = write_translated_name(new_name, old_name,
 
593
                     prefix_path, last_value, extension);
 
594
 
 
595
    /* Set the "current source path" (for use of Include ">...") */
 
596
 
 
597
    if (command_line_flag==1)
 
598
    {   strcpy(current_source_path, new_name);
 
599
        for (i=strlen(current_source_path)-1;
 
600
             ((i>0)&&(current_source_path[i]!=FN_SEP));i--) ;
 
601
 
 
602
        if (i!=0) current_source_path[i+1] = 0; /* Current file in subdir   */
 
603
        else current_source_path[0] = 0;        /* Current file at root dir */
 
604
    }
 
605
 
 
606
    return last_value;
 
607
}
 
608
 
 
609
extern int translate_link_filename(int last_value,
 
610
    char *new_name, char *old_name)
 
611
{   char *prefix_path = NULL;
 
612
    char *extension;
 
613
 
 
614
    if (contains_separator(old_name)==0)
 
615
        if (Module_Path[0]!=0)
 
616
            prefix_path = Module_Path;
 
617
 
 
618
#ifdef FILE_EXTENSIONS
 
619
    extension = check_extension(old_name, Module_Extension);
 
620
#else
 
621
    extension = "";
 
622
#endif
 
623
 
 
624
    return write_translated_name(new_name, old_name,
 
625
               prefix_path, last_value, extension);
 
626
}
 
627
 
 
628
static int translate_icl_filename(int last_value,
 
629
    char *new_name, char *old_name)
 
630
{   char *prefix_path = NULL;
 
631
    char *extension = "";
 
632
 
 
633
    if (contains_separator(old_name)==0)
 
634
        if (ICL_Path[0]!=0)
 
635
            prefix_path = ICL_Path;
 
636
 
 
637
#ifdef FILE_EXTENSIONS
 
638
    extension = check_extension(old_name, ICL_Extension);
 
639
#endif
 
640
 
 
641
    return write_translated_name(new_name, old_name,
 
642
               prefix_path, last_value, extension);
 
643
}
 
644
 
 
645
extern void translate_out_filename(char *new_name, char *old_name)
 
646
{   char *prefix_path;
 
647
    char *extension = "";
 
648
    int i;
 
649
 
 
650
    /* If !convert_filename_flag, then the old_name is just the <file2>
 
651
       parameter on the Inform command line, which we leave alone. */
 
652
 
 
653
    if (!convert_filename_flag)
 
654
    {   strcpy(new_name, old_name); return;
 
655
    }
 
656
 
 
657
    /* Remove any pathname or extension in <file1>. */
 
658
 
 
659
    if (contains_separator(old_name)==1)
 
660
    {   for (i=strlen(old_name)-1; (i>=0)&&(old_name[i]!=FN_SEP) ;i--) ;
 
661
            if (old_name[i]==FN_SEP) i++;
 
662
        old_name += i;
 
663
    }
 
664
#ifdef FILE_EXTENSIONS
 
665
    for (i=strlen(old_name)-1; (i>=0)&&(old_name[i]!='.') ;i--) ;
 
666
    if (old_name[i] == '.') old_name[i] = 0;
 
667
#endif
 
668
 
 
669
    prefix_path = NULL;
 
670
    if (module_switch)
 
671
    {   extension = Module_Extension;
 
672
        if (Module_Path[0]!=0) prefix_path = Module_Path;
 
673
    }
 
674
    else
 
675
    {
 
676
        if (!glulx_mode) {
 
677
            switch(version_number)
 
678
            {   case 3: extension = Code_Extension;   break;
 
679
                case 4: extension = V4Code_Extension; break;
 
680
                case 5: extension = V5Code_Extension; break;
 
681
                case 6: extension = V6Code_Extension; break;
 
682
                case 7: extension = V7Code_Extension; break;
 
683
                case 8: extension = V8Code_Extension; break;
 
684
            }
 
685
        }
 
686
        else {
 
687
            extension = GlulxCode_Extension;
 
688
        }
 
689
        if (Code_Path[0]!=0) prefix_path = Code_Path;
 
690
    }
 
691
 
 
692
#ifdef FILE_EXTENSIONS
 
693
    extension = check_extension(old_name, extension);
 
694
#endif
 
695
 
 
696
    write_translated_name(new_name, old_name, prefix_path, 0, extension);
 
697
}
 
698
 
 
699
static char *name_or_unset(char *p)
 
700
{   if (p[0]==0) return "(unset)";
 
701
    return p;
 
702
}
 
703
 
 
704
static void help_on_filenames(void)
 
705
{   char old_name[PATHLEN];
 
706
    char new_name[PATHLEN];
 
707
    int save_mm = module_switch, x;
 
708
 
 
709
    module_switch = FALSE;
 
710
 
 
711
    printf("Help information on filenames:\n\n");
 
712
 
 
713
    printf(
 
714
"The command line can take one of two forms:\n\n\
 
715
  inform [commands...] <file1>\n\
 
716
  inform [commands...] <file1> <file2>\n\n\
 
717
Inform translates <file1> into a source file name (see below) for its input.\n\
 
718
<file2> is usually omitted: if so, the output filename is made from <file1>\n\
 
719
by cutting out the name part and translating that (see below).\n\
 
720
If <file2> is given, however, the output filename is set to just <file2>\n\
 
721
(not altered in any way).\n\n");
 
722
 
 
723
    printf(
 
724
"Filenames given in the game source (with commands like Include \"name\" and\n\
 
725
Link \"name\") are also translated by the rules below.\n\n");
 
726
 
 
727
    printf(
 
728
"Rules of translation:\n\n\
 
729
Inform translates plain filenames (such as \"xyzzy\") into full pathnames\n\
 
730
(such as \"adventure%cgames%cxyzzy\") according to the following rules.\n\n\
 
731
1. If the name contains a '%c' character (so it's already a pathname), it\n\
 
732
   isn't changed.\n\n", FN_SEP, FN_SEP, FN_SEP);
 
733
 
 
734
    printf(
 
735
"   [Exception: when the name is given in an Include command using the >\n\
 
736
   form (such as Include \">prologue\"), the \">\" is replaced by the path\n\
 
737
   of the file doing the inclusion");
 
738
#ifdef FILE_EXTENSIONS
 
739
                          printf(" and a suitable file extension is added");
 
740
#endif
 
741
    printf(".]\n\n");
 
742
 
 
743
    printf(
 
744
"   Filenames must never contain double-quotation marks \".  To use filenames\n\
 
745
   which contain spaces, write them in double-quotes: for instance,\n\n\
 
746
   \"inform +code_path=\"Jigsaw Final Version\" jigsaw\".\n\n");
 
747
 
 
748
    printf(
 
749
"2. The file is looked for at a particular \"path\" (the filename of a\n\
 
750
   directory), depending on what kind of file it is.\n\n\
 
751
       File type              Name                Current setting\n\n\
 
752
       Source code (in)       source_path         %s\n\
 
753
       Include file (in)      include_path        %s\n\
 
754
       Story file (out)       code_path           %s\n",
 
755
   name_or_unset(Source_Path), name_or_unset(Include_Path),
 
756
   name_or_unset(Code_Path));
 
757
 
 
758
    printf(
 
759
"       Temporary file (out)   temporary_path      %s\n\
 
760
       ICL command file (in)  icl_path            %s\n\
 
761
       Module (in & out)      module_path         %s\n\n",
 
762
   name_or_unset(Temporary_Path),
 
763
   name_or_unset(ICL_Path), name_or_unset(Module_Path));
 
764
 
 
765
    printf(
 
766
"   If the path is unset, then the current working directory is used (so\n\
 
767
   the filename doesn't change): if, for instance, include_path is set to\n\
 
768
   \"backup%coldlib\" then when \"parser\" is included it is looked for at\n\
 
769
   \"backup%coldlib%cparser\".\n\n\
 
770
   The paths can be set or unset on the Inform command line by, eg,\n\
 
771
   \"inform +code_path=finished jigsaw\" or\n\
 
772
   \"inform +include_path= balances\" (which unsets include_path).\n\n",
 
773
        FN_SEP, FN_SEP, FN_SEP);
 
774
 
 
775
    printf(
 
776
"   The four input path variables can be set to lists of alternative paths\n\
 
777
   separated by '%c' characters: these alternatives are always tried in\n\
 
778
   the order they are specified in, that is, left to right through the text\n\
 
779
   in the path variable.\n\
 
780
   (Modules are written to the first alternative in the module_path list;\n\
 
781
   it is an error to give alternatives at all for purely output paths.)\n\n",
 
782
   FN_ALT);
 
783
 
 
784
#ifdef FILE_EXTENSIONS
 
785
    printf("3. The following file extensions are added:\n\n\
 
786
      Source code:     %s\n\
 
787
      Include files:   %s\n\
 
788
      Story files:     %s (Version 3), %s (v4), %s (v5, the default),\n\
 
789
                       %s (v6), %s (v7), %s (v8), %s (Glulx)\n\
 
790
      Temporary files: .tmp\n\
 
791
      Modules:         %s\n\n",
 
792
      Source_Extension, Include_Extension,
 
793
      Code_Extension, V4Code_Extension, V5Code_Extension, V6Code_Extension,
 
794
      V7Code_Extension, V8Code_Extension, GlulxCode_Extension, 
 
795
      Module_Extension);
 
796
    printf("\
 
797
   except that any extension you give (on the command line or in a filename\n\
 
798
   used in a program) will override these.  If you give the null extension\n\
 
799
   \".\" then Inform uses no file extension at all (removing the \".\").\n\n");
 
800
#endif
 
801
 
 
802
    printf("Names of four individual files can also be set using the same\n\
 
803
  + command notation (though they aren't really pathnames).  These are:\n\n\
 
804
      transcript_name  (text written by -r switch): now \"%s\"\n\
 
805
      debugging_name   (data written by -k switch): now \"%s\"\n\
 
806
      language_name    (library file defining natural language of game):\n\
 
807
                       now \"%s\"\n\
 
808
      charset_map      (file for character set mapping): now \"%s\"\n\n",
 
809
    Transcript_Name, Debugging_Name, Language_Name, Charset_Map);
 
810
 
 
811
    translate_in_filename(0, new_name, "rezrov", 0, 1);
 
812
    printf("Examples: 1. \"inform rezrov\"\n\
 
813
  the source code is read from \"%s\"\n",
 
814
        new_name);
 
815
    convert_filename_flag = TRUE;
 
816
    translate_out_filename(new_name, "rezrov");
 
817
    printf("  and a story file is compiled to \"%s\".\n\n", new_name);
 
818
 
 
819
    translate_in_filename(0, new_name, "frotz", 0, 1);
 
820
    printf("2. \"inform -M frotz\"\n\
 
821
  the source code is read from \"%s\"\n",
 
822
        new_name);
 
823
    module_switch = TRUE;
 
824
    convert_filename_flag = TRUE;
 
825
    translate_out_filename(new_name, "frotz");
 
826
    printf("  and a module is compiled to \"%s\".\n\n", new_name);
 
827
 
 
828
    module_switch = FALSE;
 
829
 
 
830
    sprintf(old_name, "demos%cplugh", FN_SEP);
 
831
    printf("3. \"inform %s\"\n", old_name);
 
832
    translate_in_filename(0, new_name, old_name, 0, 1);
 
833
    printf("  the source code is read from \"%s\"\n", new_name);
 
834
    sprintf(old_name, "demos%cplugh", FN_SEP);
 
835
    convert_filename_flag = TRUE;
 
836
    translate_out_filename(new_name, old_name);
 
837
    printf("  and a story file is compiled to \"%s\".\n\n", new_name);
 
838
 
 
839
    printf("4. \"inform plover my_demo\"\n");
 
840
    translate_in_filename(0, new_name, "plover", 0, 1);
 
841
    printf("  the source code is read from \"%s\"\n", new_name);
 
842
    convert_filename_flag = FALSE;
 
843
    translate_out_filename(new_name, "my_demo");
 
844
    printf("  and a story file is compiled to \"%s\".\n\n", new_name);
 
845
 
 
846
    strcpy(old_name, Source_Path);
 
847
    sprintf(new_name, "%cnew%cold%crecent%cold%cancient",
 
848
        FN_ALT, FN_ALT, FN_SEP, FN_ALT, FN_SEP);
 
849
    printf("5. \"inform +source_path=%s zooge\"\n", new_name);
 
850
    printf(
 
851
"   Note that four alternative paths are given, the first being the empty\n\
 
852
   path-name (meaning: where you are now).  Inform looks for the source code\n\
 
853
   by trying these four places in turn, stopping when it finds anything:\n\n");
 
854
 
 
855
    set_path_value(Source_Path, new_name);
 
856
    x = 0;
 
857
    do
 
858
    {   x = translate_in_filename(x, new_name, "zooge", 0, 1);
 
859
        printf("     \"%s\"\n", new_name);
 
860
    } while (x != 0);
 
861
    strcpy(Source_Path, old_name);
 
862
    module_switch = save_mm;
 
863
}
 
864
 
 
865
/* ------------------------------------------------------------------------- */
 
866
/*  Naming temporary files                                                   */
 
867
/*       (Arguably temporary files should be made using "tmpfile" in         */
 
868
/*        the ANSI C library, but many supposed ANSI libraries lack it.)     */
 
869
/* ------------------------------------------------------------------------- */
 
870
 
 
871
extern void translate_temp_filename(int i)
 
872
{   char *p;
 
873
    switch(i)
 
874
    {   case 1: p=Temp1_Name; break;
 
875
        case 2: p=Temp2_Name; break;
 
876
        case 3: p=Temp3_Name; break;
 
877
    }
 
878
    if (strlen(Temporary_Path)+strlen(Temporary_File)+6 >= PATHLEN) {
 
879
        printf ("Temporary_Path is too long.\n");
 
880
        exit(1);
 
881
    }
 
882
    sprintf(p,"%s%s%d", Temporary_Path, Temporary_File, i);
 
883
#ifdef INCLUDE_TASK_ID
 
884
    sprintf(p+strlen(p), "_proc%08lx", (long int) unique_task_id());
 
885
#endif
 
886
#ifdef FILE_EXTENSIONS
 
887
    sprintf(p+strlen(p), ".tmp");
 
888
#endif
 
889
}
 
890
 
 
891
#ifdef ARCHIMEDES
 
892
static char riscos_ft_buffer[4];
 
893
 
 
894
extern char *riscos_file_type(void)
 
895
{
 
896
    if (riscos_file_type_format == 1)
 
897
    {   if (module_switch) return("data");
 
898
        return("11A");
 
899
    }
 
900
 
 
901
    if (module_switch) return("075");
 
902
 
 
903
    sprintf(riscos_ft_buffer, "%03x", 0x60 + version_number);
 
904
    return(riscos_ft_buffer);
 
905
}
 
906
#endif
 
907
 
 
908
/* ------------------------------------------------------------------------- */
 
909
/*   The compilation pass                                                    */
 
910
/* ------------------------------------------------------------------------- */
 
911
 
 
912
static void run_pass(void)
 
913
{
 
914
    lexer_begin_prepass();
 
915
    files_begin_prepass();
 
916
    load_sourcefile(Source_Name, 0);
 
917
 
 
918
    begin_pass();
 
919
 
 
920
    parse_program(NULL);
 
921
 
 
922
    find_the_actions();
 
923
    issue_unused_warnings();
 
924
    compile_veneer();
 
925
 
 
926
    lexer_endpass();
 
927
    if (module_switch) linker_endpass();
 
928
 
 
929
    close_all_source();
 
930
    if (hash_switch && hash_printed_since_newline) printf("\n");
 
931
 
 
932
    if (temporary_files_switch)
 
933
    {   if (module_switch) flush_link_data();
 
934
        check_temp_files();
 
935
    }
 
936
    sort_dictionary();
 
937
    construct_storyfile();
 
938
}
 
939
 
 
940
int output_has_occurred;
 
941
 
 
942
static void rennab(int32 time_taken)
 
943
{   /*  rennab = reverse of banner  */
 
944
 
 
945
    int t = no_warnings + no_suppressed_warnings;
 
946
 
 
947
    if (memout_switch) print_memory_usage();
 
948
 
 
949
    if ((no_errors + t)!=0)
 
950
    {   printf("Compiled with ");
 
951
        if (no_errors > 0)
 
952
        {   printf("%d error%s", no_errors,(no_errors==1)?"":"s");
 
953
            if (t > 0) printf(" and ");
 
954
        }
 
955
        if (no_warnings > 0)
 
956
            printf("%d warning%s", t, (t==1)?"":"s");
 
957
        if (no_suppressed_warnings > 0)
 
958
        {   if (no_warnings > 0)
 
959
                printf(" (%d suppressed)", no_suppressed_warnings);
 
960
            else
 
961
            printf("%d suppressed warning%s", no_suppressed_warnings,
 
962
                (no_suppressed_warnings==1)?"":"s");
 
963
        }
 
964
        if (output_has_occurred == FALSE) printf(" (no output)");
 
965
        printf("\n");
 
966
    }
 
967
 
 
968
    if (no_compiler_errors > 0) print_sorry_message();
 
969
 
 
970
    if (statistics_switch)
 
971
        printf("Completed in %ld seconds\n", (long int) time_taken);
 
972
}
 
973
 
 
974
/* ------------------------------------------------------------------------- */
 
975
/*   The compiler abstracted to a routine.                                   */
 
976
/* ------------------------------------------------------------------------- */
 
977
 
 
978
static int execute_icl_header(char *file1);
 
979
 
 
980
static int compile(int number_of_files_specified, char *file1, char *file2)
 
981
{   int32 time_start;
 
982
 
 
983
    if (execute_icl_header(file1))
 
984
      return 1;
 
985
 
 
986
    select_target(glulx_mode);
 
987
 
 
988
    if (define_INFIX_switch && glulx_mode) {
 
989
        printf("Infix (-X) facilities are not available in Glulx: \
 
990
disabling -X switch\n");
 
991
        define_INFIX_switch = FALSE;
 
992
    }
 
993
 
 
994
    if (module_switch && glulx_mode) {
 
995
        printf("Modules are not available in Glulx: \
 
996
disabling -M switch\n");
 
997
        module_switch = FALSE;
 
998
    }
 
999
 
 
1000
    if (define_INFIX_switch && module_switch)
 
1001
    {   printf("Infix (-X) facilities are not available when compiling \
 
1002
modules: disabling -X switch\n");
 
1003
        define_INFIX_switch = FALSE;
 
1004
    }
 
1005
    if (runtime_error_checking_switch && module_switch)
 
1006
    {   printf("Strict checking (-S) facilities are not available when \
 
1007
compiling modules: disabling -S switch\n");
 
1008
        runtime_error_checking_switch = FALSE;
 
1009
    }
 
1010
 
 
1011
    time_start=time(0); no_compilations++;
 
1012
 
 
1013
    strcpy(Source_Name, file1); convert_filename_flag = TRUE;
 
1014
    strcpy(Code_Name, file1);
 
1015
    if (number_of_files_specified == 2)
 
1016
    {   strcpy(Code_Name, file2); convert_filename_flag = FALSE;
 
1017
    }
 
1018
 
 
1019
    init_vars();
 
1020
    allocate_arrays();
 
1021
 
 
1022
    if (debugfile_switch) begin_debug_file();
 
1023
    if (transcript_switch) open_transcript_file(Source_Name);
 
1024
 
 
1025
    run_pass();
 
1026
 
 
1027
    if (transcript_switch)
 
1028
    {   write_dictionary_to_transcript();
 
1029
        close_transcript_file();
 
1030
    }
 
1031
 
 
1032
    if (no_errors==0) { output_file(); output_has_occurred = TRUE; }
 
1033
    else { output_has_occurred = FALSE; }
 
1034
 
 
1035
    if (debugfile_switch) close_debug_file();
 
1036
 
 
1037
    if (temporary_files_switch && (no_errors>0)) remove_temp_files();
 
1038
 
 
1039
    free_arrays();
 
1040
 
 
1041
    rennab((int32) (time(0)-time_start));
 
1042
 
 
1043
    if (optimise_switch) optimise_abbreviations();
 
1044
 
 
1045
    if (store_the_text) my_free(&all_text,"transcription text");
 
1046
 
 
1047
    return (no_errors==0)?0:1;
 
1048
}
 
1049
 
 
1050
/* ------------------------------------------------------------------------- */
 
1051
/*   The command line interpreter                                            */
 
1052
/* ------------------------------------------------------------------------- */
 
1053
 
 
1054
static void cli_print_help(int help_level)
 
1055
{
 
1056
    printf(
 
1057
"\nThis program is a compiler of Infocom format (also called \"Z-machine\")\n\
 
1058
story files: copyright (c) Graham Nelson 1993 - 2006.\n\n");
 
1059
 
 
1060
   /* For people typing just "inform", a summary only: */
 
1061
 
 
1062
   if (help_level==0)
 
1063
   {
 
1064
 
 
1065
#ifndef PROMPT_INPUT
 
1066
  printf("Usage: \"inform [commands...] <file1> [<file2>]\"\n\n");
 
1067
#else
 
1068
  printf("When run, Inform prompts you for commands (and switches),\n\
 
1069
which are optional, then an input <file1> and an (optional) output\n\
 
1070
<file2>.\n\n");
 
1071
#endif
 
1072
 
 
1073
  printf(
 
1074
"<file1> is the Inform source file of the game to be compiled. <file2>,\n\
 
1075
if given, overrides the filename Inform would normally use for the\n\
 
1076
compiled output.  Try \"inform -h1\" for file-naming conventions.\n\n\
 
1077
One or more words can be supplied as \"commands\". These may be:\n\n\
 
1078
  -switches     a list of compiler switches, 1 or 2 letter\n\
 
1079
                (see \"inform -h2\" for the full range)\n\n\
 
1080
  +dir          set Include_Path to this directory\n\
 
1081
  +PATH=dir     change the PATH to this directory\n\n\
 
1082
  $...          one of the following memory commands:\n");
 
1083
  printf(
 
1084
"     $list            list current memory allocation settings\n\
 
1085
     $huge            make standard \"huge game\" settings %s\n\
 
1086
     $large           make standard \"large game\" settings %s\n\
 
1087
     $small           make standard \"small game\" settings %s\n\
 
1088
     $?SETTING        explain briefly what SETTING is for\n\
 
1089
     $SETTING=number  change SETTING to given number\n\n\
 
1090
  (filename)    read in a list of commands (in the format above)\n\
 
1091
                from this \"setup file\"\n\n",
 
1092
    (DEFAULT_MEMORY_SIZE==HUGE_SIZE)?"(default)":"",
 
1093
    (DEFAULT_MEMORY_SIZE==LARGE_SIZE)?"(default)":"",
 
1094
    (DEFAULT_MEMORY_SIZE==SMALL_SIZE)?"(default)":"");
 
1095
 
 
1096
#ifndef PROMPT_INPUT
 
1097
    printf("For example: \"inform -dexs $huge curses\".\n\n");
 
1098
#endif
 
1099
 
 
1100
    printf(
 
1101
"For fuller information, see the Inform Designer's Manual.\n");
 
1102
 
 
1103
       return;
 
1104
   }
 
1105
 
 
1106
   /* The -h1 (filenaming) help information: */
 
1107
 
 
1108
   if (help_level == 1) { help_on_filenames(); return; }
 
1109
 
 
1110
   /* The -h2 (switches) help information: */
 
1111
 
 
1112
   printf("Help on the full list of legal switch commands:\n\n\
 
1113
  a   trace assembly-language (without hex dumps; see -t)\n\
 
1114
  c   more concise error messages\n\
 
1115
  d   contract double spaces after full stops in text\n\
 
1116
  d2  contract double spaces after exclamation and question marks, too\n\
 
1117
  e   economy mode (slower): make use of declared abbreviations\n");
 
1118
 
 
1119
   printf("\
 
1120
  f   frequencies mode: show how useful abbreviations are\n\
 
1121
  g   traces calls to functions (except in the library)\n\
 
1122
  g2  traces calls to all functions\n\
 
1123
  h   print this information\n");
 
1124
 
 
1125
   printf("\
 
1126
  i   ignore default switches set within the file\n\
 
1127
  j   list objects as constructed\n\
 
1128
  k   output Infix debugging information to \"%s\" (and switch -D on)\n\
 
1129
  l   list every statement run through Inform\n\
 
1130
  m   say how much memory has been allocated\n\
 
1131
  n   print numbers of properties, attributes and actions\n",
 
1132
          Debugging_Name);
 
1133
   printf("\
 
1134
  o   print offset addresses\n\
 
1135
  p   give percentage breakdown of story file\n\
 
1136
  q   keep quiet about obsolete usages\n\
 
1137
  r   record all the text to \"%s\"\n\
 
1138
  s   give statistics\n\
 
1139
  t   trace assembly-language (with full hex dumps; see -a)\n",
 
1140
      Transcript_Name);
 
1141
 
 
1142
   printf("\
 
1143
  u   work out most useful abbreviations (very very slowly)\n\
 
1144
  v3  compile to version-3 (\"Standard\") story file\n\
 
1145
  v4  compile to version-4 (\"Plus\") story file\n\
 
1146
  v5  compile to version-5 (\"Advanced\") story file: the default\n\
 
1147
  v6  compile to version-6 (graphical) story file\n\
 
1148
  v8  compile to version-8 (expanded \"Advanced\") story file\n\
 
1149
  w   disable warning messages\n\
 
1150
  x   print # for every 100 lines compiled\n\
 
1151
  y   trace linking system\n\
 
1152
  z   print memory map of the Z-machine\n\n");
 
1153
 
 
1154
printf("\
 
1155
  B   use big memory model (for large V6/V7 files)\n\
 
1156
  C0  text character set is plain ASCII only\n\
 
1157
  Cn  text character set is ISO 8859-n (n = 1 to 9)\n\
 
1158
      (1 to 4, Latin1 to Latin4; 5, Cyrillic; 6, Arabic;\n\
 
1159
       7, Greek; 8, Hebrew; 9, Latin5.  Default is -C1.)\n");
 
1160
printf("  D   insert \"Constant DEBUG;\" automatically\n");
 
1161
printf("  E0  Archimedes-style error messages%s\n",
 
1162
      (error_format==0)?" (current setting)":"");
 
1163
printf("  E1  Microsoft-style error messages%s\n",
 
1164
      (error_format==1)?" (current setting)":"");
 
1165
printf("  E2  Macintosh MPW-style error messages%s\n",
 
1166
      (error_format==2)?" (current setting)":"");
 
1167
#ifdef USE_TEMPORARY_FILES
 
1168
printf("  F0  use extra memory rather than temporary files\n");
 
1169
#else
 
1170
printf("  F1  use temporary files to reduce memory consumption\n");
 
1171
#endif
 
1172
printf("  G   compile a Glulx game file\n");
 
1173
printf("  H   use Huffman encoding to compress Glulx strings\n");
 
1174
printf("  M   compile as a Module for future linking\n");
 
1175
 
 
1176
#ifdef ARCHIMEDES
 
1177
printf("\
 
1178
  R0  use filetype 060 + version number for games (default)\n\
 
1179
  R1  use official Acorn filetype 11A for all games\n");
 
1180
#endif
 
1181
printf("  S   compile strict error-checking at run-time (on by default)\n");
 
1182
#ifdef ARC_THROWBACK
 
1183
printf("  T   enable throwback of errors in the DDE\n");
 
1184
#endif
 
1185
printf("  U   insert \"Constant USE_MODULES;\" automatically\n");
 
1186
printf("  Wn  header extension table is at least n words (n = 3 to 99)\n");
 
1187
printf("  X   compile with INFIX debugging facilities present\n");
 
1188
  printf("\n");
 
1189
}
 
1190
 
 
1191
extern void switches(char *p, int cmode)
 
1192
{   int i, s=1, state;
 
1193
    /* Here cmode is 0 if switches list is from a "Switches" directive
 
1194
       and 1 if from a "-switches" command-line or ICL list */
 
1195
 
 
1196
    if (cmode==1)
 
1197
    {   if (p[0]!='-')
 
1198
        {   printf(
 
1199
                "Ignoring second word which should be a -list of switches.\n");
 
1200
            return;
 
1201
        }
 
1202
    }
 
1203
    for (i=cmode; p[i]!=0; i+=s, s=1)
 
1204
    {   state = TRUE;
 
1205
        if (p[i] == '~')
 
1206
        {   state = FALSE;
 
1207
            i++;
 
1208
        }
 
1209
        switch(p[i])
 
1210
        {
 
1211
        case 'a': asm_trace_setting = 1; break;
 
1212
        case 'b': bothpasses_switch = state; break;
 
1213
        case 'c': concise_switch = state; break;
 
1214
        case 'd': switch(p[i+1])
 
1215
                  {   case '1': double_space_setting=1; s=2; break;
 
1216
                      case '2': double_space_setting=2; s=2; break;
 
1217
                      default: double_space_setting=1; break;
 
1218
                  }
 
1219
                  break;
 
1220
        case 'e': economy_switch = state; break;
 
1221
        case 'f': frequencies_switch = state; break;
 
1222
        case 'g': switch(p[i+1])
 
1223
                  {   case '1': trace_fns_setting=1; s=2; break;
 
1224
                      case '2': trace_fns_setting=2; s=2; break;
 
1225
                      default: trace_fns_setting=1; break;
 
1226
                  }
 
1227
                  break;
 
1228
        case 'h': switch(p[i+1])
 
1229
                  {   case '1': cli_print_help(1); s=2; break;
 
1230
                      case '2': cli_print_help(2); s=2; break;
 
1231
                      case '0': s=2;
 
1232
                      default:  cli_print_help(0); break;
 
1233
                  }
 
1234
                  break;
 
1235
        case 'i': ignore_switches_switch = state; break;
 
1236
        case 'j': listobjects_switch = state; break;
 
1237
        case 'k': if (cmode == 0)
 
1238
                      error("The switch '-k' can't be set with 'Switches'");
 
1239
                  else
 
1240
                  {   debugfile_switch = state;
 
1241
                      if (state) define_DEBUG_switch = TRUE;
 
1242
                  }
 
1243
                  break;
 
1244
        case 'l': listing_switch = state; break;
 
1245
        case 'm': memout_switch = state; break;
 
1246
        case 'n': printprops_switch = state; break;
 
1247
        case 'o': offsets_switch = state; break;
 
1248
        case 'p': percentages_switch = state; break;
 
1249
        case 'q': obsolete_switch = state; break;
 
1250
        case 'r': if (cmode == 0)
 
1251
                      error("The switch '-r' can't be set with 'Switches'");
 
1252
                  else
 
1253
                      transcript_switch = state; break;
 
1254
        case 's': statistics_switch = state; break;
 
1255
        case 't': asm_trace_setting=2; break;
 
1256
        case 'u': optimise_switch = state; break;
 
1257
        case 'v': if ((cmode==0) && (version_set_switch)) { s=2; break; }
 
1258
                  version_set_switch = TRUE; s=2;
 
1259
                  switch(p[i+1])
 
1260
                  {   case '3': select_version(3); break;
 
1261
                      case '4': select_version(4); break;
 
1262
                      case '5': select_version(5); break;
 
1263
                      case '6': select_version(6); break;
 
1264
                      case '7': select_version(7); break;
 
1265
                      case '8': select_version(8); break;
 
1266
                      default:  printf("-v must be followed by 3 to 8\n");
 
1267
                                version_set_switch=0; s=1;
 
1268
                                break;
 
1269
                  }
 
1270
                  break;
 
1271
        case 'w': nowarnings_switch = state; break;
 
1272
        case 'x': hash_switch = state; break;
 
1273
        case 'y': s=2; linker_trace_setting=p[i+1]-'0'; break;
 
1274
        case 'z': memory_map_switch = state; break;
 
1275
        case 'B': oddeven_packing_switch = state; break;
 
1276
        case 'C': s=2; character_set_setting=p[i+1]-'0';
 
1277
                  if ((character_set_setting < 0)
 
1278
                      || (character_set_setting > 9))
 
1279
                  {   printf("-C must be followed by 0 to 9\n");
 
1280
                      character_set_setting = 1;
 
1281
                  }
 
1282
                  if (cmode == 0) change_character_set();
 
1283
                  break;
 
1284
        case 'D': define_DEBUG_switch = state; break;
 
1285
        case 'E': switch(p[i+1])
 
1286
                  {   case '0': s=2; error_format=0; break;
 
1287
                      case '1': s=2; error_format=1; break;
 
1288
                      case '2': s=2; error_format=2; break;
 
1289
                      default:  error_format=1; break;
 
1290
                  }
 
1291
                  break;
 
1292
        case 'F': switch(p[i+1])
 
1293
                  {   case '0': s=2; temporary_files_switch = FALSE; break;
 
1294
                      case '1': s=2; temporary_files_switch = TRUE; break;
 
1295
                      default:  temporary_files_switch = state; break;
 
1296
                  }
 
1297
                  break;
 
1298
        case 'M': module_switch = state;
 
1299
                  if (state && (r_e_c_s_set == FALSE))
 
1300
                      runtime_error_checking_switch = FALSE;
 
1301
                  break;
 
1302
#ifdef ARCHIMEDES
 
1303
        case 'R': switch(p[i+1])
 
1304
                  {   case '0': s=2; riscos_file_type_format=0; break;
 
1305
                      case '1': s=2; riscos_file_type_format=1; break;
 
1306
                      default:  riscos_file_type_format=1; break;
 
1307
                  }
 
1308
                  break;
 
1309
#endif
 
1310
#ifdef ARC_THROWBACK
 
1311
        case 'T': throwback_switch = state; break;
 
1312
#endif
 
1313
        case 'S': runtime_error_checking_switch = state;
 
1314
                  r_e_c_s_set = TRUE; break;
 
1315
        case 'G': if (cmode == 0)
 
1316
                      error("The switch '-G' can't be set with 'Switches'");
 
1317
                  else
 
1318
                  {   glulx_mode = state; /* ###- */
 
1319
                      adjust_memory_sizes();
 
1320
                  }
 
1321
                  break;
 
1322
        case 'H': compression_switch = state; break;
 
1323
        case 'U': define_USE_MODULES_switch = state; break;
 
1324
        case 'W': if ((p[i+1]>='0') && (p[i+1]<='9'))
 
1325
                  {   s=2; header_ext_setting = p[i+1]-'0';
 
1326
                      if ((p[i+2]>='0') && (p[i+2]<='9'))
 
1327
                      {   s=3; header_ext_setting *= 10;
 
1328
                          header_ext_setting += p[i+2]-'0';
 
1329
                      }
 
1330
                  }
 
1331
                  break;
 
1332
        case 'X': define_INFIX_switch = state; break;
 
1333
        default:
 
1334
          printf("Switch \"-%c\" unknown (try \"inform -h2\" for the list)\n",
 
1335
              p[i]);
 
1336
          break;
 
1337
        }
 
1338
    }
 
1339
 
 
1340
    if (optimise_switch && (!store_the_text))
 
1341
    {   store_the_text=TRUE;
 
1342
#ifdef PC_QUICKC
 
1343
        if (memout_switch)
 
1344
            printf("Allocation %ld bytes for transcription text\n",
 
1345
                (long) MAX_TRANSCRIPT_SIZE);
 
1346
        all_text = halloc(MAX_TRANSCRIPT_SIZE,1);
 
1347
        malloced_bytes += MAX_TRANSCRIPT_SIZE;
 
1348
        if (all_text==NULL)
 
1349
         fatalerror("Can't hallocate memory for transcription text.  Darn.");
 
1350
#else
 
1351
        all_text=my_malloc(MAX_TRANSCRIPT_SIZE,"transcription text");
 
1352
#endif
 
1353
    }
 
1354
}
 
1355
 
 
1356
static int icl_command(char *p)
 
1357
{   if ((p[0]=='+')||(p[0]=='-')||(p[0]=='$')
 
1358
        || ((p[0]=='(')&&(p[strlen(p)-1]==')')) ) return TRUE;
 
1359
    return FALSE;
 
1360
}
 
1361
 
 
1362
static void icl_error(char *filename, int line)
 
1363
{   printf("Error in ICL file '%s', line %d:\n", filename, line);
 
1364
}
 
1365
 
 
1366
static void icl_header_error(char *filename, int line)
 
1367
{   printf("Error in ICL header of file '%s', line %d:\n", filename, line);
 
1368
}
 
1369
 
 
1370
static int copy_icl_word(char *from, char *to, int max)
 
1371
{
 
1372
    /*  Copies one token from 'from' to 'to', null-terminated:
 
1373
        returns the number of chars in 'from' read past (possibly 0).  */
 
1374
 
 
1375
    int i, j, quoted_mode, truncated;
 
1376
 
 
1377
    i = 0; truncated = 0;
 
1378
    while ((from[i] == ' ') || (from[i] == TAB_CHARACTER)
 
1379
           || (from[i] == (char) 10) || (from[i] == (char) 13)) i++;
 
1380
 
 
1381
    if (from[i] == '!')
 
1382
    {   while (from[i] != 0) i++;
 
1383
        to[0] = 0; return i;
 
1384
    }
 
1385
 
 
1386
    for (quoted_mode = FALSE, j=0;;)
 
1387
    {   if (from[i] == 0) break;
 
1388
        if (from[i] == 10) break;
 
1389
        if (from[i] == 13) break;
 
1390
        if (from[i] == TAB_CHARACTER) break;
 
1391
        if ((from[i] == ' ') && (!quoted_mode)) break;
 
1392
        if (from[i] == '\"') { quoted_mode = !quoted_mode; i++; }
 
1393
        else to[j++] = from[i++];
 
1394
        if (j == max) {
 
1395
            j--;
 
1396
            truncated = 1;
 
1397
        }
 
1398
    }
 
1399
    to[j] = 0;
 
1400
    if (truncated == 1)
 
1401
        printf("The following parameter has been truncated:\n%s\n", to);
 
1402
    return i;
 
1403
}
 
1404
 
 
1405
static void execute_icl_command(char *p);
 
1406
 
 
1407
static int execute_icl_header(char *argname)
 
1408
{
 
1409
  FILE *command_file;
 
1410
  char cli_buff[256], fw[256];
 
1411
  int line = 0;
 
1412
  int errcount = 0;
 
1413
  int i;
 
1414
  char filename[PATHLEN]; 
 
1415
  int x = 0;
 
1416
 
 
1417
  do
 
1418
    {   x = translate_in_filename(x, filename, argname, 0, 1);
 
1419
        command_file = fopen(filename,"r");
 
1420
    } while ((command_file == NULL) && (x != 0));
 
1421
  if (!command_file) {
 
1422
    /* Fail silently. The regular compiler will try to open the file
 
1423
       again, and report the problem. */
 
1424
    return 0;
 
1425
  }
 
1426
 
 
1427
  while (feof(command_file)==0) {
 
1428
    if (fgets(cli_buff,256,command_file)==0) break;
 
1429
    line++;
 
1430
    if (!(cli_buff[0] == '!' && cli_buff[1] == '%'))
 
1431
      break;
 
1432
    i = copy_icl_word(cli_buff+2, fw, 256);
 
1433
    if (icl_command(fw)) {
 
1434
      execute_icl_command(fw);
 
1435
      copy_icl_word(cli_buff+2 + i, fw, 256);
 
1436
      if ((fw[0] != 0) && (fw[0] != '!')) {
 
1437
        icl_header_error(filename, line);
 
1438
        errcount++;
 
1439
        printf("expected comment or nothing but found '%s'\n", fw);
 
1440
      }
 
1441
    }
 
1442
    else {
 
1443
      if (fw[0]!=0) {
 
1444
        icl_header_error(filename, line);
 
1445
        errcount++;
 
1446
        printf("Expected command or comment but found '%s'\n", fw);
 
1447
      }
 
1448
    }
 
1449
  }
 
1450
  fclose(command_file);
 
1451
 
 
1452
  return (errcount==0)?0:1;
 
1453
}
 
1454
 
 
1455
 
 
1456
static void run_icl_file(char *filename, FILE *command_file)
 
1457
{   char cli_buff[256], fw[256];
 
1458
    int i, x, line = 0;
 
1459
    printf("[Running ICL file '%s']\n", filename);
 
1460
 
 
1461
    while (feof(command_file)==0)
 
1462
    {   if (fgets(cli_buff,256,command_file)==0) break;
 
1463
        line++;
 
1464
        i = copy_icl_word(cli_buff, fw, 256);
 
1465
        if (icl_command(fw))
 
1466
        {   execute_icl_command(fw);
 
1467
            copy_icl_word(cli_buff + i, fw, 256);
 
1468
            if ((fw[0] != 0) && (fw[0] != '!'))
 
1469
            {   icl_error(filename, line);
 
1470
                printf("expected comment or nothing but found '%s'\n", fw);
 
1471
            }
 
1472
        }
 
1473
        else
 
1474
        {   if (strcmp(fw, "compile")==0)
 
1475
            {   char story_name[PATHLEN], code_name[PATHLEN];
 
1476
                i += copy_icl_word(cli_buff + i, story_name, PATHLEN);
 
1477
                i += copy_icl_word(cli_buff + i, code_name, PATHLEN);
 
1478
 
 
1479
                if (code_name[0] != 0) x=2;
 
1480
                else if (story_name[0] != 0) x=1;
 
1481
                else x=0;
 
1482
 
 
1483
                switch(x)
 
1484
                {   case 0: icl_error(filename, line);
 
1485
                            printf("No filename given to 'compile'\n");
 
1486
                            break;
 
1487
                    case 1: printf("[Compiling <%s>]\n", story_name);
 
1488
                            compile(x, story_name, code_name);
 
1489
                            break;
 
1490
                    case 2: printf("[Compiling <%s> to <%s>]\n",
 
1491
                                story_name, code_name);
 
1492
                            compile(x, story_name, code_name);
 
1493
                            copy_icl_word(cli_buff + i, fw, 256);
 
1494
                            if (fw[0]!=0)
 
1495
                            {   icl_error(filename, line);
 
1496
                        printf("Expected comment or nothing but found '%s'\n",
 
1497
                                fw);
 
1498
                            }
 
1499
                            break;
 
1500
                }
 
1501
            }
 
1502
            else
 
1503
            if (fw[0]!=0)
 
1504
            {   icl_error(filename, line);
 
1505
                printf("Expected command or comment but found '%s'\n", fw);
 
1506
            }
 
1507
        }
 
1508
    }
 
1509
}
 
1510
 
 
1511
static void execute_icl_command(char *p)
 
1512
{   char filename[PATHLEN], cli_buff[256];
 
1513
    FILE *command_file;
 
1514
 
 
1515
    switch(p[0])
 
1516
    {   case '+': set_path_command(p+1); break;
 
1517
        case '-': switches(p,1); break;
 
1518
        case '$': memory_command(p+1); break;
 
1519
        case '(': strcpy(cli_buff,p+1); cli_buff[strlen(cli_buff)-1]=0;
 
1520
                  {   int x = 0;
 
1521
                      do
 
1522
                      {   x = translate_icl_filename(x, filename, cli_buff);
 
1523
                          command_file = fopen(filename,"r");
 
1524
                      } while ((command_file == NULL) && (x != 0));
 
1525
                  }
 
1526
                  if (command_file == NULL)
 
1527
                      printf("Error in ICL: Couldn't open command file '%s'\n",
 
1528
                          filename);
 
1529
                  else
 
1530
                  {   run_icl_file(filename, command_file);
 
1531
                      fclose(command_file);
 
1532
                  }
 
1533
                  break;
 
1534
    }
 
1535
}
 
1536
 
 
1537
/* ------------------------------------------------------------------------- */
 
1538
/*   Opening and closing banners                                             */
 
1539
/* ------------------------------------------------------------------------- */
 
1540
 
 
1541
char banner_line[80];
 
1542
 
 
1543
static void banner(void)
 
1544
{
 
1545
    sprintf(banner_line, "Inform %d.%d%d",
 
1546
        (VNUMBER/100)%10, (VNUMBER/10)%10, VNUMBER%10);
 
1547
    if (0) {
 
1548
        sprintf(banner_line+strlen(banner_line), " (biplatform, G%d.%d%d)",
 
1549
            (GLULX_RELEASE_NUMBER/100)%10, (GLULX_RELEASE_NUMBER/10)%10, 
 
1550
            GLULX_RELEASE_NUMBER%10);
 
1551
    }
 
1552
#ifdef MACHINE_STRING
 
1553
    sprintf(banner_line+strlen(banner_line), " for %s", MACHINE_STRING);
 
1554
#endif
 
1555
    sprintf(banner_line+strlen(banner_line), " (%s)",
 
1556
        RELEASE_DATE);
 
1557
    printf("%s\n", banner_line);
 
1558
}
 
1559
 
 
1560
/* ------------------------------------------------------------------------- */
 
1561
/*   Input from the outside world                                            */
 
1562
/* ------------------------------------------------------------------------- */
 
1563
 
 
1564
#ifdef PROMPT_INPUT
 
1565
static void read_command_line(int argc, char **argv)
 
1566
{   int i;
 
1567
    char buffer1[PATHLEN], buffer2[PATHLEN], buffer3[PATHLEN];
 
1568
    i=0;
 
1569
    printf("Source filename?\n> ");
 
1570
    while (gets(buffer1)==NULL); cli_file1=buffer1;
 
1571
    printf("Output filename (RETURN for the same)?\n> ");
 
1572
    while (gets(buffer2)==NULL); cli_file2=buffer2;
 
1573
    cli_files_specified=1;
 
1574
    if (buffer2[0]!=0) cli_files_specified=2;
 
1575
    do
 
1576
    {   printf("List of commands (RETURN to finish; \"-h\" for help)?\n> ");
 
1577
        while (gets(buffer3)==NULL); execute_icl_command(buffer3);
 
1578
    } while (buffer3[0]!=0);
 
1579
}
 
1580
#else
 
1581
static void read_command_line(int argc, char **argv)
 
1582
{   int i;
 
1583
    if (argc==1) switches("-h",1);
 
1584
 
 
1585
    for (i=1, cli_files_specified=0; i<argc; i++)
 
1586
        if (icl_command(argv[i]))
 
1587
            execute_icl_command(argv[i]);
 
1588
        else
 
1589
            switch(++cli_files_specified)
 
1590
            {   case 1: cli_file1 = argv[i]; break;
 
1591
                case 2: cli_file2 = argv[i]; break;
 
1592
                default:
 
1593
                    printf("Command line error: unknown parameter '%s'\n",
 
1594
                        argv[i]); return;
 
1595
            }
 
1596
}
 
1597
#endif
 
1598
 
 
1599
/* ------------------------------------------------------------------------- */
 
1600
/*   M A I N : An outer shell for machine-specific quirks                    */
 
1601
/*   Omitted altogether if EXTERNAL_SHELL is defined, as for instance is     */
 
1602
/*   needed for the Macintosh front end.                                     */
 
1603
/* ------------------------------------------------------------------------- */
 
1604
 
 
1605
#ifdef EXTERNAL_SHELL
 
1606
extern int sub_main(int argc, char **argv);
 
1607
#else
 
1608
 
 
1609
static int sub_main(int argc, char **argv);
 
1610
#ifdef MAC_MPW
 
1611
int main(int argc, char **argv, char *envp[])
 
1612
#else
 
1613
int main(int argc, char **argv)
 
1614
#endif
 
1615
{   int rcode;
 
1616
#ifdef MAC_MPW
 
1617
    InitCursorCtl((acurHandle)NULL); Show_Cursor(WATCH_CURSOR);
 
1618
#endif
 
1619
    rcode = sub_main(argc, argv);
 
1620
#ifdef ARC_THROWBACK
 
1621
    throwback_end();
 
1622
#endif
 
1623
    return rcode;
 
1624
}
 
1625
 
 
1626
#endif
 
1627
 
 
1628
/* ------------------------------------------------------------------------- */
 
1629
/*   M A I N  II:  Starting up ICL with the command line                     */
 
1630
/* ------------------------------------------------------------------------- */
 
1631
 
 
1632
#ifdef EXTERNAL_SHELL
 
1633
extern int sub_main(int argc, char **argv)
 
1634
#else
 
1635
static int sub_main(int argc, char **argv)
 
1636
#endif
 
1637
{   int return_code;
 
1638
 
 
1639
#ifdef MAC_FACE
 
1640
    ProcessEvents (&g_proc);
 
1641
    if (g_proc != true)
 
1642
    {   free_arrays();
 
1643
        if (store_the_text) my_free(&all_text,"transcription text");
 
1644
        longjmp (g_fallback, 1);
 
1645
    }
 
1646
#endif
 
1647
 
 
1648
    banner();
 
1649
 
 
1650
    set_memory_sizes(DEFAULT_MEMORY_SIZE); set_default_paths();
 
1651
    reset_switch_settings(); select_version(5);
 
1652
 
 
1653
    cli_files_specified = 0; no_compilations = 0;
 
1654
    cli_file1 = "source"; cli_file2 = "output";
 
1655
 
 
1656
    read_command_line(argc, argv);
 
1657
 
 
1658
    if (cli_files_specified > 0)
 
1659
    {   return_code = compile(cli_files_specified, cli_file1, cli_file2);
 
1660
 
 
1661
        if (return_code != 0) return(return_code);
 
1662
    }
 
1663
 
 
1664
    if (no_compilations == 0)
 
1665
        printf("\n[No compilation requested]\n");
 
1666
    if (no_compilations > 1)
 
1667
        printf("[%d compilations completed]\n", no_compilations);
 
1668
 
 
1669
    return(0);
 
1670
}
 
1671
 
 
1672
/* ========================================================================= */