+
+/* --------------------------------------------------------------------------
+ * Expandable symbol tables. A template, which is instantiated for the name,
+ * tycon, class, instance and module tables. Also, potentially, TREX Exts.
+ * ------------------------------------------------------------------------*/
+
+#ifdef DEBUG_STORAGE_EXTRA
+static Bool debugStorageExtra = TRUE;
+#else
+static Bool debugStorageExtra = FALSE;
+#endif
+
+
+#define EXPANDABLE_SYMBOL_TABLE(type_name,struct_name, \
+ proc_name,free_proc_name, \
+ free_list,tab_name,tab_size,err_msg, \
+ TAB_INIT_SIZE,TAB_MAX_SIZE, \
+ TAB_BASE_ADDR) \
+ \
+ struct struct_name* tab_name = NULL; \
+ int tab_size = 0; \
+ static type_name free_list = TAB_BASE_ADDR-1; \
+ \
+ void free_proc_name ( type_name n ) \
+ { \
+ assert(TAB_BASE_ADDR <= n); \
+ assert(n < TAB_BASE_ADDR+tab_size); \
+ assert(tab_name[n-TAB_BASE_ADDR].inUse); \
+ tab_name[n-TAB_BASE_ADDR].inUse = FALSE; \
+ if (!debugStorageExtra) { \
+ tab_name[n-TAB_BASE_ADDR].nextFree = free_list; \
+ free_list = n; \
+ } \
+ } \
+ \
+ type_name proc_name ( void ) \
+ { \
+ Int i; \
+ Int newSz; \
+ struct struct_name* newTab; \
+ struct struct_name* temp; \
+ try_again: \
+ if (free_list != TAB_BASE_ADDR-1) { \
+ type_name t = free_list; \
+ free_list = tab_name[free_list-TAB_BASE_ADDR].nextFree; \
+ assert (!(tab_name[t-TAB_BASE_ADDR].inUse)); \
+ tab_name[t-TAB_BASE_ADDR].inUse = TRUE; \
+ return t; \
+ } \
+ \
+ newSz = (tab_size == 0 ? TAB_INIT_SIZE : 2 * tab_size); \
+ if (newSz > TAB_MAX_SIZE) goto cant_allocate; \
+ newTab = malloc(newSz * sizeof(struct struct_name)); \
+ if (!newTab) goto cant_allocate; \
+ for (i = 0; i < tab_size; i++) \
+ newTab[i] = tab_name[i]; \
+ for (i = tab_size; i < newSz; i++) { \
+ newTab[i].inUse = FALSE; \
+ newTab[i].nextFree = i-1+TAB_BASE_ADDR; \
+ } \
+ if (0 && debugStorageExtra) \
+ fprintf(stderr, "Expanding " #type_name \
+ "table to size %d\n", newSz ); \
+ newTab[tab_size].nextFree = TAB_BASE_ADDR-1; \
+ free_list = newSz-1+TAB_BASE_ADDR; \
+ tab_size = newSz; \
+ temp = tab_name; \
+ tab_name = newTab; \
+ if (temp) free(temp); \
+ goto try_again; \
+ \
+ cant_allocate: \
+ ERRMSG(0) err_msg \
+ EEND; \
+ } \
+
+
+
+EXPANDABLE_SYMBOL_TABLE(Name,strName,allocNewName,freeName,
+ nameFL,tabName,tabNameSz,
+ "Name storage space exhausted",
+ NAME_INIT_SIZE,NAME_MAX_SIZE,NAME_BASE_ADDR)
+
+
+EXPANDABLE_SYMBOL_TABLE(Tycon,strTycon,allocNewTycon,freeTycon,
+ tyconFL,tabTycon,tabTyconSz,
+ "Type constructor storage space exhausted",
+ TYCON_INIT_SIZE,TYCON_MAX_SIZE,TYCON_BASE_ADDR)
+
+
+EXPANDABLE_SYMBOL_TABLE(Class,strClass,allocNewClass,freeClass,
+ classFL,tabClass,tabClassSz,
+ "Class storage space exhausted",
+ CCLASS_INIT_SIZE,CCLASS_MAX_SIZE,CCLASS_BASE_ADDR)
+
+
+EXPANDABLE_SYMBOL_TABLE(Inst,strInst,allocNewInst,freeInst,
+ instFL,tabInst,tabInstSz,
+ "Instance storage space exhausted",
+ INST_INIT_SIZE,INST_MAX_SIZE,INST_BASE_ADDR)
+
+
+EXPANDABLE_SYMBOL_TABLE(Module,strModule,allocNewModule,freeModule,
+ moduleFL,tabModule,tabModuleSz,
+ "Module storage space exhausted",
+ MODULE_INIT_SIZE,MODULE_MAX_SIZE,MODULE_BASE_ADDR)
+
+#ifdef DEBUG_STORAGE
+struct strName* generate_name_ref ( Cell nm )
+{
+ assert(isName(nm));
+ nm -= NAME_BASE_ADDR;
+ assert(tabName[nm].inUse);
+ assert(isModule(tabName[nm].mod));
+ return & tabName[nm];
+}
+struct strTycon* generate_tycon_ref ( Cell tc )
+{
+ assert(isTycon(tc) || isTuple(tc));
+ tc -= TYCON_BASE_ADDR;
+ assert(tabTycon[tc].inUse);
+ assert(isModule(tabTycon[tc].mod));
+ return & tabTycon[tc];
+}
+struct strClass* generate_cclass_ref ( Cell cl )
+{
+ assert(isClass(cl));
+ cl -= CCLASS_BASE_ADDR;
+ assert(tabClass[cl].inUse);
+ assert(isModule(tabClass[cl].mod));
+ return & tabClass[cl];
+}
+struct strInst* generate_inst_ref ( Cell in )
+{
+ assert(isInst(in));
+ in -= INST_BASE_ADDR;
+ assert(tabInst[in].inUse);
+ assert(isModule(tabInst[in].mod));
+ return & tabInst[in];
+}
+struct strModule* generate_module_ref ( Cell mo )
+{
+ assert(isModule(mo));
+ mo -= MODULE_BASE_ADDR;
+ assert(tabModule[mo].inUse);
+ return & tabModule[mo];
+}
+#endif
+
+