/* Copyright (c) 1993 Stephen F. White */ #include "cool.h" #include "proto.h" #include "netio.h" #include "servers.h" static int dbtop (void); static void set_dbtop (int newdbtop); static void free_vars (Object * o, Vardef * v); static void store_malloc (void *where, int size); static void delete_malloc (void *where); Object *new_object (void) { Object *o = MALLOC (Object, 1); o->id.server = 0; o->id.id = -1; o->ref = 1; o->parents = 0; o->locks = 0; o->vars = 0; o->verbs = 0; o->symbols = 0; o->methods = 0; o->st_size = 0; o->methods = 0; o->last_search = -1; return o; } Object *clone (Objid pid) { Object *o; int top; if (pid.server != 0 || pid.id < 0) { return 0; } else { top = dbtop () + 1; set_dbtop (top); o = new_object (); o->id.server = 0; o->id.id = top; sym_init (o); o->parents = list_new (1); o->parents->el[0].type = OBJ; o->parents->el[0].v.obj = pid; assign_object (o->id, o); return o; } } int destroy (Objid oid) { if (!valid (oid)) { return 1; } else { cache_del (oid.id, 0); return 0; } } static int dbtop (void) { Var top; if (sys_get_global ("dbtop", &top) != E_NONE) { return 0; } else if (top.type != NUM) { writelog (); fprintf (stderr, "#%d.dbtop non-numeric\n", SYS_OBJ); return 0; } else { return top.v.num; } } static void set_dbtop (int newdbtop) { Var v; v.type = NUM; v.v.num = newdbtop; sys_assign_global ("dbtop", v); } void assign_object (Objid oid, Object * new) { Object *old; if (oid.server != 0 || oid.id < 0) { return; } if ((old = retrieve (oid))) { old->ref++; /* save old obj till we're done */ cache_put (new, oid.id); /* put in new one */ var_copy_vars (old, new); /* copy vars from old to new */ free_object (old); /* really free old one */ } else { cache_put (new, oid.id); } if (oid.id > dbtop ()) { set_dbtop (oid.id); } } static void free_vars (Object * o, Vardef * v) { Vardef *vnext; if (!v) { return; } for (; v; v = vnext) { vnext = v->next; sym_free (o, v->name); var_free (v->value); FREE (v); } } void free_method (Object * o, Method * m) { if (--m->ref) { return; } sym_free (o, m->name); free_vars (o, m->vars); opcode_free_symbols (o, m); if (m->code) { FREE (m->code); } FREE (m); } void free_object (Object * o) { Method *m, *mnext; Verbdef *vb, *vbnext; int i, hval; if (--o->ref) { /* if refcount is nonzero, */ return; /* don't free object */ } if (o->parents) { list_free (o->parents); } if (o->methods) { for (hval = 0; hval < o->methods->size; hval++) { for (m = o->methods->table[hval]; m; m = mnext) { mnext = m->next; free_method (o, m); } } FREE (o->methods); } for (vb = o->verbs; vb; vb = vbnext) { vbnext = vb->next; sym_free (o, vb->verb); if (vb->prep >= 0) { sym_free (o, vb->prep); } sym_free (o, vb->method); FREE (vb); } if (o->vars) { for (hval = 0; hval < o->vars->size; hval++) { free_vars (o, o->vars->table[hval]); } FREE (o->vars); } if (o->symbols) { for (i = 0; i < o->nsymb; i++) { if (o->symbols[i].ref > 0) { string_free (o->symbols[i].s); } } FREE (o->symbols); } FREE (o); } struct mem_tbl { void *where; int size; struct mem_tbl *next; }; struct mem_tbl *sm_head; static void store_malloc (void *where, int size) { struct mem_tbl *s; s = (struct mem_tbl *) malloc (sizeof (struct mem_tbl)); s->where = where; s->size = size; s->next = sm_head; sm_head = s; } static void delete_malloc (void *where) { struct mem_tbl *s, *t; if (where == sm_head->where) { s = sm_head; sm_head = sm_head->next; free ((void *) s); return; } for (s = sm_head; s->next; s = s->next) { if (s->next->where == where) { t = s->next; s->next = s->next->next; free ((void *) t); return; } } writelog (); fprintf (stderr, "MALLOC: non-malloc'ed memory freed at 0x%x!\n", (int) where); #ifndef WIN32 kill(getpid(), SIGQUIT); #else WIN32CLEANUP exit(1); #endif } static int chunks = 0; const char *check_malloc (void) { struct mem_tbl *s; static char buf[80]; #ifdef DEBUG_MALLOC int total = 0; for (s = sm_head; s; s = s->next) { total += s->size; } sprintf (buf, "%d bytes used in %d chunks.", total, chunks); #else sprintf (buf, "%d chunks of memory allocated.", chunks); #endif return buf; } void *cool_malloc (unsigned size) { void *memptr; memptr = (void *) malloc (size); if (!memptr) { writelog (); fprintf (stderr, "MALLOC (size %d bytes) failed!\n", size); #ifndef WIN32 kill(getpid(), SIGQUIT); #else WIN32CLEANUP exit(1); #endif } #ifdef DEBUG_MALLOC store_malloc (memptr, size); #endif chunks++; return memptr; } void cool_free (void *ptr) { #ifdef DEBUG_MALLOC delete_malloc (ptr); #endif free ((void *) ptr); chunks--; } void write_object (FILE * f, Objid oid); static char *written; void write_flatfile (const char *dbfile, const char *dumpfile) { FILE *f; Objid oid; int top; init (dbfile, 0, 1); top = dbtop (); if (!strcmp (dumpfile, "-")) { f = stdout; } else { f = fopen (dumpfile, "wb"); if (!f) { writelog (); perror (dumpfile); return; } /* if */ } /* if */ written = MALLOC (char, top + 1); if (!written) return; oid.server = 0; for (oid.id = 0; oid.id <= top; oid.id++) written[oid.id] = 0; for (oid.id = 0; oid.id <= top; oid.id++) { write_object (f, oid); cache_reset (); } /* for */ FREE (written); fclose (f); shutdown_server (); } /* write_flatfile */ void write_object (FILE * f, Objid oid) { String *listing; int i; Object *o = retrieve (oid); if (!o || written[oid.id]) return; for (i = 0; i < o->parents->len; i++) { if (o->parents->el[i].v.obj.id > oid.id) { write_object (f, o->parents->el[i].v.obj); } /* if */ } /* for */ listing = decompile_object (o); listing = string_strip_cr (listing); fputs (listing->str, f); string_free (listing); written[oid.id] = 1; }