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.
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 @@
 	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 @@
 	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 @@
 	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 @@
 			      &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 @@
 	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 @@
 #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 @@
 		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 @@
 	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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 {
 	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 @@
 		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 @@
 		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 @@
 	WFILE *p;
 {
 	int i, n;
+	PyBufferProcs *pb;
 	
 	if (v == NULL) {
 		w_byte(TYPE_NULL, p);
@@ -251,7 +252,7 @@
 		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_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 @@
 	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;