assembly_operand AO;
int extraspace;
- int orig_area_size;
int32 global_symbol;
const char *global_name;
extraspace += WORDSIZE;
if (!is_static) {
- orig_area_size = dynamic_array_area_size;
array_base = dynamic_array_area_size;
dynamic_array_area_size += extraspace;
}
else {
- orig_area_size = static_array_area_size;
array_base = static_array_area_size;
static_array_area_size += extraspace;
}
if (operand_rules==TEXT)
{ int32 i;
- uchar *tmp = translate_text(zcode_holding_area + zcode_ha_size, zcode_holding_area+MAX_ZCODE_SIZE, AI->text);
+ uchar *tmp = translate_text(zcode_holding_area + zcode_ha_size, zcode_holding_area+MAX_ZCODE_SIZE, AI->text, STRCTX_GAMEOPC);
if (!tmp)
memoryerror("MAX_ZCODE_SIZE", MAX_ZCODE_SIZE);
j = subtract_pointers(tmp, (zcode_holding_area + zcode_ha_size));
sprintf(fnt, "[ %s(", name);
AO.marker = STRING_MV;
AO.type = CONSTANT_OT;
- AO.value = compile_string(fnt, FALSE, FALSE);
+ AO.value = compile_string(fnt, STRCTX_INFIX);
assembleg_1(streamstr_gc, AO);
if (!stackargs) {
sprintf(fnt, "%s%s = ", (ix==1)?"":", ", variable_name(ix));
AO.marker = STRING_MV;
AO.type = CONSTANT_OT;
- AO.value = compile_string(fnt, FALSE, FALSE);
+ AO.value = compile_string(fnt, STRCTX_INFIX);
assembleg_1(streamstr_gc, AO);
AO.marker = 0;
AO.type = LOCALVAR_OT;
sprintf(fnt, "%s = ", variable_name(1));
AO.marker = STRING_MV;
AO.type = CONSTANT_OT;
- AO.value = compile_string(fnt, FALSE, FALSE);
+ AO.value = compile_string(fnt, STRCTX_INFIX);
assembleg_1(streamstr_gc, AO);
AO.marker = 0;
AO.type = LOCALVAR_OT;
AO.marker = STRING_MV;
AO.type = CONSTANT_OT;
- AO.value = compile_string(") ]^", FALSE, FALSE);
+ AO.value = compile_string(") ]^", STRCTX_INFIX);
assembleg_1(streamstr_gc, AO);
}
}
break;
case CONSTANT_T:
case INDIVIDUAL_PROPERTY_T:
+ case PROPERTY_T:
/* value is unchanged */
break;
default:
static int constant_made_yet; /* Have any constants been defined yet? */
-static int ifdef_stack[32], ifdef_sp;
+#define MAX_IFDEF_STACK (32)
+static int ifdef_stack[MAX_IFDEF_STACK], ifdef_sp;
/* ------------------------------------------------------------------------- */
assembly_operand AO;
put_token_back();
AO = parse_expression(CONSTANT_CONTEXT);
- if (module_switch && (AO.marker != 0))
+ if (AO.marker != 0)
error("A definite value must be given as a Dictionary flag");
else
val1 = AO.value;
assembly_operand AO;
put_token_back();
AO = parse_expression(CONSTANT_CONTEXT);
- if (module_switch && (AO.marker != 0))
+ if (AO.marker != 0)
error("A definite value must be given as a Dictionary flag");
else
val3 = AO.value;
case IFTRUE_CODE:
{ assembly_operand AO;
AO = parse_expression(CONSTANT_CONTEXT);
- if (module_switch && (AO.marker != 0))
+ if (AO.marker != 0)
{ error("This condition can't be determined");
flag = 0;
}
case IFFALSE_CODE:
{ assembly_operand AO;
AO = parse_expression(CONSTANT_CONTEXT);
- if (module_switch && (AO.marker != 0))
+ if (AO.marker != 0)
{ error("This condition can't be determined");
flag = 1;
}
if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
return ebf_error_recover("semicolon after 'If...' condition", token_text);
+ if (ifdef_sp >= MAX_IFDEF_STACK) {
+ error("'If' directives nested too deeply");
+ panic_mode_error_recovery(); return FALSE;
+ }
+
if (flag)
{ ifdef_stack[ifdef_sp++] = TRUE; return FALSE; }
else
if (token_type != DQ_TT)
return ebf_error_recover("literal string in double-quotes", token_text);
- assign_symbol(i, compile_string(token_text, TRUE, TRUE), CONSTANT_T);
+ assign_symbol(i, compile_string(token_text, STRCTX_LOWSTRING), CONSTANT_T);
break;
/* --------------------------------------------------------------------- */
case RELEASE_CODE:
{ assembly_operand AO;
AO = parse_expression(CONSTANT_CONTEXT);
- if (module_switch && (AO.marker != 0))
+ if (AO.marker != 0)
error("A definite value must be given as release number");
else
release_number = AO.value;
break;
}
- if (module_switch && (AO.marker != 0))
+ if (AO.marker != 0)
error("A definite value must be given as version number");
else
if (glulx_mode)
if (!(ErrorReport.main_flag)) printf("\"%s\", ", p);
printf("line %d: ", ErrorReport.line_number);
+
if (ErrorReport.orig_file) {
char *op;
if (ErrorReport.orig_file <= 0 || ErrorReport.orig_file > total_files)
}
printf("%s", p);
if (with_extension_flag) printf("%s", Source_Extension);
- printf("(%d): ", ErrorReport.line_number);
+ printf("(%d)", ErrorReport.line_number);
+
+ if (ErrorReport.orig_file) {
+ char *op;
+ if (ErrorReport.orig_file <= 0 || ErrorReport.orig_file > total_files)
+ op = ErrorReport.orig_source;
+ else
+ op = InputFiles[ErrorReport.orig_file-1].filename;
+ printf("|%s", op);
+ if (ErrorReport.orig_line) {
+ printf("(%d", ErrorReport.orig_line);
+ if (ErrorReport.orig_char) {
+ printf(":%d", ErrorReport.orig_char);
+ }
+ printf(")");
+ }
+ }
+
+ printf(": ");
break;
case 2: /* Macintosh Programmer's Workshop error message format */
- printf("File \"%s\"; Line %d\t# ", p, ErrorReport.line_number);
+ printf("File \"%s\"; Line %d", p, ErrorReport.line_number);
+
+ if (ErrorReport.orig_file) {
+ char *op;
+ if (ErrorReport.orig_file <= 0 || ErrorReport.orig_file > total_files)
+ op = ErrorReport.orig_source;
+ else
+ op = InputFiles[ErrorReport.orig_file-1].filename;
+ printf(": (\"%s\"", op);
+ if (ErrorReport.orig_line) {
+ printf("; Line %d", ErrorReport.orig_line);
+ if (ErrorReport.orig_char) {
+ printf("; Char %d", ErrorReport.orig_char);
+ }
+ }
+ printf(")");
+ }
+
+ printf("\t# ");
break;
}
}
if (j <= 0 || j > total_files) p = errpos.source;
else p = InputFiles[j-1].filename;
+ if (!p && errpos.line_number == 0) {
+ /* Special case */
+ strcpy(other_pos_buff, "compiler setup");
+ return other_pos_buff;
+ }
+
if (!p) p = "";
len = 0;
index_ao;
int x = 0, y = 0, byte_flag = FALSE, read_flag = FALSE, from_module = FALSE;
+ INITAO(&zero_ao);
+ INITAO(&size_ao);
+ INITAO(&type_ao);
+
if (AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV)
{
- INITAO(&zero_ao);
-
if ((oc == loadb_zc) || (oc == storeb_zc)) byte_flag=TRUE;
else byte_flag = FALSE;
if ((oc == loadb_zc) || (oc == loadw_zc)) read_flag=TRUE;
else
read_flag = FALSE;
+ INITAO(&zero_ao);
+ INITAO(&size_ao);
+ INITAO(&type_ao);
+
if (AO1.marker == ARRAY_MV || AO1.marker == STATIC_ARRAY_MV)
{
- INITAO(&zero_ao);
-
size_ao = zero_ao; size_ao.value = -1;
for (x=0; x<no_arrays; x++)
{ if (((AO1.marker == ARRAY_MV) == (!array_locs[x]))
extern int *variable_usage;
+/* Must be at least as many as keyword_group system_functions (currently 12) */
int system_function_usage[32];
static int get_next_etoken(void)
o->type = LONG_CONSTANT_OT;
else
o->type = CONSTANT_OT;
- o->value = compile_string(t.text, FALSE, FALSE);
+ o->value = compile_string(t.text, STRCTX_GAME);
return(TRUE);
case VARIABLE_TT:
if (!glulx_mode) {
if ((below != -1) && (ET[below].right != -1))
{ int n = ET[below].right, flag = FALSE;
+ /* Can we handle this dot operator as a native @get_prop (etc)
+ opcode? Only if we recognize the property value as a declared
+ common property constant. */
if ((ET[n].down == -1)
&& ((ET[n].value.type == LONG_CONSTANT_OT)
|| (ET[n].value.type == SHORT_CONSTANT_OT))
&& ((ET[n].value.value > 0) && (ET[n].value.value < 64))
- && ((!module_switch) || (ET[n].value.marker == 0)))
+ && (!module_switch)
+ && (ET[n].value.marker == 0))
flag = TRUE;
if (!flag)
FILE *transcript_file_handle; int transcript_open;
-extern void write_to_transcript_file(char *text)
-{ fputs(text, transcript_file_handle);
+extern void write_to_transcript_file(char *text, int linetype)
+{
+ if (TRANSCRIPT_FORMAT == 1) {
+ char ch = '?';
+ switch (linetype) {
+ case STRCTX_INFO:
+ ch = 'I'; break;
+ case STRCTX_GAME:
+ ch = 'G'; break;
+ case STRCTX_GAMEOPC:
+ ch = 'H'; break;
+ case STRCTX_VENEER:
+ ch = 'V'; break;
+ case STRCTX_VENEEROPC:
+ ch = 'W'; break;
+ case STRCTX_LOWSTRING:
+ ch = 'L'; break;
+ case STRCTX_ABBREV:
+ ch = 'A'; break;
+ case STRCTX_DICT:
+ ch = 'D'; break;
+ case STRCTX_OBJNAME:
+ ch = 'O'; break;
+ case STRCTX_SYMBOL:
+ ch = 'S'; break;
+ case STRCTX_INFIX:
+ ch = 'X'; break;
+ }
+ fputc(ch, transcript_file_handle);
+ fputs(": ", transcript_file_handle);
+ }
+ fputs(text, transcript_file_handle);
fputc('\n', transcript_file_handle);
}
transcript_open = TRUE;
- sprintf(topline_buffer, "Transcript of the text of \"%s\"\n\
-[From %s]\n", what_of, banner_line);
- write_to_transcript_file(topline_buffer);
+ sprintf(topline_buffer, "Transcript of the text of \"%s\"", what_of);
+ write_to_transcript_file(topline_buffer, STRCTX_INFO);
+ sprintf(topline_buffer, "[From %s]", banner_line);
+ write_to_transcript_file(topline_buffer, STRCTX_INFO);
+ if (TRANSCRIPT_FORMAT == 1) {
+ write_to_transcript_file("[I:info, G:game text, V:veneer text, L:lowmem string, A:abbreviation, D:dict word, O:object name, S:symbol, X:infix]", STRCTX_INFO);
+ if (!glulx_mode)
+ write_to_transcript_file("[H:game text inline in opcode, W:veneer text inline in opcode]", STRCTX_INFO);
+ }
+ write_to_transcript_file("", STRCTX_INFO);
}
extern void abort_transcript_file(void)
char sn_buffer[7];
write_serial_number(sn_buffer);
- sprintf(botline_buffer, "\n[End of transcript: release %d.%s]\n",
+ sprintf(botline_buffer, "[End of transcript: release %d, serial %s]",
release_number, sn_buffer);
- write_to_transcript_file(botline_buffer);
+ write_to_transcript_file("", STRCTX_INFO);
+ write_to_transcript_file(botline_buffer, STRCTX_INFO);
+ write_to_transcript_file("", STRCTX_INFO);
if (ferror(transcript_file_handle))
fatalerror("I/O failure: couldn't write to transcript file");
how far back from the label to go
to find the opmode byte to modify. */
+/* ------------------------------------------------------------------------- */
+/* "String contexts"; the purpose for a given string. This info gets */
+/* written to the transcript file (gametext.txt). */
+/* ------------------------------------------------------------------------- */
+
+#define STRCTX_INFO 0 /* comment; not stored in game file */
+#define STRCTX_GAME 1 /* strings area */
+#define STRCTX_GAMEOPC 2 /* inline text in opcode (Z-code only) */
+#define STRCTX_VENEER 3 /* strings area, from veneer code */
+#define STRCTX_VENEEROPC 4 /* inline text, veneer code (Z-code only) */
+#define STRCTX_LOWSTRING 5 /* lowmem (Z-code); also dynamic-str literals */
+#define STRCTX_ABBREV 6 /* abbreviation */
+#define STRCTX_DICT 7 /* dictionary word */
+#define STRCTX_OBJNAME 8 /* object "hardware name" */
+#define STRCTX_SYMBOL 9 /* prop/attr/etc names */
+#define STRCTX_INFIX 10 /* text printed in asterisk traces */
+
/* ========================================================================= */
/* Initialisation extern definitions */
/* */
extern void remove_temp_files(void);
extern void open_transcript_file(char *what_of);
-extern void write_to_transcript_file(char *text);
+extern void write_to_transcript_file(char *text, int linetype);
extern void close_transcript_file(void);
extern void abort_transcript_file(void);
extern int ZCODE_HEADER_EXT_WORDS, ZCODE_HEADER_FLAGS_3;
extern int NUM_ATTR_BYTES, GLULX_OBJECT_EXT_BYTES;
extern int WARN_UNUSED_ROUTINES, OMIT_UNUSED_ROUTINES;
+extern int TRANSCRIPT_FORMAT;
/* These macros define offsets that depend on the value of NUM_ATTR_BYTES.
(Meaningful only for Glulx.) */
extern void assign_marked_symbol(int index, int marker, int32 value, int type);
extern void assign_symbol(int index, int32 value, int type);
extern void issue_unused_warnings(void);
+extern void add_config_symbol_definition(char *symbol, int32 value);
extern void add_symbol_replacement_mapping(int original, int renamed);
extern int find_symbol_replacement(int *value);
extern void df_note_function_start(char *name, uint32 address,
/* end of the Glulx string compression stuff */
extern void ao_free_arrays(void);
-extern int32 compile_string(char *b, int in_low_memory, int is_abbrev);
-extern uchar *translate_text(uchar *p, uchar *p_limit, char *s_text);
+extern int32 compile_string(char *b, int strctx);
+extern uchar *translate_text(uchar *p, uchar *p_limit, char *s_text, int strctx);
extern void optimise_abbreviations(void);
extern void make_abbreviation(char *text);
extern void show_dictionary(void);
/* 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) {
{ 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");
++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\
+" $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",
+ $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)":"");
--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("\
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);
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\
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;
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;
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, '=')) {
filename, module_size/1024);
if (linker_trace_level >= 1) printf("%s\n", link_banner);
if (transcript_switch)
- write_to_transcript_file(link_banner);
+ write_to_transcript_file(link_banner, STRCTX_INFO);
}
/* (4) Merge in the dictionary */
int ALLOC_CHUNK_SIZE;
int WARN_UNUSED_ROUTINES; /* 0: no, 1: yes except in system files, 2: yes always */
int OMIT_UNUSED_ROUTINES; /* 0: no, 1: yes */
+int TRANSCRIPT_FORMAT; /* 0: classic, 1: prefixed */
/* The way memory sizes are set causes great nuisance for those parameters
which have different defaults under Z-code and Glulx. We have to get
(long int) MAX_STATIC_STRINGS);
printf("| %25s = %-7d |\n","MAX_SYMBOLS",MAX_SYMBOLS);
printf("| %25s = %-7d |\n","SYMBOLS_CHUNK_SIZE",SYMBOLS_CHUNK_SIZE);
+ printf("| %25s = %-7d |\n","TRANSCRIPT_FORMAT",TRANSCRIPT_FORMAT);
printf("| %25s = %-7ld |\n","MAX_TRANSCRIPT_SIZE",
(long int) MAX_TRANSCRIPT_SIZE);
if (glulx_mode)
MAX_STACK_SIZE = 4096;
OMIT_UNUSED_ROUTINES = 0;
WARN_UNUSED_ROUTINES = 0;
+ TRANSCRIPT_FORMAT = 0;
adjust_memory_sizes();
}
memory after the game file. (Glulx only)\n");
return;
}
+ if (strcmp(command,"TRANSCRIPT_FORMAT")==0)
+ {
+ printf(
+" TRANSCRIPT_FORMAT, if set to 1, adjusts the gametext.txt transcript for \n\
+ easier machine processing; each line will be prefixed by its context.\n");
+ return;
+ }
if (strcmp(command,"WARN_UNUSED_ROUTINES")==0)
{
printf(
return 1;
}
+static void add_predefined_symbol(char *command)
+{
+ int ix;
+
+ int value = 0;
+ char *valpos = NULL;
+
+ for (ix=0; command[ix]; ix++) {
+ if (command[ix] == '=') {
+ valpos = command+(ix+1);
+ command[ix] = '\0';
+ break;
+ }
+ }
+
+ for (ix=0; command[ix]; ix++) {
+ if ((ix == 0 && isdigit(command[ix]))
+ || !(isalnum(command[ix]) || command[ix] == '_')) {
+ printf("Attempt to define invalid symbol: %s\n", command);
+ return;
+ }
+ }
+
+ if (valpos) {
+ if (!parse_memory_setting(valpos, command, &value)) {
+ return;
+ };
+ }
+
+ add_config_symbol_definition(command, value);
+}
+
+/* Handle a dollar-sign command option: $LIST, $FOO=VAL, and so on.
+ The option may come from the command line, an ICL file, or a header
+ comment.
+
+ (Unix-style command-line options are converted to dollar-sign format
+ before being sent here.)
+
+ The name of this function is outdated. Many of these settings are not
+ really about memory allocation.
+*/
extern void memory_command(char *command)
{ int i, k, flag=0; int32 j;
if (islower(command[k])) command[k]=toupper(command[k]);
if (command[0]=='?') { explain_parameter(command+1); return; }
+ if (command[0]=='#') { add_predefined_symbol(command+1); return; }
if (strcmp(command, "HUGE")==0) { set_memory_sizes(HUGE_SIZE); return; }
if (strcmp(command, "LARGE")==0) { set_memory_sizes(LARGE_SIZE); return; }
/* Adjust up to a 256-byte boundary. */
MEMORY_MAP_EXTENSION = (MEMORY_MAP_EXTENSION + 0xFF) & (~0xFF);
}
+ if (strcmp(command,"TRANSCRIPT_FORMAT")==0)
+ {
+ TRANSCRIPT_FORMAT=j, flag=1;
+ if (TRANSCRIPT_FORMAT > 1 || TRANSCRIPT_FORMAT < 0)
+ TRANSCRIPT_FORMAT = 1;
+ }
if (strcmp(command,"WARN_UNUSED_ROUTINES")==0)
{
WARN_UNUSED_ROUTINES=j, flag=1;
{ uchar *tmp;
if (mark+1+510 >= MAX_PROP_TABLE_SIZE)
memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
- tmp = translate_text(p+mark+1,p+mark+1+510,shortname);
+ tmp = translate_text(p+mark+1,p+mark+1+510,shortname,STRCTX_OBJNAME);
if (!tmp) error ("Short name of object exceeded 765 Z-characters");
i = subtract_pointers(tmp,(p+mark+1));
p[mark] = i/2;
}
objectsg[no_objects].shortname = compile_string(shortname_buffer,
- FALSE, FALSE);
+ STRCTX_OBJNAME);
/* The properties table consists simply of a sequence of property
blocks, one for each object in order of definition, exactly as
{ int n, duplicates_to_make = 0, class_number = no_objects+1,
metaclass_flag = (metaclass_name != NULL);
char duplicate_name[128];
- int class_symbol;
debug_location_beginning beginning_debug_location =
get_token_location_beginning();
full_object_g.propdata[0].marker = OBJECT_MV;
}
- class_symbol = token_value;
-
if (!metaclass_flag)
{ get_next_token();
if ((token_type == SEP_TT) && (token_value == OPENB_SEP))
if (strlen(token_text) > 32)
{ INITAOT(&AO, LONG_CONSTANT_OT);
AO.marker = STRING_MV;
- AO.value = compile_string(token_text, FALSE, FALSE);
+ AO.value = compile_string(token_text, STRCTX_GAME);
assemblez_1(print_paddr_zc, AO);
if (finally_return)
{ get_next_token();
so this always goes into the string area. */
{ INITAOT(&AO, CONSTANT_OT);
AO.marker = STRING_MV;
- AO.value = compile_string(token_text, FALSE, FALSE);
+ AO.value = compile_string(token_text, STRCTX_GAME);
assembleg_1(streamstr_gc, AO);
if (finally_return)
{ get_next_token();
get_next_token();
/* Initialisation code */
+ AO.type = OMITTED_OT;
+ spare_debug_location1 = statement_debug_location;
+ AO2.type = OMITTED_OT; flag = 0;
+ spare_debug_location2 = statement_debug_location;
if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
{ put_token_back();
assemble_label_no(ln2);
return;
}
- AO.type = OMITTED_OT;
goto ParseUpdate;
}
put_token_back();
}
get_next_token();
- AO.type = OMITTED_OT;
if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
{ put_token_back();
spare_debug_location1 = get_token_location();
get_next_token();
ParseUpdate:
- AO2.type = OMITTED_OT; flag = 0;
if (!((token_type==SEP_TT)&&(token_value==CLOSEB_SEP)))
{ put_token_back();
spare_debug_location2 = get_token_location();
get_next_token();
if (token_type == DQ_TT)
{ INITAOT(&AO4, LONG_CONSTANT_OT);
- AO4.value = compile_string(token_text, TRUE, TRUE);
+ /* This string must be in low memory so that the
+ dynamic string table can refer to it. */
+ AO4.value = compile_string(token_text, STRCTX_LOWSTRING);
}
else
{ put_token_back();
get_next_token();
/* Initialisation code */
+ AO.type = OMITTED_OT;
+ spare_debug_location1 = statement_debug_location;
+ AO2.type = OMITTED_OT; flag = 0;
+ spare_debug_location2 = statement_debug_location;
if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
{ put_token_back();
assemble_label_no(ln2);
return;
}
- AO.type = OMITTED_OT;
goto ParseUpdate;
}
put_token_back();
}
get_next_token();
- AO.type = OMITTED_OT;
if (!((token_type==SEP_TT)&&(token_value==COLON_SEP)))
{ put_token_back();
spare_debug_location1 = get_token_location();
get_next_token();
ParseUpdate:
- AO2.type = OMITTED_OT; flag = 0;
if (!((token_type==SEP_TT)&&(token_value==CLOSEB_SEP)))
{ put_token_back();
spare_debug_location2 = get_token_location();
get_next_token();
if (token_type == DQ_TT)
{ INITAOT(&AO4, CONSTANT_OT);
- AO4.value = compile_string(token_text, TRUE, TRUE);
+ /* This is not actually placed in low memory; Glulx
+ has no such concept. We use the LOWSTRING flag
+ for compatibility with older compiler behavior. */
+ AO4.value = compile_string(token_text, STRCTX_LOWSTRING);
AO4.marker = STRING_MV;
}
else
the name strings of symbols */
static int no_symbol_name_space_chunks;
+/* Symbol replacements (used by the "Replace X Y" directive). */
+
typedef struct value_pair_struct {
int original_symbol;
int renamed_symbol;
static int symbol_replacements_count;
static int symbol_replacements_size; /* calloced size */
+/* Symbol definitions requested at compile time. (There may not be any.)
+ These are set up at command-line parse time, not in init_symbols_vars().
+ Similarly, they are not cleaned up by symbols_free_arrays(). */
+
+typedef struct keyvalue_pair_struct {
+ char *symbol;
+ int32 value;
+} keyvalue_pair_t;
+static keyvalue_pair_t *symbol_definitions = NULL;
+static int symbol_definitions_count = 0;
+static int symbol_definitions_size = 0; /* calloced size */
+
/* ------------------------------------------------------------------------- */
/* The symbols table is "hash-coded" into a disjoint union of linked */
/* lists, so that for any symbol i, next_entry[i] is either -1 (meaning */
return -qc;
}
+/* ------------------------------------------------------------------------- */
+
+extern void add_config_symbol_definition(char *symbol, int32 value)
+{
+ if (symbol_definitions_count == symbol_definitions_size) {
+ int oldsize = symbol_definitions_size;
+ if (symbol_definitions_size == 0)
+ symbol_definitions_size = 4;
+ else
+ symbol_definitions_size *= 2;
+ my_recalloc(&symbol_definitions, sizeof(keyvalue_pair_t), oldsize,
+ symbol_definitions_size, "symbol definition table");
+ }
+
+ char *str = my_malloc(strlen(symbol)+1, "symbol name");
+ strcpy(str, symbol);
+
+ symbol_definitions[symbol_definitions_count].symbol = str;
+ symbol_definitions[symbol_definitions_count].value = value;
+ symbol_definitions_count++;
+}
+
/* ------------------------------------------------------------------------- */
/* Symbol finding, creating, and removing. */
/* ------------------------------------------------------------------------- */
veneer_mode = TRUE;
- null_value = compile_string(unknown_attribute, FALSE, FALSE);
+ null_value = compile_string(unknown_attribute, STRCTX_SYMBOL);
for (i=0; i<NUM_ATTR_BYTES*8; i++) attribute_name_strings[i] = null_value;
for (i=0; i<no_symbols; i++)
}
individual_name_strings[svals[i]]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
}
else
{ sprintf(idname_string, "%s", (char *) symbs[i]);
individual_name_strings[svals[i]]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
}
if (t == ATTRIBUTE_T)
}
attribute_name_strings[svals[i]]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
}
else
{ sprintf(idname_string, "%s", (char *) symbs[i]);
attribute_name_strings[svals[i]]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
}
if (sflags[i] & ACTION_SFLAG)
}
action_name_strings[svals[i]]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
}
action_name_strings[svals[i]
- ((grammar_version_number==1)?256:4096) + no_actions]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
}
sprintf(idname_string, "%s", (char *) symbs[i]);
array_name_strings[j]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
if (define_INFIX_switch)
{ for (i=0; i<no_symbols; i++)
{ if (stypes[i] == GLOBAL_VARIABLE_T)
{ sprintf(idname_string, "%s", (char *) symbs[i]);
array_name_strings[no_arrays + svals[i] -16]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
}
for (i=0; i<no_named_routines; i++)
{ sprintf(idname_string, "%s", (char *) symbs[named_routine_symbols[i]]);
array_name_strings[no_arrays + no_globals + i]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
for (i=0, no_named_constants=0; i<no_symbols; i++)
{ sprintf(idname_string, "%s", (char *) symbs[i]);
array_name_strings[no_arrays + no_globals + no_named_routines
+ no_named_constants++]
- = compile_string(idname_string, FALSE, FALSE);
+ = compile_string(idname_string, STRCTX_SYMBOL);
}
}
}
static void create_symbol(char *p, int32 value, int type)
{ int i = symbol_index(p, -1);
+ if (!(sflags[i] & (UNKNOWN_SFLAG + REDEFINABLE_SFLAG))) {
+ /* Symbol already defined! */
+ if (svals[i] == value && stypes[i] == type) {
+ /* Special case: the symbol was already defined with this same
+ value. We let it pass. */
+ return;
+ }
+ else {
+ ebf_symbol_error("new symbol", p, typename(stypes[i]), slines[i]);
+ return;
+ }
+ }
svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
- sflags[i] = USED_SFLAG + SYSTEM_SFLAG;
+ /* If the symbol already existed with REDEFINABLE_SFLAG, we keep that. */
+ sflags[i] = USED_SFLAG + SYSTEM_SFLAG + (sflags[i] & REDEFINABLE_SFLAG);
emit_debug_information_for_predefined_symbol(p, i, value, type);
}
static void create_rsymbol(char *p, int value, int type)
{ int i = symbol_index(p, -1);
+ /* This is only called for a few symbols with known names.
+ They will not collide. */
svals[i] = value; stypes[i] = type; slines[i] = blank_brief_location;
sflags[i] = USED_SFLAG + SYSTEM_SFLAG + REDEFINABLE_SFLAG;
emit_debug_information_for_predefined_symbol(p, i, value, type);
create_symbol("FLOAT_NINFINITY", 0xFF800000, CONSTANT_T);
create_symbol("FLOAT_NAN", 0x7FC00000, CONSTANT_T);
}
+
+ if (symbol_definitions && symbol_definitions_count) {
+ int ix;
+ for (ix=0; ix<symbol_definitions_count; ix++) {
+ char *str = symbol_definitions[ix].symbol;
+ int32 val = symbol_definitions[ix].value;
+ create_symbol(str, val, CONSTANT_T);
+ }
+ }
}
/* ------------------------------------------------------------------------- */
mark them as used. */
func = df_functions_head;
- if (!func || func->address != DF_NOT_IN_FUNCTION)
+ if (!func || func->address != DF_NOT_IN_FUNCTION) {
compiler_error("DF: Global namespace entry is not at the head of the chain.");
+ return;
+ }
for (ent = func->refs; ent; ent=ent->refsnext) {
uint32 addr;
"array name strings");
write_the_identifier_names();
- threespaces = compile_string(" ", FALSE, FALSE);
+ threespaces = compile_string(" ", STRCTX_GAME);
compress_game_text();
text buffer holding the entire text
of the game, when it is being
recorded */
-int is_abbreviation, /* When TRUE, the string being trans
- is itself an abbreviation string
- so can't make use of abbreviations */
- abbrevs_lookup_table_made, /* The abbreviations lookup table is
+int abbrevs_lookup_table_made, /* The abbreviations lookup table is
constructed when the first non-
abbreviation string is translated:
this flag is TRUE after that */
strcpy((char *)abbreviations_at
+ no_abbreviations*MAX_ABBREV_LENGTH, text);
- is_abbreviation = TRUE;
- abbrev_values[no_abbreviations] = compile_string(text, TRUE, TRUE);
- is_abbreviation = FALSE;
+ abbrev_values[no_abbreviations] = compile_string(text, STRCTX_ABBREV);
/* The quality is the number of Z-chars saved by using this */
/* abbreviation: note that it takes 2 Z-chars to print it. */
}
/* ------------------------------------------------------------------------- */
-/* The front end routine for text translation */
+/* The front end routine for text translation. */
+/* strctx indicates the purpose of the string. This is mostly used for */
+/* informational output (gametext.txt), but we treat some string contexts */
+/* specially during compilation. */
/* ------------------------------------------------------------------------- */
-extern int32 compile_string(char *b, int in_low_memory, int is_abbrev)
+extern int32 compile_string(char *b, int strctx)
{ int i, j; uchar *c;
- is_abbreviation = is_abbrev;
-
- /* Put into the low memory pool (at 0x100 in the Z-machine) of strings */
- /* which may be wanted as possible entries in the abbreviations table */
+ /* In Z-code, abbreviations go in the low memory pool (0x100). So
+ do strings explicitly defined with the Lowstring directive.
+ (In Glulx, the in_low_memory flag is ignored.) */
+ int in_low_memory = (strctx == STRCTX_ABBREV || strctx == STRCTX_LOWSTRING);
if (!glulx_mode && in_low_memory)
{ j=subtract_pointers(low_strings_top,low_strings);
- low_strings_top=translate_text(low_strings_top, low_strings+MAX_LOW_STRINGS, b);
+ low_strings_top=translate_text(low_strings_top, low_strings+MAX_LOW_STRINGS, b, strctx);
if (!low_strings_top)
memoryerror("MAX_LOW_STRINGS", MAX_LOW_STRINGS);
- is_abbreviation = FALSE;
return(0x21+(j/2));
}
if (glulx_mode && done_compression)
compiler_error("Tried to add a string after compression was done.");
- c = translate_text(strings_holding_area, strings_holding_area+MAX_STATIC_STRINGS, b);
+ c = translate_text(strings_holding_area, strings_holding_area+MAX_STATIC_STRINGS, b, strctx);
if (!c)
memoryerror("MAX_STATIC_STRINGS",MAX_STATIC_STRINGS);
write_byte_to_memory_block(&static_strings_area,
static_strings_extent, *c);
- is_abbreviation = FALSE;
-
if (!glulx_mode) {
return(j/scale_factor);
}
/* Note that the source text may be corrupted by this routine. */
/* ------------------------------------------------------------------------- */
-extern uchar *translate_text(uchar *p, uchar *p_limit, char *s_text)
+extern uchar *translate_text(uchar *p, uchar *p_limit, char *s_text, int strctx)
{ int i, j, k, in_alphabet, lookup_value;
int32 unicode; int zscii;
unsigned char *text_in;
+ /* For STRCTX_ABBREV, the string being translated is itself an
+ abbreviation string, so it can't make use of abbreviations. Set
+ the is_abbreviation flag to indicate this.
+ The compiler has historically set this flag for the Lowstring
+ directive as well -- the in_low_memory and is_abbreviation flag were
+ always the same. I am preserving that convention. */
+ int is_abbreviation = (strctx == STRCTX_ABBREV || strctx == STRCTX_LOWSTRING);
+
+
/* Cast the input and output streams to unsigned char: text_out_pc will
advance as bytes of Z-coded text are written, but text_in doesn't */
all_text_top += strlen(all_text_top);
}
- if (transcript_switch && (!veneer_mode))
- write_to_transcript_file(s_text);
-
+ if (transcript_switch) {
+ /* Omit veneer strings, unless we're using the new transcript format, which includes everything. */
+ if ((!veneer_mode) || TRANSCRIPT_FORMAT == 1) {
+ int label = strctx;
+ if (veneer_mode) {
+ if (label == STRCTX_GAME)
+ label = STRCTX_VENEER;
+ else if (label == STRCTX_GAMEOPC)
+ label = STRCTX_VENEEROPC;
+ }
+ write_to_transcript_file(s_text, label);
+ }
+ }
+
if (!glulx_mode) {
/* The empty string of Z-text is illegal, since it can't carry an end
/* For Glulx, the form is instead: (But see below about Unicode-valued */
/* dictionaries and my heinie.) */
/* */
-/* <plain text> <flags> <verbnumber> <adjectivenumber> */
-/* DICT_WORD_SIZE short short short */
+/* <tag> <plain text> <flags> <verbnumber> <adjectivenumber> */
+/* $60 DICT_WORD_SIZE short short short */
/* */
/* These records are stored in "accession order" (i.e. in order of their */
/* first being received by these routines) and only alphabetically sorted */
for (; i<9; i++) wd[i]=5;
- /* The array of Z-chars is converted to three 2-byte blocks */
+ /* The array of Z-chars is converted to two or three 2-byte blocks */
tot = wd[2] + wd[1]*(1<<5) + wd[0]*(1<<10);
prepared_sort[1]=tot%0x100;
tot = wd[5] + wd[4]*(1<<5) + wd[3]*(1<<10);
prepared_sort[3]=tot%0x100;
prepared_sort[2]=(tot/0x100)%0x100;
- tot = wd[8] + wd[7]*(1<<5) + wd[6]*(1<<10);
+ if (version_number==3)
+ tot = 0;
+ else
+ tot = wd[8] + wd[7]*(1<<5) + wd[6]*(1<<10);
prepared_sort[5]=tot%0x100;
prepared_sort[4]=(tot/0x100)%0x100;
/* by the linker. */
/* ------------------------------------------------------------------------- */
-static char *d_show_to;
-static int d_show_total;
+/* In the dictionary-showing code, if d_show_buf is NULL, the text is
+ printed directly. (The "Trace dictionary" directive does this.)
+ If d_show_buf is not NULL, we add words to it (reallocing if necessary)
+ until it's a page-width.
+*/
+static char *d_show_buf = NULL;
+static int d_show_size; /* allocated size */
+static int d_show_len; /* current length */
static void show_char(char c)
-{ if (d_show_to == NULL) printf("%c", c);
- else
- { int i = strlen(d_show_to);
- d_show_to[i] = c; d_show_to[i+1] = 0;
+{
+ if (d_show_buf == NULL) {
+ printf("%c", c);
+ }
+ else {
+ if (d_show_len+2 >= d_show_size) {
+ int newsize = 2 * d_show_len + 16;
+ my_realloc(&d_show_buf, d_show_size, newsize, "dictionary display buffer");
+ d_show_size = newsize;
+ }
+ d_show_buf[d_show_len++] = c;
+ d_show_buf[d_show_len] = '\0';
}
}
+/* Display a Unicode character in user-readable form. This uses the same
+ character encoding as the source code. */
+static void show_uchar(uint32 c)
+{
+ char buf[16];
+ int ix;
+
+ if (c < 0x80) {
+ /* ASCII always works */
+ show_char(c);
+ return;
+ }
+ if (character_set_unicode) {
+ /* UTF-8 the character */
+ if (c < 0x80) {
+ show_char(c);
+ }
+ else if (c < 0x800) {
+ show_char((0xC0 | ((c & 0x7C0) >> 6)));
+ show_char((0x80 | (c & 0x03F) ));
+ }
+ else if (c < 0x10000) {
+ show_char((0xE0 | ((c & 0xF000) >> 12)));
+ show_char((0x80 | ((c & 0x0FC0) >> 6)));
+ show_char((0x80 | (c & 0x003F) ));
+ }
+ else if (c < 0x200000) {
+ show_char((0xF0 | ((c & 0x1C0000) >> 18)));
+ show_char((0x80 | ((c & 0x03F000) >> 12)));
+ show_char((0x80 | ((c & 0x000FC0) >> 6)));
+ show_char((0x80 | (c & 0x00003F) ));
+ }
+ else {
+ show_char('?');
+ }
+ return;
+ }
+ if (character_set_setting == 1 && c < 0x100) {
+ /* Fits in Latin-1 */
+ show_char(c);
+ return;
+ }
+ /* Supporting other character_set_setting is harder; not currently implemented. */
+
+ /* Use the escaped form */
+ sprintf(buf, "@{%x}", c);
+ for (ix=0; buf[ix]; ix++)
+ show_char(buf[ix]);
+}
+
extern void word_to_ascii(uchar *p, char *results)
{ int i, shift, cc, zchar; uchar encoded_word[9];
encoded_word[0] = (((int) p[0])&0x7c)/4;
static void recursively_show_z(int node)
{ int i, cprinted, flags; uchar *p;
char textual_form[32];
- int res = (version_number == 3)?4:6;
+ int res = (version_number == 3)?4:6; /* byte length of encoded text */
if (dtree[node].branch[0] != VACANT)
recursively_show_z(dtree[node].branch[0]);
for (; cprinted < 4 + ((version_number==3)?6:9); cprinted++)
show_char(' ');
- if (d_show_to == NULL)
+ if (d_show_buf == NULL)
{ for (i=0; i<3+res; i++) printf("%02x ",p[i]);
flags = (int) p[res];
printf("\n");
}
- if (d_show_total++ == 5)
- { d_show_total = 0;
- if (d_show_to != NULL)
- { write_to_transcript_file(d_show_to);
- d_show_to[0] = 0;
- }
+ /* Show five words per line in classic TRANSCRIPT_FORMAT; one per line in the new format. */
+ if (d_show_buf && (d_show_len >= 64 || TRANSCRIPT_FORMAT == 1))
+ {
+ write_to_transcript_file(d_show_buf, STRCTX_DICT);
+ d_show_len = 0;
}
if (dtree[node].branch[1] != VACANT)
}
static void recursively_show_g(int node)
-{
- warning("### Glulx dictionary-show not yet implemented.\n");
+{ int i, cprinted;
+ uchar *p;
+
+ if (dtree[node].branch[0] != VACANT)
+ recursively_show_g(dtree[node].branch[0]);
+
+ p = (uchar *)dictionary + 4 + DICT_ENTRY_BYTE_LENGTH*node;
+
+ for (cprinted = 0; cprinted<DICT_WORD_SIZE; cprinted++)
+ {
+ uint32 ch;
+ if (DICT_CHAR_SIZE == 1)
+ ch = p[1+cprinted];
+ else
+ ch = (p[4*cprinted+4] << 24) + (p[4*cprinted+5] << 16) + (p[4*cprinted+6] << 8) + (p[4*cprinted+7]);
+ if (!ch)
+ break;
+ show_uchar(ch);
+ }
+ for (; cprinted<DICT_WORD_SIZE+4; cprinted++)
+ show_char(' ');
+
+ if (d_show_buf == NULL)
+ { for (i=0; i<DICT_ENTRY_BYTE_LENGTH; i++) printf("%02x ",p[i]);
+ int flagpos = (DICT_CHAR_SIZE == 1) ? (DICT_WORD_SIZE+1) : (DICT_WORD_BYTES+4);
+ int flags = (p[flagpos+0] << 8) | (p[flagpos+1]);
+ int verbnum = (p[flagpos+2] << 8) | (p[flagpos+3]);
+ if (flags & 128)
+ { printf("noun ");
+ if (flags & 4) printf("p"); else printf(" ");
+ printf(" ");
+ }
+ else printf(" ");
+ if (flags & 8)
+ { printf("preposition ");
+ }
+ if ((flags & 3) == 3) printf("metaverb:%d ", verbnum);
+ else if ((flags & 3) == 1) printf("verb:%d ", verbnum);
+ printf("\n");
+ }
+
+ /* Show five words per line in classic TRANSCRIPT_FORMAT; one per line in the new format. */
+ if (d_show_buf && (d_show_len >= 64 || TRANSCRIPT_FORMAT == 1))
+ {
+ write_to_transcript_file(d_show_buf, STRCTX_DICT);
+ d_show_len = 0;
+ }
+
+ if (dtree[node].branch[1] != VACANT)
+ recursively_show_g(dtree[node].branch[1]);
}
static void show_alphabet(int i)
extern void show_dictionary(void)
{ printf("Dictionary contains %d entries:\n",dict_entries);
if (dict_entries != 0)
- { d_show_total = 0; d_show_to = NULL;
+ { d_show_len = 0; d_show_buf = NULL;
if (!glulx_mode)
recursively_show_z(root);
else
recursively_show_g(root);
}
- printf("\nZ-machine alphabet entries:\n");
- show_alphabet(0);
- show_alphabet(1);
- show_alphabet(2);
+ if (!glulx_mode)
+ {
+ printf("\nZ-machine alphabet entries:\n");
+ show_alphabet(0);
+ show_alphabet(1);
+ show_alphabet(2);
+ }
}
extern void write_dictionary_to_transcript(void)
-{ char d_buffer[81];
-
- sprintf(d_buffer, "\n[Dictionary contains %d entries:]\n", dict_entries);
+{
+ d_show_size = 80; /* initial size */
+ d_show_buf = my_malloc(d_show_size, "dictionary display buffer");
- d_buffer[0] = 0; write_to_transcript_file(d_buffer);
+ write_to_transcript_file("", STRCTX_INFO);
+ sprintf(d_show_buf, "[Dictionary contains %d entries:]", dict_entries);
+ write_to_transcript_file(d_show_buf, STRCTX_INFO);
+
+ d_show_len = 0;
if (dict_entries != 0)
- { d_show_total = 0; d_show_to = d_buffer;
+ {
if (!glulx_mode)
recursively_show_z(root);
else
recursively_show_g(root);
}
- if (d_show_total != 0) write_to_transcript_file(d_buffer);
+ if (d_show_len != 0) write_to_transcript_file(d_show_buf, STRCTX_DICT);
+
+ my_free(&d_show_buf, "dictionary display buffer");
+ d_show_len = 0; d_show_buf = NULL;
}
/* ========================================================================= */
grandtable = NULL;
grandflags = NULL;
no_chars_transcribed = 0;
- is_abbreviation = FALSE;
for (j=0; j<256; j++) abbrevs_lookup[j] = -1;
= my_malloc(MAX_STATIC_STRINGS,"static strings holding area");
low_strings = my_malloc(MAX_LOW_STRINGS,"low (abbreviation) strings");
+ d_show_buf = NULL;
+ d_show_size = 0;
+ d_show_len = 0;
+
huff_entities = NULL;
hufflist = NULL;
unicode_usage_entries = NULL;
/* for example the English verbs "take" and "drop" both normally */
/* correspond in a game's dictionary to the same Inform verb. An */
/* Inform verb is essentially a list of grammar lines. */
+/* (Calling them "English verbs" is of course out of date. Read */
+/* this as jargon for "dict words which are verbs". */
/* ------------------------------------------------------------------------- */
/* Arrays defined below: */
/* */
static int English_verb_list_size; /* Size of the list in bytes
(redundant but convenient) */
+/* Maximum synonyms in a single Verb/Extend directive */
+#define MAX_VERB_SYNONYMS (32)
+
/* ------------------------------------------------------------------------- */
/* Arrays used by this file */
/* ------------------------------------------------------------------------- */
int Inform_verb, meta_verb_flag=FALSE, verb_equals_form=FALSE;
- char *English_verbs_given[32]; int no_given = 0, i;
+ char *English_verbs_given[MAX_VERB_SYNONYMS];
+ int no_given = 0, i;
directive_keywords.enabled = TRUE;
}
while ((token_type == DQ_TT) || (token_type == SQ_TT))
- { English_verbs_given[no_given++] = token_text;
+ {
+ if (no_given >= MAX_VERB_SYNONYMS) {
+ error("Too many synonyms in a Verb directive.");
+ panic_mode_error_recovery(); return;
+ }
+ English_verbs_given[no_given++] = token_text;
get_next_token();
}