Charles G. Waldman <cgw@fnal.gov>:
Add the EXTENDED_ARG opcode to the virtual machine, allowing 32-bit
arguments to opcodes instead of being forced to stick to the 16-bit
limit.  This is especially useful for machine-generated code, which
can be too long for the SET_LINENO parameter to fit into 16 bits.

This closes the implementation portion of SourceForge patch #100893.
diff --git a/Include/node.h b/Include/node.h
index affa8cd..96eb350 100644
--- a/Include/node.h
+++ b/Include/node.h
@@ -19,8 +19,8 @@
 typedef struct _node {
     short		n_type;
     char		*n_str;
-    short		n_lineno;
-    short		n_nchildren;
+    int			n_lineno;
+    int			n_nchildren;
     struct _node	*n_child;
 } node;
 
diff --git a/Include/opcode.h b/Include/opcode.h
index a7b642a..f900aa9 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -130,6 +130,9 @@
 #define CALL_FUNCTION_KW           141	/* #args + (#kwargs<<8) */
 #define CALL_FUNCTION_VAR_KW       142	/* #args + (#kwargs<<8) */
 
+/* Support for opargs more than 16 bits long */
+#define EXTENDED_ARG  143
+
 /* Comparison operator codes (argument to COMPARE_OP) */
 enum cmp_op {LT, LE, EQ, NE, GT, GE, IN, NOT_IN, IS, IS_NOT, EXC_MATCH, BAD};
 
diff --git a/Lib/dis.py b/Lib/dis.py
index 3a80e74..9fc9d30 100644
--- a/Lib/dis.py
+++ b/Lib/dis.py
@@ -56,6 +56,7 @@
 	labels = findlabels(code)
 	n = len(code)
 	i = 0
+	extended_arg = 0
 	while i < n:
 		c = code[i]
 		op = ord(c)
@@ -68,8 +69,11 @@
 		print string.ljust(opname[op], 20),
 		i = i+1
 		if op >= HAVE_ARGUMENT:
-			oparg = ord(code[i]) + ord(code[i+1])*256
+			oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
+			extended_arg = 0
 			i = i+2
+			if op == EXTENDED_ARG:
+				extended_arg = oparg*65536L
 			print string.rjust(`oparg`, 5),
 			if op in hasconst:
 				print '(' + `co.co_consts[oparg]` + ')',
@@ -258,6 +262,8 @@
 def_op('CALL_FUNCTION_KW', 141)      # #args + (#kwargs << 8)
 def_op('CALL_FUNCTION_VAR_KW', 142)  # #args + (#kwargs << 8)
 
+def_op('EXTENDED_ARG', 143) 
+EXTENDED_ARG = 143
 
 def _test():
 	"""Simple test program to disassemble a file."""
diff --git a/Parser/node.c b/Parser/node.c
index 910192d..6844965 100644
--- a/Parser/node.c
+++ b/Parser/node.c
@@ -8,7 +8,12 @@
 redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 ******************************************************************/
 
+#ifdef HAVE_LIMITS_H
 #include <limits.h>
+#endif
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
 
 /* Parse tree node implementation */
 
@@ -39,7 +44,7 @@
 	register int nch = n1->n_nchildren;
 	register int nch1 = nch+1;
 	register node *n;
-	if (nch == SHRT_MAX || nch < 0)
+	if (nch == INT_MAX || nch < 0)
 		return E_OVERFLOW;
 	if (XXXROUNDUP(nch) < nch1) {
 		n = n1->n_child;
diff --git a/Python/ceval.c b/Python/ceval.c
index 23c477b..fb7b5bc 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -613,6 +613,7 @@
 		opcode = NEXTOP();
 		if (HAS_ARG(opcode))
 			oparg = NEXTARG();
+	  dispatch_opcode:
 #ifdef DYNAMIC_EXECUTION_PROFILE
 #ifdef DXPAIRS
 		dxpairs[lastopcode][opcode]++;
@@ -1750,6 +1751,11 @@
 			if (x != NULL) continue;
 			break;
 
+		case EXTENDED_ARG:
+			opcode = NEXTOP();
+			oparg = oparg<<16 | NEXTARG();
+			goto dispatch_opcode;
+			break;
 
 		default:
 			fprintf(stderr,
diff --git a/Python/compile.c b/Python/compile.c
index f239bb6..3b7c87a 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -36,6 +36,9 @@
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
 #endif
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
 
 /* Three symbols from graminit.h are also defined in Python.h, with
    Py_ prefixes to their names.  Python.h can't include graminit.h
@@ -572,11 +575,17 @@
 static void
 com_addoparg(struct compiling *c, int op, int arg)
 {
+	int extended_arg = arg >> 16;
 	if (op == SET_LINENO) {
 		com_set_lineno(c, arg);
 		if (Py_OptimizeFlag)
 			return;
 	}
+	if (extended_arg){
+		com_addbyte(c, EXTENDED_ARG);
+		com_addint(c, extended_arg);
+		arg &= 0xffff;
+	}
 	com_addbyte(c, op);
 	com_addint(c, arg);
 }
@@ -606,7 +615,14 @@
 		prev = code[anchor] + (code[anchor+1] << 8);
 		dist = target - (anchor+2);
 		code[anchor] = dist & 0xff;
-		code[anchor+1] = dist >> 8;
+		dist >>= 8;
+		code[anchor+1] = dist;
+		dist >>= 8;
+		if (dist) {
+			com_error(c, PyExc_SystemError,
+				  "com_backpatch: offset too large");
+			break;
+		}
 		if (!prev)
 			break;
 		anchor -= prev;
@@ -3364,6 +3380,7 @@
 			break;
 		if (HAS_ARG(opcode))
 			oparg = NEXTARG();
+	  dispatch_opcode1:
 		switch (opcode) {
 		case STORE_NAME:
 		case DELETE_NAME:
@@ -3374,6 +3391,11 @@
 		case EXEC_STMT:
 			c->c_flags &= ~CO_OPTIMIZED;
 			break;
+		case EXTENDED_ARG:
+			opcode = NEXTOP();
+			oparg = oparg<<16 | NEXTARG();
+			goto dispatch_opcode1;
+			break;
 		}
 	}
 	
@@ -3389,6 +3411,7 @@
 			break;
 		if (HAS_ARG(opcode))
 			oparg = NEXTARG();
+	  dispatch_opcode2:
 		if (opcode == LOAD_NAME ||
 		    opcode == STORE_NAME ||
 		    opcode == DELETE_NAME) {
@@ -3403,13 +3426,20 @@
 				continue;
 			}
 			i = PyInt_AsLong(v);
+			if (i >> 16) /* too big for 2 bytes */
+				continue;
 			switch (opcode) {
 			case LOAD_NAME: cur_instr[0] = LOAD_FAST; break;
 			case STORE_NAME: cur_instr[0] = STORE_FAST; break;
 			case DELETE_NAME: cur_instr[0] = DELETE_FAST; break;
 			}
 			cur_instr[1] = i & 0xff;
-			cur_instr[2] = (i>>8) & 0xff;
+			cur_instr[2] = i >> 8;
+		}
+		if (opcode == EXTENDED_ARG) {
+			opcode = NEXTOP();
+			oparg = oparg<<16 | NEXTARG();
+			goto dispatch_opcode2;
 		}
 	}