Loading...
libkern/c++/OSUnserializeXML.cpp xnu-344.49 xnu-792.6.70
--- xnu/xnu-344.49/libkern/c++/OSUnserializeXML.cpp
+++ xnu/xnu-792.6.70/libkern/c++/OSUnserializeXML.cpp
@@ -1,36 +1,37 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 
-/*  OSUnserializeXML.y created by rsulack on Tue Oct 12 1999 */
-
-// 		XML parser for unserializing OSContainer objects
+/*
+ * HISTORY
+ *
+ * OSUnserializeXML.y created by rsulack on Tue Oct 12 1999
+ */
+
+// parser for unserializing OSContainer objects serialized to XML
 //
 // to build :
 //	bison -p OSUnserializeXML OSUnserializeXML.y
 //	head -50 OSUnserializeXML.y > OSUnserializeXML.cpp
-//	sed -e "s/stdio.h/stddef.h/" < OSUnserializeXML.tab.c >> OSUnserializeXML.cpp
+//	sed -e "s/#include <stdio.h>//" < OSUnserializeXML.tab.c >> OSUnserializeXML.cpp
 //
 //	when changing code check in both OSUnserializeXML.y and OSUnserializeXML.cpp
 //
@@ -38,8 +39,6 @@
 //
 //
 //
-//
-//
 //		 DO NOT EDIT OSUnserializeXML.cpp!
 //
 //			this means you!
@@ -49,8 +48,6 @@
 //
 //
 //
-//
-
 
 /*  A Bison parser, made from OSUnserializeXML.y
     by GNU Bison version 1.28  */
@@ -75,58 +72,76 @@
 #define	STRING	265
 #define	SYNTAX_ERROR	266
 
-#line 52 "OSUnserializeXML.y"
+#line 55 "OSUnserializeXML.y"
 
 #include <string.h>
 #include <libkern/c++/OSMetaClass.h>
 #include <libkern/c++/OSContainers.h>
 #include <libkern/c++/OSLib.h>
 
+#define YYSTYPE object_t *
+#define YYPARSE_PARAM	state
+#define YYLEX_PARAM	state
+
+// this is the internal struct used to hold objects on parser stack
+// it represents objects both before and after they have been created
 typedef	struct object {
 	struct object	*next;
 	struct object	*free;
 	struct object	*elements;
 	OSObject	*object;
-	const OSSymbol	*key;		// for dictionary
+	OSString	*key;			// for dictionary
 	int		size;
-	void		*data;		// for data
-	char		*string;	// for string & symbol
-	long long 	number;		// for number
+	void		*data;			// for data
+	char		*string;		// for string & symbol
+	long long 	number;			// for number
 	int		idref;
 } object_t;
 
-static int yyparse();
-static int yyerror(char *s);
-static int yylex();
-
-static object_t * newObject();
-static void freeObject(object_t *o);
-
-static object_t *buildOSDictionary(object_t *);
-static object_t *buildOSArray(object_t *);
-static object_t *buildOSSet(object_t *);
-static object_t *buildOSString(object_t *);
-static object_t *buildKey(object_t *);
-static object_t *buildOSData(object_t *);
-static object_t *buildOSNumber(object_t *);
-static object_t *buildOSBoolean(object_t *o);
-
-static void rememberObject(int, OSObject *);
-static object_t *retrieveObject(int);
-
-// resultant object of parsed text
-static OSObject	*parsedObject;
-
-#define YYSTYPE object_t *
+// this code is reentrant, this structure contains all
+// state information for the parsing of a single buffer
+typedef struct parser_state {
+	const char	*parseBuffer;		// start of text to be parsed
+	int		parseBufferIndex;	// current index into text
+	int		lineNumber;		// current line number
+	object_t	*objects;		// internal objects in use
+	object_t	*freeObjects;		// internal objects that are free
+	OSDictionary	*tags;			// used to remember "ID" tags
+	OSString	**errorString;		// parse error with line
+	OSObject	*parsedObject;		// resultant object of parsed text
+} parser_state_t;
+
+#define STATE		((parser_state_t *)state)
+
+#undef yyerror 	
+#define yyerror(s)	OSUnserializeerror(STATE, (s))
+static int		OSUnserializeerror(parser_state_t *state, char *s);
+
+static int		yylex(YYSTYPE *lvalp, parser_state_t *state);
+static int		yyparse(void * state);
+
+static object_t 	*newObject(parser_state_t *state);
+static void 		freeObject(parser_state_t *state, object_t *o);
+static void		rememberObject(parser_state_t *state, int tag, OSObject *o);
+static object_t		*retrieveObject(parser_state_t *state, int tag);
+static void		cleanupObjects(parser_state_t *state);
+
+static object_t		*buildDictionary(parser_state_t *state, object_t *o);
+static object_t		*buildArray(parser_state_t *state, object_t *o);
+static object_t		*buildSet(parser_state_t *state, object_t *o);
+static object_t		*buildString(parser_state_t *state, object_t *o);
+static object_t		*buildData(parser_state_t *state, object_t *o);
+static object_t		*buildNumber(parser_state_t *state, object_t *o);
+static object_t		*buildBoolean(parser_state_t *state, object_t *o);
 
 extern "C" {
-extern void *kern_os_malloc(size_t size);
-extern void *kern_os_realloc(void * addr, size_t size);
-extern void kern_os_free(void * addr);
+extern void		*kern_os_malloc(size_t size);
+extern void		*kern_os_realloc(void * addr, size_t size);
+extern void		kern_os_free(void * addr);
 
 //XXX shouldn't have to define these
-extern long strtol(const char *, char **, int);
-extern unsigned long strtoul(const char *, char **, int);
+extern long		strtol(const char *, char **, int);
+extern unsigned long	strtoul(const char *, char **, int);
 
 } /* extern "C" */
 
@@ -137,6 +152,7 @@
 #ifndef YYSTYPE
 #define YYSTYPE int
 #endif
+
 
 #ifndef __cplusplus
 #ifndef __STDC__
@@ -205,10 +221,10 @@
 
 #if YYDEBUG != 0
 static const short yyrline[] = { 0,
-   123,   124,   129,   135,   136,   137,   138,   139,   140,   141,
-   142,   155,   158,   161,   164,   165,   170,   178,   183,   186,
-   189,   192,   195,   198,   201,   204,   211,   214,   217,   220,
-   223
+   144,   147,   152,   157,   158,   159,   160,   161,   162,   163,
+   164,   177,   180,   183,   186,   187,   192,   201,   206,   209,
+   212,   215,   218,   221,   224,   227,   234,   237,   240,   243,
+   246
 };
 #endif
 
@@ -291,6 +307,8 @@
     16,    17,     3,     4,     5,     6,     7,    -1,     9,    10,
     11,    -1,    13,    -1,    15,    -1,    17
 };
+#define YYPURE 1
+
 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
 #line 3 "/usr/share/bison.simple"
 /* This file comes from bison-1.28.  */
@@ -837,127 +855,129 @@
   switch (yyn) {
 
 case 1:
-#line 123 "OSUnserializeXML.y"
-{ parsedObject = (OSObject *)NULL; YYACCEPT; ;
+#line 144 "OSUnserializeXML.y"
+{ yyerror("unexpected end of buffer");
+				  YYERROR;
+				;
     break;}
 case 2:
-#line 124 "OSUnserializeXML.y"
-{ parsedObject = yyvsp[0]->object;
+#line 147 "OSUnserializeXML.y"
+{ STATE->parsedObject = yyvsp[0]->object;
 				  yyvsp[0]->object = 0;
-				  freeObject(yyvsp[0]);
+				  freeObject(STATE, yyvsp[0]);
 				  YYACCEPT;
 				;
     break;}
 case 3:
-#line 129 "OSUnserializeXML.y"
-{
-				  yyerror("syntax error");
+#line 152 "OSUnserializeXML.y"
+{ yyerror("syntax error");
 				  YYERROR;
 				;
     break;}
 case 4:
-#line 135 "OSUnserializeXML.y"
-{ yyval = buildOSDictionary(yyvsp[0]); ;
+#line 157 "OSUnserializeXML.y"
+{ yyval = buildDictionary(STATE, yyvsp[0]); ;
     break;}
 case 5:
-#line 136 "OSUnserializeXML.y"
-{ yyval = buildOSArray(yyvsp[0]); ;
+#line 158 "OSUnserializeXML.y"
+{ yyval = buildArray(STATE, yyvsp[0]); ;
     break;}
 case 6:
-#line 137 "OSUnserializeXML.y"
-{ yyval = buildOSSet(yyvsp[0]); ;
+#line 159 "OSUnserializeXML.y"
+{ yyval = buildSet(STATE, yyvsp[0]); ;
     break;}
 case 7:
-#line 138 "OSUnserializeXML.y"
-{ yyval = buildOSString(yyvsp[0]); ;
+#line 160 "OSUnserializeXML.y"
+{ yyval = buildString(STATE, yyvsp[0]); ;
     break;}
 case 8:
-#line 139 "OSUnserializeXML.y"
-{ yyval = buildOSData(yyvsp[0]); ;
+#line 161 "OSUnserializeXML.y"
+{ yyval = buildData(STATE, yyvsp[0]); ;
     break;}
 case 9:
-#line 140 "OSUnserializeXML.y"
-{ yyval = buildOSNumber(yyvsp[0]); ;
+#line 162 "OSUnserializeXML.y"
+{ yyval = buildNumber(STATE, yyvsp[0]); ;
     break;}
 case 10:
-#line 141 "OSUnserializeXML.y"
-{ yyval = buildOSBoolean(yyvsp[0]); ;
+#line 163 "OSUnserializeXML.y"
+{ yyval = buildBoolean(STATE, yyvsp[0]); ;
     break;}
 case 11:
-#line 142 "OSUnserializeXML.y"
-{ yyval = retrieveObject(yyvsp[0]->idref);
+#line 164 "OSUnserializeXML.y"
+{ yyval = retrieveObject(STATE, yyvsp[0]->idref);
 				  if (yyval) {
 				    yyval->object->retain();
 				  } else { 
 				    yyerror("forward reference detected");
 				    YYERROR;
 				  }
-				  freeObject(yyvsp[0]);
+				  freeObject(STATE, yyvsp[0]);
 				;
     break;}
 case 12:
-#line 155 "OSUnserializeXML.y"
+#line 177 "OSUnserializeXML.y"
 { yyval = yyvsp[-1];
 				  yyval->elements = NULL;
 				;
     break;}
 case 13:
-#line 158 "OSUnserializeXML.y"
+#line 180 "OSUnserializeXML.y"
 { yyval = yyvsp[-2];
 				  yyval->elements = yyvsp[-1];
 				;
     break;}
 case 16:
-#line 165 "OSUnserializeXML.y"
+#line 187 "OSUnserializeXML.y"
 { yyval = yyvsp[0];
 				  yyval->next = yyvsp[-1];
 				;
     break;}
 case 17:
-#line 170 "OSUnserializeXML.y"
+#line 192 "OSUnserializeXML.y"
 { yyval = yyvsp[-1];
+				  yyval->key = yyval->object;
+				  yyval->object = yyvsp[0]->object;
 				  yyval->next = NULL; 
-				  yyval->object = yyvsp[0]->object;
 				  yyvsp[0]->object = 0;
-				  freeObject(yyvsp[0]);
+				  freeObject(STATE, yyvsp[0]);
 				;
     break;}
 case 18:
-#line 178 "OSUnserializeXML.y"
-{ yyval = buildKey(yyvsp[0]); ;
+#line 201 "OSUnserializeXML.y"
+{ yyval = buildString(STATE, yyvsp[0]); ;
     break;}
 case 19:
-#line 183 "OSUnserializeXML.y"
+#line 206 "OSUnserializeXML.y"
 { yyval = yyvsp[-1];
 				  yyval->elements = NULL;
 				;
     break;}
 case 20:
-#line 186 "OSUnserializeXML.y"
+#line 209 "OSUnserializeXML.y"
 { yyval = yyvsp[-2];
 				  yyval->elements = yyvsp[-1];
 				;
     break;}
 case 22:
-#line 192 "OSUnserializeXML.y"
+#line 215 "OSUnserializeXML.y"
 { yyval = yyvsp[-1];
 				  yyval->elements = NULL;
 				;
     break;}
 case 23:
-#line 195 "OSUnserializeXML.y"
+#line 218 "OSUnserializeXML.y"
 { yyval = yyvsp[-2];
 				  yyval->elements = yyvsp[-1];
 				;
     break;}
 case 25:
-#line 201 "OSUnserializeXML.y"
+#line 224 "OSUnserializeXML.y"
 { yyval = yyvsp[0]; 
 				  yyval->next = NULL; 
 				;
     break;}
 case 26:
-#line 204 "OSUnserializeXML.y"
+#line 227 "OSUnserializeXML.y"
 { yyval = yyvsp[0];
 				  yyval->next = yyvsp[-1];
 				;
@@ -1185,31 +1205,20 @@
     }
   return 1;
 }
-#line 226 "OSUnserializeXML.y"
-
-     
-static int		lineNumber = 0;
-static const char	*parseBuffer;
-static int		parseBufferIndex;
-
-#define currentChar()	(parseBuffer[parseBufferIndex])
-#define nextChar()	(parseBuffer[++parseBufferIndex])
-#define prevChar()	(parseBuffer[parseBufferIndex - 1])
-
-#define isSpace(c)	((c) == ' ' || (c) == '\t')
-#define isAlpha(c)	(((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
-#define isDigit(c)	((c) >= '0' && (c) <= '9')
-#define isAlphaDigit(c)	((c) >= 'a' && (c) <= 'f')
-#define isHexDigit(c)	(isDigit(c) || isAlphaDigit(c))
-#define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-')) 
-
-static char yyerror_message[128];
+#line 249 "OSUnserializeXML.y"
+
 
 int
-yyerror(char *s)  /* Called by yyparse on error */
-{
-	sprintf(yyerror_message, "OSUnserializeXML: %s near line %d\n", s, lineNumber);
-	return 0;
+OSUnserializeerror(parser_state_t * state, char *s)  /* Called by yyparse on errors */
+{
+    char tempString[128];
+
+    if (state->errorString) {
+	snprintf(tempString, 128, "OSUnserializeXML: %s near line %d\n", s, state->lineNumber);
+	*(state->errorString) = OSString::withCString(tempString);
+    }
+
+    return 0;
 }
 
 #define TAG_MAX_LENGTH		32
@@ -1220,13 +1229,25 @@
 #define TAG_EMPTY		3
 #define TAG_COMMENT		4
 
+#define currentChar()	(state->parseBuffer[state->parseBufferIndex])
+#define nextChar()	(state->parseBuffer[++state->parseBufferIndex])
+#define prevChar()	(state->parseBuffer[state->parseBufferIndex - 1])
+
+#define isSpace(c)	((c) == ' ' || (c) == '\t')
+#define isAlpha(c)	(((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+#define isDigit(c)	((c) >= '0' && (c) <= '9')
+#define isAlphaDigit(c)	((c) >= 'a' && (c) <= 'f')
+#define isHexDigit(c)	(isDigit(c) || isAlphaDigit(c))
+#define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-')) 
+
 static int
-getTag(char tag[TAG_MAX_LENGTH],
+getTag(parser_state_t *state,
+       char tag[TAG_MAX_LENGTH],
        int *attributeCount, 
        char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH],
        char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] )
 {
-	int length = 0;;
+	int length = 0;
 	int c = currentChar();
 	int tagType = TAG_START;
 
@@ -1237,7 +1258,7 @@
 
         if (c == '?' || c == '!') {
                 while ((c = nextChar()) != 0) {
-                        if (c == '\n') lineNumber++;
+                        if (c == '\n') state->lineNumber++;
                         if (c == '>') {
                                 (void)nextChar();
                                 return TAG_COMMENT;
@@ -1260,7 +1281,7 @@
 
 	tag[length] = 0;
 
-//printf("tag %s, type %d\n", tag, tagType);
+//	printf("tag %s, type %d\n", tag, tagType);
 	
 	// look for attributes of the form attribute = "value" ...
 	while ((c != '>') && (c != '/')) {
@@ -1293,7 +1314,8 @@
 
 		c = nextChar(); // skip closing quote
 
-//printf("	attribute '%s' = '%s', nextchar = '%c'\n", attributes[*attributeCount], values[*attributeCount], c);
+//		printf("	attribute '%s' = '%s', nextchar = '%c'\n", 
+//		       attributes[*attributeCount], values[*attributeCount], c);
 
 		(*attributeCount)++;
 		if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD;
@@ -1310,18 +1332,17 @@
 }
 
 static char *
-getString()
+getString(parser_state_t *state)
 {
 	int c = currentChar();
-
-	int start, length, i, j;;
+	int start, length, i, j;
 	char * tempString;
 
-	start = parseBufferIndex;
+	start = state->parseBufferIndex;
 	/* find end of string */
 
 	while (c != 0) {
-		if (c == '\n') lineNumber++;
+		if (c == '\n') state->lineNumber++;
 		if (c == '<') {
 			break;
 		}
@@ -1330,13 +1351,13 @@
 
 	if (c != '<') return 0;
 
-	length = parseBufferIndex - start;
+	length = state->parseBufferIndex - start;
 
 	/* copy to null terminated buffer */
 	tempString = (char *)malloc(length + 1);
 	if (tempString == 0) {
 		printf("OSUnserializeXML: can't alloc temp memory\n");
-		return 0;
+		goto error;
 	}
 
 	// copy out string in tempString
@@ -1344,29 +1365,29 @@
 
 	i = j = 0;
 	while (i < length) {
-		c = parseBuffer[start + i++];
+		c = state->parseBuffer[start + i++];
 		if (c != '&') {
 			tempString[j++] = c;
 		} else {
 			if ((i+3) > length) goto error;
-			c = parseBuffer[start + i++];
+			c = state->parseBuffer[start + i++];
 			if (c == 'l') {
-				if (parseBuffer[start + i++] != 't') goto error;
-				if (parseBuffer[start + i++] != ';') goto error;
+				if (state->parseBuffer[start + i++] != 't') goto error;
+				if (state->parseBuffer[start + i++] != ';') goto error;
 				tempString[j++] = '<';
 				continue;
 			}	
 			if (c == 'g') {
-				if (parseBuffer[start + i++] != 't') goto error;
-				if (parseBuffer[start + i++] != ';') goto error;
+				if (state->parseBuffer[start + i++] != 't') goto error;
+				if (state->parseBuffer[start + i++] != ';') goto error;
 				tempString[j++] = '>';
 				continue;
 			}	
 			if ((i+3) > length) goto error;
 			if (c == 'a') {
-				if (parseBuffer[start + i++] != 'm') goto error;
-				if (parseBuffer[start + i++] != 'p') goto error;
-				if (parseBuffer[start + i++] != ';') goto error;
+				if (state->parseBuffer[start + i++] != 'm') goto error;
+				if (state->parseBuffer[start + i++] != 'p') goto error;
+				if (state->parseBuffer[start + i++] != ';') goto error;
 				tempString[j++] = '&';
 				continue;
 			}
@@ -1375,7 +1396,7 @@
 	}
 	tempString[j] = 0;
 
-//printf("string %s\n", tempString);
+//	printf("string %s\n", tempString);
 
 	return tempString;
 
@@ -1385,13 +1406,12 @@
 }
 
 static long long
-getNumber()
+getNumber(parser_state_t *state)
 {
 	unsigned long long n = 0;
 	int base = 10;
+	bool negate = false;
 	int c = currentChar();
-
-	if (!isDigit (c)) return 0;
 
 	if (c == '0') {
 		c = nextChar();
@@ -1401,9 +1421,16 @@
 		}
 	}
 	if (base == 10) {
+		if (c == '-') {
+			negate = true;
+			c = nextChar();
+		}
 		while(isDigit(c)) {
 			n = (n * base + c - '0');
 			c = nextChar();
+		}
+		if (negate) {
+			n = (unsigned long long)((long long)n * (long long)-1);
 		}
 	} else {
 		while(isHexDigit(c)) {
@@ -1415,7 +1442,7 @@
 			c = nextChar();
 		}
 	}
-//printf("number 0x%x\n", (unsigned long)n);
+//	printf("number 0x%x\n", (unsigned long)n);
 	return n;
 }
 
@@ -1440,14 +1467,14 @@
     /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
 };
 
-#define OSDATA_ALLOC_SIZE 4096
+#define DATA_ALLOC_SIZE 4096
 
 static void *
-getCFEncodedData(unsigned int *size)
+getCFEncodedData(parser_state_t *state, unsigned int *size)
 {
     int numeq = 0, acc = 0, cntr = 0;
     int tmpbufpos = 0, tmpbuflen = 0;
-    unsigned char *tmpbuf = (unsigned char *)malloc(OSDATA_ALLOC_SIZE);
+    unsigned char *tmpbuf = (unsigned char *)malloc(DATA_ALLOC_SIZE);
 
     int c = currentChar();
     *size = 0;
@@ -1459,7 +1486,7 @@
 		return 0;
 	}
 	if (c == '=') numeq++; else numeq = 0;
-	if (c == '\n') lineNumber++;
+	if (c == '\n') state->lineNumber++;
         if (__CFPLDataDecodeTable[c] < 0) {
 	    c = nextChar();
             continue;
@@ -1469,7 +1496,7 @@
         acc += __CFPLDataDecodeTable[c];
         if (0 == (cntr & 0x3)) {
             if (tmpbuflen <= tmpbufpos + 2) {
-                tmpbuflen += OSDATA_ALLOC_SIZE;
+                tmpbuflen += DATA_ALLOC_SIZE;
 		tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen);
             }
             tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
@@ -1481,23 +1508,27 @@
 	c = nextChar();
     }
     *size = tmpbufpos;
+    if (*size == 0) {
+	free(tmpbuf);
+	return 0;
+    }
     return tmpbuf;
 }
 
 static void *
-getHexData(unsigned int *size)
+getHexData(parser_state_t *state, unsigned int *size)
 {
     int c;
     unsigned char *d, *start, *lastStart;
 
-    start = lastStart = d = (unsigned char *)malloc(OSDATA_ALLOC_SIZE);
+    start = lastStart = d = (unsigned char *)malloc(DATA_ALLOC_SIZE);
     c = currentChar();
 
     while (c != '<') {
 
 	if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
 	if (c == '\n') {
-	    lineNumber++;
+	    state->lineNumber++;
 	    c = nextChar();
 	    continue;
 	}
@@ -1522,9 +1553,9 @@
 	}
 	
 	d++;
-	if ((d - lastStart) >= OSDATA_ALLOC_SIZE) {
+	if ((d - lastStart) >= DATA_ALLOC_SIZE) {
 	    int oldsize = d - start;
-	    start = (unsigned char *)realloc(start, oldsize + OSDATA_ALLOC_SIZE);
+	    start = (unsigned char *)realloc(start, oldsize + DATA_ALLOC_SIZE);
 	    d = lastStart = start + oldsize;
 	}
 	c = nextChar();
@@ -1541,16 +1572,15 @@
 }
 
 static int
-yylex()
-{
-	int c;
+yylex(YYSTYPE *lvalp, parser_state_t *state)
+{
+	int c, i;
 	int tagType;
 	char tag[TAG_MAX_LENGTH];
 	int attributeCount;
 	char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
 	char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
-
-	if (parseBufferIndex == 0) lineNumber = 1;
+	object_t *object;
 
  top:
 	c = currentChar();
@@ -1560,21 +1590,22 @@
 
 	/* keep track of line number, don't return \n's */
 	if (c == '\n') {
-		lineNumber++;
+		STATE->lineNumber++;
 		(void)nextChar();
 		goto top;
 	}
-	
-	if (!c)	return c;
-
-	tagType = getTag(tag, &attributeCount, attributes, values);
+
+	// end of the buffer?
+	if (!c)	return 0;
+
+	tagType = getTag(STATE, tag, &attributeCount, attributes, values);
 	if (tagType == TAG_BAD) return SYNTAX_ERROR;
 	if (tagType == TAG_COMMENT) goto top;
 
 	// handle allocation and check for "ID" and "IDREF" tags up front
-	yylval = newObject();
-	yylval->idref = -1;
-	for (int i=0; i < attributeCount; i++) {
+	*lvalp = object = newObject(STATE);
+	object->idref = -1;
+	for (i=0; i < attributeCount; i++) {
 	    if (attributes[i][0] == 'I' && attributes[i][1] == 'D') {
 		// check for idref's, note: we ignore the tag, for
 		// this to work correctly, all idrefs must be unique
@@ -1582,12 +1613,12 @@
 		if (attributes[i][2] == 'R' && attributes[i][3] == 'E' &&
 		    attributes[i][4] == 'F' && !attributes[i][5]) {
 		    if (tagType != TAG_EMPTY) return SYNTAX_ERROR;
-		    yylval->idref = strtol(values[i], NULL, 0);
+		    object->idref = strtol(values[i], NULL, 0);
 		    return IDREF;
 		}
 		// check for id's
 		if (!attributes[i][2]) {
-		    yylval->idref = strtol(values[i], NULL, 0);
+		    object->idref = strtol(values[i], NULL, 0);
 		} else {
 		    return SYNTAX_ERROR;
 		}
@@ -1598,7 +1629,7 @@
 	case 'a':
 		if (!strcmp(tag, "array")) {
 			if (tagType == TAG_EMPTY) {
-				yylval->elements = NULL;
+				object->elements = NULL;
 				return ARRAY;
 			}
 			return (tagType == TAG_START) ? '(' : ')';
@@ -1607,33 +1638,34 @@
 	case 'd':
 		if (!strcmp(tag, "dict")) {
 			if (tagType == TAG_EMPTY) {
-				yylval->elements = NULL;
+				object->elements = NULL;
 				return DICTIONARY;
 			}
 			return (tagType == TAG_START) ? '{' : '}';
 		}
 		if (!strcmp(tag, "data")) {
 			unsigned int size;
-			int readable = 0;
 			if (tagType == TAG_EMPTY) {
-				yylval->data = NULL;
-				yylval->size = 0;
+				object->data = NULL;
+				object->size = 0;
 				return DATA;
 			}
+
+			bool isHexFormat = false;
 			for (int i=0; i < attributeCount; i++) {
 				if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) {
-					readable++;
+					isHexFormat = true;
 					break;
 				}
 			}
 			// CF encoded is the default form
-			if (readable) {
-			    yylval->data = getHexData(&size);
+			if (isHexFormat) {
+			    object->data = getHexData(STATE, &size);
 			} else {
-			    yylval->data = getCFEncodedData(&size);
+			    object->data = getCFEncodedData(STATE, &size);
 			}
-			yylval->size = size;
-			if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) {
+			object->size = size;
+			if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) {
 				return SYNTAX_ERROR;
 			}
 			return DATA;
@@ -1642,25 +1674,25 @@
 	case 'f':
 		if (!strcmp(tag, "false")) {
 			if (tagType == TAG_EMPTY) {
-				yylval->number = 0;
+				object->number = 0;
 				return BOOLEAN;
 			}
 		}
 		break;
 	case 'i':
 		if (!strcmp(tag, "integer")) {
-			yylval->size = 64;	// default
-			for (int i=0; i < attributeCount; i++) {
+			object->size = 64;	// default
+			for (i=0; i < attributeCount; i++) {
 				if (!strcmp(attributes[i], "size")) {
-					yylval->size = strtoul(values[i], NULL, 0);
+					object->size = strtoul(values[i], NULL, 0);
 				}
 			}
 			if (tagType == TAG_EMPTY) {
-				yylval->number = 0;
+				object->number = 0;
 				return NUMBER;
 			}
-			yylval->number = getNumber();
-			if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) {
+			object->number = getNumber(STATE);
+			if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) {
 				return SYNTAX_ERROR;
 			}
 			return NUMBER;
@@ -1669,11 +1701,11 @@
 	case 'k':
 		if (!strcmp(tag, "key")) {
 			if (tagType == TAG_EMPTY) return SYNTAX_ERROR;
-			yylval->string = getString();
-			if (!yylval->string) {
+			object->string = getString(STATE);
+			if (!object->string) {
 				return SYNTAX_ERROR;
 			}
-			if ((getTag(tag, &attributeCount, attributes, values) != TAG_END)
+			if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
 			   || strcmp(tag, "key")) {
 				return SYNTAX_ERROR;
 			}
@@ -1682,22 +1714,22 @@
 		break;
 	case 'p':
 		if (!strcmp(tag, "plist")) {
-			freeObject(yylval);
+			freeObject(STATE, object);
 			goto top;
 		}
 		break;
 	case 's':
 		if (!strcmp(tag, "string")) {
 			if (tagType == TAG_EMPTY) {
-			    	yylval->string = (char *)malloc(1);
-			    	*yylval->string = 0;
+			    	object->string = (char *)malloc(1);
+			    	object->string[0] = 0;
 				return STRING;
 			}
-			yylval->string = getString();
-			if (!yylval->string) {
+			object->string = getString(STATE);
+			if (!object->string) {
 				return SYNTAX_ERROR;
 			}
-			if ((getTag(tag, &attributeCount, attributes, values) != TAG_END)
+			if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
 			   || strcmp(tag, "string")) {
 				return SYNTAX_ERROR;
 			}
@@ -1705,7 +1737,7 @@
 		}
 		if (!strcmp(tag, "set")) {
 			if (tagType == TAG_EMPTY) {
-				yylval->elements = NULL;
+				object->elements = NULL;
 				return SET;;
 			}
 			if (tagType == TAG_START) {
@@ -1718,19 +1750,14 @@
 	case 't':
 		if (!strcmp(tag, "true")) {
 			if (tagType == TAG_EMPTY) {
-				yylval->number = 1;
+				object->number = 1;
 				return BOOLEAN;
 			}
 		}
 		break;
-
-	default:
-		// XXX should we ignore invalid tags?
-		return SYNTAX_ERROR;
-		break;
-	}
-
-	return 0;
+	}
+
+	return SYNTAX_ERROR;
 }
 
 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
@@ -1739,94 +1766,96 @@
 
 // "java" like allocation, if this code hits a syntax error in the
 // the middle of the parsed string we just bail with pointers hanging
-// all over place, so this code helps keeps all together
-
-static object_t *objects = 0;
-static object_t *freeObjects = 0;
+// all over place, this code helps keeps it all together
+
+//static int object_count = 0;
 
 object_t *
-newObject()
+newObject(parser_state_t *state)
 {
 	object_t *o;
 
-	if (freeObjects) {
-		o = freeObjects;
-		freeObjects = freeObjects->next;
+	if (state->freeObjects) {
+		o = state->freeObjects;
+		state->freeObjects = state->freeObjects->next;
 	} else {
 		o = (object_t *)malloc(sizeof(object_t));
+//		object_count++;
 		bzero(o, sizeof(object_t));
-		o->free = objects;
-		objects = o;
+		o->free = state->objects;
+		state->objects = o;
 	}
 	
 	return o;
 }
 
 void
-freeObject(object_t *o)
-{
-	o->next = freeObjects;
-	freeObjects = o;	
+freeObject(parser_state_t * state, object_t *o)
+{
+	o->next = state->freeObjects;
+	state->freeObjects = o;	
 }
 
 void
-cleanupObjects()
-{
-	object_t *t, *o = objects;
+cleanupObjects(parser_state_t *state)
+{
+	object_t *t, *o = state->objects;
 
 	while (o) {
 		if (o->object) {
-			printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object);
+//			printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object);
 			o->object->release();
 		}
 		if (o->data) {
-			printf("OSUnserializeXML: freeing   object o=%x data=%x\n", (int)o, (int)o->data);
+//			printf("OSUnserializeXML: freeing   object o=%x data=%x\n", (int)o, (int)o->data);
 			free(o->data);
 		}
 		if (o->key) {
-			printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key);
+//			printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key);
 			o->key->release();
 		}
 		if (o->string) {
-			printf("OSUnserializeXML: freeing   object o=%x string=%x\n", (int)o, (int)o->string);
+//			printf("OSUnserializeXML: freeing   object o=%x string=%x\n", (int)o, (int)o->string);
 			free(o->string);
 		}
 
 		t = o;
 		o = o->free;
 		free(t);
-	}
+//		object_count--;
+	}
+//	printf("object_count = %d\n", object_count);
 }
 
 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
 
-static OSDictionary *tags;
-
 static void 
-rememberObject(int tag, OSObject *o)
+rememberObject(parser_state_t *state, int tag, OSObject *o)
 {
 	char key[16];
-	sprintf(key, "%u", tag);
-
-//printf("remember key %s\n", key);
-
-	tags->setObject(key, o);
+	snprintf(key, 16, "%u", tag);
+
+//	printf("remember key %s\n", key);
+
+	state->tags->setObject(key, o);
 }
 
 static object_t *
-retrieveObject(int tag)
-{
+retrieveObject(parser_state_t *state, int tag)
+{
+	OSObject *ref;
+	object_t *o;
 	char key[16];
-	sprintf(key, "%u", tag);
-
-//printf("retrieve key '%s'\n", key);
-
-	OSObject *ref = tags->getObject(key);
+	snprintf(key, 16, "%u", tag);
+
+//	printf("retrieve key '%s'\n", key);
+
+	ref = state->tags->getObject(key);
 	if (!ref) return 0;
 
-	object_t *o = newObject();
+	o = newObject(state);
 	o->object = ref;
 	return o;
 }
@@ -1836,10 +1865,11 @@
 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
 
 object_t *
-buildOSDictionary(object_t * header)
+buildDictionary(parser_state_t *state, object_t * header)
 {
 	object_t *o, *t;
 	int count = 0;
+	OSDictionary *dict;
 
 	// get count and reverse order
 	o = header->elements;
@@ -1853,31 +1883,33 @@
 		header->elements = t;
 	}
 
-	OSDictionary *d = OSDictionary::withCapacity(count);
-
-	if (header->idref >= 0) rememberObject(header->idref, d);
+	dict = OSDictionary::withCapacity(count);
+	if (header->idref >= 0) rememberObject(state, header->idref, dict);
 
 	o = header->elements;
 	while (o) {
-		d->setObject(o->key, o->object);
+		dict->setObject(o->key, o->object);
+
+		o->key->release();
 		o->object->release();
+		o->key = 0;
 		o->object = 0;
-		o->key->release();
-		o->key = 0;
+
 		t = o;
 		o = o->next;
-		freeObject(t);
+		freeObject(state, t);
 	}
 	o = header;
-	o->object = d;
+	o->object = dict;
 	return o;
 };
 
 object_t *
-buildOSArray(object_t * header)
+buildArray(parser_state_t *state, object_t * header)
 {
 	object_t *o, *t;
 	int count = 0;
+	OSArray *array;
 
 	// get count and reverse order
 	o = header->elements;
@@ -1891,140 +1923,120 @@
 		header->elements = t;
 	}
 
-	OSArray *a = OSArray::withCapacity(count);
-
-	if (header->idref >= 0) rememberObject(header->idref, a);
+	array = OSArray::withCapacity(count);
+	if (header->idref >= 0) rememberObject(state, header->idref, array);
 
 	o = header->elements;
 	while (o) {
-		a->setObject(o->object);
+		array->setObject(o->object);
+
 		o->object->release();
 		o->object = 0;
+
 		t = o;
 		o = o->next;
-		freeObject(t);
+		freeObject(state, t);
 	}
 	o = header;
-	o->object = a;
+	o->object = array;
 	return o;
 };
 
 object_t *
-buildOSSet(object_t *o)
-{
-	o = buildOSArray(o);
-	OSArray *a = (OSArray *)o->object;
-
-	OSSet *s = OSSet::withArray(a, a->getCapacity());
-
-	//write over reference created in array
-	if (o->idref >= 0) rememberObject(o->idref, s);
-
-	a->release();
-	o->object = s;
+buildSet(parser_state_t *state, object_t *header)
+{
+	object_t *o = buildArray(state, header);
+
+	OSArray *array = (OSArray *)o->object;
+	OSSet *set = OSSet::withArray(array, array->getCapacity());
+
+	// write over the reference created in buildArray
+	if (header->idref >= 0) rememberObject(state, header->idref, set);
+
+	array->release();
+	o->object = set;
 	return o;
 };
 
 object_t *
-buildOSString(object_t *o)
-{
-	OSString *s = OSString::withCString(o->string);
-
-	if (o->idref >= 0) rememberObject(o->idref, s);
+buildString(parser_state_t *state, object_t *o)
+{
+	OSString *string;
+
+	string = OSString::withCString(o->string);
+	if (o->idref >= 0) rememberObject(state, o->idref, string);
 
 	free(o->string);
 	o->string = 0;
-	o->object = s;
+	o->object = string;
 
 	return o;
 };
 
 object_t *
-buildKey(object_t *o)
-{
-	const OSSymbol *s = OSSymbol::withCString(o->string);
-
-	free(o->string);
-	o->string = 0;
-	o->key = s;
-
+buildData(parser_state_t *state, object_t *o)
+{
+	OSData *data;
+
+	if (o->size) {
+		data = OSData::withBytes(o->data, o->size);
+	} else {
+		data = OSData::withCapacity(0);
+	}
+	if (o->idref >= 0) rememberObject(state, o->idref, data);
+
+	if (o->size) free(o->data);
+	o->data = 0;
+	o->object = data;
 	return o;
 };
 
 object_t *
-buildOSData(object_t *o)
-{
-	OSData *d;
-
-	if (o->size) {
-		d = OSData::withBytes(o->data, o->size);
-		free(o->data);
-	} else {
-		d = OSData::withCapacity(0);
-	}
-	if (o->idref >= 0) rememberObject(o->idref, d);
-
-	o->data = 0;
-	o->object = d;
+buildNumber(parser_state_t *state, object_t *o)
+{
+	OSNumber *number = OSNumber::withNumber(o->number, o->size);
+
+	if (o->idref >= 0) rememberObject(state, o->idref, number);
+
+	o->object = number;
 	return o;
 };
 
 object_t *
-buildOSNumber(object_t *o)
-{
-	OSNumber *n = OSNumber::withNumber(o->number, o->size);
-
-	if (o->idref >= 0) rememberObject(o->idref, n);
-
-	o->object = n;
+buildBoolean(parser_state_t *state, object_t *o)
+{
+	o->object = ((o->number == 0) ? kOSBooleanFalse : kOSBooleanTrue);
+	o->object->retain();
 	return o;
 };
 
-object_t *
-buildOSBoolean(object_t *o)
-{
-	OSBoolean *b = OSBoolean::withBoolean(o->number != 0);
-	o->object = b;
-	return o;
-};
-
-__BEGIN_DECLS
-#include <kern/lock.h>
-__END_DECLS
-
-static mutex_t *lock = 0;
-
 OSObject*
 OSUnserializeXML(const char *buffer, OSString **errorString)
 {
 	OSObject *object;
-
-	if (!lock) {
-		lock = mutex_alloc(ETAP_IO_AHA);
-		mutex_lock(lock);
-	} else {
-		mutex_lock(lock);
-
-	}
-
-	objects = 0;
-	freeObjects = 0;
-	yyerror_message[0] = 0;		//just in case
-	parseBuffer = buffer;
-	parseBufferIndex = 0;
-	tags = OSDictionary::withCapacity(128);
-	if (yyparse() == 0) {
-		object = parsedObject;
-		if (errorString) *errorString = 0;
-	} else {
-		object = 0;
-		if (errorString)
-			*errorString = OSString::withCString(yyerror_message);
-	}
-
-	cleanupObjects();
-	tags->release();
-	mutex_unlock(lock);
+	parser_state_t *state = (parser_state_t *)malloc(sizeof(parser_state_t));
+
+	if ((!state) || (!buffer)) return 0;
+
+	// just in case
+	if (errorString) *errorString = NULL;
+
+	state->parseBuffer = buffer;
+	state->parseBufferIndex = 0;
+	state->lineNumber = 1;
+	state->objects = 0;
+	state->freeObjects = 0;
+	state->tags = OSDictionary::withCapacity(128);
+	state->errorString = errorString;
+	state->parsedObject = 0;
+
+	(void)yyparse((void *)state);
+
+	object = state->parsedObject;
+
+	cleanupObjects(state);
+	state->tags->release();
+	free(state);
 
 	return object;
 }