1
/* ------------------------------------------------------------------------- */
2
/* "inform" : The top level of Inform: switches, pathnames, filenaming */
3
/* conventions, ICL (Inform Command Line) files, main */
5
/* Part of Inform 6.30 */
6
/* copyright (c) Graham Nelson 1993 - 2004 */
8
/* ------------------------------------------------------------------------- */
10
#define MAIN_INFORM_FILE
13
/* ------------------------------------------------------------------------- */
14
/* Compiler progress */
15
/* ------------------------------------------------------------------------- */
17
static int no_compilations;
19
int endofpass_flag; /* set to TRUE when an "end" directive is reached
20
(the inputs routines insert one into the stream
23
/* ------------------------------------------------------------------------- */
25
/* ------------------------------------------------------------------------- */
27
/* This stuff is Z-code only, for now. It might handle multiple Glulx
28
versions someday, if needed. */
30
int version_number, /* 3 to 8 */
31
instruction_set_number,
32
/* 3 to 6: versions 7 and 8 use instruction set of
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 */
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;
44
if (version_number==3) scale_factor = 2;
45
if (version_number==8) scale_factor = 8;
47
length_scale_factor = scale_factor;
48
if ((version_number==6)||(version_number==7)) length_scale_factor = 8;
50
instruction_set_number = version_number;
51
if ((version_number==7)||(version_number==8)) instruction_set_number = 5;
54
/* ------------------------------------------------------------------------- */
55
/* Target: variables which vary between the Z-machine and Glulx */
56
/* ------------------------------------------------------------------------- */
58
int WORDSIZE; /* Size of a machine word: 2 or 4 */
59
int32 MAXINTWORD; /* 0x7FFF or 0x7FFFFFFF */
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.
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.
71
int OBJECT_BYTE_LENGTH;
73
static void select_target(int targ)
79
INDIV_PROP_START = 64;
80
OBJECT_BYTE_LENGTH = 0; /* not used */
82
if (DICT_WORD_SIZE != 6) {
84
warning("You cannot change DICT_WORD_SIZE in Z-code; resetting to 6");
86
if (NUM_ATTR_BYTES != 6) {
88
warning("You cannot change NUM_ATTR_BYTES in Z-code; resetting to 6");
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");
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");
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 */
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);
111
OBJECT_BYTE_LENGTH = (1 + (NUM_ATTR_BYTES) + 6*4);
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
120
if (DICT_WORD_SIZE > MAX_DICT_WORD_SIZE) {
121
DICT_WORD_SIZE = MAX_DICT_WORD_SIZE;
123
"DICT_WORD_SIZE cannot exceed MAX_DICT_WORD_SIZE; resetting",
125
/* MAX_DICT_WORD_SIZE can be increased in header.h without fear. */
127
if (NUM_ATTR_BYTES > MAX_NUM_ATTR_BYTES) {
128
NUM_ATTR_BYTES = MAX_NUM_ATTR_BYTES;
130
"NUM_ATTR_BYTES cannot exceed MAX_NUM_ATTR_BYTES; resetting",
132
/* MAX_NUM_ATTR_BYTES can be increased in header.h without fear. */
136
/* ------------------------------------------------------------------------- */
137
/* Tracery: output control variables */
138
/* ------------------------------------------------------------------------- */
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 */
147
/* ------------------------------------------------------------------------- */
148
/* On/off switch variables (by default all FALSE); other switch settings */
149
/* ------------------------------------------------------------------------- */
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 */
179
int throwback_switch; /* -T */
182
int riscos_file_type_format; /* set by -R */
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? */
197
int glulx_mode; /* -G */
199
static void reset_switch_settings(void)
200
{ asm_trace_setting=0;
201
linker_trace_level=0;
202
tokens_trace_level=0;
204
store_the_text = FALSE;
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;
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;
233
temporary_files_switch = FALSE;
235
define_USE_MODULES_switch = FALSE;
236
module_switch = FALSE;
238
throwback_switch = FALSE;
240
runtime_error_checking_switch = TRUE;
242
define_INFIX_switch = FALSE;
244
riscos_file_type_format = 0;
246
error_format=DEFAULT_ERROR_FORMAT;
248
character_set_setting = 1; /* Default is ISO Latin-1 */
249
header_ext_setting = 0;
251
compression_switch = TRUE;
255
/* ------------------------------------------------------------------------- */
256
/* Number of files given as command line parameters (0, 1 or 2) */
257
/* ------------------------------------------------------------------------- */
259
static int cli_files_specified,
260
convert_filename_flag;
262
char Source_Name[100]; /* Processed name of first input file */
263
char Code_Name[100]; /* Processed name of output file */
265
static char *cli_file1, *cli_file2; /* Unprocessed (and unsafe to alter) */
267
/* ========================================================================= */
268
/* Data structure management routines */
269
/* ------------------------------------------------------------------------- */
271
static void init_vars(void)
279
init_expressc_vars();
280
init_expressp_vars();
295
static void begin_pass(void)
301
directs_begin_pass();
303
expressc_begin_pass();
304
expressp_begin_pass();
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;
316
objects_begin_pass();
318
symbols_begin_pass();
327
/* Compile a Main__ routine (see "veneer.c") */
329
compile_initial_routine();
331
/* Make the four metaclasses: Class must be object number 1, so
332
it must come first */
337
make_class("Object");
338
make_class("Routine");
339
make_class("String");
345
extern void allocate_arrays(void)
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();
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();
370
extern void free_arrays(void)
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. */
376
arrays_free_arrays();
378
bpatch_free_arrays();
380
directs_free_arrays();
381
errors_free_arrays();
382
expressc_free_arrays();
383
expressp_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();
395
veneer_free_arrays();
399
/* ------------------------------------------------------------------------- */
400
/* Name translation code for filenames */
401
/* ------------------------------------------------------------------------- */
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];
415
static void set_path_value(char *path, char *value)
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);
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;
434
else path[i++] = value[j++];
438
static void set_default_paths(void)
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, "");
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++) ;
456
if (command[i]==0) { new_value=command; path_to_set=Include_Path; }
458
{ char pathname[PATHLEN];
459
if (i>=PATHLEN) i=PATHLEN-1;
460
new_value = command+i+1;
462
if (isupper(command[j])) pathname[j]=tolower(command[j]);
463
else pathname[j]=command[j];
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;
477
if (path_to_set == NULL)
478
{ printf("No such path setting as \"%s\"\n", pathname);
483
set_path_value(path_to_set, new_value);
486
static int contains_separator(char *name)
488
for (i=0; name[i]!=0; i++)
489
if (name[i] == FN_SEP) return 1;
493
static int write_translated_name(char *new_name, char *old_name,
494
char *prefix_path, int start_pos,
497
if (prefix_path == NULL)
498
{ sprintf(new_name,"%s%s", old_name, extension);
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);
508
#ifdef FILE_EXTENSIONS
509
static char *check_extension(char *name, char *extension)
512
/* If a filename ends in '.', remove the dot and add no file extension: */
514
if (name[i] == '.') { name[i]=0; return ""; }
516
/* Remove the new extension if it's already got one: */
518
for (; (i>=0) && (name[i]!=FN_SEP); i--)
519
if (name[i] == '.') return "";
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: */
529
/* int translate_*_filename(int last_value, ...) */
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. */
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
/* ------------------------------------------------------------------------- */
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;
546
int add_path_flag = 1;
549
if ((same_directory_flag==0)
550
&& (contains_separator(old_name)==1)) add_path_flag=0;
552
if (add_path_flag==1)
553
{ if (command_line_flag == 0)
554
{ /* File is opened as a result of an Include directive */
556
if (same_directory_flag==1)
557
prefix_path = current_source_path;
559
if (Include_Path[0]!=0) prefix_path = Include_Path;
561
/* Main file being opened from the command line */
563
else if (Source_Path[0]!=0) prefix_path = Source_Path;
566
#ifdef FILE_EXTENSIONS
567
/* Which file extension is expected? */
569
if ((command_line_flag==1)||(same_directory_flag==1))
570
extension = Source_Extension;
572
extension = Include_Extension;
574
extension = check_extension(old_name, extension);
579
last_value = write_translated_name(new_name, old_name,
580
prefix_path, last_value, extension);
582
/* Set the "current source path" (for use of Include ">...") */
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--) ;
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 */
596
extern int translate_link_filename(int last_value,
597
char *new_name, char *old_name)
598
{ char *prefix_path = NULL;
601
if (contains_separator(old_name)==0)
602
if (Module_Path[0]!=0)
603
prefix_path = Module_Path;
605
#ifdef FILE_EXTENSIONS
606
extension = check_extension(old_name, Module_Extension);
611
return write_translated_name(new_name, old_name,
612
prefix_path, last_value, extension);
615
static int translate_icl_filename(int last_value,
616
char *new_name, char *old_name)
617
{ char *prefix_path = NULL;
618
char *extension = "";
620
if (contains_separator(old_name)==0)
622
prefix_path = ICL_Path;
624
#ifdef FILE_EXTENSIONS
625
extension = check_extension(old_name, ICL_Extension);
628
return write_translated_name(new_name, old_name,
629
prefix_path, last_value, extension);
632
extern void translate_out_filename(char *new_name, char *old_name)
634
char *extension = "";
637
/* If !convert_filename_flag, then the old_name is just the <file2>
638
parameter on the Inform command line, which we leave alone. */
640
if (!convert_filename_flag)
641
{ strcpy(new_name, old_name); return;
644
/* Remove any pathname or extension in <file1>. */
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++;
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;
658
{ extension = Module_Extension;
659
if (Module_Path[0]!=0) prefix_path = Module_Path;
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;
674
extension = GlulxCode_Extension;
676
if (Code_Path[0]!=0) prefix_path = Code_Path;
679
#ifdef FILE_EXTENSIONS
680
extension = check_extension(old_name, extension);
683
write_translated_name(new_name, old_name, prefix_path, 0, extension);
686
static char *name_or_unset(char *p)
687
{ if (p[0]==0) return "(unset)";
691
static void help_on_filenames(void)
692
{ char old_name[PATHLEN];
693
char new_name[PATHLEN];
694
int save_mm = module_switch, x;
696
module_switch = FALSE;
698
printf("Help information on filenames:\n\n");
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");
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");
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);
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");
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");
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));
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));
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);
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",
771
#ifdef FILE_EXTENSIONS
772
printf("3. The following file extensions are added:\n\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\
779
Source_Extension, Include_Extension,
780
Code_Extension, V4Code_Extension, V5Code_Extension, V6Code_Extension,
781
V7Code_Extension, V8Code_Extension, GlulxCode_Extension,
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");
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\
795
charset_map (file for character set mapping): now \"%s\"\n\n",
796
Transcript_Name, Debugging_Name, Language_Name, Charset_Map);
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",
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);
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",
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);
815
module_switch = FALSE;
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);
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);
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);
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");
842
set_path_value(Source_Path, new_name);
845
{ x = translate_in_filename(x, new_name, "zooge", 0, 1);
846
printf(" \"%s\"\n", new_name);
848
strcpy(Source_Path, old_name);
849
module_switch = save_mm;
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
/* ------------------------------------------------------------------------- */
858
extern void translate_temp_filename(int i)
861
{ case 1: p=Temp1_Name; break;
862
case 2: p=Temp2_Name; break;
863
case 3: p=Temp3_Name; break;
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());
869
#ifdef FILE_EXTENSIONS
870
sprintf(p+strlen(p), ".tmp");
875
static char riscos_ft_buffer[4];
877
extern char *riscos_file_type(void)
879
if (riscos_file_type_format == 1)
880
{ if (module_switch) return("data");
884
if (module_switch) return("075");
886
sprintf(riscos_ft_buffer, "%03x", 0x60 + version_number);
887
return(riscos_ft_buffer);
891
/* ------------------------------------------------------------------------- */
892
/* The compilation pass */
893
/* ------------------------------------------------------------------------- */
895
static void run_pass(void)
897
lexer_begin_prepass();
898
files_begin_prepass();
899
load_sourcefile(Source_Name, 0);
906
issue_unused_warnings();
910
if (module_switch) linker_endpass();
913
if (hash_switch && hash_printed_since_newline) printf("\n");
915
if (temporary_files_switch)
916
{ if (module_switch) flush_link_data();
920
construct_storyfile();
923
int output_has_occurred;
925
static void rennab(int32 time_taken)
926
{ /* rennab = reverse of banner */
928
int t = no_warnings + no_suppressed_warnings;
930
if (memout_switch) print_memory_usage();
932
if ((no_errors + t)!=0)
933
{ printf("Compiled with ");
935
{ printf("%d error%s", no_errors,(no_errors==1)?"":"s");
936
if (t > 0) printf(" and ");
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);
944
printf("%d suppressed warning%s", no_suppressed_warnings,
945
(no_suppressed_warnings==1)?"":"s");
947
if (output_has_occurred == FALSE) printf(" (no output)");
951
if (no_compiler_errors > 0) print_sorry_message();
953
if (statistics_switch)
954
printf("Completed in %ld seconds\n", (long int) time_taken);
957
/* ------------------------------------------------------------------------- */
958
/* The compiler abstracted to a routine. */
959
/* ------------------------------------------------------------------------- */
961
static int execute_icl_header(char *file1);
963
static int compile(int number_of_files_specified, char *file1, char *file2)
966
if (execute_icl_header(file1))
969
select_target(glulx_mode);
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;
977
if (module_switch && glulx_mode) {
978
printf("Modules are not available in Glulx: \
979
disabling -M switch\n");
980
module_switch = FALSE;
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;
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;
994
time_start=time(0); no_compilations++;
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;
1005
if (debugfile_switch) begin_debug_file();
1006
if (transcript_switch) open_transcript_file(Source_Name);
1010
if (transcript_switch)
1011
{ write_dictionary_to_transcript();
1012
close_transcript_file();
1015
if (no_errors==0) { output_file(); output_has_occurred = TRUE; }
1016
else { output_has_occurred = FALSE; }
1018
if (debugfile_switch) close_debug_file();
1020
if (temporary_files_switch && (no_errors>0)) remove_temp_files();
1024
rennab((int32) (time(0)-time_start));
1026
if (optimise_switch) optimise_abbreviations();
1028
if (store_the_text) my_free(&all_text,"transcription text");
1030
return (no_errors==0)?0:1;
1033
/* ------------------------------------------------------------------------- */
1034
/* The command line interpreter */
1035
/* ------------------------------------------------------------------------- */
1037
static void cli_print_help(int help_level)
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");
1043
/* For people typing just "inform", a summary only: */
1048
#ifndef PROMPT_INPUT
1049
printf("Usage: \"inform [commands...] <file1> [<file2>]\"\n\n");
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\
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");
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)":"");
1079
#ifndef PROMPT_INPUT
1080
printf("For example: \"inform -dexs $huge curses\".\n\n");
1084
"For fuller information, see the Inform Designer's Manual.\n");
1089
/* The -h1 (filenaming) help information: */
1091
if (help_level == 1) { help_on_filenames(); return; }
1093
/* The -h2 (switches) help information: */
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");
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");
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",
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",
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");
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");
1153
printf(" F1 use temporary files to reduce memory consumption\n");
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");
1161
R0 use filetype 060 + version number for games (default)\n\
1162
R1 use official Acorn filetype 11A for all games\n");
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");
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");
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 */
1182
"Ignoring second word which should be a -list of switches.\n");
1186
for (i=cmode; p[i]!=0; i+=s, s=1)
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;
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;
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;
1215
default: cli_print_help(0); 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'");
1223
{ debugfile_switch = state;
1224
if (state) define_DEBUG_switch = TRUE;
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'");
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;
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;
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;
1265
if (cmode == 0) change_character_set();
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;
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;
1281
case 'M': module_switch = state;
1282
if (state && (r_e_c_s_set == FALSE))
1283
runtime_error_checking_switch = FALSE;
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;
1293
#ifdef ARC_THROWBACK
1294
case 'T': throwback_switch = state; break;
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'");
1301
{ glulx_mode = state; /* ###- */
1302
adjust_memory_sizes();
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';
1315
case 'X': define_INFIX_switch = state; break;
1317
printf("Switch \"-%c\" unknown (try \"inform -h2\" for the list)\n",
1323
if (optimise_switch && (!store_the_text))
1324
{ store_the_text=TRUE;
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;
1332
fatalerror("Can't hallocate memory for transcription text. Darn.");
1334
all_text=my_malloc(MAX_TRANSCRIPT_SIZE,"transcription text");
1339
static int icl_command(char *p)
1340
{ if ((p[0]=='+')||(p[0]=='-')||(p[0]=='$')
1341
|| ((p[0]=='(')&&(p[strlen(p)-1]==')')) ) return TRUE;
1345
static void icl_error(char *filename, int line)
1346
{ printf("Error in ICL file '%s', line %d:\n", filename, line);
1349
static void icl_header_error(char *filename, int line)
1350
{ printf("Error in ICL header of file '%s', line %d:\n", filename, line);
1353
static int copy_icl_word(char *from, char *to)
1355
/* Copies one token from 'from' to 'to', null-terminated:
1356
returns the number of chars in 'from' read past (possibly 0). */
1358
int i, j, quoted_mode;
1361
while ((from[i] == ' ') || (from[i] == TAB_CHARACTER)
1362
|| (from[i] == (char) 10) || (from[i] == (char) 13)) i++;
1365
{ while (from[i] != 0) i++;
1366
to[0] = 0; return i;
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++];
1378
to[j] = 0; return i;
1381
static void execute_icl_command(char *p);
1383
static int execute_icl_header(char *argname)
1386
char cli_buff[256], fw[256];
1390
char filename[PATHLEN];
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. */
1403
while (feof(command_file)==0) {
1404
if (fgets(cli_buff,256,command_file)==0) break;
1406
if (!(cli_buff[0] == '!' && cli_buff[1] == '%'))
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);
1415
printf("expected comment or nothing but found '%s'\n", fw);
1420
icl_header_error(filename, line);
1422
printf("Expected command or comment but found '%s'\n", fw);
1426
fclose(command_file);
1428
return (errcount==0)?0:1;
1432
static void run_icl_file(char *filename, FILE *command_file)
1433
{ char cli_buff[256], fw[256];
1435
printf("[Running ICL file '%s']\n", filename);
1437
while (feof(command_file)==0)
1438
{ if (fgets(cli_buff,256,command_file)==0) break;
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);
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);
1455
if (code_name[0] != 0) x=2;
1456
else if (story_name[0] != 0) x=1;
1460
{ case 0: icl_error(filename, line);
1461
printf("No filename given to 'compile'\n");
1463
case 1: printf("[Compiling <%s>]\n", story_name);
1464
compile(x, story_name, code_name);
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);
1471
{ icl_error(filename, line);
1472
printf("Expected comment or nothing but found '%s'\n",
1480
{ icl_error(filename, line);
1481
printf("Expected command or comment but found '%s'\n", fw);
1487
static void execute_icl_command(char *p)
1488
{ char filename[PATHLEN], cli_buff[256];
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;
1498
{ x = translate_icl_filename(x, filename, cli_buff);
1499
command_file = fopen(filename,"r");
1500
} while ((command_file == NULL) && (x != 0));
1502
if (command_file == NULL)
1503
printf("Error in ICL: Couldn't open command file '%s'\n",
1506
{ run_icl_file(filename, command_file);
1507
fclose(command_file);
1513
/* ------------------------------------------------------------------------- */
1514
/* Opening and closing banners */
1515
/* ------------------------------------------------------------------------- */
1517
char banner_line[80];
1519
static void banner(void)
1521
sprintf(banner_line, "Inform %d.%d%d",
1522
(VNUMBER/100)%10, (VNUMBER/10)%10, VNUMBER%10);
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);
1528
#ifdef MACHINE_STRING
1529
sprintf(banner_line+strlen(banner_line), " for %s", MACHINE_STRING);
1531
sprintf(banner_line+strlen(banner_line), " (%s)",
1533
printf("%s\n", banner_line);
1536
/* ------------------------------------------------------------------------- */
1537
/* Input from the outside world */
1538
/* ------------------------------------------------------------------------- */
1541
static void read_command_line(int argc, char **argv)
1543
char buffer1[100], buffer2[100], buffer3[100];
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;
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);
1557
static void read_command_line(int argc, char **argv)
1559
if (argc==1) switches("-h",1);
1561
for (i=1, cli_files_specified=0; i<argc; i++)
1562
if (icl_command(argv[i]))
1563
execute_icl_command(argv[i]);
1565
switch(++cli_files_specified)
1566
{ case 1: cli_file1 = argv[i]; break;
1567
case 2: cli_file2 = argv[i]; break;
1569
printf("Command line error: unknown parameter '%s'\n",
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
/* ------------------------------------------------------------------------- */
1581
#ifdef EXTERNAL_SHELL
1582
extern int sub_main(int argc, char **argv);
1585
static int sub_main(int argc, char **argv);
1587
int main(int argc, char **argv, char *envp[])
1589
int main(int argc, char **argv)
1593
InitCursorCtl((acurHandle)NULL); Show_Cursor(WATCH_CURSOR);
1595
rcode = sub_main(argc, argv);
1596
#ifdef ARC_THROWBACK
1604
/* ------------------------------------------------------------------------- */
1605
/* M A I N II: Starting up ICL with the command line */
1606
/* ------------------------------------------------------------------------- */
1608
#ifdef EXTERNAL_SHELL
1609
extern int sub_main(int argc, char **argv)
1611
static int sub_main(int argc, char **argv)
1616
ProcessEvents (&g_proc);
1619
if (store_the_text) my_free(&all_text,"transcription text");
1620
longjmp (g_fallback, 1);
1626
set_memory_sizes(DEFAULT_MEMORY_SIZE); set_default_paths();
1627
reset_switch_settings(); select_version(5);
1629
cli_files_specified = 0; no_compilations = 0;
1630
cli_file1 = "source"; cli_file2 = "output";
1632
read_command_line(argc, argv);
1634
if (cli_files_specified > 0)
1635
{ return_code = compile(cli_files_specified, cli_file1, cli_file2);
1637
if (return_code != 0) return(return_code);
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);
1648
/* ========================================================================= */