extern void find_the_actions(void) { int i; int32 j; char action_sub[MAX_IDENTIFIER_LENGTH+4]; if (module_switch) for (i=0; i<no_actions; i++) action_byte_offset[i] = 0; else for (i=0; i<no_actions; i++) { strcpy(action_sub, (char *) symbs[action_symbol[i]]); strcpy(action_sub + strlen(action_sub) - 3, "Sub"); j = symbol_index(action_sub, -1); if (sflags[j] & UNKNOWN_SFLAG) error_named("There is no action routine called", action_sub); else if (stypes[j] != ROUTINE_T) error_named("Not an action routine:", action_sub); else { action_byte_offset[i] = svals[j]; sflags[j] |= USED_SFLAG; } } }
static int get_verb(void) { /* Look at the last-read token: if it's the name of an English verb understood by Inform, in double-quotes, then return the Inform-verb that word refers to: otherwise give an error and return -1. */ int j; if ((token_type == DQ_TT) || (token_type == SQ_TT)) { j = find_or_renumber_verb(token_text, NULL); if (j==-1) error_named("There is no previous grammar for the verb", token_text); return j; } ebf_error("an English verb in quotes", token_text); return -1; }
static void register_verb(char *English_verb, int number) { /* Registers a new English verb as referring to the given Inform-verb number. (See comments above for format of the list.) */ if (find_or_renumber_verb(English_verb, NULL) != -1) { error_named("Two different verb definitions refer to", English_verb); return; } English_verb_list_size += strlen(English_verb)+4; if (English_verb_list_size >= MAX_VERBSPACE) memoryerror("MAX_VERBSPACE", MAX_VERBSPACE); English_verb_list_top[0] = 4+strlen(English_verb); 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 += English_verb_list_top[0]; }
extern int32 parse_routine(char *source, int embedded_flag, char *name, int veneer_flag, int r_symbol) { int32 packed_address; int i; int debug_flag = FALSE; int switch_clause_made = FALSE, default_clause_made = FALSE, switch_label = 0; debug_location_beginning beginning_debug_location = get_token_location_beginning(); /* (switch_label needs no initialisation here, but it prevents some compilers from issuing warnings) */ if ((source != lexical_source) || (veneer_flag)) { lexical_source = source; restart_lexer(lexical_source, name); } no_locals = 0; for (i=0; i<MAX_LOCAL_VARIABLES-1; i++) local_variables.keywords[i] = ""; do { statements.enabled = TRUE; dont_enter_into_symbol_table = TRUE; get_next_token(); dont_enter_into_symbol_table = FALSE; if ((token_type == SEP_TT) && (token_value == TIMES_SEP) && (no_locals == 0) && (!debug_flag)) { debug_flag = TRUE; continue; } if (token_type != DQ_TT) { if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) break; ebf_error("local variable name or ';'", token_text); panic_mode_error_recovery(); break; } if (strlen(token_text) > MAX_IDENTIFIER_LENGTH) { error_named("Local variable identifier too long:", token_text); panic_mode_error_recovery(); break; } if (no_locals == MAX_LOCAL_VARIABLES-1) { error_numbered("Too many local variables for a routine; max is", MAX_LOCAL_VARIABLES-1); panic_mode_error_recovery(); break; } for (i=0; i<no_locals; i++) if (strcmpcis(token_text, local_variables.keywords[i])==0) error_named("Local variable defined twice:", token_text); local_variables.keywords[no_locals++] = token_text; } while(TRUE); construct_local_variable_tables(); if ((trace_fns_setting==3) || ((trace_fns_setting==2) && (veneer_mode==FALSE)) || ((trace_fns_setting==1) && (is_systemfile()==FALSE))) debug_flag = TRUE; if ((embedded_flag == FALSE) && (veneer_mode == FALSE) && debug_flag) sflags[r_symbol] |= STAR_SFLAG; packed_address = assemble_routine_header(no_locals, debug_flag, name, embedded_flag, r_symbol); do { begin_syntax_line(TRUE); get_next_token(); if (token_type == EOF_TT) { ebf_error("']'", token_text); assemble_routine_end (embedded_flag, get_token_location_end(beginning_debug_location)); put_token_back(); break; } if ((token_type == SEP_TT) && (token_value == CLOSE_SQUARE_SEP)) { if (switch_clause_made && (!default_clause_made)) assemble_label_no(switch_label); directives.enabled = TRUE; sequence_point_follows = TRUE; get_next_token(); assemble_routine_end (embedded_flag, get_token_location_end(beginning_debug_location)); put_token_back(); break; } if ((token_type == STATEMENT_TT) && (token_value == SDEFAULT_CODE)) { if (default_clause_made) error("Multiple 'default' clauses defined in same 'switch'"); default_clause_made = TRUE; if (switch_clause_made) { if (!execution_never_reaches_here) { sequence_point_follows = FALSE; if (!glulx_mode) assemblez_0((embedded_flag)?rfalse_zc:rtrue_zc); else assembleg_1(return_gc, ((embedded_flag)?zero_operand:one_operand)); } assemble_label_no(switch_label); } switch_clause_made = TRUE; get_next_token(); if ((token_type == SEP_TT) && (token_value == COLON_SEP)) continue; ebf_error("':' after 'default'", token_text); panic_mode_error_recovery(); continue; } /* Only check for the form of a case switch if the initial token isn't double-quoted text, as that would mean it was a print_ret statement: this is a mild ambiguity in the grammar. Action statements also cannot be cases. */ if ((token_type != DQ_TT) && (token_type != SEP_TT)) { get_next_token(); if (switch_sign() > 0) { assembly_operand AO; if (default_clause_made) error("'default' must be the last 'switch' case"); if (switch_clause_made) { if (!execution_never_reaches_here) { sequence_point_follows = FALSE; if (!glulx_mode) assemblez_0((embedded_flag)?rfalse_zc:rtrue_zc); else assembleg_1(return_gc, ((embedded_flag)?zero_operand:one_operand)); } assemble_label_no(switch_label); } switch_label = next_label++; switch_clause_made = TRUE; put_token_back(); put_token_back(); if (!glulx_mode) { INITAOTV(&AO, VARIABLE_OT, 249); } else { INITAOTV(&AO, GLOBALVAR_OT, MAX_LOCAL_VARIABLES+6); /* sw__var */ } parse_switch_spec(AO, switch_label, TRUE); continue; } else { put_token_back(); put_token_back(); get_next_token(); sequence_point_follows = TRUE; } } parse_statement(-1, -1); } while (TRUE); return packed_address; }