X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Fverbs.c;h=31b42bb2ee999a5c92087c6c2c840f7e5ea9aa64;hb=8e63120c630c94c598d4e2d6ba823dac59bce8fa;hp=962b32f847a3e9a46962745549da8488547e0ece;hpb=d11f2f726ed7feea617476d99cf7505ddd9a27ce;p=inform.git diff --git a/src/verbs.c b/src/verbs.c index 962b32f..31b42bb 100644 --- a/src/verbs.c +++ b/src/verbs.c @@ -2,8 +2,8 @@ /* "verbs" : Manages actions and grammar tables; parses the directives */ /* Verb and Extend. */ /* */ -/* 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 */ @@ -31,13 +31,8 @@ int32 grammar_version_symbol; /* Index of "Grammar__Version" /* ------------------------------------------------------------------------- */ /* Array defined below: */ /* */ -/* int32 action_byte_offset[n] The (byte) offset in the Z-machine */ -/* code area of the ...Sub routine */ -/* for action n. (NB: This is left */ -/* blank until the end of the */ -/* compilation pass.) */ -/* int32 action_symbol[n] The symbol table index of the n-th */ -/* action's name. */ +/* actioninfo actions[n] Symbol table index and byte offset */ +/* of the ...Sub routine */ /* ------------------------------------------------------------------------- */ int no_actions, /* Number of actions made so far */ @@ -83,42 +78,228 @@ int no_Inform_verbs, /* Number of Inform-verbs made so far */ /* The format of this list is a sequence of variable-length records: */ /* */ /* Byte offset to start of next record (1 byte) */ -/* Inform verb number this word corresponds to (1 byte) */ +/* Inform verb number this word corresponds to (2 bytes) */ /* The English verb-word (reduced to lower case), null-terminated */ /* ------------------------------------------------------------------------- */ -static char *English_verb_list, /* First byte of first record */ - *English_verb_list_top; /* Next byte free for new record */ +static char *English_verb_list; /* Allocated to English_verb_list_size */ +static memory_list English_verb_list_memlist; -static int English_verb_list_size; /* Size of the list in bytes - (redundant but convenient) */ +static int English_verb_list_size; /* Size of the list in bytes */ -/* Maximum synonyms in a single Verb/Extend directive */ -#define MAX_VERB_SYNONYMS (32) +static char *English_verbs_given; /* Allocated to verbs_given_pos + (Used only within make_verb()) */ +static memory_list English_verbs_given_memlist; /* ------------------------------------------------------------------------- */ /* Arrays used by this file */ /* ------------------------------------------------------------------------- */ - verbt *Inform_verbs; - uchar *grammar_lines; + verbt *Inform_verbs; /* Allocated up to no_Inform_verbs */ + static memory_list Inform_verbs_memlist; + uchar *grammar_lines; /* Allocated to grammar_lines_top */ + static memory_list grammar_lines_memlist; int32 grammar_lines_top; int no_grammar_lines, no_grammar_tokens; - int32 *action_byte_offset, - *action_symbol, - *grammar_token_routine, - *adjectives; - static uchar *adjective_sort_code; + actioninfo *actions; /* Allocated to no_actions */ + memory_list actions_memlist; + int32 *grammar_token_routine; /* Allocated to no_grammar_token_routines */ + static memory_list grammar_token_routine_memlist; + + int32 *adjectives; /* Allocated to no_adjectives */ + static memory_list adjectives_memlist; + + static uchar *adjective_sort_code; /* Allocated to no_adjectives*DICT_WORD_BYTES */ + static memory_list adjective_sort_code_memlist; /* ------------------------------------------------------------------------- */ /* Tracing for compiler maintenance */ /* ------------------------------------------------------------------------- */ +static char *find_verb_by_number(int num); + +static void list_grammar_line_v1(int mark) +{ + int action, actsym; + int ix, len; + char *str; + + /* There is no GV1 for Glulx. */ + if (glulx_mode) + return; + + action = (grammar_lines[mark] << 8) | (grammar_lines[mark+1]); + mark += 2; + + printf(" *"); + while (grammar_lines[mark] != 15) { + uchar tok = grammar_lines[mark]; + mark += 3; + + switch (tok) { + case 0: + printf(" noun"); + break; + case 1: + printf(" held"); + break; + case 2: + printf(" multi"); + break; + case 3: + printf(" multiheld"); + break; + case 4: + printf(" multiexcept"); + break; + case 5: + printf(" multiinside"); + break; + case 6: + printf(" creature"); + break; + case 7: + printf(" special"); + break; + case 8: + printf(" number"); + break; + default: + if (tok >= 16 && tok < 48) { + printf(" noun=%d", tok-16); + } + else if (tok >= 48 && tok < 80) { + printf(" routine=%d", tok-48); + } + else if (tok >= 80 && tok < 128) { + printf(" scope=%d", tok-80); + } + else if (tok >= 128 && tok < 160) { + printf(" attr=%d", tok-128); + } + else if (tok >= 160) { + printf(" prep=%d", tok); + } + else { + printf(" ???"); + } + } + } + + printf(" -> "); + actsym = actions[action].symbol; + str = (symbols[actsym].name); + len = strlen(str) - 3; /* remove "__A" */ + for (ix=0; ix> 4) & 0x03; + mark += 1; + tokdat = (grammar_lines[mark] << 8) | (grammar_lines[mark+1]); + mark += 2; + } + else { + toktype = grammar_lines[mark] & 0x0F; + tokalt = (grammar_lines[mark] >> 4) & 0x03; + mark += 1; + tokdat = (grammar_lines[mark] << 24) | (grammar_lines[mark+1] << 16) | (grammar_lines[mark+2] << 8) | (grammar_lines[mark+3]); + mark += 4; + } + + if (tokalt == 3 || tokalt == 1) + printf(" /"); + + switch (toktype) { + case 1: + switch (tokdat) { + case 0: printf(" noun"); break; + case 1: printf(" held"); break; + case 2: printf(" multi"); break; + case 3: printf(" multiheld"); break; + case 4: printf(" multiexcept"); break; + case 5: printf(" multiinside"); break; + case 6: printf(" creature"); break; + case 7: printf(" special"); break; + case 8: printf(" number"); break; + case 9: printf(" topic"); break; + default: printf(" ???"); break; + } + break; + case 2: + printf(" '"); + print_dict_word(tokdat); + printf("'"); + break; + case 3: + printf(" noun=%d", tokdat); + break; + case 4: + printf(" attr=%d", tokdat); + break; + case 5: + printf(" scope=%d", tokdat); + break; + case 6: + printf(" routine=%d", tokdat); + break; + default: + printf(" ???%d:%d", toktype, tokdat); + break; + } + } + printf(" -> "); + actsym = actions[action].symbol; + str = (symbols[actsym].name); + len = strlen(str) - 3; /* remove "__A" */ + for (ix=0; ix"); debug_file_printf("##%s", token_text); - debug_file_printf("%d", svals[i]); + debug_file_printf("%d", symbols[i].value); get_next_token(); write_debug_locations (get_token_location_end(beginning_debug_location)); @@ -193,33 +374,34 @@ extern assembly_operand action_of_name(char *name) snprintf(action_sub, MAX_IDENTIFIER_LENGTH+4, "%s__A", name); j = symbol_index(action_sub, -1); - if (stypes[j] == FAKE_ACTION_T) + if (symbols[j].type == FAKE_ACTION_T) { INITAO(&AO); - AO.value = svals[j]; + AO.value = symbols[j].value; if (!glulx_mode) AO.type = LONG_CONSTANT_OT; else set_constant_ot(&AO); - sflags[j] |= USED_SFLAG; + symbols[j].flags |= USED_SFLAG; return AO; } - if (sflags[j] & UNKNOWN_SFLAG) + if (symbols[j].flags & UNKNOWN_SFLAG) { - if (no_actions>=MAX_ACTIONS) memoryerror("MAX_ACTIONS",MAX_ACTIONS); + ensure_memory_list_available(&actions_memlist, no_actions+1); new_action(name, no_actions); - action_symbol[no_actions] = j; + actions[no_actions].symbol = j; + actions[no_actions].byte_offset = 0; /* fill in later */ assign_symbol(j, no_actions++, CONSTANT_T); - sflags[j] |= ACTION_SFLAG; + symbols[j].flags |= ACTION_SFLAG; } - sflags[j] |= USED_SFLAG; + symbols[j].flags |= USED_SFLAG; INITAO(&AO); - AO.value = svals[j]; + AO.value = symbols[j].value; AO.marker = ACTION_MV; if (!glulx_mode) { AO.type = (module_switch)?LONG_CONSTANT_OT:SHORT_CONSTANT_OT; - if (svals[j] >= 256) AO.type = LONG_CONSTANT_OT; + if (symbols[j].value >= 256) AO.type = LONG_CONSTANT_OT; } else { AO.type = CONSTANT_OT; @@ -233,27 +415,27 @@ extern void find_the_actions(void) char action_sub[MAX_IDENTIFIER_LENGTH+4]; if (module_switch) - for (i=0; i= MAX_ADJECTIVES) - memoryerror("MAX_ADJECTIVES", MAX_ADJECTIVES); + if (no_adjectives >= 255) { + error("Grammar version 1 cannot support more than 255 prepositions"); + return 0; + } + if (ZCODE_LESS_DICT_DATA && !glulx_mode) { + /* We need to use #dict_par3 for the preposition number. */ + error("Grammar version 1 cannot be used with ZCODE_LESS_DICT_DATA"); + return 0; + } + ensure_memory_list_available(&adjectives_memlist, no_adjectives+1); + ensure_memory_list_available(&adjective_sort_code_memlist, (no_adjectives+1) * DICT_WORD_BYTES); dictionary_prepare(English_word, new_sort_code); for (i=0; i MAX_VERB_WORD_SIZE+4) error_numbered("Verb word is too long -- max length is", MAX_VERB_WORD_SIZE); + ensure_memory_list_available(&English_verb_list_memlist, English_verb_list_size + entrysize); + top = English_verb_list + English_verb_list_size; English_verb_list_size += entrysize; - if (English_verb_list_size >= MAX_VERBSPACE) - memoryerror("MAX_VERBSPACE", MAX_VERBSPACE); - - English_verb_list_top[0] = entrysize; - English_verb_list_top[1] = number/256; - English_verb_list_top[2] = number%256; - strcpy(English_verb_list_top+3, English_verb); - English_verb_list_top += entrysize; + + top[0] = entrysize; + top[1] = number/256; + top[2] = number%256; + strcpy(top+3, English_verb); } static int get_verb(void) @@ -395,9 +604,25 @@ static int get_verb(void) /* Grammar lines for Verb/Extend directives. */ /* ------------------------------------------------------------------------- */ +static void ensure_grammar_lines_available(int verbnum, int num) +{ + /* Note that the size field always starts positive. */ + if (num > Inform_verbs[verbnum].size) { + int newsize = 2*num+4; + my_realloc(&Inform_verbs[verbnum].l, sizeof(int) * Inform_verbs[verbnum].size, sizeof(int) * newsize, "grammar lines for one verb"); + Inform_verbs[verbnum].size = newsize; + } +} + static int grammar_line(int verbnum, int line) { - /* Parse a grammar line, to be written into grammar_lines[mark] onward. + /* Parse a grammar line, to be written into grammar_lines[] starting + at grammar_lines_top. grammar_lines_top is left at the end + of the new line. + + This stores the line position in Inform_verbs[verbnum].l[line]. + (It does not increment Inform_verbs[verbnum].lines; the caller + must do that.) Syntax: * ... -> @@ -435,32 +660,9 @@ static int grammar_line(int verbnum, int line) return FALSE; } - /* Have we run out of lines or token space? */ - - if (line >= MAX_LINES_PER_VERB) - { discard_token_location(beginning_debug_location); - error("Too many lines of grammar for verb. This maximum is built \ -into Inform, so suggest rewriting grammar using general parsing routines"); - return(FALSE); - } - - /* Internally, a line can be up to 3*32 + 1 + 2 = 99 bytes long */ - /* In Glulx, that's 5*32 + 4 = 164 bytes */ - mark = grammar_lines_top; - if (!glulx_mode) { - if (mark + 100 >= MAX_LINESPACE) - { discard_token_location(beginning_debug_location); - memoryerror("MAX_LINESPACE", MAX_LINESPACE); - } - } - else { - if (mark + 165 >= MAX_LINESPACE) - { discard_token_location(beginning_debug_location); - memoryerror("MAX_LINESPACE", MAX_LINESPACE); - } - } + ensure_grammar_lines_available(verbnum, line+1); Inform_verbs[verbnum].l[line] = mark; if (!glulx_mode) { @@ -471,6 +673,7 @@ into Inform, so suggest rewriting grammar using general parsing routines"); mark = mark + 3; TOKEN_SIZE = 5; } + ensure_memory_list_available(&grammar_lines_memlist, mark); grammar_token = 0; last_was_slash = TRUE; slash_mode = FALSE; no_grammar_lines++; @@ -522,7 +725,7 @@ into Inform, so suggest rewriting grammar using general parsing routines"); get_next_token(); if ((token_type != SYMBOL_TT) - || (stypes[token_value] != ROUTINE_T)) + || (symbols[token_value].type != ROUTINE_T)) { discard_token_location(beginning_debug_location); ebf_error("routine name after 'noun='", token_text); panic_mode_error_recovery(); @@ -530,12 +733,12 @@ into Inform, so suggest rewriting grammar using general parsing routines"); } if (grammar_version_number == 1) bytecode - = 16 + make_parsing_routine(svals[token_value]); + = 16 + make_parsing_routine(symbols[token_value].value); else { bytecode = 0x83; - wordcode = svals[token_value]; + wordcode = symbols[token_value].value; } - sflags[token_value] |= USED_SFLAG; + symbols[token_value].flags |= USED_SFLAG; } else { put_token_back(); @@ -586,7 +789,7 @@ are using Library 6/3 or later"); get_next_token(); if ((token_type != SYMBOL_TT) - || (stypes[token_value] != ROUTINE_T)) + || (symbols[token_value].type != ROUTINE_T)) { discard_token_location(beginning_debug_location); ebf_error("routine name after 'scope='", token_text); panic_mode_error_recovery(); @@ -595,9 +798,9 @@ are using Library 6/3 or later"); if (grammar_version_number == 1) bytecode = 80 + - make_parsing_routine(svals[token_value]); - else { bytecode = 0x85; wordcode = svals[token_value]; } - sflags[token_value] |= USED_SFLAG; + make_parsing_routine(symbols[token_value].value); + else { bytecode = 0x85; wordcode = symbols[token_value].value; } + symbols[token_value].flags |= USED_SFLAG; } else if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)) { discard_token_location(beginning_debug_location); @@ -608,25 +811,25 @@ are using Library 6/3 or later"); else { /* or tokens */ if ((token_type != SYMBOL_TT) - || ((stypes[token_value] != ATTRIBUTE_T) - && (stypes[token_value] != ROUTINE_T))) + || ((symbols[token_value].type != ATTRIBUTE_T) + && (symbols[token_value].type != ROUTINE_T))) { discard_token_location(beginning_debug_location); error_named("No such grammar token as", token_text); panic_mode_error_recovery(); return FALSE; } - if (stypes[token_value]==ATTRIBUTE_T) + if (symbols[token_value].type==ATTRIBUTE_T) { if (grammar_version_number == 1) - bytecode = 128 + svals[token_value]; - else { bytecode = 4; wordcode = svals[token_value]; } + bytecode = 128 + symbols[token_value].value; + else { bytecode = 4; wordcode = symbols[token_value].value; } } else { if (grammar_version_number == 1) bytecode = 48 + - make_parsing_routine(svals[token_value]); - else { bytecode = 0x86; wordcode = svals[token_value]; } + make_parsing_routine(symbols[token_value].value); + else { bytecode = 0x86; wordcode = symbols[token_value].value; } } - sflags[token_value] |= USED_SFLAG; + symbols[token_value].flags |= USED_SFLAG; } grammar_token++; no_grammar_tokens++; @@ -641,6 +844,7 @@ tokens in any line (unless you're compiling with library 6/3 or later)"); error("'/' can only be applied to prepositions"); bytecode |= 0x10; } + ensure_memory_list_available(&grammar_lines_memlist, mark+5); grammar_lines[mark++] = bytecode; if (!glulx_mode) { grammar_lines[mark++] = wordcode/256; @@ -656,6 +860,7 @@ tokens in any line (unless you're compiling with library 6/3 or later)"); } while (TRUE); + ensure_memory_list_available(&grammar_lines_memlist, mark+1); grammar_lines[mark++] = 15; grammar_lines_top = mark; @@ -702,6 +907,7 @@ Library 6/3 or later"); debug_file_printf(""); } + ensure_memory_list_available(&grammar_lines_memlist, mark+3); if (!glulx_mode) { if (reverse_action) j = j + 0x400; @@ -731,8 +937,8 @@ extern void make_verb(void) int Inform_verb, meta_verb_flag=FALSE, verb_equals_form=FALSE; - char *English_verbs_given[MAX_VERB_SYNONYMS]; - int no_given = 0, i; + int no_given = 0, verbs_given_pos = 0; + int i, pos; directive_keywords.enabled = TRUE; @@ -745,11 +951,11 @@ extern void make_verb(void) while ((token_type == DQ_TT) || (token_type == SQ_TT)) { - 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; + int len = strlen(token_text) + 1; + ensure_memory_list_available(&English_verbs_given_memlist, verbs_given_pos + len); + strcpy(English_verbs_given+verbs_given_pos, token_text); + verbs_given_pos += len; + no_given++; get_next_token(); } @@ -768,16 +974,25 @@ extern void make_verb(void) ebf_error("';' after English verb", token_text); } else - { Inform_verb = no_Inform_verbs; - if (no_Inform_verbs == MAX_VERBS) - memoryerror("MAX_VERBS",MAX_VERBS); + { verb_equals_form = FALSE; + if (!glulx_mode && no_Inform_verbs >= 255) { + error("Z-code is limited to 255 verbs."); + panic_mode_error_recovery(); return; + } + ensure_memory_list_available(&Inform_verbs_memlist, no_Inform_verbs+1); + Inform_verb = no_Inform_verbs; + Inform_verbs[no_Inform_verbs].lines = 0; + Inform_verbs[no_Inform_verbs].size = 4; + Inform_verbs[no_Inform_verbs].l = my_malloc(sizeof(int) * Inform_verbs[no_Inform_verbs].size, "grammar lines for one verb"); } - for (i=0; i= 255) { + error("Z-code is limited to 255 verbs."); + panic_mode_error_recovery(); return; + } + ensure_memory_list_available(&Inform_verbs_memlist, no_Inform_verbs+1); + l = -1; while (get_next_token(), ((token_type == DQ_TT) || (token_type == SQ_TT))) { Inform_verb = get_verb(); @@ -836,8 +1055,15 @@ extern void extend_verb(void) /* Copy the old Inform-verb into a new one which the list of English-verbs given have had their dictionary entries modified to point to */ + /* (We are copying entry Inform_verb to no_Inform_verbs here.) */ - Inform_verbs[no_Inform_verbs] = Inform_verbs[Inform_verb]; + l = Inform_verbs[Inform_verb].lines; /* number of lines to copy */ + + Inform_verbs[no_Inform_verbs].lines = l; + Inform_verbs[no_Inform_verbs].size = l+4; + Inform_verbs[no_Inform_verbs].l = my_malloc(sizeof(int) * Inform_verbs[no_Inform_verbs].size, "grammar lines for one verb"); + for (k=0; k0; k--) Inform_verbs[Inform_verb].l[k+lines] = Inform_verbs[Inform_verb].l[k-1+lines]; + } } while (grammar_line(Inform_verb, lines++)); if (extend_mode == EXTEND_FIRST) - { Inform_verbs[Inform_verb].lines = l+lines-1; - for (k=0; k