Commit 968a03a2 authored by Daniel Veillard's avatar Daniel Veillard
Browse files

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
parent 264cee69
......@@ -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);
......
......@@ -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);
}
/*
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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:
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment