void Glulxe::classes_remove(int classid, void *obj) { classtable_t *ctab; classref_t *cref; classref_t **crefp; gidispatch_rock_t objrock; if (classid < 0 || classid >= num_classes) return; ctab = classes[classid]; objrock = gidispatch_get_objrock(obj, classid); cref = (classref_t *)objrock.ptr; if (!cref) return; crefp = &(ctab->bucket[cref->bucknum]); for (; *crefp; crefp = &((*crefp)->next)) { if ((*crefp) == cref) { *crefp = cref->next; if (!cref->obj) { nonfatal_warning("attempt to free nullptr object!"); } cref->obj = nullptr; cref->id = 0; cref->next = nullptr; glulx_free(cref); return; } } return; }
/* Delete a Glk object from the appropriate hash table. */ static void classes_remove(int classid, void *obj) { classtable_t *ctab; classref_t *cref; classref_t **crefp; gidispatch_rock_t objrock; if (classid < 0 || classid >= num_classes) return; ctab = git_classes[classid]; objrock = gidispatch_get_objrock(obj, classid); cref = objrock.ptr; if (!cref) return; crefp = &(ctab->bucket[cref->bucknum]); for (; *crefp; crefp = &((*crefp)->next)) { if ((*crefp) == cref) { *crefp = cref->next; cref->obj = NULL; cref->id = 0; cref->next = NULL; glulx_free(cref); return; } } return; }
/* git_find_id_for_schannel(): Return the ID of a given Glk schannel. */ glui32 git_find_id_for_schannel(schanid_t schan) { gidispatch_rock_t objrock; if (!schan) return 0; objrock = gidispatch_get_objrock(schan, gidisp_Class_Schannel); return ((classref_t *)objrock.ptr)->id; }
/* git_find_id_for_fileref(): Return the ID of a given Glk fileref. */ glui32 git_find_id_for_fileref(frefid_t fref) { gidispatch_rock_t objrock; if (!fref) return 0; objrock = gidispatch_get_objrock(fref, gidisp_Class_Fileref); return ((classref_t *)objrock.ptr)->id; }
/* git_find_id_for_stream(): Return the ID of a given Glk stream. */ glui32 git_find_id_for_stream(strid_t str) { gidispatch_rock_t objrock; if (!str) return 0; objrock = gidispatch_get_objrock(str, gidisp_Class_Stream); return ((classref_t *)objrock.ptr)->id; }
/* git_find_id_for_window(): Return the ID of a given Glk window. */ glui32 git_find_id_for_window(winid_t win) { gidispatch_rock_t objrock; if (!win) return 0; objrock = gidispatch_get_objrock(win, gidisp_Class_Window); return ((classref_t *)objrock.ptr)->id; }
static void release_temp_ptr_array(void **arr, glui32 addr, glui32 len, int objclass, int passout) { arrayref_t *arref = NULL; arrayref_t **aptr; glui32 ix, val, addr2; if (arr) { for (aptr=(&arrays); (*aptr); aptr=(&((*aptr)->next))) { if ((*aptr)->array == arr) break; } arref = *aptr; if (!arref) fatalError("Unable to re-find array argument in Glk call."); if (arref->addr != addr || arref->len != len) fatalError("Mismatched array argument in Glk call."); if (arref->retained) { return; } *aptr = arref->next; arref->next = NULL; if (passout) { for (ix=0, addr2=addr; ix<len; ix++, addr2+=4) { void *opref = arr[ix]; if (opref) { gidispatch_rock_t objrock = gidispatch_get_objrock(opref, objclass); val = ((classref_t *)objrock.ptr)->id; } else { val = 0; } memWrite32(addr2, val); } } glulx_free(arr); glulx_free(arref); } }
void Glulxe::unparse_glk_args(dispatch_splot_t *splot, const char **proto, int depth, int *argnumptr, uint subaddress, int subpassout) { const char *cx; int ix, argx; int gargnum, numwanted; void *opref; gluniversal_t *garglist; uint *varglist; garglist = splot->garglist; varglist = splot->varglist; gargnum = *argnumptr; cx = *proto; numwanted = 0; while (*cx >= '0' && *cx <= '9') { numwanted = 10 * numwanted + (*cx - '0'); cx++; } for (argx = 0, ix = 0; argx < numwanted; argx++, ix++) { char typeclass; int skipval; int isref, passin, passout, nullok, isarray, isretained, isreturn; cx = read_prefix(cx, &isref, &isarray, &passin, &passout, &nullok, &isretained, &isreturn); typeclass = *cx; cx++; skipval = false; if (isref) { if (!isreturn && varglist[ix] == 0) { if (!nullok) error("Zero passed invalidly to Glk function."); garglist[gargnum]._ptrflag = false; gargnum++; skipval = true; } else { garglist[gargnum]._ptrflag = true; gargnum++; } } if (!skipval) { uint thisval = 0; if (typeclass == '[') { unparse_glk_args(splot, &cx, depth + 1, &gargnum, varglist[ix], passout); } else if (isarray) { /* definitely isref */ switch (typeclass) { case 'C': ReleaseCArray((char *)garglist[gargnum]._array, varglist[ix], varglist[ix + 1], passout); gargnum++; ix++; gargnum++; cx++; break; case 'I': ReleaseIArray((uint *)garglist[gargnum]._array, varglist[ix], varglist[ix + 1], passout); gargnum++; ix++; gargnum++; cx++; break; case 'Q': ReleasePtrArray((void **)garglist[gargnum]._array, varglist[ix], varglist[ix + 1], (*cx - 'a'), passout); gargnum++; ix++; gargnum++; cx++; break; default: error("Illegal format string."); break; } } else { /* a plain value or a reference to one. */ if (isreturn || (depth > 0 && subpassout) || (isref && passout)) { skipval = false; } else { skipval = true; } switch (typeclass) { case 'I': if (!skipval) { if (*cx == 'u') thisval = (uint)garglist[gargnum]._uint; else if (*cx == 's') thisval = (uint)garglist[gargnum]._sint; else error("Illegal format string."); } gargnum++; cx++; break; case 'Q': if (!skipval) { opref = garglist[gargnum]._opaqueref; if (opref) { gidispatch_rock_t objrock = gidispatch_get_objrock(opref, *cx - 'a'); assert(objrock.ptr); thisval = ((classref_t *)objrock.ptr)->id; } else { thisval = 0; } } gargnum++; cx++; break; case 'C': if (!skipval) { if (*cx == 'u') thisval = (uint)garglist[gargnum]._uch; else if (*cx == 's') thisval = (uint)garglist[gargnum]._sch; else if (*cx == 'n') thisval = (uint)garglist[gargnum]._ch; else error("Illegal format string."); } gargnum++; cx++; break; case 'S': if (garglist[gargnum]._charstr) ReleaseVMString(garglist[gargnum]._charstr); gargnum++; break; #ifdef GLK_MODULE_UNICODE case 'U': if (garglist[gargnum]._unicharstr) ReleaseVMUstring(garglist[gargnum]._unicharstr); gargnum++; break; #endif /* GLK_MODULE_UNICODE */ default: error("Illegal format string."); break; } if (isreturn) { *(splot->retval) = thisval; } else if (depth > 0) { /* Definitely not isref or isarray. */ if (subpassout) WriteStructField(subaddress, ix, thisval); } else if (isref) { if (passout) WriteMemory(varglist[ix], thisval); } } } else { /* We got a null reference, so we have to skip the format element. */ if (typeclass == '[') { int numsubwanted, refdepth; numsubwanted = 0; while (*cx >= '0' && *cx <= '9') { numsubwanted = 10 * numsubwanted + (*cx - '0'); cx++; } refdepth = 1; while (refdepth > 0) { if (*cx == '[') refdepth++; else if (*cx == ']') refdepth--; cx++; } } else if (typeclass == 'S' || typeclass == 'U') { /* leave it */ } else { cx++; if (isarray) ix++; } } } if (depth > 0) { if (*cx != ']') error("Illegal format string."); cx++; } else { if (*cx != ':' && *cx != '\0') error("Illegal format string."); } *proto = cx; *argnumptr = gargnum; }