/* ------------------------------------------------------------------------- */
/* "expressp" : The expression parser */
/* */
-/* Part of Inform 6.35 */
-/* copyright (c) Graham Nelson 1993 - 2021 */
+/* Part of Inform 6.42 */
+/* copyright (c) Graham Nelson 1993 - 2024 */
/* */
/* Inform is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
array_init_ambiguity, action_ambiguity,
etoken_count, inserting_token, bracket_level;
-extern int *variable_usage;
+int system_function_usage[NUMBER_SYSTEM_FUNCTIONS];
-int system_function_usage[32];
+static void check_system_constant_available(int);
static int get_next_etoken(void)
{ int v, symbol = 0, mark_symbol_as_used = FALSE,
current_token.value = token_value;
current_token.type = token_type;
current_token.marker = 0;
+ current_token.symindex = -1;
current_token.symtype = 0;
current_token.symflags = -1;
}
switch(current_token.type)
{ case LOCAL_VARIABLE_TT:
current_token.type = VARIABLE_TT;
- variable_usage[current_token.value] = TRUE;
+ variables[current_token.value].usage = TRUE;
break;
case DQ_TT:
mark_symbol_as_used = TRUE;
- v = svals[symbol];
+ v = symbols[symbol].value;
- current_token.symtype = stypes[symbol];
- current_token.symflags = sflags[symbol];
- switch(stypes[symbol])
+ current_token.symindex = symbol;
+ current_token.symtype = symbols[symbol].type;
+ current_token.symflags = symbols[symbol].flags;
+ switch(symbols[symbol].type)
{ case ROUTINE_T:
/* Replaced functions must always be backpatched
because there could be another definition coming. */
- if (sflags[symbol] & REPLACE_SFLAG)
+ if (symbols[symbol].flags & REPLACE_SFLAG)
{ current_token.marker = SYMBOL_MV;
- if (module_switch) import_symbol(symbol);
v = symbol;
break;
}
case OBJECT_T:
case CLASS_T:
/* All objects must be backpatched in Glulx. */
- if (module_switch || glulx_mode)
+ if (glulx_mode)
current_token.marker = OBJECT_MV;
break;
case ARRAY_T:
current_token.marker = STATIC_ARRAY_MV;
break;
case INDIVIDUAL_PROPERTY_T:
- if (module_switch) current_token.marker = IDENT_MV;
break;
case CONSTANT_T:
- if (sflags[symbol] & (UNKNOWN_SFLAG + CHANGE_SFLAG))
+ if (symbols[symbol].flags & (UNKNOWN_SFLAG + CHANGE_SFLAG))
{ current_token.marker = SYMBOL_MV;
- if (module_switch) import_symbol(symbol);
v = symbol;
}
else current_token.marker = 0;
current_token.marker = 0;
break;
}
- if (sflags[symbol] & SYSTEM_SFLAG)
+ if (symbols[symbol].flags & SYSTEM_SFLAG)
current_token.marker = 0;
current_token.value = v;
else current_token.type = SMALL_NUMBER_TT;
}
- if (stypes[symbol] == GLOBAL_VARIABLE_T)
+ if (symbols[symbol].type == GLOBAL_VARIABLE_T)
{ current_token.type = VARIABLE_TT;
- variable_usage[current_token.value] = TRUE;
+ variables[current_token.value].usage = TRUE;
}
break;
current_token.text += 3;
current_token.type = SYMBOL_TT;
- symbol = symbol_index(current_token.text, -1);
- if (stypes[symbol] != GLOBAL_VARIABLE_T) {
+ symbol = get_symbol_index(current_token.text);
+ if (symbol < 0 || symbols[symbol].type != GLOBAL_VARIABLE_T) {
ebf_error(
"global variable name after '#g$'",
current_token.text);
break;
}
mark_symbol_as_used = TRUE;
- current_token.value = svals[symbol] - MAX_LOCAL_VARIABLES;
+ current_token.value = symbols[symbol].value - MAX_LOCAL_VARIABLES;
current_token.marker = 0;
if (!glulx_mode) {
if (current_token.value >= 0x100)
"'#r$Routine' can now be written just 'Routine'");
current_token.text += 3;
current_token.type = SYMBOL_TT;
- current_token.value = symbol_index(current_token.text, -1);
+ current_token.value = symbol_index(current_token.text, -1, NULL);
goto ReceiveSymbol;
case HASHWDOLLAR_SEP:
get_next_token();
system_constants.enabled = FALSE;
if (token_type != SYSTEM_CONSTANT_TT)
- { ebf_error(
- "'r$', 'n$', 'g$' or internal Inform constant name after '#'",
- token_text);
+ { ebf_curtoken_error(
+ "'r$', 'n$', 'g$' or internal Inform constant name after '#'");
break;
}
else
- { current_token.type = token_type;
+ {
+ check_system_constant_available(token_value);
+ current_token.type = token_type;
current_token.value = token_value;
current_token.text = token_text;
current_token.marker = INCON_MV;
if (token_type_allowable[current_token.type]==0)
{ if (expr_trace_level >= 3)
{ printf("Discarding as not allowable: '%s' ", current_token.text);
- describe_token(current_token);
+ describe_token(¤t_token);
printf("\n");
}
current_token.type = ENDEXP_TT;
|| (operators[current_token.value].usage == PRE_U)))
{ if (expr_trace_level >= 3)
{ printf("Discarding as no longer part: '%s' ", current_token.text);
- describe_token(current_token);
+ describe_token(¤t_token);
printf("\n");
}
current_token.type = ENDEXP_TT;
}
else
- { if (mark_symbol_as_used) sflags[symbol] |= USED_SFLAG;
+ { if (mark_symbol_as_used) symbols[symbol].flags |= USED_SFLAG;
if (expr_trace_level >= 3)
{ printf("Expr token = '%s' ", current_token.text);
- describe_token(current_token);
+ describe_token(¤t_token);
printf("\n");
}
}
return TRUE;
}
-/* --- Operator precedences ------------------------------------------------ */
+/* --- Operator precedences and error values-------------------------------- */
#define LOWER_P 101
#define EQUAL_P 102
#define GREATER_P 103
-#define e1 1 /* Missing operand error */
-#define e2 2 /* Unexpected close bracket */
-#define e3 3 /* Missing operator error */
-#define e4 4 /* Expression ends with an open bracket */
-#define e5 5 /* Associativity illegal error */
+#define BYPREC -1 /* Compare the precedence of two operators */
-const int prec_table[] = {
+#define NOVAL_E 1 /* Missing operand error */
+#define CLOSEB_E 2 /* Unexpected close bracket */
+#define NOOP_E 3 /* Missing operator error */
+#define OPENB_E 4 /* Expression ends with an open bracket */
+#define ASSOC_E 5 /* Associativity illegal error */
-/* a .......... ( ) end op term */
+const int prec_table[49] = {
-/* b ( */ LOWER_P, e3, LOWER_P, LOWER_P, e3,
-/* . ) */ EQUAL_P, GREATER_P, e2, GREATER_P, GREATER_P,
-/* . end */ e4, GREATER_P, e1, GREATER_P, GREATER_P,
-/* . op */ LOWER_P, GREATER_P, LOWER_P, -1, GREATER_P,
-/* . term */ LOWER_P, e3, LOWER_P, LOWER_P, e3
+/* a ....... ( ) end op:pre op:bin op:post term */
+
+/* b ( */ LOWER_P, NOOP_E, LOWER_P, LOWER_P, LOWER_P, NOOP_E, NOOP_E,
+/* . ) */ EQUAL_P, GREATER_P, CLOSEB_E, GREATER_P, GREATER_P, GREATER_P, GREATER_P,
+/* . end */ OPENB_E, GREATER_P, NOVAL_E, GREATER_P, GREATER_P, GREATER_P, GREATER_P,
+/* . op:pre */ LOWER_P, NOOP_E, LOWER_P, BYPREC, BYPREC, NOOP_E, NOOP_E,
+/* . op:bin */ LOWER_P, GREATER_P, LOWER_P, BYPREC, BYPREC, BYPREC, GREATER_P,
+/* . op:post */ LOWER_P, GREATER_P, LOWER_P, BYPREC, BYPREC, BYPREC, GREATER_P,
+/* . term */ LOWER_P, NOOP_E, LOWER_P, LOWER_P, LOWER_P, NOOP_E, NOOP_E
};
-static int find_prec(token_data a, token_data b)
+static int find_prec(const token_data *a, const token_data *b)
{
/* We are comparing the precedence of tokens a and b
(where a occurs to the left of b). If the expression is correct,
the only possible values are GREATER_P, LOWER_P or EQUAL_P;
- if it is malformed then one of e1 to e5 results.
+ if it is malformed then one of the *_E results.
Note that this routine is not symmetrical and that the relation
is not trichotomous.
a GREATER_P a if a left-associative
*/
- int i, j, l1, l2;
+ int ai, bi, j, l1, l2;
- switch(a.type)
- { case SUBOPEN_TT: i=0; break;
- case SUBCLOSE_TT: i=1; break;
- case ENDEXP_TT: i=2; break;
- case OP_TT: i=3; break;
- default: i=4; break;
+ /* Select a column and row in prec_table, based on the type of
+ a and b. If a/b is an operator, we have to distinguish three
+ columns/rows depending on whether the operator is prefix,
+ postfix, or neither.
+ */
+
+ switch(a->type)
+ { case SUBOPEN_TT: ai=0; break;
+ case SUBCLOSE_TT: ai=1; break;
+ case ENDEXP_TT: ai=2; break;
+ case OP_TT:
+ if (operators[a->value].usage == PRE_U)
+ ai=3;
+ else if (operators[a->value].usage == POST_U)
+ ai=5;
+ else
+ ai=4;
+ break;
+ default: ai=6; break;
}
- switch(b.type)
- { case SUBOPEN_TT: i+=0; break;
- case SUBCLOSE_TT: i+=5; break;
- case ENDEXP_TT: i+=10; break;
- case OP_TT: i+=15; break;
- default: i+=20; break;
+ switch(b->type)
+ { case SUBOPEN_TT: bi=0; break;
+ case SUBCLOSE_TT: bi=1; break;
+ case ENDEXP_TT: bi=2; break;
+ case OP_TT:
+ if (operators[b->value].usage == PRE_U)
+ bi=3;
+ else if (operators[b->value].usage == POST_U)
+ bi=5;
+ else
+ bi=4;
+ break;
+ default: bi=6; break;
}
+
+ j = prec_table[ai+7*bi];
+ if (j != BYPREC) return j;
- j = prec_table[i]; if (j != -1) return j;
-
- l1 = operators[a.value].precedence;
- l2 = operators[b.value].precedence;
- if (operators[b.value].usage == PRE_U) return LOWER_P;
- if (operators[a.value].usage == POST_U) return GREATER_P;
+ /* BYPREC is the (a=OP, b=OP) cases. We must compare the precedence of the
+ two operators.
+ (We've already eliminated invalid cases like (a++ --b).)
+ */
+ l1 = operators[a->value].precedence;
+ l2 = operators[b->value].precedence;
+ if (operators[b->value].usage == PRE_U) return LOWER_P;
+ if (operators[a->value].usage == POST_U) return GREATER_P;
/* Anomalous rule to resolve the function call precedence, which is
different on the right from on the left, e.g., in:
if (l1 < l2) return LOWER_P;
if (l1 > l2) return GREATER_P;
- switch(operators[a.value].associativity)
+ switch(operators[a->value].associativity)
{ case L_A: return GREATER_P;
case R_A: return LOWER_P;
- case 0: return e5;
+ case 0: return ASSOC_E;
}
return GREATER_P;
}
/* --- Converting token to operand ----------------------------------------- */
-/* Must match the switch statement below */
+/* List used to generate gameinfo.dbg.
+ Must match the switch statement below. */
int z_system_constant_list[] =
{ adjectives_table_SC,
actions_table_SC,
highest_class_number_SC,
class_objects_array_SC,
highest_object_number_SC,
+ dictionary_table_SC,
+ grammar_table_SC,
-1 };
+static void check_system_constant_available(int t)
+{
+ if (OMIT_SYMBOL_TABLE) {
+ /* Certain system constants refer to the symbol table, which
+ is meaningless if OMIT_SYMBOL_TABLE is set. */
+ switch(t)
+ {
+ case identifiers_table_SC:
+ case attribute_names_array_SC:
+ case property_names_array_SC:
+ case action_names_array_SC:
+ case fake_action_names_array_SC:
+ case array_names_offset_SC:
+ case global_names_array_SC:
+ case routine_names_array_SC:
+ case constant_names_array_SC:
+ error_named("OMIT_SYMBOL_TABLE omits system constant", system_constants.keywords[t]);
+ default:
+ break;
+ }
+ }
+}
+
static int32 value_of_system_constant_z(int t)
-{ switch(t)
+{
+ switch(t)
{ case adjectives_table_SC:
return adjectives_offset;
case actions_table_SC:
case ipv__end_SC:
return variables_offset;
case array__start_SC:
- return variables_offset + (MAX_GLOBAL_VARIABLES*WORDSIZE);
+ return variables_offset + (MAX_ZCODE_GLOBAL_VARS*WORDSIZE);
case array__end_SC:
return static_memory_offset;
+ case dictionary_table_SC:
+ return dictionary_offset;
+ case grammar_table_SC:
+ return static_memory_offset;
case highest_attribute_number_SC:
return no_attributes-1;
return(0);
}
-/* Must match the switch statement below */
+/* List used to generate gameinfo.dbg.
+ Must match the switch statement below. */
int glulx_system_constant_list[] =
{ classes_table_SC,
identifiers_table_SC,
return value_of_system_constant_g(t);
}
-static int evaluate_term(token_data t, assembly_operand *o)
+extern char *name_of_system_constant(int t)
+{
+ if (t < 0 || t >= NO_SYSTEM_CONSTANTS) {
+ return "???";
+ }
+ return system_constants.keywords[t];
+}
+
+static int evaluate_term(const token_data *t, assembly_operand *o)
{
/* If the given token is a constant, evaluate it into the operand.
For now, the identifiers are considered variables.
int32 v;
- o->marker = t.marker;
- o->symtype = t.symtype;
- o->symflags = t.symflags;
+ o->marker = t->marker;
+ o->symindex = t->symindex;
- switch(t.type)
+ switch(t->type)
{ case LARGE_NUMBER_TT:
- v = t.value;
+ v = t->value;
if (!glulx_mode) {
if (v < 0) v = v + 0x10000;
o->type = LONG_CONSTANT_OT;
}
return(TRUE);
case SMALL_NUMBER_TT:
- v = t.value;
+ v = t->value;
if (!glulx_mode) {
if (v < 0) v = v + 0x10000;
o->type = SHORT_CONSTANT_OT;
o->type = LONG_CONSTANT_OT;
else
o->type = CONSTANT_OT;
- o->value = dictionary_add(t.text, 0x80, 0, 0);
+ o->value = dictionary_add(t->text, 0x80, 0, 0);
return(TRUE);
case DQ_TT:
/* Create as a static string */
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) {
o->type = VARIABLE_OT;
}
else {
- if (t.value >= MAX_LOCAL_VARIABLES) {
+ if (t->value >= MAX_LOCAL_VARIABLES) {
o->type = GLOBALVAR_OT;
}
else {
o->type = LOCALVAR_OT;
}
}
- o->value = t.value;
+ o->value = t->value;
return(TRUE);
case SYSFUN_TT:
if (!glulx_mode) {
o->type = VARIABLE_OT;
- o->value = t.value + 256;
+ o->value = t->value + 256;
}
else {
o->type = SYSFUN_OT;
- o->value = t.value;
+ o->value = t->value;
}
- system_function_usage[t.value] = 1;
+ system_function_usage[t->value] = 1;
return(TRUE);
case ACTION_TT:
- *o = action_of_name(t.text);
+ *o = action_of_name(t->text);
return(TRUE);
case SYSTEM_CONSTANT_TT:
/* Certain system constants depend only on the
them immediately. */
if (!glulx_mode) {
o->type = LONG_CONSTANT_OT;
- switch(t.value)
+ switch(t->value)
{
case version_number_SC:
o->type = SHORT_CONSTANT_OT;
case dict_par3_SC:
o->type = SHORT_CONSTANT_OT;
o->marker = 0;
+ if (ZCODE_LESS_DICT_DATA)
+ error("#dict_par3 is unavailable when ZCODE_LESS_DICT_DATA is set");
v = (version_number==3)?6:8; break;
case lowest_attribute_number_SC:
case lowest_action_number_SC:
o->type = SHORT_CONSTANT_OT; o->marker = 0;
v = oddeven_packing_switch; break;
default:
- v = t.value;
+ v = t->value;
o->marker = INCON_MV;
break;
}
}
else {
o->type = CONSTANT_OT;
- switch(t.value)
+ switch(t->value)
{
/* The three dict_par flags point at the lower byte
of the flag field, because the library is written
/* ###fix: need to fill more of these in! */
default:
- v = t.value;
+ v = t->value;
o->marker = INCON_MV;
break;
}
/* --- Emitter ------------------------------------------------------------- */
-expression_tree_node *ET;
+expression_tree_node *ET; /* Allocated to ET_used */
+static memory_list ET_memlist;
static int ET_used;
extern void clear_expression_space(void)
{ ET_used = 0;
}
-static assembly_operand *emitter_stack;
-static int *emitter_markers;
-static int *emitter_bracket_counts;
+typedef struct emitterstackinfo_s {
+ assembly_operand op;
+ int marker;
+ int bracket_count;
+} emitterstackinfo;
#define FUNCTION_VALUE_MARKER 1
#define ARGUMENT_VALUE_MARKER 2
#define OR_VALUE_MARKER 3
+static emitterstackinfo *emitter_stack; /* Allocated to emitter_sp */
+static memory_list emitter_stack_memlist;
static int emitter_sp;
static int is_property_t(int symbol_type)
{ return ((symbol_type == PROPERTY_T) || (symbol_type == INDIVIDUAL_PROPERTY_T));
}
-static void mark_top_of_emitter_stack(int marker, token_data t)
+static void mark_top_of_emitter_stack(int marker, const token_data *t)
{ if (emitter_sp < 1)
{ compiler_error("SR error: Attempt to add a marker to the top of an empty emitter stack");
return;
}
if (expr_trace_level >= 2)
{ printf("Marking top of emitter stack (which is ");
- print_operand(emitter_stack[emitter_sp-1]);
+ print_operand(&emitter_stack[emitter_sp-1].op, FALSE);
printf(") as ");
switch(marker)
{
}
printf("\n");
}
- if (emitter_markers[emitter_sp-1])
+ if (emitter_stack[emitter_sp-1].marker)
{ if (marker == ARGUMENT_VALUE_MARKER)
{
warning("Ignoring spurious leading comma");
return;
}
- error_named("Missing operand for", t.text);
- if (emitter_sp == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
- emitter_markers[emitter_sp] = 0;
- emitter_bracket_counts[emitter_sp] = 0;
- emitter_stack[emitter_sp] = zero_operand;
+ error_named("Missing operand for", t->text);
+ ensure_memory_list_available(&emitter_stack_memlist, emitter_sp+1);
+ emitter_stack[emitter_sp].marker = 0;
+ emitter_stack[emitter_sp].bracket_count = 0;
+ emitter_stack[emitter_sp].op = zero_operand;
emitter_sp++;
}
- emitter_markers[emitter_sp-1] = marker;
+ emitter_stack[emitter_sp-1].marker = marker;
}
static void add_bracket_layer_to_emitter_stack(int depth)
{ /* There's no point in tracking bracket layers that don't fence off any values. */
if (emitter_sp < depth + 1) return;
if (expr_trace_level >= 2)
- printf("Adding bracket layer\n");
- ++emitter_bracket_counts[emitter_sp-depth-1];
+ printf("Adding bracket layer (depth %d)\n", depth);
+ ++emitter_stack[emitter_sp-depth-1].bracket_count;
}
static void remove_bracket_layer_from_emitter_stack()
if (emitter_sp < 2) return;
if (expr_trace_level >= 2)
printf("Removing bracket layer\n");
- if (emitter_bracket_counts[emitter_sp-2] <= 0)
+ if (emitter_stack[emitter_sp-2].bracket_count <= 0)
{ compiler_error("SR error: Attempt to remove a nonexistent bracket layer from the emitter stack");
return;
}
- --emitter_bracket_counts[emitter_sp-2];
+ --emitter_stack[emitter_sp-2].bracket_count;
}
-static void emit_token(token_data t)
+static void emit_token(const token_data *t)
{ assembly_operand o1, o2; int arity, stack_size, i;
int op_node_number, operand_node_number, previous_node_number;
int32 x = 0;
if (expr_trace_level >= 2)
- { printf("Output: %-19s%21s ", t.text, "");
+ { printf("Output: %-19s%21s ", t->text, "");
for (i=0; i<emitter_sp; i++)
- { print_operand(emitter_stack[i]); printf(" ");
- if (emitter_markers[i] == FUNCTION_VALUE_MARKER) printf(":FUNCTION ");
- if (emitter_markers[i] == ARGUMENT_VALUE_MARKER) printf(":ARGUMENT ");
- if (emitter_markers[i] == OR_VALUE_MARKER) printf(":OR ");
- if (emitter_bracket_counts[i]) printf(":BRACKETS(%d) ", emitter_bracket_counts[i]);
+ { print_operand(&emitter_stack[i].op, FALSE); printf(" ");
+ if (emitter_stack[i].marker == FUNCTION_VALUE_MARKER) printf(":FUNCTION ");
+ if (emitter_stack[i].marker == ARGUMENT_VALUE_MARKER) printf(":ARGUMENT ");
+ if (emitter_stack[i].marker == OR_VALUE_MARKER) printf(":OR ");
+ if (emitter_stack[i].bracket_count) printf(":BRACKETS(%d) ", emitter_stack[i].bracket_count);
}
printf("\n");
}
- if (t.type == SUBOPEN_TT) return;
+ if (t->type == SUBOPEN_TT) return;
stack_size = 0;
while ((stack_size < emitter_sp) &&
- !emitter_markers[emitter_sp-stack_size-1] &&
- !emitter_bracket_counts[emitter_sp-stack_size-1])
+ !emitter_stack[emitter_sp-stack_size-1].marker &&
+ !emitter_stack[emitter_sp-stack_size-1].bracket_count)
stack_size++;
- if (t.type == SUBCLOSE_TT)
- { if (stack_size < emitter_sp && emitter_bracket_counts[emitter_sp-stack_size-1])
+ if (t->type == SUBCLOSE_TT)
+ { if (stack_size < emitter_sp && emitter_stack[emitter_sp-stack_size-1].bracket_count)
{ if (stack_size == 0)
{ error("No expression between brackets '(' and ')'");
- emitter_stack[emitter_sp] = zero_operand;
- emitter_markers[emitter_sp] = 0;
- emitter_bracket_counts[emitter_sp] = 0;
- ++emitter_sp;
+ ensure_memory_list_available(&emitter_stack_memlist, emitter_sp+1);
+ emitter_stack[emitter_sp].op = zero_operand;
+ emitter_stack[emitter_sp].marker = 0;
+ emitter_stack[emitter_sp].bracket_count = 0;
+ emitter_sp++;
}
else if (stack_size < 1)
compiler_error("SR error: emitter stack empty in subexpression");
return;
}
- if (t.type != OP_TT)
- { emitter_markers[emitter_sp] = 0;
- emitter_bracket_counts[emitter_sp] = 0;
+ if (t->type != OP_TT)
+ {
+ ensure_memory_list_available(&emitter_stack_memlist, emitter_sp+1);
+ emitter_stack[emitter_sp].marker = 0;
+ emitter_stack[emitter_sp].bracket_count = 0;
- if (emitter_sp == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
- if (!evaluate_term(t, &(emitter_stack[emitter_sp++])))
- compiler_error_named("Emit token error:", t.text);
+ if (!evaluate_term(t, &(emitter_stack[emitter_sp++].op)))
+ compiler_error_named("Emit token error:", t->text);
return;
}
call, since we ignore spurious leading commas in function argument lists)
with no intervening brackets. Function calls are variadic, so we don't
apply argument-separating commas. */
- if (t.value == COMMA_OP &&
+ if (t->value == COMMA_OP &&
stack_size < emitter_sp &&
- (emitter_markers[emitter_sp-stack_size-1] == ARGUMENT_VALUE_MARKER ||
- emitter_markers[emitter_sp-stack_size-1] == FUNCTION_VALUE_MARKER) &&
- !emitter_bracket_counts[emitter_sp-stack_size-1])
+ (emitter_stack[emitter_sp-stack_size-1].marker == ARGUMENT_VALUE_MARKER ||
+ emitter_stack[emitter_sp-stack_size-1].marker == FUNCTION_VALUE_MARKER) &&
+ !emitter_stack[emitter_sp-stack_size-1].bracket_count)
{ if (expr_trace_level >= 2)
printf("Treating comma as argument-separating\n");
return;
}
- if (t.value == OR_OP)
+ if (t->value == OR_OP)
return;
arity = 1;
- if (t.value == FCALL_OP)
+ if (t->value == FCALL_OP)
{ if (expr_trace_level >= 3)
{ printf("FCALL_OP finds marker stack: ");
- for (x=0; x<emitter_sp; x++) printf("%d ", emitter_markers[x]);
+ for (x=0; x<emitter_sp; x++) printf("%d ", emitter_stack[x].marker);
printf("\n");
}
- if (emitter_markers[emitter_sp-1] == ARGUMENT_VALUE_MARKER)
+ if (emitter_stack[emitter_sp-1].marker == ARGUMENT_VALUE_MARKER)
warning("Ignoring spurious trailing comma");
- while (emitter_markers[emitter_sp-arity] != FUNCTION_VALUE_MARKER)
+ while (emitter_stack[emitter_sp-arity].marker != FUNCTION_VALUE_MARKER)
{
if ((glulx_mode &&
- emitter_stack[emitter_sp-arity].type == SYSFUN_OT) ||
+ emitter_stack[emitter_sp-arity].op.type == SYSFUN_OT) ||
(!glulx_mode &&
- emitter_stack[emitter_sp-arity].type == VARIABLE_OT &&
- emitter_stack[emitter_sp-arity].value >= 256 &&
- emitter_stack[emitter_sp-arity].value < 288))
- { int index = emitter_stack[emitter_sp-arity].value;
+ emitter_stack[emitter_sp-arity].op.type == VARIABLE_OT &&
+ emitter_stack[emitter_sp-arity].op.value >= 256 &&
+ emitter_stack[emitter_sp-arity].op.value < 288))
+ { int index = emitter_stack[emitter_sp-arity].op.value;
if(!glulx_mode)
index -= 256;
if(index >= 0 && index < NUMBER_SYSTEM_FUNCTIONS)
error_named("System function name used as a value:", system_functions.keywords[index]);
else
compiler_error("Found unnamed system function used as a value");
- emitter_stack[emitter_sp-arity] = zero_operand;
+ emitter_stack[emitter_sp-arity].op = zero_operand;
}
++arity;
}
}
else
{ arity = 1;
- if (operators[t.value].usage == IN_U) arity = 2;
+ if (operators[t->value].usage == IN_U) arity = 2;
- if (operators[t.value].precedence == 3)
+ if (operators[t->value].precedence == 3)
{ arity = 2;
x = emitter_sp-1;
- if(!emitter_markers[x] && !emitter_bracket_counts[x])
- { for (--x; emitter_markers[x] == OR_VALUE_MARKER && !emitter_bracket_counts[x]; --x)
+ if(!emitter_stack[x].marker && !emitter_stack[x].bracket_count)
+ { for (--x; emitter_stack[x].marker == OR_VALUE_MARKER && !emitter_stack[x].bracket_count; --x)
{ ++arity;
++stack_size;
}
- for (;x >= 0 && !emitter_markers[x] && !emitter_bracket_counts[x]; --x)
+ for (;x >= 0 && !emitter_stack[x].marker && !emitter_stack[x].bracket_count; --x)
++stack_size;
}
}
if (arity > stack_size)
- { error_named("Missing operand for", t.text);
+ { error_named("Missing operand for", t->text);
while (arity > stack_size)
- { if (emitter_sp == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
- emitter_markers[emitter_sp] = 0;
- emitter_bracket_counts[emitter_sp] = 0;
- emitter_stack[emitter_sp] = zero_operand;
+ { ensure_memory_list_available(&emitter_stack_memlist, emitter_sp+1);
+ emitter_stack[emitter_sp].marker = 0;
+ emitter_stack[emitter_sp].bracket_count = 0;
+ emitter_stack[emitter_sp].op = zero_operand;
emitter_sp++;
stack_size++;
}
}
}
- /* pseudo-typecheck in 6.30 */
+ /* pseudo-typecheck in 6.30: catch an unqualified property name */
for (i = 1; i <= arity; i++)
{
- o1 = emitter_stack[emitter_sp - i];
- if (is_property_t(o1.symtype) ) {
- switch(t.value)
+ o1 = emitter_stack[emitter_sp - i].op;
+ if ((o1.symindex >= 0)
+ && is_property_t(symbols[o1.symindex].type)) {
+ switch(t->value)
{
case FCALL_OP:
case SETEQUALS_OP: case NOTEQUAL_OP:
case PROPERTY_OP:
if (i < arity) break;
case GE_OP: case LE_OP:
- if ((i < arity) && (o1.symflags & STAR_SFLAG)) break;
+ /* Direction properties "n_to", etc *are* compared
+ in some libraries. They have STAR_SFLAG to tell us
+ to skip the warning. */
+ if ((i < arity)
+ && (symbols[o1.symindex].flags & STAR_SFLAG)) break;
default:
warning("Property name in expression is not qualified by object");
}
- } /* if (is_property_t */
+ }
}
switch(arity)
{ case 1:
- o1 = emitter_stack[emitter_sp - 1];
+ o1 = emitter_stack[emitter_sp - 1].op;
if ((o1.marker == 0) && is_constant_ot(o1.type))
- { switch(t.value)
- { case UNARY_MINUS_OP: x = -o1.value; goto FoldConstant;
+ { switch(t->value)
+ { case UNARY_MINUS_OP:
+ if ((uint32)o1.value == 0x80000000)
+ x = 0x80000000;
+ else
+ x = -o1.value;
+ goto FoldConstant;
case ARTNOT_OP:
if (!glulx_mode)
x = (~o1.value) & 0xffff;
break;
case 2:
- o1 = emitter_stack[emitter_sp - 2];
- o2 = emitter_stack[emitter_sp - 1];
+ o1 = emitter_stack[emitter_sp - 2].op;
+ o2 = emitter_stack[emitter_sp - 1].op;
if ((o1.marker == 0) && (o2.marker == 0)
&& is_constant_ot(o1.type) && is_constant_ot(o2.type))
ov2 = (o2.value >= 0x8000) ? (o2.value - 0x10000) : o2.value;
}
- switch(t.value)
+ switch(t->value)
{
case PLUS_OP: x = ov1 + ov2; goto FoldConstantC;
case MINUS_OP: x = ov1 - ov2; goto FoldConstantC;
if (ov2 == 0)
error("Division of constant by zero");
else
- if (t.value == DIVIDE_OP) {
+ if (t->value == DIVIDE_OP) {
if (ov2 < 0) {
ov1 = -ov1;
ov2 = -ov2;
}
}
+
+ /* We can also fold logical operations if they are certain
+ to short-circuit. The right-hand argument is skipped even
+ if it's non-constant or has side effects. */
+
+ if ((o1.marker == 0)
+ && is_constant_ot(o1.type)) {
+
+ if (t->value == LOGAND_OP && o1.value == 0)
+ {
+ x = 0;
+ goto FoldConstant;
+ }
+
+ if (t->value == LOGOR_OP && o1.value != 0)
+ {
+ x = 1;
+ goto FoldConstant;
+ }
+ }
}
+ ensure_memory_list_available(&ET_memlist, ET_used+1);
op_node_number = ET_used++;
- if (op_node_number == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
- ET[op_node_number].operator_number = t.value;
+ ET[op_node_number].operator_number = t->value;
ET[op_node_number].up = -1;
ET[op_node_number].down = -1;
ET[op_node_number].right = -1;
if (expr_trace_level >= 3)
printf("i=%d, emitter_sp=%d, arity=%d, ETU=%d\n",
i, emitter_sp, arity, ET_used);
- if (emitter_stack[i].type == EXPRESSION_OT)
- operand_node_number = emitter_stack[i].value;
+ if (emitter_stack[i].op.type == EXPRESSION_OT)
+ operand_node_number = emitter_stack[i].op.value;
else
- { operand_node_number = ET_used++;
- if (operand_node_number == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
+ {
+ ensure_memory_list_available(&ET_memlist, ET_used+1);
+ operand_node_number = ET_used++;
ET[operand_node_number].down = -1;
- ET[operand_node_number].value = emitter_stack[i];
+ ET[operand_node_number].value = emitter_stack[i].op;
}
ET[operand_node_number].up = op_node_number;
ET[operand_node_number].right = -1;
emitter_sp = emitter_sp - arity + 1;
- emitter_stack[emitter_sp - 1].type = EXPRESSION_OT;
- emitter_stack[emitter_sp - 1].value = op_node_number;
+ emitter_stack[emitter_sp - 1].op.type = EXPRESSION_OT;
+ emitter_stack[emitter_sp - 1].op.value = op_node_number;
+ emitter_stack[emitter_sp - 1].op.marker = 0;
emitter_stack[emitter_sp - 1].marker = 0;
- emitter_markers[emitter_sp - 1] = 0;
- emitter_bracket_counts[emitter_sp - 1] = 0;
+ emitter_stack[emitter_sp - 1].bracket_count = 0;
/* Remove the marker for the brackets implied by operator precedence */
remove_bracket_layer_from_emitter_stack();
for 32-bit arithmetic. */
if (!glulx_mode && ((x<-32768) || (x > 32767)))
- { char folding_error[40];
+ {
int32 ov1 = (o1.value >= 0x8000) ? (o1.value - 0x10000) : o1.value;
int32 ov2 = (o2.value >= 0x8000) ? (o2.value - 0x10000) : o2.value;
- switch(t.value)
+ char op = '?';
+ switch(t->value)
{
case PLUS_OP:
- sprintf(folding_error, "%d + %d = %d", ov1, ov2, x);
+ op = '+';
break;
case MINUS_OP:
- sprintf(folding_error, "%d - %d = %d", ov1, ov2, x);
+ op = '-';
break;
case TIMES_OP:
- sprintf(folding_error, "%d * %d = %d", ov1, ov2, x);
+ op = '*';
break;
}
- error_named("Signed arithmetic on compile-time constants overflowed \
-the range -32768 to +32767:", folding_error);
+ error_fmt("Signed arithmetic on compile-time constants overflowed \
+the range -32768 to +32767 (%d %c %d = %d)", ov1, op, ov2, x);
}
FoldConstant:
if (!glulx_mode) {
if (x<256)
- emitter_stack[emitter_sp - 1].type = SHORT_CONSTANT_OT;
- else emitter_stack[emitter_sp - 1].type = LONG_CONSTANT_OT;
+ emitter_stack[emitter_sp - 1].op.type = SHORT_CONSTANT_OT;
+ else emitter_stack[emitter_sp - 1].op.type = LONG_CONSTANT_OT;
}
else {
if (x == 0)
- emitter_stack[emitter_sp - 1].type = ZEROCONSTANT_OT;
+ emitter_stack[emitter_sp - 1].op.type = ZEROCONSTANT_OT;
else if (x >= -128 && x <= 127)
- emitter_stack[emitter_sp - 1].type = BYTECONSTANT_OT;
+ emitter_stack[emitter_sp - 1].op.type = BYTECONSTANT_OT;
else if (x >= -32768 && x <= 32767)
- emitter_stack[emitter_sp - 1].type = HALFCONSTANT_OT;
+ emitter_stack[emitter_sp - 1].op.type = HALFCONSTANT_OT;
else
- emitter_stack[emitter_sp - 1].type = CONSTANT_OT;
+ emitter_stack[emitter_sp - 1].op.type = CONSTANT_OT;
}
- emitter_stack[emitter_sp - 1].value = x;
+ emitter_stack[emitter_sp - 1].op.value = x;
+ emitter_stack[emitter_sp - 1].op.marker = 0;
emitter_stack[emitter_sp - 1].marker = 0;
- emitter_markers[emitter_sp - 1] = 0;
- emitter_bracket_counts[emitter_sp - 1] = 0;
+ emitter_stack[emitter_sp - 1].bracket_count = 0;
if (expr_trace_level >= 2)
{ printf("Folding constant to: ");
- print_operand(emitter_stack[emitter_sp - 1]);
+ print_operand(&emitter_stack[emitter_sp - 1].op, FALSE);
printf("\n");
}
for (j=0; j<2*depth+2; j++) printf(" ");
if (ET[n].down == -1)
- { print_operand(ET[n].value);
- if (annotate && (ET[n].value.marker != 0))
- printf(" [%s]", describe_mv(ET[n].value.marker));
+ { print_operand(&ET[n].value, annotate);
printf("\n");
}
else
if (ET[n].right != -1) show_node(ET[n].right, depth, annotate);
}
-extern void show_tree(assembly_operand AO, int annotate)
-{ if (AO.type == EXPRESSION_OT) show_node(AO.value, 0, annotate);
+extern void show_tree(const assembly_operand *AO, int annotate)
+{ if (AO->type == EXPRESSION_OT) show_node(AO->value, 0, annotate);
else
- { printf("Constant: "); print_operand(AO);
- if (annotate && (AO.marker != 0))
- printf(" [%s]", describe_mv(AO.marker));
+ { printf("Constant: "); print_operand(AO, annotate);
printf("\n");
}
}
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)))
+ && (ET[n].value.marker == 0))
flag = TRUE;
if (!flag)
(etc) to delete the ~~ operator from the tree. Since this is
depth first, the ~~ being deleted has no ~~s beneath it, which
- is important to make "negate_condition" work. */
+ is important to make "negate_condition" work.
+
+ We also do the check for (x <= y or z) here. This must be done
+ before negate_condition.
+ */
int i;
+ if (ET[n].operator_number == LE_OP || ET[n].operator_number == GE_OP) {
+ if (ET[n].down != -1
+ && ET[ET[n].down].right != -1
+ && ET[ET[ET[n].down].right].right != -1) {
+ if (ET[n].operator_number == LE_OP)
+ warning("The behavior of (<= or) may be unexpected.");
+ else
+ warning("The behavior of (>= or) may be unexpected.");
+ }
+ }
+
if (ET[n].right != -1) delete_negations(ET[n].right, context);
if (ET[n].down == -1) return;
delete_negations(ET[n].down, context);
if (ET[n].down == -1)
{ if (context==CONDITION_CONTEXT)
- { new = ET_used++;
- if (new == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
+ {
+ ensure_memory_list_available(&ET_memlist, ET_used+1);
+ new = ET_used++;
ET[new] = ET[n];
ET[n].down = new; ET[n].operator_number = NONZERO_OP;
ET[new].up = n; ET[new].right = -1;
default:
if (context != CONDITION_CONTEXT) break;
+ ensure_memory_list_available(&ET_memlist, ET_used+1);
new = ET_used++;
- if (new == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
ET[new] = ET[n];
ET[n].down = new; ET[n].operator_number = NONZERO_OP;
ET[new].up = n; ET[new].right = -1;
|| ET[fnaddr].value.value == INDIRECT_SYSF
|| ET[fnaddr].value.value == GLK_SYSF))) {
if (etoken_num_children(pn) > (unsigned int)(opnum == FCALL_OP ? 4:3)) {
+ ensure_memory_list_available(&ET_memlist, ET_used+1);
new = ET_used++;
- if (new == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
ET[new] = ET[n];
ET[n].down = new;
ET[n].operator_number = PUSH_OP;
if (AO.type != EXPRESSION_OT)
{ if (context != CONDITION_CONTEXT) return AO;
+ ensure_memory_list_available(&ET_memlist, ET_used+1);
n = ET_used++;
- if (n == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
ET[n].down = -1;
ET[n].up = -1;
ET[n].right = -1;
/* --- Shift-reduce parser ------------------------------------------------- */
static int sr_sp;
-static token_data *sr_stack;
+static token_data *sr_stack; /* Allocated to sr_sp */
+static memory_list sr_stack_memlist;
extern assembly_operand parse_expression(int context)
{
is constant and thus known at compile time.
If an error has occurred in the expression, which recovery from was
- not possible, then the return is (short constant) 0. This should
- minimise the chance of a cascade of further error messages.
+ not possible, then the return is (short constant) 0 with marker
+ value ERROR_MV. The caller may check for this marker value to
+ decide whether to (e.g.) stop reading array values. Otherwise, it
+ will just be treated as a zero, which should minimise the chance
+ of a cascade of further error messages.
*/
token_data a, b, pop; int i;
previous_token.type = ENDEXP_TT;
previous_token.value = 0;
+ ensure_memory_list_available(&sr_stack_memlist, 1);
sr_sp = 1;
sr_stack[0] = previous_token;
directives.enabled = FALSE;
if (get_next_etoken() == FALSE)
- { ebf_error("expression", token_text);
+ { ebf_curtoken_error("expression");
+ AO.marker = ERROR_MV;
return AO;
}
if (sr_sp == 0)
{ compiler_error("SR error: stack empty");
+ AO.marker = ERROR_MV;
return(AO);
}
{ if (emitter_sp == 0)
{ error("No expression between brackets '(' and ')'");
put_token_back();
+ AO.marker = ERROR_MV;
return AO;
}
if (emitter_sp > 1)
{ compiler_error("SR error: emitter stack overfull");
+ AO.marker = ERROR_MV;
return AO;
}
- AO = emitter_stack[0];
+ AO = emitter_stack[0].op;
if (AO.type == EXPRESSION_OT)
{ if (expr_trace_level >= 3)
{ printf("Tree before lvalue checking:\n");
- show_tree(AO, FALSE);
+ show_tree(&AO, FALSE);
}
if (!glulx_mode)
check_property_operator(AO.value);
ET[AO.value].up = -1;
}
else {
- if ((context != CONSTANT_CONTEXT) && is_property_t(AO.symtype)
+ if ((context != CONSTANT_CONTEXT)
+ && (AO.symindex >= 0)
+ && is_property_t(symbols[AO.symindex].type)
&& (arrow_allowed) && (!bare_prop_allowed))
warning("Bare property name found. \"self.prop\" intended?");
}
if (context == CONSTANT_CONTEXT)
if (!is_constant_ot(AO.type))
{ AO = zero_operand;
+ AO.marker = ERROR_MV;
ebf_error("constant", "<expression>");
}
put_token_back();
return(AO);
}
- switch(find_prec(a,b))
+ switch(find_prec(&a,&b))
{
- case e5: /* Associativity error */
+ case ASSOC_E: /* Associativity error */
error_named("Brackets mandatory to clarify order of:",
a.text);
case LOWER_P:
case EQUAL_P:
- if (sr_sp == MAX_EXPRESSION_NODES)
- memoryerror("MAX_EXPRESSION_NODES", MAX_EXPRESSION_NODES);
+ ensure_memory_list_available(&sr_stack_memlist, sr_sp+1);
sr_stack[sr_sp++] = b;
switch(b.type)
{
case SUBOPEN_TT:
if (sr_sp >= 2 && sr_stack[sr_sp-2].type == OP_TT && sr_stack[sr_sp-2].value == FCALL_OP)
- mark_top_of_emitter_stack(FUNCTION_VALUE_MARKER, b);
+ mark_top_of_emitter_stack(FUNCTION_VALUE_MARKER, &b);
else
add_bracket_layer_to_emitter_stack(0);
break;
case OR_OP:
if (sr_stack[sr_sp-2].type == OP_TT &&
operators[sr_stack[sr_sp-2].value].precedence == 3)
- mark_top_of_emitter_stack(OR_VALUE_MARKER, b);
+ mark_top_of_emitter_stack(OR_VALUE_MARKER, &b);
else
{ error("'or' not between values to the right of a condition");
/* Convert to + for error recovery purposes */
if (shallowest_open_bracket_index > 0 &&
sr_stack[shallowest_open_bracket_index-1].type == OP_TT &&
sr_stack[shallowest_open_bracket_index-1].value == FCALL_OP)
- { mark_top_of_emitter_stack(ARGUMENT_VALUE_MARKER, b);
+ { mark_top_of_emitter_stack(ARGUMENT_VALUE_MARKER, &b);
break;
}
/* Non-argument-separating commas get treated like any other operator; we fall through to the default case. */
case GREATER_P:
do
{ pop = sr_stack[sr_sp - 1];
- emit_token(pop);
+ emit_token(&pop);
sr_sp--;
- } while (find_prec(sr_stack[sr_sp-1], pop) != LOWER_P);
+ } while (find_prec(&sr_stack[sr_sp-1], &pop) != LOWER_P);
break;
- case e1: /* Missing operand error */
+ case NOVAL_E: /* Missing operand error */
error_named("Missing operand after", a.text);
+ /* We insert a "0" token so that the rest of the expression
+ can be compiled. */
put_token_back();
current_token.type = NUMBER_TT;
current_token.value = 0;
current_token.text = "0";
break;
- case e2: /* Unexpected close bracket */
+ case CLOSEB_E: /* Unexpected close bracket */
error("Found '(' without matching ')'");
get_next_etoken();
break;
- case e3: /* Missing operator error */
- error("Missing operator: inserting '+'");
+ case NOOP_E: /* Missing operator error */
+ error_named("Missing operator after", a.text);
+ /* We insert a "+" token so that the rest of the expression
+ can be compiled. */
put_token_back();
current_token.type = OP_TT;
current_token.value = PLUS_OP;
current_token.text = "+";
break;
- case e4: /* Expression ends with an open bracket */
+ case OPENB_E: /* Expression ends with an open bracket */
error("Found '(' without matching ')'");
sr_sp--;
break;
return s*(ET[ET[AO.value].down].value.value);
}
+
+/* Determine if the operand (a parsed expression) is a constant (as
+ per is_constant_ot()) or a comma-separated list of such constants.
+
+ "(1)" and "(1,2,3)" both count, and even "((1,2),3)", but
+ not "(1,(2,3))"; the list must be left-associated.
+
+ Backpatched constants (function names, etc) are acceptable, as are
+ folded constant expressions. Variables are right out.
+
+ The constants are stored in the ops_found array, up to a maximum of
+ max_ops_found. For Inform parsing reasons, the array list is backwards
+ from the order found.
+
+ Returns the number of constants found. If the expression is not a list of
+ constants, returns zero.
+
+ (The return value may be more than max_ops_found, in which case we weren't
+ able to return them all in the array.)
+*/
+extern int test_constant_op_list(const assembly_operand *AO, assembly_operand *ops_found, int max_ops_found)
+{
+ int count = 0;
+ int n;
+
+ if (AO->type != EXPRESSION_OT) {
+ if (!is_constant_ot(AO->type))
+ return 0;
+
+ if (ops_found && max_ops_found > 0)
+ ops_found[0] = *AO;
+ return 1;
+ }
+
+ n = AO->value;
+
+ /* For some reason the top node is always a COMMA with no .right,
+ just a .down. Should we rely on this? For now yes. */
+
+ if (operators[ET[n].operator_number].token_value != COMMA_SEP)
+ return 0;
+ if (ET[n].right != -1)
+ return 0;
+ n = ET[n].down;
+
+ while (TRUE) {
+ if (ET[n].right != -1) {
+ if (ET[ET[n].right].down != -1)
+ return 0;
+ if (!is_constant_ot(ET[ET[n].right].value.type))
+ return 0;
+
+ if (ops_found && max_ops_found > count)
+ ops_found[count] = ET[ET[n].right].value;
+ count++;
+ }
+
+ if (ET[n].down == -1) {
+ if (!is_constant_ot(ET[n].value.type))
+ return 0;
+
+ if (ops_found && max_ops_found > count)
+ ops_found[count] = ET[n].value;
+ count++;
+ return count;
+ }
+
+ if (operators[ET[n].operator_number].token_value != COMMA_SEP)
+ return 0;
+
+ n = ET[n].down;
+ }
+}
+
/* ========================================================================= */
/* Data structure management routines */
/* ------------------------------------------------------------------------- */
{ int i;
/* make_operands(); */
make_lexical_interface_tables();
- for (i=0;i<32;i++) system_function_usage[i] = 0;
+ for (i=0; i<NUMBER_SYSTEM_FUNCTIONS; i++)
+ system_function_usage[i] = 0;
+
+ ET = NULL;
+ emitter_stack = NULL;
+ sr_stack = NULL;
}
extern void expressp_begin_pass(void)
}
extern void expressp_allocate_arrays(void)
-{ ET = my_calloc(sizeof(expression_tree_node), MAX_EXPRESSION_NODES,
+{
+ initialise_memory_list(&ET_memlist,
+ sizeof(expression_tree_node), 100, (void**)&ET,
"expression parse trees");
- emitter_markers = my_calloc(sizeof(int), MAX_EXPRESSION_NODES,
- "emitter markers");
- emitter_bracket_counts = my_calloc(sizeof(int), MAX_EXPRESSION_NODES,
- "emitter bracket layer counts");
- emitter_stack = my_calloc(sizeof(assembly_operand), MAX_EXPRESSION_NODES,
- "emitter stack");
- sr_stack = my_calloc(sizeof(token_data), MAX_EXPRESSION_NODES,
+
+ initialise_memory_list(&emitter_stack_memlist,
+ sizeof(emitterstackinfo), 100, (void**)&emitter_stack,
+ "expression stack");
+
+ initialise_memory_list(&sr_stack_memlist,
+ sizeof(token_data), 100, (void**)&sr_stack,
"shift-reduce parser stack");
}
extern void expressp_free_arrays(void)
-{ my_free(&ET, "expression parse trees");
- my_free(&emitter_markers, "emitter markers");
- my_free(&emitter_bracket_counts, "emitter bracket layer counts");
- my_free(&emitter_stack, "emitter stack");
- my_free(&sr_stack, "shift-reduce parser stack");
+{
+ deallocate_memory_list(&ET_memlist);
+
+ deallocate_memory_list(&emitter_stack_memlist);
+
+ deallocate_memory_list(&sr_stack_memlist);
}
/* ========================================================================= */