New "re" regular expression support.
This code is written by Philip Hazel and Andrew Kuchling.
It requires a new "re.py" module, too.
diff --git a/Modules/pcremodule.c b/Modules/pcremodule.c
new file mode 100644
index 0000000..7c4136a
--- /dev/null
+++ b/Modules/pcremodule.c
@@ -0,0 +1,775 @@
+/***********************************************************
+Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
+The Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI or Corporation for National Research Initiatives or
+CNRI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+While CWI is the initial source for this software, a modified version
+is made available by the Corporation for National Research Initiatives
+(CNRI) at the Internet address ftp://ftp.python.org.
+
+STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
+CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Pcre objects */
+
+#include "Python.h"
+
+#ifndef Py_eval_input
+/* For Python 1.4, graminit.h has to be explicitly included */
+#include "graminit.h"
+#define Py_eval_input eval_input
+#endif
+
+#ifndef FOR_PYTHON
+#define FOR_PYTHON
+#endif
+
+#include "pcre.h"
+#include "pcre-internal.h"
+
+static PyObject *ErrorObject;
+
+typedef struct {
+	PyObject_HEAD
+	pcre *regex;
+	pcre_extra *regex_extra;
+        int num_groups;
+} PcreObject;
+
+staticforward PyTypeObject Pcre_Type;
+
+#define PcreObject_Check(v)	((v)->ob_type == &Pcre_Type)
+#define NORMAL			0
+#define CHARCLASS		1
+#define REPLACEMENT		2
+
+#define CHAR 			0
+#define MEMORY_REFERENCE 	1
+#define SYNTAX 			2
+#define NOT_SYNTAX 		3
+#define SET			4
+#define WORD_BOUNDARY		5
+#define NOT_WORD_BOUNDARY	6
+#define BEGINNING_OF_BUFFER	7
+#define END_OF_BUFFER		8
+
+
+static PcreObject *
+newPcreObject(arg)
+	PyObject *arg;
+{
+	PcreObject *self;
+	self = PyObject_NEW(PcreObject, &Pcre_Type);
+	if (self == NULL)
+		return NULL;
+	self->regex = NULL;
+	self->regex_extra = NULL;
+	return self;
+}
+
+/* Pcre methods */
+
+static void
+PyPcre_dealloc(self)
+	PcreObject *self;
+{
+	if (self->regex) free(self->regex);
+	if (self->regex_extra) free(self->regex_extra);
+	self->regex=NULL;
+	self->regex_extra=NULL;
+	PyMem_DEL(self);
+}
+
+
+static PyObject *
+PyPcre_exec(self, args)
+	PcreObject *self;
+	PyObject *args;
+{
+        unsigned char *string;
+	int stringlen, pos=0, options=0, i, count;
+	int offsets[100*2]; /* XXX must this be fixed? */
+	PyObject *list;
+
+	if (!PyArg_ParseTuple(args, "s#|ii", &string, &stringlen, &pos, &options))
+		return NULL;
+	count = pcre_exec(self->regex, self->regex_extra, 
+			  string+pos, stringlen-pos, options,
+			  offsets, sizeof(offsets)/sizeof(int) );
+	if (count==PCRE_ERROR_NOMATCH) {Py_INCREF(Py_None); return Py_None;}
+	if (count<0)
+	  {
+	    PyErr_SetObject(ErrorObject, Py_BuildValue("si", "Regex error", count));
+	    return NULL;
+	  }
+	
+	list=PyList_New(self->num_groups+1);
+	if (list==NULL) return NULL;
+	/* XXX count can be >size_offset! */
+	for(i=0; i<=self->num_groups; i++)
+	  {
+	    PyObject *v;
+	    int start=offsets[i*2], end=offsets[i*2+1];
+	    /* If the group wasn't affected by the match, return -1, -1 */
+            if (start<0 || count<=i) 
+	      {start=end=-1;}
+	    else 
+	      {start += pos; end +=pos;}
+	    v=Py_BuildValue("ii", start, end);
+	    if (v==NULL) {Py_DECREF(list); return NULL;}
+	    PyList_SetItem(list, i, v);
+	  }
+	return list;
+}
+
+static PyMethodDef Pcre_methods[] = {
+	{"match",	(PyCFunction)PyPcre_exec,	1},
+	{NULL,		NULL}		/* sentinel */
+};
+
+static PyObject *
+PyPcre_getattr(self, name)
+	PcreObject *self;
+	char *name;
+{
+	return Py_FindMethod(Pcre_methods, (PyObject *)self, name);
+}
+
+
+staticforward PyTypeObject Pcre_Type = {
+	PyObject_HEAD_INIT(&PyType_Type)
+	0,			/*ob_size*/
+	"Pcre",			/*tp_name*/
+	sizeof(PcreObject),	/*tp_basicsize*/
+	0,			/*tp_itemsize*/
+	/* methods */
+	(destructor)PyPcre_dealloc, /*tp_dealloc*/
+	0,			/*tp_print*/
+	PyPcre_getattr,                      /*tp_getattr*/
+	0,                      /*tp_setattr*/
+	0,			/*tp_compare*/
+	0,			/*tp_repr*/
+	0,			/*tp_as_number*/
+	0,			/*tp_as_sequence*/
+	0,			/*tp_as_mapping*/
+	0,			/*tp_hash*/
+};
+/* --------------------------------------------------------------------- */
+
+static PyObject *
+PyPcre_compile(self, args)
+	PyObject *self; /* Not used */
+	PyObject *args;
+{
+	PcreObject *rv;
+	PyObject *dictionary;
+	unsigned char *pattern, *newpattern;
+	char *error;
+	int num_zeros, i, j;
+	
+	int patternlen, options, erroroffset;
+	if (!PyArg_ParseTuple(args, "s#iO!", &pattern, &patternlen, &options,
+			      &PyDict_Type, &dictionary))
+		return NULL;
+	rv = newPcreObject(args);
+	if ( rv == NULL )
+	    return NULL;
+
+	/* PCRE doesn't like having null bytes in its pattern, so we have to replace 
+	   any zeros in the string with the characters '\0'. */
+	num_zeros=1;
+	for(i=0; i<patternlen; i++) {
+	  if (pattern[i]==0) num_zeros++;
+	}
+	newpattern=malloc(patternlen+num_zeros);
+	if (newpattern==NULL) {
+	  PyErr_SetString(PyExc_MemoryError, "can't allocate memory for new pattern");
+	  return NULL;
+	}
+	for (i=j=0; i<patternlen; i++, j++)
+	  {
+	    if (pattern[i]!=0) newpattern[j]=pattern[i];
+	    else {
+	      newpattern[j++]='\\';
+	      newpattern[j]  ='0';
+	    }
+	  }
+	newpattern[j]='\0';
+
+	rv->regex = pcre_compile(newpattern, options, 
+				 &error, &erroroffset, dictionary);
+	free(newpattern);
+	if (rv->regex==NULL) 
+	  {
+	    PyMem_DEL(rv);
+	    if (!PyErr_Occurred())
+	      PyErr_SetObject(ErrorObject, Py_BuildValue("si", error, erroroffset));
+	    return NULL;
+	  }
+	rv->regex_extra=pcre_study(rv->regex, 0, &error);
+	if (rv->regex_extra==NULL && error!=NULL) 
+	  {
+	    PyMem_DEL(rv);
+	    PyErr_SetObject(ErrorObject, Py_BuildValue("si", error, 0));
+	    return NULL;
+	  }
+        rv->num_groups = pcre_info(rv->regex, NULL, NULL);
+	if (rv->num_groups<0) 
+	  {
+	    PyErr_SetObject(ErrorObject, Py_BuildValue("si", "Regex error", rv->num_groups));
+	    PyMem_DEL(rv);
+	    return NULL;
+	  }
+	return (PyObject *)rv;
+}
+
+static PyObject *
+PyPcre_expand_escape(self, args)
+	PyObject *self;
+	PyObject *args;
+{
+  unsigned char c, *pattern;
+  int index, pattern_len;
+  const int context=REPLACEMENT;
+
+  if (!PyArg_ParseTuple(args, "s#i", &pattern, &pattern_len, &index)) 
+    return NULL;
+  if (pattern_len<=index)
+    {
+      PyErr_SetString(ErrorObject, "escape ends too soon");
+      return NULL;
+    }
+  c=pattern[index]; index++;
+  switch (c)
+    {
+    case('t'):
+      return Py_BuildValue("ici", CHAR, (char)9, index);
+      break;
+    case('n'):
+      return Py_BuildValue("ici", CHAR, (char)10, index);
+      break;
+    case('v'):
+      return Py_BuildValue("ici", CHAR, (char)11, index);
+      break;
+    case('r'):
+      return Py_BuildValue("ici", CHAR, (char)13, index);
+      break;
+    case('f'):
+      return Py_BuildValue("ici", CHAR, (char)12, index);
+      break;
+    case('a'):
+      return Py_BuildValue("ici", CHAR, (char)7, index);
+      break;
+    case('x'):
+      {
+	int end, length;
+	unsigned char *string;
+	PyObject *v, *result;
+
+	end=index; 
+	while (end<pattern_len && 
+	       ( pcre_ctypes[ pattern[end] ] & ctype_xdigit ) )
+	  end++;
+	if (end==index)
+	  {
+	    PyErr_SetString(ErrorObject, "\\x must be followed by hex digits");
+	    return NULL;
+	  }
+	length=end-index;
+	string=malloc(length+4+1);
+	if (string==NULL)
+	  {
+	    PyErr_SetString(PyExc_MemoryError, "can't allocate memory for \\x string");
+	    return NULL;
+	  }
+	/* Create a string containing "\x<hexdigits>", which will be
+	   passed to eval() */
+	string[0]=string[length+3]='"';
+	string[1]='\\';
+	string[length+4]='\0';
+	memcpy(string+2, pattern+index-1, length+1);
+	v=PyRun_String((char *)string, Py_eval_input, 
+		       PyEval_GetGlobals(), PyEval_GetLocals());
+	free(string);
+	/* The evaluation raised an exception */
+	if (v==NULL) return NULL;
+	result=Py_BuildValue("iOi", CHAR, v, end);
+	Py_DECREF(v);
+	return result;
+      }
+      break;
+
+    case('b'):
+      if (context!=NORMAL)
+	return Py_BuildValue("ici", CHAR, (char)8, index);
+      else 
+	{
+	  unsigned char empty_string[1];
+	  empty_string[0]='\0';
+	  return Py_BuildValue("isi", WORD_BOUNDARY, empty_string, index);
+	}
+      break;
+    case('B'):
+      if (context!=NORMAL)
+	return Py_BuildValue("ici", CHAR, 'B', index);
+      else 
+	{
+	  unsigned char empty_string[1];
+	  empty_string[0]='\0';
+	  return Py_BuildValue("isi", NOT_WORD_BOUNDARY, empty_string, index);
+	}
+      break;
+    case('A'):
+      if (context!=NORMAL)
+	return Py_BuildValue("ici", CHAR, 'A', index);
+      else 
+	{
+	  unsigned char empty_string[1];
+	  empty_string[0]='\0';
+	  return Py_BuildValue("isi", BEGINNING_OF_BUFFER, empty_string, index);
+	}
+      break;
+    case('Z'):
+      if (context!=NORMAL)
+	return Py_BuildValue("ici", CHAR, 'Z', index);
+      else 
+	{
+	  unsigned char empty_string[1];
+	  empty_string[0]='\0';
+	  return Py_BuildValue("isi", END_OF_BUFFER, empty_string, index);
+	}
+      break;
+    case('E'):    case('G'):    case('L'):    case('Q'):
+    case('U'):    case('l'):    case('u'):
+      {
+	char message[50];
+	sprintf(message, "\\%c is not allowed", c);
+	PyErr_SetString(ErrorObject, message);
+	return NULL;
+      }
+
+    case ('w'):
+      return Py_BuildValue("ici", CHAR, 'w', index);
+      break;
+    case ('W'):
+      return Py_BuildValue("ici", CHAR, 'W', index);
+      break;
+    case ('s'):
+	return Py_BuildValue("ici", CHAR, 's', index);
+      break;
+    case ('S'):
+	return Py_BuildValue("ici", CHAR, 'S', index);
+      break;
+
+    case ('d'):
+	return Py_BuildValue("ici", CHAR, 'd', index);
+      break;
+    case ('D'):
+	return Py_BuildValue("ici", CHAR, 'D', index);
+      break;
+
+    case('g'):
+      {
+	int end, valid, i;
+	if (pattern_len<=index)
+	  {
+	    PyErr_SetString(ErrorObject, "unfinished symbolic reference");
+	    return NULL;
+	  }
+	if (pattern[index]!='<')
+	  {
+	    PyErr_SetString(ErrorObject, "missing < in symbolic reference");
+	    return NULL;
+	  }
+	index++;
+	end=index;
+	while (end<pattern_len && pattern[end]!='>')
+	  end++;
+	if (end==pattern_len)
+	  {
+	    PyErr_SetString(ErrorObject, "unfinished symbolic reference");
+	    return NULL;
+	  }
+	valid=1;
+	if (index==end		/* Zero-length name */
+	    || !(pcre_ctypes[pattern[index]] & ctype_word) /* First char. not alphanumeric */
+	    || (pcre_ctypes[pattern[index]] & ctype_digit) ) /* First char. a digit */
+	  valid=0;
+
+	for(i=index+1; i<end; i++)
+	  {
+	    if (!(pcre_ctypes[pattern[i]] & ctype_word) )
+	      valid=0;
+	  }	
+	if (!valid)
+	  {
+	    /* XXX should include the text of the reference */
+	    PyErr_SetString(ErrorObject, "illegal symbolic reference");
+	    return NULL;
+	  }
+	    
+	return Py_BuildValue("is#i", MEMORY_REFERENCE, 
+			             pattern+index, end-index, 
+			             end+1);
+      }
+    break;
+
+    case('0'):
+      {
+	/* \0 always indicates an octal escape, so we consume up to 3
+	   characters, as long as they're all octal digits */
+	int octval=0, i;
+	index--;
+	for(i=index;
+	    i<=index+2 && i<pattern_len 
+	      && (pcre_ctypes[ pattern[i] ] & ctype_odigit );
+	    i++)
+	  {
+	    octval = octval * 8 + pattern[i] - '0';
+	  }
+	if (octval>255)
+	  {
+	    PyErr_SetString(ErrorObject, "octal value out of range");
+	    return NULL;
+	  }
+	return Py_BuildValue("ici", CHAR, (unsigned char)octval, i);
+      }
+      break;
+    case('1'):    case('2'):    case('3'):    case('4'):
+    case('5'):    case('6'):    case('7'):    case('8'):
+    case('9'):
+      {
+	/* Handle \?, where ? is from 1 through 9 */
+	int value=0;
+	index--;
+	/* If it's at least a two-digit reference, like \34, it might
+           either be a 3-digit octal escape (\123) or a 2-digit
+           decimal memory reference (\34) */
+
+	if ( (index+1) <pattern_len && 
+	    (pcre_ctypes[ pattern[index+1] ] & ctype_digit) )
+	  {
+	    if ( (index+2) <pattern_len && 
+		(pcre_ctypes[ pattern[index+2] ] & ctype_odigit) &&
+		(pcre_ctypes[ pattern[index+1] ] & ctype_odigit) &&
+		(pcre_ctypes[ pattern[index  ] ] & ctype_odigit)
+		)
+	      {
+		/* 3 octal digits */
+		value= 8*8*(pattern[index  ]-'0') +
+		         8*(pattern[index+1]-'0') +
+		           (pattern[index+2]-'0');
+		if (value>255)
+		  {
+		    PyErr_SetString(ErrorObject, "octal value out of range");
+		    return NULL;
+		  }
+		return Py_BuildValue("ici", CHAR, (unsigned char)value, index+3);
+	      }
+	    else
+	      {
+		/* 2-digit form, so it's a memory reference */
+		if (context==CHARCLASS)
+		  {
+		    PyErr_SetString(ErrorObject, "cannot reference a register "
+				    "from inside a character class");
+		    return NULL;
+		  }
+		value= 10*(pattern[index  ]-'0') +
+		          (pattern[index+1]-'0');
+		if (value<1 || EXTRACT_MAX<=value)
+		  {
+		    PyErr_SetString(ErrorObject, "memory reference out of range");
+		    return NULL;
+		  }
+		return Py_BuildValue("iii", MEMORY_REFERENCE, 
+				     value, index+2);
+	      }
+	  }
+	else 
+	  {
+	    /* Single-digit form, like \2, so it's a memory reference */
+	    if (context==CHARCLASS)
+	      {
+		PyErr_SetString(ErrorObject, "cannot reference a register "
+				"from inside a character class");
+		return NULL;
+	      }
+	    return Py_BuildValue("iii", MEMORY_REFERENCE, 
+				 pattern[index]-'0', index+1);
+	  }
+      }
+      break;
+
+    default:
+	return Py_BuildValue("ici", CHAR, c, index);
+	break;
+    }
+}
+
+static PyObject *
+PyPcre_expand(self, args)
+	PyObject *self;
+	PyObject *args;
+{
+  PyObject *results, *match_obj;
+  PyObject *repl_obj, *newstring;
+  unsigned char *repl;
+  int size, total_len, i, start, pos;
+
+  if (!PyArg_ParseTuple(args, "OS", &match_obj, &repl_obj)) 
+    return NULL;
+
+  repl=(unsigned char *)PyString_AsString(repl_obj);
+  size=PyString_Size(repl_obj);
+  results=PyList_New(0);
+  if (results==NULL) return NULL;
+  for(start=total_len=i=0; i<size; i++)
+    {
+      if (repl[i]=='\\')
+	{
+	  PyObject *args, *t, *value;
+	  int escape_type;
+
+	  if (start!=i)
+	    {
+	      PyList_Append(results, 
+			    PyString_FromStringAndSize((char *)repl+start, i-start));
+	      total_len += i-start;
+	    }
+	  i++;
+	  args=Py_BuildValue("Oi", repl_obj, i);
+	  t=PyPcre_expand_escape(NULL, args);
+	  Py_DECREF(args);
+	  if (t==NULL)
+	    {
+	      /* PyPcre_expand_escape triggered an exception of some sort,
+		 so just return */
+	      Py_DECREF(results);
+	      return NULL;
+	    }
+	  value=PyTuple_GetItem(t, 1);
+	  escape_type=PyInt_AsLong(PyTuple_GetItem(t, 0));
+	  switch (escape_type)
+	    {
+	    case (CHAR):
+	      PyList_Append(results, value);
+	      total_len += PyString_Size(value);
+	      break;
+	    case(MEMORY_REFERENCE):
+	      {
+		PyObject *r, *tuple, *result;
+		r=PyObject_GetAttrString(match_obj, "group");
+		tuple=PyTuple_New(1);
+		Py_INCREF(value);
+		PyTuple_SetItem(tuple, 0, value);
+		result=PyEval_CallObject(r, tuple);
+		Py_DECREF(r); Py_DECREF(tuple);
+		if (result==NULL)
+		  {
+		    /* The group() method trigged an exception of some sort */
+		    Py_DECREF(results);
+		    return NULL;
+		  }
+		if (result==Py_None)
+		  {
+		    char message[50];
+		    sprintf(message, 
+			    "group %li did not contribute to the match",
+			    PyInt_AsLong(value));
+		    PyErr_SetString(ErrorObject, 
+				    message);
+		    Py_DECREF(result);
+		    Py_DECREF(t);
+		    Py_DECREF(results);
+		    return NULL;
+		  }
+		/* XXX typecheck that it's a string! */
+		PyList_Append(results, result);
+		total_len += PyString_Size(result);
+		Py_DECREF(result);
+	      }
+	      break;
+	    default:
+	      Py_DECREF(t);
+	      Py_DECREF(results);
+	      PyErr_SetString(ErrorObject, 
+			      "bad escape in replacement");
+	      return NULL;
+	    }
+	  i=start=PyInt_AsLong(PyTuple_GetItem(t, 2));
+	  i--; /* Decrement now, because the 'for' loop will increment it */
+	  Py_DECREF(t);
+	}
+    } /* endif repl[i]!='\\' */
+
+  if (start!=i)
+    {
+      PyList_Append(results, PyString_FromStringAndSize((char *)repl+start, i-start));
+      total_len += i-start;
+    }
+
+  /* Whew!  Now we've constructed a list containing various pieces of
+     strings that will make up our final result.  So, iterate over 
+     the list concatenating them.  A new string measuring total_len
+     bytes is allocated and filled in. */
+     
+  newstring=PyString_FromStringAndSize(NULL, total_len);
+  if (newstring==NULL)
+    {
+      Py_DECREF(results);
+      return NULL;
+    }
+
+  repl=(unsigned char *)PyString_AsString(newstring);
+  for (pos=i=0; i<PyList_Size(results); i++)
+    {
+      PyObject *item=PyList_GetItem(results, i);
+      memcpy(repl+pos, PyString_AsString(item), PyString_Size(item) );
+      pos += PyString_Size(item);
+    }
+  Py_DECREF(results);
+  return newstring;
+}
+
+
+/* List of functions defined in the module */
+
+static PyMethodDef pcre_methods[] = {
+	{"pcre_compile",		PyPcre_compile,		1},
+	{"pcre_expand",		PyPcre_expand,		1},
+	{NULL,		NULL}		/* sentinel */
+};
+
+
+/*
+ * Convenience routine to export an integer value.
+ * For simplicity, errors (which are unlikely anyway) are ignored.
+ */
+
+static void
+insint(d, name, value)
+	PyObject * d;
+	char * name;
+	int value;
+{
+	PyObject *v = PyInt_FromLong((long) value);
+	if (v == NULL) {
+		/* Don't bother reporting this error */
+		PyErr_Clear();
+	}
+	else {
+		PyDict_SetItemString(d, name, v);
+		Py_DECREF(v);
+	}
+}
+
+
+/* Initialization function for the module (*must* be called initpcre) */
+
+void
+initpcre()
+{
+	PyObject *m, *d;
+	int a;
+
+	/* Create the module and add the functions */
+	m = Py_InitModule("pcre", pcre_methods);
+
+	/* Add some symbolic constants to the module */
+	d = PyModule_GetDict(m);
+	ErrorObject = PyString_FromString("pcre.error");
+	PyDict_SetItemString(d, "error", ErrorObject);
+
+	/* Insert the flags */
+	insint(d, "IGNORECASE", PCRE_CASELESS);
+	insint(d, "ANCHORED", PCRE_ANCHORED);
+	insint(d, "MULTILINE", PCRE_MULTILINE);
+	insint(d, "DOTALL", PCRE_DOTALL);
+	insint(d, "VERBOSE", PCRE_EXTENDED);
+	
+	/* Insert the opcodes */
+	insint(d, "OP_END", OP_END);
+	insint(d, "OP_SOD", OP_SOD);
+	insint(d, "OP_NOT_WORD_BOUNDARY", OP_NOT_WORD_BOUNDARY);
+	insint(d, "OP_WORD_BOUNDARY", OP_WORD_BOUNDARY);
+	insint(d, "OP_NOT_DIGIT", OP_NOT_DIGIT);
+	insint(d, "OP_NOT_WHITESPACE", OP_NOT_WHITESPACE);
+	insint(d, "OP_WHITESPACE", OP_WHITESPACE);
+	insint(d, "OP_NOT_WORDCHAR", OP_NOT_WORDCHAR);
+	insint(d, "OP_WORDCHAR", OP_WORDCHAR);
+	insint(d, "OP_EOD", OP_EOD);
+	insint(d, "OP_CIRC", OP_CIRC);
+	insint(d, "OP_DOLL", OP_DOLL);
+	insint(d, "OP_ANY", OP_ANY);
+	insint(d, "OP_CHARS", OP_CHARS);
+
+	insint(d, "OP_STAR", OP_STAR);
+	insint(d, "OP_MINSTAR", OP_MINSTAR);
+	insint(d, "OP_PLUS", OP_PLUS);
+	insint(d, "OP_MINPLUS", OP_MINPLUS);
+	insint(d, "OP_QUERY", OP_QUERY);
+	insint(d, "OP_MINQUERY", OP_MINQUERY);
+	insint(d, "OP_UPTO", OP_UPTO);
+	insint(d, "OP_MINUPTO", OP_MINUPTO);
+	insint(d, "OP_EXACT", OP_EXACT);
+
+	insint(d, "OP_TYPESTAR", OP_TYPESTAR);
+	insint(d, "OP_TYPEMINSTAR", OP_TYPEMINSTAR);
+	insint(d, "OP_TYPEPLUS", OP_TYPEPLUS);
+	insint(d, "OP_TYPEMINPLUS", OP_TYPEMINPLUS);
+	insint(d, "OP_TYPEQUERY", OP_TYPEQUERY);
+	insint(d, "OP_TYPEMINQUERY", OP_TYPEMINQUERY);
+	insint(d, "OP_TYPEUPTO", OP_TYPEUPTO);
+	insint(d, "OP_TYPEMINUPTO", OP_TYPEMINUPTO);
+	insint(d, "OP_TYPEEXACT", OP_TYPEEXACT);
+
+	insint(d, "OP_CRSTAR", OP_CRSTAR);
+	insint(d, "OP_CRMINSTAR", OP_CRMINSTAR);
+	insint(d, "OP_CRPLUS", OP_CRPLUS);
+	insint(d, "OP_CRMINPLUS", OP_CRMINPLUS);
+	insint(d, "OP_CRQUERY", OP_CRQUERY);
+	insint(d, "OP_CRMINQUERY", OP_CRMINQUERY);
+	insint(d, "OP_CRRANGE", OP_CRRANGE);
+	insint(d, "OP_CRMINRANGE", OP_CRMINRANGE);
+
+	insint(d, "OP_CLASS", OP_CLASS);
+	insint(d, "OP_NEGCLASS", OP_NEGCLASS);
+	insint(d, "OP_REF", OP_REF);
+
+	insint(d, "OP_ALT", OP_ALT);
+	insint(d, "OP_KET", OP_KET);
+	insint(d, "OP_KETRMAX", OP_KETRMAX);
+	insint(d, "OP_KETRMIN", OP_KETRMIN);
+
+	insint(d, "OP_ASSERT", OP_ASSERT);
+	insint(d, "OP_ASSERT_NOT", OP_ASSERT_NOT);
+
+	insint(d, "OP_BRAZERO", OP_BRAZERO);
+	insint(d, "OP_BRAMINZERO", OP_BRAMINZERO);
+	insint(d, "OP_BRA", OP_BRA);
+	
+	/* Check for errors */
+	if (PyErr_Occurred())
+		Py_FatalError("can't initialize module pcre");
+}
+