void enter_object_hash P1(struct object *, ob) { int h = ObjHash(ob->name); IF_DEBUG(struct object *s); IF_DEBUG(s = find_obj_n(ob->name)); DEBUG_CHECK1(s && s != ob, "Duplicate object \"%s\" in object hash table", ob->name); DEBUG_CHECK1(s, "Entering object \"%s\" twice in object table", ob->name); DEBUG_CHECK1(ob->next_hash, "Object \"%s\" not found in object table but next link not null", ob->name); ob->next_hash = obj_table[h]; obj_table[h] = ob; objs_in_table++; return; }
void free_string (const char * str) { block_t **prev, *b; int h; b = BLOCK(str); DEBUG_CHECK1(b != findblock(str),"stralloc.c: free_string called on non-shared string: %s.\n", str); /* * if a string has been ref'd USHRT_MAX times then we assume that its used * often enough to justify never freeing it. */ if (!REFS(b)) return; REFS(b)--; SUB_STRING(SIZE(b)); NDBG(b); if (REFS(b) > 0) return; h = StrHash(str); prev = base_table + h; while ((b = *prev)) { if (STRING(b) == str) { *prev = NEXT(b); break; } prev = &(NEXT(b)); } DEBUG_CHECK1(!b, "free_string: not found in string table! (\"%s\")\n", str); SUB_NEW_STRING(SIZE(b), sizeof(block_t)); FREE(b); CHECK_STRING_STATS; }
void remove_object_hash P1(struct object *, ob) { int h = ObjHash(ob->name); struct object *s; s = find_obj_n(ob->name); DEBUG_CHECK1(s != ob, "Remove object \"%s\": found a different object!", ob->name); obj_table[h] = ob->next_hash; ob->next_hash = 0; objs_in_table--; return; }
void deallocate_string (char * str) { int h; block_t *b, **prev; h = StrHash(str); prev = base_table + h; while ((b = *prev)) { if (STRING(b) == str) { *prev = NEXT(b); break; } prev = &(NEXT(b)); } DEBUG_CHECK1(!b,"stralloc.c: deallocate_string called on non-shared string: %s.\n", str); FREE(b); }
void remove_living_name (object_t * ob) { object_t **hl; ob->flags &= ~O_ENABLE_COMMANDS; if (!ob->living_name) return; num_living_names--; DEBUG_CHECK(!ob->living_name, "remove_living_name: no living name set.\n"); hl = &hashed_living[hash_living_name(ob->living_name)]; while (*hl) { if (*hl == ob) break; hl = &(*hl)->next_hashed_living; } DEBUG_CHECK1(*hl == 0, "remove_living_name: Object named %s no in hash list.\n", ob->living_name); *hl = ob->next_hashed_living; free_string(ob->living_name); ob->next_hashed_living = 0; ob->living_name = 0; }
void i_generate_node P1(struct parse_node *, expr) { if (!expr) return; if (expr->line && expr->line != line_being_generated) switch_to_line(expr->line); switch (expr->kind) { case F_OR: case F_XOR: case F_AND: case F_EQ: case F_NE: case F_GT: case F_GE: case F_LT: case F_LE: case F_LSH: case F_RSH: case F_ADD: case F_SUBTRACT: case F_MULTIPLY: case F_DIVIDE: case F_MOD: i_generate_node(expr->l.expr); /* fall through */ case F_RETURN: case F_POP_VALUE: case F_PRE_INC: case F_PRE_DEC: case F_INC: case F_DEC: case F_POST_INC: case F_POST_DEC: case F_NOT: case F_COMPL: case F_NEGATE: i_generate_node(expr->r.expr); /* fall through */ case F_CONST0: case F_CONST1: #ifdef DEBUG case F_BREAK_POINT: #endif case F_BREAK: ins_f_byte(expr->kind); break; case F_ASSIGN: /* note these are backwards */ case F_VOID_ASSIGN: case F_VOID_ADD_EQ: case F_ADD_EQ: case F_AND_EQ: case F_OR_EQ: case F_XOR_EQ: case F_LSH_EQ: case F_RSH_EQ: case F_SUB_EQ: case F_MULT_EQ: case F_MOD_EQ: case F_DIV_EQ: case F_INDEX_LVALUE: case F_INDEX: case F_RINDEX: case F_RINDEX_LVALUE: i_generate_node(expr->r.expr); i_generate_node(expr->l.expr); ins_f_byte(expr->kind); break; case F_NN_RANGE: case F_RN_RANGE: case F_RR_RANGE: case F_NR_RANGE: case F_NN_RANGE_LVALUE: case F_RN_RANGE_LVALUE: case F_NR_RANGE_LVALUE: case F_RR_RANGE_LVALUE: i_generate_node(expr->l.expr); i_generate_node(expr->r.expr); i_generate_node(expr->v.expr); ins_f_byte(expr->kind); break; case NODE_NE_RANGE_LVALUE: i_generate_node(expr->l.expr); ins_f_byte(F_CONST1); i_generate_node(expr->v.expr); ins_f_byte(F_NR_RANGE_LVALUE); break; case NODE_RE_RANGE_LVALUE: i_generate_node(expr->l.expr); ins_f_byte(F_CONST1); i_generate_node(expr->v.expr); ins_f_byte(F_RR_RANGE_LVALUE); break; case F_RE_RANGE: case F_NE_RANGE: i_generate_node(expr->l.expr); i_generate_node(expr->v.expr); ins_f_byte(expr->kind); break; case F_STRING: if (expr->v.number <= 0xff) { ins_f_byte(F_SHORT_STRING); ins_byte(expr->v.number); } else { ins_f_byte(F_STRING); ins_short(expr->v.number); } break; case F_REAL: ins_f_byte(F_REAL); ins_real(expr->v.real); break; case F_NBYTE: case F_BYTE: ins_f_byte(expr->kind); ins_byte(expr->v.number); break; case F_NUMBER: write_number(expr->v.number); break; case F_LOR: case F_LAND: i_generate_node(expr->l.expr); i_generate_forward_branch(expr->kind); i_generate_node(expr->r.expr); if (expr->l.expr->kind == NODE_BRANCH_LINK){ i_update_forward_branch_links(expr->kind,expr->l.expr); } else i_update_forward_branch(); break; case NODE_BRANCH_LINK: i_generate_node(expr->l.expr); ins_byte(0); expr->line = CURRENT_PROGRAM_SIZE; ins_short(0); i_generate_node(expr->r.expr); break; case F_AGGREGATE: case F_AGGREGATE_ASSOC: generate_expr_list(expr->r.expr); ins_f_byte(expr->kind); ins_short(expr->v.number); break; case NODE_COMMA: case NODE_ASSOC: i_generate_node(expr->l.expr); i_generate_node(expr->r.expr); break; case NODE_BREAK: ins_f_byte(F_BRANCH); expr->v.expr = break_ptr; expr->line = CURRENT_PROGRAM_SIZE; expr->type = 0; ins_short(0); break_ptr = expr; break; case NODE_CONTINUE: if (switches) { ins_f_byte(F_POP_BREAK); ins_byte(switches); } ins_f_byte(F_BRANCH); expr->v.expr = cont_ptr; expr->line = CURRENT_PROGRAM_SIZE; expr->type = 0; ins_short(0); cont_ptr = expr; break; case NODE_STATEMENTS: i_generate_node(expr->l.expr); i_generate_node(expr->r.expr); break; case NODE_PARAMETER: ins_f_byte(F_LOCAL); ins_byte(expr->v.number + current_num_values); break; case NODE_PARAMETER_LVALUE: ins_f_byte(F_LOCAL_LVALUE); ins_byte(expr->v.number + current_num_values); break; case NODE_VALUE: ins_f_byte(F_LOCAL); ins_byte(expr->v.number); break; case NODE_LVALUE: ins_f_byte(F_LOCAL_LVALUE); ins_byte(expr->v.number); break; case NODE_IF: if (expr->v.expr->kind == F_NOT) { i_generate_node(expr->v.expr->r.expr); i_generate_forward_branch(F_BRANCH_WHEN_NON_ZERO); } else { i_generate_node(expr->v.expr); i_generate_forward_branch(F_BRANCH_WHEN_ZERO); } i_generate_node(expr->l.expr); if (expr->r.expr) { i_generate_else(); i_generate_node(expr->r.expr); } i_update_forward_branch(); break; case NODE_FOR: { int forever = node_always_true(expr->l.expr->v.expr), pos; i_save_loop_info(); i_generate_node(expr->l.expr->l.expr); if (!forever) i_generate_forward_branch(F_BRANCH); pos = CURRENT_PROGRAM_SIZE; i_generate_node(expr->r.expr); i_update_continues(); i_generate_node(expr->l.expr->r.expr); if (!forever) i_update_forward_branch(); if (expr->l.expr->v.expr->kind == F_LOOP_COND){ i_generate_node(expr->l.expr->v.expr); ins_short(CURRENT_PROGRAM_SIZE - pos); } else i_branch_backwards(generate_conditional_branch(expr->l.expr->v.expr), pos); i_update_breaks(); i_restore_loop_info(); } break; case NODE_WHILE: { int forever = node_always_true(expr->l.expr), pos; i_save_loop_info(); if (!forever) i_generate_forward_branch(F_BRANCH); pos = CURRENT_PROGRAM_SIZE; i_generate_node(expr->r.expr); if (!forever) i_update_forward_branch(); i_update_continues(); if (expr->l.expr->kind == F_LOOP_COND){ i_generate_node(expr->l.expr); ins_short(CURRENT_PROGRAM_SIZE - pos); } else i_branch_backwards(generate_conditional_branch(expr->l.expr), pos); i_update_breaks(); i_restore_loop_info(); } break; case NODE_DO_WHILE: { int pos; i_save_loop_info(); pos = CURRENT_PROGRAM_SIZE; i_generate_node(expr->l.expr); i_update_continues(); i_branch_backwards(generate_conditional_branch(expr->r.expr), pos); i_update_breaks(); i_restore_loop_info(); } break; case NODE_CASE_NUMBER: case NODE_CASE_STRING: if (expr->v.expr) { struct parse_node *other = expr->v.expr; expr->v.number = 1; other->l.expr = expr->l.expr; other->v.number = CURRENT_PROGRAM_SIZE; expr->l.expr = other; } else { expr->v.number = CURRENT_PROGRAM_SIZE; } break; case NODE_DEFAULT: expr->v.number = CURRENT_PROGRAM_SIZE; break; case NODE_SWITCH_STRINGS: case NODE_SWITCH_NUMBERS: case NODE_SWITCH_DIRECT: { int addr; i_generate_node(expr->l.expr); switches++; ins_f_byte(F_SWITCH); ins_byte(0xff); /* kind of table */ addr = CURRENT_PROGRAM_SIZE; ins_short(0); /* address of table */ ins_short(0); /* break address to push, table is entered before */ ins_short(0); /* default address */ i_generate_node(expr->r.expr); if (expr->v.expr && expr->v.expr->kind == NODE_DEFAULT) { upd_short(addr + 4, expr->v.expr->v.number); expr->v.expr = expr->v.expr->l.expr; } else { upd_short(addr + 4, CURRENT_PROGRAM_SIZE); } /* just in case the last case doesn't have a break */ ins_f_byte(F_BREAK); /* build table */ upd_short(addr, CURRENT_PROGRAM_SIZE); #ifdef BINARIES if (expr->kind == NODE_SWITCH_STRINGS) { short sw; sw = addr - 2; add_to_mem_block(A_PATCH, (char *)&sw, sizeof sw); } #endif if (expr->kind == NODE_SWITCH_DIRECT) { struct parse_node *pn = expr->v.expr; while (pn) { ins_short((short)pn->v.number); pn = pn->l.expr; } ins_int(expr->v.expr->r.number); mem_block[current_block].block[addr-1] = (char)0xfe; } else { int table_size = 0; int power_of_two = 1; int i = 0; struct parse_node *pn = expr->v.expr; while (pn) { INS_POINTER((POINTER_INT)pn->r.expr); ins_short((short)pn->v.number); pn = pn->l.expr; table_size += 1; } while ((power_of_two<<1) <= table_size) { power_of_two <<= 1; i++; } if (expr->kind == NODE_SWITCH_NUMBERS) mem_block[current_block].block[addr-1] = (char)(0xf0+i); else mem_block[current_block].block[addr-1] = (char)(i*0x10+0x0f); } upd_short(addr + 2, CURRENT_PROGRAM_SIZE); break; } case NODE_CONDITIONAL: { int addr; i_generate_node(expr->l.expr); ins_f_byte(F_BRANCH_WHEN_ZERO); addr = CURRENT_PROGRAM_SIZE; ins_short(0); i_generate_node(expr->r.expr->l.expr); upd_short(addr, CURRENT_PROGRAM_SIZE - addr + 3); /*over the branch */ ins_f_byte(F_BRANCH); addr = CURRENT_PROGRAM_SIZE; ins_short(0); i_generate_node(expr->r.expr->r.expr); upd_short(addr, CURRENT_PROGRAM_SIZE - addr); } break; case F_CATCH: { int addr; ins_f_byte(F_CATCH); addr = CURRENT_PROGRAM_SIZE; ins_short(0); i_generate_node(expr->r.expr); ins_f_byte(F_END_CATCH); upd_short(addr, CURRENT_PROGRAM_SIZE - addr); break; } case F_SSCANF: i_generate_node(expr->l.expr->l.expr); i_generate_node(expr->l.expr->r.expr); ins_f_byte(F_SSCANF); ins_byte(expr->r.expr->v.number); generate_lvalue_list(expr->r.expr); break; case F_PARSE_COMMAND: i_generate_node(expr->l.expr->l.expr); i_generate_node(expr->l.expr->r.expr->l.expr); i_generate_node(expr->l.expr->r.expr->r.expr); ins_f_byte(F_PARSE_COMMAND); ins_byte(expr->r.expr->v.number); generate_lvalue_list(expr->r.expr); break; case F_TIME_EXPRESSION: ins_f_byte(F_TIME_EXPRESSION); i_generate_node(expr->r.expr); ins_f_byte(F_END_TIME_EXPRESSION); break; case F_TO_FLOAT: case F_TO_INT: generate_expr_list(expr->r.expr); ins_f_byte(expr->kind); break; case F_GLOBAL_LVALUE: case F_GLOBAL: case F_LOCAL_LVALUE: case F_LOCAL: case F_LOOP_INCR: case F_WHILE_DEC: ins_f_byte(expr->kind); ins_byte(expr->v.number); break; case F_LOOP_COND: { int i; ins_f_byte(F_LOOP_COND); ins_byte(expr->l.expr->v.number); /* expand this into a number so we can pull it fast at runtime */ if (expr->r.expr->kind == F_LOCAL) { i_generate_node(expr->r.expr); } else { ins_f_byte(F_NUMBER); switch (expr->r.expr->kind) { case F_CONST0: i = 0; break; case F_CONST1: i = 1; break; case F_NBYTE: i = - expr->r.expr->v.number; break; case F_BYTE: case F_NUMBER: i = expr->r.expr->v.number; break; default: fatal("Unknown node %i in F_LOOP_COND\n", expr->r.expr->kind); } ins_int(i); } break; } case F_SIMUL_EFUN: case F_CALL_FUNCTION_BY_ADDRESS: generate_expr_list(expr->r.expr); ins_f_byte(expr->kind); ins_short(expr->v.number); ins_byte((expr->r.expr ? expr->r.expr->kind : 0)); break; case F_CALL_INHERITED: generate_expr_list(expr->r.expr); ins_f_byte(F_CALL_INHERITED); ins_byte(expr->v.number & 0xff); ins_short(expr->v.number >> 8); ins_byte((expr->r.expr ? expr->r.expr->kind : 0)); break; case F_EVALUATE: #ifdef NEW_FUNCTIONS generate_expr_list(expr->r.expr); ins_f_byte(F_EVALUATE); #else i_generate_node(expr->l.expr); ins_f_byte(F_EVALUATE); generate_expr_list(expr->r.expr); ins_f_byte(F_CALL_OTHER); #endif ins_byte(expr->v.number); break; case F_FUNCTION_CONSTRUCTOR: #ifdef NEW_FUNCTIONS if ((expr->v.number & 0xff) == FP_CALL_OTHER) { i_generate_node(expr->l.expr); i_generate_node(expr->r.expr); ins_f_byte(F_FUNCTION_CONSTRUCTOR); ins_f_byte(FP_CALL_OTHER); break; } if (expr->r.expr) { generate_expr_list(expr->r.expr); ins_f_byte(F_AGGREGATE); ins_short(expr->r.expr->kind); } else ins_f_byte(F_CONST0); ins_f_byte(F_FUNCTION_CONSTRUCTOR); ins_byte(expr->v.number & 0xff); switch (expr->v.number & 0xff) { case FP_SIMUL: case FP_LOCAL: ins_short(expr->v.number >> 8); break; case FP_EFUN: ins_f_byte(predefs[expr->v.number >> 8].token); break; case FP_FUNCTIONAL: case FP_FUNCTIONAL | FP_NOT_BINDABLE: { int addr, save_current_num_values = current_num_values; ins_byte(expr->v.number >> 8); addr = CURRENT_PROGRAM_SIZE; ins_short(0); current_num_values = expr->r.expr ? expr->r.expr->kind : 0; i_generate_node(expr->l.expr); current_num_values = save_current_num_values; ins_f_byte(F_RETURN); upd_short(addr, CURRENT_PROGRAM_SIZE - addr - 2); break; } } #else if (expr->l.expr) i_generate_node(expr->l.expr); i_generate_node(expr->r.expr); ins_f_byte(F_FUNCTION_CONSTRUCTOR); ins_byte(expr->v.number); #endif break; #ifdef NEW_FUNCTIONS case NODE_ANON_FUNC: { int addr; ins_f_byte(F_FUNCTION_CONSTRUCTOR); ins_byte(FP_ANONYMOUS); ins_byte(expr->v.number); ins_byte(expr->l.number); addr = CURRENT_PROGRAM_SIZE; ins_short(0); i_generate_node(expr->r.expr); upd_short(addr, CURRENT_PROGRAM_SIZE - addr - 2); break; } #endif default: DEBUG_CHECK1(expr->kind < BASE, "Unknown eoperator %s in i_generate_node.\n", get_f_name(expr->kind)); generate_expr_list(expr->r.expr); ins_f_byte(expr->kind); if (expr->v.number != -1) ins_byte(expr->v.number); } }