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

« back to all changes in this revision

Viewing changes to 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.30                                                     */
6
 
/*   copyright (c) Graham Nelson 1993 - 2004                                 */
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[100];                 /* Processed name of first input file */
263
 
char Code_Name[100];                   /* 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 (value[j-1] == 0) return;
433
 
        }
434
 
        else path[i++] = value[j++];
435
 
    }
436
 
}
437
 
 
438
 
static void set_default_paths(void)
439
 
{
440
 
    set_path_value(Source_Path,     Source_Directory);
441
 
    set_path_value(Include_Path,    Include_Directory);
442
 
    set_path_value(Code_Path,       Code_Directory);
443
 
    set_path_value(Module_Path,     Module_Directory);
444
 
    set_path_value(ICL_Path,        ICL_Directory);
445
 
    set_path_value(Temporary_Path,  Temporary_Directory);
446
 
    set_path_value(Debugging_Name,  Debugging_File);
447
 
    set_path_value(Transcript_Name, Transcript_File);
448
 
    set_path_value(Language_Name,   "English");
449
 
    set_path_value(Charset_Map,     "");
450
 
}
451
 
 
452
 
static void set_path_command(char *command)
453
 
{   int i, j; char *path_to_set = NULL, *new_value;
454
 
    for (i=0; (command[i]!=0) && (command[i]!='=');i++) ;
455
 
 
456
 
    if (command[i]==0) { new_value=command; path_to_set=Include_Path; }
457
 
    else
458
 
    {   char pathname[PATHLEN];
459
 
        if (i>=PATHLEN) i=PATHLEN-1;
460
 
        new_value = command+i+1;
461
 
        for (j=0;j<i;j++)
462
 
            if (isupper(command[j])) pathname[j]=tolower(command[j]);
463
 
            else pathname[j]=command[j];
464
 
        pathname[j]=0;
465
 
 
466
 
        if (strcmp(pathname, "source_path")==0)  path_to_set=Source_Path;
467
 
        if (strcmp(pathname, "include_path")==0) path_to_set=Include_Path;
468
 
        if (strcmp(pathname, "code_path")==0)    path_to_set=Code_Path;
469
 
        if (strcmp(pathname, "module_path")==0)  path_to_set=Module_Path;
470
 
        if (strcmp(pathname, "icl_path")==0)     path_to_set=ICL_Path;
471
 
        if (strcmp(pathname, "temporary_path")==0) path_to_set=Temporary_Path;
472
 
        if (strcmp(pathname, "debugging_name")==0) path_to_set=Debugging_Name;
473
 
        if (strcmp(pathname, "transcript_name")==0) path_to_set=Transcript_Name;
474
 
        if (strcmp(pathname, "language_name")==0) path_to_set=Language_Name;
475
 
        if (strcmp(pathname, "charset_map")==0) path_to_set=Charset_Map;
476
 
 
477
 
        if (path_to_set == NULL)
478
 
        {   printf("No such path setting as \"%s\"\n", pathname);
479
 
            exit(1);
480
 
        }
481
 
    }
482
 
 
483
 
    set_path_value(path_to_set, new_value);
484
 
}
485
 
 
486
 
static int contains_separator(char *name)
487
 
{   int i;
488
 
    for (i=0; name[i]!=0; i++)
489
 
        if (name[i] == FN_SEP) return 1;
490
 
    return 0;
491
 
}
492
 
 
493
 
static int write_translated_name(char *new_name, char *old_name,
494
 
                                 char *prefix_path, int start_pos,
495
 
                                 char *extension)
496
 
{   int x;
497
 
    if (prefix_path == NULL)
498
 
    {   sprintf(new_name,"%s%s", old_name, extension);
499
 
        return 0;
500
 
    }
501
 
    strcpy(new_name, prefix_path + start_pos);
502
 
    for (x=0; (new_name[x]!=0) && (new_name[x]!=FN_ALT); x++) ;
503
 
    if (new_name[x] == 0) start_pos = 0; else start_pos += x+1;
504
 
    sprintf(new_name + x, "%s%s", old_name, extension);
505
 
    return start_pos;
506
 
}
507
 
 
508
 
#ifdef FILE_EXTENSIONS
509
 
static char *check_extension(char *name, char *extension)
510
 
{   int i;
511
 
 
512
 
    /* If a filename ends in '.', remove the dot and add no file extension: */
513
 
    i = strlen(name)-1;
514
 
    if (name[i] == '.') { name[i]=0; return ""; }
515
 
 
516
 
    /* Remove the new extension if it's already got one: */
517
 
 
518
 
    for (; (i>=0) && (name[i]!=FN_SEP); i--)
519
 
        if (name[i] == '.') return "";
520
 
    return extension;
521
 
}
522
 
#endif
523
 
 
524
 
/* ------------------------------------------------------------------------- */
525
 
/*    Three translation routines have to deal with path variables which may  */
526
 
/*    contain alternative locations separated by the FN_ALT character.       */
527
 
/*    These have the protocol:                                               */
528
 
/*                                                                           */
529
 
/*        int translate_*_filename(int last_value, ...)                      */
530
 
/*                                                                           */
531
 
/*    and should first be called with last_value equal to 0.  If the         */
532
 
/*    translated filename works, fine.  Otherwise, if the returned integer   */
533
 
/*    was zero, the caller knows that no filename works and can issue an     */
534
 
/*    error message.  If it was non-zero, the caller should pass it on as    */
535
 
/*    the last_value again.                                                  */
536
 
/*                                                                           */
537
 
/*    As implemented below, last_value is the position in the path variable  */
538
 
/*    string at which the next directory name to try begins.                 */
539
 
/* ------------------------------------------------------------------------- */
540
 
 
541
 
extern int translate_in_filename(int last_value,
542
 
    char *new_name, char *old_name,
543
 
    int same_directory_flag, int command_line_flag)
544
 
{   char *prefix_path = NULL;
545
 
    char *extension;
546
 
    int add_path_flag = 1;
547
 
    int i;
548
 
 
549
 
    if ((same_directory_flag==0)
550
 
        && (contains_separator(old_name)==1)) add_path_flag=0;
551
 
 
552
 
    if (add_path_flag==1)
553
 
    {   if (command_line_flag == 0)
554
 
        {   /* File is opened as a result of an Include directive */
555
 
 
556
 
            if (same_directory_flag==1)
557
 
                prefix_path = current_source_path;
558
 
            else
559
 
                if (Include_Path[0]!=0) prefix_path = Include_Path;
560
 
        }
561
 
        /* Main file being opened from the command line */
562
 
 
563
 
        else if (Source_Path[0]!=0) prefix_path = Source_Path;
564
 
    }
565
 
 
566
 
#ifdef FILE_EXTENSIONS
567
 
    /* Which file extension is expected? */
568
 
 
569
 
    if ((command_line_flag==1)||(same_directory_flag==1))
570
 
        extension = Source_Extension;
571
 
    else
572
 
        extension = Include_Extension;
573
 
 
574
 
    extension = check_extension(old_name, extension);
575
 
#else
576
 
    extension = "";
577
 
#endif
578
 
 
579
 
    last_value = write_translated_name(new_name, old_name,
580
 
                     prefix_path, last_value, extension);
581
 
 
582
 
    /* Set the "current source path" (for use of Include ">...") */
583
 
 
584
 
    if (command_line_flag==1)
585
 
    {   strcpy(current_source_path, new_name);
586
 
        for (i=strlen(current_source_path)-1;
587
 
             ((i>0)&&(current_source_path[i]!=FN_SEP));i--) ;
588
 
 
589
 
        if (i!=0) current_source_path[i+1] = 0; /* Current file in subdir   */
590
 
        else current_source_path[0] = 0;        /* Current file at root dir */
591
 
    }
592
 
 
593
 
    return last_value;
594
 
}
595
 
 
596
 
extern int translate_link_filename(int last_value,
597
 
    char *new_name, char *old_name)
598
 
{   char *prefix_path = NULL;
599
 
    char *extension;
600
 
 
601
 
    if (contains_separator(old_name)==0)
602
 
        if (Module_Path[0]!=0)
603
 
            prefix_path = Module_Path;
604
 
 
605
 
#ifdef FILE_EXTENSIONS
606
 
    extension = check_extension(old_name, Module_Extension);
607
 
#else
608
 
    extension = "";
609
 
#endif
610
 
 
611
 
    return write_translated_name(new_name, old_name,
612
 
               prefix_path, last_value, extension);
613
 
}
614
 
 
615
 
static int translate_icl_filename(int last_value,
616
 
    char *new_name, char *old_name)
617
 
{   char *prefix_path = NULL;
618
 
    char *extension = "";
619
 
 
620
 
    if (contains_separator(old_name)==0)
621
 
        if (ICL_Path[0]!=0)
622
 
            prefix_path = ICL_Path;
623
 
 
624
 
#ifdef FILE_EXTENSIONS
625
 
    extension = check_extension(old_name, ICL_Extension);
626
 
#endif
627
 
 
628
 
    return write_translated_name(new_name, old_name,
629
 
               prefix_path, last_value, extension);
630
 
}
631
 
 
632
 
extern void translate_out_filename(char *new_name, char *old_name)
633
 
{   char *prefix_path;
634
 
    char *extension = "";
635
 
    int i;
636
 
 
637
 
    /* If !convert_filename_flag, then the old_name is just the <file2>
638
 
       parameter on the Inform command line, which we leave alone. */
639
 
 
640
 
    if (!convert_filename_flag)
641
 
    {   strcpy(new_name, old_name); return;
642
 
    }
643
 
 
644
 
    /* Remove any pathname or extension in <file1>. */
645
 
 
646
 
    if (contains_separator(old_name)==1)
647
 
    {   for (i=strlen(old_name)-1; (i>=0)&&(old_name[i]!=FN_SEP) ;i--) ;
648
 
            if (old_name[i]==FN_SEP) i++;
649
 
        old_name += i;
650
 
    }
651
 
#ifdef FILE_EXTENSIONS
652
 
    for (i=strlen(old_name)-1; (i>=0)&&(old_name[i]!='.') ;i--) ;
653
 
    if (old_name[i] == '.') old_name[i] = 0;
654
 
#endif
655
 
 
656
 
    prefix_path = NULL;
657
 
    if (module_switch)
658
 
    {   extension = Module_Extension;
659
 
        if (Module_Path[0]!=0) prefix_path = Module_Path;
660
 
    }
661
 
    else
662
 
    {
663
 
        if (!glulx_mode) {
664
 
            switch(version_number)
665
 
            {   case 3: extension = Code_Extension;   break;
666
 
                case 4: extension = V4Code_Extension; break;
667
 
                case 5: extension = V5Code_Extension; break;
668
 
                case 6: extension = V6Code_Extension; break;
669
 
                case 7: extension = V7Code_Extension; break;
670
 
                case 8: extension = V8Code_Extension; break;
671
 
            }
672
 
        }
673
 
        else {
674
 
            extension = GlulxCode_Extension;
675
 
        }
676
 
        if (Code_Path[0]!=0) prefix_path = Code_Path;
677
 
    }
678
 
 
679
 
#ifdef FILE_EXTENSIONS
680
 
    extension = check_extension(old_name, extension);
681
 
#endif
682
 
 
683
 
    write_translated_name(new_name, old_name, prefix_path, 0, extension);
684
 
}
685
 
 
686
 
static char *name_or_unset(char *p)
687
 
{   if (p[0]==0) return "(unset)";
688
 
    return p;
689
 
}
690
 
 
691
 
static void help_on_filenames(void)
692
 
{   char old_name[PATHLEN];
693
 
    char new_name[PATHLEN];
694
 
    int save_mm = module_switch, x;
695
 
 
696
 
    module_switch = FALSE;
697
 
 
698
 
    printf("Help information on filenames:\n\n");
699
 
 
700
 
    printf(
701
 
"The command line can take one of two forms:\n\n\
702
 
  inform [commands...] <file1>\n\
703
 
  inform [commands...] <file1> <file2>\n\n\
704
 
Inform translates <file1> into a source file name (see below) for its input.\n\
705
 
<file2> is usually omitted: if so, the output filename is made from <file1>\n\
706
 
by cutting out the name part and translating that (see below).\n\
707
 
If <file2> is given, however, the output filename is set to just <file2>\n\
708
 
(not altered in any way).\n\n");
709
 
 
710
 
    printf(
711
 
"Filenames given in the game source (with commands like Include \"name\" and\n\
712
 
Link \"name\") are also translated by the rules below.\n\n");
713
 
 
714
 
    printf(
715
 
"Rules of translation:\n\n\
716
 
Inform translates plain filenames (such as \"xyzzy\") into full pathnames\n\
717
 
(such as \"adventure%cgames%cxyzzy\") according to the following rules.\n\n\
718
 
1. If the name contains a '%c' character (so it's already a pathname), it\n\
719
 
   isn't changed.\n\n", FN_SEP, FN_SEP, FN_SEP);
720
 
 
721
 
    printf(
722
 
"   [Exception: when the name is given in an Include command using the >\n\
723
 
   form (such as Include \">prologue\"), the \">\" is replaced by the path\n\
724
 
   of the file doing the inclusion");
725
 
#ifdef FILE_EXTENSIONS
726
 
                          printf(" and a suitable file extension is added");
727
 
#endif
728
 
    printf(".]\n\n");
729
 
 
730
 
    printf(
731
 
"   Filenames must never contain double-quotation marks \".  To use filenames\n\
732
 
   which contain spaces, write them in double-quotes: for instance,\n\n\
733
 
   \"inform +code_path=\"Jigsaw Final Version\" jigsaw\".\n\n");
734
 
 
735
 
    printf(
736
 
"2. The file is looked for at a particular \"path\" (the filename of a\n\
737
 
   directory), depending on what kind of file it is.\n\n\
738
 
       File type              Name                Current setting\n\n\
739
 
       Source code (in)       source_path         %s\n\
740
 
       Include file (in)      include_path        %s\n\
741
 
       Story file (out)       code_path           %s\n",
742
 
   name_or_unset(Source_Path), name_or_unset(Include_Path),
743
 
   name_or_unset(Code_Path));
744
 
 
745
 
    printf(
746
 
"       Temporary file (out)   temporary_path      %s\n\
747
 
       ICL command file (in)  icl_path            %s\n\
748
 
       Module (in & out)      module_path         %s\n\n",
749
 
   name_or_unset(Temporary_Path),
750
 
   name_or_unset(ICL_Path), name_or_unset(Module_Path));
751
 
 
752
 
    printf(
753
 
"   If the path is unset, then the current working directory is used (so\n\
754
 
   the filename doesn't change): if, for instance, include_path is set to\n\
755
 
   \"backup%coldlib\" then when \"parser\" is included it is looked for at\n\
756
 
   \"backup%coldlib%cparser\".\n\n\
757
 
   The paths can be set or unset on the Inform command line by, eg,\n\
758
 
   \"inform +code_path=finished jigsaw\" or\n\
759
 
   \"inform +include_path= balances\" (which unsets include_path).\n\n",
760
 
        FN_SEP, FN_SEP, FN_SEP);
761
 
 
762
 
    printf(
763
 
"   The four input path variables can be set to lists of alternative paths\n\
764
 
   separated by '%c' characters: these alternatives are always tried in\n\
765
 
   the order they are specified in, that is, left to right through the text\n\
766
 
   in the path variable.\n\
767
 
   (Modules are written to the first alternative in the module_path list;\n\
768
 
   it is an error to give alternatives at all for purely output paths.)\n\n",
769
 
   FN_ALT);
770
 
 
771
 
#ifdef FILE_EXTENSIONS
772
 
    printf("3. The following file extensions are added:\n\n\
773
 
      Source code:     %s\n\
774
 
      Include files:   %s\n\
775
 
      Story files:     %s (Version 3), %s (v4), %s (v5, the default),\n\
776
 
                       %s (v6), %s (v7), %s (v8), %s (Glulx)\n\
777
 
      Temporary files: .tmp\n\
778
 
      Modules:         %s\n\n",
779
 
      Source_Extension, Include_Extension,
780
 
      Code_Extension, V4Code_Extension, V5Code_Extension, V6Code_Extension,
781
 
      V7Code_Extension, V8Code_Extension, GlulxCode_Extension, 
782
 
      Module_Extension);
783
 
    printf("\
784
 
   except that any extension you give (on the command line or in a filename\n\
785
 
   used in a program) will override these.  If you give the null extension\n\
786
 
   \".\" then Inform uses no file extension at all (removing the \".\").\n\n");
787
 
#endif
788
 
 
789
 
    printf("Names of four individual files can also be set using the same\n\
790
 
  + command notation (though they aren't really pathnames).  These are:\n\n\
791
 
      transcript_name  (text written by -r switch): now \"%s\"\n\
792
 
      debugging_name   (data written by -k switch): now \"%s\"\n\
793
 
      language_name    (library file defining natural language of game):\n\
794
 
                       now \"%s\"\n\
795
 
      charset_map      (file for character set mapping): now \"%s\"\n\n",
796
 
    Transcript_Name, Debugging_Name, Language_Name, Charset_Map);
797
 
 
798
 
    translate_in_filename(0, new_name, "rezrov", 0, 1);
799
 
    printf("Examples: 1. \"inform rezrov\"\n\
800
 
  the source code is read from \"%s\"\n",
801
 
        new_name);
802
 
    convert_filename_flag = TRUE;
803
 
    translate_out_filename(new_name, "rezrov");
804
 
    printf("  and a story file is compiled to \"%s\".\n\n", new_name);
805
 
 
806
 
    translate_in_filename(0, new_name, "frotz", 0, 1);
807
 
    printf("2. \"inform -M frotz\"\n\
808
 
  the source code is read from \"%s\"\n",
809
 
        new_name);
810
 
    module_switch = TRUE;
811
 
    convert_filename_flag = TRUE;
812
 
    translate_out_filename(new_name, "frotz");
813
 
    printf("  and a module is compiled to \"%s\".\n\n", new_name);
814
 
 
815
 
    module_switch = FALSE;
816
 
 
817
 
    sprintf(old_name, "demos%cplugh", FN_SEP);
818
 
    printf("3. \"inform %s\"\n", old_name);
819
 
    translate_in_filename(0, new_name, old_name, 0, 1);
820
 
    printf("  the source code is read from \"%s\"\n", new_name);
821
 
    sprintf(old_name, "demos%cplugh", FN_SEP);
822
 
    convert_filename_flag = TRUE;
823
 
    translate_out_filename(new_name, old_name);
824
 
    printf("  and a story file is compiled to \"%s\".\n\n", new_name);
825
 
 
826
 
    printf("4. \"inform plover my_demo\"\n");
827
 
    translate_in_filename(0, new_name, "plover", 0, 1);
828
 
    printf("  the source code is read from \"%s\"\n", new_name);
829
 
    convert_filename_flag = FALSE;
830
 
    translate_out_filename(new_name, "my_demo");
831
 
    printf("  and a story file is compiled to \"%s\".\n\n", new_name);
832
 
 
833
 
    strcpy(old_name, Source_Path);
834
 
    sprintf(new_name, "%cnew%cold%crecent%cold%cancient",
835
 
        FN_ALT, FN_ALT, FN_SEP, FN_ALT, FN_SEP);
836
 
    printf("5. \"inform +source_path=%s zooge\"\n", new_name);
837
 
    printf(
838
 
"   Note that four alternative paths are given, the first being the empty\n\
839
 
   path-name (meaning: where you are now).  Inform looks for the source code\n\
840
 
   by trying these four places in turn, stopping when it finds anything:\n\n");
841
 
 
842
 
    set_path_value(Source_Path, new_name);
843
 
    x = 0;
844
 
    do
845
 
    {   x = translate_in_filename(x, new_name, "zooge", 0, 1);
846
 
        printf("     \"%s\"\n", new_name);
847
 
    } while (x != 0);
848
 
    strcpy(Source_Path, old_name);
849
 
    module_switch = save_mm;
850
 
}
851
 
 
852
 
/* ------------------------------------------------------------------------- */
853
 
/*  Naming temporary files                                                   */
854
 
/*       (Arguably temporary files should be made using "tmpfile" in         */
855
 
/*        the ANSI C library, but many supposed ANSI libraries lack it.)     */
856
 
/* ------------------------------------------------------------------------- */
857
 
 
858
 
extern void translate_temp_filename(int i)
859
 
{   char *p;
860
 
    switch(i)
861
 
    {   case 1: p=Temp1_Name; break;
862
 
        case 2: p=Temp2_Name; break;
863
 
        case 3: p=Temp3_Name; break;
864
 
    }
865
 
    sprintf(p,"%s%s%d", Temporary_Path, Temporary_File, i);
866
 
#ifdef INCLUDE_TASK_ID
867
 
    sprintf(p+strlen(p), "_proc%08lx", (long int) unique_task_id());
868
 
#endif
869
 
#ifdef FILE_EXTENSIONS
870
 
    sprintf(p+strlen(p), ".tmp");
871
 
#endif
872
 
}
873
 
 
874
 
#ifdef ARCHIMEDES
875
 
static char riscos_ft_buffer[4];
876
 
 
877
 
extern char *riscos_file_type(void)
878
 
{
879
 
    if (riscos_file_type_format == 1)
880
 
    {   if (module_switch) return("data");
881
 
        return("11A");
882
 
    }
883
 
 
884
 
    if (module_switch) return("075");
885
 
 
886
 
    sprintf(riscos_ft_buffer, "%03x", 0x60 + version_number);
887
 
    return(riscos_ft_buffer);
888
 
}
889
 
#endif
890
 
 
891
 
/* ------------------------------------------------------------------------- */
892
 
/*   The compilation pass                                                    */
893
 
/* ------------------------------------------------------------------------- */
894
 
 
895
 
static void run_pass(void)
896
 
{
897
 
    lexer_begin_prepass();
898
 
    files_begin_prepass();
899
 
    load_sourcefile(Source_Name, 0);
900
 
 
901
 
    begin_pass();
902
 
 
903
 
    parse_program(NULL);
904
 
 
905
 
    find_the_actions();
906
 
    issue_unused_warnings();
907
 
    compile_veneer();
908
 
 
909
 
    lexer_endpass();
910
 
    if (module_switch) linker_endpass();
911
 
 
912
 
    close_all_source();
913
 
    if (hash_switch && hash_printed_since_newline) printf("\n");
914
 
 
915
 
    if (temporary_files_switch)
916
 
    {   if (module_switch) flush_link_data();
917
 
        check_temp_files();
918
 
    }
919
 
    sort_dictionary();
920
 
    construct_storyfile();
921
 
}
922
 
 
923
 
int output_has_occurred;
924
 
 
925
 
static void rennab(int32 time_taken)
926
 
{   /*  rennab = reverse of banner  */
927
 
 
928
 
    int t = no_warnings + no_suppressed_warnings;
929
 
 
930
 
    if (memout_switch) print_memory_usage();
931
 
 
932
 
    if ((no_errors + t)!=0)
933
 
    {   printf("Compiled with ");
934
 
        if (no_errors > 0)
935
 
        {   printf("%d error%s", no_errors,(no_errors==1)?"":"s");
936
 
            if (t > 0) printf(" and ");
937
 
        }
938
 
        if (no_warnings > 0)
939
 
            printf("%d warning%s", t, (t==1)?"":"s");
940
 
        if (no_suppressed_warnings > 0)
941
 
        {   if (no_warnings > 0)
942
 
                printf(" (%d suppressed)", no_suppressed_warnings);
943
 
            else
944
 
            printf("%d suppressed warning%s", no_suppressed_warnings,
945
 
                (no_suppressed_warnings==1)?"":"s");
946
 
        }
947
 
        if (output_has_occurred == FALSE) printf(" (no output)");
948
 
        printf("\n");
949
 
    }
950
 
 
951
 
    if (no_compiler_errors > 0) print_sorry_message();
952
 
 
953
 
    if (statistics_switch)
954
 
        printf("Completed in %ld seconds\n", (long int) time_taken);
955
 
}
956
 
 
957
 
/* ------------------------------------------------------------------------- */
958
 
/*   The compiler abstracted to a routine.                                   */
959
 
/* ------------------------------------------------------------------------- */
960
 
 
961
 
static int execute_icl_header(char *file1);
962
 
 
963
 
static int compile(int number_of_files_specified, char *file1, char *file2)
964
 
{   int32 time_start;
965
 
 
966
 
    if (execute_icl_header(file1))
967
 
      return 1;
968
 
 
969
 
    select_target(glulx_mode);
970
 
 
971
 
    if (define_INFIX_switch && glulx_mode) {
972
 
        printf("Infix (-X) facilities are not available in Glulx: \
973
 
disabling -X switch\n");
974
 
        define_INFIX_switch = FALSE;
975
 
    }
976
 
 
977
 
    if (module_switch && glulx_mode) {
978
 
        printf("Modules are not available in Glulx: \
979
 
disabling -M switch\n");
980
 
        module_switch = FALSE;
981
 
    }
982
 
 
983
 
    if (define_INFIX_switch && module_switch)
984
 
    {   printf("Infix (-X) facilities are not available when compiling \
985
 
modules: disabling -X switch\n");
986
 
        define_INFIX_switch = FALSE;
987
 
    }
988
 
    if (runtime_error_checking_switch && module_switch)
989
 
    {   printf("Strict checking (-S) facilities are not available when \
990
 
compiling modules: disabling -S switch\n");
991
 
        runtime_error_checking_switch = FALSE;
992
 
    }
993
 
 
994
 
    time_start=time(0); no_compilations++;
995
 
 
996
 
    strcpy(Source_Name, file1); convert_filename_flag = TRUE;
997
 
    strcpy(Code_Name, file1);
998
 
    if (number_of_files_specified == 2)
999
 
    {   strcpy(Code_Name, file2); convert_filename_flag = FALSE;
1000
 
    }
1001
 
 
1002
 
    init_vars();
1003
 
    allocate_arrays();
1004
 
 
1005
 
    if (debugfile_switch) begin_debug_file();
1006
 
    if (transcript_switch) open_transcript_file(Source_Name);
1007
 
 
1008
 
    run_pass();
1009
 
 
1010
 
    if (transcript_switch)
1011
 
    {   write_dictionary_to_transcript();
1012
 
        close_transcript_file();
1013
 
    }
1014
 
 
1015
 
    if (no_errors==0) { output_file(); output_has_occurred = TRUE; }
1016
 
    else { output_has_occurred = FALSE; }
1017
 
 
1018
 
    if (debugfile_switch) close_debug_file();
1019
 
 
1020
 
    if (temporary_files_switch && (no_errors>0)) remove_temp_files();
1021
 
 
1022
 
    free_arrays();
1023
 
 
1024
 
    rennab((int32) (time(0)-time_start));
1025
 
 
1026
 
    if (optimise_switch) optimise_abbreviations();
1027
 
 
1028
 
    if (store_the_text) my_free(&all_text,"transcription text");
1029
 
 
1030
 
    return (no_errors==0)?0:1;
1031
 
}
1032
 
 
1033
 
/* ------------------------------------------------------------------------- */
1034
 
/*   The command line interpreter                                            */
1035
 
/* ------------------------------------------------------------------------- */
1036
 
 
1037
 
static void cli_print_help(int help_level)
1038
 
{
1039
 
    printf(
1040
 
"\nThis program is a compiler of Infocom format (also called \"Z-machine\")\n\
1041
 
story files: copyright (c) Graham Nelson 1993 - 2004.\n\n");
1042
 
 
1043
 
   /* For people typing just "inform", a summary only: */
1044
 
 
1045
 
   if (help_level==0)
1046
 
   {
1047
 
 
1048
 
#ifndef PROMPT_INPUT
1049
 
  printf("Usage: \"inform [commands...] <file1> [<file2>]\"\n\n");
1050
 
#else
1051
 
  printf("When run, Inform prompts you for commands (and switches),\n\
1052
 
which are optional, then an input <file1> and an (optional) output\n\
1053
 
<file2>.\n\n");
1054
 
#endif
1055
 
 
1056
 
  printf(
1057
 
"<file1> is the Inform source file of the game to be compiled. <file2>,\n\
1058
 
if given, overrides the filename Inform would normally use for the\n\
1059
 
compiled output.  Try \"inform -h1\" for file-naming conventions.\n\n\
1060
 
One or more words can be supplied as \"commands\". These may be:\n\n\
1061
 
  -switches     a list of compiler switches, 1 or 2 letter\n\
1062
 
                (see \"inform -h2\" for the full range)\n\n\
1063
 
  +dir          set Include_Path to this directory\n\
1064
 
  +PATH=dir     change the PATH to this directory\n\n\
1065
 
  $...          one of the following memory commands:\n");
1066
 
  printf(
1067
 
"     $list            list current memory allocation settings\n\
1068
 
     $huge            make standard \"huge game\" settings %s\n\
1069
 
     $large           make standard \"large game\" settings %s\n\
1070
 
     $small           make standard \"small game\" settings %s\n\
1071
 
     $?SETTING        explain briefly what SETTING is for\n\
1072
 
     $SETTING=number  change SETTING to given number\n\n\
1073
 
  (filename)    read in a list of commands (in the format above)\n\
1074
 
                from this \"setup file\"\n\n",
1075
 
    (DEFAULT_MEMORY_SIZE==HUGE_SIZE)?"(default)":"",
1076
 
    (DEFAULT_MEMORY_SIZE==LARGE_SIZE)?"(default)":"",
1077
 
    (DEFAULT_MEMORY_SIZE==SMALL_SIZE)?"(default)":"");
1078
 
 
1079
 
#ifndef PROMPT_INPUT
1080
 
    printf("For example: \"inform -dexs $huge curses\".\n\n");
1081
 
#endif
1082
 
 
1083
 
    printf(
1084
 
"For fuller information, see the Inform Designer's Manual.\n");
1085
 
 
1086
 
       return;
1087
 
   }
1088
 
 
1089
 
   /* The -h1 (filenaming) help information: */
1090
 
 
1091
 
   if (help_level == 1) { help_on_filenames(); return; }
1092
 
 
1093
 
   /* The -h2 (switches) help information: */
1094
 
 
1095
 
   printf("Help on the full list of legal switch commands:\n\n\
1096
 
  a   trace assembly-language (without hex dumps; see -t)\n\
1097
 
  c   more concise error messages\n\
1098
 
  d   contract double spaces after full stops in text\n\
1099
 
  d2  contract double spaces after exclamation and question marks, too\n\
1100
 
  e   economy mode (slower): make use of declared abbreviations\n");
1101
 
 
1102
 
   printf("\
1103
 
  f   frequencies mode: show how useful abbreviations are\n\
1104
 
  g   traces calls to functions (except in the library)\n\
1105
 
  g2  traces calls to all functions\n\
1106
 
  h   print this information\n");
1107
 
 
1108
 
   printf("\
1109
 
  i   ignore default switches set within the file\n\
1110
 
  j   list objects as constructed\n\
1111
 
  k   output Infix debugging information to \"%s\" (and switch -D on)\n\
1112
 
  l   list every statement run through Inform\n\
1113
 
  m   say how much memory has been allocated\n\
1114
 
  n   print numbers of properties, attributes and actions\n",
1115
 
          Debugging_Name);
1116
 
   printf("\
1117
 
  o   print offset addresses\n\
1118
 
  p   give percentage breakdown of story file\n\
1119
 
  q   keep quiet about obsolete usages\n\
1120
 
  r   record all the text to \"%s\"\n\
1121
 
  s   give statistics\n\
1122
 
  t   trace assembly-language (with full hex dumps; see -a)\n",
1123
 
      Transcript_Name);
1124
 
 
1125
 
   printf("\
1126
 
  u   work out most useful abbreviations (very very slowly)\n\
1127
 
  v3  compile to version-3 (\"Standard\") story file\n\
1128
 
  v4  compile to version-4 (\"Plus\") story file\n\
1129
 
  v5  compile to version-5 (\"Advanced\") story file: the default\n\
1130
 
  v6  compile to version-6 (graphical) story file\n\
1131
 
  v8  compile to version-8 (expanded \"Advanced\") story file\n\
1132
 
  w   disable warning messages\n\
1133
 
  x   print # for every 100 lines compiled\n\
1134
 
  y   trace linking system\n\
1135
 
  z   print memory map of the Z-machine\n\n");
1136
 
 
1137
 
printf("\
1138
 
  B   use big memory model (for large V6/V7 files)\n\
1139
 
  C0  text character set is plain ASCII only\n\
1140
 
  Cn  text character set is ISO 8859-n (n = 1 to 9)\n\
1141
 
      (1 to 4, Latin1 to Latin4; 5, Cyrillic; 6, Arabic;\n\
1142
 
       7, Greek; 8, Hebrew; 9, Latin5.  Default is -C1.)\n");
1143
 
printf("  D   insert \"Constant DEBUG;\" automatically\n");
1144
 
printf("  E0  Archimedes-style error messages%s\n",
1145
 
      (error_format==0)?" (current setting)":"");
1146
 
printf("  E1  Microsoft-style error messages%s\n",
1147
 
      (error_format==1)?" (current setting)":"");
1148
 
printf("  E2  Macintosh MPW-style error messages%s\n",
1149
 
      (error_format==2)?" (current setting)":"");
1150
 
#ifdef USE_TEMPORARY_FILES
1151
 
printf("  F0  use extra memory rather than temporary files\n");
1152
 
#else
1153
 
printf("  F1  use temporary files to reduce memory consumption\n");
1154
 
#endif
1155
 
printf("  G   compile a Glulx game file\n");
1156
 
printf("  H   use Huffman encoding to compress Glulx strings\n");
1157
 
printf("  M   compile as a Module for future linking\n");
1158
 
 
1159
 
#ifdef ARCHIMEDES
1160
 
printf("\
1161
 
  R0  use filetype 060 + version number for games (default)\n\
1162
 
  R1  use official Acorn filetype 11A for all games\n");
1163
 
#endif
1164
 
printf("  S   compile strict error-checking at run-time (on by default)\n");
1165
 
#ifdef ARC_THROWBACK
1166
 
printf("  T   enable throwback of errors in the DDE\n");
1167
 
#endif
1168
 
printf("  U   insert \"Constant USE_MODULES;\" automatically\n");
1169
 
printf("  Wn  header extension table is at least n words (n = 3 to 99)\n");
1170
 
printf("  X   compile with INFIX debugging facilities present\n");
1171
 
  printf("\n");
1172
 
}
1173
 
 
1174
 
extern void switches(char *p, int cmode)
1175
 
{   int i, s=1, state;
1176
 
    /* Here cmode is 0 if switches list is from a "Switches" directive
1177
 
       and 1 if from a "-switches" command-line or ICL list */
1178
 
 
1179
 
    if (cmode==1)
1180
 
    {   if (p[0]!='-')
1181
 
        {   printf(
1182
 
                "Ignoring second word which should be a -list of switches.\n");
1183
 
            return;
1184
 
        }
1185
 
    }
1186
 
    for (i=cmode; p[i]!=0; i+=s, s=1)
1187
 
    {   state = TRUE;
1188
 
        if (p[i] == '~')
1189
 
        {   state = FALSE;
1190
 
            i++;
1191
 
        }
1192
 
        switch(p[i])
1193
 
        {
1194
 
        case 'a': asm_trace_setting = 1; break;
1195
 
        case 'b': bothpasses_switch = state; break;
1196
 
        case 'c': concise_switch = state; break;
1197
 
        case 'd': switch(p[i+1])
1198
 
                  {   case '1': double_space_setting=1; s=2; break;
1199
 
                      case '2': double_space_setting=2; s=2; break;
1200
 
                      default: double_space_setting=1; break;
1201
 
                  }
1202
 
                  break;
1203
 
        case 'e': economy_switch = state; break;
1204
 
        case 'f': frequencies_switch = state; break;
1205
 
        case 'g': switch(p[i+1])
1206
 
                  {   case '1': trace_fns_setting=1; s=2; break;
1207
 
                      case '2': trace_fns_setting=2; s=2; break;
1208
 
                      default: trace_fns_setting=1; break;
1209
 
                  }
1210
 
                  break;
1211
 
        case 'h': switch(p[i+1])
1212
 
                  {   case '1': cli_print_help(1); s=2; break;
1213
 
                      case '2': cli_print_help(2); s=2; break;
1214
 
                      case '0': s=2;
1215
 
                      default:  cli_print_help(0); break;
1216
 
                  }
1217
 
                  break;
1218
 
        case 'i': ignore_switches_switch = state; break;
1219
 
        case 'j': listobjects_switch = state; break;
1220
 
        case 'k': if (cmode == 0)
1221
 
                      error("The switch '-k' can't be set with 'Switches'");
1222
 
                  else
1223
 
                  {   debugfile_switch = state;
1224
 
                      if (state) define_DEBUG_switch = TRUE;
1225
 
                  }
1226
 
                  break;
1227
 
        case 'l': listing_switch = state; break;
1228
 
        case 'm': memout_switch = state; break;
1229
 
        case 'n': printprops_switch = state; break;
1230
 
        case 'o': offsets_switch = state; break;
1231
 
        case 'p': percentages_switch = state; break;
1232
 
        case 'q': obsolete_switch = state; break;
1233
 
        case 'r': if (cmode == 0)
1234
 
                      error("The switch '-r' can't be set with 'Switches'");
1235
 
                  else
1236
 
                      transcript_switch = state; break;
1237
 
        case 's': statistics_switch = state; break;
1238
 
        case 't': asm_trace_setting=2; break;
1239
 
        case 'u': optimise_switch = state; break;
1240
 
        case 'v': if ((cmode==0) && (version_set_switch)) { s=2; break; }
1241
 
                  version_set_switch = TRUE; s=2;
1242
 
                  switch(p[i+1])
1243
 
                  {   case '3': select_version(3); break;
1244
 
                      case '4': select_version(4); break;
1245
 
                      case '5': select_version(5); break;
1246
 
                      case '6': select_version(6); break;
1247
 
                      case '7': select_version(7); break;
1248
 
                      case '8': select_version(8); break;
1249
 
                      default:  printf("-v must be followed by 3 to 8\n");
1250
 
                                version_set_switch=0; s=1;
1251
 
                                break;
1252
 
                  }
1253
 
                  break;
1254
 
        case 'w': nowarnings_switch = state; break;
1255
 
        case 'x': hash_switch = state; break;
1256
 
        case 'y': s=2; linker_trace_setting=p[i+1]-'0'; break;
1257
 
        case 'z': memory_map_switch = state; break;
1258
 
        case 'B': oddeven_packing_switch = state; break;
1259
 
        case 'C': s=2; character_set_setting=p[i+1]-'0';
1260
 
                  if ((character_set_setting < 0)
1261
 
                      || (character_set_setting > 9))
1262
 
                  {   printf("-C must be followed by 0 to 9\n");
1263
 
                      character_set_setting = 1;
1264
 
                  }
1265
 
                  if (cmode == 0) change_character_set();
1266
 
                  break;
1267
 
        case 'D': define_DEBUG_switch = state; break;
1268
 
        case 'E': switch(p[i+1])
1269
 
                  {   case '0': s=2; error_format=0; break;
1270
 
                      case '1': s=2; error_format=1; break;
1271
 
                      case '2': s=2; error_format=2; break;
1272
 
                      default:  error_format=1; break;
1273
 
                  }
1274
 
                  break;
1275
 
        case 'F': switch(p[i+1])
1276
 
                  {   case '0': s=2; temporary_files_switch = FALSE; break;
1277
 
                      case '1': s=2; temporary_files_switch = TRUE; break;
1278
 
                      default:  temporary_files_switch = state; break;
1279
 
                  }
1280
 
                  break;
1281
 
        case 'M': module_switch = state;
1282
 
                  if (state && (r_e_c_s_set == FALSE))
1283
 
                      runtime_error_checking_switch = FALSE;
1284
 
                  break;
1285
 
#ifdef ARCHIMEDES
1286
 
        case 'R': switch(p[i+1])
1287
 
                  {   case '0': s=2; riscos_file_type_format=0; break;
1288
 
                      case '1': s=2; riscos_file_type_format=1; break;
1289
 
                      default:  riscos_file_type_format=1; break;
1290
 
                  }
1291
 
                  break;
1292
 
#endif
1293
 
#ifdef ARC_THROWBACK
1294
 
        case 'T': throwback_switch = state; break;
1295
 
#endif
1296
 
        case 'S': runtime_error_checking_switch = state;
1297
 
                  r_e_c_s_set = TRUE; break;
1298
 
        case 'G': if (cmode == 0)
1299
 
                      error("The switch '-G' can't be set with 'Switches'");
1300
 
                  else
1301
 
                  {   glulx_mode = state; /* ###- */
1302
 
                      adjust_memory_sizes();
1303
 
                  }
1304
 
                  break;
1305
 
        case 'H': compression_switch = state; break;
1306
 
        case 'U': define_USE_MODULES_switch = state; break;
1307
 
        case 'W': if ((p[i+1]>='0') && (p[i+1]<='9'))
1308
 
                  {   s=2; header_ext_setting = p[i+1]-'0';
1309
 
                      if ((p[i+2]>='0') && (p[i+2]<='9'))
1310
 
                      {   s=3; header_ext_setting *= 10;
1311
 
                          header_ext_setting += p[i+2]-'0';
1312
 
                      }
1313
 
                  }
1314
 
                  break;
1315
 
        case 'X': define_INFIX_switch = state; break;
1316
 
        default:
1317
 
          printf("Switch \"-%c\" unknown (try \"inform -h2\" for the list)\n",
1318
 
              p[i]);
1319
 
          break;
1320
 
        }
1321
 
    }
1322
 
 
1323
 
    if (optimise_switch && (!store_the_text))
1324
 
    {   store_the_text=TRUE;
1325
 
#ifdef PC_QUICKC
1326
 
        if (memout_switch)
1327
 
            printf("Allocation %ld bytes for transcription text\n",
1328
 
                (long) MAX_TRANSCRIPT_SIZE);
1329
 
        all_text = halloc(MAX_TRANSCRIPT_SIZE,1);
1330
 
        malloced_bytes += MAX_TRANSCRIPT_SIZE;
1331
 
        if (all_text==NULL)
1332
 
         fatalerror("Can't hallocate memory for transcription text.  Darn.");
1333
 
#else
1334
 
        all_text=my_malloc(MAX_TRANSCRIPT_SIZE,"transcription text");
1335
 
#endif
1336
 
    }
1337
 
}
1338
 
 
1339
 
static int icl_command(char *p)
1340
 
{   if ((p[0]=='+')||(p[0]=='-')||(p[0]=='$')
1341
 
        || ((p[0]=='(')&&(p[strlen(p)-1]==')')) ) return TRUE;
1342
 
    return FALSE;
1343
 
}
1344
 
 
1345
 
static void icl_error(char *filename, int line)
1346
 
{   printf("Error in ICL file '%s', line %d:\n", filename, line);
1347
 
}
1348
 
 
1349
 
static void icl_header_error(char *filename, int line)
1350
 
{   printf("Error in ICL header of file '%s', line %d:\n", filename, line);
1351
 
}
1352
 
 
1353
 
static int copy_icl_word(char *from, char *to)
1354
 
{
1355
 
    /*  Copies one token from 'from' to 'to', null-terminated:
1356
 
        returns the number of chars in 'from' read past (possibly 0).  */
1357
 
 
1358
 
    int i, j, quoted_mode;
1359
 
 
1360
 
    i = 0;
1361
 
    while ((from[i] == ' ') || (from[i] == TAB_CHARACTER)
1362
 
           || (from[i] == (char) 10) || (from[i] == (char) 13)) i++;
1363
 
 
1364
 
    if (from[i] == '!')
1365
 
    {   while (from[i] != 0) i++;
1366
 
        to[0] = 0; return i;
1367
 
    }
1368
 
 
1369
 
    for (quoted_mode = FALSE, j=0;;)
1370
 
    {   if (from[i] == 0) break;
1371
 
        if (from[i] == 10) break;
1372
 
        if (from[i] == 13) break;
1373
 
        if (from[i] == TAB_CHARACTER) break;
1374
 
        if ((from[i] == ' ') && (!quoted_mode)) break;
1375
 
        if (from[i] == '\"') { quoted_mode = !quoted_mode; i++; }
1376
 
        else to[j++] = from[i++];
1377
 
    }
1378
 
    to[j] = 0; return i;
1379
 
}
1380
 
 
1381
 
static void execute_icl_command(char *p);
1382
 
 
1383
 
static int execute_icl_header(char *argname)
1384
 
{
1385
 
  FILE *command_file;
1386
 
  char cli_buff[256], fw[256];
1387
 
  int line = 0;
1388
 
  int errcount = 0;
1389
 
  int i;
1390
 
  char filename[PATHLEN]; 
1391
 
  int x = 0;
1392
 
 
1393
 
  do
1394
 
    {   x = translate_in_filename(x, filename, argname, 0, 1);
1395
 
        command_file = fopen(filename,"r");
1396
 
    } while ((command_file == NULL) && (x != 0));
1397
 
  if (!command_file) {
1398
 
    /* Fail silently. The regular compiler will try to open the file
1399
 
       again, and report the problem. */
1400
 
    return 0;
1401
 
  }
1402
 
 
1403
 
  while (feof(command_file)==0) {
1404
 
    if (fgets(cli_buff,256,command_file)==0) break;
1405
 
    line++;
1406
 
    if (!(cli_buff[0] == '!' && cli_buff[1] == '%'))
1407
 
      break;
1408
 
    i = copy_icl_word(cli_buff+2, fw);
1409
 
    if (icl_command(fw)) {
1410
 
      execute_icl_command(fw);
1411
 
      copy_icl_word(cli_buff+2 + i, fw);
1412
 
      if ((fw[0] != 0) && (fw[0] != '!')) {
1413
 
        icl_header_error(filename, line);
1414
 
        errcount++;
1415
 
        printf("expected comment or nothing but found '%s'\n", fw);
1416
 
      }
1417
 
    }
1418
 
    else {
1419
 
      if (fw[0]!=0) {
1420
 
        icl_header_error(filename, line);
1421
 
        errcount++;
1422
 
        printf("Expected command or comment but found '%s'\n", fw);
1423
 
      }
1424
 
    }
1425
 
  }
1426
 
  fclose(command_file);
1427
 
 
1428
 
  return (errcount==0)?0:1;
1429
 
}
1430
 
 
1431
 
 
1432
 
static void run_icl_file(char *filename, FILE *command_file)
1433
 
{   char cli_buff[256], fw[256];
1434
 
    int i, x, line = 0;
1435
 
    printf("[Running ICL file '%s']\n", filename);
1436
 
 
1437
 
    while (feof(command_file)==0)
1438
 
    {   if (fgets(cli_buff,256,command_file)==0) break;
1439
 
        line++;
1440
 
        i = copy_icl_word(cli_buff, fw);
1441
 
        if (icl_command(fw))
1442
 
        {   execute_icl_command(fw);
1443
 
            copy_icl_word(cli_buff + i, fw);
1444
 
            if ((fw[0] != 0) && (fw[0] != '!'))
1445
 
            {   icl_error(filename, line);
1446
 
                printf("expected comment or nothing but found '%s'\n", fw);
1447
 
            }
1448
 
        }
1449
 
        else
1450
 
        {   if (strcmp(fw, "compile")==0)
1451
 
            {   char story_name[PATHLEN], code_name[PATHLEN];
1452
 
                i += copy_icl_word(cli_buff + i, story_name);
1453
 
                i += copy_icl_word(cli_buff + i, code_name);
1454
 
 
1455
 
                if (code_name[0] != 0) x=2;
1456
 
                else if (story_name[0] != 0) x=1;
1457
 
                else x=0;
1458
 
 
1459
 
                switch(x)
1460
 
                {   case 0: icl_error(filename, line);
1461
 
                            printf("No filename given to 'compile'\n");
1462
 
                            break;
1463
 
                    case 1: printf("[Compiling <%s>]\n", story_name);
1464
 
                            compile(x, story_name, code_name);
1465
 
                            break;
1466
 
                    case 2: printf("[Compiling <%s> to <%s>]\n",
1467
 
                                story_name, code_name);
1468
 
                            compile(x, story_name, code_name);
1469
 
                            copy_icl_word(cli_buff + i, fw);
1470
 
                            if (fw[0]!=0)
1471
 
                            {   icl_error(filename, line);
1472
 
                        printf("Expected comment or nothing but found '%s'\n",
1473
 
                                fw);
1474
 
                            }
1475
 
                            break;
1476
 
                }
1477
 
            }
1478
 
            else
1479
 
            if (fw[0]!=0)
1480
 
            {   icl_error(filename, line);
1481
 
                printf("Expected command or comment but found '%s'\n", fw);
1482
 
            }
1483
 
        }
1484
 
    }
1485
 
}
1486
 
 
1487
 
static void execute_icl_command(char *p)
1488
 
{   char filename[PATHLEN], cli_buff[256];
1489
 
    FILE *command_file;
1490
 
 
1491
 
    switch(p[0])
1492
 
    {   case '+': set_path_command(p+1); break;
1493
 
        case '-': switches(p,1); break;
1494
 
        case '$': memory_command(p+1); break;
1495
 
        case '(': strcpy(cli_buff,p+1); cli_buff[strlen(cli_buff)-1]=0;
1496
 
                  {   int x = 0;
1497
 
                      do
1498
 
                      {   x = translate_icl_filename(x, filename, cli_buff);
1499
 
                          command_file = fopen(filename,"r");
1500
 
                      } while ((command_file == NULL) && (x != 0));
1501
 
                  }
1502
 
                  if (command_file == NULL)
1503
 
                      printf("Error in ICL: Couldn't open command file '%s'\n",
1504
 
                          filename);
1505
 
                  else
1506
 
                  {   run_icl_file(filename, command_file);
1507
 
                      fclose(command_file);
1508
 
                  }
1509
 
                  break;
1510
 
    }
1511
 
}
1512
 
 
1513
 
/* ------------------------------------------------------------------------- */
1514
 
/*   Opening and closing banners                                             */
1515
 
/* ------------------------------------------------------------------------- */
1516
 
 
1517
 
char banner_line[80];
1518
 
 
1519
 
static void banner(void)
1520
 
{
1521
 
    sprintf(banner_line, "Inform %d.%d%d",
1522
 
        (VNUMBER/100)%10, (VNUMBER/10)%10, VNUMBER%10);
1523
 
    if (0) {
1524
 
        sprintf(banner_line+strlen(banner_line), " (biplatform, G%d.%d%d)",
1525
 
            (GLULX_RELEASE_NUMBER/100)%10, (GLULX_RELEASE_NUMBER/10)%10, 
1526
 
            GLULX_RELEASE_NUMBER%10);
1527
 
    }
1528
 
#ifdef MACHINE_STRING
1529
 
    sprintf(banner_line+strlen(banner_line), " for %s", MACHINE_STRING);
1530
 
#endif
1531
 
    sprintf(banner_line+strlen(banner_line), " (%s)",
1532
 
        RELEASE_DATE);
1533
 
    printf("%s\n", banner_line);
1534
 
}
1535
 
 
1536
 
/* ------------------------------------------------------------------------- */
1537
 
/*   Input from the outside world                                            */
1538
 
/* ------------------------------------------------------------------------- */
1539
 
 
1540
 
#ifdef PROMPT_INPUT
1541
 
static void read_command_line(int argc, char **argv)
1542
 
{   int i;
1543
 
    char buffer1[100], buffer2[100], buffer3[100];
1544
 
    i=0;
1545
 
    printf("Source filename?\n> ");
1546
 
    while (gets(buffer1)==NULL); cli_file1=buffer1;
1547
 
    printf("Output filename (RETURN for the same)?\n> ");
1548
 
    while (gets(buffer2)==NULL); cli_file2=buffer2;
1549
 
    cli_files_specified=1;
1550
 
    if (buffer2[0]!=0) cli_files_specified=2;
1551
 
    do
1552
 
    {   printf("List of commands (RETURN to finish; \"-h\" for help)?\n> ");
1553
 
        while (gets(buffer3)==NULL); execute_icl_command(buffer3);
1554
 
    } while (buffer3[0]!=0);
1555
 
}
1556
 
#else
1557
 
static void read_command_line(int argc, char **argv)
1558
 
{   int i;
1559
 
    if (argc==1) switches("-h",1);
1560
 
 
1561
 
    for (i=1, cli_files_specified=0; i<argc; i++)
1562
 
        if (icl_command(argv[i]))
1563
 
            execute_icl_command(argv[i]);
1564
 
        else
1565
 
            switch(++cli_files_specified)
1566
 
            {   case 1: cli_file1 = argv[i]; break;
1567
 
                case 2: cli_file2 = argv[i]; break;
1568
 
                default:
1569
 
                    printf("Command line error: unknown parameter '%s'\n",
1570
 
                        argv[i]); return;
1571
 
            }
1572
 
}
1573
 
#endif
1574
 
 
1575
 
/* ------------------------------------------------------------------------- */
1576
 
/*   M A I N : An outer shell for machine-specific quirks                    */
1577
 
/*   Omitted altogether if EXTERNAL_SHELL is defined, as for instance is     */
1578
 
/*   needed for the Macintosh front end.                                     */
1579
 
/* ------------------------------------------------------------------------- */
1580
 
 
1581
 
#ifdef EXTERNAL_SHELL
1582
 
extern int sub_main(int argc, char **argv);
1583
 
#else
1584
 
 
1585
 
static int sub_main(int argc, char **argv);
1586
 
#ifdef MAC_MPW
1587
 
int main(int argc, char **argv, char *envp[])
1588
 
#else
1589
 
int main(int argc, char **argv)
1590
 
#endif
1591
 
{   int rcode;
1592
 
#ifdef MAC_MPW
1593
 
    InitCursorCtl((acurHandle)NULL); Show_Cursor(WATCH_CURSOR);
1594
 
#endif
1595
 
    rcode = sub_main(argc, argv);
1596
 
#ifdef ARC_THROWBACK
1597
 
    throwback_end();
1598
 
#endif
1599
 
    return rcode;
1600
 
}
1601
 
 
1602
 
#endif
1603
 
 
1604
 
/* ------------------------------------------------------------------------- */
1605
 
/*   M A I N  II:  Starting up ICL with the command line                     */
1606
 
/* ------------------------------------------------------------------------- */
1607
 
 
1608
 
#ifdef EXTERNAL_SHELL
1609
 
extern int sub_main(int argc, char **argv)
1610
 
#else
1611
 
static int sub_main(int argc, char **argv)
1612
 
#endif
1613
 
{   int return_code;
1614
 
 
1615
 
#ifdef MAC_FACE
1616
 
    ProcessEvents (&g_proc);
1617
 
    if (g_proc != true)
1618
 
    {   free_arrays();
1619
 
        if (store_the_text) my_free(&all_text,"transcription text");
1620
 
        longjmp (g_fallback, 1);
1621
 
    }
1622
 
#endif
1623
 
 
1624
 
    banner();
1625
 
 
1626
 
    set_memory_sizes(DEFAULT_MEMORY_SIZE); set_default_paths();
1627
 
    reset_switch_settings(); select_version(5);
1628
 
 
1629
 
    cli_files_specified = 0; no_compilations = 0;
1630
 
    cli_file1 = "source"; cli_file2 = "output";
1631
 
 
1632
 
    read_command_line(argc, argv);
1633
 
 
1634
 
    if (cli_files_specified > 0)
1635
 
    {   return_code = compile(cli_files_specified, cli_file1, cli_file2);
1636
 
 
1637
 
        if (return_code != 0) return(return_code);
1638
 
    }
1639
 
 
1640
 
    if (no_compilations == 0)
1641
 
        printf("\n[No compilation requested]\n");
1642
 
    if (no_compilations > 1)
1643
 
        printf("[%d compilations completed]\n", no_compilations);
1644
 
 
1645
 
    return(0);
1646
 
}
1647
 
 
1648
 
/* ========================================================================= */