X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Finform.c;h=a72d81ef6e7a62714000768c361e59771763e68b;hb=d8d68d0bd4c45af6f0dc69b4fc33d37d961aca85;hp=8888077c9addfa4aa4ba9726381dd6590a9a3762;hpb=81ffe9a7de1db0b3a318a053b38882d1b7ab304c;p=inform.git diff --git a/src/inform.c b/src/inform.c index 8888077..a72d81e 100644 --- a/src/inform.c +++ b/src/inform.c @@ -2,9 +2,8 @@ /* "inform" : The top level of Inform: switches, pathnames, filenaming */ /* conventions, ICL (Inform Command Line) files, main */ /* */ -/* Copyright (c) Graham Nelson 1993 - 2018 */ -/* */ -/* This file is part of Inform. */ +/* Part of Inform 6.35 */ +/* copyright (c) Graham Nelson 1993 - 2021 */ /* */ /* Inform is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ @@ -17,13 +16,15 @@ /* 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/ * /* */ /* ------------------------------------------------------------------------- */ #define MAIN_INFORM_FILE #include "header.h" +#define CMD_BUF_SIZE (256) + /* ------------------------------------------------------------------------- */ /* Compiler progress */ /* ------------------------------------------------------------------------- */ @@ -194,6 +195,12 @@ 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) { @@ -218,6 +225,34 @@ static void select_target(int targ) 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; + } + } + 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. */ + } + } } /* ------------------------------------------------------------------------- */ @@ -602,7 +637,7 @@ static void set_default_paths(void) 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, "english"); + set_path_value(Language_Name, Default_Language); set_path_value(Charset_Map, ""); } @@ -1049,6 +1084,7 @@ extern void translate_temp_filename(int 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"); @@ -1236,7 +1272,8 @@ static void cli_print_help(int help_level) { printf( "\nThis program is a compiler of Infocom format (also called \"Z-machine\")\n\ -story files: copyright (c) Graham Nelson 1993 - 2017.\n\n"); +story files, as well as \"Glulx\" story files:\n\ +Copyright (c) Graham Nelson 1993 - 2021.\n\n"); /* For people typing just "inform", a summary only: */ @@ -1259,23 +1296,40 @@ One or more words can be supplied as \"commands\". These may be:\n\n\ -switches a list of compiler switches, 1 or 2 letter\n\ (see \"inform -h2\" for the full range)\n\n\ +dir set Include_Path to this directory\n\ - +PATH=dir change the PATH to this directory\n\n\ - $... one of the following memory commands:\n"); + ++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 configuration commands:\n"); + printf( -" $list list current memory allocation settings\n\ +" $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\n\ - (filename) read in a list of commands (in the format above)\n\ - from this \"setup file\"\n\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)":""); + printf( +" (filename) read in a list of commands (in the format above)\n\ + from this \"setup file\"\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"); + #ifndef PROMPT_INPUT - printf("For example: \"inform -dexs $huge curses\".\n\n"); + printf("For example: \"inform -dexs $huge curses\".\n"); #endif return; @@ -1296,15 +1350,18 @@ One or more words can be supplied as \"commands\". These may be:\n\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\ + 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", Debugging_Name); @@ -1319,15 +1376,16 @@ One or more words can be supplied as \"commands\". These may be:\n\n\ 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 Z-machine\n\n"); + z print memory map of the virtual machine\n\n"); printf("\ B use big memory model (for large V6/V7 files)\n\ @@ -1402,6 +1460,7 @@ extern void switches(char *p, int cmode) 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; @@ -1417,9 +1476,7 @@ extern void switches(char *p, int cmode) 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; @@ -1515,6 +1572,8 @@ extern void switches(char *p, int cmode) r_e_c_s_set = TRUE; break; case 'G': if (cmode == 0) error("The switch '-G' can't be set with 'Switches'"); + else if (version_set_switch) + error("The '-G' switch cannot follow the '-v' switch"); else { glulx_mode = state; adjust_memory_sizes(); @@ -1604,12 +1663,29 @@ static int copy_icl_word(char *from, char *to, int max) return i; } +/* Copy a string, converting to uppercase. The to array should be + (at least) max characters. Result will be null-terminated, so + at most max-1 characters will be copied. +*/ +static int strcpyupper(char *to, char *from, int max) +{ + int ix; + for (ix=0; ix to <%s>]\n", story_name, code_name); compile(x, story_name, code_name); - copy_icl_word(cli_buff + i, fw, 256); + copy_icl_word(cli_buff + i, fw, CMD_BUF_SIZE); if (fw[0]!=0) { icl_error(filename, line); printf("Expected comment or nothing but found '%s'\n", @@ -1710,49 +1786,155 @@ static void run_icl_file(char *filename, FILE *command_file) } } +/* This should only be called if the argument has been verified to be + an ICL command, e.g. by checking icl_command(). +*/ static void execute_icl_command(char *p) -{ char filename[PATHLEN], cli_buff[256]; +{ char filename[PATHLEN], cli_buff[CMD_BUF_SIZE]; FILE *command_file; - + int len; + switch(p[0]) { case '+': set_path_command(p+1); break; case '-': switches(p,1); break; case '$': memory_command(p+1); break; - case '(': strcpy(cli_buff,p+1); cli_buff[strlen(cli_buff)-1]=0; + case '(': len = strlen(p); + if (p[len-1] != ')') { + printf("Error in ICL: (command) missing closing paren\n"); + break; + } + len -= 2; /* omit parens */ + if (len > CMD_BUF_SIZE-1) len = CMD_BUF_SIZE-1; + strncpy(cli_buff, p+1, len); + cli_buff[len]=0; { int x = 0; do { x = translate_icl_filename(x, filename, cli_buff); command_file = fopen(filename,"r"); } while ((command_file == NULL) && (x != 0)); } - if (command_file == NULL) + if (command_file == NULL) { printf("Error in ICL: Couldn't open command file '%s'\n", filename); - else - { run_icl_file(filename, command_file); - fclose(command_file); + break; } + run_icl_file(filename, command_file); + fclose(command_file); break; } } +/* Convert a --command into the equivalent ICL command and call + execute_icl_command(). The dashes have already been stripped. + + The second argument is the following command-line argument + (or NULL if there was none). This may or may not be consumed. + Returns TRUE if it was. +*/ +static int execute_dashdash_command(char *p, char *p2) +{ + char cli_buff[CMD_BUF_SIZE]; + int consumed2 = FALSE; + + if (!strcmp(p, "help")) { + strcpy(cli_buff, "-h"); + } + else if (!strcmp(p, "list")) { + strcpy(cli_buff, "$LIST"); + } + else if (!strcmp(p, "size")) { + consumed2 = TRUE; + 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+1, p2, CMD_BUF_SIZE-1); + } + else if (!strcmp(p, "opt")) { + consumed2 = TRUE; + if (!p2 || !strchr(p2, '=')) { + printf("--opt must be followed by \"setting=number\"\n"); + return consumed2; + } + strcpy(cli_buff, "$"); + strcpyupper(cli_buff+1, p2, CMD_BUF_SIZE-1); + } + else if (!strcmp(p, "helpopt")) { + consumed2 = TRUE; + if (!p2) { + printf("--helpopt must be followed by \"setting\"\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, '=')) { + printf("--path must be followed by \"name=path\"\n"); + return consumed2; + } + snprintf(cli_buff, CMD_BUF_SIZE, "+%s", p2); + } + else if (!strcmp(p, "addpath")) { + consumed2 = TRUE; + if (!p2 || !strchr(p2, '=')) { + printf("--addpath must be followed by \"name=path\"\n"); + return consumed2; + } + snprintf(cli_buff, CMD_BUF_SIZE, "++%s", p2); + } + else if (!strcmp(p, "config")) { + consumed2 = TRUE; + if (!p2) { + printf("--config must be followed by \"file.icl\"\n"); + return consumed2; + } + snprintf(cli_buff, CMD_BUF_SIZE, "(%s)", p2); + } + else { + printf("Option \"--%s\" unknown (try \"inform -h\")\n", p); + return FALSE; + } + + execute_icl_command(cli_buff); + return consumed2; +} + /* ------------------------------------------------------------------------- */ /* Opening and closing banners */ /* ------------------------------------------------------------------------- */ -char banner_line[80]; +char banner_line[CMD_BUF_SIZE]; +/* We store the banner text for use elsewhere (see files.c). +*/ static void banner(void) { - sprintf(banner_line, "Inform %s", - (VERSION)); + int len; + snprintf(banner_line, CMD_BUF_SIZE, "Inform %d.%d%d", + (VNUMBER/100)%10, (VNUMBER/10)%10, VNUMBER%10); #ifdef RELEASE_SUFFIX - strcat(banner_line, RELEASE_SUFFIX); + len = strlen(banner_line); + snprintf(banner_line+len, CMD_BUF_SIZE-len, "%s", RELEASE_SUFFIX); #endif #ifdef MACHINE_STRING - sprintf(banner_line+strlen(banner_line), " for %s", MACHINE_STRING); + len = strlen(banner_line); + snprintf(banner_line+len, CMD_BUF_SIZE-len, " for %s", MACHINE_STRING); #endif - sprintf(banner_line+strlen(banner_line), " (%s)", RELEASE_DATE); + len = strlen(banner_line); + snprintf(banner_line+len, CMD_BUF_SIZE-len, " (%s)", RELEASE_DATE); + printf("%s\n", banner_line); } @@ -1782,9 +1964,19 @@ static void read_command_line(int argc, char **argv) if (argc==1) switches("-h",1); for (i=1, cli_files_specified=0; i