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; }
int glkunix_startup_code(glkunix_startup_t *data) { /* It turns out to be more convenient if we return TRUE from here, even when an error occurs, and display an error in glk_main(). */ int ix; char *filename = NULL; char *gameinfofilename = NULL; int gameinfoloaded = FALSE; unsigned char buf[12]; int res; #ifdef GARGLK char *cx; #endif #ifdef GARGLK garglk_set_program_name("Glulxe 0.5.2"); garglk_set_program_info("Glulxe 0.5.2 by Andrew Plotkin"); #endif /* Parse out the arguments. They've already been checked for validity, and the library-specific ones stripped out. As usual for Unix, the zeroth argument is the executable name. */ for (ix=1; ix<data->argc; ix++) { #if VM_PROFILING if (!strcmp(data->argv[ix], "--profile")) { ix++; if (ix<data->argc) { strid_t profstr = glkunix_stream_open_pathname_gen(data->argv[ix], TRUE, FALSE, 1); if (!profstr) { init_err = "Unable to open profile output file."; init_err2 = data->argv[ix]; return TRUE; } setup_profile(profstr, NULL); } continue; } if (!strcmp(data->argv[ix], "--profcalls")) { profile_set_call_counts(TRUE); continue; } #endif /* VM_PROFILING */ #if VM_DEBUGGER if (!strcmp(data->argv[ix], "--gameinfo")) { ix++; if (ix<data->argc) { gameinfofilename = data->argv[ix]; } continue; } if (!strcmp(data->argv[ix], "--cpu")) { debugger_track_cpu(TRUE); continue; } if (!strcmp(data->argv[ix], "--starttrap")) { debugger_set_start_trap(TRUE); continue; } if (!strcmp(data->argv[ix], "--quittrap")) { debugger_set_quit_trap(TRUE); continue; } if (!strcmp(data->argv[ix], "--crashtrap")) { debugger_set_crash_trap(TRUE); continue; } #endif /* VM_DEBUGGER */ if (filename) { init_err = "You must supply exactly one game file."; return TRUE; } filename = data->argv[ix]; } if (!filename) { init_err = "You must supply the name of a game file."; return TRUE; } gamefile = glkunix_stream_open_pathname(filename, FALSE, 1); if (!gamefile) { init_err = "The game file could not be opened."; init_err2 = filename; return TRUE; } #ifdef GARGLK cx = strrchr(data->argv[1], '/'); if (!cx) cx = strrchr(data->argv[1], '\\'); garglk_set_story_name(cx ? cx + 1 : data->argv[1]); #endif #if VM_DEBUGGER if (gameinfofilename) { strid_t debugstr = glkunix_stream_open_pathname_gen(gameinfofilename, FALSE, FALSE, 1); if (!debugstr) { nonfatal_warning("Unable to open gameinfo file for debug data."); } else { int bres = debugger_load_info_stream(debugstr); glk_stream_close(debugstr, NULL); if (!bres) nonfatal_warning("Unable to parse game info."); else gameinfoloaded = TRUE; } } /* Report debugging available, whether a game info file is loaded or not. */ gidebug_debugging_available(debugger_cmd_handler, debugger_cycle_handler); #endif /* VM_DEBUGGER */ /* Now we have to check to see if it's a Blorb file. */ glk_stream_set_position(gamefile, 0, seekmode_Start); res = glk_get_buffer_stream(gamefile, (char *)buf, 12); if (!res) { init_err = "The data in this stand-alone game is too short to read."; return TRUE; } if (buf[0] == 'G' && buf[1] == 'l' && buf[2] == 'u' && buf[3] == 'l') { /* Load game directly from file. */ locate_gamefile(FALSE); return TRUE; } else if (buf[0] == 'F' && buf[1] == 'O' && buf[2] == 'R' && buf[3] == 'M' && buf[8] == 'I' && buf[9] == 'F' && buf[10] == 'R' && buf[11] == 'S') { /* Load game from a chunk in the Blorb file. */ locate_gamefile(TRUE); #if VM_DEBUGGER /* Load the debug info from the Blorb, if it wasn't loaded from a file. */ if (!gameinfoloaded) { glui32 giblorb_ID_Dbug = giblorb_make_id('D', 'b', 'u', 'g'); giblorb_err_t err; giblorb_result_t blorbres; err = giblorb_load_chunk_by_type(giblorb_get_resource_map(), giblorb_method_FilePos, &blorbres, giblorb_ID_Dbug, 0); if (!err) { int bres = debugger_load_info_chunk(gamefile, blorbres.data.startpos, blorbres.length); if (!bres) nonfatal_warning("Unable to parse game info."); else gameinfoloaded = TRUE; } } #endif /* VM_DEBUGGER */ return TRUE; } else { init_err = "This is neither a Glulx game file nor a Blorb file " "which contains one."; return TRUE; } }