1
/* ------------------------------------------------------------------------- */
2
/* "inform" : The top level of Inform: switches, pathnames, filenaming */
3
/* conventions, ICL (Inform Command Line) files, main */
5
/* Part of Inform 6.31 */
6
/* copyright (c) Graham Nelson 1993 - 2006 */
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[PATHLEN]; /* Processed name of first input file */
263
char Code_Name[PATHLEN]; /* 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 (i == PATHLEN-1) {
433
printf("A specified path is longer than %d characters.\n",
437
if (value[j-1] == 0) return;
439
else path[i++] = value[j++];
443
static void set_default_paths(void)
445
set_path_value(Source_Path, Source_Directory);
446
set_path_value(Include_Path, Include_Directory);
447
set_path_value(Code_Path, Code_Directory);
448
set_path_value(Module_Path, Module_Directory);
449
set_path_value(ICL_Path, ICL_Directory);
450
set_path_value(Temporary_Path, Temporary_Directory);
451
set_path_value(Debugging_Name, Debugging_File);
452
set_path_value(Transcript_Name, Transcript_File);
453
set_path_value(Language_Name, "English");
454
set_path_value(Charset_Map, "");
457
static void set_path_command(char *command)
458
{ int i, j; char *path_to_set = NULL, *new_value;
459
for (i=0; (command[i]!=0) && (command[i]!='=');i++) ;
461
if (command[i]==0) { new_value=command; path_to_set=Include_Path; }
463
{ char pathname[PATHLEN];
464
if (i>=PATHLEN) i=PATHLEN-1;
465
new_value = command+i+1;
467
if (isupper(command[j])) pathname[j]=tolower(command[j]);
468
else pathname[j]=command[j];
471
if (strcmp(pathname, "source_path")==0) path_to_set=Source_Path;
472
if (strcmp(pathname, "include_path")==0) path_to_set=Include_Path;
473
if (strcmp(pathname, "code_path")==0) path_to_set=Code_Path;
474
if (strcmp(pathname, "module_path")==0) path_to_set=Module_Path;
475
if (strcmp(pathname, "icl_path")==0) path_to_set=ICL_Path;
476
if (strcmp(pathname, "temporary_path")==0) path_to_set=Temporary_Path;
477
if (strcmp(pathname, "debugging_name")==0) path_to_set=Debugging_Name;
478
if (strcmp(pathname, "transcript_name")==0) path_to_set=Transcript_Name;
479
if (strcmp(pathname, "language_name")==0) path_to_set=Language_Name;
480
if (strcmp(pathname, "charset_map")==0) path_to_set=Charset_Map;
482
if (path_to_set == NULL)
483
{ printf("No such path setting as \"%s\"\n", pathname);
488
set_path_value(path_to_set, new_value);
491
static int contains_separator(char *name)
493
for (i=0; name[i]!=0; i++)
494
if (name[i] == FN_SEP) return 1;
498
static int write_translated_name(char *new_name, char *old_name,
499
char *prefix_path, int start_pos,
502
if (strlen(old_name)+strlen(extension) >= PATHLEN) {
503
printf("One of your filenames is longer than %d characters.\n", PATHLEN);
506
if (prefix_path == NULL)
507
{ sprintf(new_name,"%s%s", old_name, extension);
510
strcpy(new_name, prefix_path + start_pos);
511
for (x=0; (new_name[x]!=0) && (new_name[x]!=FN_ALT); x++) ;
512
if (new_name[x] == 0) start_pos = 0; else start_pos += x+1;
513
if (x+strlen(old_name)+strlen(extension) >= PATHLEN) {
514
printf("One of your pathnames is longer than %d characters.\n", PATHLEN);
517
sprintf(new_name + x, "%s%s", old_name, extension);
521
#ifdef FILE_EXTENSIONS
522
static char *check_extension(char *name, char *extension)
525
/* If a filename ends in '.', remove the dot and add no file extension: */
527
if (name[i] == '.') { name[i]=0; return ""; }
529
/* Remove the new extension if it's already got one: */
531
for (; (i>=0) && (name[i]!=FN_SEP); i--)
532
if (name[i] == '.') return "";
537
/* ------------------------------------------------------------------------- */
538
/* Three translation routines have to deal with path variables which may */
539
/* contain alternative locations separated by the FN_ALT character. */
540
/* These have the protocol: */
542
/* int translate_*_filename(int last_value, ...) */
544
/* and should first be called with last_value equal to 0. If the */
545
/* translated filename works, fine. Otherwise, if the returned integer */
546
/* was zero, the caller knows that no filename works and can issue an */
547
/* error message. If it was non-zero, the caller should pass it on as */
548
/* the last_value again. */
550
/* As implemented below, last_value is the position in the path variable */
551
/* string at which the next directory name to try begins. */
552
/* ------------------------------------------------------------------------- */
554
extern int translate_in_filename(int last_value,
555
char *new_name, char *old_name,
556
int same_directory_flag, int command_line_flag)
557
{ char *prefix_path = NULL;
559
int add_path_flag = 1;
562
if ((same_directory_flag==0)
563
&& (contains_separator(old_name)==1)) add_path_flag=0;
565
if (add_path_flag==1)
566
{ if (command_line_flag == 0)
567
{ /* File is opened as a result of an Include directive */
569
if (same_directory_flag==1)
570
prefix_path = current_source_path;
572
if (Include_Path[0]!=0) prefix_path = Include_Path;
574
/* Main file being opened from the command line */
576
else if (Source_Path[0]!=0) prefix_path = Source_Path;
579
#ifdef FILE_EXTENSIONS
580
/* Which file extension is expected? */
582
if ((command_line_flag==1)||(same_directory_flag==1))
583
extension = Source_Extension;
585
extension = Include_Extension;
587
extension = check_extension(old_name, extension);
592
last_value = write_translated_name(new_name, old_name,
593
prefix_path, last_value, extension);
595
/* Set the "current source path" (for use of Include ">...") */
597
if (command_line_flag==1)
598
{ strcpy(current_source_path, new_name);
599
for (i=strlen(current_source_path)-1;
600
((i>0)&&(current_source_path[i]!=FN_SEP));i--) ;
602
if (i!=0) current_source_path[i+1] = 0; /* Current file in subdir */
603
else current_source_path[0] = 0; /* Current file at root dir */
609
extern int translate_link_filename(int last_value,
610
char *new_name, char *old_name)
611
{ char *prefix_path = NULL;
614
if (contains_separator(old_name)==0)
615
if (Module_Path[0]!=0)
616
prefix_path = Module_Path;
618
#ifdef FILE_EXTENSIONS
619
extension = check_extension(old_name, Module_Extension);
624
return write_translated_name(new_name, old_name,
625
prefix_path, last_value, extension);
628
static int translate_icl_filename(int last_value,
629
char *new_name, char *old_name)
630
{ char *prefix_path = NULL;
631
char *extension = "";
633
if (contains_separator(old_name)==0)
635
prefix_path = ICL_Path;
637
#ifdef FILE_EXTENSIONS
638
extension = check_extension(old_name, ICL_Extension);
641
return write_translated_name(new_name, old_name,
642
prefix_path, last_value, extension);
645
extern void translate_out_filename(char *new_name, char *old_name)
647
char *extension = "";
650
/* If !convert_filename_flag, then the old_name is just the <file2>
651
parameter on the Inform command line, which we leave alone. */
653
if (!convert_filename_flag)
654
{ strcpy(new_name, old_name); return;
657
/* Remove any pathname or extension in <file1>. */
659
if (contains_separator(old_name)==1)
660
{ for (i=strlen(old_name)-1; (i>=0)&&(old_name[i]!=FN_SEP) ;i--) ;
661
if (old_name[i]==FN_SEP) i++;
664
#ifdef FILE_EXTENSIONS
665
for (i=strlen(old_name)-1; (i>=0)&&(old_name[i]!='.') ;i--) ;
666
if (old_name[i] == '.') old_name[i] = 0;
671
{ extension = Module_Extension;
672
if (Module_Path[0]!=0) prefix_path = Module_Path;
677
switch(version_number)
678
{ case 3: extension = Code_Extension; break;
679
case 4: extension = V4Code_Extension; break;
680
case 5: extension = V5Code_Extension; break;
681
case 6: extension = V6Code_Extension; break;
682
case 7: extension = V7Code_Extension; break;
683
case 8: extension = V8Code_Extension; break;
687
extension = GlulxCode_Extension;
689
if (Code_Path[0]!=0) prefix_path = Code_Path;
692
#ifdef FILE_EXTENSIONS
693
extension = check_extension(old_name, extension);
696
write_translated_name(new_name, old_name, prefix_path, 0, extension);
699
static char *name_or_unset(char *p)
700
{ if (p[0]==0) return "(unset)";
704
static void help_on_filenames(void)
705
{ char old_name[PATHLEN];
706
char new_name[PATHLEN];
707
int save_mm = module_switch, x;
709
module_switch = FALSE;
711
printf("Help information on filenames:\n\n");
714
"The command line can take one of two forms:\n\n\
715
inform [commands...] <file1>\n\
716
inform [commands...] <file1> <file2>\n\n\
717
Inform translates <file1> into a source file name (see below) for its input.\n\
718
<file2> is usually omitted: if so, the output filename is made from <file1>\n\
719
by cutting out the name part and translating that (see below).\n\
720
If <file2> is given, however, the output filename is set to just <file2>\n\
721
(not altered in any way).\n\n");
724
"Filenames given in the game source (with commands like Include \"name\" and\n\
725
Link \"name\") are also translated by the rules below.\n\n");
728
"Rules of translation:\n\n\
729
Inform translates plain filenames (such as \"xyzzy\") into full pathnames\n\
730
(such as \"adventure%cgames%cxyzzy\") according to the following rules.\n\n\
731
1. If the name contains a '%c' character (so it's already a pathname), it\n\
732
isn't changed.\n\n", FN_SEP, FN_SEP, FN_SEP);
735
" [Exception: when the name is given in an Include command using the >\n\
736
form (such as Include \">prologue\"), the \">\" is replaced by the path\n\
737
of the file doing the inclusion");
738
#ifdef FILE_EXTENSIONS
739
printf(" and a suitable file extension is added");
744
" Filenames must never contain double-quotation marks \". To use filenames\n\
745
which contain spaces, write them in double-quotes: for instance,\n\n\
746
\"inform +code_path=\"Jigsaw Final Version\" jigsaw\".\n\n");
749
"2. The file is looked for at a particular \"path\" (the filename of a\n\
750
directory), depending on what kind of file it is.\n\n\
751
File type Name Current setting\n\n\
752
Source code (in) source_path %s\n\
753
Include file (in) include_path %s\n\
754
Story file (out) code_path %s\n",
755
name_or_unset(Source_Path), name_or_unset(Include_Path),
756
name_or_unset(Code_Path));
759
" Temporary file (out) temporary_path %s\n\
760
ICL command file (in) icl_path %s\n\
761
Module (in & out) module_path %s\n\n",
762
name_or_unset(Temporary_Path),
763
name_or_unset(ICL_Path), name_or_unset(Module_Path));
766
" If the path is unset, then the current working directory is used (so\n\
767
the filename doesn't change): if, for instance, include_path is set to\n\
768
\"backup%coldlib\" then when \"parser\" is included it is looked for at\n\
769
\"backup%coldlib%cparser\".\n\n\
770
The paths can be set or unset on the Inform command line by, eg,\n\
771
\"inform +code_path=finished jigsaw\" or\n\
772
\"inform +include_path= balances\" (which unsets include_path).\n\n",
773
FN_SEP, FN_SEP, FN_SEP);
776
" The four input path variables can be set to lists of alternative paths\n\
777
separated by '%c' characters: these alternatives are always tried in\n\
778
the order they are specified in, that is, left to right through the text\n\
779
in the path variable.\n\
780
(Modules are written to the first alternative in the module_path list;\n\
781
it is an error to give alternatives at all for purely output paths.)\n\n",
784
#ifdef FILE_EXTENSIONS
785
printf("3. The following file extensions are added:\n\n\
788
Story files: %s (Version 3), %s (v4), %s (v5, the default),\n\
789
%s (v6), %s (v7), %s (v8), %s (Glulx)\n\
790
Temporary files: .tmp\n\
792
Source_Extension, Include_Extension,
793
Code_Extension, V4Code_Extension, V5Code_Extension, V6Code_Extension,
794
V7Code_Extension, V8Code_Extension, GlulxCode_Extension,
797
except that any extension you give (on the command line or in a filename\n\
798
used in a program) will override these. If you give the null extension\n\
799
\".\" then Inform uses no file extension at all (removing the \".\").\n\n");
802
printf("Names of four individual files can also be set using the same\n\
803
+ command notation (though they aren't really pathnames). These are:\n\n\
804
transcript_name (text written by -r switch): now \"%s\"\n\
805
debugging_name (data written by -k switch): now \"%s\"\n\
806
language_name (library file defining natural language of game):\n\
808
charset_map (file for character set mapping): now \"%s\"\n\n",
809
Transcript_Name, Debugging_Name, Language_Name, Charset_Map);
811
translate_in_filename(0, new_name, "rezrov", 0, 1);
812
printf("Examples: 1. \"inform rezrov\"\n\
813
the source code is read from \"%s\"\n",
815
convert_filename_flag = TRUE;
816
translate_out_filename(new_name, "rezrov");
817
printf(" and a story file is compiled to \"%s\".\n\n", new_name);
819
translate_in_filename(0, new_name, "frotz", 0, 1);
820
printf("2. \"inform -M frotz\"\n\
821
the source code is read from \"%s\"\n",
823
module_switch = TRUE;
824
convert_filename_flag = TRUE;
825
translate_out_filename(new_name, "frotz");
826
printf(" and a module is compiled to \"%s\".\n\n", new_name);
828
module_switch = FALSE;
830
sprintf(old_name, "demos%cplugh", FN_SEP);
831
printf("3. \"inform %s\"\n", old_name);
832
translate_in_filename(0, new_name, old_name, 0, 1);
833
printf(" the source code is read from \"%s\"\n", new_name);
834
sprintf(old_name, "demos%cplugh", FN_SEP);
835
convert_filename_flag = TRUE;
836
translate_out_filename(new_name, old_name);
837
printf(" and a story file is compiled to \"%s\".\n\n", new_name);
839
printf("4. \"inform plover my_demo\"\n");
840
translate_in_filename(0, new_name, "plover", 0, 1);
841
printf(" the source code is read from \"%s\"\n", new_name);
842
convert_filename_flag = FALSE;
843
translate_out_filename(new_name, "my_demo");
844
printf(" and a story file is compiled to \"%s\".\n\n", new_name);
846
strcpy(old_name, Source_Path);
847
sprintf(new_name, "%cnew%cold%crecent%cold%cancient",
848
FN_ALT, FN_ALT, FN_SEP, FN_ALT, FN_SEP);
849
printf("5. \"inform +source_path=%s zooge\"\n", new_name);
851
" Note that four alternative paths are given, the first being the empty\n\
852
path-name (meaning: where you are now). Inform looks for the source code\n\
853
by trying these four places in turn, stopping when it finds anything:\n\n");
855
set_path_value(Source_Path, new_name);
858
{ x = translate_in_filename(x, new_name, "zooge", 0, 1);
859
printf(" \"%s\"\n", new_name);
861
strcpy(Source_Path, old_name);
862
module_switch = save_mm;
865
/* ------------------------------------------------------------------------- */
866
/* Naming temporary files */
867
/* (Arguably temporary files should be made using "tmpfile" in */
868
/* the ANSI C library, but many supposed ANSI libraries lack it.) */
869
/* ------------------------------------------------------------------------- */
871
extern void translate_temp_filename(int i)
874
{ case 1: p=Temp1_Name; break;
875
case 2: p=Temp2_Name; break;
876
case 3: p=Temp3_Name; break;
878
if (strlen(Temporary_Path)+strlen(Temporary_File)+6 >= PATHLEN) {
879
printf ("Temporary_Path is too long.\n");
882
sprintf(p,"%s%s%d", Temporary_Path, Temporary_File, i);
883
#ifdef INCLUDE_TASK_ID
884
sprintf(p+strlen(p), "_proc%08lx", (long int) unique_task_id());
886
#ifdef FILE_EXTENSIONS
887
sprintf(p+strlen(p), ".tmp");
892
static char riscos_ft_buffer[4];
894
extern char *riscos_file_type(void)
896
if (riscos_file_type_format == 1)
897
{ if (module_switch) return("data");
901
if (module_switch) return("075");
903
sprintf(riscos_ft_buffer, "%03x", 0x60 + version_number);
904
return(riscos_ft_buffer);
908
/* ------------------------------------------------------------------------- */
909
/* The compilation pass */
910
/* ------------------------------------------------------------------------- */
912
static void run_pass(void)
914
lexer_begin_prepass();
915
files_begin_prepass();
916
load_sourcefile(Source_Name, 0);
923
issue_unused_warnings();
927
if (module_switch) linker_endpass();
930
if (hash_switch && hash_printed_since_newline) printf("\n");
932
if (temporary_files_switch)
933
{ if (module_switch) flush_link_data();
937
construct_storyfile();
940
int output_has_occurred;
942
static void rennab(int32 time_taken)
943
{ /* rennab = reverse of banner */
945
int t = no_warnings + no_suppressed_warnings;
947
if (memout_switch) print_memory_usage();
949
if ((no_errors + t)!=0)
950
{ printf("Compiled with ");
952
{ printf("%d error%s", no_errors,(no_errors==1)?"":"s");
953
if (t > 0) printf(" and ");
956
printf("%d warning%s", t, (t==1)?"":"s");
957
if (no_suppressed_warnings > 0)
958
{ if (no_warnings > 0)
959
printf(" (%d suppressed)", no_suppressed_warnings);
961
printf("%d suppressed warning%s", no_suppressed_warnings,
962
(no_suppressed_warnings==1)?"":"s");
964
if (output_has_occurred == FALSE) printf(" (no output)");
968
if (no_compiler_errors > 0) print_sorry_message();
970
if (statistics_switch)
971
printf("Completed in %ld seconds\n", (long int) time_taken);
974
/* ------------------------------------------------------------------------- */
975
/* The compiler abstracted to a routine. */
976
/* ------------------------------------------------------------------------- */
978
static int execute_icl_header(char *file1);
980
static int compile(int number_of_files_specified, char *file1, char *file2)
983
if (execute_icl_header(file1))
986
select_target(glulx_mode);
988
if (define_INFIX_switch && glulx_mode) {
989
printf("Infix (-X) facilities are not available in Glulx: \
990
disabling -X switch\n");
991
define_INFIX_switch = FALSE;
994
if (module_switch && glulx_mode) {
995
printf("Modules are not available in Glulx: \
996
disabling -M switch\n");
997
module_switch = FALSE;
1000
if (define_INFIX_switch && module_switch)
1001
{ printf("Infix (-X) facilities are not available when compiling \
1002
modules: disabling -X switch\n");
1003
define_INFIX_switch = FALSE;
1005
if (runtime_error_checking_switch && module_switch)
1006
{ printf("Strict checking (-S) facilities are not available when \
1007
compiling modules: disabling -S switch\n");
1008
runtime_error_checking_switch = FALSE;
1011
time_start=time(0); no_compilations++;
1013
strcpy(Source_Name, file1); convert_filename_flag = TRUE;
1014
strcpy(Code_Name, file1);
1015
if (number_of_files_specified == 2)
1016
{ strcpy(Code_Name, file2); convert_filename_flag = FALSE;
1022
if (debugfile_switch) begin_debug_file();
1023
if (transcript_switch) open_transcript_file(Source_Name);
1027
if (transcript_switch)
1028
{ write_dictionary_to_transcript();
1029
close_transcript_file();
1032
if (no_errors==0) { output_file(); output_has_occurred = TRUE; }
1033
else { output_has_occurred = FALSE; }
1035
if (debugfile_switch) close_debug_file();
1037
if (temporary_files_switch && (no_errors>0)) remove_temp_files();
1041
rennab((int32) (time(0)-time_start));
1043
if (optimise_switch) optimise_abbreviations();
1045
if (store_the_text) my_free(&all_text,"transcription text");
1047
return (no_errors==0)?0:1;
1050
/* ------------------------------------------------------------------------- */
1051
/* The command line interpreter */
1052
/* ------------------------------------------------------------------------- */
1054
static void cli_print_help(int help_level)
1057
"\nThis program is a compiler of Infocom format (also called \"Z-machine\")\n\
1058
story files: copyright (c) Graham Nelson 1993 - 2006.\n\n");
1060
/* For people typing just "inform", a summary only: */
1065
#ifndef PROMPT_INPUT
1066
printf("Usage: \"inform [commands...] <file1> [<file2>]\"\n\n");
1068
printf("When run, Inform prompts you for commands (and switches),\n\
1069
which are optional, then an input <file1> and an (optional) output\n\
1074
"<file1> is the Inform source file of the game to be compiled. <file2>,\n\
1075
if given, overrides the filename Inform would normally use for the\n\
1076
compiled output. Try \"inform -h1\" for file-naming conventions.\n\n\
1077
One or more words can be supplied as \"commands\". These may be:\n\n\
1078
-switches a list of compiler switches, 1 or 2 letter\n\
1079
(see \"inform -h2\" for the full range)\n\n\
1080
+dir set Include_Path to this directory\n\
1081
+PATH=dir change the PATH to this directory\n\n\
1082
$... one of the following memory commands:\n");
1084
" $list list current memory allocation settings\n\
1085
$huge make standard \"huge game\" settings %s\n\
1086
$large make standard \"large game\" settings %s\n\
1087
$small make standard \"small game\" settings %s\n\
1088
$?SETTING explain briefly what SETTING is for\n\
1089
$SETTING=number change SETTING to given number\n\n\
1090
(filename) read in a list of commands (in the format above)\n\
1091
from this \"setup file\"\n\n",
1092
(DEFAULT_MEMORY_SIZE==HUGE_SIZE)?"(default)":"",
1093
(DEFAULT_MEMORY_SIZE==LARGE_SIZE)?"(default)":"",
1094
(DEFAULT_MEMORY_SIZE==SMALL_SIZE)?"(default)":"");
1096
#ifndef PROMPT_INPUT
1097
printf("For example: \"inform -dexs $huge curses\".\n\n");
1101
"For fuller information, see the Inform Designer's Manual.\n");
1106
/* The -h1 (filenaming) help information: */
1108
if (help_level == 1) { help_on_filenames(); return; }
1110
/* The -h2 (switches) help information: */
1112
printf("Help on the full list of legal switch commands:\n\n\
1113
a trace assembly-language (without hex dumps; see -t)\n\
1114
c more concise error messages\n\
1115
d contract double spaces after full stops in text\n\
1116
d2 contract double spaces after exclamation and question marks, too\n\
1117
e economy mode (slower): make use of declared abbreviations\n");
1120
f frequencies mode: show how useful abbreviations are\n\
1121
g traces calls to functions (except in the library)\n\
1122
g2 traces calls to all functions\n\
1123
h print this information\n");
1126
i ignore default switches set within the file\n\
1127
j list objects as constructed\n\
1128
k output Infix debugging information to \"%s\" (and switch -D on)\n\
1129
l list every statement run through Inform\n\
1130
m say how much memory has been allocated\n\
1131
n print numbers of properties, attributes and actions\n",
1134
o print offset addresses\n\
1135
p give percentage breakdown of story file\n\
1136
q keep quiet about obsolete usages\n\
1137
r record all the text to \"%s\"\n\
1138
s give statistics\n\
1139
t trace assembly-language (with full hex dumps; see -a)\n",
1143
u work out most useful abbreviations (very very slowly)\n\
1144
v3 compile to version-3 (\"Standard\") story file\n\
1145
v4 compile to version-4 (\"Plus\") story file\n\
1146
v5 compile to version-5 (\"Advanced\") story file: the default\n\
1147
v6 compile to version-6 (graphical) story file\n\
1148
v8 compile to version-8 (expanded \"Advanced\") story file\n\
1149
w disable warning messages\n\
1150
x print # for every 100 lines compiled\n\
1151
y trace linking system\n\
1152
z print memory map of the Z-machine\n\n");
1155
B use big memory model (for large V6/V7 files)\n\
1156
C0 text character set is plain ASCII only\n\
1157
Cn text character set is ISO 8859-n (n = 1 to 9)\n\
1158
(1 to 4, Latin1 to Latin4; 5, Cyrillic; 6, Arabic;\n\
1159
7, Greek; 8, Hebrew; 9, Latin5. Default is -C1.)\n");
1160
printf(" D insert \"Constant DEBUG;\" automatically\n");
1161
printf(" E0 Archimedes-style error messages%s\n",
1162
(error_format==0)?" (current setting)":"");
1163
printf(" E1 Microsoft-style error messages%s\n",
1164
(error_format==1)?" (current setting)":"");
1165
printf(" E2 Macintosh MPW-style error messages%s\n",
1166
(error_format==2)?" (current setting)":"");
1167
#ifdef USE_TEMPORARY_FILES
1168
printf(" F0 use extra memory rather than temporary files\n");
1170
printf(" F1 use temporary files to reduce memory consumption\n");
1172
printf(" G compile a Glulx game file\n");
1173
printf(" H use Huffman encoding to compress Glulx strings\n");
1174
printf(" M compile as a Module for future linking\n");
1178
R0 use filetype 060 + version number for games (default)\n\
1179
R1 use official Acorn filetype 11A for all games\n");
1181
printf(" S compile strict error-checking at run-time (on by default)\n");
1182
#ifdef ARC_THROWBACK
1183
printf(" T enable throwback of errors in the DDE\n");
1185
printf(" U insert \"Constant USE_MODULES;\" automatically\n");
1186
printf(" Wn header extension table is at least n words (n = 3 to 99)\n");
1187
printf(" X compile with INFIX debugging facilities present\n");
1191
extern void switches(char *p, int cmode)
1192
{ int i, s=1, state;
1193
/* Here cmode is 0 if switches list is from a "Switches" directive
1194
and 1 if from a "-switches" command-line or ICL list */
1199
"Ignoring second word which should be a -list of switches.\n");
1203
for (i=cmode; p[i]!=0; i+=s, s=1)
1211
case 'a': asm_trace_setting = 1; break;
1212
case 'b': bothpasses_switch = state; break;
1213
case 'c': concise_switch = state; break;
1214
case 'd': switch(p[i+1])
1215
{ case '1': double_space_setting=1; s=2; break;
1216
case '2': double_space_setting=2; s=2; break;
1217
default: double_space_setting=1; break;
1220
case 'e': economy_switch = state; break;
1221
case 'f': frequencies_switch = state; break;
1222
case 'g': switch(p[i+1])
1223
{ case '1': trace_fns_setting=1; s=2; break;
1224
case '2': trace_fns_setting=2; s=2; break;
1225
default: trace_fns_setting=1; break;
1228
case 'h': switch(p[i+1])
1229
{ case '1': cli_print_help(1); s=2; break;
1230
case '2': cli_print_help(2); s=2; break;
1232
default: cli_print_help(0); break;
1235
case 'i': ignore_switches_switch = state; break;
1236
case 'j': listobjects_switch = state; break;
1237
case 'k': if (cmode == 0)
1238
error("The switch '-k' can't be set with 'Switches'");
1240
{ debugfile_switch = state;
1241
if (state) define_DEBUG_switch = TRUE;
1244
case 'l': listing_switch = state; break;
1245
case 'm': memout_switch = state; break;
1246
case 'n': printprops_switch = state; break;
1247
case 'o': offsets_switch = state; break;
1248
case 'p': percentages_switch = state; break;
1249
case 'q': obsolete_switch = state; break;
1250
case 'r': if (cmode == 0)
1251
error("The switch '-r' can't be set with 'Switches'");
1253
transcript_switch = state; break;
1254
case 's': statistics_switch = state; break;
1255
case 't': asm_trace_setting=2; break;
1256
case 'u': optimise_switch = state; break;
1257
case 'v': if ((cmode==0) && (version_set_switch)) { s=2; break; }
1258
version_set_switch = TRUE; s=2;
1260
{ case '3': select_version(3); break;
1261
case '4': select_version(4); break;
1262
case '5': select_version(5); break;
1263
case '6': select_version(6); break;
1264
case '7': select_version(7); break;
1265
case '8': select_version(8); break;
1266
default: printf("-v must be followed by 3 to 8\n");
1267
version_set_switch=0; s=1;
1271
case 'w': nowarnings_switch = state; break;
1272
case 'x': hash_switch = state; break;
1273
case 'y': s=2; linker_trace_setting=p[i+1]-'0'; break;
1274
case 'z': memory_map_switch = state; break;
1275
case 'B': oddeven_packing_switch = state; break;
1276
case 'C': s=2; character_set_setting=p[i+1]-'0';
1277
if ((character_set_setting < 0)
1278
|| (character_set_setting > 9))
1279
{ printf("-C must be followed by 0 to 9\n");
1280
character_set_setting = 1;
1282
if (cmode == 0) change_character_set();
1284
case 'D': define_DEBUG_switch = state; break;
1285
case 'E': switch(p[i+1])
1286
{ case '0': s=2; error_format=0; break;
1287
case '1': s=2; error_format=1; break;
1288
case '2': s=2; error_format=2; break;
1289
default: error_format=1; break;
1292
case 'F': switch(p[i+1])
1293
{ case '0': s=2; temporary_files_switch = FALSE; break;
1294
case '1': s=2; temporary_files_switch = TRUE; break;
1295
default: temporary_files_switch = state; break;
1298
case 'M': module_switch = state;
1299
if (state && (r_e_c_s_set == FALSE))
1300
runtime_error_checking_switch = FALSE;
1303
case 'R': switch(p[i+1])
1304
{ case '0': s=2; riscos_file_type_format=0; break;
1305
case '1': s=2; riscos_file_type_format=1; break;
1306
default: riscos_file_type_format=1; break;
1310
#ifdef ARC_THROWBACK
1311
case 'T': throwback_switch = state; break;
1313
case 'S': runtime_error_checking_switch = state;
1314
r_e_c_s_set = TRUE; break;
1315
case 'G': if (cmode == 0)
1316
error("The switch '-G' can't be set with 'Switches'");
1318
{ glulx_mode = state; /* ###- */
1319
adjust_memory_sizes();
1322
case 'H': compression_switch = state; break;
1323
case 'U': define_USE_MODULES_switch = state; break;
1324
case 'W': if ((p[i+1]>='0') && (p[i+1]<='9'))
1325
{ s=2; header_ext_setting = p[i+1]-'0';
1326
if ((p[i+2]>='0') && (p[i+2]<='9'))
1327
{ s=3; header_ext_setting *= 10;
1328
header_ext_setting += p[i+2]-'0';
1332
case 'X': define_INFIX_switch = state; break;
1334
printf("Switch \"-%c\" unknown (try \"inform -h2\" for the list)\n",
1340
if (optimise_switch && (!store_the_text))
1341
{ store_the_text=TRUE;
1344
printf("Allocation %ld bytes for transcription text\n",
1345
(long) MAX_TRANSCRIPT_SIZE);
1346
all_text = halloc(MAX_TRANSCRIPT_SIZE,1);
1347
malloced_bytes += MAX_TRANSCRIPT_SIZE;
1349
fatalerror("Can't hallocate memory for transcription text. Darn.");
1351
all_text=my_malloc(MAX_TRANSCRIPT_SIZE,"transcription text");
1356
static int icl_command(char *p)
1357
{ if ((p[0]=='+')||(p[0]=='-')||(p[0]=='$')
1358
|| ((p[0]=='(')&&(p[strlen(p)-1]==')')) ) return TRUE;
1362
static void icl_error(char *filename, int line)
1363
{ printf("Error in ICL file '%s', line %d:\n", filename, line);
1366
static void icl_header_error(char *filename, int line)
1367
{ printf("Error in ICL header of file '%s', line %d:\n", filename, line);
1370
static int copy_icl_word(char *from, char *to, int max)
1372
/* Copies one token from 'from' to 'to', null-terminated:
1373
returns the number of chars in 'from' read past (possibly 0). */
1375
int i, j, quoted_mode, truncated;
1377
i = 0; truncated = 0;
1378
while ((from[i] == ' ') || (from[i] == TAB_CHARACTER)
1379
|| (from[i] == (char) 10) || (from[i] == (char) 13)) i++;
1382
{ while (from[i] != 0) i++;
1383
to[0] = 0; return i;
1386
for (quoted_mode = FALSE, j=0;;)
1387
{ if (from[i] == 0) break;
1388
if (from[i] == 10) break;
1389
if (from[i] == 13) break;
1390
if (from[i] == TAB_CHARACTER) break;
1391
if ((from[i] == ' ') && (!quoted_mode)) break;
1392
if (from[i] == '\"') { quoted_mode = !quoted_mode; i++; }
1393
else to[j++] = from[i++];
1401
printf("The following parameter has been truncated:\n%s\n", to);
1405
static void execute_icl_command(char *p);
1407
static int execute_icl_header(char *argname)
1410
char cli_buff[256], fw[256];
1414
char filename[PATHLEN];
1418
{ x = translate_in_filename(x, filename, argname, 0, 1);
1419
command_file = fopen(filename,"r");
1420
} while ((command_file == NULL) && (x != 0));
1421
if (!command_file) {
1422
/* Fail silently. The regular compiler will try to open the file
1423
again, and report the problem. */
1427
while (feof(command_file)==0) {
1428
if (fgets(cli_buff,256,command_file)==0) break;
1430
if (!(cli_buff[0] == '!' && cli_buff[1] == '%'))
1432
i = copy_icl_word(cli_buff+2, fw, 256);
1433
if (icl_command(fw)) {
1434
execute_icl_command(fw);
1435
copy_icl_word(cli_buff+2 + i, fw, 256);
1436
if ((fw[0] != 0) && (fw[0] != '!')) {
1437
icl_header_error(filename, line);
1439
printf("expected comment or nothing but found '%s'\n", fw);
1444
icl_header_error(filename, line);
1446
printf("Expected command or comment but found '%s'\n", fw);
1450
fclose(command_file);
1452
return (errcount==0)?0:1;
1456
static void run_icl_file(char *filename, FILE *command_file)
1457
{ char cli_buff[256], fw[256];
1459
printf("[Running ICL file '%s']\n", filename);
1461
while (feof(command_file)==0)
1462
{ if (fgets(cli_buff,256,command_file)==0) break;
1464
i = copy_icl_word(cli_buff, fw, 256);
1465
if (icl_command(fw))
1466
{ execute_icl_command(fw);
1467
copy_icl_word(cli_buff + i, fw, 256);
1468
if ((fw[0] != 0) && (fw[0] != '!'))
1469
{ icl_error(filename, line);
1470
printf("expected comment or nothing but found '%s'\n", fw);
1474
{ if (strcmp(fw, "compile")==0)
1475
{ char story_name[PATHLEN], code_name[PATHLEN];
1476
i += copy_icl_word(cli_buff + i, story_name, PATHLEN);
1477
i += copy_icl_word(cli_buff + i, code_name, PATHLEN);
1479
if (code_name[0] != 0) x=2;
1480
else if (story_name[0] != 0) x=1;
1484
{ case 0: icl_error(filename, line);
1485
printf("No filename given to 'compile'\n");
1487
case 1: printf("[Compiling <%s>]\n", story_name);
1488
compile(x, story_name, code_name);
1490
case 2: printf("[Compiling <%s> to <%s>]\n",
1491
story_name, code_name);
1492
compile(x, story_name, code_name);
1493
copy_icl_word(cli_buff + i, fw, 256);
1495
{ icl_error(filename, line);
1496
printf("Expected comment or nothing but found '%s'\n",
1504
{ icl_error(filename, line);
1505
printf("Expected command or comment but found '%s'\n", fw);
1511
static void execute_icl_command(char *p)
1512
{ char filename[PATHLEN], cli_buff[256];
1516
{ case '+': set_path_command(p+1); break;
1517
case '-': switches(p,1); break;
1518
case '$': memory_command(p+1); break;
1519
case '(': strcpy(cli_buff,p+1); cli_buff[strlen(cli_buff)-1]=0;
1522
{ x = translate_icl_filename(x, filename, cli_buff);
1523
command_file = fopen(filename,"r");
1524
} while ((command_file == NULL) && (x != 0));
1526
if (command_file == NULL)
1527
printf("Error in ICL: Couldn't open command file '%s'\n",
1530
{ run_icl_file(filename, command_file);
1531
fclose(command_file);
1537
/* ------------------------------------------------------------------------- */
1538
/* Opening and closing banners */
1539
/* ------------------------------------------------------------------------- */
1541
char banner_line[80];
1543
static void banner(void)
1545
sprintf(banner_line, "Inform %d.%d%d",
1546
(VNUMBER/100)%10, (VNUMBER/10)%10, VNUMBER%10);
1548
sprintf(banner_line+strlen(banner_line), " (biplatform, G%d.%d%d)",
1549
(GLULX_RELEASE_NUMBER/100)%10, (GLULX_RELEASE_NUMBER/10)%10,
1550
GLULX_RELEASE_NUMBER%10);
1552
#ifdef MACHINE_STRING
1553
sprintf(banner_line+strlen(banner_line), " for %s", MACHINE_STRING);
1555
sprintf(banner_line+strlen(banner_line), " (%s)",
1557
printf("%s\n", banner_line);
1560
/* ------------------------------------------------------------------------- */
1561
/* Input from the outside world */
1562
/* ------------------------------------------------------------------------- */
1565
static void read_command_line(int argc, char **argv)
1567
char buffer1[PATHLEN], buffer2[PATHLEN], buffer3[PATHLEN];
1569
printf("Source filename?\n> ");
1570
while (gets(buffer1)==NULL); cli_file1=buffer1;
1571
printf("Output filename (RETURN for the same)?\n> ");
1572
while (gets(buffer2)==NULL); cli_file2=buffer2;
1573
cli_files_specified=1;
1574
if (buffer2[0]!=0) cli_files_specified=2;
1576
{ printf("List of commands (RETURN to finish; \"-h\" for help)?\n> ");
1577
while (gets(buffer3)==NULL); execute_icl_command(buffer3);
1578
} while (buffer3[0]!=0);
1581
static void read_command_line(int argc, char **argv)
1583
if (argc==1) switches("-h",1);
1585
for (i=1, cli_files_specified=0; i<argc; i++)
1586
if (icl_command(argv[i]))
1587
execute_icl_command(argv[i]);
1589
switch(++cli_files_specified)
1590
{ case 1: cli_file1 = argv[i]; break;
1591
case 2: cli_file2 = argv[i]; break;
1593
printf("Command line error: unknown parameter '%s'\n",
1599
/* ------------------------------------------------------------------------- */
1600
/* M A I N : An outer shell for machine-specific quirks */
1601
/* Omitted altogether if EXTERNAL_SHELL is defined, as for instance is */
1602
/* needed for the Macintosh front end. */
1603
/* ------------------------------------------------------------------------- */
1605
#ifdef EXTERNAL_SHELL
1606
extern int sub_main(int argc, char **argv);
1609
static int sub_main(int argc, char **argv);
1611
int main(int argc, char **argv, char *envp[])
1613
int main(int argc, char **argv)
1617
InitCursorCtl((acurHandle)NULL); Show_Cursor(WATCH_CURSOR);
1619
rcode = sub_main(argc, argv);
1620
#ifdef ARC_THROWBACK
1628
/* ------------------------------------------------------------------------- */
1629
/* M A I N II: Starting up ICL with the command line */
1630
/* ------------------------------------------------------------------------- */
1632
#ifdef EXTERNAL_SHELL
1633
extern int sub_main(int argc, char **argv)
1635
static int sub_main(int argc, char **argv)
1640
ProcessEvents (&g_proc);
1643
if (store_the_text) my_free(&all_text,"transcription text");
1644
longjmp (g_fallback, 1);
1650
set_memory_sizes(DEFAULT_MEMORY_SIZE); set_default_paths();
1651
reset_switch_settings(); select_version(5);
1653
cli_files_specified = 0; no_compilations = 0;
1654
cli_file1 = "source"; cli_file2 = "output";
1656
read_command_line(argc, argv);
1658
if (cli_files_specified > 0)
1659
{ return_code = compile(cli_files_specified, cli_file1, cli_file2);
1661
if (return_code != 0) return(return_code);
1664
if (no_compilations == 0)
1665
printf("\n[No compilation requested]\n");
1666
if (no_compilations > 1)
1667
printf("[%d compilations completed]\n", no_compilations);
1672
/* ========================================================================= */