Add support for big line numbers in error reporting

Fix the lack of line number as reported by Johan Corveleyn <jcorvel@gmail.com>

* parser.c include/libxml/parser.h: add an XML_PARSE_BIG_LINES parser
  option not switch on by default, it's an opt-in
* SAX2.c: if XML_PARSE_BIG_LINES is set store the long line numbers
  in the psvi field of text nodes
* tree.c: expand xmlGetLineNo to extract those informations, also
  make sure we can't fail on recursive behaviour
* error.c: in __xmlRaiseError, if a node is provided, call
  xmlGetLineNo() if we can't get a valid line number.
* xmllint.c: switch on XML_PARSE_BIG_LINES in xmllint
This commit is contained in:
Daniel Veillard 2012-08-13 12:41:33 +08:00
parent 264cee695a
commit 968a03a2e5
6 changed files with 64 additions and 16 deletions

17
SAX2.c
View File

@ -1817,7 +1817,7 @@ xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
* @str: the input string
* @len: the string length
*
* Remove the entities from an attribute value
* Callback for a text node
*
* Returns the newly allocated string or NULL if not needed or error
*/
@ -1850,7 +1850,7 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
if ((len < (int) (2 * sizeof(void *))) &&
(ctxt->options & XML_PARSE_COMPACT)) {
/* store the string in the node overrithing properties and nsDef */
/* store the string in the node overriding properties and nsDef */
xmlChar *tmp = (xmlChar *) &(ret->properties);
memcpy(tmp, str, len);
tmp[len] = 0;
@ -1882,8 +1882,17 @@ skip:
} else
ret->content = (xmlChar *) intern;
if (ctxt->input != NULL)
ret->line = ctxt->input->line;
if (ctxt->linenumbers) {
if (ctxt->input != NULL) {
if (ctxt->input->line < 65535)
ret->line = (short) ctxt->input->line;
else {
ret->line = 65535;
if (ctxt->options & XML_PARSE_BIG_LINES)
ret->psvi = (void *) ctxt->input->line;
}
}
}
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
xmlRegisterNodeDefaultValue(ret);

View File

@ -530,6 +530,8 @@ __xmlRaiseError(xmlStructuredErrorFunc schannel,
if ((node != NULL) && (node->type == XML_ELEMENT_NODE))
line = node->line;
if ((line == 0) || (line == 65535))
line = xmlGetLineNo(node);
}
/*

View File

@ -1109,7 +1109,8 @@ typedef enum {
XML_PARSE_NOBASEFIX = 1<<18,/* do not fixup XINCLUDE xml:base uris */
XML_PARSE_HUGE = 1<<19,/* relax any hardcoded limit from the parser */
XML_PARSE_OLDSAX = 1<<20,/* parse using SAX2 interface before 2.7.0 */
XML_PARSE_IGNORE_ENC= 1<<21 /* ignore internal document encoding hint */
XML_PARSE_IGNORE_ENC= 1<<21,/* ignore internal document encoding hint */
XML_PARSE_BIG_LINES = 1<<22 /* Store big lines numbers in text PSVI field */
} xmlParserOption;
XMLPUBFUN void XMLCALL

View File

@ -14965,6 +14965,10 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi
ctxt->options |= XML_PARSE_IGNORE_ENC;
options -= XML_PARSE_IGNORE_ENC;
}
if (options & XML_PARSE_BIG_LINES) {
ctxt->options |= XML_PARSE_BIG_LINES;
options -= XML_PARSE_BIG_LINES;
}
ctxt->linenumbers = 1;
return (options);
}

52
tree.c
View File

@ -4528,39 +4528,71 @@ xmlCopyDoc(xmlDocPtr doc, int recursive) {
************************************************************************/
/**
* xmlGetLineNo:
* xmlGetLineNoInternal:
* @node: valid node
* @depth: used to limit any risk of recursion
*
* Get line number of @node. This requires activation of this option
* before invoking the parser by calling xmlLineNumbersDefault(1)
* Get line number of @node.
* Try to override the limitation of lines being store in 16 bits ints
*
* Returns the line number if successful, -1 otherwise
*/
long
xmlGetLineNo(xmlNodePtr node)
static long
xmlGetLineNoInternal(xmlNodePtr node, int depth)
{
long result = -1;
if (depth >= 5)
return(-1);
if (!node)
return result;
if ((node->type == XML_ELEMENT_NODE) ||
(node->type == XML_TEXT_NODE) ||
(node->type == XML_COMMENT_NODE) ||
(node->type == XML_PI_NODE))
result = (long) node->line;
else if ((node->prev != NULL) &&
(node->type == XML_PI_NODE)) {
if (node->line == 65535) {
if ((node->type == XML_TEXT_NODE) && (node->psvi != NULL))
result = (long) node->psvi;
else if ((node->type == XML_ELEMENT_NODE) &&
(node->children != NULL))
result = xmlGetLineNoInternal(node->children, depth + 1);
else if (node->next != NULL)
result = xmlGetLineNoInternal(node->next, depth + 1);
else if (node->prev != NULL)
result = xmlGetLineNoInternal(node->prev, depth + 1);
}
if ((result == -1) || (result == 65535))
result = (long) node->line;
} else if ((node->prev != NULL) &&
((node->prev->type == XML_ELEMENT_NODE) ||
(node->prev->type == XML_TEXT_NODE) ||
(node->prev->type == XML_COMMENT_NODE) ||
(node->prev->type == XML_PI_NODE)))
result = xmlGetLineNo(node->prev);
result = xmlGetLineNoInternal(node->prev, depth + 1);
else if ((node->parent != NULL) &&
(node->parent->type == XML_ELEMENT_NODE))
result = xmlGetLineNo(node->parent);
result = xmlGetLineNoInternal(node->parent, depth + 1);
return result;
}
/**
* xmlGetLineNo:
* @node: valid node
*
* Get line number of @node.
* Try to override the limitation of lines being store in 16 bits ints
* if XML_PARSE_BIG_LINES parser option was used
*
* Returns the line number if successful, -1 otherwise
*/
long
xmlGetLineNo(xmlNodePtr node)
{
return(xmlGetLineNoInternal(node, 0));
}
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
/**
* xmlGetNodePath:

View File

@ -209,7 +209,7 @@ static xmlStreamCtxtPtr patstream = NULL;
#ifdef LIBXML_XPATH_ENABLED
static const char *xpathquery = NULL;
#endif
static int options = XML_PARSE_COMPACT;
static int options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES;
static int sax = 0;
static int oldxml10 = 0;