From a19a216bc60160c162e616145ef091dd18ce4e61 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Tue, 16 Feb 2021 14:40:46 -0600 Subject: Python 0.9.1 as posted in alt.sources --- src/amoebamodule.c | 774 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 774 insertions(+) create mode 100644 src/amoebamodule.c (limited to 'src/amoebamodule.c') diff --git a/src/amoebamodule.c b/src/amoebamodule.c new file mode 100644 index 0000000..c9131b7 --- /dev/null +++ b/src/amoebamodule.c @@ -0,0 +1,774 @@ +/*********************************************************** +Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The +Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +/* Amoeba module implementation */ + +/* Amoeba includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* C includes */ +#include +#include + +/* POSIX includes */ +#include +#include +#include + +/* Python includes */ +#include "allobjects.h" +#include "modsupport.h" +#include "sc_global.h" +#include "stubcode.h" + +extern char *err_why(); +extern char *ar_cap(); + +#define STUBCODE "+stubcode" + +static object *AmoebaError; +object *StubcodeError; + +static object *sc_dict; + +/* Module initialization */ + +extern struct methodlist amoeba_methods[]; /* Forward */ +extern object *convertcapv(); /* Forward */ + +static void +ins(d, name, v) + object *d; + char *name; + object *v; +{ + if (v == NULL || dictinsert(d, name, v) != 0) + fatal("can't initialize amoeba module"); +} + +void +initamoeba() +{ + object *m, *d, *v; + + m = initmodule("amoeba", amoeba_methods); + d = getmoduledict(m); + + /* Define capv */ + v = convertcapv(); + ins(d, "capv", v); + DECREF(v); + + /* Set timeout */ + timeout((interval)2000); + + /* Initialize amoeba.error exception */ + AmoebaError = newstringobject("amoeba.error"); + ins(d, "error", AmoebaError); + StubcodeError = newstringobject("amoeba.stubcode_error"); + ins(d, "stubcode_error", StubcodeError); + sc_dict = newdictobject(); +} + + +/* Set an Amoeba-specific error, and return NULL */ + +object * +amoeba_error(err) + errstat err; +{ + object *v = newtupleobject(2); + if (v != NULL) { + settupleitem(v, 0, newintobject((long)err)); + settupleitem(v, 1, newstringobject(err_why(err))); + } + err_setval(AmoebaError, v); + if (v != NULL) + DECREF(v); + return NULL; +} + + +/* Capability object implementation */ + +extern typeobject Captype; /* Forward */ + +#define is_capobject(v) ((v)->ob_type == &Captype) + +typedef struct { + OB_HEAD + capability ob_cap; +} capobject; + +object * +newcapobject(cap) + capability *cap; +{ + capobject *v = NEWOBJ(capobject, &Captype); + if (v == NULL) + return NULL; + v->ob_cap = *cap; + return (object *)v; +} + +getcapability(v, cap) + object *v; + capability *cap; +{ + + if (!is_capobject(v)) + return err_badarg(); + *cap = ((capobject *)v)->ob_cap; + return 0; +} + +/* + * is_capobj exports the is_capobject macro to the stubcode modules + */ + +int +is_capobj(v) + object *v; +{ + + return is_capobject(v); +} + +/* Methods */ + +static void +capprint(v, fp, flags) + capobject *v; + FILE *fp; + int flags; +{ + /* XXX needs lock when multi-threading */ + fputs(ar_cap(&v->ob_cap), fp); +} + +static object * +caprepr(v) + capobject *v; +{ + /* XXX needs lock when multi-threading */ + return newstringobject(ar_cap(&v->ob_cap)); +} + +extern object *sc_interpreter(); + +extern struct methodlist cap_methods[]; /* Forward */ + +object * +sc_makeself(cap, stubcode, name) + object *cap, *stubcode; + char *name; +{ + object *sc_name, *sc_self; + + sc_name = newstringobject(name); + if (sc_name == NULL) + return NULL; + sc_self = newtupleobject(3); + if (sc_self == NULL) { + DECREF(sc_name); + return NULL; + } + if (settupleitem(sc_self, NAME, sc_name) != 0) { + DECREF(sc_self); + return NULL; + } + INCREF(cap); + if (settupleitem(sc_self, CAP, cap) != 0) { + DECREF(sc_self); + return NULL; + } + INCREF(stubcode); + if (settupleitem(sc_self, STUBC, stubcode) != 0) { + DECREF(sc_self); + return NULL; + } + return sc_self; +} + + +static void +swapcode(code, len) + char *code; + int len; +{ + int i = sizeof(TscOperand); + TscOpcode opcode; + TscOperand operand; + + while (i < len) { + memcpy(&opcode, &code[i], sizeof(TscOpcode)); + SwapOpcode(opcode); + memcpy(&code[i], &opcode, sizeof(TscOpcode)); + i += sizeof(TscOpcode); + if (opcode & OPERAND) { + memcpy(&operand, &code[i], sizeof(TscOperand)); + SwapOperand(operand); + memcpy(&code[i], &operand, sizeof(TscOperand)); + i += sizeof(TscOperand); + } + } +} + +object * +sc_findstubcode(v, name) + object *v; + char *name; +{ + int fd, fsize; + char *fname, *buffer; + struct stat statbuf; + object *sc_stubcode, *ret; + TscOperand sc_magic; + + /* + * Only look in the current directory for now. + */ + fname = malloc(strlen(name) + 4); + if (fname == NULL) { + return err_nomem(); + } + sprintf(fname, "%s.sc", name); + if ((fd = open(fname, O_RDONLY)) == -1) { + extern int errno; + + if (errno == 2) { + /* + ** errno == 2 is file not found. + */ + err_setstr(NameError, fname); + return NULL; + } + free(fname); + return err_errno(newstringobject(name)); + } + fstat(fd, &statbuf); + fsize = (int)statbuf.st_size; + buffer = malloc(fsize); + if (buffer == NULL) { + free(fname); + close(fd); + return err_nomem(); + } + if (read(fd, buffer, fsize) != fsize) { + close(fd); + free(fname); + return err_errno(newstringobject(name)); + } + close(fd); + free(fname); + memcpy(&sc_magic, buffer, sizeof(TscOperand)); + if (sc_magic != SC_MAGIC) { + SwapOperand(sc_magic); + if (sc_magic != SC_MAGIC) { + free(buffer); + return NULL; + } else { + swapcode(buffer, fsize); + } + } + sc_stubcode = newsizedstringobject( &buffer[sizeof(TscOperand)], + fsize - sizeof(TscOperand)); + free(buffer); + if (sc_stubcode == NULL) { + return NULL; + } + if (dictinsert(sc_dict, name, sc_stubcode) != 0) { + DECREF(sc_stubcode); + return NULL; + } + DECREF(sc_stubcode); /* XXXX */ + sc_stubcode = sc_makeself(v, sc_stubcode, name); + if (sc_stubcode == NULL) { + return NULL; + } + return sc_stubcode; +} + +object * +capgetattr(v, name) + capobject *v; + char *name; +{ + object *sc_method, *sc_stubcodemethod; + + if (sc_dict == NULL) { + /* + ** For some reason the dictionary has not been + ** initialized. Try to find one of the built in + ** methods. + */ + return findmethod(cap_methods, (object *)v, name); + } + sc_stubcodemethod = dictlookup(sc_dict, name); + if (sc_stubcodemethod != NULL) { + /* + ** There is a stubcode method in the dictionary. + ** Execute the stubcode interpreter with the right + ** arguments. + */ + object *self, *ret; + + self = sc_makeself((object *)v, sc_stubcodemethod, name); + if (self == NULL) { + return NULL; + } + ret = findmethod(cap_methods, self, STUBCODE); + DECREF(self); + return ret; + } + err_clear(); + sc_method = findmethod(cap_methods, (object *)v, name); + if (sc_method == NULL) { + /* + ** The method is not built in and not in the + ** dictionary. Try to find it as a stubcode file. + */ + object *self, *ret; + + err_clear(); + self = sc_findstubcode((object *)v, name); + if (self == NULL) { + return NULL; + } + ret = findmethod(cap_methods, self, STUBCODE); + DECREF(self); + return ret; + } + return sc_method; +} + +int +capcompare(v, w) + capobject *v, *w; +{ + int cmp = bcmp((char *)&v->ob_cap.cap_port, + (char *)&w->ob_cap, PORTSIZE); + if (cmp != 0) + return cmp; + return prv_number(&v->ob_cap.cap_priv) - + prv_number(&w->ob_cap.cap_priv); +} + +static typeobject Captype = { + OB_HEAD_INIT(&Typetype) + 0, + "capability", + sizeof(capobject), + 0, + free, /*tp_dealloc*/ + capprint, /*tp_print*/ + capgetattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + capcompare, /*tp_comp +are*/ + caprepr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; + + +/* Return a dictionary corresponding to capv */ + +extern struct caplist *capv; + +static object * +convertcapv() +{ + object *d; + struct caplist *c; + d = newdictobject(); + if (d == NULL) + return NULL; + if (capv == NULL) + return d; + for (c = capv; c->cl_name != NULL; c++) { + object *v = newcapobject(c->cl_cap); + if (v == NULL || dictinsert(d, c->cl_name, v) != 0) { + DECREF(d); + return NULL; + } + DECREF(v); + } + return d; +} + + +/* Strongly Amoeba-specific argument handlers */ + +static int +getcaparg(v, a) + object *v; + capability *a; +{ + if (v == NULL || !is_capobject(v)) + return err_badarg(); + *a = ((capobject *)v) -> ob_cap; + return 1; +} + +static int +getstrcapargs(v, a, b) + object *v; + object **a; + capability *b; +{ + if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) + return err_badarg(); + return getstrarg(gettupleitem(v, 0), a) && + getcaparg(gettupleitem(v, 1), b); +} + + +/* Amoeba methods */ + +static object * +amoeba_name_lookup(self, args) + object *self; + object *args; +{ + object *name; + capability cap; + errstat err; + if (!getstrarg(args, &name)) + return NULL; + err = name_lookup(getstringvalue(name), &cap); + if (err != STD_OK) + return amoeba_error(err); + return newcapobject(&cap); +} + +static object * +amoeba_name_append(self, args) + object *self; + object *args; +{ + object *name; + capability cap; + errstat err; + if (!getstrcapargs(args, &name, &cap)) + return NULL; + err = name_append(getstringvalue(name), &cap); + if (err != STD_OK) + return amoeba_error(err); + INCREF(None); + return None; +} + +static object * +amoeba_name_replace(self, args) + object *self; + object *args; +{ + object *name; + capability cap; + errstat err; + if (!getstrcapargs(args, &name, &cap)) + return NULL; + err = name_replace(getstringvalue(name), &cap); + if (err != STD_OK) + return amoeba_error(err); + INCREF(None); + return None; +} + +static object * +amoeba_name_delete(self, args) + object *self; + object *args; +{ + object *name; + errstat err; + if (!getstrarg(args, &name)) + return NULL; + err = name_delete(getstringvalue(name)); + if (err != STD_OK) + return amoeba_error(err); + INCREF(None); + return None; +} + +static object * +amoeba_timeout(self, args) + object *self; + object *args; +{ + int i; + object *v; + interval tout; + if (!getintarg(args, &i)) + return NULL; + tout = timeout((interval)i); + v = newintobject((long)tout); + if (v == NULL) + timeout(tout); + return v; +} + +static struct methodlist amoeba_methods[] = { + {"name_append", amoeba_name_append}, + {"name_delete", amoeba_name_delete}, + {"name_lookup", amoeba_name_lookup}, + {"name_replace", amoeba_name_replace}, + {"timeout", amoeba_timeout}, + {NULL, NULL} /* Sentinel */ +}; + +/* Capability methods */ + +static object * +cap_b_size(self, args) + capobject *self; + object *args; +{ + errstat err; + b_fsize size; + if (!getnoarg(args)) + return NULL; + err = b_size(&self->ob_cap, &size); + if (err != STD_OK) + return amoeba_error(err); + return newintobject((long)size); +} + +static object * +cap_b_read(self, args) + capobject *self; + object *args; +{ + errstat err; + char *buf; + object *v; + long offset, size; + b_fsize nread; + if (!getlonglongargs(args, &offset, &size)) + return NULL; + buf = malloc((unsigned int)size); + if (buf == NULL) { + return err_nomem(); + } + err = b_read(&self->ob_cap, (b_fsize)offset, buf, (b_fsize)size, + &nread); + if (err != STD_OK) { + free(buf); + return amoeba_error(err); + } + v = newsizedstringobject(buf, (int)nread); + free(buf); + return v; +} + +static object * +cap_dir_lookup(self, args) + capobject *self; + object *args; +{ + object *name; + capability cap; + errstat err; + if (!getstrarg(args, &name)) + return NULL; + err = dir_lookup(&self->ob_cap, getstringvalue(name), &cap); + if (err != STD_OK) + return amoeba_error(err); + return newcapobject(&cap); +} + +static object * +cap_dir_append(self, args) + capobject *self; + object *args; +{ + object *name; + capability cap; + errstat err; + if (!getstrcapargs(args, &name, &cap)) + return NULL; + err = dir_append(&self->ob_cap, getstringvalue(name), &cap); + if (err != STD_OK) + return amoeba_error(err); + INCREF(None); + return None; +} + +static object * +cap_dir_delete(self, args) + capobject *self; + object *args; +{ + object *name; + errstat err; + if (!getstrarg(args, &name)) + return NULL; + err = dir_delete(&self->ob_cap, getstringvalue(name)); + if (err != STD_OK) + return amoeba_error(err); + INCREF(None); + return None; +} + +static object * +cap_dir_replace(self, args) + capobject *self; + object *args; +{ + object *name; + capability cap; + errstat err; + if (!getstrcapargs(args, &name, &cap)) + return NULL; + err = dir_replace(&self->ob_cap, getstringvalue(name), &cap); + if (err != STD_OK) + return amoeba_error(err); + INCREF(None); + return None; +} + +static object * +cap_dir_list(self, args) + capobject *self; + object *args; +{ + errstat err; + struct dir_open *dd; + object *d; + char *name; + if (!getnoarg(args)) + return NULL; + if ((dd = dir_open(&self->ob_cap)) == NULL) + return amoeba_error(STD_COMBAD); + if ((d = newlistobject(0)) == NULL) { + dir_close(dd); + return NULL; + } + while ((name = dir_next(dd)) != NULL) { + object *v; + v = newstringobject(name); + if (v == NULL) { + DECREF(d); + d = NULL; + break; + } + if (addlistitem(d, v) != 0) { + DECREF(v); + DECREF(d); + d = NULL; + break; + } + DECREF(v); + } + dir_close(dd); + return d; +} + +object * +cap_std_info(self, args) + capobject *self; + object *args; +{ + char buf[256]; + errstat err; + int n; + if (!getnoarg(args)) + return NULL; + err = std_info(&self->ob_cap, buf, sizeof buf, &n); + if (err != STD_OK) + return amoeba_error(err); + return newsizedstringobject(buf, n); +} + +object * +cap_tod_gettime(self, args) + capobject *self; + object *args; +{ + header h; + errstat err; + bufsize n; + long sec; + int msec, tz, dst; + if (!getnoarg(args)) + return NULL; + h.h_port = self->ob_cap.cap_port; + h.h_priv = self->ob_cap.cap_priv; + h.h_command = TOD_GETTIME; + n = trans(&h, NILBUF, 0, &h, NILBUF, 0); + if (ERR_STATUS(n)) + return amoeba_error(ERR_CONVERT(n)); + tod_decode(&h, &sec, &msec, &tz, &dst); + return newintobject(sec); +} + +object * +cap_tod_settime(self, args) + capobject *self; + object *args; +{ + header h; + errstat err; + bufsize n; + long sec; + if (!getlongarg(args, &sec)) + return NULL; + h.h_port = self->ob_cap.cap_port; + h.h_priv = self->ob_cap.cap_priv; + h.h_command = TOD_SETTIME; + tod_encode(&h, sec, 0, 0, 0); + n = trans(&h, NILBUF, 0, &h, NILBUF, 0); + if (ERR_STATUS(n)) + return amoeba_error(ERR_CONVERT(n)); + INCREF(None); + return None; +} + +static struct methodlist cap_methods[] = { + { STUBCODE, sc_interpreter}, + {"b_read", cap_b_read}, + {"b_size", cap_b_size}, + {"dir_append", cap_dir_append}, + {"dir_delete", cap_dir_delete}, + {"dir_list", cap_dir_list}, + {"dir_lookup", cap_dir_lookup}, + {"dir_replace", cap_dir_replace}, + {"std_info", cap_std_info}, + {"tod_gettime", cap_tod_gettime}, + {"tod_settime", cap_tod_settime}, + {NULL, NULL} /* Sentinel */ +}; -- cgit v1.2.3