Update to commit a469d404a7dc4e87e18f367eb4d8e05fc32d20a7
[inform.git] / src / inform.c
index a72d81ef6e7a62714000768c361e59771763e68b..5c02b6bfe123020f4c05cafc09f55e55993f8b98 100644 (file)
@@ -2,8 +2,8 @@
 /*   "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 - 2021                                 */
+/*   Part of Inform 6.40                                                     */
+/*   copyright (c) Graham Nelson 1993 - 2022                                 */
 /*                                                                           */
 /* Inform is free software: you can redistribute it and/or modify            */
 /* it under the terms of the GNU General Public License as published by      */
@@ -16,7 +16,7 @@
 /* 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/                  */
 /*                                                                           */
 /* ------------------------------------------------------------------------- */
 
@@ -123,6 +123,8 @@ static void select_target(int targ)
     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");
@@ -139,18 +141,6 @@ static void select_target(int targ)
       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 */
@@ -158,6 +148,10 @@ static void select_target(int targ)
     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);
@@ -174,12 +168,11 @@ static void select_target(int targ)
     }
   }
 
-  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 (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 (DICT_WORD_SIZE > MAX_DICT_WORD_SIZE) {
     DICT_WORD_SIZE = MAX_DICT_WORD_SIZE;
     warning_numbered(
@@ -195,21 +188,13 @@ static void select_target(int targ)
     /* MAX_NUM_ATTR_BYTES can be increased in header.h without fear. */
   }
 
-  if (MAX_ADJECTIVES > 255) {
-    MAX_ADJECTIVES = 255;
-    warning("MAX_ADJECTIVES cannot exceed 255; resetting to 255");
-    /* Only used under Grammar__Version 1, which is obsolete. */
-  }
-    
   /* Set up a few more variables that depend on the above values */
 
   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 {
@@ -245,54 +230,45 @@ static void select_target(int targ)
       MAX_ABBREVS = 64;
     }
   }
-  else {
-    if (MAX_DYNAMIC_STRINGS > 100) {
-      MAX_DYNAMIC_STRINGS = 100;
-      warning("MAX_DYNAMIC_STRINGS cannot exceed 100; resetting to 100");
-      /* This is because they are specified in text literals like "@00",
-         with two digits. */
-    }
-  }
 }
 
 /* ------------------------------------------------------------------------- */
 /*   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        */
+    linker_trace_level,  /* linker tracing: 0 to 4 levels                    */
+    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 */
@@ -307,53 +283,66 @@ int compression_switch;             /* set by -H */
 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 */
+    linker_trace_setting,           /* $!LINKER: initial value of
+                                       linker_trace_level */
+    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;
+    linker_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
@@ -373,6 +362,12 @@ static void reset_switch_settings(void)
     compression_switch = TRUE;
     glulx_mode = FALSE;
     requested_glulx_version = 0;
+
+    /* These aren't switches, but for clarity we reset them too. */
+    asm_trace_level = 0;
+    expr_trace_level = 0;
+    linker_trace_level = 0;
+    tokens_trace_level = 0;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -428,10 +423,10 @@ static void begin_pass(void)
     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;
+    tokens_trace_level = tokens_trace_setting;
     linker_trace_level = linker_trace_setting;
-    if (listing_switch) line_trace_level=1;
 
     lexer_begin_pass();
     linker_begin_pass();
@@ -527,7 +522,6 @@ 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];
@@ -634,7 +628,6 @@ static void set_default_paths(void)
     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);
@@ -676,7 +669,6 @@ static void set_path_command(char *command)
         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;
@@ -962,10 +954,8 @@ Inform translates plain filenames (such as \"xyzzy\") into full pathnames\n\
    name_or_unset(Code_Path));
 
     printf(
-"       Temporary file (out)   temporary_path      %s\n\
-       ICL command file (in)  icl_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));
 
     printf(
@@ -997,7 +987,6 @@ Inform translates plain filenames (such as \"xyzzy\") into full pathnames\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",
       Source_Extension, Include_Extension,
       Code_Extension, V4Code_Extension, V5Code_Extension, V6Code_Extension,
@@ -1072,33 +1061,6 @@ Inform translates plain filenames (such as \"xyzzy\") into full pathnames\n\
     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;
-        default: return;
-    }
-    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
 static char riscos_ft_buffer[4];
 
@@ -1137,13 +1099,11 @@ static void run_pass(void)
     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();
@@ -1152,9 +1112,8 @@ static void run_pass(void)
 
 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();
@@ -1181,7 +1140,16 @@ static void rennab(int32 time_taken)
     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);
+    }
 }
 
 /* ------------------------------------------------------------------------- */
@@ -1191,7 +1159,9 @@ static void rennab(int32 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;
@@ -1221,7 +1191,9 @@ 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);
@@ -1251,15 +1223,22 @@ compiling modules: disabling -S switch\n");
     {   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;
 }
@@ -1273,7 +1252,7 @@ static void cli_print_help(int help_level)
     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 - 2021.\n\n");
+Copyright (c) Graham Nelson 1993 - 2022.\n\n");
 
    /* For people typing just "inform", a summary only: */
 
@@ -1303,15 +1282,12 @@ One or more words can be supplied as \"commands\". These may be:\n\n\
   
   printf(
 "     $list            list current 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\
      $?SETTING        explain briefly what SETTING is for\n\
      $SETTING=number  change SETTING to given number\n\
-     $#SYMBOL=number  define SYMBOL as a constant in the story\n\n",
-    (DEFAULT_MEMORY_SIZE==HUGE_SIZE)?"(default)":"",
-    (DEFAULT_MEMORY_SIZE==LARGE_SIZE)?"(default)":"",
-    (DEFAULT_MEMORY_SIZE==SMALL_SIZE)?"(default)":"");
+     $!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\
@@ -1319,17 +1295,19 @@ One or more words can be supplied as \"commands\". These may be:\n\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\
-  --define 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;
@@ -1342,7 +1320,8 @@ One or more words can be supplied as \"commands\". These may be:\n\n\
    /* 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\
@@ -1359,19 +1338,12 @@ One or more words can be supplied as \"commands\". These may be:\n\n\
 
    printf("\
   i   ignore default switches set within the file\n\
-  j   list objects as constructed\n\
-  k   output debugging information to \"%s\"\n\
-  l   list every statement run through Inform (not implemented)\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("\
@@ -1384,7 +1356,6 @@ One or more words can be supplied as \"commands\". These may be:\n\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("\
@@ -1401,11 +1372,6 @@ printf("  E1  Microsoft-style error messages%s\n",
       (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");
@@ -1446,8 +1412,14 @@ extern void switches(char *p, int cmode)
         }
         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;
@@ -1456,7 +1428,7 @@ extern void switches(char *p, int cmode)
                   }
                   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;
@@ -1472,24 +1444,17 @@ extern void switches(char *p, int cmode)
                   }
                   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;
                   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;
@@ -1514,8 +1479,7 @@ extern void switches(char *p, int cmode)
                   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') {
@@ -1543,16 +1507,6 @@ extern void switches(char *p, int cmode)
                       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;
@@ -1598,22 +1552,15 @@ extern void switches(char *p, int cmode)
         }
     }
 
-    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;
@@ -1844,6 +1791,7 @@ static int execute_dashdash_command(char *p, char *p2)
     }
     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;
@@ -1902,6 +1850,17 @@ static int execute_dashdash_command(char *p, char *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;
@@ -2039,7 +1998,7 @@ static int sub_main(int argc, char **argv)
 
     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;