mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
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.
This commit is contained in:
parent
437ff8600a
commit
d076c73cc8
5 changed files with 61 additions and 16 deletions
|
@ -44,7 +44,7 @@ typedef struct {
|
||||||
int co_nlocals; /* #local variables */
|
int co_nlocals; /* #local variables */
|
||||||
int co_stacksize; /* #entries needed for evaluation stack */
|
int co_stacksize; /* #entries needed for evaluation stack */
|
||||||
int co_flags; /* CO_..., see below */
|
int co_flags; /* CO_..., see below */
|
||||||
PyStringObject *co_code; /* instruction opcodes */
|
PyObject *co_code; /* instruction opcodes */
|
||||||
PyObject *co_consts; /* list (constants used) */
|
PyObject *co_consts; /* list (constants used) */
|
||||||
PyObject *co_names; /* list of strings (names used) */
|
PyObject *co_names; /* list of strings (names used) */
|
||||||
PyObject *co_varnames; /* tuple of strings (local variable names) */
|
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 */
|
PyObject *, PyObject *, int, PyObject *)); /* same as struct above */
|
||||||
int PyCode_Addr2Line Py_PROTO((PyCodeObject *, int));
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -150,8 +150,9 @@ new_code(unused, args)
|
||||||
PyObject* name;
|
PyObject* name;
|
||||||
int firstlineno;
|
int firstlineno;
|
||||||
PyObject* lnotab;
|
PyObject* lnotab;
|
||||||
|
PyBufferProcs *pb;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS",
|
if (!PyArg_ParseTuple(args, "iiiiOO!O!O!SSiS",
|
||||||
&argcount, &nlocals, &stacksize, &flags,
|
&argcount, &nlocals, &stacksize, &flags,
|
||||||
&code,
|
&code,
|
||||||
&PyTuple_Type, &consts,
|
&PyTuple_Type, &consts,
|
||||||
|
@ -160,6 +161,18 @@ new_code(unused, args)
|
||||||
&filename, &name,
|
&filename, &name,
|
||||||
&firstlineno, &lnotab))
|
&firstlineno, &lnotab))
|
||||||
return NULL;
|
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,
|
return (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,
|
||||||
code, consts, names, varnames,
|
code, consts, names, varnames,
|
||||||
filename, name, firstlineno, lnotab);
|
filename, name, firstlineno, lnotab);
|
||||||
|
|
|
@ -366,6 +366,7 @@ eval_code2(co, globals, locals,
|
||||||
register PyObject **fastlocals = NULL;
|
register PyObject **fastlocals = NULL;
|
||||||
PyObject *retval = NULL; /* Return value */
|
PyObject *retval = NULL; /* Return value */
|
||||||
PyThreadState *tstate = PyThreadState_Get();
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
|
unsigned char *first_instr;
|
||||||
#ifdef LLTRACE
|
#ifdef LLTRACE
|
||||||
int lltrace;
|
int lltrace;
|
||||||
#endif
|
#endif
|
||||||
|
@ -379,11 +380,10 @@ eval_code2(co, globals, locals,
|
||||||
#define GETCONST(i) Getconst(f, i)
|
#define GETCONST(i) Getconst(f, i)
|
||||||
#define GETNAME(i) Getname(f, i)
|
#define GETNAME(i) Getname(f, i)
|
||||||
#define GETNAMEV(i) Getnamev(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 NEXTOP() (*next_instr++)
|
||||||
#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
|
#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))
|
#define JUMPBY(x) (next_instr += (x))
|
||||||
|
|
||||||
/* Stack manipulation macros */
|
/* Stack manipulation macros */
|
||||||
|
@ -580,7 +580,8 @@ eval_code2(co, globals, locals,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
next_instr = GETUSTRINGVALUE(co->co_code);
|
_PyCode_GETCODEPTR(co, &first_instr);
|
||||||
|
next_instr = first_instr;
|
||||||
stack_pointer = f->f_valuestack;
|
stack_pointer = f->f_valuestack;
|
||||||
|
|
||||||
why = WHY_NOT;
|
why = WHY_NOT;
|
||||||
|
@ -2801,7 +2802,9 @@ find_from_args(f, nexti)
|
||||||
PyObject *list, *name;
|
PyObject *list, *name;
|
||||||
unsigned char *next_instr;
|
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++);
|
opcode = (*next_instr++);
|
||||||
if (opcode != IMPORT_FROM) {
|
if (opcode != IMPORT_FROM) {
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
|
|
@ -121,9 +121,11 @@ code_repr(co)
|
||||||
{
|
{
|
||||||
char buf[500];
|
char buf[500];
|
||||||
int lineno = -1;
|
int lineno = -1;
|
||||||
char *p = PyString_AS_STRING(co->co_code);
|
unsigned char *p;
|
||||||
char *filename = "???";
|
char *filename = "???";
|
||||||
char *name = "???";
|
char *name = "???";
|
||||||
|
|
||||||
|
_PyCode_GETCODEPTR(co, &p);
|
||||||
if (*p == SET_LINENO)
|
if (*p == SET_LINENO)
|
||||||
lineno = (p[1] & 0xff) | ((p[2] & 0xff) << 8);
|
lineno = (p[1] & 0xff) | ((p[2] & 0xff) << 8);
|
||||||
if (co->co_filename && PyString_Check(co->co_filename))
|
if (co->co_filename && PyString_Check(co->co_filename))
|
||||||
|
@ -146,8 +148,7 @@ code_compare(co, cp)
|
||||||
if (cmp) return cmp;
|
if (cmp) return cmp;
|
||||||
cmp = co->co_flags - cp->co_flags;
|
cmp = co->co_flags - cp->co_flags;
|
||||||
if (cmp) return cmp;
|
if (cmp) return cmp;
|
||||||
cmp = PyObject_Compare((PyObject *)co->co_code,
|
cmp = PyObject_Compare(co->co_code, cp->co_code);
|
||||||
(PyObject *)cp->co_code);
|
|
||||||
if (cmp) return cmp;
|
if (cmp) return cmp;
|
||||||
cmp = PyObject_Compare(co->co_consts, cp->co_consts);
|
cmp = PyObject_Compare(co->co_consts, cp->co_consts);
|
||||||
if (cmp) return cmp;
|
if (cmp) return cmp;
|
||||||
|
@ -162,7 +163,7 @@ code_hash(co)
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
{
|
{
|
||||||
long h, h1, h2, h3, h4;
|
long h, h1, h2, h3, h4;
|
||||||
h1 = PyObject_Hash((PyObject *)co->co_code);
|
h1 = PyObject_Hash(co->co_code);
|
||||||
if (h1 == -1) return -1;
|
if (h1 == -1) return -1;
|
||||||
h2 = PyObject_Hash(co->co_consts);
|
h2 = PyObject_Hash(co->co_consts);
|
||||||
if (h2 == -1) return -1;
|
if (h2 == -1) return -1;
|
||||||
|
@ -216,9 +217,10 @@ PyCode_New(argcount, nlocals, stacksize, flags,
|
||||||
{
|
{
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
int i;
|
int i;
|
||||||
|
PyBufferProcs *pb;
|
||||||
/* Check argument types */
|
/* Check argument types */
|
||||||
if (argcount < 0 || nlocals < 0 ||
|
if (argcount < 0 || nlocals < 0 ||
|
||||||
code == NULL || !PyString_Check(code) ||
|
code == NULL ||
|
||||||
consts == NULL || !PyTuple_Check(consts) ||
|
consts == NULL || !PyTuple_Check(consts) ||
|
||||||
names == NULL || !PyTuple_Check(names) ||
|
names == NULL || !PyTuple_Check(names) ||
|
||||||
varnames == NULL || !PyTuple_Check(varnames) ||
|
varnames == NULL || !PyTuple_Check(varnames) ||
|
||||||
|
@ -228,6 +230,15 @@ PyCode_New(argcount, nlocals, stacksize, flags,
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
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 */
|
/* Make sure names and varnames are all strings, & intern them */
|
||||||
for (i = PyTuple_Size(names); --i >= 0; ) {
|
for (i = PyTuple_Size(names); --i >= 0; ) {
|
||||||
PyObject *v = PyTuple_GetItem(names, i);
|
PyObject *v = PyTuple_GetItem(names, i);
|
||||||
|
@ -264,7 +275,7 @@ PyCode_New(argcount, nlocals, stacksize, flags,
|
||||||
co->co_stacksize = stacksize;
|
co->co_stacksize = stacksize;
|
||||||
co->co_flags = flags;
|
co->co_flags = flags;
|
||||||
Py_INCREF(code);
|
Py_INCREF(code);
|
||||||
co->co_code = (PyStringObject *)code;
|
co->co_code = code;
|
||||||
Py_INCREF(consts);
|
Py_INCREF(consts);
|
||||||
co->co_consts = consts;
|
co->co_consts = consts;
|
||||||
Py_INCREF(names);
|
Py_INCREF(names);
|
||||||
|
|
|
@ -142,6 +142,7 @@ w_object(v, p)
|
||||||
WFILE *p;
|
WFILE *p;
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
|
PyBufferProcs *pb;
|
||||||
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
w_byte(TYPE_NULL, p);
|
w_byte(TYPE_NULL, p);
|
||||||
|
@ -251,7 +252,7 @@ w_object(v, p)
|
||||||
w_short(co->co_nlocals, p);
|
w_short(co->co_nlocals, p);
|
||||||
w_short(co->co_stacksize, p);
|
w_short(co->co_stacksize, p);
|
||||||
w_short(co->co_flags, 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_consts, p);
|
||||||
w_object(co->co_names, p);
|
w_object(co->co_names, p);
|
||||||
w_object(co->co_varnames, p);
|
w_object(co->co_varnames, p);
|
||||||
|
@ -260,6 +261,18 @@ w_object(v, p)
|
||||||
w_short(co->co_firstlineno, p);
|
w_short(co->co_firstlineno, p);
|
||||||
w_object(co->co_lnotab, 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 {
|
else {
|
||||||
w_byte(TYPE_UNKNOWN, p);
|
w_byte(TYPE_UNKNOWN, p);
|
||||||
p->error = 1;
|
p->error = 1;
|
||||||
|
@ -730,7 +743,7 @@ marshal_loads(self, args)
|
||||||
PyObject *v;
|
PyObject *v;
|
||||||
char *s;
|
char *s;
|
||||||
int n;
|
int n;
|
||||||
if (!PyArg_Parse(args, "s#", &s, &n))
|
if (!PyArg_Parse(args, "r#", &s, &n))
|
||||||
return NULL;
|
return NULL;
|
||||||
rf.fp = NULL;
|
rf.fp = NULL;
|
||||||
rf.str = args;
|
rf.str = args;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue