From d076c73cc81a974794c9aa7e812931b74d6e03c2 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 7 Oct 1998 19:42:25 +0000 Subject: Changes to support other object types besides strings as the code string of code objects, as long as they support the (readonly) buffer interface. By Greg Stein. --- Include/compile.h | 7 ++++++- Modules/newmodule.c | 17 +++++++++++++++-- Python/ceval.c | 13 ++++++++----- Python/compile.c | 23 +++++++++++++++++------ Python/marshal.c | 17 +++++++++++++++-- 5 files changed, 61 insertions(+), 16 deletions(-) diff --git a/Include/compile.h b/Include/compile.h index 6c8a62d..b735617 100644 --- a/Include/compile.h +++ b/Include/compile.h @@ -44,7 +44,7 @@ typedef struct { int co_nlocals; /* #local variables */ int co_stacksize; /* #entries needed for evaluation stack */ int co_flags; /* CO_..., see below */ - PyStringObject *co_code; /* instruction opcodes */ + PyObject *co_code; /* instruction opcodes */ PyObject *co_consts; /* list (constants used) */ PyObject *co_names; /* list of strings (names used) */ PyObject *co_varnames; /* tuple of strings (local variable names) */ @@ -75,6 +75,11 @@ PyCodeObject *PyCode_New Py_PROTO(( PyObject *, PyObject *, int, PyObject *)); /* same as struct above */ int PyCode_Addr2Line Py_PROTO((PyCodeObject *, int)); +/* for internal use only */ +#define _PyCode_GETCODEPTR(co, pp) \ + ((*(co)->co_code->ob_type->tp_as_buffer->bf_getreadbuffer) \ + ((co)->co_code, 0, (void **)(pp))) + #ifdef __cplusplus } #endif diff --git a/Modules/newmodule.c b/Modules/newmodule.c index 52328a9..5c92e0e 100644 --- a/Modules/newmodule.c +++ b/Modules/newmodule.c @@ -150,8 +150,9 @@ new_code(unused, args) PyObject* name; int firstlineno; PyObject* lnotab; - - if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS", + PyBufferProcs *pb; + + if (!PyArg_ParseTuple(args, "iiiiOO!O!O!SSiS", &argcount, &nlocals, &stacksize, &flags, &code, &PyTuple_Type, &consts, @@ -160,6 +161,18 @@ new_code(unused, args) &filename, &name, &firstlineno, &lnotab)) return NULL; + + pb = code->ob_type->tp_as_buffer; + if (pb == NULL || + pb->bf_getreadbuffer == NULL || + pb->bf_getsegcount == NULL || + (*pb->bf_getsegcount)(code, NULL) != 1) + { + PyErr_SetString(PyExc_TypeError, + "bytecode object must be a single-segment read-only buffer"); + return NULL; + } + return (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab); diff --git a/Python/ceval.c b/Python/ceval.c index b004c79..413b316 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -366,6 +366,7 @@ eval_code2(co, globals, locals, register PyObject **fastlocals = NULL; PyObject *retval = NULL; /* Return value */ PyThreadState *tstate = PyThreadState_Get(); + unsigned char *first_instr; #ifdef LLTRACE int lltrace; #endif @@ -379,11 +380,10 @@ eval_code2(co, globals, locals, #define GETCONST(i) Getconst(f, i) #define GETNAME(i) Getname(f, i) #define GETNAMEV(i) Getnamev(f, i) -#define FIRST_INSTR() (GETUSTRINGVALUE(co->co_code)) -#define INSTR_OFFSET() (next_instr - FIRST_INSTR()) +#define INSTR_OFFSET() (next_instr - first_instr) #define NEXTOP() (*next_instr++) #define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2]) -#define JUMPTO(x) (next_instr = FIRST_INSTR() + (x)) +#define JUMPTO(x) (next_instr = first_instr + (x)) #define JUMPBY(x) (next_instr += (x)) /* Stack manipulation macros */ @@ -580,7 +580,8 @@ eval_code2(co, globals, locals, return NULL; } - next_instr = GETUSTRINGVALUE(co->co_code); + _PyCode_GETCODEPTR(co, &first_instr); + next_instr = first_instr; stack_pointer = f->f_valuestack; why = WHY_NOT; @@ -2801,7 +2802,9 @@ find_from_args(f, nexti) PyObject *list, *name; unsigned char *next_instr; - next_instr = GETUSTRINGVALUE(f->f_code->co_code) + nexti; + _PyCode_GETCODEPTR(f->f_code, &next_instr); + next_instr += nexti; + opcode = (*next_instr++); if (opcode != IMPORT_FROM) { Py_INCREF(Py_None); diff --git a/Python/compile.c b/Python/compile.c index 9871b0f..19f18e6 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -121,9 +121,11 @@ code_repr(co) { char buf[500]; int lineno = -1; - char *p = PyString_AS_STRING(co->co_code); + unsigned char *p; char *filename = "???"; char *name = "???"; + + _PyCode_GETCODEPTR(co, &p); if (*p == SET_LINENO) lineno = (p[1] & 0xff) | ((p[2] & 0xff) << 8); if (co->co_filename && PyString_Check(co->co_filename)) @@ -146,8 +148,7 @@ code_compare(co, cp) if (cmp) return cmp; cmp = co->co_flags - cp->co_flags; if (cmp) return cmp; - cmp = PyObject_Compare((PyObject *)co->co_code, - (PyObject *)cp->co_code); + cmp = PyObject_Compare(co->co_code, cp->co_code); if (cmp) return cmp; cmp = PyObject_Compare(co->co_consts, cp->co_consts); if (cmp) return cmp; @@ -162,7 +163,7 @@ code_hash(co) PyCodeObject *co; { long h, h1, h2, h3, h4; - h1 = PyObject_Hash((PyObject *)co->co_code); + h1 = PyObject_Hash(co->co_code); if (h1 == -1) return -1; h2 = PyObject_Hash(co->co_consts); if (h2 == -1) return -1; @@ -216,9 +217,10 @@ PyCode_New(argcount, nlocals, stacksize, flags, { PyCodeObject *co; int i; + PyBufferProcs *pb; /* Check argument types */ if (argcount < 0 || nlocals < 0 || - code == NULL || !PyString_Check(code) || + code == NULL || consts == NULL || !PyTuple_Check(consts) || names == NULL || !PyTuple_Check(names) || varnames == NULL || !PyTuple_Check(varnames) || @@ -228,6 +230,15 @@ PyCode_New(argcount, nlocals, stacksize, flags, PyErr_BadInternalCall(); return NULL; } + pb = code->ob_type->tp_as_buffer; + if (pb == NULL || + pb->bf_getreadbuffer == NULL || + pb->bf_getsegcount == NULL || + (*pb->bf_getsegcount)(code, NULL) != 1) + { + PyErr_BadInternalCall(); + return NULL; + } /* Make sure names and varnames are all strings, & intern them */ for (i = PyTuple_Size(names); --i >= 0; ) { PyObject *v = PyTuple_GetItem(names, i); @@ -264,7 +275,7 @@ PyCode_New(argcount, nlocals, stacksize, flags, co->co_stacksize = stacksize; co->co_flags = flags; Py_INCREF(code); - co->co_code = (PyStringObject *)code; + co->co_code = code; Py_INCREF(consts); co->co_consts = consts; Py_INCREF(names); diff --git a/Python/marshal.c b/Python/marshal.c index 3d5f2e5..df7f51c 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -142,6 +142,7 @@ w_object(v, p) WFILE *p; { int i, n; + PyBufferProcs *pb; if (v == NULL) { w_byte(TYPE_NULL, p); @@ -251,7 +252,7 @@ w_object(v, p) w_short(co->co_nlocals, p); w_short(co->co_stacksize, p); w_short(co->co_flags, p); - w_object((PyObject *)co->co_code, p); + w_object(co->co_code, p); w_object(co->co_consts, p); w_object(co->co_names, p); w_object(co->co_varnames, p); @@ -260,6 +261,18 @@ w_object(v, p) w_short(co->co_firstlineno, p); w_object(co->co_lnotab, p); } + else if ((pb = v->ob_type->tp_as_buffer) != NULL && + pb->bf_getsegcount != NULL && + pb->bf_getreadbuffer != NULL && + (*pb->bf_getsegcount)(v, NULL) == 1) + { + /* Write unknown buffer-style objects as a string */ + char *s; + w_byte(TYPE_STRING, p); + n = (*pb->bf_getreadbuffer)(v, 0, (void **)&s); + w_long((long)n, p); + w_string(s, n, p); + } else { w_byte(TYPE_UNKNOWN, p); p->error = 1; @@ -730,7 +743,7 @@ marshal_loads(self, args) PyObject *v; char *s; int n; - if (!PyArg_Parse(args, "s#", &s, &n)) + if (!PyArg_Parse(args, "r#", &s, &n)) return NULL; rf.fp = NULL; rf.str = args; -- cgit v0.12