/* * NAME: del_lhs() * DESCRIPTION: delete the left-hand side in an assignment */ static void del_lhs(dataspace *data, value *lhs) { string *str; array *arr; switch (lhs->type) { case T_STRING: str = lhs->u.string; if (str->primary != (strref *) NULL && str->primary->data == data) { /* in this object */ if (--(str->primary->ref) == 0) { str->primary->str = (string *) NULL; str->primary = (strref *) NULL; str_del(str); data->plane->schange++; /* last reference removed */ } data->plane->flags |= MOD_STRINGREF; } else { /* not in this object: deref imported string */ data->plane->schange--; } break; case T_ARRAY: case T_MAPPING: case T_LWOBJECT: arr = lhs->u.array; if (arr->primary->data == data) { /* in this object */ if (arr->primary->arr != (array *) NULL) { /* swapped in */ data->plane->flags |= MOD_ARRAYREF; if ((--(arr->primary->ref) & ~ARR_MOD) == 0) { d_get_elts(arr); arr->primary->arr = (array *) NULL; arr->primary = &arr->primary->plane->alocal; arr_del(arr); data->plane->achange++; } } else { /* deref new array */ data->plane->achange--; } } else { /* not in this object: deref imported array */ data->plane->imports--; data->plane->achange--; } break; } }
/* * NAME: path->include() * DESCRIPTION: resolve an include path */ char *path_include(char *buf, char *from, char *file, string ***strs, int *nstr) { frame *f; int i; value *v; string **str; *strs = NULL; *nstr = 0; if (c_autodriver()) { return path_from(buf, from, file); } f = cframe; PUSH_STRVAL(f, str_new(from, strlen(from))); PUSH_STRVAL(f, str_new(file, (long) strlen(file))); if (!call_driver_object(f, "include_file", 2)) { f->sp++; return path_from(buf, from, file); } if (f->sp->type == T_STRING) { /* simple path */ path_resolve(buf, f->sp->u.string->text); str_del((f->sp++)->u.string); return buf; } else if (f->sp->type == T_ARRAY) { /* * Array of strings. Check that the array does indeed contain only * strings, then return it. */ i = f->sp->u.array->size; if (i != 0) { v = d_get_elts(f->sp->u.array); while ((v++)->type == T_STRING) { if (--i == 0) { *nstr = i = f->sp->u.array->size; str = ALLOC(string*, i); do { str_ref(*str++ = (--v)->u.string); } while (--i != 0); *strs = str; arr_del((f->sp++)->u.array); /* return the untranslated path, as well */ return path_from(buf, from, file); } }
/* * NAME: data->list_callouts() * DESCRIPTION: list all call_outs in an object */ array *d_list_callouts(dataspace *host, dataspace *data) { uindex n, count, size; dcallout *co; value *v, *v2, *elts; array *list, *a; uindex max_args; xfloat flt; if (data->ncallouts == 0) { return arr_new(host, 0L); } if (data->callouts == (dcallout *) NULL) { d_get_callouts(data); } /* get the number of callouts in this object */ count = data->ncallouts; for (n = data->fcallouts; n != 0; n = data->callouts[n - 1].co_next) { --count; } if (count > conf_array_size()) { return (array *) NULL; } list = arr_new(host, (long) count); elts = list->elts; max_args = conf_array_size() - 3; for (co = data->callouts; count > 0; co++) { if (co->val[0].type == T_STRING) { size = co->nargs; if (size > max_args) { /* unlikely, but possible */ size = max_args; } a = arr_new(host, size + 3L); v = a->elts; /* handle */ PUT_INTVAL(v, co - data->callouts + 1); v++; /* function */ PUT_STRVAL(v, co->val[0].u.string); v++; /* time */ if (co->mtime == 0xffff) { PUT_INTVAL(v, co->time); } else { flt.low = co->time; flt.high = co->mtime; PUT_FLTVAL(v, flt); } v++; /* copy arguments */ switch (size) { case 3: *v++ = co->val[3]; case 2: *v++ = co->val[2]; case 1: *v++ = co->val[1]; case 0: break; default: n = size - 2; for (v2 = d_get_elts(co->val[3].u.array) + n; n > 0; --n) { *v++ = *--v2; } *v++ = co->val[2]; *v++ = co->val[1]; break; } while (size > 0) { i_ref_value(--v); --size; } d_ref_imports(a); /* put in list */ PUT_ARRVAL(elts, a); elts++; --count; } } co_list(list); return list; }
/* * NAME: data->get_call_out() * DESCRIPTION: get a callout */ string *d_get_call_out(dataspace *data, unsigned int handle, frame *f, int *nargs) { string *str; dcallout *co; value *v, *o; uindex n; if (data->callouts == (dcallout *) NULL) { d_get_callouts(data); } co = &data->callouts[handle - 1]; v = co->val; del_lhs(data, &v[0]); str = v[0].u.string; i_grow_stack(f, (*nargs = co->nargs) + 1); *--f->sp = v[0]; switch (co->nargs) { case 3: del_lhs(data, &v[3]); *--f->sp = v[3]; case 2: del_lhs(data, &v[2]); *--f->sp = v[2]; case 1: del_lhs(data, &v[1]); *--f->sp = v[1]; case 0: break; default: n = co->nargs - 2; f->sp -= n; memcpy(f->sp, d_get_elts(v[3].u.array), n * sizeof(value)); del_lhs(data, &v[3]); FREE(v[3].u.array->elts); v[3].u.array->elts = (value *) NULL; arr_del(v[3].u.array); del_lhs(data, &v[2]); *--f->sp = v[2]; del_lhs(data, &v[1]); *--f->sp = v[1]; break; } /* wipe out destructed objects */ for (n = co->nargs, v = f->sp; n > 0; --n, v++) { switch (v->type) { case T_OBJECT: if (DESTRUCTED(v)) { *v = nil_value; } break; case T_LWOBJECT: o = d_get_elts(v->u.array); if (o->type == T_OBJECT && DESTRUCTED(o)) { arr_del(v->u.array); *v = nil_value; } break; } } co->val[0] = nil_value; n = data->fcallouts; if (n != 0) { data->callouts[n - 1].co_prev = handle; } co->co_next = n; data->fcallouts = handle; data->plane->flags |= MOD_CALLOUT; return str; }