diff options
Diffstat (limited to 'Modules/regexmodule.c')
-rw-r--r-- | Modules/regexmodule.c | 690 |
1 files changed, 0 insertions, 690 deletions
diff --git a/Modules/regexmodule.c b/Modules/regexmodule.c deleted file mode 100644 index 2fb4198..0000000 --- a/Modules/regexmodule.c +++ /dev/null @@ -1,690 +0,0 @@ -/* -XXX support range parameter on search -XXX support mstop parameter on search -*/ - - -/* Regular expression objects */ -/* This uses Tatu Ylonen's copyleft-free reimplementation of - GNU regular expressions */ - -#include "Python.h" - -#include <ctype.h> - -#include "regexpr.h" - -static PyObject *RegexError; /* Exception */ - -typedef struct { - PyObject_HEAD - struct re_pattern_buffer re_patbuf; /* The compiled expression */ - struct re_registers re_regs; /* The registers from the last match */ - char re_fastmap[256]; /* Storage for fastmap */ - PyObject *re_translate; /* String object for translate table */ - PyObject *re_lastok; /* String object last matched/searched */ - PyObject *re_groupindex; /* Group name to index dictionary */ - PyObject *re_givenpat; /* Pattern with symbolic groups */ - PyObject *re_realpat; /* Pattern without symbolic groups */ -} regexobject; - -/* Regex object methods */ - -static void -reg_dealloc(regexobject *re) -{ - if (re->re_patbuf.buffer) - free(re->re_patbuf.buffer); - Py_XDECREF(re->re_translate); - Py_XDECREF(re->re_lastok); - Py_XDECREF(re->re_groupindex); - Py_XDECREF(re->re_givenpat); - Py_XDECREF(re->re_realpat); - PyObject_Del(re); -} - -static PyObject * -makeresult(struct re_registers *regs) -{ - PyObject *v; - int i; - static PyObject *filler = NULL; - - if (filler == NULL) { - filler = Py_BuildValue("(ii)", -1, -1); - if (filler == NULL) - return NULL; - } - v = PyTuple_New(RE_NREGS); - if (v == NULL) - return NULL; - - for (i = 0; i < RE_NREGS; i++) { - int lo = regs->start[i]; - int hi = regs->end[i]; - PyObject *w; - if (lo == -1 && hi == -1) { - w = filler; - Py_INCREF(w); - } - else - w = Py_BuildValue("(ii)", lo, hi); - if (w == NULL || PyTuple_SetItem(v, i, w) < 0) { - Py_DECREF(v); - return NULL; - } - } - return v; -} - -static PyObject * -regobj_match(regexobject *re, PyObject *args) -{ - PyObject *argstring; - char *buffer; - int size; - int offset = 0; - int result; - - if (!PyArg_ParseTuple(args, "O|i:match", &argstring, &offset)) - return NULL; - if (!PyArg_Parse(argstring, "t#", &buffer, &size)) - return NULL; - - if (offset < 0 || offset > size) { - PyErr_SetString(RegexError, "match offset out of range"); - return NULL; - } - Py_XDECREF(re->re_lastok); - re->re_lastok = NULL; - result = _Py_re_match(&re->re_patbuf, (unsigned char *)buffer, size, offset, - &re->re_regs); - if (result < -1) { - /* Serious failure of some sort; if re_match didn't - set an exception, raise a generic error */ - if (!PyErr_Occurred()) - PyErr_SetString(RegexError, "match failure"); - return NULL; - } - if (result >= 0) { - Py_INCREF(argstring); - re->re_lastok = argstring; - } - return PyInt_FromLong((long)result); /* Length of the match or -1 */ -} - -static PyObject * -regobj_search(regexobject *re, PyObject *args) -{ - PyObject *argstring; - char *buffer; - int size; - int offset = 0; - int range; - int result; - - if (!PyArg_ParseTuple(args, "O|i:search", &argstring, &offset)) - return NULL; - if (!PyArg_Parse(argstring, "t#:search", &buffer, &size)) - return NULL; - - if (offset < 0 || offset > size) { - PyErr_SetString(RegexError, "search offset out of range"); - return NULL; - } - /* NB: In Emacs 18.57, the documentation for re_search[_2] and - the implementation don't match: the documentation states that - |range| positions are tried, while the code tries |range|+1 - positions. It seems more productive to believe the code! */ - range = size - offset; - Py_XDECREF(re->re_lastok); - re->re_lastok = NULL; - result = _Py_re_search(&re->re_patbuf, (unsigned char *)buffer, size, offset, range, - &re->re_regs); - if (result < -1) { - /* Serious failure of some sort; if re_match didn't - set an exception, raise a generic error */ - if (!PyErr_Occurred()) - PyErr_SetString(RegexError, "match failure"); - return NULL; - } - if (result >= 0) { - Py_INCREF(argstring); - re->re_lastok = argstring; - } - return PyInt_FromLong((long)result); /* Position of the match or -1 */ -} - -/* get the group from the regex where index can be a string (group name) or - an integer index [0 .. 99] - */ -static PyObject* -group_from_index(regexobject *re, PyObject *index) -{ - int i, a, b; - char *v; - - if (PyString_Check(index)) - if (re->re_groupindex == NULL || - !(index = PyDict_GetItem(re->re_groupindex, index))) - { - PyErr_SetString(RegexError, - "group() group name doesn't exist"); - return NULL; - } - - i = PyInt_AsLong(index); - if (i == -1 && PyErr_Occurred()) - return NULL; - - if (i < 0 || i >= RE_NREGS) { - PyErr_SetString(RegexError, "group() index out of range"); - return NULL; - } - if (re->re_lastok == NULL) { - PyErr_SetString(RegexError, - "group() only valid after successful match/search"); - return NULL; - } - a = re->re_regs.start[i]; - b = re->re_regs.end[i]; - if (a < 0 || b < 0) { - Py_INCREF(Py_None); - return Py_None; - } - - if (!(v = PyString_AsString(re->re_lastok))) - return NULL; - - return PyString_FromStringAndSize(v+a, b-a); -} - - -static PyObject * -regobj_group(regexobject *re, PyObject *args) -{ - int n = PyTuple_Size(args); - int i; - PyObject *res = NULL; - - if (n < 0) - return NULL; - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "not enough arguments"); - return NULL; - } - if (n == 1) { - /* return value is a single string */ - PyObject *index = PyTuple_GetItem(args, 0); - if (!index) - return NULL; - - return group_from_index(re, index); - } - - /* return value is a tuple */ - if (!(res = PyTuple_New(n))) - return NULL; - - for (i = 0; i < n; i++) { - PyObject *index = PyTuple_GetItem(args, i); - PyObject *group = NULL; - - if (!index) - goto finally; - if (!(group = group_from_index(re, index))) - goto finally; - if (PyTuple_SetItem(res, i, group) < 0) - goto finally; - } - return res; - - finally: - Py_DECREF(res); - return NULL; -} - - -static struct PyMethodDef reg_methods[] = { - {"match", (PyCFunction)regobj_match, METH_VARARGS}, - {"search", (PyCFunction)regobj_search, METH_VARARGS}, - {"group", (PyCFunction)regobj_group, METH_VARARGS}, - {NULL, NULL} /* sentinel */ -}; - - - -static char* members[] = { - "last", "regs", "translate", - "groupindex", "realpat", "givenpat", - NULL -}; - - -static PyObject * -regobj_getattr(regexobject *re, char *name) -{ - if (strcmp(name, "regs") == 0) { - if (re->re_lastok == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return makeresult(&re->re_regs); - } - if (strcmp(name, "last") == 0) { - if (re->re_lastok == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - Py_INCREF(re->re_lastok); - return re->re_lastok; - } - if (strcmp(name, "translate") == 0) { - if (re->re_translate == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - Py_INCREF(re->re_translate); - return re->re_translate; - } - if (strcmp(name, "groupindex") == 0) { - if (re->re_groupindex == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - Py_INCREF(re->re_groupindex); - return re->re_groupindex; - } - if (strcmp(name, "realpat") == 0) { - if (re->re_realpat == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - Py_INCREF(re->re_realpat); - return re->re_realpat; - } - if (strcmp(name, "givenpat") == 0) { - if (re->re_givenpat == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - Py_INCREF(re->re_givenpat); - return re->re_givenpat; - } - if (strcmp(name, "__members__") == 0) { - int i = 0; - PyObject *list = NULL; - - /* okay, so it's unlikely this list will change that often. - still, it's easier to change it in just one place. - */ - while (members[i]) - i++; - if (!(list = PyList_New(i))) - return NULL; - - i = 0; - while (members[i]) { - PyObject* v = PyString_FromString(members[i]); - if (!v || PyList_SetItem(list, i, v) < 0) { - Py_DECREF(list); - return NULL; - } - i++; - } - return list; - } - return Py_FindMethod(reg_methods, (PyObject *)re, name); -} - -static PyTypeObject Regextype = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "regex.regex", /*tp_name*/ - sizeof(regexobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)reg_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)regobj_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ -}; - -/* reference counting invariants: - pattern: borrowed - translate: borrowed - givenpat: borrowed - groupindex: transferred -*/ -static PyObject * -newregexobject(PyObject *pattern, PyObject *translate, PyObject *givenpat, PyObject *groupindex) -{ - regexobject *re; - char *pat; - int size; - - if (!PyArg_Parse(pattern, "t#", &pat, &size)) - return NULL; - - if (translate != NULL && PyString_Size(translate) != 256) { - PyErr_SetString(RegexError, - "translation table must be 256 bytes"); - return NULL; - } - re = PyObject_New(regexobject, &Regextype); - if (re != NULL) { - char *error; - re->re_patbuf.buffer = NULL; - re->re_patbuf.allocated = 0; - re->re_patbuf.fastmap = (unsigned char *)re->re_fastmap; - if (translate) { - re->re_patbuf.translate = (unsigned char *)PyString_AsString(translate); - if (!re->re_patbuf.translate) - goto finally; - Py_INCREF(translate); - } - else - re->re_patbuf.translate = NULL; - re->re_translate = translate; - re->re_lastok = NULL; - re->re_groupindex = groupindex; - Py_INCREF(pattern); - re->re_realpat = pattern; - Py_INCREF(givenpat); - re->re_givenpat = givenpat; - error = _Py_re_compile_pattern((unsigned char *)pat, size, &re->re_patbuf); - if (error != NULL) { - PyErr_SetString(RegexError, error); - goto finally; - } - } - return (PyObject *)re; - finally: - Py_DECREF(re); - return NULL; -} - -static PyObject * -regex_compile(PyObject *self, PyObject *args) -{ - PyObject *pat = NULL; - PyObject *tran = NULL; - - if (!PyArg_ParseTuple(args, "S|S:compile", &pat, &tran)) - return NULL; - return newregexobject(pat, tran, pat, NULL); -} - -static PyObject * -symcomp(PyObject *pattern, PyObject *gdict) -{ - char *opat, *oend, *o, *n, *g, *v; - int group_count = 0; - int sz; - int escaped = 0; - char name_buf[128]; - PyObject *npattern; - int require_escape = re_syntax & RE_NO_BK_PARENS ? 0 : 1; - - if (!(opat = PyString_AsString(pattern))) - return NULL; - - if ((sz = PyString_Size(pattern)) < 0) - return NULL; - - oend = opat + sz; - o = opat; - - if (oend == opat) { - Py_INCREF(pattern); - return pattern; - } - - if (!(npattern = PyString_FromStringAndSize((char*)NULL, sz)) || - !(n = PyString_AsString(npattern))) - return NULL; - - while (o < oend) { - if (*o == '(' && escaped == require_escape) { - char *backtrack; - escaped = 0; - ++group_count; - *n++ = *o; - if (++o >= oend || *o != '<') - continue; - /* *o == '<' */ - if (o+1 < oend && *(o+1) == '>') - continue; - backtrack = o; - g = name_buf; - for (++o; o < oend;) { - if (*o == '>') { - PyObject *group_name = NULL; - PyObject *group_index = NULL; - *g++ = '\0'; - group_name = PyString_FromString(name_buf); - group_index = PyInt_FromLong(group_count); - if (group_name == NULL || - group_index == NULL || - PyDict_SetItem(gdict, group_name, - group_index) != 0) - { - Py_XDECREF(group_name); - Py_XDECREF(group_index); - Py_XDECREF(npattern); - return NULL; - } - Py_DECREF(group_name); - Py_DECREF(group_index); - ++o; /* eat the '>' */ - break; - } - if (!isalnum(Py_CHARMASK(*o)) && *o != '_') { - o = backtrack; - break; - } - *g++ = *o++; - } - } - else if (*o == '[' && !escaped) { - *n++ = *o; - ++o; /* eat the char following '[' */ - *n++ = *o; - while (o < oend && *o != ']') { - ++o; - *n++ = *o; - } - if (o < oend) - ++o; - } - else if (*o == '\\') { - escaped = 1; - *n++ = *o; - ++o; - } - else { - escaped = 0; - *n++ = *o; - ++o; - } - } - - if (!(v = PyString_AsString(npattern))) { - Py_DECREF(npattern); - return NULL; - } - /* _PyString_Resize() decrements npattern on failure */ - _PyString_Resize(&npattern, n - v); - return npattern; - -} - -static PyObject * -regex_symcomp(PyObject *self, PyObject *args) -{ - PyObject *pattern; - PyObject *tran = NULL; - PyObject *gdict = NULL; - PyObject *npattern; - PyObject *retval = NULL; - - if (!PyArg_ParseTuple(args, "S|S:symcomp", &pattern, &tran)) - return NULL; - - gdict = PyDict_New(); - if (gdict == NULL || (npattern = symcomp(pattern, gdict)) == NULL) { - Py_XDECREF(gdict); - return NULL; - } - retval = newregexobject(npattern, tran, pattern, gdict); - Py_DECREF(npattern); - return retval; -} - - -static PyObject *cache_pat; -static PyObject *cache_prog; - -static int -update_cache(PyObject *pat) -{ - PyObject *tuple = PyTuple_Pack(1, pat); - int status = 0; - - if (!tuple) - return -1; - - if (pat != cache_pat) { - Py_XDECREF(cache_pat); - cache_pat = NULL; - Py_XDECREF(cache_prog); - cache_prog = regex_compile((PyObject *)NULL, tuple); - if (cache_prog == NULL) { - status = -1; - goto finally; - } - cache_pat = pat; - Py_INCREF(cache_pat); - } - finally: - Py_DECREF(tuple); - return status; -} - -static PyObject * -regex_match(PyObject *self, PyObject *args) -{ - PyObject *pat, *string; - PyObject *tuple, *v; - - if (!PyArg_ParseTuple(args, "SS:match", &pat, &string)) - return NULL; - if (update_cache(pat) < 0) - return NULL; - - if (!(tuple = Py_BuildValue("(S)", string))) - return NULL; - v = regobj_match((regexobject *)cache_prog, tuple); - Py_DECREF(tuple); - return v; -} - -static PyObject * -regex_search(PyObject *self, PyObject *args) -{ - PyObject *pat, *string; - PyObject *tuple, *v; - - if (!PyArg_ParseTuple(args, "SS:search", &pat, &string)) - return NULL; - if (update_cache(pat) < 0) - return NULL; - - if (!(tuple = Py_BuildValue("(S)", string))) - return NULL; - v = regobj_search((regexobject *)cache_prog, tuple); - Py_DECREF(tuple); - return v; -} - -static PyObject * -regex_set_syntax(PyObject *self, PyObject *args) -{ - int syntax; - if (!PyArg_ParseTuple(args, "i:set_syntax", &syntax)) - return NULL; - syntax = re_set_syntax(syntax); - /* wipe the global pattern cache */ - Py_XDECREF(cache_pat); - cache_pat = NULL; - Py_XDECREF(cache_prog); - cache_prog = NULL; - return PyInt_FromLong((long)syntax); -} - -static PyObject * -regex_get_syntax(PyObject *self) -{ - return PyInt_FromLong((long)re_syntax); -} - - -static struct PyMethodDef regex_global_methods[] = { - {"compile", regex_compile, METH_VARARGS}, - {"symcomp", regex_symcomp, METH_VARARGS}, - {"match", regex_match, METH_VARARGS}, - {"search", regex_search, METH_VARARGS}, - {"set_syntax", regex_set_syntax, METH_VARARGS}, - {"get_syntax", (PyCFunction)regex_get_syntax, METH_NOARGS}, - {NULL, NULL} /* sentinel */ -}; - -PyMODINIT_FUNC -initregex(void) -{ - PyObject *m, *d, *v; - int i; - char *s; - - /* Initialize object type */ - Regextype.ob_type = &PyType_Type; - - m = Py_InitModule("regex", regex_global_methods); - if (m == NULL) - return; - d = PyModule_GetDict(m); - - if (PyErr_Warn(PyExc_DeprecationWarning, - "the regex module is deprecated; " - "please use the re module") < 0) - return; - - /* Initialize regex.error exception */ - v = RegexError = PyErr_NewException("regex.error", NULL, NULL); - if (v == NULL || PyDict_SetItemString(d, "error", v) != 0) - goto finally; - - /* Initialize regex.casefold constant */ - if (!(v = PyString_FromStringAndSize((char *)NULL, 256))) - goto finally; - - if (!(s = PyString_AsString(v))) - goto finally; - - for (i = 0; i < 256; i++) { - if (isupper(i)) - s[i] = tolower(i); - else - s[i] = i; - } - if (PyDict_SetItemString(d, "casefold", v) < 0) - goto finally; - Py_DECREF(v); - - if (!PyErr_Occurred()) - return; - finally: - /* Nothing */ ; -} |