mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			636 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			636 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 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-int.h"
 | |
| 
 | |
| static PyObject *ErrorObject;
 | |
| 
 | |
| typedef struct {
 | |
| 	PyObject_HEAD
 | |
| 	pcre *regex;
 | |
| 	pcre_extra *regex_extra;
 | |
|         int num_groups;
 | |
| } PcreObject;
 | |
| 
 | |
| static 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
 | |
| #define STRING                  9
 | |
| 
 | |
| static PcreObject *
 | |
| newPcreObject(PyObject *args)
 | |
| {
 | |
| 	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(PcreObject *self)
 | |
| {
 | |
| 	if (self->regex) (pcre_free)(self->regex);
 | |
| 	if (self->regex_extra) (pcre_free)(self->regex_extra);
 | |
| 	PyObject_Del(self);
 | |
| }
 | |
| 
 | |
| 
 | |
| static PyObject *
 | |
| PyPcre_exec(PcreObject *self, PyObject *args)
 | |
| {
 | |
|         char *string;
 | |
| 	int stringlen, pos = 0, options=0, endpos = -1, i, count;
 | |
| 	int offsets[100*2]; 
 | |
| 	PyObject *list;
 | |
| 
 | |
| 	if (!PyArg_ParseTuple(args, "t#|iii:match", &string, &stringlen, 
 | |
|                                      &pos, &endpos, &options))
 | |
| 		return NULL;
 | |
| 	if (endpos == -1) {endpos = stringlen;}
 | |
| 	count = pcre_exec(self->regex, self->regex_extra, 
 | |
| 			  string, endpos, pos, options,
 | |
| 			  offsets, sizeof(offsets)/sizeof(int) );
 | |
| 	/* If an error occurred during the match, and an exception was raised,
 | |
| 	   just return NULL and leave the exception alone.  The most likely
 | |
| 	   problem to cause this would be running out of memory for
 | |
| 	   the failure stack. */
 | |
| 	if (PyErr_Occurred())
 | |
| 	{
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	if (count==PCRE_ERROR_NOMATCH) {Py_INCREF(Py_None); return Py_None;}
 | |
| 	if (count<0)
 | |
| 	{
 | |
| 		PyObject *errval = Py_BuildValue("si", "Regex execution error", count);
 | |
| 		PyErr_SetObject(ErrorObject, errval);
 | |
| 		Py_XDECREF(errval);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	
 | |
| 	list=PyList_New(self->num_groups+1);
 | |
| 	if (list==NULL) return NULL;
 | |
| 	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;}
 | |
| 		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,	METH_VARARGS},
 | |
| 	{NULL,		NULL}		/* sentinel */
 | |
| };
 | |
| 
 | |
| static PyObject *
 | |
| PyPcre_getattr(PcreObject *self, char *name)
 | |
| {
 | |
| 	return Py_FindMethod(Pcre_methods, (PyObject *)self, name);
 | |
| }
 | |
| 
 | |
| 
 | |
| static PyTypeObject Pcre_Type = {
 | |
| 	PyObject_HEAD_INIT(NULL)
 | |
| 	0,			/*ob_size*/
 | |
| 	"pcre.Pcre",		/*tp_name*/
 | |
| 	sizeof(PcreObject),	/*tp_basicsize*/
 | |
| 	0,			/*tp_itemsize*/
 | |
| 	/* methods */
 | |
| 	(destructor)PyPcre_dealloc, /*tp_dealloc*/
 | |
| 	0,			/*tp_print*/
 | |
| 	(getattrfunc)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(PyObject *self, PyObject *args)
 | |
| {
 | |
| 	PcreObject *rv;
 | |
| 	PyObject *dictionary;
 | |
| 	char *pattern;
 | |
| 	const char *error;
 | |
| 	
 | |
| 	int options, erroroffset;
 | |
| 	if (!PyArg_ParseTuple(args, "siO!:pcre_compile", &pattern, &options,
 | |
| 			      &PyDict_Type, &dictionary))
 | |
| 		return NULL;
 | |
| 	rv = newPcreObject(args);
 | |
| 	if ( rv == NULL )
 | |
| 		return NULL;
 | |
| 
 | |
| 	rv->regex = pcre_compile((char*)pattern, options, 
 | |
| 				 &error, &erroroffset, dictionary);
 | |
| 	if (rv->regex==NULL) 
 | |
| 	{
 | |
| 		Py_DECREF(rv);
 | |
| 		if (!PyErr_Occurred())
 | |
| 		{
 | |
| 			PyObject *errval = Py_BuildValue("si", error, erroroffset);
 | |
| 			PyErr_SetObject(ErrorObject, errval);
 | |
| 			Py_XDECREF(errval);
 | |
| 		}
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	rv->regex_extra=pcre_study(rv->regex, 0, &error);
 | |
| 	if (rv->regex_extra==NULL && error!=NULL) 
 | |
| 	{
 | |
| 		PyObject *errval = Py_BuildValue("si", error, 0);
 | |
| 		Py_DECREF(rv);
 | |
| 		PyErr_SetObject(ErrorObject, errval);
 | |
| 		Py_XDECREF(errval);
 | |
| 		return NULL;
 | |
| 	}
 | |
|         rv->num_groups = pcre_info(rv->regex, NULL, NULL);
 | |
| 	if (rv->num_groups<0) 
 | |
| 	{
 | |
| 		PyObject *errval = Py_BuildValue("si", error, rv->num_groups);
 | |
| 		PyErr_SetObject(ErrorObject, errval);
 | |
| 		Py_XDECREF(errval);
 | |
| 		Py_DECREF(rv);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	return (PyObject *)rv;
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| PyPcre_expand_escape(unsigned char *pattern, int pattern_len,
 | |
|                      int *indexptr, int *typeptr)
 | |
| {
 | |
| 	unsigned char c;
 | |
| 	int index = *indexptr;
 | |
|   
 | |
| 	if (pattern_len<=index)
 | |
| 	{
 | |
| 		PyErr_SetString(ErrorObject, "escape ends too soon");
 | |
| 		return NULL;
 | |
| 	}
 | |
| 	c=pattern[index]; index++;
 | |
| 	*typeptr=CHAR;
 | |
| 
 | |
| 	switch (c)
 | |
| 	{
 | |
| 	case('t'):
 | |
| 		*indexptr=index;
 | |
| 		return Py_BuildValue("c", (char)9);
 | |
| 	case('n'):
 | |
| 		*indexptr = index;
 | |
| 		return Py_BuildValue("c", (char)10);
 | |
| 	case('v'):
 | |
| 		*indexptr = index;
 | |
| 		return Py_BuildValue("c", (char)11);
 | |
| 	case('r'):
 | |
| 		*indexptr = index;
 | |
| 		return Py_BuildValue("c", (char)13);
 | |
| 	case('f'):
 | |
| 		*indexptr = index;
 | |
| 		return Py_BuildValue("c", (char)12);
 | |
| 	case('a'):
 | |
| 		*indexptr = index;
 | |
| 		return Py_BuildValue("c", (char)7);
 | |
| 	case('b'):
 | |
| 		*indexptr=index;
 | |
| 		return Py_BuildValue("c", (char)8);
 | |
| 	case('\\'):
 | |
| 		*indexptr=index;
 | |
| 		return Py_BuildValue("c", '\\');
 | |
| 
 | |
| 	case('x'):
 | |
| 	{
 | |
| 		int x, ch, end;
 | |
| 
 | |
| 		x = 0; end = index;
 | |
| 		while ( (end<pattern_len && pcre_ctypes[ pattern[end] ] & ctype_xdigit) != 0)
 | |
| 		{
 | |
| 			ch = pattern[end];
 | |
| 			x = x * 16 + pcre_lcc[ch] -
 | |
| 				(((pcre_ctypes[ch] & ctype_digit) != 0)? '0' : 'W');
 | |
| 			x &= 255;
 | |
| 			end++;
 | |
| 		}
 | |
| 		if (end==index)
 | |
| 		{
 | |
| 			PyErr_SetString(ErrorObject, "\\x must be followed by hex digits");
 | |
| 			return NULL;
 | |
| 		}
 | |
| 		*indexptr = end;
 | |
| 		return Py_BuildValue("c", (char)x);
 | |
| 	}
 | |
| 
 | |
| 	case('E'):    case('G'):    case('L'):    case('Q'):
 | |
| 	case('U'):    case('l'):    case('u'):
 | |
| 	{
 | |
| 		char message[50];
 | |
| 		PyOS_snprintf(message, sizeof(message),
 | |
| 			      "\\%c is not allowed", c);
 | |
| 		PyErr_SetString(ErrorObject, message);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	case('g'):
 | |
| 	{
 | |
| 		int end, i;
 | |
| 		int group_num = 0, is_number=0;
 | |
| 
 | |
| 		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;
 | |
| 		}
 | |
| 
 | |
| 		if (index==end)		/* Zero-length name */
 | |
| 		{
 | |
| 			/* XXX should include the text of the reference */
 | |
| 			PyErr_SetString(ErrorObject, "zero-length symbolic reference");
 | |
| 			return NULL;
 | |
| 		}
 | |
| 		if ((pcre_ctypes[pattern[index]] & ctype_digit)) /* First char. a digit */
 | |
| 		{
 | |
| 		        is_number = 1;
 | |
| 			group_num = pattern[index] - '0';
 | |
| 		}
 | |
| 
 | |
| 		for(i=index+1; i<end; i++)
 | |
| 		{
 | |
| 		        if (is_number && 
 | |
| 			    !(pcre_ctypes[pattern[i]] & ctype_digit) )
 | |
| 			{
 | |
| 				/* XXX should include the text of the reference */
 | |
| 				PyErr_SetString(ErrorObject, "illegal non-digit character in \\g<...> starting with digit");
 | |
| 				return NULL;			       
 | |
| 			}
 | |
| 			else {group_num = group_num * 10 + pattern[i] - '0';}
 | |
| 			if (!(pcre_ctypes[pattern[i]] & ctype_word) )
 | |
| 			{
 | |
| 				/* XXX should include the text of the reference */
 | |
| 				PyErr_SetString(ErrorObject, "illegal symbolic reference");
 | |
| 				return NULL;
 | |
| 			}
 | |
| 		}	
 | |
| 	    
 | |
| 		*typeptr = MEMORY_REFERENCE;
 | |
| 		*indexptr = end+1;
 | |
| 		/* If it's a number, return the integer value of the group */
 | |
| 		if (is_number) return Py_BuildValue("i", group_num);
 | |
| 		/* Otherwise, return a string containing the group name */
 | |
| 		return Py_BuildValue("s#", pattern+index, end-index);
 | |
| 	}
 | |
| 
 | |
| 	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;
 | |
| 		}
 | |
| 		*indexptr = i;
 | |
| 		return Py_BuildValue("c", (unsigned char)octval);
 | |
| 	}
 | |
| 
 | |
| 	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;
 | |
| 				}
 | |
| 				*indexptr = index+3;
 | |
| 				return Py_BuildValue("c", (unsigned char)value);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				/* 2-digit form, so it's a memory reference */
 | |
| 				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;
 | |
| 				}
 | |
| 				*typeptr = MEMORY_REFERENCE;
 | |
| 				*indexptr = index+2;
 | |
| 				return Py_BuildValue("i", value);
 | |
| 			}
 | |
| 		}
 | |
| 		else 
 | |
| 		{
 | |
| 			/* Single-digit form, like \2, so it's a memory reference */
 | |
| 			*typeptr = MEMORY_REFERENCE;
 | |
| 			*indexptr = index+1;
 | |
| 			return Py_BuildValue("i", pattern[index]-'0');
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	default:
 | |
| 	  /* It's some unknown escape like \s, so return a string containing
 | |
| 	     \s */
 | |
| 		*typeptr = STRING;
 | |
| 		*indexptr = index;
 | |
| 		return Py_BuildValue("s#", pattern+index-2, 2);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| PyPcre_expand(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:pcre_expand", &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 *value;
 | |
| 			int escape_type;
 | |
| 
 | |
| 			if (start!=i)
 | |
| 			{
 | |
| 				int status;
 | |
| 				PyObject *s = PyString_FromStringAndSize(
 | |
| 					(char *)repl+start, i-start);
 | |
| 				if (s == NULL) {
 | |
| 					Py_DECREF(results);
 | |
| 					return NULL;
 | |
| 				}
 | |
| 				status = PyList_Append(results, s);
 | |
| 				Py_DECREF(s);
 | |
| 				if (status < 0) {
 | |
| 					Py_DECREF(results);
 | |
| 					return NULL;
 | |
| 				}
 | |
| 				total_len += i-start;
 | |
| 			}
 | |
| 			i++;
 | |
| 			value=PyPcre_expand_escape(repl, size, &i, &escape_type);
 | |
| 			if (value==NULL)
 | |
| 			{
 | |
| 				/* PyPcre_expand_escape triggered an exception of some sort,
 | |
| 				   so just return */
 | |
| 				Py_DECREF(results);
 | |
| 				return NULL;
 | |
| 			}
 | |
| 			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");
 | |
| 				if (r == NULL) {
 | |
| 					Py_DECREF(results);
 | |
| 					return NULL;
 | |
| 				}
 | |
| 				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 triggered an exception of some sort */
 | |
| 					Py_DECREF(results);
 | |
| 					Py_DECREF(value);
 | |
| 					return NULL;
 | |
| 				}
 | |
| 				if (result==Py_None)
 | |
| 				{
 | |
| 					char message[50];
 | |
| 					PyOS_snprintf(message, sizeof(message),
 | |
| 						"group did not contribute to the match");
 | |
| 					PyErr_SetString(ErrorObject, 
 | |
| 							message);
 | |
| 					Py_DECREF(result);
 | |
| 					Py_DECREF(value);
 | |
| 					Py_DECREF(results);
 | |
| 					return NULL;
 | |
| 				}
 | |
| 				/* typecheck that it's a string! */
 | |
| 				if (!PyString_Check(result))
 | |
| 				{
 | |
| 					Py_DECREF(results);
 | |
| 					Py_DECREF(result);
 | |
| 					PyErr_SetString(ErrorObject, 
 | |
| 							"group() must return a string value for replacement");
 | |
| 					return NULL;
 | |
| 				}
 | |
| 				PyList_Append(results, result);
 | |
| 				total_len += PyString_Size(result);
 | |
| 				Py_DECREF(result);
 | |
| 			}
 | |
| 			break;
 | |
| 			case(STRING):
 | |
| 			  {
 | |
| 			    PyList_Append(results, value);
 | |
| 			    total_len += PyString_Size(value);
 | |
| 			    break;
 | |
| 			  }
 | |
| 			default:
 | |
| 				Py_DECREF(results);
 | |
| 				PyErr_SetString(ErrorObject, 
 | |
| 						"bad escape in replacement");
 | |
| 				return NULL;
 | |
| 			}
 | |
| 			Py_DECREF(value);
 | |
| 			start=i;
 | |
| 			i--; /* Decrement now, because the 'for' loop will increment it */
 | |
| 		}
 | |
| 	} /* endif repl[i]!='\\' */
 | |
| 
 | |
| 	if (start!=i)
 | |
| 	{
 | |
| 		int status;
 | |
| 		PyObject *s = PyString_FromStringAndSize((char *)repl+start, 
 | |
| 							 i-start);
 | |
| 		if (s == NULL) {
 | |
| 			Py_DECREF(results);
 | |
| 			return NULL;
 | |
| 		}
 | |
| 		status = PyList_Append(results, s);
 | |
| 		Py_DECREF(s);
 | |
| 		if (status < 0) {
 | |
| 			Py_DECREF(results);
 | |
| 			return NULL;
 | |
| 		}
 | |
| 		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,		METH_VARARGS},
 | |
| 	{"pcre_expand",		PyPcre_expand,		METH_VARARGS},
 | |
| 	{NULL,		NULL}		/* sentinel */
 | |
| };
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Convenience routine to export an integer value.
 | |
|  * For simplicity, errors (which are unlikely anyway) are ignored.
 | |
|  */
 | |
| 
 | |
| static void
 | |
| insint(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) */
 | |
| 
 | |
| PyMODINIT_FUNC
 | |
| initpcre(void)
 | |
| {
 | |
| 	PyObject *m, *d;
 | |
| 
 | |
|         Pcre_Type.ob_type = &PyType_Type;
 | |
| 
 | |
| 	/* 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 = PyErr_NewException("pcre.error", NULL, NULL);
 | |
| 	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);
 | |
| 	insint(d, "LOCALE", PCRE_LOCALE);
 | |
| }
 | |
| 
 | 
