[Python-checkins] CVS: python/dist/src/Modules pyexpat.c,2.39,2.40

Fred L. Drake fdrake@users.sourceforge.net
Wed, 14 Feb 2001 10:29:47 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv18719

Modified Files:
	pyexpat.c 
Log Message:
xmlparseobject:  Remove the unused conv_attrs field, added an
    in_callback field that's set to true whenever a callback into an
    event handler is true.  Needed for:

set_error():  Add line number of offset information to the exception
    as attributes, so users don't need to parse the text of the
    message.

set_error_attr():  New helper function for set_error().

xmlparse_GetInputContext():  New function of the parser object;
    returns the document source for an event during a callback, None
    at all other times.

xmlparse_SetParamEntityParsing():  Make the signature consistent with
    the other parser methods (use xmlparseobject* for self instead of
    PyObject*).

initpyexpat():  Don't lose the reference to the exception class!

call_with_frame(),
getcode():  Re-indent to be consistent with the rest of the file.


Index: pyexpat.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/pyexpat.c,v
retrieving revision 2.39
retrieving revision 2.40
diff -C2 -r2.39 -r2.40
*** pyexpat.c	2001/02/08 15:39:08	2.39
--- pyexpat.c	2001/02/14 18:29:45	2.40
***************
*** 74,78 ****
      int ordered_attributes;     /* Return attributes as a list. */
      int specified_attributes;   /* Report only specified attributes. */
!     PyObject *(*conv_attrs)(XML_Char **);
      PyObject **handlers;
  } xmlparseobject;
--- 74,78 ----
      int ordered_attributes;     /* Return attributes as a list. */
      int specified_attributes;   /* Report only specified attributes. */
!     int in_callback;            /* Is a callback active? */
      PyObject **handlers;
  } xmlparseobject;
***************
*** 92,96 ****
--- 92,113 ----
  staticforward struct HandlerInfo handler_info[64];
  
+ /* Set an integer attribute on the error object; return true on success,
+  * false on an exception.
+  */
+ static int
+ set_error_attr(PyObject *err, char *name, int value)
+ {
+     PyObject *v = PyInt_FromLong(value);
+ 
+     if (v != NULL && PyObject_SetAttrString(err, name, v) == -1) {
+         Py_DECREF(v);
+         return 0;
+     }
+     return 1;
+ }
  
+ /* Build and set an Expat exception, including positioning
+  * information.  Always returns NULL.
+  */
  static PyObject *
  set_error(xmlparseobject *self)
***************
*** 99,113 ****
      char buffer[256];
      XML_Parser parser = self->itself;
  
      sprintf(buffer, "%.200s: line %i, column %i",
!             XML_ErrorString(XML_GetErrorCode(parser)),
!             XML_GetErrorLineNumber(parser),
!             XML_GetErrorColumnNumber(parser));
      err = PyObject_CallFunction(ErrorObject, "s", buffer);
!     if (err != NULL) {
!         PyObject *code = PyInt_FromLong(XML_GetErrorCode(parser));
! 
!         if (code != NULL && PyObject_SetAttrString(err, "code", code) != -1)
!             PyErr_SetObject(ErrorObject, err);
      }
      return NULL;
--- 116,131 ----
      char buffer[256];
      XML_Parser parser = self->itself;
+     int lineno = XML_GetErrorLineNumber(parser);
+     int column = XML_GetErrorColumnNumber(parser);
+     enum XML_Error code = XML_GetErrorCode(parser);
  
      sprintf(buffer, "%.200s: line %i, column %i",
!             XML_ErrorString(code), lineno, column);
      err = PyObject_CallFunction(ErrorObject, "s", buffer);
!     if (  err != NULL
!           && set_error_attr(err, "code", code)
!           && set_error_attr(err, "offset", column)
!           && set_error_attr(err, "lineno", lineno)) {
!         PyErr_SetObject(ErrorObject, err);
      }
      return NULL;
***************
*** 277,325 ****
  getcode(enum HandlerTypes slot, char* func_name, int lineno)
  {
! 	PyObject *code = NULL;
! 	PyObject *name = NULL;
! 	PyObject *nulltuple = NULL;
! 	PyObject *filename = NULL;
! 	if (handler_info[slot].tb_code == NULL) {
! 		code = PyString_FromString("");
! 		if (code == NULL)
! 			goto failed;
! 		name = PyString_FromString(func_name);
! 		if (name == NULL)
! 			goto failed;
! 		nulltuple = PyTuple_New(0);
! 		if (nulltuple == NULL)
! 			goto failed;
! 		filename = PyString_FromString(__FILE__);
! 		handler_info[slot].tb_code = PyCode_New(
! 			0,		/* argcount */
! 			0,		/* nlocals */
! 			0,		/* stacksize */
! 			0,		/* flags */
! 			code,		/* code */
! 			nulltuple,	/* consts */
! 			nulltuple,	/* names */
! 			nulltuple,	/* varnames */
  #if PYTHON_API_VERSION >= 1010
! 			nulltuple,	/* freevars */
! 			nulltuple,	/* cellvars */
  #endif
! 			filename,	/* filename */
! 			name,		/* name */
! 			lineno,		/* firstlineno */
! 			code		/* lnotab */
! 			);
! 		if (handler_info[slot].tb_code == NULL)
! 			goto failed;
! 		Py_DECREF(code);
! 		Py_DECREF(nulltuple);
! 		Py_DECREF(filename);
! 		Py_DECREF(name);
! 	}
! 	return handler_info[slot].tb_code;
!   failed:
! 	Py_XDECREF(code);
! 	Py_XDECREF(name);
! 	return NULL;
  }
  
--- 295,344 ----
  getcode(enum HandlerTypes slot, char* func_name, int lineno)
  {
!     PyObject *code = NULL;
!     PyObject *name = NULL;
!     PyObject *nulltuple = NULL;
!     PyObject *filename = NULL;
! 
!     if (handler_info[slot].tb_code == NULL) {
!         code = PyString_FromString("");
!         if (code == NULL)
!             goto failed;
!         name = PyString_FromString(func_name);
!         if (name == NULL)
!             goto failed;
!         nulltuple = PyTuple_New(0);
!         if (nulltuple == NULL)
!             goto failed;
!         filename = PyString_FromString(__FILE__);
!         handler_info[slot].tb_code =
!             PyCode_New(0,		/* argcount */
!                        0,		/* nlocals */
!                        0,		/* stacksize */
!                        0,		/* flags */
!                        code,		/* code */
!                        nulltuple,	/* consts */
!                        nulltuple,	/* names */
!                        nulltuple,	/* varnames */
  #if PYTHON_API_VERSION >= 1010
!                        nulltuple,	/* freevars */
!                        nulltuple,	/* cellvars */
  #endif
!                        filename,	/* filename */
!                        name,		/* name */
!                        lineno,		/* firstlineno */
!                        code		/* lnotab */
!                        );
!         if (handler_info[slot].tb_code == NULL)
!             goto failed;
!         Py_DECREF(code);
!         Py_DECREF(nulltuple);
!         Py_DECREF(filename);
!         Py_DECREF(name);
!     }
!     return handler_info[slot].tb_code;
!  failed:
!     Py_XDECREF(code);
!     Py_XDECREF(name);
!     return NULL;
  }
  
***************
*** 327,353 ****
  call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args)
  {
! 	PyThreadState *tstate = PyThreadState_GET();
! 	PyFrameObject *f;
! 	PyObject *res;
! 	if (c == NULL)
! 		return NULL;
! 	f = PyFrame_New(
! 			tstate,			/*back*/
! 			c,			/*code*/
! 			tstate->frame->f_globals,	/*globals*/
! 			NULL			/*locals*/
  #if PYTHON_API_VERSION >= 1010
! 			,NULL			/*closure*/
  #endif
! 		);
! 	if (f == NULL)
! 		return NULL;
! 	tstate->frame = f;
! 	res = PyEval_CallObject(func, args);
! 	if (res == NULL && tstate->curexc_traceback == NULL)
! 		PyTraceBack_Here(f);
! 	tstate->frame = f->f_back;
! 	Py_DECREF(f);
! 	return res;
  }
  
--- 346,373 ----
  call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args)
  {
!     PyThreadState *tstate = PyThreadState_GET();
!     PyFrameObject *f;
!     PyObject *res;
! 
!     if (c == NULL)
!         return NULL;
!     f = PyFrame_New(
!                     tstate,			/*back*/
!                     c,				/*code*/
!                     tstate->frame->f_globals,	/*globals*/
!                     NULL			/*locals*/
  #if PYTHON_API_VERSION >= 1010
!                     ,NULL			/*closure*/
  #endif
!                     );
!     if (f == NULL)
!         return NULL;
!     tstate->frame = f;
!     res = PyEval_CallObject(func, args);
!     if (res == NULL && tstate->curexc_traceback == NULL)
!         PyTraceBack_Here(f);
!     tstate->frame = f->f_back;
!     Py_DECREF(f);
!     return res;
  }
  
***************
*** 427,437 ****
          }
          /* Container is now a borrowed reference; ignore it. */
! 	rv = call_with_frame(getcode(StartElement, "StartElement", __LINE__),
                               self->handlers[StartElement], args);
! 	Py_DECREF(args);
          if (rv == NULL) {
              flag_error(self);
              return;
! 	}
          Py_DECREF(rv);
      }
--- 447,459 ----
          }
          /* Container is now a borrowed reference; ignore it. */
!         self->in_callback = 1;
!         rv = call_with_frame(getcode(StartElement, "StartElement", __LINE__),
                               self->handlers[StartElement], args);
!         self->in_callback = 0;
!         Py_DECREF(args);
          if (rv == NULL) {
              flag_error(self);
              return;
!         }
          Py_DECREF(rv);
      }
***************
*** 452,457 ****
--- 474,481 ----
          if (!args) \
              return RETURN; \
+         self->in_callback = 1; \
          rv = call_with_frame(getcode(NAME,#NAME,__LINE__), \
                               self->handlers[NAME], args); \
+         self->in_callback = 0; \
          Py_DECREF(args); \
          if (rv == NULL) { \
***************
*** 911,914 ****
--- 935,972 ----
  }
  
+ #if EXPAT_VERSION >= 0x015f00
+ static char xmlparse_GetInputContext__doc__[] =
+ "GetInputContext() -> string\n\
+ Return the untranslated text of the input that caused the current event.\n\
+ If the event was generated by a large amount of text (such as a start tag\n\
+ for an element with many attributes), not all of the text may be available.";
+ 
+ static PyObject *
+ xmlparse_GetInputContext(xmlparseobject *self, PyObject *args)
+ {
+     PyObject *result = NULL;
+ 
+     if (PyArg_ParseTuple(args, ":GetInputContext")) {
+         if (self->in_callback) {
+             int offset, size;
+             const char *buffer
+                 = XML_GetInputContext(self->itself, &offset, &size);
+ 
+             if (buffer != NULL)
+                 result = PyString_FromStringAndSize(buffer + offset, size);
+             else {
+                 result = Py_None;
+                 Py_INCREF(result);
+             }
+         }
+         else {
+             result = Py_None;
+             Py_INCREF(result);
+         }
+     }
+     return result;
+ }
+ #endif
+ 
  static char xmlparse_ExternalEntityParserCreate__doc__[] = 
  "ExternalEntityParserCreate(context[, encoding])\n\
***************
*** 941,945 ****
      new_parser->ordered_attributes = self->ordered_attributes;
      new_parser->specified_attributes = self->specified_attributes;
!     new_parser->conv_attrs = self->conv_attrs;
      new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context,
  							encoding);
--- 999,1003 ----
      new_parser->ordered_attributes = self->ordered_attributes;
      new_parser->specified_attributes = self->specified_attributes;
!     new_parser->in_callback = 0;
      new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context,
  							encoding);
***************
*** 988,997 ****
  
  static PyObject*
! xmlparse_SetParamEntityParsing(PyObject *p, PyObject* args)
  {
      int flag;
      if (!PyArg_ParseTuple(args, "i", &flag))
          return NULL;
!     flag = XML_SetParamEntityParsing(((xmlparseobject*)p)->itself, flag);
      return PyInt_FromLong(flag);
  }
--- 1046,1055 ----
  
  static PyObject*
! xmlparse_SetParamEntityParsing(xmlparseobject *p, PyObject* args)
  {
      int flag;
      if (!PyArg_ParseTuple(args, "i", &flag))
          return NULL;
!     flag = XML_SetParamEntityParsing(p->itself, flag);
      return PyInt_FromLong(flag);
  }
***************
*** 1001,1017 ****
  static struct PyMethodDef xmlparse_methods[] = {
      {"Parse",	  (PyCFunction)xmlparse_Parse,
! 	 	  METH_VARARGS,	xmlparse_Parse__doc__},
      {"ParseFile", (PyCFunction)xmlparse_ParseFile,
! 	 	  METH_VARARGS,	xmlparse_ParseFile__doc__},
      {"SetBase",   (PyCFunction)xmlparse_SetBase,
! 	 	  METH_VARARGS,      xmlparse_SetBase__doc__},
      {"GetBase",   (PyCFunction)xmlparse_GetBase,
! 	 	  METH_VARARGS,      xmlparse_GetBase__doc__},
      {"ExternalEntityParserCreate", (PyCFunction)xmlparse_ExternalEntityParserCreate,
  	 	  METH_VARARGS,      xmlparse_ExternalEntityParserCreate__doc__},
  #if EXPAT_VERSION >= 0x010200
!     {"SetParamEntityParsing", xmlparse_SetParamEntityParsing,
!      METH_VARARGS, xmlparse_SetParamEntityParsing__doc__},
  #endif
  	{NULL,		NULL}		/* sentinel */
  };
--- 1059,1079 ----
  static struct PyMethodDef xmlparse_methods[] = {
      {"Parse",	  (PyCFunction)xmlparse_Parse,
! 		  METH_VARARGS,	xmlparse_Parse__doc__},
      {"ParseFile", (PyCFunction)xmlparse_ParseFile,
! 		  METH_VARARGS,	xmlparse_ParseFile__doc__},
      {"SetBase",   (PyCFunction)xmlparse_SetBase,
! 		  METH_VARARGS,      xmlparse_SetBase__doc__},
      {"GetBase",   (PyCFunction)xmlparse_GetBase,
! 		  METH_VARARGS,      xmlparse_GetBase__doc__},
      {"ExternalEntityParserCreate", (PyCFunction)xmlparse_ExternalEntityParserCreate,
  	 	  METH_VARARGS,      xmlparse_ExternalEntityParserCreate__doc__},
  #if EXPAT_VERSION >= 0x010200
!     {"SetParamEntityParsing", (PyCFunction)xmlparse_SetParamEntityParsing,
! 		  METH_VARARGS, xmlparse_SetParamEntityParsing__doc__},
  #endif
+ #if EXPAT_VERSION >= 0x015f00
+     {"GetInputContext", (PyCFunction)xmlparse_GetInputContext,
+ 		  METH_VARARGS, xmlparse_GetInputContext__doc__},
+ #endif
  	{NULL,		NULL}		/* sentinel */
  };
***************
*** 1097,1100 ****
--- 1159,1163 ----
      self->ordered_attributes = 0;
      self->specified_attributes = 0;
+     self->in_callback = 0;
      self->handlers = NULL;
      if (namespace_separator) {
***************
*** 1444,1451 ****
  
      /* Add some symbolic constants to the module */
!     if (ErrorObject == NULL)
!         ErrorObject = PyErr_NewException("xml.parsers.expat.error",
                                           NULL, NULL);
      PyModule_AddObject(m, "error", ErrorObject);
      Py_INCREF(&Xmlparsetype);
      PyModule_AddObject(m, "XMLParserType", (PyObject *) &Xmlparsetype);
--- 1507,1520 ----
  
      /* Add some symbolic constants to the module */
!     if (ErrorObject == NULL) {
!         ErrorObject = PyErr_NewException("xml.parsers.expat.ExpatError",
                                           NULL, NULL);
+         if (ErrorObject == NULL)
+             return;
+     }
+     Py_INCREF(ErrorObject);
      PyModule_AddObject(m, "error", ErrorObject);
+     Py_INCREF(ErrorObject);
+     PyModule_AddObject(m, "ExpatError", ErrorObject);
      Py_INCREF(&Xmlparsetype);
      PyModule_AddObject(m, "XMLParserType", (PyObject *) &Xmlparsetype);