To manage the memory storage of inter code.

§1.

typedef struct inter_warehouse {
    struct filename *origin_file;
    struct inter_warehouse_room *first_room;
    int size;
    int capacity;
    struct inter_resource_holder *stored_resources;
    CLASS_DEFINITION
} inter_warehouse;

§2.

enum NO_IRSRC from 0
enum STRING_IRSRC
enum SYMBOLS_TABLE_IRSRC
enum FRAME_LIST_IRSRC
enum PACKAGE_IRSRC
enum REF_IRSRC
typedef struct inter_resource_holder {
    int irsrc;
    struct inter_package *owning_package;
    struct inter_symbols_table *stored_symbols_table;
    struct inter_node_list *stored_frame_list;
    struct inter_package *stored_package;
    struct text_stream *stored_text_stream;
    void *stored_ref;
} inter_resource_holder;

typedef struct inter_warehouse_room {
    struct inter_warehouse *owning_warehouse;
    inter_ti index_offset;
    int size;
    int capacity;
    inter_ti *bytecode;
    struct inter_warehouse_room *next_room;
    CLASS_DEFINITION
} inter_warehouse_room;

§3.

inter_warehouse *the_only_warehouse = NULL;

inter_warehouse *Inter::Warehouse::new(void) {
    if (the_only_warehouse == NULL) {
        inter_warehouse *warehouse = CREATE(inter_warehouse);
        warehouse->origin_file = NULL;
        warehouse->first_room = Inter::Warehouse::new_room(warehouse, 4096, NULL);
        warehouse->size = 1;
        warehouse->capacity = 0;
        warehouse->stored_resources = NULL;
        the_only_warehouse = warehouse;
    }
    return the_only_warehouse;
}

inter_warehouse_room *Inter::Warehouse::new_room(inter_warehouse *owner, int capacity, inter_warehouse_room *prec) {
    inter_warehouse_room *IS = CREATE(inter_warehouse_room);
    IS->owning_warehouse = owner;
    IS->index_offset = (prec)?(prec->index_offset + (inter_ti) prec->capacity):0;
    IS->size = 0;
    IS->capacity = capacity;
    IS->bytecode = (inter_ti *)
        Memory::calloc(capacity, sizeof(inter_ti), INTER_BYTECODE_MREASON);
    LOGIF(INTER_MEMORY, "Created repository %d segment %d with capacity %d\n",
        owner->allocation_id, IS->allocation_id, IS->capacity);
    return IS;
}

typedef struct warehouse_floor_space {
    struct inter_warehouse_room *repo_segment;
    int index;
    inter_ti *data;
    int extent;
} warehouse_floor_space;

warehouse_floor_space Inter::Warehouse::find_room_in_room(inter_warehouse_room *IS, int n) {
    if ((IS->size < 0) || (IS->size > IS->capacity)) internal_error("bad segment");
    if (IS->next_room != NULL) internal_error("nonfinal segment");
    if (IS->size + n + PREFRAME_SIZE > IS->capacity) {
        int next_size = Inter::Warehouse::enlarge_size(IS->capacity, n + PREFRAME_SIZE);
        IS->capacity = IS->size;
        IS->next_room = Inter::Warehouse::new_room(IS->owning_warehouse, next_size, IS);
        IS = IS->next_room;
    }

    int at = IS->size, this_piece = PREFRAME_SIZE + n;
    for (int i=0; i<this_piece; i++) IS->bytecode[at + i] = 0;
    IS->bytecode[at + PREFRAME_SKIP_AMOUNT] = (inter_ti) this_piece;
    IS->size += this_piece;

    warehouse_floor_space W;
    W.repo_segment = IS; W.index = at;
    if ((IS) && (at >= 0) && (at < IS->size)) {
        W.data = &(IS->bytecode[at + PREFRAME_SIZE]);
        W.extent = ((int) IS->bytecode[at + PREFRAME_SKIP_AMOUNT]) - PREFRAME_SIZE;
    } else {
        W.data = NULL; W.extent = 0;
    }
    return W;
}

int Inter::Warehouse::enlarge_size(int n, int at_least) {
    int next_size = 2*n;
    if (next_size < 128) next_size = 128;
    while (n + at_least > next_size) next_size = 2*next_size;
    return next_size;
}

inter_tree_node *Inter::Warehouse::find_room(inter_warehouse *warehouse, inter_tree *I,
    int n, inter_error_location *eloc, inter_package *owner) {
    if (warehouse == NULL) internal_error("no warehouse");
    if (I == NULL) internal_error("no tree supplied");
    inter_warehouse_room *IS = warehouse->first_room;
    while (IS->next_room) IS = IS->next_room;
    warehouse_floor_space W = Inter::Warehouse::find_room_in_room(IS, n);
    inter_tree_node *F = Inode::new(I, W);
    Inode::set_metadata(F, PREFRAME_ORIGIN, Inter::Warehouse::store_origin(warehouse, eloc));
    Inode::attach_package(F, owner);
    return F;
}

inter_ti Inter::Warehouse::create_resource(inter_warehouse *warehouse) {
    if (warehouse->size >= warehouse->capacity) {
        int new_size = 128;
        while (new_size < 2*warehouse->capacity) new_size = 2*new_size;

        LOGIF(INTER_MEMORY, "Giving warehouse %d frame list of size %d (up from %d)\n",
            warehouse->allocation_id, new_size, warehouse->capacity);

        inter_resource_holder *storage = (inter_resource_holder *) Memory::calloc(new_size, sizeof(inter_resource_holder), INTER_LINKS_MREASON);
        inter_resource_holder *old = warehouse->stored_resources;
        for (int i=0; i<warehouse->capacity; i++) storage[i] = old[i];
        if (warehouse->capacity > 0)
            Memory::I7_free(old, INTER_LINKS_MREASON, warehouse->capacity);
        warehouse->stored_resources = storage;
        warehouse->capacity = new_size;
    }
    int n = warehouse->size ++;
    warehouse->stored_resources[n].irsrc = NO_IRSRC;
    warehouse->stored_resources[n].owning_package = NULL;
    warehouse->stored_resources[n].stored_symbols_table = NULL;
    warehouse->stored_resources[n].stored_ref = NULL;
    warehouse->stored_resources[n].stored_package = NULL;
    warehouse->stored_resources[n].stored_text_stream = NULL;
    warehouse->stored_resources[n].stored_frame_list = NULL;
    return (inter_ti) n;
}

inter_ti Inter::Warehouse::store_origin(inter_warehouse *warehouse, inter_error_location *eloc) {
    if (eloc) {
        if (eloc->error_interb) {
            warehouse->origin_file = eloc->error_interb;
            return (inter_ti) (0x10000000 + eloc->error_offset);
        }
        if (eloc->error_tfp) {
            warehouse->origin_file = eloc->error_tfp->text_file_filename;
            return (inter_ti) (eloc->error_tfp->line_count);
        }
    }
    return 0;
}

typedef struct inter_error_stash {
    struct inter_error_location stashed_eloc;
    struct text_file_position stashed_tfp;
    CLASS_DEFINITION
} inter_error_stash;

inter_error_location *Inter::Warehouse::retrieve_origin(inter_warehouse *warehouse, inter_ti C) {
    if ((warehouse) && (warehouse->origin_file)) {
        inter_error_stash *stash = CREATE(inter_error_stash);
        stash->stashed_tfp = TextFiles::nowhere();
        if (C < 0x10000000) {
            text_file_position *tfp = &(stash->stashed_tfp);
            tfp->text_file_filename = warehouse->origin_file;
            tfp->line_count = (int) C;
            stash->stashed_eloc = Inter::Errors::file_location(NULL, tfp);
        } else {
            stash->stashed_eloc = Inter::Errors::interb_location(warehouse->origin_file, (size_t) (C - 0x10000000));
        }
        return &(stash->stashed_eloc);
    }
    return NULL;
}

inter_symbols_table *Inter::Warehouse::get_symbols_table(inter_warehouse *warehouse, inter_ti n) {
    if (n >= (inter_ti) warehouse->size) return NULL;
    if (n == 0) return NULL;
    return warehouse->stored_resources[n].stored_symbols_table;
}

inter_ti Inter::Warehouse::create_symbols_table(inter_warehouse *warehouse) {
    inter_ti n = Inter::Warehouse::create_resource(warehouse);
    if (warehouse->stored_resources[n].stored_symbols_table == NULL) {
        warehouse->stored_resources[n].irsrc = SYMBOLS_TABLE_IRSRC;
        warehouse->stored_resources[n].stored_symbols_table = InterSymbolsTables::new();
        warehouse->stored_resources[n].stored_symbols_table->n_index = (int) n;
    }
    return n;
}

void Inter::Warehouse::attribute_resource(inter_warehouse *warehouse, inter_ti n, inter_package *owner) {
    if (n >= (inter_ti) warehouse->size) internal_error("out of range");
    warehouse->stored_resources[n].owning_package = owner;
}

text_stream *Inter::Warehouse::get_text(inter_warehouse *warehouse, inter_ti n) {
    if (n >= (inter_ti) warehouse->size) return NULL;
    return warehouse->stored_resources[n].stored_text_stream;
}

inter_ti Inter::Warehouse::create_text(inter_warehouse *warehouse, inter_package *owner) {
    inter_ti n = Inter::Warehouse::create_resource(warehouse);
    if (warehouse->stored_resources[n].stored_text_stream == NULL) {
        warehouse->stored_resources[n].irsrc = STRING_IRSRC;
        warehouse->stored_resources[n].stored_text_stream = Str::new();
        warehouse->stored_resources[n].owning_package = owner;
    }
    return n;
}

inter_package *Inter::Warehouse::get_package(inter_warehouse *warehouse, inter_ti n) {
    if (n >= (inter_ti) warehouse->size) return NULL;
    if (n == 0) return NULL;
    return warehouse->stored_resources[n].stored_package;
}

inter_ti Inter::Warehouse::create_package(inter_warehouse *warehouse, inter_tree *I) {
    inter_ti n = Inter::Warehouse::create_resource(warehouse);
    if (warehouse->stored_resources[n].stored_package == NULL) {
        warehouse->stored_resources[n].irsrc = PACKAGE_IRSRC;
        warehouse->stored_resources[n].stored_package = Inter::Packages::new(I, n);
        warehouse->stored_resources[n].owning_package =
            warehouse->stored_resources[n].stored_package;
    }
    return n;
}

void *Inter::Warehouse::get_ref(inter_warehouse *warehouse, inter_ti n) {
    if (n >= (inter_ti) warehouse->size) return NULL;
    return warehouse->stored_resources[n].stored_ref;
}

inter_ti Inter::Warehouse::create_ref(inter_warehouse *warehouse) {
    inter_ti n = Inter::Warehouse::create_resource(warehouse);
    warehouse->stored_resources[n].irsrc = REF_IRSRC;
    warehouse->stored_resources[n].stored_ref = NULL;
    return n;
}

inter_node_list *Inter::Warehouse::get_frame_list(inter_warehouse *warehouse, inter_ti N) {
    if (warehouse == NULL) return NULL;
    int n = (int) N;
    if (n >= warehouse->size) return NULL;
    return warehouse->stored_resources[n].stored_frame_list;
}

inter_ti Inter::Warehouse::create_frame_list(inter_warehouse *warehouse) {
    inter_ti n = Inter::Warehouse::create_resource(warehouse);
    warehouse->stored_resources[n].irsrc = FRAME_LIST_IRSRC;
    warehouse->stored_resources[n].stored_frame_list = Inter::ListLiterals::new();
    return n;
}

void Inter::Warehouse::set_ref(inter_warehouse *warehouse, inter_ti n, void *ref) {
    if (n >= (inter_ti) warehouse->size) return;
    warehouse->stored_resources[n].stored_ref = ref;
}

void Inter::Warehouse::wipe(void) {
    if (the_only_warehouse == NULL) return;
    for (int i=0; i<the_only_warehouse->size; i++) {
        if (the_only_warehouse->stored_resources[i].irsrc == STRING_IRSRC) {
            text_stream *T = the_only_warehouse->stored_resources[i].stored_text_stream;
            if (T) {
                Str::clear(T);
                WRITE_TO(T, "XYZZY-%d", i);
            }
        }
    }
}