/* "inform" : The top level of Inform: switches, pathnames, filenaming */
/* conventions, ICL (Inform Command Line) files, main */
/* */
-/* Part of Inform 6.35 */
-/* copyright (c) Graham Nelson 1993 - 2020 */
+/* Part of Inform 6.42 */
+/* copyright (c) Graham Nelson 1993 - 2024 */
/* */
/* Inform is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
-/* along with Inform. If not, see https://gnu.org/licenses/ *
+/* along with Inform. If not, see https://gnu.org/licenses/ */
/* */
/* ------------------------------------------------------------------------- */
int32 scale_factor, /* packed address multiplier */
length_scale_factor; /* length-in-header multiplier */
-int32 requested_glulx_version;
+int32 requested_glulx_version; /* version requested via -v switch */
+int32 final_glulx_version; /* requested version combined with game
+ feature requirements */
extern void select_version(int vn)
{ version_number = vn;
WORDSIZE = 2;
MAXINTWORD = 0x7FFF;
+ MAX_LOCAL_VARIABLES = 16; /* including "sp" */
+
if (INDIV_PROP_START != 64) {
INDIV_PROP_START = 64;
fatalerror("You cannot change INDIV_PROP_START in Z-code");
NUM_ATTR_BYTES = 6;
fatalerror("You cannot change NUM_ATTR_BYTES in Z-code");
}
- if (MAX_LOCAL_VARIABLES != 16) {
- MAX_LOCAL_VARIABLES = 16;
- fatalerror("You cannot change MAX_LOCAL_VARIABLES in Z-code");
- }
- if (MAX_GLOBAL_VARIABLES != 240) {
- MAX_GLOBAL_VARIABLES = 240;
- fatalerror("You cannot change MAX_GLOBAL_VARIABLES in Z-code");
- }
- if (MAX_VERBS > 255) {
- MAX_VERBS = 255;
- fatalerror("MAX_VERBS can only go above 255 when Glulx is used");
- }
}
else {
/* Glulx */
MAXINTWORD = 0x7FFFFFFF;
scale_factor = 0; /* It should never even get used in Glulx */
+ /* This could really be 120, since the practical limit is the size
+ of local_variables.keywords. But historically it's been 119. */
+ MAX_LOCAL_VARIABLES = 119; /* including "sp" */
+
if (INDIV_PROP_START < 256) {
INDIV_PROP_START = 256;
- warning_numbered("INDIV_PROP_START should be at least 256 in Glulx. Setting to", INDIV_PROP_START);
+ warning_fmt("INDIV_PROP_START should be at least 256 in Glulx; setting to %d", INDIV_PROP_START);
}
if (NUM_ATTR_BYTES % 4 != 3) {
NUM_ATTR_BYTES += (3 - (NUM_ATTR_BYTES % 4));
- warning_numbered("NUM_ATTR_BYTES must be a multiple of four, plus three. Increasing to", NUM_ATTR_BYTES);
+ warning_fmt("NUM_ATTR_BYTES must be a multiple of four, plus three; increasing to %d", NUM_ATTR_BYTES);
}
if (DICT_CHAR_SIZE != 1 && DICT_CHAR_SIZE != 4) {
DICT_CHAR_SIZE = 4;
- warning_numbered("DICT_CHAR_SIZE must be either 1 or 4. Setting to", DICT_CHAR_SIZE);
+ warning_fmt("DICT_CHAR_SIZE must be either 1 or 4; setting to %d", DICT_CHAR_SIZE);
}
}
- if (MAX_LOCAL_VARIABLES >= 120) {
- MAX_LOCAL_VARIABLES = 119;
- warning("MAX_LOCAL_VARIABLES cannot exceed 119; resetting to 119");
- /* This is because the keyword table in the lexer only has 120
- entries. */
- }
- if (DICT_WORD_SIZE > MAX_DICT_WORD_SIZE) {
- DICT_WORD_SIZE = MAX_DICT_WORD_SIZE;
- warning_numbered(
- "DICT_WORD_SIZE cannot exceed MAX_DICT_WORD_SIZE; resetting",
- MAX_DICT_WORD_SIZE);
- /* MAX_DICT_WORD_SIZE can be increased in header.h without fear. */
+ if (MAX_LOCAL_VARIABLES > MAX_KEYWORD_GROUP_SIZE) {
+ compiler_error("MAX_LOCAL_VARIABLES cannot exceed MAX_KEYWORD_GROUP_SIZE");
+ MAX_LOCAL_VARIABLES = MAX_KEYWORD_GROUP_SIZE;
}
+
if (NUM_ATTR_BYTES > MAX_NUM_ATTR_BYTES) {
NUM_ATTR_BYTES = MAX_NUM_ATTR_BYTES;
- warning_numbered(
- "NUM_ATTR_BYTES cannot exceed MAX_NUM_ATTR_BYTES; resetting",
+ warning_fmt(
+ "NUM_ATTR_BYTES cannot exceed MAX_NUM_ATTR_BYTES; resetting to %d",
MAX_NUM_ATTR_BYTES);
/* MAX_NUM_ATTR_BYTES can be increased in header.h without fear. */
}
if (!targ) {
/* Z-machine */
DICT_WORD_BYTES = DICT_WORD_SIZE;
- /* The Z-code generator doesn't use the following variables, although
- it would be a little cleaner if it did. */
OBJECT_BYTE_LENGTH = 0;
- DICT_ENTRY_BYTE_LENGTH = (version_number==3)?7:9;
+ DICT_ENTRY_BYTE_LENGTH = ((version_number==3)?7:9) - (ZCODE_LESS_DICT_DATA?1:0);
DICT_ENTRY_FLAG_POS = 0;
}
else {
DICT_ENTRY_FLAG_POS = (4+DICT_WORD_BYTES);
}
}
+
+ if (!targ) {
+ /* Z-machine */
+ /* The Z-machine's 96 abbreviations are used for these two purposes.
+ Make sure they are set consistently. If exactly one has been
+ set non-default, set the other to match. */
+ if (MAX_DYNAMIC_STRINGS == 32 && MAX_ABBREVS != 64) {
+ MAX_DYNAMIC_STRINGS = 96 - MAX_ABBREVS;
+ }
+ if (MAX_ABBREVS == 64 && MAX_DYNAMIC_STRINGS != 32) {
+ MAX_ABBREVS = 96 - MAX_DYNAMIC_STRINGS;
+ }
+ if (MAX_ABBREVS + MAX_DYNAMIC_STRINGS != 96
+ || MAX_ABBREVS < 0
+ || MAX_DYNAMIC_STRINGS < 0) {
+ warning("MAX_ABBREVS plus MAX_DYNAMIC_STRINGS must be 96 in Z-code; resetting both");
+ MAX_DYNAMIC_STRINGS = 32;
+ MAX_ABBREVS = 64;
+ }
+ }
}
/* ------------------------------------------------------------------------- */
/* Tracery: output control variables */
+/* (These are initially set to foo_trace_setting, but the Trace directive */
+/* can change them on the fly) */
/* ------------------------------------------------------------------------- */
int asm_trace_level, /* trace assembly: 0 for off, 1 for assembly
- only, 2 for full assembly tracing with hex dumps */
- line_trace_level, /* line tracing: 0 off, 1 on */
- expr_trace_level, /* expression tracing: 0 off, 1 full, 2 brief */
- linker_trace_level, /* set by -y: 0 to 4 levels of tracing */
- tokens_trace_level; /* lexer output tracing: 0 off, 1 on */
+ only, 2 for full assembly tracing with hex dumps,
+ 3 for branch shortening info, 4 for verbose
+ branch info */
+ expr_trace_level, /* expression tracing: 0 off, 1 on, 2/3 more */
+ tokens_trace_level; /* lexer output tracing: 0 off, 1 on, 2/3 more */
/* ------------------------------------------------------------------------- */
/* On/off switch variables (by default all FALSE); other switch settings */
+/* (Some of these have become numerical settings now) */
/* ------------------------------------------------------------------------- */
-int bothpasses_switch, /* -b */
- concise_switch, /* -c */
+int concise_switch, /* -c */
economy_switch, /* -e */
- frequencies_switch, /* -f */
+ frequencies_setting, /* $!FREQ, -f */
ignore_switches_switch, /* -i */
- listobjects_switch, /* -j */
debugfile_switch, /* -k */
- listing_switch, /* -l */
- memout_switch, /* -m */
- printprops_switch, /* -n */
- offsets_switch, /* -o */
- percentages_switch, /* -p */
+ memout_switch, /* $!MEM */
+ printprops_switch, /* $!PROPS */
+ printactions_switch, /* $!ACTIONS */
obsolete_switch, /* -q */
transcript_switch, /* -r */
- statistics_switch, /* -s */
+ statistics_switch, /* $!STATS, -s */
optimise_switch, /* -u */
version_set_switch, /* -v */
nowarnings_switch, /* -w */
hash_switch, /* -x */
- memory_map_switch, /* -z */
+ memory_map_setting, /* $!MAP, -z */
oddeven_packing_switch, /* -B */
define_DEBUG_switch, /* -D */
- temporary_files_switch, /* -F */
- module_switch, /* -M */
runtime_error_checking_switch, /* -S */
- define_USE_MODULES_switch, /* -U */
define_INFIX_switch; /* -X */
#ifdef ARC_THROWBACK
int throwback_switch; /* -T */
int character_set_setting, /* set by -C0 through -C9 */
character_set_unicode, /* set by -Cu */
error_format, /* set by -E */
- asm_trace_setting, /* set by -a and -t: value of
- asm_trace_level to use when tracing */
+ asm_trace_setting, /* $!ASM, -a: initial value of
+ asm_trace_level */
+ bpatch_trace_setting, /* $!BPATCH */
+ symdef_trace_setting, /* $!SYMDEF */
+ expr_trace_setting, /* $!EXPR: initial value of
+ expr_trace_level */
+ tokens_trace_setting, /* $!TOKENS: initial value of
+ tokens_trace_level */
+ optabbrevs_trace_setting, /* $!FINDABBREVS */
double_space_setting, /* set by -d: 0, 1 or 2 */
- trace_fns_setting, /* set by -g: 0, 1 or 2 */
- linker_trace_setting, /* set by -y: ditto for linker_... */
+ trace_fns_setting, /* $!RUNTIME, -g: 0, 1, 2, or 3 */
+ files_trace_setting, /* $!FILES */
+ list_verbs_setting, /* $!VERBS */
+ list_dict_setting, /* $!DICT */
+ list_objects_setting, /* $!OBJECTS */
+ list_symbols_setting, /* $!SYMBOLS */
store_the_text; /* when set, record game text to a chunk
- of memory (used by both -r & -k) */
+ of memory (used by -u) */
static int r_e_c_s_set; /* has -S been explicitly set? */
int glulx_mode; /* -G */
static void reset_switch_settings(void)
-{ asm_trace_setting=0;
- linker_trace_level=0;
- tokens_trace_level=0;
+{ asm_trace_setting = 0;
+ tokens_trace_setting = 0;
+ expr_trace_setting = 0;
+ bpatch_trace_setting = 0;
+ symdef_trace_setting = 0;
+ list_verbs_setting = 0;
+ list_dict_setting = 0;
+ list_objects_setting = 0;
+ list_symbols_setting = 0;
store_the_text = FALSE;
- bothpasses_switch = FALSE;
concise_switch = FALSE;
double_space_setting = 0;
economy_switch = FALSE;
- frequencies_switch = FALSE;
+ files_trace_setting = 0;
+ frequencies_setting = 0;
trace_fns_setting = 0;
ignore_switches_switch = FALSE;
- listobjects_switch = FALSE;
debugfile_switch = FALSE;
- listing_switch = FALSE;
- memout_switch = FALSE;
- printprops_switch = FALSE;
- offsets_switch = FALSE;
- percentages_switch = FALSE;
+ memout_switch = 0;
+ printprops_switch = 0;
+ printactions_switch = 0;
obsolete_switch = FALSE;
transcript_switch = FALSE;
statistics_switch = FALSE;
optimise_switch = FALSE;
+ optabbrevs_trace_setting = 0;
version_set_switch = FALSE;
nowarnings_switch = FALSE;
hash_switch = FALSE;
- memory_map_switch = FALSE;
+ memory_map_setting = 0;
oddeven_packing_switch = FALSE;
define_DEBUG_switch = FALSE;
-#ifdef USE_TEMPORARY_FILES
- temporary_files_switch = TRUE;
-#else
- temporary_files_switch = FALSE;
-#endif
- define_USE_MODULES_switch = FALSE;
- module_switch = FALSE;
#ifdef ARC_THROWBACK
throwback_switch = FALSE;
#endif
compression_switch = TRUE;
glulx_mode = FALSE;
requested_glulx_version = 0;
+ final_glulx_version = 0;
+
+ /* These aren't switches, but for clarity we reset them too. */
+ asm_trace_level = 0;
+ expr_trace_level = 0;
+ tokens_trace_level = 0;
}
/* ------------------------------------------------------------------------- */
init_expressp_vars();
init_files_vars();
init_lexer_vars();
- init_linker_vars();
init_memory_vars();
init_objects_vars();
init_states_vars();
files_begin_pass();
endofpass_flag = FALSE;
- line_trace_level = 0; expr_trace_level = 0;
+ expr_trace_level = expr_trace_setting;
asm_trace_level = asm_trace_setting;
- linker_trace_level = linker_trace_setting;
- if (listing_switch) line_trace_level=1;
+ tokens_trace_level = tokens_trace_setting;
lexer_begin_pass();
- linker_begin_pass();
memory_begin_pass();
objects_begin_pass();
states_begin_pass();
veneer_begin_pass();
verbs_begin_pass();
- if (!module_switch)
- {
- /* Compile a Main__ routine (see "veneer.c") */
-
- compile_initial_routine();
-
- /* Make the four metaclasses: Class must be object number 1, so
- it must come first */
-
- veneer_mode = TRUE;
-
- make_class("Class");
- make_class("Object");
- make_class("Routine");
- make_class("String");
-
- veneer_mode = FALSE;
- }
+ /* Compile a Main__ routine (see "veneer.c") */
+
+ compile_initial_routine();
+
+ /* Make the four metaclasses: Class must be object number 1, so
+ it must come first */
+
+ veneer_mode = TRUE;
+
+ make_class("Class");
+ make_class("Object");
+ make_class("Routine");
+ make_class("String");
+
+ veneer_mode = FALSE;
}
extern void allocate_arrays(void)
files_allocate_arrays();
lexer_allocate_arrays();
- linker_allocate_arrays();
memory_allocate_arrays();
objects_allocate_arrays();
states_allocate_arrays();
files_free_arrays();
lexer_free_arrays();
- linker_free_arrays();
memory_free_arrays();
objects_free_arrays();
states_free_arrays();
static char Source_Path[PATHLEN];
static char Include_Path[PATHLEN];
static char Code_Path[PATHLEN];
-static char Module_Path[PATHLEN];
-static char Temporary_Path[PATHLEN];
static char current_source_path[PATHLEN];
char Debugging_Name[PATHLEN];
char Transcript_Name[PATHLEN];
/* Set one of the above Path buffers to the given location, or list of
locations. (A list is comma-separated, and only accepted for Source_Path,
- Include_Path, ICL_Path, Module_Path.)
+ Include_Path, ICL_Path.)
*/
static void set_path_value(char *path, char *value)
{ int i, j;
if ((value[j] == FN_ALT) || (value[j] == 0))
{ if ((value[j] == FN_ALT)
&& (path != Source_Path) && (path != Include_Path)
- && (path != ICL_Path) && (path != Module_Path))
+ && (path != ICL_Path))
{ printf("The character '%c' is used to divide entries in a list \
-of possible locations, and can only be used in the Include_Path, Source_Path, \
-Module_Path or ICL_Path variables. Other paths are for output only.\n", FN_ALT);
+of possible locations, and can only be used in the Include_Path, Source_Path \
+or ICL_Path variables. Other paths are for output only.\n", FN_ALT);
exit(1);
}
if ((path != Debugging_Name) && (path != Transcript_Name)
/* Prepend the given location or list of locations to one of the above
Path buffers. This is only permitted for Source_Path, Include_Path,
- ICL_Path, Module_Path.
+ ICL_Path.
An empty field (in the comma-separated list) means the current
directory. If the Path buffer is entirely empty, we assume that
char new_path[PATHLEN];
if ((path != Source_Path) && (path != Include_Path)
- && (path != ICL_Path) && (path != Module_Path))
+ && (path != ICL_Path))
{ printf("The character '+' is used to add to a list \
-of possible locations, and can only be used in the Include_Path, Source_Path, \
-Module_Path or ICL_Path variables. Other paths are for output only.\n");
+of possible locations, and can only be used in the Include_Path, Source_Path \
+or ICL_Path variables. Other paths are for output only.\n");
exit(1);
}
set_path_value(Source_Path, Source_Directory);
set_path_value(Include_Path, Include_Directory);
set_path_value(Code_Path, Code_Directory);
- set_path_value(Module_Path, Module_Directory);
set_path_value(ICL_Path, ICL_Directory);
- set_path_value(Temporary_Path, Temporary_Directory);
set_path_value(Debugging_Name, Debugging_File);
set_path_value(Transcript_Name, Transcript_File);
set_path_value(Language_Name, Default_Language);
if (strcmp(pathname, "source_path")==0) path_to_set=Source_Path;
if (strcmp(pathname, "include_path")==0) path_to_set=Include_Path;
if (strcmp(pathname, "code_path")==0) path_to_set=Code_Path;
- if (strcmp(pathname, "module_path")==0) path_to_set=Module_Path;
if (strcmp(pathname, "icl_path")==0) path_to_set=ICL_Path;
- if (strcmp(pathname, "temporary_path")==0) path_to_set=Temporary_Path;
if (strcmp(pathname, "debugging_name")==0) path_to_set=Debugging_Name;
if (strcmp(pathname, "transcript_name")==0) path_to_set=Transcript_Name;
if (strcmp(pathname, "language_name")==0) path_to_set=Language_Name;
return last_value;
}
-extern int translate_link_filename(int last_value,
- char *new_name, char *old_name)
-{ char *prefix_path = NULL;
- char *extension;
-
- if (contains_separator(old_name)==0)
- if (Module_Path[0]!=0)
- prefix_path = Module_Path;
-
-#ifdef FILE_EXTENSIONS
- extension = check_extension(old_name, Module_Extension);
-#else
- extension = "";
-#endif
-
- return write_translated_name(new_name, old_name,
- prefix_path, last_value, extension);
-}
-
static int translate_icl_filename(int last_value,
char *new_name, char *old_name)
{ char *prefix_path = NULL;
#endif
prefix_path = NULL;
- if (module_switch)
- { extension = Module_Extension;
- if (Module_Path[0]!=0) prefix_path = Module_Path;
- }
- else
- {
- if (!glulx_mode) {
- switch(version_number)
- { case 3: extension = Code_Extension; break;
- case 4: extension = V4Code_Extension; break;
- case 5: extension = V5Code_Extension; break;
- case 6: extension = V6Code_Extension; break;
- case 7: extension = V7Code_Extension; break;
- case 8: extension = V8Code_Extension; break;
- }
- }
- else {
- extension = GlulxCode_Extension;
+
+ if (!glulx_mode) {
+ switch(version_number)
+ { case 3: extension = Code_Extension; break;
+ case 4: extension = V4Code_Extension; break;
+ case 5: extension = V5Code_Extension; break;
+ case 6: extension = V6Code_Extension; break;
+ case 7: extension = V7Code_Extension; break;
+ case 8: extension = V8Code_Extension; break;
}
- if (Code_Path[0]!=0) prefix_path = Code_Path;
}
+ else {
+ extension = GlulxCode_Extension;
+ }
+ if (Code_Path[0]!=0) prefix_path = Code_Path;
#ifdef FILE_EXTENSIONS
extension = check_extension(old_name, extension);
static void help_on_filenames(void)
{ char old_name[PATHLEN];
char new_name[PATHLEN];
- int save_mm = module_switch, x;
-
- module_switch = FALSE;
+ int x;
printf("Help information on filenames:\n\n");
(not altered in any way).\n\n");
printf(
-"Filenames given in the game source (with commands like Include \"name\" and\n\
-Link \"name\") are also translated by the rules below.\n\n");
+"Filenames given in the game source (with commands like Include \"name\")\n\
+are also translated by the rules below.\n\n");
printf(
"Rules of translation:\n\n\
name_or_unset(Code_Path));
printf(
-" Temporary file (out) temporary_path %s\n\
- ICL command file (in) icl_path %s\n\
- Module (in & out) module_path %s\n\n",
- name_or_unset(Temporary_Path),
- name_or_unset(ICL_Path), name_or_unset(Module_Path));
+" ICL command file (in) icl_path %s\n\n",
+ name_or_unset(ICL_Path));
printf(
" If the path is unset, then the current working directory is used (so\n\
" If two '+' signs are used (\"inform ++include_path=dir jigsaw\") then\n\
the path or paths are added to the existing list.\n\n");
printf(
-" (Modules are written to the first alternative in the module_path list;\n\
- it is an error to give alternatives at all for purely output paths.)\n\n");
+" (It is an error to give alternatives at all for purely output paths.)\n\n");
#ifdef FILE_EXTENSIONS
printf("3. The following file extensions are added:\n\n\
Source code: %s\n\
Include files: %s\n\
Story files: %s (Version 3), %s (v4), %s (v5, the default),\n\
- %s (v6), %s (v7), %s (v8), %s (Glulx)\n\
- Temporary files: .tmp\n\
- Modules: %s\n\n",
+ %s (v6), %s (v7), %s (v8), %s (Glulx)\n\n",
Source_Extension, Include_Extension,
Code_Extension, V4Code_Extension, V5Code_Extension, V6Code_Extension,
- V7Code_Extension, V8Code_Extension, GlulxCode_Extension,
- Module_Extension);
+ V7Code_Extension, V8Code_Extension, GlulxCode_Extension);
printf("\
except that any extension you give (on the command line or in a filename\n\
used in a program) will override these. If you give the null extension\n\
translate_out_filename(new_name, "rezrov");
printf(" and a story file is compiled to \"%s\".\n\n", new_name);
- translate_in_filename(0, new_name, "frotz", 0, 1);
- printf("2. \"inform -M frotz\"\n\
- the source code is read from \"%s\"\n",
- new_name);
- module_switch = TRUE;
- convert_filename_flag = TRUE;
- translate_out_filename(new_name, "frotz");
- printf(" and a module is compiled to \"%s\".\n\n", new_name);
-
- module_switch = FALSE;
-
sprintf(old_name, "demos%cplugh", FN_SEP);
- printf("3. \"inform %s\"\n", old_name);
+ printf("2. \"inform %s\"\n", old_name);
translate_in_filename(0, new_name, old_name, 0, 1);
printf(" the source code is read from \"%s\"\n", new_name);
sprintf(old_name, "demos%cplugh", FN_SEP);
translate_out_filename(new_name, old_name);
printf(" and a story file is compiled to \"%s\".\n\n", new_name);
- printf("4. \"inform plover my_demo\"\n");
+ printf("3. \"inform plover my_demo\"\n");
translate_in_filename(0, new_name, "plover", 0, 1);
printf(" the source code is read from \"%s\"\n", new_name);
convert_filename_flag = FALSE;
strcpy(old_name, Source_Path);
sprintf(new_name, "%cnew%cold%crecent%cold%cancient",
FN_ALT, FN_ALT, FN_SEP, FN_ALT, FN_SEP);
- printf("5. \"inform +source_path=%s zooge\"\n", new_name);
+ printf("4. \"inform +source_path=%s zooge\"\n", new_name);
printf(
" Note that four alternative paths are given, the first being the empty\n\
path-name (meaning: where you are now). Inform looks for the source code\n\
printf(" \"%s\"\n", new_name);
} while (x != 0);
strcpy(Source_Path, old_name);
- module_switch = save_mm;
-}
-
-/* ------------------------------------------------------------------------- */
-/* Naming temporary files */
-/* (Arguably temporary files should be made using "tmpfile" in */
-/* the ANSI C library, but many supposed ANSI libraries lack it.) */
-/* ------------------------------------------------------------------------- */
-
-extern void translate_temp_filename(int i)
-{ char *p = NULL;
- switch(i)
- { case 1: p=Temp1_Name; break;
- case 2: p=Temp2_Name; break;
- case 3: p=Temp3_Name; break;
- }
- if (strlen(Temporary_Path)+strlen(Temporary_File)+6 >= PATHLEN) {
- printf ("Temporary_Path is too long.\n");
- exit(1);
- }
- sprintf(p,"%s%s%d", Temporary_Path, Temporary_File, i);
-#ifdef INCLUDE_TASK_ID
- sprintf(p+strlen(p), "_proc%08lx", (long int) unique_task_id());
-#endif
-#ifdef FILE_EXTENSIONS
- sprintf(p+strlen(p), ".tmp");
-#endif
}
#ifdef ARCHIMEDES
extern char *riscos_file_type(void)
{
if (riscos_file_type_format == 1)
- { if (module_switch) return("data");
+ {
return("11A");
}
- if (module_switch) return("075");
-
sprintf(riscos_ft_buffer, "%03x", 0x60 + version_number);
return(riscos_ft_buffer);
}
compile_veneer();
lexer_endpass();
- if (module_switch) linker_endpass();
+ issue_debug_symbol_warnings();
+
close_all_source();
if (hash_switch && hash_printed_since_newline) printf("\n");
- if (temporary_files_switch)
- { if (module_switch) flush_link_data();
- check_temp_files();
- }
sort_dictionary();
if (track_unused_routines)
locate_dead_functions();
+ locate_dead_grammar_lines();
construct_storyfile();
}
int output_has_occurred;
-static void rennab(int32 time_taken)
+static void rennab(float time_taken)
{ /* rennab = reverse of banner */
-
int t = no_warnings + no_suppressed_warnings;
if (memout_switch) print_memory_usage();
if (no_compiler_errors > 0) print_sorry_message();
if (statistics_switch)
- printf("Completed in %ld seconds\n", (long int) time_taken);
+ {
+ /* Print the duration to a sensible number of decimal places.
+ (We aim for three significant figures.) */
+ if (time_taken >= 10.0)
+ printf("Completed in %.1f seconds\n", time_taken);
+ else if (time_taken >= 1.0)
+ printf("Completed in %.2f seconds\n", time_taken);
+ else
+ printf("Completed in %.3f seconds\n", time_taken);
+ }
}
/* ------------------------------------------------------------------------- */
static int execute_icl_header(char *file1);
static int compile(int number_of_files_specified, char *file1, char *file2)
-{ int32 time_start;
+{
+ TIMEVALUE time_start, time_end;
+ float duration;
if (execute_icl_header(file1))
return 1;
define_INFIX_switch = FALSE;
}
- if (module_switch && glulx_mode) {
- printf("Modules are not available in Glulx: \
-disabling -M switch\n");
- module_switch = FALSE;
- }
-
- if (define_INFIX_switch && module_switch)
- { printf("Infix (-X) facilities are not available when compiling \
-modules: disabling -X switch\n");
- define_INFIX_switch = FALSE;
- }
- if (runtime_error_checking_switch && module_switch)
- { printf("Strict checking (-S) facilities are not available when \
-compiling modules: disabling -S switch\n");
- runtime_error_checking_switch = FALSE;
- }
-
- time_start=time(0); no_compilations++;
+ TIMEVALUE_NOW(&time_start);
+
+ no_compilations++;
strcpy(Source_Name, file1); convert_filename_flag = TRUE;
strcpy(Code_Name, file1);
run_pass();
+ if (no_errors==0) { output_file(); output_has_occurred = TRUE; }
+ else { output_has_occurred = FALSE; }
+
if (transcript_switch)
{ write_dictionary_to_transcript();
close_transcript_file();
}
- if (no_errors==0) { output_file(); output_has_occurred = TRUE; }
- else { output_has_occurred = FALSE; }
-
if (debugfile_switch)
{ end_debug_file();
}
- if (temporary_files_switch && (no_errors>0)) remove_temp_files();
+ if (optimise_switch) {
+ /* Pull out all_text so that it will not be freed. */
+ extract_all_text();
+ }
free_arrays();
- rennab((int32) (time(0)-time_start));
-
- if (optimise_switch) optimise_abbreviations();
+ TIMEVALUE_NOW(&time_end);
+ duration = TIMEVALUE_DIFFERENCE(&time_start, &time_end);
+
+ rennab(duration);
- if (store_the_text) my_free(&all_text,"transcription text");
+ if (optimise_switch) {
+ optimise_abbreviations();
+ ao_free_arrays();
+ }
return (no_errors==0)?0:1;
}
printf(
"\nThis program is a compiler of Infocom format (also called \"Z-machine\")\n\
story files, as well as \"Glulx\" story files:\n\
-Copyright (c) Graham Nelson 1993 - 2020.\n\n");
+Copyright (c) Graham Nelson 1993 - 2024.\n\n");
/* For people typing just "inform", a summary only: */
++dir add this directory to Include_Path\n\
+PATH=dir change the PATH to this directory\n\
++PATH=dir add this directory to the PATH\n\n\
- $... one of the following memory commands:\n");
+ $... one of the following configuration commands:\n");
printf(
-" $list list current memory allocation settings\n\
- $huge make standard \"huge game\" settings %s\n\
- $large make standard \"large game\" settings %s\n\
- $small make standard \"small game\" settings %s\n\
+" $list list current settings\n\
$?SETTING explain briefly what SETTING is for\n\
- $SETTING=number change SETTING to given number\n\n",
- (DEFAULT_MEMORY_SIZE==HUGE_SIZE)?"(default)":"",
- (DEFAULT_MEMORY_SIZE==LARGE_SIZE)?"(default)":"",
- (DEFAULT_MEMORY_SIZE==SMALL_SIZE)?"(default)":"");
+ $SETTING=number change SETTING to given number\n\
+ $!TRACEOPT set trace option TRACEOPT\n\
+ (or $!TRACEOPT=2, 3, etc for more tracing;\n\
+ $! by itself to list all trace options)\n\
+ $#SYMBOL=number define SYMBOL as a constant in the story\n\n");
printf(
" (filename) read in a list of commands (in the format above)\n\
printf("Alternate command-line formats for the above:\n\
--help (this page)\n\
- --path PATH=dir\n\
- --addpath PATH=dir\n\
- --list\n\
- --size huge, --size large, --size small\n\
- --helpopt SETTING\n\
- --opt SETTING=number\n\
- --config filename (setup file)\n\n");
+ --path PATH=dir (set path)\n\
+ --addpath PATH=dir (add to path)\n\
+ --list (list current settings)\n\
+ --helpopt SETTING (explain setting)\n\
+ --opt SETTING=number (change setting)\n\
+ --helptrace (list all trace options)\n\
+ --trace TRACEOPT (set trace option)\n\
+ --trace TRACEOPT=num (more tracing)\n\
+ --define SYMBOL=number (define constant)\n\
+ --config filename (read setup file)\n\n");
#ifndef PROMPT_INPUT
- printf("For example: \"inform -dexs $huge curses\".\n");
+ printf("For example: \"inform -dexs curses\".\n");
#endif
return;
/* The -h2 (switches) help information: */
printf("Help on the full list of legal switch commands:\n\n\
- a trace assembly-language (without hex dumps; see -t)\n\
+ a trace assembly-language\n\
+ a2 trace assembly with hex dumps\n\
c more concise error messages\n\
d contract double spaces after full stops in text\n\
d2 contract double spaces after exclamation and question marks, too\n\
printf("\
f frequencies mode: show how useful abbreviations are\n\
- g traces calls to functions (except in the library)\n\
- g2 traces calls to all functions\n\
- h print this information\n");
+ g traces calls to all game functions\n\
+ g2 traces calls to all game and library functions\n\
+ g3 traces calls to all functions (including veneer)\n\
+ h print general help information\n\
+ h1 print help information on filenames and path options\n\
+ h2 print help information on switches (this page)\n");
printf("\
i ignore default switches set within the file\n\
- j list objects as constructed\n\
- k output Infix debugging information to \"%s\" (and switch -D on)\n\
- l list every statement run through Inform\n\
- m say how much memory has been allocated\n\
- n print numbers of properties, attributes and actions\n",
+ k output debugging information to \"%s\"\n",
Debugging_Name);
printf("\
- o print offset addresses\n\
- p give percentage breakdown of story file\n\
q keep quiet about obsolete usages\n\
r record all the text to \"%s\"\n\
- s give statistics\n\
- t trace assembly-language (with full hex dumps; see -a)\n",
+ s give statistics\n",
Transcript_Name);
printf("\
u work out most useful abbreviations (very very slowly)\n\
- v3 compile to version-3 (\"Standard\") story file\n\
- v4 compile to version-4 (\"Plus\") story file\n\
- v5 compile to version-5 (\"Advanced\") story file: the default\n\
- v6 compile to version-6 (graphical) story file\n\
+ v3 compile to version-3 (\"Standard\"/\"ZIP\") story file\n\
+ v4 compile to version-4 (\"Plus\"/\"EZIP\") story file\n\
+ v5 compile to version-5 (\"Advanced\"/\"XZIP\") story file: the default\n\
+ v6 compile to version-6 (graphical/\"YZIP\") story file\n\
+ v7 compile to version-7 (expanded \"Advanced\") story file\n\
v8 compile to version-8 (expanded \"Advanced\") story file\n\
w disable warning messages\n\
x print # for every 100 lines compiled\n\
- y trace linking system\n\
z print memory map of the virtual machine\n\n");
printf("\
(error_format==1)?" (current setting)":"");
printf(" E2 Macintosh MPW-style error messages%s\n",
(error_format==2)?" (current setting)":"");
-#ifdef USE_TEMPORARY_FILES
-printf(" F0 use extra memory rather than temporary files\n");
-#else
-printf(" F1 use temporary files to reduce memory consumption\n");
-#endif
printf(" G compile a Glulx game file\n");
printf(" H use Huffman encoding to compress Glulx strings\n");
-printf(" M compile as a Module for future linking\n");
#ifdef ARCHIMEDES
printf("\
#ifdef ARC_THROWBACK
printf(" T enable throwback of errors in the DDE\n");
#endif
-printf(" U insert \"Constant USE_MODULES;\" automatically\n");
printf(" V print the version and date of this program\n");
printf(" Wn header extension table is at least n words (n = 3 to 99)\n");
printf(" X compile with INFIX debugging facilities present\n");
}
switch(p[i])
{
- case 'a': asm_trace_setting = 1; break;
- case 'b': bothpasses_switch = state; break;
+ case 'a': switch(p[i+1])
+ { case '1': asm_trace_setting=1; s=2; break;
+ case '2': asm_trace_setting=2; s=2; break;
+ case '3': asm_trace_setting=3; s=2; break;
+ case '4': asm_trace_setting=4; s=2; break;
+ default: asm_trace_setting=1; break;
+ }
+ break;
case 'c': concise_switch = state; break;
case 'd': switch(p[i+1])
{ case '1': double_space_setting=1; s=2; break;
}
break;
case 'e': economy_switch = state; break;
- case 'f': frequencies_switch = state; break;
+ case 'f': frequencies_setting = (state?1:0); break;
case 'g': switch(p[i+1])
{ case '1': trace_fns_setting=1; s=2; break;
case '2': trace_fns_setting=2; s=2; break;
+ case '3': trace_fns_setting=3; s=2; break;
default: trace_fns_setting=1; break;
}
break;
}
break;
case 'i': ignore_switches_switch = state; break;
- case 'j': listobjects_switch = state; break;
case 'k': if (cmode == 0)
error("The switch '-k' can't be set with 'Switches'");
else
- { debugfile_switch = state;
- if (state) define_DEBUG_switch = TRUE;
- }
+ debugfile_switch = state;
break;
- case 'l': listing_switch = state; break;
- case 'm': memout_switch = state; break;
- case 'n': printprops_switch = state; break;
- case 'o': offsets_switch = state; break;
- case 'p': percentages_switch = state; break;
case 'q': obsolete_switch = state; break;
case 'r': if (cmode == 0)
error("The switch '-r' can't be set with 'Switches'");
else
transcript_switch = state; break;
case 's': statistics_switch = state; break;
- case 't': asm_trace_setting=2; break;
case 'u': if (cmode == 0) {
error("The switch '-u' can't be set with 'Switches'");
break;
break;
case 'w': nowarnings_switch = state; break;
case 'x': hash_switch = state; break;
- case 'y': s=2; linker_trace_setting=p[i+1]-'0'; break;
- case 'z': memory_map_switch = state; break;
+ case 'z': memory_map_setting = (state ? 1 : 0); break;
case 'B': oddeven_packing_switch = state; break;
case 'C': s=2;
if (p[i+1] == 'u') {
default: error_format=1; break;
}
break;
- case 'F': if (cmode == 0) {
- error("The switch '-F' can't be set with 'Switches'");
- break;
- }
- switch(p[i+1])
- { case '0': s=2; temporary_files_switch = FALSE; break;
- case '1': s=2; temporary_files_switch = TRUE; break;
- default: temporary_files_switch = state; break;
- }
- break;
- case 'M': module_switch = state;
- if (state && (r_e_c_s_set == FALSE))
- runtime_error_checking_switch = FALSE;
- break;
#ifdef ARCHIMEDES
case 'R': switch(p[i+1])
{ case '0': s=2; riscos_file_type_format=0; break;
}
break;
case 'H': compression_switch = state; break;
- case 'U': define_USE_MODULES_switch = state; break;
case 'V': exit(0); break;
case 'W': if ((p[i+1]>='0') && (p[i+1]<='9'))
{ s=2; ZCODE_HEADER_EXT_WORDS = p[i+1]-'0';
}
}
- if (optimise_switch && (!store_the_text))
- { store_the_text=TRUE;
-#ifdef PC_QUICKC
- if (memout_switch)
- printf("Allocation %ld bytes for transcription text\n",
- (long) MAX_TRANSCRIPT_SIZE);
- all_text = halloc(MAX_TRANSCRIPT_SIZE,1);
- malloced_bytes += MAX_TRANSCRIPT_SIZE;
- if (all_text==NULL)
- fatalerror("Can't hallocate memory for transcription text. Darn.");
-#else
- all_text=my_malloc(MAX_TRANSCRIPT_SIZE,"transcription text");
-#endif
+ if (optimise_switch)
+ {
+ /* store_the_text is equivalent to optimise_switch; -u sets both.
+ We could simplify this. */
+ store_the_text=TRUE;
}
}
+/* Check whether the string looks like an ICL command. */
static int icl_command(char *p)
{ if ((p[0]=='+')||(p[0]=='-')||(p[0]=='$')
|| ((p[0]=='(')&&(p[strlen(p)-1]==')')) ) return TRUE;
static void execute_icl_command(char *p);
static int execute_dashdash_command(char *p, char *p2);
+/* Open a file and see whether the initial lines match the "!% ..." format
+ used for ICL commands. Stop when we reach a line that doesn't.
+
+ This does not do line break conversion. It just reads to the next
+ \n (and ignores \r as whitespace). Therefore it will work on Unix and
+ DOS source files, but fail to cope with Mac-Classic (\r) source files.
+ I am not going to worry about this, because files from the Mac-Classic
+ era shouldn't have "!%" lines; that convention was invented well after
+ Mac switched over to \n format.
+ */
static int execute_icl_header(char *argname)
{
FILE *command_file;
do
{ x = translate_in_filename(x, filename, argname, 0, 1);
- command_file = fopen(filename,"r");
+ command_file = fopen(filename,"rb");
} while ((command_file == NULL) && (x != 0));
if (!command_file) {
/* Fail silently. The regular compiler will try to open the file
}
else if (!strcmp(p, "size")) {
consumed2 = TRUE;
+ /* We accept these arguments even though they've been withdrawn. */
if (!(p2 && (!strcmpcis(p2, "HUGE") || !strcmpcis(p2, "LARGE") || !strcmpcis(p2, "SMALL")))) {
printf("--size must be followed by \"huge\", \"large\", or \"small\"\n");
return consumed2;
strcpy(cli_buff, "$?");
strcpyupper(cli_buff+2, p2, CMD_BUF_SIZE-2);
}
+ else if (!strcmp(p, "define")) {
+ consumed2 = TRUE;
+ if (!p2) {
+ printf("--define must be followed by \"symbol=number\"\n");
+ return consumed2;
+ }
+ strcpy(cli_buff, "$#");
+ strcpyupper(cli_buff+2, p2, CMD_BUF_SIZE-2);
+ }
else if (!strcmp(p, "path")) {
consumed2 = TRUE;
if (!p2 || !strchr(p2, '=')) {
}
snprintf(cli_buff, CMD_BUF_SIZE, "(%s)", p2);
}
+ else if (!strcmp(p, "trace")) {
+ consumed2 = TRUE;
+ if (!p2) {
+ printf("--trace must be followed by \"traceopt\" or \"traceopt=N\"\n");
+ return consumed2;
+ }
+ snprintf(cli_buff, CMD_BUF_SIZE, "$!%s", p2);
+ }
+ else if (!strcmp(p, "helptrace")) {
+ strcpy(cli_buff, "$!");
+ }
else {
printf("Option \"--%s\" unknown (try \"inform -h\")\n", p);
return FALSE;
for (i=1, cli_files_specified=0; i<argc; i++)
if (argv[i][0] == '-' && argv[i][1] == '-') {
char *nextarg = NULL;
+ int consumed2;
if (i+1 < argc) nextarg = argv[i+1];
- int consumed2 = execute_dashdash_command(argv[i]+2, nextarg);
+ consumed2 = execute_dashdash_command(argv[i]+2, nextarg);
if (consumed2 && i+1 < argc) {
i++;
}
banner();
- set_memory_sizes(DEFAULT_MEMORY_SIZE); set_default_paths();
+ set_memory_sizes(); set_default_paths();
reset_switch_settings(); select_version(5);
cli_files_specified = 0; no_compilations = 0;