summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2007-04-22 00:17:55 +0100
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2007-04-22 00:17:55 +0100
commitc0310456d00840947ff2f93687b1152d71311159 (patch)
tree2f687e0211ddf494b7ed9fb579ec55ed96727335
parent497d74fe5b6a68b904a6944a9c60dd3c631654a6 (diff)
parent559008cadf0bc3457696e145b0abe764132fe92d (diff)
downloadxine-lib-c0310456d00840947ff2f93687b1152d71311159.tar.gz
xine-lib-c0310456d00840947ff2f93687b1152d71311159.tar.bz2
Merge relaxed XML parsing & adapt it to the enumerations.
-rw-r--r--src/xine-utils/xmlparser.c70
-rw-r--r--src/xine-utils/xmlparser.h1
2 files changed, 60 insertions, 11 deletions
diff --git a/src/xine-utils/xmlparser.c b/src/xine-utils/xmlparser.c
index c8723a12e..93217637d 100644
--- a/src/xine-utils/xmlparser.c
+++ b/src/xine-utils/xmlparser.c
@@ -162,6 +162,7 @@ typedef enum {
STATE_TAG_TERM,
STATE_ATTRIBUTE_EQUALS,
STATE_STRING,
+ STATE_TAG_TERM_IGNORE,
/* <?foo ...?> */
STATE_Q_NODE,
STATE_Q_ATTRIBUTE,
@@ -176,7 +177,8 @@ typedef enum {
#define Q_STATE(CURRENT,NEW) (STATE_##NEW + state - STATE_##CURRENT)
-static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int rec) {
+static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_names[], int rec, int relaxed)
+{
char tok[TOKEN_SIZE];
char property_name[TOKEN_SIZE];
char node_name[TOKEN_SIZE];
@@ -184,6 +186,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r
int res = 0;
int parse_res;
int bypass_get_token = 0;
+ int retval = 0; /* used when state==4; non-0 if there are missing </...> */
xml_node_t *subtree = NULL;
xml_node_t *current_subtree = NULL;
xml_property_t *current_property = NULL;
@@ -203,7 +206,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r
/* do nothing */
break;
case (T_EOF):
- return 0; /* normal end */
+ return retval; /* normal end */
break;
case (T_M_START_1):
state = STATE_NODE;
@@ -279,8 +282,9 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r
/* set node propertys */
subtree->props = properties;
lprintf("info: rec %d new subtree %s\n", rec, node_name);
- parse_res = xml_parser_get_node(subtree, node_name, rec + 1);
- if (parse_res != 0) {
+ root_names[rec + 1] = node_name;
+ parse_res = xml_parser_get_node_internal(subtree, root_names, rec + 1, relaxed);
+ if (parse_res == -1 || parse_res > 0) {
return parse_res;
}
if (current_subtree == NULL) {
@@ -290,6 +294,10 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r
current_subtree->next = subtree;
current_subtree = subtree;
}
+ if (parse_res < -1) {
+ /* badly-formed XML (missing close tag) */
+ return parse_res + 1 + (parse_res == -2);
+ }
state = STATE_IDLE;
break;
case (T_M_STOP_2):
@@ -356,10 +364,26 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r
if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) {
strtoupper(tok);
}
- if (strcmp(tok, root_name) == 0) {
+ if (strcmp(tok, root_names[rec]) == 0) {
state = STATE_TAG_TERM;
- } else {
- lprintf("error: xml struct, tok=%s, waited_tok=%s\n", tok, root_name);
+ } else if (relaxed) {
+ int r = rec;
+ while (--r >= 0)
+ if (strcmp(tok, root_names[r]) == 0) {
+ lprintf("warning: wanted %s, got %s - assuming missing close tags\n", root_names[rec], tok);
+ retval = r - rec - 1; /* -1 - (no. of implied close tags) */
+ state = STATE_TAG_TERM;
+ break;
+ }
+ /* relaxed parsing, ignoring extra close tag (but we don't handle out-of-order) */
+ if (r < 0) {
+ lprintf("warning: extra close tag %s - ignoring\n", tok);
+ state = STATE_TAG_TERM_IGNORE;
+ }
+ }
+ else
+ {
+ lprintf("error: xml struct, tok=%s, waited_tok=%s\n", tok, root_names[rec]);
return -1;
}
break;
@@ -374,7 +398,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r
case STATE_TAG_TERM:
switch (res) {
case (T_M_STOP_1):
- return 0;
+ return retval;
break;
default:
lprintf("error: unexpected token \"%s\", state %d\n", tok, state);
@@ -505,6 +529,19 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r
}
break;
+ /* > expected (following unmatched "</...") */
+ case STATE_TAG_TERM_IGNORE:
+ switch (res) {
+ case (T_M_STOP_1):
+ state = STATE_IDLE;
+ break;
+ default:
+ lprintf("error: unexpected token \"%s\", state %d\n", tok, state);
+ return -1;
+ break;
+ }
+ break;
+
default:
lprintf("error: unknown parser state, state=%d\n", state);
@@ -521,12 +558,19 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r
}
}
-int xml_parser_build_tree(xml_node_t **root_node) {
- xml_node_t *tmp_node, *pri_node, *q_node = NULL;
+static int xml_parser_get_node (xml_node_t *current_node, int relaxed)
+{
+ char *root_names[MAX_RECURSION + 1];
+ root_names[0] = "";
+ return xml_parser_get_node_internal (current_node, root_names, 0, relaxed);
+}
+
+int xml_parser_build_tree_relaxed(xml_node_t **root_node, int relaxed) {
+ xml_node_t *tmp_node, *pri_node, *q_node;
int res;
tmp_node = new_xml_node();
- res = xml_parser_get_node(tmp_node, "", 0);
+ res = xml_parser_get_node(tmp_node, relaxed);
/* find first non-<?...?> node */;
for (pri_node = tmp_node->child;
@@ -551,6 +595,10 @@ int xml_parser_build_tree(xml_node_t **root_node) {
return res;
}
+int xml_parser_build_tree(xml_node_t **root_node) {
+ return xml_parser_build_tree_relaxed (root_node, 0);
+}
+
const char *xml_parser_get_property (const xml_node_t *node, const char *name) {
xml_property_t *prop;
diff --git a/src/xine-utils/xmlparser.h b/src/xine-utils/xmlparser.h
index f202ca28d..8d4915abf 100644
--- a/src/xine-utils/xmlparser.h
+++ b/src/xine-utils/xmlparser.h
@@ -57,6 +57,7 @@ typedef struct xml_node_s {
void xml_parser_init(const char * buf, int size, int mode) XINE_PROTECTED;
int xml_parser_build_tree(xml_node_t **root_node) XINE_PROTECTED;
+int xml_parser_build_tree_relaxed(xml_node_t **root_node, int relaxed) XINE_PROTECTED;
void xml_parser_free_tree(xml_node_t *root_node) XINE_PROTECTED;