diff options
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/classobject.c | 268 | ||||
-rw-r--r-- | Objects/fileobject.c | 267 | ||||
-rw-r--r-- | Objects/floatobject.c | 240 | ||||
-rw-r--r-- | Objects/funcobject.c | 101 | ||||
-rw-r--r-- | Objects/intobject.c | 250 | ||||
-rw-r--r-- | Objects/listobject.c | 482 | ||||
-rw-r--r-- | Objects/methodobject.c | 113 | ||||
-rw-r--r-- | Objects/moduleobject.c | 130 | ||||
-rw-r--r-- | Objects/object.c | 195 | ||||
-rw-r--r-- | Objects/stringobject.c | 328 | ||||
-rw-r--r-- | Objects/tupleobject.c | 276 | ||||
-rw-r--r-- | Objects/typeobject.c | 47 | ||||
-rw-r--r-- | Objects/xxobject.c | 94 |
13 files changed, 2791 insertions, 0 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c new file mode 100644 index 0000000..9a55280 --- /dev/null +++ b/Objects/classobject.c @@ -0,0 +1,268 @@ +/* Class object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "node.h" +#include "object.h" +#include "stringobject.h" +#include "tupleobject.h" +#include "dictobject.h" +#include "funcobject.h" +#include "classobject.h" +#include "objimpl.h" + +typedef struct { + OB_HEAD + node *cl_tree; /* The entire classdef parse tree */ + object *cl_bases; /* A tuple */ + object *cl_methods; /* A dictionary */ +} classobject; + +object * +newclassobject(tree, bases, methods) + node *tree; + object *bases; /* NULL or tuple of classobjects! */ + object *methods; +{ + classobject *op; + op = NEWOBJ(classobject, &Classtype); + if (op == NULL) + return NULL; + op->cl_tree = tree; + if (bases != NULL) + INCREF(bases); + op->cl_bases = bases; + INCREF(methods); + op->cl_methods = methods; + return (object *) op; +} + +/* Class methods */ + +static void +class_dealloc(op) + classobject *op; +{ + int i; + if (op->cl_bases != NULL) + DECREF(op->cl_bases); + DECREF(op->cl_methods); + free((ANY *)op); +} + +static object * +class_getattr(op, name) + register classobject *op; + register char *name; +{ + register object *v; + v = dictlookup(op->cl_methods, name); + if (v != NULL) { + INCREF(v); + return v; + } + if (op->cl_bases != NULL) { + int n = gettuplesize(op->cl_bases); + int i; + for (i = 0; i < n; i++) { + v = class_getattr(gettupleitem(op->cl_bases, i), name); + if (v != NULL) + return v; + } + } + errno = ESRCH; + return NULL; +} + +typeobject Classtype = { + OB_HEAD_INIT(&Typetype) + 0, + "class", + sizeof(classobject), + 0, + class_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + class_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; + + +/* We're not done yet: next, we define class member objects... */ + +typedef struct { + OB_HEAD + classobject *cm_class; /* The class object */ + object *cm_attr; /* A dictionary */ +} classmemberobject; + +object * +newclassmemberobject(class) + register object *class; +{ + register classmemberobject *cm; + if (!is_classobject(class)) { + errno = EINVAL; + return NULL; + } + cm = NEWOBJ(classmemberobject, &Classmembertype); + if (cm == NULL) + return NULL; + INCREF(class); + cm->cm_class = (classobject *)class; + cm->cm_attr = newdictobject(); + if (cm->cm_attr == NULL) { + DECREF(cm); + return NULL; + } + return (object *)cm; +} + +/* Class member methods */ + +static void +classmember_dealloc(cm) + register classmemberobject *cm; +{ + DECREF(cm->cm_class); + if (cm->cm_attr != NULL) + DECREF(cm->cm_attr); + free((ANY *)cm); +} + +static object * +classmember_getattr(cm, name) + register classmemberobject *cm; + register char *name; +{ + register object *v = dictlookup(cm->cm_attr, name); + if (v != NULL) { + INCREF(v); + return v; + } + v = class_getattr(cm->cm_class, name); + if (v == NULL) + return v; /* class_getattr() has set errno */ + if (is_funcobject(v)) { + object *w = newclassmethodobject(v, (object *)cm); + DECREF(v); + return w; + } + DECREF(v); + errno = ESRCH; + return NULL; +} + +static int +classmember_setattr(cm, name, v) + classmemberobject *cm; + char *name; + object *v; +{ + if (v == NULL) + return dictremove(cm->cm_attr, name); + else + return dictinsert(cm->cm_attr, name, v); +} + +typeobject Classmembertype = { + OB_HEAD_INIT(&Typetype) + 0, + "class member", + sizeof(classmemberobject), + 0, + classmember_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + classmember_getattr, /*tp_getattr*/ + classmember_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; + + +/* And finally, here are class method objects */ +/* (Really methods of class members) */ + +typedef struct { + OB_HEAD + object *cm_func; /* The method function */ + object *cm_self; /* The object to which this applies */ +} classmethodobject; + +object * +newclassmethodobject(func, self) + object *func; + object *self; +{ + register classmethodobject *cm; + if (!is_funcobject(func)) { + errno = EINVAL; + return NULL; + } + cm = NEWOBJ(classmethodobject, &Classmethodtype); + if (cm == NULL) + return NULL; + INCREF(func); + cm->cm_func = func; + INCREF(self); + cm->cm_self = self; + return (object *)cm; +} + +object * +classmethodgetfunc(cm) + register object *cm; +{ + if (!is_classmethodobject(cm)) { + errno = EINVAL; + return NULL; + } + return ((classmethodobject *)cm)->cm_func; +} + +object * +classmethodgetself(cm) + register object *cm; +{ + if (!is_classmethodobject(cm)) { + errno = EINVAL; + return NULL; + } + return ((classmethodobject *)cm)->cm_self; +} + +/* Class method methods */ + +static void +classmethod_dealloc(cm) + register classmethodobject *cm; +{ + DECREF(cm->cm_func); + DECREF(cm->cm_self); + free((ANY *)cm); +} + +typeobject Classmethodtype = { + OB_HEAD_INIT(&Typetype) + 0, + "class method", + sizeof(classmethodobject), + 0, + classmethod_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; diff --git a/Objects/fileobject.c b/Objects/fileobject.c new file mode 100644 index 0000000..4879620 --- /dev/null +++ b/Objects/fileobject.c @@ -0,0 +1,267 @@ +/* File object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "stringobject.h" +#include "intobject.h" +#include "fileobject.h" +#include "methodobject.h" +#include "objimpl.h" + +typedef struct { + OB_HEAD + FILE *f_fp; + object *f_name; + object *f_mode; + /* XXX Should move the 'need space' on printing flag here */ +} fileobject; + +FILE * +getfilefile(f) + object *f; +{ + if (!is_fileobject(f)) { + errno = EBADF; + return NULL; + } + return ((fileobject *)f)->f_fp; +} + +object * +newopenfileobject(fp, name, mode) + FILE *fp; + char *name; + char *mode; +{ + fileobject *f = NEWOBJ(fileobject, &Filetype); + if (f == NULL) + return NULL; + f->f_fp = NULL; + f->f_name = newstringobject(name); + f->f_mode = newstringobject(mode); + if (f->f_name == NULL || f->f_mode == NULL) { + DECREF(f); + errno = ENOMEM; + return NULL; + } + f->f_fp = fp; + return (object *) f; +} + +object * +newfileobject(name, mode) + char *name, *mode; +{ + fileobject *f; + FILE *fp; + f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode); + if (f == NULL) + return NULL; + if ((f->f_fp = fopen(name, mode)) == NULL) { + DECREF(f); + return NULL; + } + return (object *)f; +} + +/* Methods */ + +static void +filedealloc(f) + fileobject *f; +{ + if (f->f_fp != NULL) + fclose(f->f_fp); + if (f->f_name != NULL) + DECREF(f->f_name); + if (f->f_mode != NULL) + DECREF(f->f_mode); + free((char *)f); +} + +static void +fileprint(f, fp, flags) + fileobject *f; + FILE *fp; + int flags; +{ + fprintf(fp, "<%s file ", f->f_fp == NULL ? "closed" : "open"); + printobject(f->f_name, fp, flags); + fprintf(fp, ", mode "); + printobject(f->f_mode, fp, flags); + fprintf(fp, ">"); +} + +static object * +filerepr(f) + fileobject *f; +{ + char buf[300]; + /* XXX This differs from fileprint if the filename contains + quotes or other funny characters. */ + sprintf(buf, "<%s file '%.256s', mode '%.10s'>", + f->f_fp == NULL ? "closed" : "open", + getstringvalue(f->f_name), + getstringvalue(f->f_mode)); + return newstringobject(buf); +} + +static object * +fileclose(f, args) + fileobject *f; + object *args; +{ + if (args != NULL) { + errno = EINVAL; + return NULL; + } + if (f->f_fp != NULL) { + fclose(f->f_fp); + f->f_fp = NULL; + } + INCREF(None); + return None; +} + +static object * +fileread(f, args) + fileobject *f; + object *args; +{ + int n; + object *v; + if (f->f_fp == NULL) { + errno = EBADF; + return NULL; + } + if (args == NULL || !is_intobject(args)) { + errno = EINVAL; + return NULL; + } + n = getintvalue(args); + if (n <= 0 /* || n > 0x7fff /*XXX*/ ) { + errno = EDOM; + return NULL; + } + v = newsizedstringobject((char *)NULL, n); + if (v == NULL) { + errno = ENOMEM; + return NULL; + } + n = fread(getstringvalue(v), 1, n, f->f_fp); + /* EOF is reported as an empty string */ + /* XXX should detect real I/O errors? */ + resizestring(&v, n); + return v; +} + +/* XXX Should this be unified with raw_input()? */ + +static object * +filereadline(f, args) + fileobject *f; + object *args; +{ + int n; + object *v; + if (f->f_fp == NULL) { + errno = EBADF; + return NULL; + } + if (args == NULL) { + n = 10000; /* XXX should really be unlimited */ + } + else if (is_intobject(args)) { + n = getintvalue(args); + if (n < 0 || n > 0x7fff /*XXX*/ ) { + errno = EDOM; + return NULL; + } + } + else { + errno = EINVAL; + return NULL; + } + v = newsizedstringobject((char *)NULL, n); + if (v == NULL) { + errno = ENOMEM; + return NULL; + } + if (fgets(getstringvalue(v), n+1, f->f_fp) == NULL) { + /* EOF is reported as an empty string */ + /* XXX should detect real I/O errors? */ + n = 0; + } + else { + n = strlen(getstringvalue(v)); + } + resizestring(&v, n); + return v; +} + +static object * +filewrite(f, args) + fileobject *f; + object *args; +{ + int n, n2; + if (f->f_fp == NULL) { + errno = EBADF; + return NULL; + } + if (args == NULL || !is_stringobject(args)) { + errno = EINVAL; + return NULL; + } + errno = 0; + n2 = fwrite(getstringvalue(args), 1, n = getstringsize(args), f->f_fp); + if (n2 != n) { + if (errno == 0) + errno = EIO; + return NULL; + } + INCREF(None); + return None; +} + +static struct methodlist { + char *ml_name; + method ml_meth; +} filemethods[] = { + {"write", filewrite}, + {"read", fileread}, + {"readline", filereadline}, + {"close", fileclose}, + {NULL, NULL} /* sentinel */ +}; + +static object * +filegetattr(f, name) + fileobject *f; + char *name; +{ + struct methodlist *ml = filemethods; + for (; ml->ml_name != NULL; ml++) { + if (strcmp(name, ml->ml_name) == 0) + return newmethodobject(ml->ml_name, ml->ml_meth, + (object *)f); + } + errno = ESRCH; + return NULL; +} + +typeobject Filetype = { + OB_HEAD_INIT(&Typetype) + 0, + "file", + sizeof(fileobject), + 0, + filedealloc, /*tp_dealloc*/ + fileprint, /*tp_print*/ + filegetattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + filerepr, /*tp_repr*/ +}; diff --git a/Objects/floatobject.c b/Objects/floatobject.c new file mode 100644 index 0000000..f176333 --- /dev/null +++ b/Objects/floatobject.c @@ -0,0 +1,240 @@ +/* Float object implementation */ + +#include <stdio.h> +#include <math.h> +#include <ctype.h> + +#include "PROTO.h" +#include "object.h" +#include "floatobject.h" +#include "stringobject.h" +#include "objimpl.h" + +object * +newfloatobject(fval) + double fval; +{ + /* For efficiency, this code is copied from newobject() */ + register floatobject *op = (floatobject *) malloc(sizeof(floatobject)); + if (op == NULL) { + errno = ENOMEM; + } + else { + NEWREF(op); + op->ob_type = &Floattype; + op->ob_fval = fval; + } + return (object *) op; +} + +double +getfloatvalue(op) + object *op; +{ + if (!is_floatobject(op)) { + errno = EBADF; + return -1; + } + else + return ((floatobject *)op) -> ob_fval; +} + +/* Methods */ + +static void +float_buf_repr(buf, v) + char *buf; + floatobject *v; +{ + register char *cp; + /* Subroutine for float_repr and float_print. + We want float numbers to be recognizable as such, + i.e., they should contain a decimal point or an exponent. + However, %g may print the number as an integer; + in such cases, we append ".0" to the string. */ + sprintf(buf, "%.12g", v->ob_fval); + cp = buf; + if (*cp == '-') + cp++; + for (; *cp != '\0'; cp++) { + /* Any non-digit means it's not an integer; + this takes care of NAN and INF as well. */ + if (!isdigit(*cp)) + break; + } + if (*cp == '\0') { + *cp++ = '.'; + *cp++ = '0'; + *cp++ = '\0'; + } +} + +static void +float_print(v, fp, flags) + floatobject *v; + FILE *fp; + int flags; +{ + char buf[100]; + float_buf_repr(buf, v); + fputs(buf, fp); +} + +static object * +float_repr(v) + floatobject *v; +{ + char buf[100]; + float_buf_repr(buf, v); + return newstringobject(buf); +} + +static int +float_compare(v, w) + floatobject *v, *w; +{ + double i = v->ob_fval; + double j = w->ob_fval; + return (i < j) ? -1 : (i > j) ? 1 : 0; +} + +static object * +float_add(v, w) + floatobject *v; + object *w; +{ + if (!is_floatobject(w)) { + errno = EINVAL; + return NULL; + } + return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval); +} + +static object * +float_sub(v, w) + floatobject *v; + object *w; +{ + if (!is_floatobject(w)) { + errno = EINVAL; + return NULL; + } + return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval); +} + +static object * +float_mul(v, w) + floatobject *v; + object *w; +{ + if (!is_floatobject(w)) { + errno = EINVAL; + return NULL; + } + return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval); +} + +static object * +float_div(v, w) + floatobject *v; + object *w; +{ + if (!is_floatobject(w)) { + errno = EINVAL; + return NULL; + } + if (((floatobject *)w) -> ob_fval == 0) { + errno = EDOM; + return NULL; + } + return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval); +} + +static object * +float_rem(v, w) + floatobject *v; + object *w; +{ + double wx; + extern double fmod(); + if (!is_floatobject(w)) { + errno = EINVAL; + return NULL; + } + wx = ((floatobject *)w) -> ob_fval; + if (wx == 0.0) { + errno = EDOM; + return NULL; + } + return newfloatobject(fmod(v->ob_fval, wx)); +} + +static object * +float_pow(v, w) + floatobject *v; + object *w; +{ + double iv, iw, ix; + extern double pow(); + if (!is_floatobject(w)) { + errno = EINVAL; + return NULL; + } + iv = v->ob_fval; + iw = ((floatobject *)w)->ob_fval; + errno = 0; + ix = pow(iv, iw); + if (errno != 0) + return NULL; + else + return newfloatobject(ix); +} + +static object * +float_neg(v) + floatobject *v; +{ + return newfloatobject(-v->ob_fval); +} + +static object * +float_pos(v) + floatobject *v; +{ + return newfloatobject(v->ob_fval); +} + +static number_methods float_as_number = { + float_add, /*tp_add*/ + float_sub, /*tp_subtract*/ + float_mul, /*tp_multiply*/ + float_div, /*tp_divide*/ + float_rem, /*tp_remainder*/ + float_pow, /*tp_power*/ + float_neg, /*tp_negate*/ + float_pos, /*tp_plus*/ +}; + +typeobject Floattype = { + OB_HEAD_INIT(&Typetype) + 0, + "float", + sizeof(floatobject), + 0, + free, /*tp_dealloc*/ + float_print, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + float_compare, /*tp_compare*/ + float_repr, /*tp_repr*/ + &float_as_number, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; + +/* +XXX This is not enough. Need: +- automatic casts for mixed arithmetic (3.1 * 4) +- mixed comparisons (!) +- look at other uses of ints that could be extended to floats +*/ diff --git a/Objects/funcobject.c b/Objects/funcobject.c new file mode 100644 index 0000000..1c6f6a6 --- /dev/null +++ b/Objects/funcobject.c @@ -0,0 +1,101 @@ +/* Function object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "node.h" +#include "stringobject.h" +#include "funcobject.h" +#include "objimpl.h" +#include "token.h" + +typedef struct { + OB_HEAD + node *func_node; + object *func_globals; +} funcobject; + +object * +newfuncobject(n, globals) + node *n; + object *globals; +{ + funcobject *op = NEWOBJ(funcobject, &Functype); + if (op != NULL) { + op->func_node = n; + if (globals != NULL) + INCREF(globals); + op->func_globals = globals; + } + return (object *)op; +} + +node * +getfuncnode(op) + object *op; +{ + if (!is_funcobject(op)) { + errno = EBADF; + return NULL; + } + return ((funcobject *) op) -> func_node; +} + +object * +getfuncglobals(op) + object *op; +{ + if (!is_funcobject(op)) { + errno = EBADF; + return NULL; + } + return ((funcobject *) op) -> func_globals; +} + +/* Methods */ + +static void +funcdealloc(op) + funcobject *op; +{ + /* XXX free node? */ + DECREF(op->func_globals); + free((char *)op); +} + +static void +funcprint(op, fp, flags) + funcobject *op; + FILE *fp; + int flags; +{ + node *n = op->func_node; + n = CHILD(n, 1); + fprintf(fp, "<user function %s>", STR(n)); +} + +static object * +funcrepr(op) + funcobject *op; +{ + char buf[100]; + node *n = op->func_node; + n = CHILD(n, 1); + sprintf(buf, "<user function %.80s>", STR(n)); + return newstringobject(buf); +} + +typeobject Functype = { + OB_HEAD_INIT(&Typetype) + 0, + "function", + sizeof(funcobject), + 0, + funcdealloc, /*tp_dealloc*/ + funcprint, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + funcrepr, /*tp_repr*/ +}; diff --git a/Objects/intobject.c b/Objects/intobject.c new file mode 100644 index 0000000..7a69238 --- /dev/null +++ b/Objects/intobject.c @@ -0,0 +1,250 @@ +/* Integer object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "intobject.h" +#include "stringobject.h" +#include "objimpl.h" + +/* Standard Booleans */ +intobject FalseObject = { + OB_HEAD_INIT(&Inttype) + 0 +}; +intobject TrueObject = { + OB_HEAD_INIT(&Inttype) + 1 +}; + +object * +newintobject(ival) + long ival; +{ + /* For efficiency, this code is copied from newobject() */ + register intobject *op = (intobject *) malloc(sizeof(intobject)); + if (op == NULL) { + errno = ENOMEM; + } + else { + NEWREF(op); + op->ob_type = &Inttype; + op->ob_ival = ival; + } + return (object *) op; +} + +long +getintvalue(op) + register object *op; +{ + if (!is_intobject(op)) { + errno = EBADF; + return -1; + } + else + return ((intobject *)op) -> ob_ival; +} + +/* Methods */ + +static void +intprint(v, fp, flags) + intobject *v; + FILE *fp; + int flags; +{ + fprintf(fp, "%ld", v->ob_ival); +} + +static object * +intrepr(v) + intobject *v; +{ + char buf[20]; + sprintf(buf, "%ld", v->ob_ival); + return newstringobject(buf); +} + +static int +intcompare(v, w) + intobject *v, *w; +{ + register long i = v->ob_ival; + register long j = w->ob_ival; + return (i < j) ? -1 : (i > j) ? 1 : 0; +} + +static object * +intadd(v, w) + intobject *v; + register object *w; +{ + register long a, b, x; + if (!is_intobject(w)) { + errno = EINVAL; + return NULL; + } + a = v->ob_ival; + b = ((intobject *)w) -> ob_ival; + x = a + b; + if ((x^a) < 0 && (x^b) < 0) { + errno = ERANGE; + return NULL; + } + return newintobject(x); +} + +static object * +intsub(v, w) + intobject *v; + register object *w; +{ + register long a, b, x; + if (!is_intobject(w)) { + errno = EINVAL; + return NULL; + } + a = v->ob_ival; + b = ((intobject *)w) -> ob_ival; + x = a - b; + if ((x^a) < 0 && (x^~b) < 0) { + errno = ERANGE; + return NULL; + } + return newintobject(x); +} + +static object * +intmul(v, w) + intobject *v; + register object *w; +{ + register long a, b; + double x; + if (!is_intobject(w)) { + errno = EINVAL; + return NULL; + } + a = v->ob_ival; + b = ((intobject *)w) -> ob_ival; + x = (double)a * (double)b; + if (x > 0x7fffffff || x < (double) (long) 0x80000000) { + errno = ERANGE; + return NULL; + } + return newintobject(a * b); +} + +static object * +intdiv(v, w) + intobject *v; + register object *w; +{ + if (!is_intobject(w)) { + errno = EINVAL; + return NULL; + } + if (((intobject *)w) -> ob_ival == 0) { + errno = EDOM; + return NULL; + } + return newintobject(v->ob_ival / ((intobject *)w) -> ob_ival); +} + +static object * +intrem(v, w) + intobject *v; + register object *w; +{ + if (!is_intobject(w)) { + errno = EINVAL; + return NULL; + } + if (((intobject *)w) -> ob_ival == 0) { + errno = EDOM; + return NULL; + } + return newintobject(v->ob_ival % ((intobject *)w) -> ob_ival); +} + +static object * +intpow(v, w) + intobject *v; + register object *w; +{ + register long iv, iw, ix; + register int neg; + if (!is_intobject(w)) { + errno = EINVAL; + return NULL; + } + iv = v->ob_ival; + iw = ((intobject *)w)->ob_ival; + neg = 0; + if (iw < 0) + neg = 1, iw = -iw; + ix = 1; + for (; iw > 0; iw--) + ix = ix * iv; + if (neg) { + if (ix == 0) { + errno = EDOM; + return NULL; + } + ix = 1/ix; + } + /* XXX How to check for overflow? */ + return newintobject(ix); +} + +static object * +intneg(v) + intobject *v; +{ + register long a, x; + a = v->ob_ival; + x = -a; + if (a < 0 && x < 0) { + errno = ERANGE; + return NULL; + } + return newintobject(x); +} + +static object * +intpos(v) + intobject *v; +{ + INCREF(v); + return (object *)v; +} + +static number_methods int_as_number = { + intadd, /*tp_add*/ + intsub, /*tp_subtract*/ + intmul, /*tp_multiply*/ + intdiv, /*tp_divide*/ + intrem, /*tp_remainder*/ + intpow, /*tp_power*/ + intneg, /*tp_negate*/ + intpos, /*tp_plus*/ +}; + +typeobject Inttype = { + OB_HEAD_INIT(&Typetype) + 0, + "int", + sizeof(intobject), + 0, + free, /*tp_dealloc*/ + intprint, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + intcompare, /*tp_compare*/ + intrepr, /*tp_repr*/ + &int_as_number, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; diff --git a/Objects/listobject.c b/Objects/listobject.c new file mode 100644 index 0000000..0ee76d1 --- /dev/null +++ b/Objects/listobject.c @@ -0,0 +1,482 @@ +/* List object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "intobject.h" +#include "stringobject.h" +#include "tupleobject.h" +#include "methodobject.h" +#include "listobject.h" +#include "objimpl.h" +#include "modsupport.h" + +typedef struct { + OB_VARHEAD + object **ob_item; +} listobject; + +object * +newlistobject(size) + int size; +{ + int i; + listobject *op; + if (size < 0) { + errno = EINVAL; + return NULL; + } + op = (listobject *) malloc(sizeof(listobject)); + if (op == NULL) { + errno = ENOMEM; + return NULL; + } + if (size <= 0) { + op->ob_item = NULL; + } + else { + op->ob_item = (object **) malloc(size * sizeof(object *)); + if (op->ob_item == NULL) { + free((ANY *)op); + errno = ENOMEM; + return NULL; + } + } + NEWREF(op); + op->ob_type = &Listtype; + op->ob_size = size; + for (i = 0; i < size; i++) + op->ob_item[i] = NULL; + return (object *) op; +} + +int +getlistsize(op) + object *op; +{ + if (!is_listobject(op)) { + errno = EBADF; + return -1; + } + else + return ((listobject *)op) -> ob_size; +} + +object * +getlistitem(op, i) + object *op; + int i; +{ + if (!is_listobject(op)) { + errno = EBADF; + return NULL; + } + if (i < 0 || i >= ((listobject *)op) -> ob_size) { + errno = EDOM; + return NULL; + } + return ((listobject *)op) -> ob_item[i]; +} + +int +setlistitem(op, i, newitem) + register object *op; + register int i; + register object *newitem; +{ + register object *olditem; + if (!is_listobject(op)) { + if (newitem != NULL) + DECREF(newitem); + return errno = EBADF; + } + if (i < 0 || i >= ((listobject *)op) -> ob_size) { + if (newitem != NULL) + DECREF(newitem); + return errno = EDOM; + } + olditem = ((listobject *)op) -> ob_item[i]; + ((listobject *)op) -> ob_item[i] = newitem; + if (olditem != NULL) + DECREF(olditem); + return 0; +} + +static int +ins1(self, where, v) + listobject *self; + int where; + object *v; +{ + int i; + object **items; + if (v == NULL) + return errno = EINVAL; + items = self->ob_item; + RESIZE(items, object *, self->ob_size+1); + if (items == NULL) + return errno = ENOMEM; + if (where < 0) + where = 0; + if (where > self->ob_size) + where = self->ob_size; + for (i = self->ob_size; --i >= where; ) + items[i+1] = items[i]; + INCREF(v); + items[where] = v; + self->ob_item = items; + self->ob_size++; + return 0; +} + +int +inslistitem(op, where, newitem) + object *op; + int where; + object *newitem; +{ + if (!is_listobject(op)) + return errno = EBADF; + return ins1((listobject *)op, where, newitem); +} + +int +addlistitem(op, newitem) + object *op; + object *newitem; +{ + if (!is_listobject(op)) + return errno = EBADF; + return ins1((listobject *)op, + (int) ((listobject *)op)->ob_size, newitem); +} + +/* Methods */ + +static void +list_dealloc(op) + listobject *op; +{ + int i; + for (i = 0; i < op->ob_size; i++) { + if (op->ob_item[i] != NULL) + DECREF(op->ob_item[i]); + } + if (op->ob_item != NULL) + free((ANY *)op->ob_item); + free((ANY *)op); +} + +static void +list_print(op, fp, flags) + listobject *op; + FILE *fp; + int flags; +{ + int i; + fprintf(fp, "["); + for (i = 0; i < op->ob_size && !StopPrint; i++) { + if (i > 0) { + fprintf(fp, ", "); + } + printobject(op->ob_item[i], fp, flags); + } + fprintf(fp, "]"); +} + +object * +list_repr(v) + listobject *v; +{ + object *s, *t, *comma; + int i; + s = newstringobject("["); + comma = newstringobject(", "); + for (i = 0; i < v->ob_size && s != NULL; i++) { + if (i > 0) + joinstring(&s, comma); + t = reprobject(v->ob_item[i]); + joinstring(&s, t); + DECREF(t); + } + DECREF(comma); + t = newstringobject("]"); + joinstring(&s, t); + DECREF(t); + return s; +} + +static int +list_compare(v, w) + listobject *v, *w; +{ + int len = (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size; + int i; + for (i = 0; i < len; i++) { + int cmp = cmpobject(v->ob_item[i], w->ob_item[i]); + if (cmp != 0) + return cmp; + } + return v->ob_size - w->ob_size; +} + +static int +list_length(a) + listobject *a; +{ + return a->ob_size; +} + +static object * +list_item(a, i) + listobject *a; + int i; +{ + if (i < 0 || i >= a->ob_size) { + errno = EDOM; + return NULL; + } + INCREF(a->ob_item[i]); + return a->ob_item[i]; +} + +static object * +list_slice(a, ilow, ihigh) + listobject *a; + int ilow, ihigh; +{ + listobject *np; + int i; + if (ilow < 0) + ilow = 0; + else if (ilow > a->ob_size) + ilow = a->ob_size; + if (ihigh < 0) + ihigh = 0; + if (ihigh < ilow) + ihigh = ilow; + else if (ihigh > a->ob_size) + ihigh = a->ob_size; + np = (listobject *) newlistobject(ihigh - ilow); + if (np == NULL) + return NULL; + for (i = ilow; i < ihigh; i++) { + object *v = a->ob_item[i]; + INCREF(v); + np->ob_item[i - ilow] = v; + } + return (object *)np; +} + +static object * +list_concat(a, bb) + listobject *a; + object *bb; +{ + int size; + int i; + listobject *np; + if (!is_listobject(bb)) { + errno = EINVAL; + return NULL; + } +#define b ((listobject *)bb) + size = a->ob_size + b->ob_size; + np = (listobject *) newlistobject(size); + if (np == NULL) { + errno = ENOMEM; + return NULL; + } + for (i = 0; i < a->ob_size; i++) { + object *v = a->ob_item[i]; + INCREF(v); + np->ob_item[i] = v; + } + for (i = 0; i < b->ob_size; i++) { + object *v = b->ob_item[i]; + INCREF(v); + np->ob_item[i + a->ob_size] = v; + } + return (object *)np; +#undef b +} + +static int +list_ass_item(a, i, v) + listobject *a; + int i; + object *v; +{ + if (i < 0 || i >= a->ob_size) + return errno = EDOM; + if (v == NULL) + return list_ass_slice(a, i, i+1, v); + INCREF(v); + DECREF(a->ob_item[i]); + a->ob_item[i] = v; + return 0; +} + +static int +list_ass_slice(a, ilow, ihigh, v) + listobject *a; + int ilow, ihigh; + object *v; +{ + object **item; + int n; /* Size of replacement list */ + int d; /* Change in size */ + int k; /* Loop index */ +#define b ((listobject *)v) + if (v == NULL) + n = 0; + else if (is_listobject(v)) + n = b->ob_size; + else + return errno = EINVAL; + if (ilow < 0) + ilow = 0; + else if (ilow > a->ob_size) + ilow = a->ob_size; + if (ihigh < 0) + ihigh = 0; + if (ihigh < ilow) + ihigh = ilow; + else if (ihigh > a->ob_size) + ihigh = a->ob_size; + item = a->ob_item; + d = n - (ihigh-ilow); + if (d <= 0) { /* Delete -d items; DECREF ihigh-ilow items */ + for (k = ilow; k < ihigh; k++) + DECREF(item[k]); + if (d < 0) { + for (/*k = ihigh*/; k < a->ob_size; k++) + item[k+d] = item[k]; + a->ob_size += d; + RESIZE(item, object *, a->ob_size); /* Can't fail */ + a->ob_item = item; + } + } + else { /* Insert d items; DECREF ihigh-ilow items */ + RESIZE(item, object *, a->ob_size + d); + if (item == NULL) + return errno = ENOMEM; + for (k = a->ob_size; --k >= ihigh; ) + item[k+d] = item[k]; + for (/*k = ihigh-1*/; k >= ilow; --k) + DECREF(item[k]); + a->ob_item = item; + a->ob_size += d; + } + for (k = 0; k < n; k++, ilow++) { + object *w = b->ob_item[k]; + INCREF(w); + item[ilow] = w; + } + return 0; +#undef b +} + +static object * +ins(self, where, v) + listobject *self; + int where; + object *v; +{ + if (ins1(self, where, v) != 0) + return NULL; + INCREF(None); + return None; +} + +static object * +listinsert(self, args) + listobject *self; + object *args; +{ + int i; + if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) { + errno = EINVAL; + return NULL; + } + if (!getintarg(gettupleitem(args, 0), &i)) + return NULL; + return ins(self, i, gettupleitem(args, 1)); +} + +static object * +listappend(self, args) + listobject *self; + object *args; +{ + return ins(self, (int) self->ob_size, args); +} + +static int +cmp(v, w) + char *v, *w; +{ + return cmpobject(* (object **) v, * (object **) w); +} + +static object * +listsort(self, args) + listobject *self; + object *args; +{ + if (args != NULL) { + errno = EINVAL; + return NULL; + } + errno = 0; + if (self->ob_size > 1) + qsort((char *)self->ob_item, + (int) self->ob_size, sizeof(object *), cmp); + if (errno != 0) + return NULL; + INCREF(None); + return None; +} + +static struct methodlist list_methods[] = { + {"append", listappend}, + {"insert", listinsert}, + {"sort", listsort}, + {NULL, NULL} /* sentinel */ +}; + +static object * +list_getattr(f, name) + listobject *f; + char *name; +{ + return findmethod(list_methods, (object *)f, name); +} + +static sequence_methods list_as_sequence = { + list_length, /*sq_length*/ + list_concat, /*sq_concat*/ + 0, /*sq_repeat*/ + list_item, /*sq_item*/ + list_slice, /*sq_slice*/ + list_ass_item, /*sq_ass_item*/ + list_ass_slice, /*sq_ass_slice*/ +}; + +typeobject Listtype = { + OB_HEAD_INIT(&Typetype) + 0, + "list", + sizeof(listobject), + 0, + list_dealloc, /*tp_dealloc*/ + list_print, /*tp_print*/ + list_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + list_compare, /*tp_compare*/ + list_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + &list_as_sequence, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; diff --git a/Objects/methodobject.c b/Objects/methodobject.c new file mode 100644 index 0000000..5015899 --- /dev/null +++ b/Objects/methodobject.c @@ -0,0 +1,113 @@ +/* Method object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "node.h" +#include "stringobject.h" +#include "methodobject.h" +#include "objimpl.h" +#include "token.h" + +typedef struct { + OB_HEAD + char *m_name; + method m_meth; + object *m_self; +} methodobject; + +object * +newmethodobject(name, meth, self) + char *name; /* static string */ + method meth; + object *self; +{ + methodobject *op = NEWOBJ(methodobject, &Methodtype); + if (op != NULL) { + op->m_name = name; + op->m_meth = meth; + if (self != NULL) + INCREF(self); + op->m_self = self; + } + return (object *)op; +} + +method +getmethod(op) + object *op; +{ + if (!is_methodobject(op)) { + errno = EBADF; + return NULL; + } + return ((methodobject *)op) -> m_meth; +} + +object * +getself(op) + object *op; +{ + if (!is_methodobject(op)) { + errno = EBADF; + return NULL; + } + return ((methodobject *)op) -> m_self; +} + +/* Methods (the standard built-in methods, that is) */ + +static void +meth_dealloc(m) + methodobject *m; +{ + if (m->m_self != NULL) + DECREF(m->m_self); + free((char *)m); +} + +static void +meth_print(m, fp, flags) + methodobject *m; + FILE *fp; + int flags; +{ + if (m->m_self == NULL) + fprintf(fp, "<%s method>", m->m_name); + else + fprintf(fp, "<%s method of %s object at %lx>", + m->m_name, m->m_self->ob_type->tp_name, + (long)m->m_self); +} + +static object * +meth_repr(m) + methodobject *m; +{ + char buf[200]; + if (m->m_self == NULL) + sprintf(buf, "<%.80s method>", m->m_name); + else + sprintf(buf, "<%.80s method of %.80s object at %lx>", + m->m_name, m->m_self->ob_type->tp_name, + (long)m->m_self); + return newstringobject(buf); +} + +typeobject Methodtype = { + OB_HEAD_INIT(&Typetype) + 0, + "method", + sizeof(methodobject), + 0, + meth_dealloc, /*tp_dealloc*/ + meth_print, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + meth_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c new file mode 100644 index 0000000..95dc094 --- /dev/null +++ b/Objects/moduleobject.c @@ -0,0 +1,130 @@ +/* Module object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "stringobject.h" +#include "dictobject.h" +#include "moduleobject.h" +#include "objimpl.h" + +typedef struct { + OB_HEAD + object *md_name; + object *md_dict; +} moduleobject; + +object * +newmoduleobject(name) + char *name; +{ + moduleobject *m = NEWOBJ(moduleobject, &Moduletype); + if (m == NULL) + return NULL; + m->md_name = newstringobject(name); + m->md_dict = newdictobject(); + if (m->md_name == NULL || m->md_dict == NULL) { + DECREF(m); + return NULL; + } + return (object *)m; +} + +object * +getmoduledict(m) + object *m; +{ + if (!is_moduleobject(m)) { + errno = EBADF; + return NULL; + } + return ((moduleobject *)m) -> md_dict; +} + +int +setmoduledict(m, v) + object *m; + object *v; +{ + if (!is_moduleobject(m)) + return errno = EBADF; + if (!is_dictobject(v)) + return errno = EINVAL; + DECREF(((moduleobject *)m) -> md_dict); + INCREF(v); + ((moduleobject *)m) -> md_dict = v; + return 0; +} + +/* Methods */ + +static void +moduledealloc(m) + moduleobject *m; +{ + if (m->md_name != NULL) + DECREF(m->md_name); + if (m->md_dict != NULL) + DECREF(m->md_dict); + free((char *)m); +} + +static void +moduleprint(m, fp, flags) + moduleobject *m; + FILE *fp; + int flags; +{ + fprintf(fp, "<module %s>", getstringvalue(m->md_name)); +} + +static object * +modulerepr(m) + moduleobject *m; +{ + char buf[100]; + sprintf(buf, "<module %.80s>", getstringvalue(m->md_name)); + return newstringobject(buf); +} + +static object * +modulegetattr(m, name) + moduleobject *m; + char *name; +{ + object *res = dictlookup(m->md_dict, name); + if (res == NULL) { + if (errno == ENOENT) + errno = ESRCH; + } + else + INCREF(res); + return res; +} + +static int +modulesetattr(m, name, v) + moduleobject *m; + char *name; + object *v; +{ + if (v == NULL) + return dictremove(m->md_dict, name); + else + return dictinsert(m->md_dict, name, v); +} + +typeobject Moduletype = { + OB_HEAD_INIT(&Typetype) + 0, /*ob_size*/ + "module", /*tp_name*/ + sizeof(moduleobject), /*tp_size*/ + 0, /*tp_itemsize*/ + moduledealloc, /*tp_dealloc*/ + moduleprint, /*tp_print*/ + modulegetattr, /*tp_getattr*/ + modulesetattr, /*tp_setattr*/ + 0, /*tp_compare*/ + modulerepr, /*tp_repr*/ +}; diff --git a/Objects/object.c b/Objects/object.c new file mode 100644 index 0000000..9f5b6c1 --- /dev/null +++ b/Objects/object.c @@ -0,0 +1,195 @@ +/* Object implementation; and 'noobject' implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "stringobject.h" +#include "objimpl.h" +#include "errors.h" + +extern object *err_nomem PROTO((void)); /* XXX from modsupport.c */ + +int StopPrint; /* Flag to indicate printing must be stopped */ + +/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros */ + +object * +newobject(tp) + typeobject *tp; +{ + object *op = (object *) malloc(tp->tp_basicsize); + if (op == NULL) + return err_nomem(); + NEWREF(op); + op->ob_type = tp; + return op; +} + +#if 0 /* unused */ + +varobject * +newvarobject(tp, size) + typeobject *tp; + unsigned int size; +{ + varobject *op = (varobject *) + malloc(tp->tp_basicsize + size * tp->tp_itemsize); + if (op == NULL) + return err_nomem(); + NEWREF(op); + op->ob_type = tp; + op->ob_size = size; + return op; +} + +#endif + +static int prlevel; + +void +printobject(op, fp, flags) + object *op; + FILE *fp; + int flags; +{ + /* Hacks to make printing a long or recursive object interruptible */ + prlevel++; + if (!StopPrint && intrcheck()) { + fprintf(fp, "\n[print interrupted]\n"); + StopPrint = 1; + } + if (!StopPrint) { + if (op == NULL) { + fprintf(fp, "<nil>"); + } + else if (op->ob_type->tp_print == NULL) { + fprintf(fp, "<%s object at %lx>", + op->ob_type->tp_name, (long)op); + } + else { + (*op->ob_type->tp_print)(op, fp, flags); + } + } + prlevel--; + if (prlevel == 0) + StopPrint = 0; +} + +object * +reprobject(v) + object *v; +{ + object *w; + /* Hacks to make converting a long or recursive object interruptible */ + prlevel++; + if (!StopPrint && intrcheck()) { + StopPrint = 1; + w = NULL; + err_set(KeyboardInterrupt); + } + if (!StopPrint) { + if (v == NULL) { + w = newstringobject("<nil>"); + } + else if (v->ob_type->tp_repr == NULL) { + char buf[100]; + sprintf(buf, "<%.80s object at %lx>", + v->ob_type->tp_name, (long)v); + w = newstringobject(buf); + } + else { + w = (*v->ob_type->tp_repr)(v); + } + } + prlevel--; + if (prlevel == 0) + StopPrint = 0; + return w; +} + +int +cmpobject(v, w) + object *v, *w; +{ + typeobject *tp; + if (v == w) + return 0; + if (v == NULL) + return -1; + if (w == NULL) + return 1; + if ((tp = v->ob_type) != w->ob_type) + return strcmp(tp->tp_name, w->ob_type->tp_name); + if (tp->tp_compare == NULL) + return (v < w) ? -1 : 1; + return ((*tp->tp_compare)(v, w)); +} + + +/* +NoObject is usable as a non-NULL undefined value, used by the macro None. +There is (and should be!) no way to create other objects of this type, +so there is exactly one. +*/ + +static void +noprint(op, fp, flags) + object *op; + FILE *fp; + int flags; +{ + fprintf(fp, "<no value>"); +} + +static typeobject Notype = { + OB_HEAD_INIT(&Typetype) + 0, + "novalue", + 0, + 0, + 0, /*tp_dealloc*/ /*never called*/ + noprint, /*tp_print*/ +}; + +object NoObject = { + OB_HEAD_INIT(&Notype) +}; + + +#ifdef TRACE_REFS + +static object refchain = {&refchain, &refchain}; + +NEWREF(op) + object *op; +{ + ref_total++; + op->ob_refcnt = 1; + op->_ob_next = refchain._ob_next; + op->_ob_prev = &refchain; + refchain._ob_next->_ob_prev = op; + refchain._ob_next = op; +} + +DELREF(op) + object *op; +{ + op->_ob_next->_ob_prev = op->_ob_prev; + op->_ob_prev->_ob_next = op->_ob_next; + (*(op)->ob_type->tp_dealloc)(op); +} + +printrefs(fp) + FILE *fp; +{ + object *op; + fprintf(fp, "Remaining objects:\n"); + for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) { + fprintf(fp, "[%d] ", op->ob_refcnt); + printobject(op, fp, 0); + putc('\n', fp); + } +} + +#endif diff --git a/Objects/stringobject.c b/Objects/stringobject.c new file mode 100644 index 0000000..6430c0f --- /dev/null +++ b/Objects/stringobject.c @@ -0,0 +1,328 @@ +/* String object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "stringobject.h" +#include "intobject.h" +#include "objimpl.h" + +object * +newsizedstringobject(str, size) + char *str; + int size; +{ + register stringobject *op = (stringobject *) + malloc(sizeof(stringobject) + size * sizeof(char)); + if (op == NULL) { + errno = ENOMEM; + } + else { + NEWREF(op); + op->ob_type = &Stringtype; + op->ob_size = size; + if (str != NULL) + memcpy(op->ob_sval, str, size); + op->ob_sval[size] = '\0'; + } + return (object *) op; +} + +object * +newstringobject(str) + char *str; +{ + register unsigned int size = strlen(str); + register stringobject *op = (stringobject *) + malloc(sizeof(stringobject) + size * sizeof(char)); + if (op == NULL) { + errno = ENOMEM; + } + else { + NEWREF(op); + op->ob_type = &Stringtype; + op->ob_size = size; + strcpy(op->ob_sval, str); + } + return (object *) op; +} + +unsigned int +getstringsize(op) + register object *op; +{ + if (!is_stringobject(op)) { + errno = EBADF; + return -1; + } + return ((stringobject *)op) -> ob_size; +} + +/*const*/ char * +getstringvalue(op) + register object *op; +{ + if (!is_stringobject(op)) { + errno = EBADF; + return NULL; + } + return ((stringobject *)op) -> ob_sval; +} + +/* Methods */ + +static void +stringprint(op, fp, flags) + stringobject *op; + FILE *fp; + int flags; +{ + int i; + char c; + if (flags & PRINT_RAW) { + fwrite(op->ob_sval, 1, (int) op->ob_size, fp); + return; + } + fprintf(fp, "'"); + for (i = 0; i < op->ob_size; i++) { + c = op->ob_sval[i]; + if (c == '\'' || c == '\\') + fprintf(fp, "\\%c", c); + else if (c < ' ' || c >= 0177) + fprintf(fp, "\\%03o", c&0377); + else + putc(c, fp); + } + fprintf(fp, "'"); +} + +static object * +stringrepr(op) + register stringobject *op; +{ + /* XXX overflow? */ + int newsize = 2 + 4 * op->ob_size * sizeof(char); + object *v = newsizedstringobject((char *)NULL, newsize); + if (v == NULL) { + errno = ENOMEM; + } + else { + register int i; + register char c; + register char *p; + NEWREF(v); + v->ob_type = &Stringtype; + ((stringobject *)v)->ob_size = newsize; + p = ((stringobject *)v)->ob_sval; + *p++ = '\''; + for (i = 0; i < op->ob_size; i++) { + c = op->ob_sval[i]; + if (c == '\'' || c == '\\') + *p++ = '\\', *p++ = c; + else if (c < ' ' || c >= 0177) { + sprintf(p, "\\%03o", c&0377); + while (*p != '\0') + p++; + + } + else + *p++ = c; + } + *p++ = '\''; + *p = '\0'; + resizestring(&v, (int) (p - ((stringobject *)v)->ob_sval)); + } + return v; +} + +static int +stringlength(a) + stringobject *a; +{ + return a->ob_size; +} + +static object * +stringconcat(a, bb) + register stringobject *a; + register object *bb; +{ + register unsigned int size; + register stringobject *op; + if (!is_stringobject(bb)) { + errno = EINVAL; + return NULL; + } +#define b ((stringobject *)bb) + /* Optimize cases with empty left or right operand */ + if (a->ob_size == 0) { + INCREF(bb); + return bb; + } + if (b->ob_size == 0) { + INCREF(a); + return (object *)a; + } + size = a->ob_size + b->ob_size; + op = (stringobject *) + malloc(sizeof(stringobject) + size * sizeof(char)); + if (op == NULL) { + errno = ENOMEM; + } + else { + NEWREF(op); + op->ob_type = &Stringtype; + op->ob_size = size; + memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size); + memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size); + op->ob_sval[size] = '\0'; + } + return (object *) op; +#undef b +} + +static object * +stringrepeat(a, n) + register stringobject *a; + register int n; +{ + register int i; + register unsigned int size; + register stringobject *op; + if (n < 0) + n = 0; + size = a->ob_size * n; + if (size == a->ob_size) { + INCREF(a); + return (object *)a; + } + op = (stringobject *) + malloc(sizeof(stringobject) + size * sizeof(char)); + if (op == NULL) { + errno = ENOMEM; + } + else { + NEWREF(op); + op->ob_type = &Stringtype; + op->ob_size = size; + for (i = 0; i < size; i += a->ob_size) + memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size); + op->ob_sval[size] = '\0'; + } + return (object *) op; +} + +/* String slice a[i:j] consists of characters a[i] ... a[j-1] */ + +static object * +stringslice(a, i, j) + register stringobject *a; + register int i, j; /* May be negative! */ +{ + if (i < 0) + i = 0; + if (j < 0) + j = 0; /* Avoid signed/unsigned bug in next line */ + if (j > a->ob_size) + j = a->ob_size; + if (i == 0 && j == a->ob_size) { /* It's the same as a */ + INCREF(a); + return (object *)a; + } + if (j < i) + j = i; + return newsizedstringobject(a->ob_sval + i, (int) (j-i)); +} + +static object * +stringitem(a, i) + stringobject *a; + register int i; +{ + if (i < 0 || i >= a->ob_size) { + errno = EDOM; + return NULL; + } + return stringslice(a, i, i+1); +} + +static int +stringcompare(a, b) + stringobject *a, *b; +{ + /* XXX should use memcmp on shortest size, then compare lengths */ + return strcmp(a->ob_sval, b->ob_sval); +} + +static sequence_methods string_as_sequence = { + stringlength, /*tp_length*/ + stringconcat, /*tp_concat*/ + stringrepeat, /*tp_repeat*/ + stringitem, /*tp_item*/ + stringslice, /*tp_slice*/ + 0, /*tp_ass_item*/ + 0, /*tp_ass_slice*/ +}; + +typeobject Stringtype = { + OB_HEAD_INIT(&Typetype) + 0, + "string", + sizeof(stringobject), + sizeof(char), + free, /*tp_dealloc*/ + stringprint, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + stringcompare, /*tp_compare*/ + stringrepr, /*tp_repr*/ + 0, /*tp_as_number*/ + &string_as_sequence, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; + +void +joinstring(pv, w) + register object **pv; + register object *w; +{ + register object *v; + if (*pv == NULL || w == NULL || !is_stringobject(*pv)) + return; + v = stringconcat((stringobject *) *pv, w); + DECREF(*pv); + *pv = v; +} + +/* The following function breaks the notion that strings are immutable: + it changes the size of a string. We get away with this only if there + is only one module referencing the object. You can also think of it + as creating a new string object and destroying the old one, only + more efficiently. In any case, don't use this if the string may + already be known to some other part of the code... */ + +int +resizestring(pv, newsize) + object **pv; + int newsize; +{ + register stringobject *v; + v = (stringobject *) *pv; + if (!is_stringobject(v) || v->ob_refcnt != 1) { + *pv = 0; + DECREF(v); + return errno = EBADF; + } + *pv = (object *) + realloc((char *)v, + sizeof(stringobject) + newsize * sizeof(char)); + if (*pv == NULL) { + DECREF(v); + return errno = ENOMEM; + } + v = (stringobject *) *pv; + v->ob_size = newsize; + v->ob_sval[newsize] = '\0'; + return 0; +} diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c new file mode 100644 index 0000000..02d68b3 --- /dev/null +++ b/Objects/tupleobject.c @@ -0,0 +1,276 @@ +/* Tuple object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "stringobject.h" +#include "tupleobject.h" +#include "intobject.h" +#include "objimpl.h" + +typedef struct { + OB_VARHEAD + object *ob_item[1]; +} tupleobject; + +object * +newtupleobject(size) + register int size; +{ + register int i; + register tupleobject *op; + if (size < 0) { + errno = EINVAL; + return NULL; + } + op = (tupleobject *) + malloc(sizeof(tupleobject) + size * sizeof(object *)); + if (op == NULL) { + errno = ENOMEM; + return NULL; + } + NEWREF(op); + op->ob_type = &Tupletype; + op->ob_size = size; + for (i = 0; i < size; i++) + op->ob_item[i] = NULL; + return (object *) op; +} + +int +gettuplesize(op) + register object *op; +{ + if (!is_tupleobject(op)) { + errno = EBADF; + return -1; + } + else + return ((tupleobject *)op)->ob_size; +} + +object * +gettupleitem(op, i) + register object *op; + register int i; +{ + if (!is_tupleobject(op)) { + errno = EBADF; + return NULL; + } + if (i < 0 || i >= ((tupleobject *)op) -> ob_size) { + errno = EDOM; + return NULL; + } + return ((tupleobject *)op) -> ob_item[i]; +} + +int +settupleitem(op, i, newitem) + register object *op; + register int i; + register object *newitem; +{ + register object *olditem; + if (!is_tupleobject(op)) { + if (newitem != NULL) + DECREF(newitem); + return errno = EBADF; + } + if (i < 0 || i >= ((tupleobject *)op) -> ob_size) { + if (newitem != NULL) + DECREF(newitem); + return errno = EDOM; + } + olditem = ((tupleobject *)op) -> ob_item[i]; + ((tupleobject *)op) -> ob_item[i] = newitem; + if (olditem != NULL) + DECREF(olditem); + return 0; +} + +/* Methods */ + +static void +tupledealloc(op) + register tupleobject *op; +{ + register int i; + for (i = 0; i < op->ob_size; i++) { + if (op->ob_item[i] != NULL) + DECREF(op->ob_item[i]); + } + free((ANY *)op); +} + +static void +tupleprint(op, fp, flags) + tupleobject *op; + FILE *fp; + int flags; +{ + int i; + fprintf(fp, "("); + for (i = 0; i < op->ob_size && !StopPrint; i++) { + if (i > 0) { + fprintf(fp, ", "); + } + printobject(op->ob_item[i], fp, flags); + } + if (op->ob_size == 1) + fprintf(fp, ","); + fprintf(fp, ")"); +} + +object * +tuplerepr(v) + tupleobject *v; +{ + object *s, *t, *comma; + int i; + s = newstringobject("("); + comma = newstringobject(", "); + for (i = 0; i < v->ob_size && s != NULL; i++) { + if (i > 0) + joinstring(&s, comma); + t = reprobject(v->ob_item[i]); + joinstring(&s, t); + if (t != NULL) + DECREF(t); + } + DECREF(comma); + if (v->ob_size == 1) { + t = newstringobject(","); + joinstring(&s, t); + DECREF(t); + } + t = newstringobject(")"); + joinstring(&s, t); + DECREF(t); + return s; +} + +static int +tuplecompare(v, w) + register tupleobject *v, *w; +{ + register int len = + (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size; + register int i; + for (i = 0; i < len; i++) { + int cmp = cmpobject(v->ob_item[i], w->ob_item[i]); + if (cmp != 0) + return cmp; + } + return v->ob_size - w->ob_size; +} + +static int +tuplelength(a) + tupleobject *a; +{ + return a->ob_size; +} + +static object * +tupleitem(a, i) + register tupleobject *a; + register int i; +{ + if (i < 0 || i >= a->ob_size) { + errno = EDOM; + return NULL; + } + INCREF(a->ob_item[i]); + return a->ob_item[i]; +} + +static object * +tupleslice(a, ilow, ihigh) + register tupleobject *a; + register int ilow, ihigh; +{ + register tupleobject *np; + register int i; + if (ilow < 0) + ilow = 0; + if (ihigh > a->ob_size) + ihigh = a->ob_size; + if (ihigh < ilow) + ihigh = ilow; + if (ilow == 0 && ihigh == a->ob_size) { + /* XXX can only do this if tuples are immutable! */ + INCREF(a); + return (object *)a; + } + np = (tupleobject *)newtupleobject(ihigh - ilow); + if (np == NULL) + return NULL; + for (i = ilow; i < ihigh; i++) { + object *v = a->ob_item[i]; + INCREF(v); + np->ob_item[i - ilow] = v; + } + return (object *)np; +} + +static object * +tupleconcat(a, bb) + register tupleobject *a; + register object *bb; +{ + register int size; + register int i; + tupleobject *np; + if (!is_tupleobject(bb)) { + errno = EINVAL; + return NULL; + } +#define b ((tupleobject *)bb) + size = a->ob_size + b->ob_size; + np = (tupleobject *) newtupleobject(size); + if (np == NULL) { + errno = ENOMEM; + return NULL; + } + for (i = 0; i < a->ob_size; i++) { + object *v = a->ob_item[i]; + INCREF(v); + np->ob_item[i] = v; + } + for (i = 0; i < b->ob_size; i++) { + object *v = b->ob_item[i]; + INCREF(v); + np->ob_item[i + a->ob_size] = v; + } + return (object *)np; +#undef b +} + +static sequence_methods tuple_as_sequence = { + tuplelength, /*sq_length*/ + tupleconcat, /*sq_concat*/ + 0, /*sq_repeat*/ + tupleitem, /*sq_item*/ + tupleslice, /*sq_slice*/ + 0, /*sq_ass_item*/ + 0, /*sq_ass_slice*/ +}; + +typeobject Tupletype = { + OB_HEAD_INIT(&Typetype) + 0, + "tuple", + sizeof(tupleobject) - sizeof(object *), + sizeof(object *), + tupledealloc, /*tp_dealloc*/ + tupleprint, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + tuplecompare, /*tp_compare*/ + tuplerepr, /*tp_repr*/ + 0, /*tp_as_number*/ + &tuple_as_sequence, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ +}; diff --git a/Objects/typeobject.c b/Objects/typeobject.c new file mode 100644 index 0000000..f7acaad --- /dev/null +++ b/Objects/typeobject.c @@ -0,0 +1,47 @@ +/* Type object implementation */ + +#include <stdio.h> + +#include "PROTO.h" +#include "object.h" +#include "stringobject.h" +#include "objimpl.h" + +/* Type object implementation */ + +static void +typeprint(v, fp, flags) + typeobject *v; + FILE *fp; + int flags; +{ + fprintf(fp, "<type '%s'>", v->tp_name); +} + +static object * +typerepr(v) + typeobject *v; +{ + char buf[100]; + sprintf(buf, "<type '%.80s'>", v->tp_name); + return newstringobject(buf); +} + +typedef struct { + OB_HEAD + long ob_ival; +} intobject; + +typeobject Typetype = { + OB_HEAD_INIT(&Typetype) + 0, /* Number of items for varobject */ + "type", /* Name of this type */ + sizeof(typeobject), /* Basic object size */ + 0, /* Item size for varobject */ + 0, /*tp_dealloc*/ + typeprint, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + typerepr, /*tp_repr*/ +}; diff --git a/Objects/xxobject.c b/Objects/xxobject.c new file mode 100644 index 0000000..ffafcd7 --- /dev/null +++ b/Objects/xxobject.c @@ -0,0 +1,94 @@ +/* Xx objects */ + +typedef struct { + OB_HEAD + object *x_attr; /* Attributes dictionary */ +} xxobject; + +extern typeobject Xxtype; /* Really static, forward */ + +static xxobject * +newxxobject(arg) + object *arg; +{ + textobject *xp; + xp = NEWOBJ(xxobject, &Xxtype); + if (xp == NULL) + return NULL; + xp->x_attr = NULL; + return xp; +} + +/* Xx methods */ + +static void +xx_dealloc(xp) + xxobject *xp; +{ + if (xp->x_attr != NULL) + DECREF(xp->x_attr); + DEL(xp); +} + +static object * +xx_demo(self, args) + xxobject *self; + object *args; +{ + if (!getnoarg(args)) + return NULL; + INCREF(None); + return None; +} + +static struct methodlist xx_methods[] = { + "demo", xx_demo, + {NULL, NULL} /* sentinel */ +}; + +static object * +xx_getattr(xp, name) + xxobject *xp; + char *name; +{ + if (xp->x_attr != NULL) { + object *v = dictlookup(xp->x_attr, name); + if (v != NULL) { + INCREF(v); + return v; + } + } + return findmethod(xx_methods, (object *)xp, name); +} + +static int +xx_setattr(xp, name, v) + xxobject *xp; + char *name; + object *v; +{ + if (xp->x_attr == NULL) { + xp->x_attr = newdictobject(); + if (xp->x_attr == NULL) + return errno; + } + if (v == NULL) + return dictremove(xp->x_attr, name); + else + return dictinsert(xp->x_attr, name, v); +} + +static typeobject Xxtype = { + OB_HEAD_INIT(&Typetype) + 0, /*ob_size*/ + "xx", /*tp_name*/ + sizeof(xxobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + xx_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + xx_getattr, /*tp_getattr*/ + xx_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ +}; |