/* Copyright (c) 1993 Stephen F. White */
#include <stdio.h>
#include "config.h"
#include "cool.h"
#include "proto.h"
#include "sys_proto.h"
#include "db_setup.h"
static void unpack_methods(Object *o, FILE *f);
static Verbdef *unpack_verbs(FILE *f);
static void unpack_gvars(Object *o, FILE *f);
static Vardef *unpack_vars(FILE *f);
static void unpack_symbols(Object *o, FILE *f);
static Lock *unpack_locks(FILE *f);
static Var unpack_var(FILE *f);
static String *unpack_string(FILE *f);
static List *unpack_list(FILE *f);
#define UNPACK(N, f) fread( (GENPTR) &(N), sizeof(N), 1, f)
Object *
unpack_object(FILE *f)
{
Object *o = new_object();
UNPACK(o->id.id, f);
UNPACK(o->id.server, f);
o->parents = unpack_list(f);
unpack_symbols(o, f);
unpack_methods(o, f);
o->verbs = unpack_verbs(f);
unpack_gvars(o, f);
o->locks = unpack_locks(f);
return o;
}
static void
unpack_methods(Object *o, FILE *f)
{
int i, nmethods;
Method *m;
unsigned char flag;
UNPACK(nmethods, f);
if (nmethods == 0) return;
o->methods = hash_new(nmethods / HASH_INIT_LOAD);
for (i = 0; i < nmethods; i++) {
m = MALLOC(Method, 1);
UNPACK(m->name, f);
UNPACK(flag, f);
m->blocked = flag;
UNPACK(m->ninst, f);
fread((char *) m->ehandler, sizeof(m->ehandler[0]), NERRS, f);
m->vars = unpack_vars(f);
if (m->ninst > 0) {
m->code = MALLOC(Inst, m->ninst);
fread( (GENPTR) m->code, sizeof(Inst), m->ninst, f);
} /* if */
m->ref = 1;
m->next = 0;
add_method(o, m);
} /* for */
}
static Verbdef *
unpack_verbs(FILE *f)
{
int nverbs;
Verbdef *vb, *prev = 0, *head = 0;
UNPACK(nverbs, f);
while (nverbs--) {
vb = MALLOC(Verbdef, 1);
UNPACK(vb->verb, f);
UNPACK(vb->prep, f);
UNPACK(vb->method, f);
vb->next = 0;
if (prev) {
prev->next = vb;
} else {
head = vb;
}
prev = vb;
}
return head;
}
static void
unpack_gvars(Object *o, FILE *f)
{
int nvars, name;
UNPACK(nvars, f);
if (!nvars) return;
o->vars = hash_new(nvars / HASH_INIT_LOAD);
while (nvars--) {
UNPACK(name, f);
var_add_global(o, name, unpack_var(f));
}
}
static Vardef *
unpack_vars(FILE *f)
{
int nvars = 0;
Vardef *v, *prev = 0, *head = 0;
UNPACK(nvars, f);
while(nvars--) {
v = MALLOC(Vardef, 1);
UNPACK(v->name, f);
v->value = unpack_var(f);
v->next = 0;
if (prev) {
prev->next = v;
} else {
head = v;
}
prev = v;
}
return head;
}
static Var
unpack_var(FILE *f)
{
Var v;
v.type = (Type_spec) fgetc(f);
switch (v.type) {
case STR:
v.v.str = unpack_string(f);
break;
case NUM:
UNPACK(v.v.num, f);
break;
case OBJ:
UNPACK(v.v.obj.id, f);
UNPACK(v.v.obj.server, f);
break;
case LIST:
v.v.list = unpack_list(f);
break;
case ERR:
UNPACK(v.v.err, f);
break;
case PC: /* should never happen */
break;
}
return v;
}
static String *
unpack_string(FILE *f)
{
String *s;
int len;
UNPACK(len, f);
s = string_new(len + 1);
fread(s->str, sizeof(char), len, f);
s->str[len] = '\0';
s->len = len;
return s;
}
static List *
unpack_list(FILE *f)
{
int i;
List *list = MALLOC(List, 1);
UNPACK(list->len, f);
list->mem = list->len;
if (list->len > 0) {
list->el = MALLOC(Var, list->len);
}
for (i = 0; i < list->len; i++) {
list->el[i] = unpack_var(f);
}
list->ref = 1;
return list;
}
static void
unpack_symbols(Object *o, FILE *f)
{
int i;
UNPACK(o->nsymb, f);
UNPACK(o->st_size, f);
if (o->st_size > 0) {
o->symbols = MALLOC(Symbol, o->st_size);
}
for (i = 0; i < o->nsymb; i++) {
UNPACK(o->symbols[i].ref, f);
if (o->symbols[i].ref) {
o->symbols[i].s = unpack_string(f);
}
}
}
static Lock *
unpack_locks(FILE *f)
{
Lock *l, *prev = 0, *head = 0;
int nlocks = 0;
UNPACK(nlocks, f);
while (nlocks--) {
l = MALLOC(Lock, 1);
l->name = unpack_string(f);
UNPACK(l->added_by, f);
l->next = 0;
if (prev) {
prev->next = l;
} else {
head = l;
}
prev = l;
}
return head;
}