/* * NAME: data->free_call_out() * DESCRIPTION: free a callout */ static void d_free_call_out(dataspace *data, unsigned int handle) { dcallout *co; value *v; uindex n; co = &data->callouts[handle - 1]; v = co->val; switch (co->nargs) { default: del_lhs(data, &v[3]); i_del_value(&v[3]); case 2: del_lhs(data, &v[2]); i_del_value(&v[2]); case 1: del_lhs(data, &v[1]); i_del_value(&v[1]); case 0: del_lhs(data, &v[0]); str_del(v[0].u.string); break; } v[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; }
/* * NAME: copatch->del() * DESCRIPTION: delete a callout patch */ static void cop_del(dataplane *plane, copatch **c, bool del) { copatch *cop; dcallout *co; int i; value *v; coptable *tab; /* remove from hash table */ cop = *c; *c = cop->next; if (del) { /* free referenced callout */ co = (cop->type == COP_ADD) ? &cop->aco : &cop->rco; v = co->val; for (i = (co->nargs > 3) ? 4 : co->nargs + 1; i > 0; --i) { i_del_value(v++); } } /* add to free list */ tab = plane->coptab; cop->next = tab->flist; tab->flist = cop; }
/* * NAME: data->assign_elt() * DESCRIPTION: assign a value to an array element */ void d_assign_elt(dataspace *data, array *arr, value *elt, value *val) { if (data->plane->level != arr->primary->data->plane->level) { /* * bring dataspace of imported array up to the current plane level */ d_new_plane(arr->primary->data, data->plane->level); } data = arr->primary->data; if (arr->primary->plane != data->plane) { /* * backup array's current elements */ arr_backup(&data->plane->achunk, arr); if (arr->primary->arr != (array *) NULL) { arr->primary->plane = data->plane; } else { arr->primary = &data->plane->alocal; } } if (arr->primary->arr != (array *) NULL) { /* * the array is in the loaded dataspace of some object */ if ((arr->primary->ref & ARR_MOD) == 0) { arr->primary->ref |= ARR_MOD; data->plane->flags |= MOD_ARRAY; } ref_rhs(data, val); del_lhs(data, elt); } else { if (T_INDEXED(val->type) && data != val->u.array->primary->data) { /* mark as imported */ if (data->plane->imports++ == 0 && ifirst != data && data->iprev == (dataspace *) NULL) { /* add to imports list */ data->iprev = (dataspace *) NULL; data->inext = ifirst; if (ifirst != (dataspace *) NULL) { ifirst->iprev = data; } ifirst = data; } } if (T_INDEXED(elt->type) && data != elt->u.array->primary->data) { /* mark as unimported */ data->plane->imports--; } } i_ref_value(val); i_del_value(elt); *elt = *val; elt->modified = TRUE; }
/* * NAME: copatch->release() * DESCRIPTION: remove a callout replacement */ static void cop_release(copatch *cop) { int i; value *v; cop->type = COP_REMOVE; for (i = (cop->aco.nargs > 3) ? 4 : cop->aco.nargs + 1, v = cop->aco.val; i > 0; --i) { i_del_value(v++); } }
/* * NAME: copatch->commit() * DESCRIPTION: commit a callout replacement */ static void cop_commit(copatch *cop) { int i; value *v; cop->type = COP_ADD; for (i = (cop->rco.nargs > 3) ? 4 : cop->rco.nargs + 1, v = cop->rco.val; i > 0; --i) { i_del_value(v++); } }
/* * NAME: path->ed_write() * DESCRIPTION: resolve an editor write file path */ char *path_ed_write(char *buf, char *file) { frame *f; f = cframe; if (OBJR(f->oindex)->flags & O_DRIVER) { return path_resolve(buf, file); } else { PUSH_STRVAL(f, str_new(file, (long) strlen(file))); call_driver_object(f, "path_write", 1); if (f->sp->type != T_STRING) { i_del_value(f->sp++); return (char *) NULL; } path_resolve(buf, f->sp->u.string->text); str_del((f->sp++)->u.string); return buf; } }
/* * NAME: data->assign_var() * DESCRIPTION: assign a value to a variable */ void d_assign_var(dataspace *data, value *var, value *val) { if (var >= data->variables && var < data->variables + data->nvariables) { if (data->plane->level != 0 && data->plane->original == (value *) NULL) { /* * back up variables */ i_copy(data->plane->original = ALLOC(value, data->nvariables), data->variables, data->nvariables); } ref_rhs(data, val); del_lhs(data, var); data->plane->flags |= MOD_VARIABLE; } i_ref_value(val); i_del_value(var); *var = *val; var->modified = TRUE; }
/* * NAME: data->discard_plane() * DESCRIPTION: discard the current data plane without committing it */ void d_discard_plane(Int level) { dataplane *p; dataspace *data; value *v; Uint i; for (p = plist; p != (dataplane *) NULL && p->level == level; p = p->plist) { /* * discard changes except for callout mods */ p->prev->flags |= p->flags & (MOD_CALLOUT | MOD_NEWCALLOUT); data = p->alocal.data; if (p->original != (value *) NULL) { /* restore original variable values */ for (v = data->variables, i = data->nvariables; i != 0; --i, v++) { i_del_value(v); } memcpy(data->variables, p->original, data->nvariables * sizeof(value)); FREE(p->original); } if (p->coptab != (coptable *) NULL) { /* undo callout changes */ discard_callouts(p); if (p->prev == &data->base) { cop_clean(p); } else { p->prev->coptab = p->coptab; } } arr_discard(&p->achunk); if (p->arrays != (arrref *) NULL) { arrref *a; /* delete new array refs */ for (a = p->arrays, i = data->narrays; i != 0; a++, --i) { if (a->arr != (array *) NULL) { arr_del(a->arr); } } FREE(p->arrays); /* fix old ones */ for (a = p->prev->arrays, i = data->narrays; i != 0; a++, --i) { if (a->arr != (array *) NULL) { a->arr->primary = a; } } } if (p->strings != (strref *) NULL) { strref *s; /* delete new string refs */ for (s = p->strings, i = data->nstrings; i != 0; s++, --i) { if (s->str != (string *) NULL) { str_del(s->str); } } FREE(p->strings); /* fix old ones */ for (s = p->prev->strings, i = data->nstrings; i != 0; s++, --i) { if (s->str != (string *) NULL) { s->str->primary = s; } } } data->plane = p->prev; plist = p->plist; FREE(p); } }
/* * NAME: data->commit_plane() * DESCRIPTION: commit the current data plane */ void d_commit_plane(Int level, value *retval) { dataplane *p, *commit, **r, **cr; dataspace *data; value *v; Uint i; dataplane *clist; /* * pass 1: construct commit planes */ clist = (dataplane *) NULL; cr = &clist; for (r = &plist, p = *r; p != (dataplane *) NULL && p->level == level; r = &p->plist, p = *r) { if (p->prev->level != level - 1) { /* insert commit plane */ commit = ALLOC(dataplane, 1); commit->level = level - 1; commit->original = (value *) NULL; commit->alocal.arr = (array *) NULL; commit->alocal.plane = commit; commit->alocal.data = p->alocal.data; commit->alocal.state = AR_CHANGED; commit->arrays = p->arrays; commit->achunk = p->achunk; commit->strings = p->strings; commit->coptab = p->coptab; commit->prev = p->prev; *cr = commit; cr = &commit->plist; p->prev = commit; } else { p->flags |= PLANE_MERGE; } } if (clist != (dataplane *) NULL) { /* insert commit planes in plane list */ *cr = p; *r = clist; } clist = *r; /* sentinel */ /* * pass 2: commit */ for (p = plist; p != clist; p = p->plist) { /* * commit changes to previous plane */ data = p->alocal.data; if (p->original != (value *) NULL) { if (p->level == 1 || p->prev->original != (value *) NULL) { /* free backed-up variable values */ for (v = p->original, i = data->nvariables; i != 0; v++, --i) { i_del_value(v); } FREE(p->original); } else { /* move originals to previous plane */ p->prev->original = p->original; } commit_values(data->variables, data->nvariables, level - 1); } if (p->coptab != (coptable *) NULL) { /* commit callout changes */ commit_callouts(p, p->flags & PLANE_MERGE); if (p->level == 1) { cop_clean(p); } else { p->prev->coptab = p->coptab; } } arr_commit(&p->achunk, p->prev, p->flags & PLANE_MERGE); if (p->flags & PLANE_MERGE) { if (p->arrays != (arrref *) NULL) { arrref *a; /* remove old array refs */ for (a = p->prev->arrays, i = data->narrays; i != 0; a++, --i) { if (a->arr != (array *) NULL) { if (a->arr->primary == &p->alocal) { a->arr->primary = &p->prev->alocal; } arr_del(a->arr); } } FREE(p->prev->arrays); p->prev->arrays = p->arrays; } if (p->strings != (strref *) NULL) { strref *s; /* remove old string refs */ for (s = p->prev->strings, i = data->nstrings; i != 0; s++, --i) { if (s->str != (string *) NULL) { str_del(s->str); } } FREE(p->prev->strings); p->prev->strings = p->strings; } } } commit_values(retval, 1, level - 1); /* * pass 3: deallocate */ for (p = plist; p != clist; p = plist) { p->prev->flags = (p->flags & MOD_ALL) | MOD_SAVE; p->prev->schange = p->schange; p->prev->achange = p->achange; p->prev->imports = p->imports; p->alocal.data->plane = p->prev; plist = p->plist; FREE(p); } }