[totem-pl-parser] Make totem-pl-parser thread-safe



commit 9cec1603cbd7991ef1eb23679acc74fdfce36f12
Author: Matt Kraai <kraai ftbfs org>
Date:   Thu Dec 3 00:48:55 2009 -0800

    Make totem-pl-parser thread-safe
    
    https://bugzilla.gnome.org/show_bug.cgi?id=572705

 plparse/totem-pl-parser.c |   15 +++-
 plparse/xmllexer.c        |  215 ++++++++++++++++++++++++++-------------------
 plparse/xmllexer.h        |   24 +++++-
 plparse/xmlparser.c       |  194 ++++++++++++++++++++++++++++++++++------
 plparse/xmlparser.h       |   25 ++++-
 5 files changed, 344 insertions(+), 129 deletions(-)
---
diff --git a/plparse/totem-pl-parser.c b/plparse/totem-pl-parser.c
index 6104c30..01c2e85 100644
--- a/plparse/totem-pl-parser.c
+++ b/plparse/totem-pl-parser.c
@@ -1680,11 +1680,16 @@ totem_pl_parser_parse_xml_relaxed (char *contents,
 	xml_node_t* doc, *node;
 	char *encoding, *new_contents;
 	gsize new_size;
+	xml_parser_t *xml_parser;
 
 	totem_pl_parser_cleanup_xml (contents);
-	xml_parser_init (contents, size, XML_PARSER_CASE_INSENSITIVE);
-	if (xml_parser_build_tree_with_options (&doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0)
+	xml_parser = xml_parser_init_r (contents, size, XML_PARSER_CASE_INSENSITIVE);
+	if (xml_parser_build_tree_with_options_r (xml_parser, &doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0) {
+		xml_parser_finalize_r (xml_parser);
 		return NULL;
+	}
+
+	xml_parser_finalize_r (xml_parser);
 
 	encoding = NULL;
 	for (node = doc; node != NULL; node = node->next) {
@@ -1709,12 +1714,14 @@ totem_pl_parser_parse_xml_relaxed (char *contents,
 	}
 	g_free (encoding);
 
-	xml_parser_init (new_contents, new_size, XML_PARSER_CASE_INSENSITIVE);
-	if (xml_parser_build_tree_with_options (&doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0) {
+	xml_parser = xml_parser_init_r (new_contents, new_size, XML_PARSER_CASE_INSENSITIVE);
+	if (xml_parser_build_tree_with_options_r (xml_parser, &doc, XML_PARSER_RELAXED | XML_PARSER_MULTI_TEXT) < 0) {
+		xml_parser_finalize_r (xml_parser);
 		g_free (new_contents);
 		return NULL;
 	}
 
+	xml_parser_finalize_r (xml_parser);
 	g_free (new_contents);
 
 	return doc;
diff --git a/plparse/xmllexer.c b/plparse/xmllexer.c
index dd87415..bc564b3 100644
--- a/plparse/xmllexer.c
+++ b/plparse/xmllexer.c
@@ -25,11 +25,14 @@
 #define LOG
 */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #ifdef XINE_COMPILE
-#include "xineutils.h"
+#include <xine/xineutils.h>
 #else
 #define lprintf(...)
-#define xine_xmalloc malloc
 #endif
 #include "xmllexer.h"
 #include <stdio.h>
@@ -45,15 +48,11 @@
 /* private constants*/
 
 /* private global variables */
-static const char * lexbuf;
-static int lexbuf_size = 0;
-static int lexbuf_pos  = 0;
-static int in_comment  = 0;
-static char *lex_malloc = NULL;
+struct lexer * static_lexer;
 
 enum utf { UTF32BE, UTF32LE, UTF16BE, UTF16LE };
 
-static void lex_convert (const char * buf, int size, enum utf utf)
+static void lex_convert (struct lexer * lexer, const char * buf, int size, enum utf utf)
 {
   char *utf8 = malloc (size * (utf >= UTF16BE ? 3 : 6) + 1);
   char *bp = utf8;
@@ -85,8 +84,16 @@ static void lex_convert (const char * buf, int size, enum utf utf)
     }
   }
   *bp = 0;
-  lexbuf_size = bp - utf8;
-  lexbuf = lex_malloc = realloc (utf8, lexbuf_size + 1);
+  lexer->lexbuf_size = bp - utf8;
+  lexer->lexbuf = lexer->lex_malloc = realloc (utf8, lexer->lexbuf_size + 1);
+}
+
+/* for ABI compatibility */
+void lexer_init(const char * buf, int size) {
+  if (static_lexer) {
+    lexer_finalize_r(static_lexer);
+  }
+  static_lexer = lexer_init_r(buf, size);
 }
 
 static enum {
@@ -95,35 +102,40 @@ static enum {
   CDATA,
 } lex_mode = NORMAL;
 
-void lexer_init(const char * buf, int size) {
+struct lexer *lexer_init_r(const char * buf, int size) {
   static const char boms[] = { 0xFF, 0xFE, 0, 0, 0xFE, 0xFF },
 		    bom_utf8[] = { 0xEF, 0xBB, 0xBF };
+  struct lexer * lexer = calloc (1, sizeof (*lexer));
 
-  free (lex_malloc);
-  lex_malloc = NULL;
-
-  lexbuf      = buf;
-  lexbuf_size = size;
+  lexer->lexbuf      = buf;
+  lexer->lexbuf_size = size;
 
   if (size >= 4 && !memcmp (buf, boms + 2, 4))
-    lex_convert (buf + 4, size - 4, UTF32BE);
+    lex_convert (lexer, buf + 4, size - 4, UTF32BE);
   else if (size >= 4 && !memcmp (buf, boms, 4))
-    lex_convert (buf + 4, size - 4, UTF32LE);
+    lex_convert (lexer, buf + 4, size - 4, UTF32LE);
   else if (size >= 3 && !memcmp (buf, bom_utf8, 3))
   {
-    lexbuf += 3;
-    lexbuf_size -= 3;
+    lexer->lexbuf += 3;
+    lexer->lexbuf_size -= 3;
   }
   else if (size >= 2 && !memcmp (buf, boms + 4, 2))
-    lex_convert (buf + 2, size - 2, UTF16BE);
+    lex_convert (lexer, buf + 2, size - 2, UTF16BE);
   else if (size >= 2 && !memcmp (buf, boms, 2))
-    lex_convert (buf + 2, size - 2, UTF16LE);
+    lex_convert (lexer, buf + 2, size - 2, UTF16LE);
 
-  lexbuf_pos  = 0;
-  lex_mode    = NORMAL;
-  in_comment  = 0;
+  lexer->lexbuf_pos  = 0;
+  lexer->lex_mode    = NORMAL;
+  lexer->in_comment  = 0;
 
   lprintf("buffer length %d\n", size);
+  return lexer;
+}
+
+void lexer_finalize_r(struct lexer * lexer)
+{
+  free(lexer->lex_malloc);
+  free(lexer);
 }
 
 typedef enum {
@@ -144,17 +156,25 @@ typedef enum {
   STATE_IDENT /* must be last */
 } lexer_state_t;
 
-int lexer_get_token(char * tok, int tok_size) {
+/* for ABI compatibility */
+int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) {
+  return lexer_get_token_d_r(static_lexer, _tok, _tok_size, fixed);
+}
+
+int lexer_get_token_d_r(struct lexer * lexer, char ** _tok, int * _tok_size, int fixed) {
+  char *tok = *_tok;
+  int tok_size = *_tok_size;
+
   int tok_pos = 0;
   lexer_state_t state = STATE_IDLE;
   char c;
 
   if (tok) {
-    while ((tok_pos < tok_size) && (lexbuf_pos < lexbuf_size)) {
-      c = lexbuf[lexbuf_pos];
-      lprintf("c=%c, state=%d, lex_mode=%d, in_comment=%d\n", c, state, lex_mode, in_comment);
+    while ((tok_pos < tok_size) && (lexer->lexbuf_pos < lexer->lexbuf_size)) {
+      c = lexer->lexbuf[lexer->lexbuf_pos];
+      lprintf("c=%c, state=%d, in_comment=%d\n", c, state, lexer->in_comment);
 
-      switch (lex_mode) {
+      switch (lexer->lex_mode) {
       case NORMAL:
 	switch (state) {
 	  /* init state */
@@ -187,7 +207,7 @@ int lexer_get_token(char * tok, int tok_size) {
 	    break;
 
 	  case '/':
-	    if (!in_comment) 
+	    if (!lexer->in_comment)
 	      state = STATE_T_M_STOP_2;
 	    tok[tok_pos] = c;
 	    tok_pos++;
@@ -214,7 +234,7 @@ int lexer_get_token(char * tok, int tok_size) {
 	    break;
 
 	  case '?':
-	    if (!in_comment)
+	    if (!lexer->in_comment)
 	      state = STATE_T_TI_STOP;
 	    tok[tok_pos] = c;
 	    tok_pos++;
@@ -226,14 +246,14 @@ int lexer_get_token(char * tok, int tok_size) {
 	    tok_pos++;
 	    break;
 	  }
-	  lexbuf_pos++;
+	  lexer->lexbuf_pos++;
 	  break;
 
 	  /* end of line */
 	case STATE_EOL:
 	  if (c == '\n' || (c == '\r')) {
 	    tok[tok_pos] = c;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    tok_pos++;
 	  } else {
 	    tok[tok_pos] = '\0';
@@ -245,7 +265,7 @@ int lexer_get_token(char * tok, int tok_size) {
 	case STATE_SEPAR:
 	  if (c == ' ' || (c == '\t')) {
 	    tok[tok_pos] = c;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    tok_pos++;
 	  } else {
 	    tok[tok_pos] = '\0';
@@ -258,20 +278,20 @@ int lexer_get_token(char * tok, int tok_size) {
 	  switch (c) {
 	  case '/':
 	    tok[tok_pos] = c;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    tok_pos++; /* FIXME */
 	    tok[tok_pos] = '\0';
 	    return T_M_START_2;
 	    break;
 	  case '!':
 	    tok[tok_pos] = c;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    tok_pos++;
 	    state = STATE_T_COMMENT;
 	    break;
 	  case '?':
 	    tok[tok_pos] = c;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    tok_pos++; /* FIXME */
 	    tok[tok_pos] = '\0';
 	    return T_TI_START;
@@ -285,8 +305,8 @@ int lexer_get_token(char * tok, int tok_size) {
 	  /* T_M_STOP_1 */
 	case STATE_T_M_STOP_1:
 	  tok[tok_pos] = '\0';
-	  if (!in_comment)
-	    lex_mode = DATA;
+	  if (!lexer->in_comment)
+	    lexer->lex_mode = DATA;
 	  return T_M_STOP_1;
 	  break;
 
@@ -294,11 +314,11 @@ int lexer_get_token(char * tok, int tok_size) {
 	case STATE_T_M_STOP_2:
 	  if (c == '>') {
 	    tok[tok_pos] = c;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    tok_pos++; /* FIXME */
 	    tok[tok_pos] = '\0';
-	    if (!in_comment)
-	      lex_mode = DATA;
+	    if (!lexer->in_comment)
+	      lexer->lex_mode = DATA;
 	    return T_M_STOP_2;
 	  } else {
 	    tok[tok_pos] = '\0';
@@ -315,7 +335,7 @@ int lexer_get_token(char * tok, int tok_size) {
 	  /* T_STRING */
 	case STATE_T_STRING_DOUBLE:
 	  tok[tok_pos] = c;
-	  lexbuf_pos++;
+	  lexer->lexbuf_pos++;
 	  if (c == '\"') { /* " */
 	    tok[tok_pos] = '\0'; /* FIXME */
 	    return T_STRING;
@@ -327,33 +347,33 @@ int lexer_get_token(char * tok, int tok_size) {
 	case STATE_T_COMMENT:
 	  switch (c) {
 	  case '-':
-	    lexbuf_pos++;
-	    if (lexbuf[lexbuf_pos] == '-')
+	    lexer->lexbuf_pos++;
+	    if (lexer->lexbuf[lexer->lexbuf_pos] == '-')
 	      {
-		lexbuf_pos++;
+		lexer->lexbuf_pos++;
 		tok[tok_pos++] = '-'; /* FIXME */
 		tok[tok_pos++] = '-';
 		tok[tok_pos] = '\0';
-		in_comment = 1;
+		lexer->in_comment = 1;
 		return T_C_START;
 	      }
 	    break;
 	  case 'D':
-	    lexbuf_pos++;
-	    if (strncmp(lexbuf + lexbuf_pos, "OCTYPE", 6) == 0) {
+	    lexer->lexbuf_pos++;
+	    if (strncmp(lexer->lexbuf + lexer->lexbuf_pos, "OCTYPE", 6) == 0) {
 	      strncpy(tok + tok_pos, "DOCTYPE", 7); /* FIXME */
-	      lexbuf_pos += 6;
+	      lexer->lexbuf_pos += 6;
 	      return T_DOCTYPE_START;
 	    } else {
 	      return T_ERROR;
 	    }
 	    break;
 	  case '[':
-	    lexbuf_pos++;
-	    if (strncmp(lexbuf + lexbuf_pos, "CDATA[", 6) == 0) {
+	    lexer->lexbuf_pos++;
+	    if (strncmp(lexer->lexbuf + lexer->lexbuf_pos, "CDATA[", 6) == 0) {
 	      strncpy (tok + tok_pos, "[CDATA[", 7); /* FIXME */
-	      lexbuf_pos += 6;
-	      lex_mode = CDATA;
+	      lexer->lexbuf_pos += 6;
+	      lexer->lex_mode = CDATA;
 	      return T_CDATA_START;
 	    } else{
 	      return T_ERROR;
@@ -369,11 +389,11 @@ int lexer_get_token(char * tok, int tok_size) {
 	case STATE_T_TI_STOP:
 	  if (c == '>') {
 	    tok[tok_pos] = c;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    tok_pos++; /* FIXME */
 	    tok[tok_pos] = '\0';
-	    if (!in_comment)
-	      lex_mode = DATA;
+	    if (!lexer->in_comment)
+	      lexer->lex_mode = DATA;
 	    return T_TI_STOP;
 	  } else {
 	    tok[tok_pos] = '\0';
@@ -387,13 +407,13 @@ int lexer_get_token(char * tok, int tok_size) {
 	  case '-':
 	    tok[tok_pos] = c;
 	    tok_pos++;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    state = STATE_T_C_STOP;
 	    break;
 	  default:
 	    tok[tok_pos] = c;
 	    tok_pos++;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    state = STATE_IDENT;
 	  }
 	  break;
@@ -404,21 +424,21 @@ int lexer_get_token(char * tok, int tok_size) {
 	  case '>':
 	    tok[tok_pos] = c;
 	    tok_pos++;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    tok[tok_pos] = '\0'; /* FIX ME */
 	    if (strlen(tok) != 3) {
 	      tok[tok_pos - 3] = '\0';
-	      lexbuf_pos -= 3;
+	      lexer->lexbuf_pos -= 3;
 	      return T_IDENT;
 	    } else {
-	      in_comment = 0;
+	      lexer->in_comment = 0;
 	      return T_C_STOP;
 	    }
 	    break;
 	  default:
 	    tok[tok_pos] = c;
 	    tok_pos++;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    state = STATE_IDENT;
 	  }
 	  break;
@@ -426,7 +446,7 @@ int lexer_get_token(char * tok, int tok_size) {
 	  /* T_STRING (single quotes) */
 	case STATE_T_STRING_SINGLE:
 	  tok[tok_pos] = c;
-	  lexbuf_pos++;
+	  lexer->lexbuf_pos++;
 	  if (c == '\'') { /* " */
 	    tok[tok_pos] = '\0'; /* FIXME */
 	    return T_STRING;
@@ -453,19 +473,19 @@ int lexer_get_token(char * tok, int tok_size) {
 	  case '?':
 	    tok[tok_pos] = c;
 	    tok_pos++;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    state = STATE_T_TI_STOP;
 	    break;
 	  case '-':
 	    tok[tok_pos] = c;
 	    tok_pos++;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	    state = STATE_T_DASHDASH;
 	    break;
 	  default:
 	    tok[tok_pos] = c;
 	    tok_pos++;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	  }
 	  break;
 	default:
@@ -479,12 +499,12 @@ int lexer_get_token(char * tok, int tok_size) {
         {
         case '<':
 	  tok[tok_pos] = '\0';
-	  lex_mode = NORMAL;
+	  lexer->lex_mode = NORMAL;
 	  return T_DATA;
 	default:
 	  tok[tok_pos] = c;
 	  tok_pos++;
-	  lexbuf_pos++;
+	  lexer->lexbuf_pos++;
 	}
 	break;
 
@@ -492,56 +512,67 @@ int lexer_get_token(char * tok, int tok_size) {
         switch (c)
         {
 	case ']':
-	  if (strncmp(lexbuf + lexbuf_pos, "]]>", 3) == 0) {
-	    lexbuf_pos += 3;
-	    lex_mode = DATA;
+	  if (strncmp(lexer->lexbuf + lexer->lexbuf_pos, "]]>", 3) == 0) {
+	    lexer->lexbuf_pos += 3;
+	    lexer->lex_mode = DATA;
 	    return T_CDATA_STOP;
 	  } else {
 	    tok[tok_pos] = c;
 	    tok_pos++;
-	    lexbuf_pos++;
+	    lexer->lexbuf_pos++;
 	  }
 	  break;
 	default:
 	  tok[tok_pos] = c;
 	  tok_pos++;
-	  lexbuf_pos++;
+	  lexer->lexbuf_pos++;
 	}
 	break;
       }
     }
-    lprintf ("loop done tok_pos = %d, tok_size=%d, lexbuf_pos=%d, lexbuf_size=%d\n", 
-	     tok_pos, tok_size, lexbuf_pos, lexbuf_size);
+    lprintf ("loop done tok_pos = %d, tok_size=%d, lexbuf_pos=%d, lexbuf_size=%d\n",
+	     tok_pos, tok_size, lexer->lexbuf_pos, lexer->lexbuf_size);
 
     /* pb */
     if (tok_pos >= tok_size) {
-      lprintf("token buffer is too little\n");
+      if (fixed)
+        return T_ERROR;
+      *_tok_size *= 2;
+      *_tok = realloc (*_tok, *_tok_size);
+      lprintf("token buffer is too small\n");
+      lprintf("increasing buffer size to %d bytes\n", *_tok_size);
+      if (*_tok) {
+          return lexer_get_token_d_r (lexer, _tok, _tok_size, 0);
+      } else {
+          return T_ERROR;
+      }
     } else {
-      if (lexbuf_pos >= lexbuf_size) {
+      if (lexer->lexbuf_pos >= lexer->lexbuf_size) {
 				/* Terminate the current token */
 	tok[tok_pos] = '\0';
 	switch (state) {
-	case 0:
-	case 1:
-	case 2:
+	case STATE_IDLE:
+	case STATE_EOL:
+	case STATE_SEPAR:
 	  return T_EOF;
 	  break;
-	case 3:
+	case STATE_T_M_START:
 	  return T_M_START_1;
 	  break;
-	case 4:
+	case STATE_T_M_STOP_1:
 	  return T_M_STOP_1;
 	  break;
-	case 5:
+	case STATE_T_M_STOP_2:
 	  return T_ERROR;
 	  break;
-	case 6:
+	case STATE_T_EQUAL:
 	  return T_EQUAL;
 	  break;
-	case 7:
+	case STATE_T_STRING_SINGLE:
+	case STATE_T_STRING_DOUBLE:
 	  return T_STRING;
 	  break;
-	case 100:
+	case STATE_IDENT:
 	  return T_DATA;
 	  break;
 	default:
@@ -558,6 +589,12 @@ int lexer_get_token(char * tok, int tok_size) {
   return T_ERROR;
 }
 
+/* for ABI compatibility */
+int lexer_get_token (char *tok, int tok_size)
+{
+  return lexer_get_token_d (&tok, &tok_size, 1);
+}
+
 static struct {
   char code;
   unsigned char namelen;
@@ -573,7 +610,7 @@ static struct {
 
 char *lexer_decode_entities (const char *tok)
 {
-  char *buf = xine_xmalloc (strlen (tok) + 1);
+  char *buf = calloc (strlen (tok) + 1, sizeof(char));
   char *bp = buf;
   char c;
 
diff --git a/plparse/xmllexer.h b/plparse/xmllexer.h
index 10bcc86..70fa86e 100644
--- a/plparse/xmllexer.h
+++ b/plparse/xmllexer.h
@@ -23,6 +23,10 @@
 #ifndef XML_LEXER_H
 #define XML_LEXER_H
 
+#ifndef XINE_DEPRECATED
+#define XINE_DEPRECATED
+#endif
+
 #ifndef XINE_PROTECTED
 #define XINE_PROTECTED
 #endif
@@ -51,9 +55,25 @@
 #define T_CDATA_STOP    19   /* ]]> */
 
 
+/* public structure */
+struct lexer
+{
+  const char * lexbuf;
+  int lexbuf_size;
+  int lexbuf_pos;
+  int lex_mode;
+  int in_comment;
+  char *lex_malloc;
+};
+
+
 /* public functions */
-void lexer_init(const char * buf, int size) XINE_PROTECTED;
-int lexer_get_token(char * tok, int tok_size) XINE_PROTECTED;
+void lexer_init(const char * buf, int size) XINE_DEPRECATED XINE_PROTECTED;
+struct lexer *lexer_init_r(const char * buf, int size) XINE_PROTECTED;
+void lexer_finalize_r(struct lexer * lexer) XINE_PROTECTED;
+int lexer_get_token_d_r(struct lexer * lexer, char ** tok, int * tok_size, int fixed) XINE_PROTECTED;
+int lexer_get_token_d(char ** tok, int * tok_size, int fixed) XINE_DEPRECATED XINE_PROTECTED;
+int lexer_get_token(char * tok, int tok_size) XINE_DEPRECATED XINE_PROTECTED;
 char *lexer_decode_entities (const char *tok) XINE_PROTECTED;
 
 #endif
diff --git a/plparse/xmlparser.c b/plparse/xmlparser.c
index 3b9bfe8..b278260 100644
--- a/plparse/xmlparser.c
+++ b/plparse/xmlparser.c
@@ -19,6 +19,10 @@
  * Floor, Boston, MA 02110, USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #ifdef XINE_COMPILE
 # include "config.h"
 #endif
@@ -38,10 +42,10 @@
 
 #include <totem_internal.h>
 #ifdef XINE_COMPILE
-#include "xineutils.h"
+#include <xine/xineutils.h>
 #else
 #define lprintf(...)
-#define xine_xmalloc malloc
+#define XINE_MALLOC
 #endif
 #include "xmllexer.h"
 #include "xmlparser.h"
@@ -52,7 +56,7 @@
 #define MAX_RECURSION 23
 
 /* private global variables */
-static int xml_parser_mode;
+xml_parser_t * static_xml_parser;
 
 /* private functions */
 
@@ -87,7 +91,7 @@ static void free_xml_node(xml_node_t * node) {
   free(node);
 }
 
-static xml_property_t * new_xml_property(void) {
+static xml_property_t *XINE_MALLOC new_xml_property(void) {
   xml_property_t * new_property;
 
   new_property = (xml_property_t*) malloc(sizeof(xml_property_t));
@@ -103,10 +107,24 @@ static void free_xml_property(xml_property_t * property) {
   free(property);
 }
 
+/* for ABI compatibility */
 void xml_parser_init(const char * buf, int size, int mode) {
+  if (static_xml_parser) {
+    xml_parser_finalize_r(static_xml_parser);
+  }
+  static_xml_parser = xml_parser_init_r(buf, size, mode);
+}
+
+xml_parser_t *xml_parser_init_r(const char * buf, int size, int mode) {
+  xml_parser_t *xml_parser = malloc(sizeof(*xml_parser));
+  xml_parser->lexer = lexer_init_r(buf, size);
+  xml_parser->mode = mode;
+  return xml_parser;
+}
 
-  lexer_init(buf, size);
-  xml_parser_mode = mode;
+void xml_parser_finalize_r(xml_parser_t *xml_parser) {
+  lexer_finalize_r(xml_parser->lexer);
+  free(xml_parser);
 }
 
 static void xml_parser_free_props(xml_property_t *current_property) {
@@ -220,11 +238,16 @@ static xml_node_t *xml_parser_append_text (xml_node_t *node, xml_node_t *subnode
 
 #define Q_STATE(CURRENT,NEW) (STATE_##NEW + state - STATE_##CURRENT)
 
-static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_names[], int rec, int flags)
+
+static int xml_parser_get_node_internal (xml_parser_t *xml_parser,
+				 char ** token_buffer, int * token_buffer_size,
+                                 char ** pname_buffer, int * pname_buffer_size,
+                                 char ** nname_buffer, int * nname_buffer_size,
+                                 xml_node_t *current_node, char *root_names[], int rec, int flags)
 {
-  char tok[TOKEN_SIZE];
-  char property_name[TOKEN_SIZE];
-  char node_name[TOKEN_SIZE];
+  char *tok = *token_buffer;
+  char *property_name = *pname_buffer;
+  char *node_name = *nname_buffer;
   parser_state_t state = STATE_IDLE;
   int res = 0;
   int parse_res;
@@ -237,9 +260,10 @@ static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_na
 
   if (rec < MAX_RECURSION) {
 
-    memset (tok, 0, TOKEN_SIZE);
+    memset (tok, 0, *token_buffer_size);
 
-    while ((bypass_get_token) || (res = lexer_get_token(tok, TOKEN_SIZE)) != T_ERROR) {
+    while ((bypass_get_token) || (res = lexer_get_token_d_r(xml_parser->lexer, token_buffer, token_buffer_size, 0)) != T_ERROR) {
+      tok = *token_buffer;
       bypass_get_token = 0;
       lprintf("info: %d - %d : '%s'\n", state, res, tok);
 
@@ -295,14 +319,19 @@ static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_na
 	  current_property = NULL;
 
 	  /* save node name */
-	  if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) {
+	  if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) {
 	    strtoupper(tok);
 	  }
 	  if (state == STATE_Q_NODE) {
-	    snprintf (node_name, TOKEN_SIZE, "?%s", tok);
+	    asprintf (&node_name, "?%s", tok);
+	    free (*nname_buffer);
+	    *nname_buffer = node_name;
+	    *nname_buffer_size = strlen (node_name) + 1;
 	    state = STATE_Q_ATTRIBUTE;
 	  } else {
-	    strcpy(node_name, tok);
+	    free (*nname_buffer);
+	    *nname_buffer = node_name = strdup (tok);
+	    *nname_buffer_size = strlen (node_name) + 1;
 	    state = STATE_ATTRIBUTE;
 	  }
 	  lprintf("info: current node name \"%s\"\n", node_name);
@@ -330,8 +359,12 @@ static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_na
 	  /* set node propertys */
 	  subtree->props = properties;
 	  lprintf("info: rec %d new subtree %s\n", rec, node_name);
-	  root_names[rec + 1] = node_name;
-	  parse_res = xml_parser_get_node_internal(subtree, root_names, rec + 1, flags);
+	  root_names[rec + 1] = strdup (node_name);
+	  parse_res = xml_parser_get_node_internal (xml_parser, token_buffer, token_buffer_size,
+						    pname_buffer, pname_buffer_size,
+						    nname_buffer, nname_buffer_size,
+						    subtree, root_names, rec + 1, flags);
+	  free (root_names[rec + 1]);
 	  if (parse_res == -1 || parse_res > 0) {
 	    return parse_res;
 	  }
@@ -367,16 +400,22 @@ static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_na
 	    current_subtree = subtree;
 	  } else {
 	    current_subtree->next = subtree;
-	    current_subtree = subtree; 
+	    current_subtree = subtree;
 	  }
 	  state = STATE_IDLE;
 	  break;
 	case (T_IDENT):
 	  /* save property name */
 	  new_prop:
-	  if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) {
+	  if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) {
 	    strtoupper(tok);
 	  }
+	  /* make sure the buffer for the property name is big enough */
+	  if (*token_buffer_size > *pname_buffer_size) {
+	    *pname_buffer_size = *token_buffer_size;
+	    *pname_buffer = realloc (*pname_buffer, *pname_buffer_size);
+	    property_name = *pname_buffer;
+	  }
 	  strcpy(property_name, tok);
 	  state = Q_STATE(ATTRIBUTE, ATTRIBUTE_EQUALS);
 	  lprintf("info: current property name \"%s\"\n", property_name);
@@ -409,7 +448,7 @@ static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_na
 	switch (res) {
 	case (T_IDENT):
 	  /* must be equal to root_name */
-	  if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) {
+	  if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) {
 	    strtoupper(tok);
 	  }
 	  if (strcmp(tok, root_names[rec]) == 0) {
@@ -621,19 +660,42 @@ static int xml_parser_get_node_internal (xml_node_t *current_node, char *root_na
   }
 }
 
-static int xml_parser_get_node (xml_node_t *current_node, int flags)
+static int xml_parser_get_node (xml_parser_t *xml_parser, xml_node_t *current_node, int flags)
 {
+  int res = 0;
+  int token_buffer_size = TOKEN_SIZE;
+  int pname_buffer_size = TOKEN_SIZE;
+  int nname_buffer_size = TOKEN_SIZE;
+  char *token_buffer = calloc(1, token_buffer_size);
+  char *pname_buffer = calloc(1, pname_buffer_size);
+  char *nname_buffer = calloc(1, nname_buffer_size);
   char *root_names[MAX_RECURSION + 1];
   root_names[0] = "";
-  return xml_parser_get_node_internal (current_node, root_names, 0, flags);
+
+  res = xml_parser_get_node_internal (xml_parser,
+			     &token_buffer, &token_buffer_size,
+                             &pname_buffer, &pname_buffer_size,
+                             &nname_buffer, &nname_buffer_size,
+                             current_node, root_names, 0, flags);
+
+  free (token_buffer);
+  free (pname_buffer);
+  free (nname_buffer);
+
+  return res;
 }
 
+/* for ABI compatibility */
 int xml_parser_build_tree_with_options(xml_node_t **root_node, int flags) {
+  return xml_parser_build_tree_with_options_r(static_xml_parser, root_node, flags);
+}
+
+int xml_parser_build_tree_with_options_r(xml_parser_t *xml_parser, xml_node_t **root_node, int flags) {
   xml_node_t *tmp_node, *pri_node, *q_node;
   int res;
 
   tmp_node = new_xml_node();
-  res = xml_parser_get_node(tmp_node, flags);
+  res = xml_parser_get_node(xml_parser, tmp_node, flags);
 
   /* delete any top-level [CDATA] nodes */;
   pri_node = tmp_node->child;
@@ -676,8 +738,13 @@ int xml_parser_build_tree_with_options(xml_node_t **root_node, int flags) {
   return res;
 }
 
+/* for ABI compatibility */
 int xml_parser_build_tree(xml_node_t **root_node) {
-  return xml_parser_build_tree_with_options (root_node, 0);
+  return xml_parser_build_tree_with_options_r (static_xml_parser, root_node, 0);
+}
+
+int xml_parser_build_tree_r(xml_parser_t *xml_parser, xml_node_t **root_node) {
+  return xml_parser_build_tree_with_options_r(xml_parser, root_node, 0);
 }
 
 const char *xml_parser_get_property (const xml_node_t *node, const char *name) {
@@ -700,7 +767,7 @@ const char *xml_parser_get_property (const xml_node_t *node, const char *name) {
   return NULL;
 }
 
-int xml_parser_get_property_int (const xml_node_t *node, const char *name, 
+int xml_parser_get_property_int (const xml_node_t *node, const char *name,
 				 int def_value) {
 
   const char *v;
@@ -717,7 +784,7 @@ int xml_parser_get_property_int (const xml_node_t *node, const char *name,
     return ret;
 }
 
-int xml_parser_get_property_bool (const xml_node_t *node, const char *name, 
+int xml_parser_get_property_bool (const xml_node_t *node, const char *name,
 				  int def_value) {
 
   const char *v;
@@ -760,7 +827,7 @@ static int xml_escape_string_internal (char *buf, const char *s,
 
 char *xml_escape_string (const char *s, xml_escape_quote_t quote_type)
 {
-  char *buf = xine_xmalloc (xml_escape_string_internal (NULL, s, quote_type));
+  char *buf = calloc (1, xml_escape_string_internal (NULL, s, quote_type));
   return buf ? (xml_escape_string_internal (buf, s, quote_type), buf) : NULL;
 }
 
@@ -768,11 +835,10 @@ static void xml_parser_dump_node (const xml_node_t *node, int indent) {
 
   xml_property_t *p;
   xml_node_t     *n;
-  int             l;
 
   printf ("%*s<%s ", indent, "", node->name);
 
-  l = strlen (node->name);
+  size_t l = strlen (node->name);
 
   p = node->props;
   while (p) {
@@ -803,3 +869,73 @@ void xml_parser_dump_tree (const xml_node_t *node) {
     node = node->next;
   } while (node);
 }
+
+#ifdef XINE_XML_PARSER_TEST
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void *xine_xmalloc (size_t size)
+{
+  return malloc (size);
+}
+
+int main (int argc, char **argv)
+{
+  int i, ret = 0;
+  for (i = 1; argv[i]; ++i)
+  {
+    xml_node_t *tree;
+    int fd;
+    void *buf;
+    struct stat st;
+
+    if (stat (argv[i], &st))
+    {
+      perror (argv[i]);
+      ret = 1;
+      continue;
+    }
+    if (!S_ISREG (st.st_mode))
+    {
+      printf ("%s: not a file\n", argv[i]);
+      ret = 1;
+      continue;
+    }
+    fd = open (argv[i], O_RDONLY);
+    if (!fd)
+    {
+      perror (argv[i]);
+      ret = 1;
+      continue;
+    }
+    buf = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+    if (!buf)
+    {
+      perror (argv[i]);
+      if (close (fd))
+        perror (argv[i]);
+      ret = 1;
+      continue;
+    }
+
+    xml_parser_init (buf, st.st_size, 0);
+    if (!xml_parser_build_tree (&tree))
+    {
+      puts (argv[i]);
+      xml_parser_dump_tree (tree);
+      xml_parser_free_tree (tree);
+    }
+    else
+      printf ("%s: parser failure\n", argv[i]);
+
+    if (close (fd))
+    {
+      perror (argv[i]);
+      ret = 1;
+    }
+  }
+  return ret;
+}
+#endif
diff --git a/plparse/xmlparser.h b/plparse/xmlparser.h
index c89cb6d..495e513 100644
--- a/plparse/xmlparser.h
+++ b/plparse/xmlparser.h
@@ -22,6 +22,10 @@
 #ifndef XML_PARSER_H
 #define XML_PARSER_H
 
+#ifndef XINE_DEPRECATED
+#define XINE_DEPRECATED
+#endif
+
 #ifndef XINE_PROTECTED
 #define XINE_PROTECTED
 #endif
@@ -65,17 +69,28 @@ typedef struct xml_node_s {
 	struct xml_node_s *next;
 } xml_node_t;
 
-void xml_parser_init(const char * buf, int size, int mode) XINE_PROTECTED;
+/* xml parser */
+typedef struct xml_parser_s {
+	struct lexer *lexer;
+	int mode;
+} xml_parser_t;
+
+void xml_parser_init(const char * buf, int size, int mode) XINE_DEPRECATED XINE_PROTECTED;
+xml_parser_t *xml_parser_init_r(const char * buf, int size, int mode) XINE_PROTECTED;
+void xml_parser_finalize_r(xml_parser_t *xml_parser) XINE_PROTECTED;
+
+int xml_parser_build_tree(xml_node_t **root_node) XINE_DEPRECATED XINE_PROTECTED;
+int xml_parser_build_tree_r(xml_parser_t *xml_parser, xml_node_t **root_node) XINE_PROTECTED;
 
-int xml_parser_build_tree(xml_node_t **root_node) XINE_PROTECTED;
-int xml_parser_build_tree_with_options(xml_node_t **root_node, int flags) XINE_PROTECTED;
+int xml_parser_build_tree_with_options(xml_node_t **root_node, int flags) XINE_DEPRECATED XINE_PROTECTED;
+int xml_parser_build_tree_with_options_r(xml_parser_t *xml_parser, xml_node_t **root_node, int flags) XINE_PROTECTED;
 
 void xml_parser_free_tree(xml_node_t *root_node) XINE_PROTECTED;
 
 const char *xml_parser_get_property (const xml_node_t *node, const char *name) XINE_PROTECTED;
-int   xml_parser_get_property_int (const xml_node_t *node, const char *name, 
+int   xml_parser_get_property_int (const xml_node_t *node, const char *name,
 				   int def_value) XINE_PROTECTED;
-int xml_parser_get_property_bool (const xml_node_t *node, const char *name, 
+int xml_parser_get_property_bool (const xml_node_t *node, const char *name,
 				  int def_value) XINE_PROTECTED;
 
 /* for output:



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]