1 /*
2  * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /*
30  * HISTORY
31  *
32  * OSUnserializeXML.y created by rsulack on Tue Oct 12 1999
33  */
34 
35 // parser for unserializing OSContainer objects serialized to XML
36 //
37 // to build :
38 //	bison -p OSUnserializeXML OSUnserializeXML.y
39 //	head -50 OSUnserializeXML.y > OSUnserializeXML.cpp
40 //	sed -e "s/#include <stdio.h>//" < OSUnserializeXML.tab.c >> OSUnserializeXML.cpp
41 //
42 //	when changing code check in both OSUnserializeXML.y and OSUnserializeXML.cpp
43 //
44 //
45 //
46 //
47 //
48 //		 DO NOT EDIT OSUnserializeXML.cpp!
49 //
50 //			this means you!
51 /* A Bison parser, made by GNU Bison 2.3.  */
52 
53 /* Skeleton implementation for Bison's Yacc-like parsers in C
54 
55    Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
56    Free Software Foundation, Inc.
57 
58    This program is free software; you can redistribute it and/or modify
59    it under the terms of the GNU General Public License as published by
60    the Free Software Foundation; either version 2, or (at your option)
61    any later version.
62 
63    This program is distributed in the hope that it will be useful,
64    but WITHOUT ANY WARRANTY; without even the implied warranty of
65    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
66    GNU General Public License for more details.
67 
68    You should have received a copy of the GNU General Public License
69    along with this program; if not, write to the Free Software
70    Foundation, Inc., 51 Franklin Street, Fifth Floor,
71    Boston, MA 02110-1301, USA.  */
72 
73 /* As a special exception, you may create a larger work that contains
74    part or all of the Bison parser skeleton and distribute that work
75    under terms of your choice, so long as that work isn't itself a
76    parser generator using the skeleton or a modified version thereof
77    as a parser skeleton.  Alternatively, if you modify or redistribute
78    the parser skeleton itself, you may (at your option) remove this
79    special exception, which will cause the skeleton and the resulting
80    Bison output files to be licensed under the GNU General Public
81    License without this special exception.
82 
83    This special exception was added by the Free Software Foundation in
84    version 2.2 of Bison.  */
85 
86 /* C LALR(1) parser skeleton written by Richard Stallman, by
87    simplifying the original so-called "semantic" parser.  */
88 
89 /* All symbols defined below should begin with yy or YY, to avoid
90    infringing on user name space.  This should be done even for local
91    variables, as they might otherwise be expanded by user macros.
92    There are some unavoidable exceptions within include files to
93    define necessary library symbols; they are noted "INFRINGES ON
94    USER NAME SPACE" below.  */
95 
96 /* Identify Bison output.  */
97 #define YYBISON 1
98 
99 /* Bison version.  */
100 #define YYBISON_VERSION "2.3"
101 
102 /* Skeleton name.  */
103 #define YYSKELETON_NAME "yacc.c"
104 
105 /* Pure parsers.  */
106 #define YYPURE 1
107 
108 /* Using locations.  */
109 #define YYLSP_NEEDED 0
110 
111 /* Substitute the variable and function names.  */
112 #define yyparse OSUnserializeXMLparse
113 #define yylex   OSUnserializeXMLlex
114 #define yyerror OSUnserializeXMLerror
115 #define yylval  OSUnserializeXMLlval
116 #define yychar  OSUnserializeXMLchar
117 #define yydebug OSUnserializeXMLdebug
118 #define yynerrs OSUnserializeXMLnerrs
119 
120 
121 /* Tokens.  */
122 #ifndef YYTOKENTYPE
123 # define YYTOKENTYPE
124    /* Put the tokens into the symbol table, so that GDB and other debuggers
125       know about them.  */
126    enum yytokentype {
127      ARRAY = 258,
128      BOOLEAN = 259,
129      DATA = 260,
130      DICTIONARY = 261,
131      IDREF = 262,
132      KEY = 263,
133      NUMBER = 264,
134      SET = 265,
135      STRING = 266,
136      SYNTAX_ERROR = 267
137    };
138 #endif
139 /* Tokens.  */
140 #define ARRAY 258
141 #define BOOLEAN 259
142 #define DATA 260
143 #define DICTIONARY 261
144 #define IDREF 262
145 #define KEY 263
146 #define NUMBER 264
147 #define SET 265
148 #define STRING 266
149 #define SYNTAX_ERROR 267
150 
151 
152 
153 
154 /* Copy the first part of user declarations.  */
155 #line 61 "OSUnserializeXML.y"
156 
157 #include <string.h>
158 #include <libkern/c++/OSMetaClass.h>
159 #include <libkern/c++/OSContainers.h>
160 #include <libkern/c++/OSLib.h>
161 
162 #define YYSTYPE object_t *
163 #define YYPARSE_PARAM	state
164 #define YYLEX_PARAM	(parser_state_t *)state
165 
166 // this is the internal struct used to hold objects on parser stack
167 // it represents objects both before and after they have been created
168 typedef	struct object {
169 	struct object	*next;
170 	struct object	*free;
171 	struct object	*elements;
172 	OSObject	*object;
173 	OSString	*key;			// for dictionary
174 	int		size;
175 	void		*data;			// for data
176 	char		*string;		// for string & symbol
177 	long long 	number;			// for number
178 	int		idref;
179 } object_t;
180 
181 // this code is reentrant, this structure contains all
182 // state information for the parsing of a single buffer
183 typedef struct parser_state {
184 	const char	*parseBuffer;		// start of text to be parsed
185 	int		parseBufferIndex;	// current index into text
186 	int		lineNumber;		// current line number
187 	object_t	*objects;		// internal objects in use
188 	object_t	*freeObjects;		// internal objects that are free
189 	OSDictionary	*tags;			// used to remember "ID" tags
190 	OSString	**errorString;		// parse error with line
191 	OSObject	*parsedObject;		// resultant object of parsed text
192 } parser_state_t;
193 
194 #define STATE		((parser_state_t *)state)
195 
196 #undef yyerror
197 #define yyerror(s)	OSUnserializeerror(STATE, (s))
198 static int		OSUnserializeerror(parser_state_t *state, char *s);
199 
200 static int		yylex(YYSTYPE *lvalp, parser_state_t *state);
201 static int		yyparse(void * state);
202 
203 static object_t 	*newObject(parser_state_t *state);
204 static void 		freeObject(parser_state_t *state, object_t *o);
205 static void		rememberObject(parser_state_t *state, int tag, OSObject *o);
206 static object_t		*retrieveObject(parser_state_t *state, int tag);
207 static void		cleanupObjects(parser_state_t *state);
208 
209 static object_t		*buildDictionary(parser_state_t *state, object_t *o);
210 static object_t		*buildArray(parser_state_t *state, object_t *o);
211 static object_t		*buildSet(parser_state_t *state, object_t *o);
212 static object_t		*buildString(parser_state_t *state, object_t *o);
213 static object_t		*buildData(parser_state_t *state, object_t *o);
214 static object_t		*buildNumber(parser_state_t *state, object_t *o);
215 static object_t		*buildBoolean(parser_state_t *state, object_t *o);
216 
217 extern "C" {
218 extern void		*kern_os_malloc(size_t size);
219 extern void		*kern_os_realloc(void * addr, size_t size);
220 extern void		kern_os_free(void * addr);
221 
222 //XXX shouldn't have to define these
223 extern long		strtol(const char *, char **, int);
224 extern unsigned long	strtoul(const char *, char **, int);
225 
226 } /* extern "C" */
227 
228 #define malloc(s) kern_os_malloc(s)
229 #define realloc(a, s) kern_os_realloc(a, s)
230 #define free(a) kern_os_free((void *)a)
231 
232 
233 
234 /* Enabling traces.  */
235 #ifndef YYDEBUG
236 # define YYDEBUG 0
237 #endif
238 
239 /* Enabling verbose error messages.  */
240 #ifdef YYERROR_VERBOSE
241 # undef YYERROR_VERBOSE
242 # define YYERROR_VERBOSE 1
243 #else
244 # define YYERROR_VERBOSE 0
245 #endif
246 
247 /* Enabling the token table.  */
248 #ifndef YYTOKEN_TABLE
249 # define YYTOKEN_TABLE 0
250 #endif
251 
252 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
253 typedef int YYSTYPE;
254 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
255 # define YYSTYPE_IS_DECLARED 1
256 # define YYSTYPE_IS_TRIVIAL 1
257 #endif
258 
259 
260 
261 /* Copy the second part of user declarations.  */
262 
263 
264 /* Line 216 of yacc.c.  */
265 #line 216 "OSUnserializeXML.tab.c"
266 
267 #ifdef short
268 # undef short
269 #endif
270 
271 #ifdef YYTYPE_UINT8
272 typedef YYTYPE_UINT8 yytype_uint8;
273 #else
274 typedef unsigned char yytype_uint8;
275 #endif
276 
277 #ifdef YYTYPE_INT8
278 typedef YYTYPE_INT8 yytype_int8;
279 #elif (defined __STDC__ || defined __C99__FUNC__ \
280      || defined __cplusplus || defined _MSC_VER)
281 typedef signed char yytype_int8;
282 #else
283 typedef short int yytype_int8;
284 #endif
285 
286 #ifdef YYTYPE_UINT16
287 typedef YYTYPE_UINT16 yytype_uint16;
288 #else
289 typedef unsigned short int yytype_uint16;
290 #endif
291 
292 #ifdef YYTYPE_INT16
293 typedef YYTYPE_INT16 yytype_int16;
294 #else
295 typedef short int yytype_int16;
296 #endif
297 
298 #ifndef YYSIZE_T
299 # ifdef __SIZE_TYPE__
300 #  define YYSIZE_T __SIZE_TYPE__
301 # elif defined size_t
302 #  define YYSIZE_T size_t
303 # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
304      || defined __cplusplus || defined _MSC_VER)
305 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
306 #  define YYSIZE_T size_t
307 # else
308 #  define YYSIZE_T unsigned int
309 # endif
310 #endif
311 
312 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
313 
314 #ifndef YY_
315 # if YYENABLE_NLS
316 #  if ENABLE_NLS
317 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
318 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
319 #  endif
320 # endif
321 # ifndef YY_
322 #  define YY_(msgid) msgid
323 # endif
324 #endif
325 
326 /* Suppress unused-variable warnings by "using" E.  */
327 #if ! defined lint || defined __GNUC__
328 # define YYUSE(e) ((void) (e))
329 #else
330 # define YYUSE(e) /* empty */
331 #endif
332 
333 /* Identity function, used to suppress warnings about constant conditions.  */
334 #ifndef lint
335 # define YYID(n) (n)
336 #else
337 #if (defined __STDC__ || defined __C99__FUNC__ \
338      || defined __cplusplus || defined _MSC_VER)
339 static int
340 YYID (int i)
341 #else
342 static int
343 YYID (i)
344     int i;
345 #endif
346 {
347   return i;
348 }
349 #endif
350 
351 #if ! defined yyoverflow || YYERROR_VERBOSE
352 
353 /* The parser invokes alloca or malloc; define the necessary symbols.  */
354 
355 # ifdef YYSTACK_USE_ALLOCA
356 #  if YYSTACK_USE_ALLOCA
357 #   ifdef __GNUC__
358 #    define YYSTACK_ALLOC __builtin_alloca
359 #   elif defined __BUILTIN_VA_ARG_INCR
360 #    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
361 #   elif defined _AIX
362 #    define YYSTACK_ALLOC __alloca
363 #   elif defined _MSC_VER
364 #    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
365 #    define alloca _alloca
366 #   else
367 #    define YYSTACK_ALLOC alloca
368 #    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
369      || defined __cplusplus || defined _MSC_VER)
370 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
371 #     ifndef _STDLIB_H
372 #      define _STDLIB_H 1
373 #     endif
374 #    endif
375 #   endif
376 #  endif
377 # endif
378 
379 # ifdef YYSTACK_ALLOC
380    /* Pacify GCC's `empty if-body' warning.  */
381 #  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
382 #  ifndef YYSTACK_ALLOC_MAXIMUM
383     /* The OS might guarantee only one guard page at the bottom of the stack,
384        and a page size can be as small as 4096 bytes.  So we cannot safely
385        invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
386        to allow for a few compiler-allocated temporary stack slots.  */
387 #   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
388 #  endif
389 # else
390 #  define YYSTACK_ALLOC YYMALLOC
391 #  define YYSTACK_FREE YYFREE
392 #  ifndef YYSTACK_ALLOC_MAXIMUM
393 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
394 #  endif
395 #  if (defined __cplusplus && ! defined _STDLIB_H \
396        && ! ((defined YYMALLOC || defined malloc) \
397 	     && (defined YYFREE || defined free)))
398 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
399 #   ifndef _STDLIB_H
400 #    define _STDLIB_H 1
401 #   endif
402 #  endif
403 #  ifndef YYMALLOC
404 #   define YYMALLOC malloc
405 #   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
406      || defined __cplusplus || defined _MSC_VER)
407 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
408 #   endif
409 #  endif
410 #  ifndef YYFREE
411 #   define YYFREE free
412 #   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
413      || defined __cplusplus || defined _MSC_VER)
414 void free (void *); /* INFRINGES ON USER NAME SPACE */
415 #   endif
416 #  endif
417 # endif
418 #endif /* ! defined yyoverflow || YYERROR_VERBOSE */
419 
420 
421 #if (! defined yyoverflow \
422      && (! defined __cplusplus \
423 	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
424 
425 /* A type that is properly aligned for any stack member.  */
426 union yyalloc
427 {
428   yytype_int16 yyss;
429   YYSTYPE yyvs;
430   };
431 
432 /* The size of the maximum gap between one aligned stack and the next.  */
433 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
434 
435 /* The size of an array large to enough to hold all stacks, each with
436    N elements.  */
437 # define YYSTACK_BYTES(N) \
438      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
439       + YYSTACK_GAP_MAXIMUM)
440 
441 /* Copy COUNT objects from FROM to TO.  The source and destination do
442    not overlap.  */
443 # ifndef YYCOPY
444 #  if defined __GNUC__ && 1 < __GNUC__
445 #   define YYCOPY(To, From, Count) \
446       __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
447 #  else
448 #   define YYCOPY(To, From, Count)		\
449       do					\
450 	{					\
451 	  YYSIZE_T yyi;				\
452 	  for (yyi = 0; yyi < (Count); yyi++)	\
453 	    (To)[yyi] = (From)[yyi];		\
454 	}					\
455       while (YYID (0))
456 #  endif
457 # endif
458 
459 /* Relocate STACK from its old location to the new one.  The
460    local variables YYSIZE and YYSTACKSIZE give the old and new number of
461    elements in the stack, and YYPTR gives the new location of the
462    stack.  Advance YYPTR to a properly aligned location for the next
463    stack.  */
464 # define YYSTACK_RELOCATE(Stack)					\
465     do									\
466       {									\
467 	YYSIZE_T yynewbytes;						\
468 	YYCOPY (&yyptr->Stack, Stack, yysize);				\
469 	Stack = &yyptr->Stack;						\
470 	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
471 	yyptr += yynewbytes / sizeof (*yyptr);				\
472       }									\
473     while (YYID (0))
474 
475 #endif
476 
477 /* YYFINAL -- State number of the termination state.  */
478 #define YYFINAL  33
479 /* YYLAST -- Last index in YYTABLE.  */
480 #define YYLAST   108
481 
482 /* YYNTOKENS -- Number of terminals.  */
483 #define YYNTOKENS  19
484 /* YYNNTS -- Number of nonterminals.  */
485 #define YYNNTS  15
486 /* YYNRULES -- Number of rules.  */
487 #define YYNRULES  32
488 /* YYNRULES -- Number of states.  */
489 #define YYNSTATES  40
490 
491 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
492 #define YYUNDEFTOK  2
493 #define YYMAXUTOK   267
494 
495 #define YYTRANSLATE(YYX)						\
496   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
497 
498 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
499 static const yytype_uint8 yytranslate[] =
500 {
501        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
502        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
503        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
504        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
505       15,    16,     2,     2,     2,     2,     2,     2,     2,     2,
506        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
507        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
508        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
509        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
510        2,    17,     2,    18,     2,     2,     2,     2,     2,     2,
511        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
512        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
513        2,     2,     2,    13,     2,    14,     2,     2,     2,     2,
514        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
515        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
516        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
517        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
518        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
519        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
520        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
521        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
522        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
523        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
524        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
525        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
526        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
527        5,     6,     7,     8,     9,    10,    11,    12
528 };
529 
530 #if YYDEBUG
531 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
532    YYRHS.  */
533 static const yytype_uint8 yyprhs[] =
534 {
535        0,     0,     3,     4,     6,     8,    10,    12,    14,    16,
536       18,    20,    22,    24,    27,    31,    33,    35,    38,    41,
537       43,    46,    50,    52,    55,    59,    61,    63,    66,    68,
538       70,    72,    74
539 };
540 
541 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
542 static const yytype_int8 yyrhs[] =
543 {
544       20,     0,    -1,    -1,    21,    -1,    12,    -1,    22,    -1,
545       26,    -1,    27,    -1,    33,    -1,    30,    -1,    32,    -1,
546       29,    -1,    31,    -1,    13,    14,    -1,    13,    23,    14,
547       -1,     6,    -1,    24,    -1,    23,    24,    -1,    25,    21,
548       -1,     8,    -1,    15,    16,    -1,    15,    28,    16,    -1,
549        3,    -1,    17,    18,    -1,    17,    28,    18,    -1,    10,
550       -1,    21,    -1,    28,    21,    -1,     4,    -1,     5,    -1,
551        7,    -1,     9,    -1,    11,    -1
552 };
553 
554 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
555 static const yytype_uint8 yyrline[] =
556 {
557        0,   150,   150,   153,   158,   163,   164,   165,   166,   167,
558      168,   169,   170,   183,   186,   189,   192,   193,   198,   207,
559      212,   215,   218,   221,   224,   227,   230,   233,   240,   243,
560      246,   249,   252
561 };
562 #endif
563 
564 #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
565 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
566    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
567 static const char *const yytname[] =
568 {
569   "$end", "error", "$undefined", "ARRAY", "BOOLEAN", "DATA", "DICTIONARY",
570   "IDREF", "KEY", "NUMBER", "SET", "STRING", "SYNTAX_ERROR", "'{'", "'}'",
571   "'('", "')'", "'['", "']'", "$accept", "input", "object", "dict",
572   "pairs", "pair", "key", "array", "set", "elements", "boolean", "data",
573   "idref", "number", "string", 0
574 };
575 #endif
576 
577 # ifdef YYPRINT
578 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
579    token YYLEX-NUM.  */
580 static const yytype_uint16 yytoknum[] =
581 {
582        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
583      265,   266,   267,   123,   125,    40,    41,    91,    93
584 };
585 # endif
586 
587 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
588 static const yytype_uint8 yyr1[] =
589 {
590        0,    19,    20,    20,    20,    21,    21,    21,    21,    21,
591       21,    21,    21,    22,    22,    22,    23,    23,    24,    25,
592       26,    26,    26,    27,    27,    27,    28,    28,    29,    30,
593       31,    32,    33
594 };
595 
596 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
597 static const yytype_uint8 yyr2[] =
598 {
599        0,     2,     0,     1,     1,     1,     1,     1,     1,     1,
600        1,     1,     1,     2,     3,     1,     1,     2,     2,     1,
601        2,     3,     1,     2,     3,     1,     1,     2,     1,     1,
602        1,     1,     1
603 };
604 
605 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
606    STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
607    means the default is an error.  */
608 static const yytype_uint8 yydefact[] =
609 {
610        2,    22,    28,    29,    15,    30,    31,    25,    32,     4,
611        0,     0,     0,     0,     3,     5,     6,     7,    11,     9,
612       12,    10,     8,    19,    13,     0,    16,     0,    20,    26,
613        0,    23,     0,     1,    14,    17,    18,    21,    27,    24
614 };
615 
616 /* YYDEFGOTO[NTERM-NUM].  */
617 static const yytype_int8 yydefgoto[] =
618 {
619       -1,    13,    29,    15,    25,    26,    27,    16,    17,    30,
620       18,    19,    20,    21,    22
621 };
622 
623 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
624    STATE-NUM.  */
625 #define YYPACT_NINF -20
626 static const yytype_int8 yypact[] =
627 {
628       46,   -20,   -20,   -20,   -20,   -20,   -20,   -20,   -20,   -20,
629        4,    61,    -2,    10,   -20,   -20,   -20,   -20,   -20,   -20,
630      -20,   -20,   -20,   -20,   -20,     6,   -20,    91,   -20,   -20,
631       76,   -20,    30,   -20,   -20,   -20,   -20,   -20,   -20,   -20
632 };
633 
634 /* YYPGOTO[NTERM-NUM].  */
635 static const yytype_int8 yypgoto[] =
636 {
637      -20,   -20,     0,   -20,   -20,   -19,   -20,   -20,   -20,     5,
638      -20,   -20,   -20,   -20,   -20
639 };
640 
641 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
642    positive, shift that token.  If negative, reduce the rule which
643    number is the opposite.  If zero, do what YYDEFACT says.
644    If YYTABLE_NINF, syntax error.  */
645 #define YYTABLE_NINF -1
646 static const yytype_uint8 yytable[] =
647 {
648       14,     1,     2,     3,     4,     5,    35,     6,     7,     8,
649       33,    10,    23,    11,    23,    12,    31,    32,    24,     0,
650       34,     0,     0,     0,     0,     0,     0,    36,     0,     0,
651       38,     0,    38,     1,     2,     3,     4,     5,     0,     6,
652        7,     8,     0,    10,     0,    11,     0,    12,    39,     1,
653        2,     3,     4,     5,     0,     6,     7,     8,     9,    10,
654        0,    11,     0,    12,     1,     2,     3,     4,     5,     0,
655        6,     7,     8,     0,    10,     0,    11,    28,    12,     1,
656        2,     3,     4,     5,     0,     6,     7,     8,     0,    10,
657        0,    11,    37,    12,     1,     2,     3,     4,     5,     0,
658        6,     7,     8,     0,    10,     0,    11,     0,    12
659 };
660 
661 static const yytype_int8 yycheck[] =
662 {
663        0,     3,     4,     5,     6,     7,    25,     9,    10,    11,
664        0,    13,     8,    15,     8,    17,    18,    12,    14,    -1,
665       14,    -1,    -1,    -1,    -1,    -1,    -1,    27,    -1,    -1,
666       30,    -1,    32,     3,     4,     5,     6,     7,    -1,     9,
667       10,    11,    -1,    13,    -1,    15,    -1,    17,    18,     3,
668        4,     5,     6,     7,    -1,     9,    10,    11,    12,    13,
669       -1,    15,    -1,    17,     3,     4,     5,     6,     7,    -1,
670        9,    10,    11,    -1,    13,    -1,    15,    16,    17,     3,
671        4,     5,     6,     7,    -1,     9,    10,    11,    -1,    13,
672       -1,    15,    16,    17,     3,     4,     5,     6,     7,    -1,
673        9,    10,    11,    -1,    13,    -1,    15,    -1,    17
674 };
675 
676 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
677    symbol of state STATE-NUM.  */
678 static const yytype_uint8 yystos[] =
679 {
680        0,     3,     4,     5,     6,     7,     9,    10,    11,    12,
681       13,    15,    17,    20,    21,    22,    26,    27,    29,    30,
682       31,    32,    33,     8,    14,    23,    24,    25,    16,    21,
683       28,    18,    28,     0,    14,    24,    21,    16,    21,    18
684 };
685 
686 #define yyerrok		(yyerrstatus = 0)
687 #define yyclearin	(yychar = YYEMPTY)
688 #define YYEMPTY		(-2)
689 #define YYEOF		0
690 
691 #define YYACCEPT	goto yyacceptlab
692 #define YYABORT		goto yyabortlab
693 #define YYERROR		goto yyerrorlab
694 
695 
696 /* Like YYERROR except do call yyerror.  This remains here temporarily
697    to ease the transition to the new meaning of YYERROR, for GCC.
698    Once GCC version 2 has supplanted version 1, this can go.  */
699 
700 #define YYFAIL		goto yyerrlab
701 
702 #define YYRECOVERING()  (!!yyerrstatus)
703 
704 #define YYBACKUP(Token, Value)					\
705 do								\
706   if (yychar == YYEMPTY && yylen == 1)				\
707     {								\
708       yychar = (Token);						\
709       yylval = (Value);						\
710       yytoken = YYTRANSLATE (yychar);				\
711       YYPOPSTACK (1);						\
712       goto yybackup;						\
713     }								\
714   else								\
715     {								\
716       yyerror (YY_("syntax error: cannot back up")); \
717       YYERROR;							\
718     }								\
719 while (YYID (0))
720 
721 
722 #define YYTERROR	1
723 #define YYERRCODE	256
724 
725 
726 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
727    If N is 0, then set CURRENT to the empty location which ends
728    the previous symbol: RHS[0] (always defined).  */
729 
730 #define YYRHSLOC(Rhs, K) ((Rhs)[K])
731 #ifndef YYLLOC_DEFAULT
732 # define YYLLOC_DEFAULT(Current, Rhs, N)				\
733     do									\
734       if (YYID (N))                                                    \
735 	{								\
736 	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
737 	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
738 	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
739 	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
740 	}								\
741       else								\
742 	{								\
743 	  (Current).first_line   = (Current).last_line   =		\
744 	    YYRHSLOC (Rhs, 0).last_line;				\
745 	  (Current).first_column = (Current).last_column =		\
746 	    YYRHSLOC (Rhs, 0).last_column;				\
747 	}								\
748     while (YYID (0))
749 #endif
750 
751 
752 /* YY_LOCATION_PRINT -- Print the location on the stream.
753    This macro was not mandated originally: define only if we know
754    we won't break user code: when these are the locations we know.  */
755 
756 #ifndef YY_LOCATION_PRINT
757 # if YYLTYPE_IS_TRIVIAL
758 #  define YY_LOCATION_PRINT(File, Loc)			\
759      fprintf (File, "%d.%d-%d.%d",			\
760 	      (Loc).first_line, (Loc).first_column,	\
761 	      (Loc).last_line,  (Loc).last_column)
762 # else
763 #  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
764 # endif
765 #endif
766 
767 
768 /* YYLEX -- calling `yylex' with the right arguments.  */
769 
770 #ifdef YYLEX_PARAM
771 # define YYLEX yylex (&yylval, YYLEX_PARAM)
772 #else
773 # define YYLEX yylex (&yylval)
774 #endif
775 
776 /* Enable debugging if requested.  */
777 #if YYDEBUG
778 
779 # ifndef YYFPRINTF
780 #  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
781 #  define YYFPRINTF fprintf
782 # endif
783 
784 # define YYDPRINTF(Args)			\
785 do {						\
786   if (yydebug)					\
787     YYFPRINTF Args;				\
788 } while (YYID (0))
789 
790 # define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
791 do {									  \
792   if (yydebug)								  \
793     {									  \
794       YYFPRINTF (stderr, "%s ", Title);					  \
795       yy_symbol_print (stderr,						  \
796 		  Type, Value); \
797       YYFPRINTF (stderr, "\n");						  \
798     }									  \
799 } while (YYID (0))
800 
801 
802 /*--------------------------------.
803 | Print this symbol on YYOUTPUT.  |
804 `--------------------------------*/
805 
806 /*ARGSUSED*/
807 #if (defined __STDC__ || defined __C99__FUNC__ \
808      || defined __cplusplus || defined _MSC_VER)
809 static void
810 yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
811 #else
812 static void
813 yy_symbol_value_print (yyoutput, yytype, yyvaluep)
814     FILE *yyoutput;
815     int yytype;
816     YYSTYPE const * const yyvaluep;
817 #endif
818 {
819   if (!yyvaluep)
820     return;
821 # ifdef YYPRINT
822   if (yytype < YYNTOKENS)
823     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
824 # else
825   YYUSE (yyoutput);
826 # endif
827   switch (yytype)
828     {
829       default:
830 	break;
831     }
832 }
833 
834 
835 /*--------------------------------.
836 | Print this symbol on YYOUTPUT.  |
837 `--------------------------------*/
838 
839 #if (defined __STDC__ || defined __C99__FUNC__ \
840      || defined __cplusplus || defined _MSC_VER)
841 static void
842 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
843 #else
844 static void
845 yy_symbol_print (yyoutput, yytype, yyvaluep)
846     FILE *yyoutput;
847     int yytype;
848     YYSTYPE const * const yyvaluep;
849 #endif
850 {
851   if (yytype < YYNTOKENS)
852     YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
853   else
854     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
855 
856   yy_symbol_value_print (yyoutput, yytype, yyvaluep);
857   YYFPRINTF (yyoutput, ")");
858 }
859 
860 /*------------------------------------------------------------------.
861 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
862 | TOP (included).                                                   |
863 `------------------------------------------------------------------*/
864 
865 #if (defined __STDC__ || defined __C99__FUNC__ \
866      || defined __cplusplus || defined _MSC_VER)
867 static void
868 yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
869 #else
870 static void
871 yy_stack_print (bottom, top)
872     yytype_int16 *bottom;
873     yytype_int16 *top;
874 #endif
875 {
876   YYFPRINTF (stderr, "Stack now");
877   for (; bottom <= top; ++bottom)
878     YYFPRINTF (stderr, " %d", *bottom);
879   YYFPRINTF (stderr, "\n");
880 }
881 
882 # define YY_STACK_PRINT(Bottom, Top)				\
883 do {								\
884   if (yydebug)							\
885     yy_stack_print ((Bottom), (Top));				\
886 } while (YYID (0))
887 
888 
889 /*------------------------------------------------.
890 | Report that the YYRULE is going to be reduced.  |
891 `------------------------------------------------*/
892 
893 #if (defined __STDC__ || defined __C99__FUNC__ \
894      || defined __cplusplus || defined _MSC_VER)
895 static void
896 yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
897 #else
898 static void
899 yy_reduce_print (yyvsp, yyrule)
900     YYSTYPE *yyvsp;
901     int yyrule;
902 #endif
903 {
904   int yynrhs = yyr2[yyrule];
905   int yyi;
906   unsigned long int yylno = yyrline[yyrule];
907   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
908 	     yyrule - 1, yylno);
909   /* The symbols being reduced.  */
910   for (yyi = 0; yyi < yynrhs; yyi++)
911     {
912       fprintf (stderr, "   $%d = ", yyi + 1);
913       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
914 		       &(yyvsp[(yyi + 1) - (yynrhs)])
915 		       		       );
916       fprintf (stderr, "\n");
917     }
918 }
919 
920 # define YY_REDUCE_PRINT(Rule)		\
921 do {					\
922   if (yydebug)				\
923     yy_reduce_print (yyvsp, Rule); \
924 } while (YYID (0))
925 
926 /* Nonzero means print parse trace.  It is left uninitialized so that
927    multiple parsers can coexist.  */
928 int yydebug;
929 #else /* !YYDEBUG */
930 # define YYDPRINTF(Args)
931 # define YY_SYMBOL_PRINT(Title, Type, Value, Location)
932 # define YY_STACK_PRINT(Bottom, Top)
933 # define YY_REDUCE_PRINT(Rule)
934 #endif /* !YYDEBUG */
935 
936 
937 /* YYINITDEPTH -- initial size of the parser's stacks.  */
938 #ifndef	YYINITDEPTH
939 # define YYINITDEPTH 200
940 #endif
941 
942 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
943    if the built-in stack extension method is used).
944 
945    Do not make this value too large; the results are undefined if
946    YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
947    evaluated with infinite-precision integer arithmetic.  */
948 
949 #ifndef YYMAXDEPTH
950 # define YYMAXDEPTH 10000
951 #endif
952 
953 
954 
955 #if YYERROR_VERBOSE
956 
957 # ifndef yystrlen
958 #  if defined __GLIBC__ && defined _STRING_H
959 #   define yystrlen strlen
960 #  else
961 /* Return the length of YYSTR.  */
962 #if (defined __STDC__ || defined __C99__FUNC__ \
963      || defined __cplusplus || defined _MSC_VER)
964 static YYSIZE_T
965 yystrlen (const char *yystr)
966 #else
967 static YYSIZE_T
968 yystrlen (yystr)
969     const char *yystr;
970 #endif
971 {
972   YYSIZE_T yylen;
973   for (yylen = 0; yystr[yylen]; yylen++)
974     continue;
975   return yylen;
976 }
977 #  endif
978 # endif
979 
980 # ifndef yystpcpy
981 #  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
982 #   define yystpcpy stpcpy
983 #  else
984 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
985    YYDEST.  */
986 #if (defined __STDC__ || defined __C99__FUNC__ \
987      || defined __cplusplus || defined _MSC_VER)
988 static char *
989 yystpcpy (char *yydest, const char *yysrc)
990 #else
991 static char *
992 yystpcpy (yydest, yysrc)
993     char *yydest;
994     const char *yysrc;
995 #endif
996 {
997   char *yyd = yydest;
998   const char *yys = yysrc;
999 
1000   while ((*yyd++ = *yys++) != '\0')
1001     continue;
1002 
1003   return yyd - 1;
1004 }
1005 #  endif
1006 # endif
1007 
1008 # ifndef yytnamerr
1009 /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
1010    quotes and backslashes, so that it's suitable for yyerror.  The
1011    heuristic is that double-quoting is unnecessary unless the string
1012    contains an apostrophe, a comma, or backslash (other than
1013    backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
1014    null, do not copy; instead, return the length of what the result
1015    would have been.  */
1016 static YYSIZE_T
1017 yytnamerr (char *yyres, const char *yystr)
1018 {
1019   if (*yystr == '"')
1020     {
1021       YYSIZE_T yyn = 0;
1022       char const *yyp = yystr;
1023 
1024       for (;;)
1025 	switch (*++yyp)
1026 	  {
1027 	  case '\'':
1028 	  case ',':
1029 	    goto do_not_strip_quotes;
1030 
1031 	  case '\\':
1032 	    if (*++yyp != '\\')
1033 	      goto do_not_strip_quotes;
1034 	    /* Fall through.  */
1035 	  default:
1036 	    if (yyres)
1037 	      yyres[yyn] = *yyp;
1038 	    yyn++;
1039 	    break;
1040 
1041 	  case '"':
1042 	    if (yyres)
1043 	      yyres[yyn] = '\0';
1044 	    return yyn;
1045 	  }
1046     do_not_strip_quotes: ;
1047     }
1048 
1049   if (! yyres)
1050     return yystrlen (yystr);
1051 
1052   return yystpcpy (yyres, yystr) - yyres;
1053 }
1054 # endif
1055 
1056 /* Copy into YYRESULT an error message about the unexpected token
1057    YYCHAR while in state YYSTATE.  Return the number of bytes copied,
1058    including the terminating null byte.  If YYRESULT is null, do not
1059    copy anything; just return the number of bytes that would be
1060    copied.  As a special case, return 0 if an ordinary "syntax error"
1061    message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
1062    size calculation.  */
1063 static YYSIZE_T
1064 yysyntax_error (char *yyresult, int yystate, int yychar)
1065 {
1066   int yyn = yypact[yystate];
1067 
1068   if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
1069     return 0;
1070   else
1071     {
1072       int yytype = YYTRANSLATE (yychar);
1073       YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
1074       YYSIZE_T yysize = yysize0;
1075       YYSIZE_T yysize1;
1076       int yysize_overflow = 0;
1077       enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
1078       char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
1079       int yyx;
1080 
1081 # if 0
1082       /* This is so xgettext sees the translatable formats that are
1083 	 constructed on the fly.  */
1084       YY_("syntax error, unexpected %s");
1085       YY_("syntax error, unexpected %s, expecting %s");
1086       YY_("syntax error, unexpected %s, expecting %s or %s");
1087       YY_("syntax error, unexpected %s, expecting %s or %s or %s");
1088       YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
1089 # endif
1090       char *yyfmt;
1091       char const *yyf;
1092       static char const yyunexpected[] = "syntax error, unexpected %s";
1093       static char const yyexpecting[] = ", expecting %s";
1094       static char const yyor[] = " or %s";
1095       char yyformat[sizeof yyunexpected
1096 		    + sizeof yyexpecting - 1
1097 		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
1098 		       * (sizeof yyor - 1))];
1099       char const *yyprefix = yyexpecting;
1100 
1101       /* Start YYX at -YYN if negative to avoid negative indexes in
1102 	 YYCHECK.  */
1103       int yyxbegin = yyn < 0 ? -yyn : 0;
1104 
1105       /* Stay within bounds of both yycheck and yytname.  */
1106       int yychecklim = YYLAST - yyn + 1;
1107       int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
1108       int yycount = 1;
1109 
1110       yyarg[0] = yytname[yytype];
1111       yyfmt = yystpcpy (yyformat, yyunexpected);
1112 
1113       for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1114 	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1115 	  {
1116 	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
1117 	      {
1118 		yycount = 1;
1119 		yysize = yysize0;
1120 		yyformat[sizeof yyunexpected - 1] = '\0';
1121 		break;
1122 	      }
1123 	    yyarg[yycount++] = yytname[yyx];
1124 	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
1125 	    yysize_overflow |= (yysize1 < yysize);
1126 	    yysize = yysize1;
1127 	    yyfmt = yystpcpy (yyfmt, yyprefix);
1128 	    yyprefix = yyor;
1129 	  }
1130 
1131       yyf = YY_(yyformat);
1132       yysize1 = yysize + yystrlen (yyf);
1133       yysize_overflow |= (yysize1 < yysize);
1134       yysize = yysize1;
1135 
1136       if (yysize_overflow)
1137 	return YYSIZE_MAXIMUM;
1138 
1139       if (yyresult)
1140 	{
1141 	  /* Avoid sprintf, as that infringes on the user's name space.
1142 	     Don't have undefined behavior even if the translation
1143 	     produced a string with the wrong number of "%s"s.  */
1144 	  char *yyp = yyresult;
1145 	  int yyi = 0;
1146 	  while ((*yyp = *yyf) != '\0')
1147 	    {
1148 	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
1149 		{
1150 		  yyp += yytnamerr (yyp, yyarg[yyi++]);
1151 		  yyf += 2;
1152 		}
1153 	      else
1154 		{
1155 		  yyp++;
1156 		  yyf++;
1157 		}
1158 	    }
1159 	}
1160       return yysize;
1161     }
1162 }
1163 #endif /* YYERROR_VERBOSE */
1164 
1165 
1166 /*-----------------------------------------------.
1167 | Release the memory associated to this symbol.  |
1168 `-----------------------------------------------*/
1169 
1170 /*ARGSUSED*/
1171 #if (defined __STDC__ || defined __C99__FUNC__ \
1172      || defined __cplusplus || defined _MSC_VER)
1173 static void
1174 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
1175 #else
1176 static void
1177 yydestruct (yymsg, yytype, yyvaluep)
1178     const char *yymsg;
1179     int yytype;
1180     YYSTYPE *yyvaluep;
1181 #endif
1182 {
1183   YYUSE (yyvaluep);
1184 
1185   if (!yymsg)
1186     yymsg = "Deleting";
1187   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
1188 
1189   switch (yytype)
1190     {
1191 
1192       default:
1193 	break;
1194     }
1195 }
1196 
1197 
1198 /* Prevent warnings from -Wmissing-prototypes.  */
1199 
1200 #ifdef YYPARSE_PARAM
1201 #if defined __STDC__ || defined __cplusplus
1202 int yyparse (void *YYPARSE_PARAM);
1203 #else
1204 int yyparse ();
1205 #endif
1206 #else /* ! YYPARSE_PARAM */
1207 #if defined __STDC__ || defined __cplusplus
1208 int yyparse (void);
1209 #else
1210 int yyparse ();
1211 #endif
1212 #endif /* ! YYPARSE_PARAM */
1213 
1214 
1215 
1216 
1217 
1218 
1219 /*----------.
1220 | yyparse.  |
1221 `----------*/
1222 
1223 #ifdef YYPARSE_PARAM
1224 #if (defined __STDC__ || defined __C99__FUNC__ \
1225      || defined __cplusplus || defined _MSC_VER)
1226 int
1227 yyparse (void *YYPARSE_PARAM)
1228 #else
1229 int
1230 yyparse (YYPARSE_PARAM)
1231     void *YYPARSE_PARAM;
1232 #endif
1233 #else /* ! YYPARSE_PARAM */
1234 #if (defined __STDC__ || defined __C99__FUNC__ \
1235      || defined __cplusplus || defined _MSC_VER)
1236 int
1237 yyparse (void)
1238 #else
1239 int
1240 yyparse ()
1241 
1242 #endif
1243 #endif
1244 {
1245   /* The look-ahead symbol.  */
1246 int yychar;
1247 
1248 /* The semantic value of the look-ahead symbol.  */
1249 YYSTYPE yylval;
1250 
1251 /* Number of syntax errors so far.  */
1252 int yynerrs;
1253 
1254   int yystate;
1255   int yyn;
1256   int yyresult;
1257   /* Number of tokens to shift before error messages enabled.  */
1258   int yyerrstatus;
1259   /* Look-ahead token as an internal (translated) token number.  */
1260   int yytoken = 0;
1261 #if YYERROR_VERBOSE
1262   /* Buffer for error messages, and its allocated size.  */
1263   char yymsgbuf[128];
1264   char *yymsg = yymsgbuf;
1265   YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
1266 #endif
1267 
1268   /* Three stacks and their tools:
1269      `yyss': related to states,
1270      `yyvs': related to semantic values,
1271      `yyls': related to locations.
1272 
1273      Refer to the stacks thru separate pointers, to allow yyoverflow
1274      to reallocate them elsewhere.  */
1275 
1276   /* The state stack.  */
1277   yytype_int16 yyssa[YYINITDEPTH];
1278   yytype_int16 *yyss = yyssa;
1279   yytype_int16 *yyssp;
1280 
1281   /* The semantic value stack.  */
1282   YYSTYPE yyvsa[YYINITDEPTH];
1283   YYSTYPE *yyvs = yyvsa;
1284   YYSTYPE *yyvsp;
1285 
1286 
1287 
1288 #define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
1289 
1290   YYSIZE_T yystacksize = YYINITDEPTH;
1291 
1292   /* The variables used to return semantic value and location from the
1293      action routines.  */
1294   YYSTYPE yyval;
1295 
1296 
1297   /* The number of symbols on the RHS of the reduced rule.
1298      Keep to zero when no symbol should be popped.  */
1299   int yylen = 0;
1300 
1301   YYDPRINTF ((stderr, "Starting parse\n"));
1302 
1303   yystate = 0;
1304   yyerrstatus = 0;
1305   yynerrs = 0;
1306   yychar = YYEMPTY;		/* Cause a token to be read.  */
1307 
1308   /* Initialize stack pointers.
1309      Waste one element of value and location stack
1310      so that they stay on the same level as the state stack.
1311      The wasted elements are never initialized.  */
1312 
1313   yyssp = yyss;
1314   yyvsp = yyvs;
1315 
1316   goto yysetstate;
1317 
1318 /*------------------------------------------------------------.
1319 | yynewstate -- Push a new state, which is found in yystate.  |
1320 `------------------------------------------------------------*/
1321  yynewstate:
1322   /* In all cases, when you get here, the value and location stacks
1323      have just been pushed.  So pushing a state here evens the stacks.  */
1324   yyssp++;
1325 
1326  yysetstate:
1327   *yyssp = yystate;
1328 
1329   if (yyss + yystacksize - 1 <= yyssp)
1330     {
1331       /* Get the current used size of the three stacks, in elements.  */
1332       YYSIZE_T yysize = yyssp - yyss + 1;
1333 
1334 #ifdef yyoverflow
1335       {
1336 	/* Give user a chance to reallocate the stack.  Use copies of
1337 	   these so that the &'s don't force the real ones into
1338 	   memory.  */
1339 	YYSTYPE *yyvs1 = yyvs;
1340 	yytype_int16 *yyss1 = yyss;
1341 
1342 
1343 	/* Each stack pointer address is followed by the size of the
1344 	   data in use in that stack, in bytes.  This used to be a
1345 	   conditional around just the two extra args, but that might
1346 	   be undefined if yyoverflow is a macro.  */
1347 	yyoverflow (YY_("memory exhausted"),
1348 		    &yyss1, yysize * sizeof (*yyssp),
1349 		    &yyvs1, yysize * sizeof (*yyvsp),
1350 
1351 		    &yystacksize);
1352 
1353 	yyss = yyss1;
1354 	yyvs = yyvs1;
1355       }
1356 #else /* no yyoverflow */
1357 # ifndef YYSTACK_RELOCATE
1358       goto yyexhaustedlab;
1359 # else
1360       /* Extend the stack our own way.  */
1361       if (YYMAXDEPTH <= yystacksize)
1362 	goto yyexhaustedlab;
1363       yystacksize *= 2;
1364       if (YYMAXDEPTH < yystacksize)
1365 	yystacksize = YYMAXDEPTH;
1366 
1367       {
1368 	yytype_int16 *yyss1 = yyss;
1369 	union yyalloc *yyptr =
1370 	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
1371 	if (! yyptr)
1372 	  goto yyexhaustedlab;
1373 	YYSTACK_RELOCATE (yyss);
1374 	YYSTACK_RELOCATE (yyvs);
1375 
1376 #  undef YYSTACK_RELOCATE
1377 	if (yyss1 != yyssa)
1378 	  YYSTACK_FREE (yyss1);
1379       }
1380 # endif
1381 #endif /* no yyoverflow */
1382 
1383       yyssp = yyss + yysize - 1;
1384       yyvsp = yyvs + yysize - 1;
1385 
1386 
1387       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1388 		  (unsigned long int) yystacksize));
1389 
1390       if (yyss + yystacksize - 1 <= yyssp)
1391 	YYABORT;
1392     }
1393 
1394   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
1395 
1396   goto yybackup;
1397 
1398 /*-----------.
1399 | yybackup.  |
1400 `-----------*/
1401 yybackup:
1402 
1403   /* Do appropriate processing given the current state.  Read a
1404      look-ahead token if we need one and don't already have one.  */
1405 
1406   /* First try to decide what to do without reference to look-ahead token.  */
1407   yyn = yypact[yystate];
1408   if (yyn == YYPACT_NINF)
1409     goto yydefault;
1410 
1411   /* Not known => get a look-ahead token if don't already have one.  */
1412 
1413   /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
1414   if (yychar == YYEMPTY)
1415     {
1416       YYDPRINTF ((stderr, "Reading a token: "));
1417       yychar = YYLEX;
1418     }
1419 
1420   if (yychar <= YYEOF)
1421     {
1422       yychar = yytoken = YYEOF;
1423       YYDPRINTF ((stderr, "Now at end of input.\n"));
1424     }
1425   else
1426     {
1427       yytoken = YYTRANSLATE (yychar);
1428       YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
1429     }
1430 
1431   /* If the proper action on seeing token YYTOKEN is to reduce or to
1432      detect an error, take that action.  */
1433   yyn += yytoken;
1434   if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
1435     goto yydefault;
1436   yyn = yytable[yyn];
1437   if (yyn <= 0)
1438     {
1439       if (yyn == 0 || yyn == YYTABLE_NINF)
1440 	goto yyerrlab;
1441       yyn = -yyn;
1442       goto yyreduce;
1443     }
1444 
1445   if (yyn == YYFINAL)
1446     YYACCEPT;
1447 
1448   /* Count tokens shifted since error; after three, turn off error
1449      status.  */
1450   if (yyerrstatus)
1451     yyerrstatus--;
1452 
1453   /* Shift the look-ahead token.  */
1454   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
1455 
1456   /* Discard the shifted token unless it is eof.  */
1457   if (yychar != YYEOF)
1458     yychar = YYEMPTY;
1459 
1460   yystate = yyn;
1461   *++yyvsp = yylval;
1462 
1463   goto yynewstate;
1464 
1465 
1466 /*-----------------------------------------------------------.
1467 | yydefault -- do the default action for the current state.  |
1468 `-----------------------------------------------------------*/
1469 yydefault:
1470   yyn = yydefact[yystate];
1471   if (yyn == 0)
1472     goto yyerrlab;
1473   goto yyreduce;
1474 
1475 
1476 /*-----------------------------.
1477 | yyreduce -- Do a reduction.  |
1478 `-----------------------------*/
1479 yyreduce:
1480   /* yyn is the number of a rule to reduce with.  */
1481   yylen = yyr2[yyn];
1482 
1483   /* If YYLEN is nonzero, implement the default value of the action:
1484      `$$ = $1'.
1485 
1486      Otherwise, the following line sets YYVAL to garbage.
1487      This behavior is undocumented and Bison
1488      users should not rely upon it.  Assigning to YYVAL
1489      unconditionally makes the parser a bit smaller, and it avoids a
1490      GCC warning that YYVAL may be used uninitialized.  */
1491   yyval = yyvsp[1-yylen];
1492 
1493 
1494   YY_REDUCE_PRINT (yyn);
1495   switch (yyn)
1496     {
1497         case 2:
1498 #line 150 "OSUnserializeXML.y"
1499     { yyerror("unexpected end of buffer");
1500 				  YYERROR;
1501 				;}
1502     break;
1503 
1504   case 3:
1505 #line 153 "OSUnserializeXML.y"
1506     { STATE->parsedObject = (yyvsp[(1) - (1)])->object;
1507 				  (yyvsp[(1) - (1)])->object = 0;
1508 				  freeObject(STATE, (yyvsp[(1) - (1)]));
1509 				  YYACCEPT;
1510 				;}
1511     break;
1512 
1513   case 4:
1514 #line 158 "OSUnserializeXML.y"
1515     { yyerror("syntax error");
1516 				  YYERROR;
1517 				;}
1518     break;
1519 
1520   case 5:
1521 #line 163 "OSUnserializeXML.y"
1522     { (yyval) = buildDictionary(STATE, (yyvsp[(1) - (1)])); ;}
1523     break;
1524 
1525   case 6:
1526 #line 164 "OSUnserializeXML.y"
1527     { (yyval) = buildArray(STATE, (yyvsp[(1) - (1)])); ;}
1528     break;
1529 
1530   case 7:
1531 #line 165 "OSUnserializeXML.y"
1532     { (yyval) = buildSet(STATE, (yyvsp[(1) - (1)])); ;}
1533     break;
1534 
1535   case 8:
1536 #line 166 "OSUnserializeXML.y"
1537     { (yyval) = buildString(STATE, (yyvsp[(1) - (1)])); ;}
1538     break;
1539 
1540   case 9:
1541 #line 167 "OSUnserializeXML.y"
1542     { (yyval) = buildData(STATE, (yyvsp[(1) - (1)])); ;}
1543     break;
1544 
1545   case 10:
1546 #line 168 "OSUnserializeXML.y"
1547     { (yyval) = buildNumber(STATE, (yyvsp[(1) - (1)])); ;}
1548     break;
1549 
1550   case 11:
1551 #line 169 "OSUnserializeXML.y"
1552     { (yyval) = buildBoolean(STATE, (yyvsp[(1) - (1)])); ;}
1553     break;
1554 
1555   case 12:
1556 #line 170 "OSUnserializeXML.y"
1557     { (yyval) = retrieveObject(STATE, (yyvsp[(1) - (1)])->idref);
1558 				  if ((yyval)) {
1559 				    (yyval)->object->retain();
1560 				  } else {
1561 				    yyerror("forward reference detected");
1562 				    YYERROR;
1563 				  }
1564 				  freeObject(STATE, (yyvsp[(1) - (1)]));
1565 				;}
1566     break;
1567 
1568   case 13:
1569 #line 183 "OSUnserializeXML.y"
1570     { (yyval) = (yyvsp[(1) - (2)]);
1571 				  (yyval)->elements = NULL;
1572 				;}
1573     break;
1574 
1575   case 14:
1576 #line 186 "OSUnserializeXML.y"
1577     { (yyval) = (yyvsp[(1) - (3)]);
1578 				  (yyval)->elements = (yyvsp[(2) - (3)]);
1579 				;}
1580     break;
1581 
1582   case 17:
1583 #line 193 "OSUnserializeXML.y"
1584     { (yyval) = (yyvsp[(2) - (2)]);
1585 				  (yyval)->next = (yyvsp[(1) - (2)]);
1586 				;}
1587     break;
1588 
1589   case 18:
1590 #line 198 "OSUnserializeXML.y"
1591     { (yyval) = (yyvsp[(1) - (2)]);
1592 				  (yyval)->key = (OSString *)(yyval)->object;
1593 				  (yyval)->object = (yyvsp[(2) - (2)])->object;
1594 				  (yyval)->next = NULL;
1595 				  (yyvsp[(2) - (2)])->object = 0;
1596 				  freeObject(STATE, (yyvsp[(2) - (2)]));
1597 				;}
1598     break;
1599 
1600   case 19:
1601 #line 207 "OSUnserializeXML.y"
1602     { (yyval) = buildString(STATE, (yyvsp[(1) - (1)])); ;}
1603     break;
1604 
1605   case 20:
1606 #line 212 "OSUnserializeXML.y"
1607     { (yyval) = (yyvsp[(1) - (2)]);
1608 				  (yyval)->elements = NULL;
1609 				;}
1610     break;
1611 
1612   case 21:
1613 #line 215 "OSUnserializeXML.y"
1614     { (yyval) = (yyvsp[(1) - (3)]);
1615 				  (yyval)->elements = (yyvsp[(2) - (3)]);
1616 				;}
1617     break;
1618 
1619   case 23:
1620 #line 221 "OSUnserializeXML.y"
1621     { (yyval) = (yyvsp[(1) - (2)]);
1622 				  (yyval)->elements = NULL;
1623 				;}
1624     break;
1625 
1626   case 24:
1627 #line 224 "OSUnserializeXML.y"
1628     { (yyval) = (yyvsp[(1) - (3)]);
1629 				  (yyval)->elements = (yyvsp[(2) - (3)]);
1630 				;}
1631     break;
1632 
1633   case 26:
1634 #line 230 "OSUnserializeXML.y"
1635     { (yyval) = (yyvsp[(1) - (1)]);
1636 				  (yyval)->next = NULL;
1637 				;}
1638     break;
1639 
1640   case 27:
1641 #line 233 "OSUnserializeXML.y"
1642     { (yyval) = (yyvsp[(2) - (2)]);
1643 				  (yyval)->next = (yyvsp[(1) - (2)]);
1644 				;}
1645     break;
1646 
1647 
1648 /* Line 1267 of yacc.c.  */
1649 #line 1600 "OSUnserializeXML.tab.c"
1650       default: break;
1651     }
1652   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
1653 
1654   YYPOPSTACK (yylen);
1655   yylen = 0;
1656   YY_STACK_PRINT (yyss, yyssp);
1657 
1658   *++yyvsp = yyval;
1659 
1660 
1661   /* Now `shift' the result of the reduction.  Determine what state
1662      that goes to, based on the state we popped back to and the rule
1663      number reduced by.  */
1664 
1665   yyn = yyr1[yyn];
1666 
1667   yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
1668   if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1669     yystate = yytable[yystate];
1670   else
1671     yystate = yydefgoto[yyn - YYNTOKENS];
1672 
1673   goto yynewstate;
1674 
1675 
1676 /*------------------------------------.
1677 | yyerrlab -- here on detecting error |
1678 `------------------------------------*/
1679 yyerrlab:
1680   /* If not already recovering from an error, report this error.  */
1681   if (!yyerrstatus)
1682     {
1683       ++yynerrs;
1684 #if ! YYERROR_VERBOSE
1685       yyerror (YY_("syntax error"));
1686 #else
1687       {
1688 	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
1689 	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
1690 	  {
1691 	    YYSIZE_T yyalloc = 2 * yysize;
1692 	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
1693 	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
1694 	    if (yymsg != yymsgbuf)
1695 	      YYSTACK_FREE (yymsg);
1696 	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
1697 	    if (yymsg)
1698 	      yymsg_alloc = yyalloc;
1699 	    else
1700 	      {
1701 		yymsg = yymsgbuf;
1702 		yymsg_alloc = sizeof yymsgbuf;
1703 	      }
1704 	  }
1705 
1706 	if (0 < yysize && yysize <= yymsg_alloc)
1707 	  {
1708 	    (void) yysyntax_error (yymsg, yystate, yychar);
1709 	    yyerror (yymsg);
1710 	  }
1711 	else
1712 	  {
1713 	    yyerror (YY_("syntax error"));
1714 	    if (yysize != 0)
1715 	      goto yyexhaustedlab;
1716 	  }
1717       }
1718 #endif
1719     }
1720 
1721 
1722 
1723   if (yyerrstatus == 3)
1724     {
1725       /* If just tried and failed to reuse look-ahead token after an
1726 	 error, discard it.  */
1727 
1728       if (yychar <= YYEOF)
1729 	{
1730 	  /* Return failure if at end of input.  */
1731 	  if (yychar == YYEOF)
1732 	    YYABORT;
1733 	}
1734       else
1735 	{
1736 	  yydestruct ("Error: discarding",
1737 		      yytoken, &yylval);
1738 	  yychar = YYEMPTY;
1739 	}
1740     }
1741 
1742   /* Else will try to reuse look-ahead token after shifting the error
1743      token.  */
1744   goto yyerrlab1;
1745 
1746 
1747 /*---------------------------------------------------.
1748 | yyerrorlab -- error raised explicitly by YYERROR.  |
1749 `---------------------------------------------------*/
1750 yyerrorlab:
1751 
1752   /* Pacify compilers like GCC when the user code never invokes
1753      YYERROR and the label yyerrorlab therefore never appears in user
1754      code.  */
1755   if (/*CONSTCOND*/ 0)
1756      goto yyerrorlab;
1757 
1758   /* Do not reclaim the symbols of the rule which action triggered
1759      this YYERROR.  */
1760   YYPOPSTACK (yylen);
1761   yylen = 0;
1762   YY_STACK_PRINT (yyss, yyssp);
1763   yystate = *yyssp;
1764   goto yyerrlab1;
1765 
1766 
1767 /*-------------------------------------------------------------.
1768 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
1769 `-------------------------------------------------------------*/
1770 yyerrlab1:
1771   yyerrstatus = 3;	/* Each real token shifted decrements this.  */
1772 
1773   for (;;)
1774     {
1775       yyn = yypact[yystate];
1776       if (yyn != YYPACT_NINF)
1777 	{
1778 	  yyn += YYTERROR;
1779 	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
1780 	    {
1781 	      yyn = yytable[yyn];
1782 	      if (0 < yyn)
1783 		break;
1784 	    }
1785 	}
1786 
1787       /* Pop the current state because it cannot handle the error token.  */
1788       if (yyssp == yyss)
1789 	YYABORT;
1790 
1791 
1792       yydestruct ("Error: popping",
1793 		  yystos[yystate], yyvsp);
1794       YYPOPSTACK (1);
1795       yystate = *yyssp;
1796       YY_STACK_PRINT (yyss, yyssp);
1797     }
1798 
1799   if (yyn == YYFINAL)
1800     YYACCEPT;
1801 
1802   *++yyvsp = yylval;
1803 
1804 
1805   /* Shift the error token.  */
1806   YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
1807 
1808   yystate = yyn;
1809   goto yynewstate;
1810 
1811 
1812 /*-------------------------------------.
1813 | yyacceptlab -- YYACCEPT comes here.  |
1814 `-------------------------------------*/
1815 yyacceptlab:
1816   yyresult = 0;
1817   goto yyreturn;
1818 
1819 /*-----------------------------------.
1820 | yyabortlab -- YYABORT comes here.  |
1821 `-----------------------------------*/
1822 yyabortlab:
1823   yyresult = 1;
1824   goto yyreturn;
1825 
1826 #ifndef yyoverflow
1827 /*-------------------------------------------------.
1828 | yyexhaustedlab -- memory exhaustion comes here.  |
1829 `-------------------------------------------------*/
1830 yyexhaustedlab:
1831   yyerror (YY_("memory exhausted"));
1832   yyresult = 2;
1833   /* Fall through.  */
1834 #endif
1835 
1836 yyreturn:
1837   if (yychar != YYEOF && yychar != YYEMPTY)
1838      yydestruct ("Cleanup: discarding lookahead",
1839 		 yytoken, &yylval);
1840   /* Do not reclaim the symbols of the rule which action triggered
1841      this YYABORT or YYACCEPT.  */
1842   YYPOPSTACK (yylen);
1843   YY_STACK_PRINT (yyss, yyssp);
1844   while (yyssp != yyss)
1845     {
1846       yydestruct ("Cleanup: popping",
1847 		  yystos[*yyssp], yyvsp);
1848       YYPOPSTACK (1);
1849     }
1850 #ifndef yyoverflow
1851   if (yyss != yyssa)
1852     YYSTACK_FREE (yyss);
1853 #endif
1854 #if YYERROR_VERBOSE
1855   if (yymsg != yymsgbuf)
1856     YYSTACK_FREE (yymsg);
1857 #endif
1858   /* Make sure YYID is used.  */
1859   return YYID (yyresult);
1860 }
1861 
1862 
1863 #line 255 "OSUnserializeXML.y"
1864 
1865 
1866 int
1867 OSUnserializeerror(parser_state_t * state, char *s)  /* Called by yyparse on errors */
1868 {
1869     char tempString[128];
1870 
1871     if (state->errorString) {
1872 	snprintf(tempString, 128, "OSUnserializeXML: %s near line %d\n", s, state->lineNumber);
1873 	*(state->errorString) = OSString::withCString(tempString);
1874     }
1875 
1876     return 0;
1877 }
1878 
1879 #define TAG_MAX_LENGTH		32
1880 #define TAG_MAX_ATTRIBUTES	32
1881 #define TAG_BAD			0
1882 #define TAG_START		1
1883 #define TAG_END			2
1884 #define TAG_EMPTY		3
1885 #define TAG_COMMENT		4
1886 
1887 #define currentChar()	(state->parseBuffer[state->parseBufferIndex])
1888 #define nextChar()	(state->parseBuffer[++state->parseBufferIndex])
1889 #define prevChar()	(state->parseBuffer[state->parseBufferIndex - 1])
1890 
1891 #define isSpace(c)	((c) == ' ' || (c) == '\t')
1892 #define isAlpha(c)	(((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
1893 #define isDigit(c)	((c) >= '0' && (c) <= '9')
1894 #define isAlphaDigit(c)	((c) >= 'a' && (c) <= 'f')
1895 #define isHexDigit(c)	(isDigit(c) || isAlphaDigit(c))
1896 #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-'))
1897 
1898 static int
1899 getTag(parser_state_t *state,
1900        char tag[TAG_MAX_LENGTH],
1901        int *attributeCount,
1902        char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH],
1903        char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] )
1904 {
1905 	int length = 0;
1906 	int c = currentChar();
1907 	int tagType = TAG_START;
1908 
1909 	*attributeCount = 0;
1910 
1911 	if (c != '<') return TAG_BAD;
1912         c = nextChar();		// skip '<'
1913 
1914         if (c == '?' || c == '!') {
1915                 while ((c = nextChar()) != 0) {
1916                         if (c == '\n') state->lineNumber++;
1917                         if (c == '>') {
1918                                 (void)nextChar();
1919                                 return TAG_COMMENT;
1920                         }
1921                 }
1922         }
1923 
1924 	if (c == '/') {
1925 		c = nextChar();		// skip '/'
1926 		tagType = TAG_END;
1927 	}
1928         if (!isAlpha(c)) return TAG_BAD;
1929 
1930 	/* find end of tag while copying it */
1931 	while (isAlphaNumeric(c)) {
1932 		tag[length++] = c;
1933 		c = nextChar();
1934 		if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1935 	}
1936 
1937 	tag[length] = 0;
1938 
1939 //	printf("tag %s, type %d\n", tag, tagType);
1940 
1941 	// look for attributes of the form attribute = "value" ...
1942 	while ((c != '>') && (c != '/')) {
1943 		while (isSpace(c)) c = nextChar();
1944 
1945 		length = 0;
1946 		while (isAlphaNumeric(c)) {
1947 			attributes[*attributeCount][length++] = c;
1948 			if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1949 			c = nextChar();
1950 		}
1951 		attributes[*attributeCount][length] = 0;
1952 
1953 		while (isSpace(c)) c = nextChar();
1954 
1955 		if (c != '=') return TAG_BAD;
1956 		c = nextChar();
1957 
1958 		while (isSpace(c)) c = nextChar();
1959 
1960 		if (c != '"') return TAG_BAD;
1961 		c = nextChar();
1962 		length = 0;
1963 		while (c != '"') {
1964 			values[*attributeCount][length++] = c;
1965 			if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1966 			c = nextChar();
1967 		}
1968 		values[*attributeCount][length] = 0;
1969 
1970 		c = nextChar(); // skip closing quote
1971 
1972 //		printf("	attribute '%s' = '%s', nextchar = '%c'\n",
1973 //		       attributes[*attributeCount], values[*attributeCount], c);
1974 
1975 		(*attributeCount)++;
1976 		if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD;
1977 	}
1978 
1979 	if (c == '/') {
1980 		c = nextChar();		// skip '/'
1981 		tagType = TAG_EMPTY;
1982 	}
1983 	if (c != '>') return TAG_BAD;
1984 	c = nextChar();		// skip '>'
1985 
1986 	return tagType;
1987 }
1988 
1989 static char *
1990 getString(parser_state_t *state)
1991 {
1992 	int c = currentChar();
1993 	int start, length, i, j;
1994 	char * tempString;
1995 
1996 	start = state->parseBufferIndex;
1997 	/* find end of string */
1998 
1999 	while (c != 0) {
2000 		if (c == '\n') state->lineNumber++;
2001 		if (c == '<') {
2002 			break;
2003 		}
2004 		c = nextChar();
2005 	}
2006 
2007 	if (c != '<') return 0;
2008 
2009 	length = state->parseBufferIndex - start;
2010 
2011 	/* copy to null terminated buffer */
2012 	tempString = (char *)malloc(length + 1);
2013 	if (tempString == 0) {
2014 		printf("OSUnserializeXML: can't alloc temp memory\n");
2015 		goto error;
2016 	}
2017 
2018 	// copy out string in tempString
2019 	// "&amp;" -> '&', "&lt;" -> '<', "&gt;" -> '>'
2020 
2021 	i = j = 0;
2022 	while (i < length) {
2023 		c = state->parseBuffer[start + i++];
2024 		if (c != '&') {
2025 			tempString[j++] = c;
2026 		} else {
2027 			if ((i+3) > length) goto error;
2028 			c = state->parseBuffer[start + i++];
2029 			if (c == 'l') {
2030 				if (state->parseBuffer[start + i++] != 't') goto error;
2031 				if (state->parseBuffer[start + i++] != ';') goto error;
2032 				tempString[j++] = '<';
2033 				continue;
2034 			}
2035 			if (c == 'g') {
2036 				if (state->parseBuffer[start + i++] != 't') goto error;
2037 				if (state->parseBuffer[start + i++] != ';') goto error;
2038 				tempString[j++] = '>';
2039 				continue;
2040 			}
2041 			if ((i+3) > length) goto error;
2042 			if (c == 'a') {
2043 				if (state->parseBuffer[start + i++] != 'm') goto error;
2044 				if (state->parseBuffer[start + i++] != 'p') goto error;
2045 				if (state->parseBuffer[start + i++] != ';') goto error;
2046 				tempString[j++] = '&';
2047 				continue;
2048 			}
2049 			goto error;
2050 		}
2051 	}
2052 	tempString[j] = 0;
2053 
2054 //	printf("string %s\n", tempString);
2055 
2056 	return tempString;
2057 
2058 error:
2059 	if (tempString) free(tempString);
2060 	return 0;
2061 }
2062 
2063 static long long
2064 getNumber(parser_state_t *state)
2065 {
2066 	unsigned long long n = 0;
2067 	int base = 10;
2068 	bool negate = false;
2069 	int c = currentChar();
2070 
2071 	if (c == '0') {
2072 		c = nextChar();
2073 		if (c == 'x') {
2074 			base = 16;
2075 			c = nextChar();
2076 		}
2077 	}
2078 	if (base == 10) {
2079 		if (c == '-') {
2080 			negate = true;
2081 			c = nextChar();
2082 		}
2083 		while(isDigit(c)) {
2084 			n = (n * base + c - '0');
2085 			c = nextChar();
2086 		}
2087 		if (negate) {
2088 			n = (unsigned long long)((long long)n * (long long)-1);
2089 		}
2090 	} else {
2091 		while(isHexDigit(c)) {
2092 			if (isDigit(c)) {
2093 				n = (n * base + c - '0');
2094 			} else {
2095 				n = (n * base + 0xa + c - 'a');
2096 			}
2097 			c = nextChar();
2098 		}
2099 	}
2100 //	printf("number 0x%x\n", (unsigned long)n);
2101 	return n;
2102 }
2103 
2104 // taken from CFXMLParsing/CFPropertyList.c
2105 
2106 static const signed char __CFPLDataDecodeTable[128] = {
2107     /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
2108     /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
2109     /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
2110     /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
2111     /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
2112     /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
2113     /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
2114     /* '8' */ 60, 61, -1, -1, -1,  0, -1, -1,
2115     /* '@' */ -1,  0,  1,  2,  3,  4,  5,  6,
2116     /* 'H' */  7,  8,  9, 10, 11, 12, 13, 14,
2117     /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
2118     /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
2119     /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
2120     /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
2121     /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
2122     /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
2123 };
2124 
2125 #define DATA_ALLOC_SIZE 4096
2126 
2127 static void *
2128 getCFEncodedData(parser_state_t *state, unsigned int *size)
2129 {
2130     int numeq = 0, acc = 0, cntr = 0;
2131     int tmpbufpos = 0, tmpbuflen = 0;
2132     unsigned char *tmpbuf = (unsigned char *)malloc(DATA_ALLOC_SIZE);
2133 
2134     int c = currentChar();
2135     *size = 0;
2136 
2137     while (c != '<') {
2138         c &= 0x7f;
2139 	if (c == 0) {
2140 		free(tmpbuf);
2141 		return 0;
2142 	}
2143 	if (c == '=') numeq++; else numeq = 0;
2144 	if (c == '\n') state->lineNumber++;
2145         if (__CFPLDataDecodeTable[c] < 0) {
2146 	    c = nextChar();
2147             continue;
2148 	}
2149         cntr++;
2150         acc <<= 6;
2151         acc += __CFPLDataDecodeTable[c];
2152         if (0 == (cntr & 0x3)) {
2153             if (tmpbuflen <= tmpbufpos + 2) {
2154                 tmpbuflen += DATA_ALLOC_SIZE;
2155 		tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen);
2156             }
2157             tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
2158             if (numeq < 2)
2159                 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
2160             if (numeq < 1)
2161                 tmpbuf[tmpbufpos++] = acc & 0xff;
2162         }
2163 	c = nextChar();
2164     }
2165     *size = tmpbufpos;
2166     if (*size == 0) {
2167 	free(tmpbuf);
2168 	return 0;
2169     }
2170     return tmpbuf;
2171 }
2172 
2173 static void *
2174 getHexData(parser_state_t *state, unsigned int *size)
2175 {
2176     int c;
2177     unsigned char *d, *start, *lastStart;
2178 
2179     start = lastStart = d = (unsigned char *)malloc(DATA_ALLOC_SIZE);
2180     c = currentChar();
2181 
2182     while (c != '<') {
2183 
2184 	if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
2185 	if (c == '\n') {
2186 	    state->lineNumber++;
2187 	    c = nextChar();
2188 	    continue;
2189 	}
2190 
2191 	// get high nibble
2192 	if (isDigit(c)) {
2193 	    *d = (c - '0') << 4;
2194 	} else if (isAlphaDigit(c)) {
2195 	    *d =  (0xa + (c - 'a')) << 4;
2196 	} else {
2197 	    goto error;
2198 	}
2199 
2200 	// get low nibble
2201 	c = nextChar();
2202 	if (isDigit(c)) {
2203 	    *d |= c - '0';
2204 	} else if (isAlphaDigit(c)) {
2205 	    *d |= 0xa + (c - 'a');
2206 	} else {
2207 	    goto error;
2208 	}
2209 
2210 	d++;
2211 	if ((d - lastStart) >= DATA_ALLOC_SIZE) {
2212 	    int oldsize = d - start;
2213 	    start = (unsigned char *)realloc(start, oldsize + DATA_ALLOC_SIZE);
2214 	    d = lastStart = start + oldsize;
2215 	}
2216 	c = nextChar();
2217     }
2218 
2219     *size = d - start;
2220     return start;
2221 
2222  error:
2223 
2224     *size = 0;
2225     free(start);
2226     return 0;
2227 }
2228 
2229 static int
2230 yylex(YYSTYPE *lvalp, parser_state_t *state)
2231 {
2232 	int c, i;
2233 	int tagType;
2234 	char tag[TAG_MAX_LENGTH];
2235 	int attributeCount;
2236 	char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
2237 	char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
2238 	object_t *object;
2239 
2240  top:
2241 	c = currentChar();
2242 
2243 	/* skip white space  */
2244 	if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
2245 
2246 	/* keep track of line number, don't return \n's */
2247 	if (c == '\n') {
2248 		STATE->lineNumber++;
2249 		(void)nextChar();
2250 		goto top;
2251 	}
2252 
2253 	// end of the buffer?
2254 	if (!c)	return 0;
2255 
2256 	tagType = getTag(STATE, tag, &attributeCount, attributes, values);
2257 	if (tagType == TAG_BAD) return SYNTAX_ERROR;
2258 	if (tagType == TAG_COMMENT) goto top;
2259 
2260 	// handle allocation and check for "ID" and "IDREF" tags up front
2261 	*lvalp = object = newObject(STATE);
2262 	object->idref = -1;
2263 	for (i=0; i < attributeCount; i++) {
2264 	    if (attributes[i][0] == 'I' && attributes[i][1] == 'D') {
2265 		// check for idref's, note: we ignore the tag, for
2266 		// this to work correctly, all idrefs must be unique
2267 		// across the whole serialization
2268 		if (attributes[i][2] == 'R' && attributes[i][3] == 'E' &&
2269 		    attributes[i][4] == 'F' && !attributes[i][5]) {
2270 		    if (tagType != TAG_EMPTY) return SYNTAX_ERROR;
2271 		    object->idref = strtol(values[i], NULL, 0);
2272 		    return IDREF;
2273 		}
2274 		// check for id's
2275 		if (!attributes[i][2]) {
2276 		    object->idref = strtol(values[i], NULL, 0);
2277 		} else {
2278 		    return SYNTAX_ERROR;
2279 		}
2280 	    }
2281 	}
2282 
2283 	switch (*tag) {
2284 	case 'a':
2285 		if (!strcmp(tag, "array")) {
2286 			if (tagType == TAG_EMPTY) {
2287 				object->elements = NULL;
2288 				return ARRAY;
2289 			}
2290 			return (tagType == TAG_START) ? '(' : ')';
2291 		}
2292 		break;
2293 	case 'd':
2294 		if (!strcmp(tag, "dict")) {
2295 			if (tagType == TAG_EMPTY) {
2296 				object->elements = NULL;
2297 				return DICTIONARY;
2298 			}
2299 			return (tagType == TAG_START) ? '{' : '}';
2300 		}
2301 		if (!strcmp(tag, "data")) {
2302 			unsigned int size;
2303 			if (tagType == TAG_EMPTY) {
2304 				object->data = NULL;
2305 				object->size = 0;
2306 				return DATA;
2307 			}
2308 
2309 			bool isHexFormat = false;
2310 			for (i=0; i < attributeCount; i++) {
2311 				if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) {
2312 					isHexFormat = true;
2313 					break;
2314 				}
2315 			}
2316 			// CF encoded is the default form
2317 			if (isHexFormat) {
2318 			    object->data = getHexData(STATE, &size);
2319 			} else {
2320 			    object->data = getCFEncodedData(STATE, &size);
2321 			}
2322 			object->size = size;
2323 			if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) {
2324 				return SYNTAX_ERROR;
2325 			}
2326 			return DATA;
2327 		}
2328 		break;
2329 	case 'f':
2330 		if (!strcmp(tag, "false")) {
2331 			if (tagType == TAG_EMPTY) {
2332 				object->number = 0;
2333 				return BOOLEAN;
2334 			}
2335 		}
2336 		break;
2337 	case 'i':
2338 		if (!strcmp(tag, "integer")) {
2339 			object->size = 64;	// default
2340 			for (i=0; i < attributeCount; i++) {
2341 				if (!strcmp(attributes[i], "size")) {
2342 					object->size = strtoul(values[i], NULL, 0);
2343 				}
2344 			}
2345 			if (tagType == TAG_EMPTY) {
2346 				object->number = 0;
2347 				return NUMBER;
2348 			}
2349 			object->number = getNumber(STATE);
2350 			if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) {
2351 				return SYNTAX_ERROR;
2352 			}
2353 			return NUMBER;
2354 		}
2355 		break;
2356 	case 'k':
2357 		if (!strcmp(tag, "key")) {
2358 			if (tagType == TAG_EMPTY) return SYNTAX_ERROR;
2359 			object->string = getString(STATE);
2360 			if (!object->string) {
2361 				return SYNTAX_ERROR;
2362 			}
2363 			if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
2364 			   || strcmp(tag, "key")) {
2365 				return SYNTAX_ERROR;
2366 			}
2367 			return KEY;
2368 		}
2369 		break;
2370 	case 'p':
2371 		if (!strcmp(tag, "plist")) {
2372 			freeObject(STATE, object);
2373 			goto top;
2374 		}
2375 		break;
2376 	case 's':
2377 		if (!strcmp(tag, "string")) {
2378 			if (tagType == TAG_EMPTY) {
2379 			    	object->string = (char *)malloc(1);
2380 			    	object->string[0] = 0;
2381 				return STRING;
2382 			}
2383 			object->string = getString(STATE);
2384 			if (!object->string) {
2385 				return SYNTAX_ERROR;
2386 			}
2387 			if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
2388 			   || strcmp(tag, "string")) {
2389 				return SYNTAX_ERROR;
2390 			}
2391 			return STRING;
2392 		}
2393 		if (!strcmp(tag, "set")) {
2394 			if (tagType == TAG_EMPTY) {
2395 				object->elements = NULL;
2396 				return SET;;
2397 			}
2398 			if (tagType == TAG_START) {
2399 				return '[';
2400 			} else {
2401 				return ']';
2402 			}
2403 		}
2404 		break;
2405 	case 't':
2406 		if (!strcmp(tag, "true")) {
2407 			if (tagType == TAG_EMPTY) {
2408 				object->number = 1;
2409 				return BOOLEAN;
2410 			}
2411 		}
2412 		break;
2413 	}
2414 
2415 	return SYNTAX_ERROR;
2416 }
2417 
2418 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2419 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2420 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2421 
2422 // "java" like allocation, if this code hits a syntax error in the
2423 // the middle of the parsed string we just bail with pointers hanging
2424 // all over place, this code helps keeps it all together
2425 
2426 //static int object_count = 0;
2427 
2428 object_t *
2429 newObject(parser_state_t *state)
2430 {
2431 	object_t *o;
2432 
2433 	if (state->freeObjects) {
2434 		o = state->freeObjects;
2435 		state->freeObjects = state->freeObjects->next;
2436 	} else {
2437 		o = (object_t *)malloc(sizeof(object_t));
2438 //		object_count++;
2439 		bzero(o, sizeof(object_t));
2440 		o->free = state->objects;
2441 		state->objects = o;
2442 	}
2443 
2444 	return o;
2445 }
2446 
2447 void
2448 freeObject(parser_state_t * state, object_t *o)
2449 {
2450 	o->next = state->freeObjects;
2451 	state->freeObjects = o;
2452 }
2453 
2454 void
2455 cleanupObjects(parser_state_t *state)
2456 {
2457 	object_t *t, *o = state->objects;
2458 
2459 	while (o) {
2460 		if (o->object) {
2461 //			printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object);
2462 			o->object->release();
2463 		}
2464 		if (o->data) {
2465 //			printf("OSUnserializeXML: freeing   object o=%x data=%x\n", (int)o, (int)o->data);
2466 			free(o->data);
2467 		}
2468 		if (o->key) {
2469 //			printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key);
2470 			o->key->release();
2471 		}
2472 		if (o->string) {
2473 //			printf("OSUnserializeXML: freeing   object o=%x string=%x\n", (int)o, (int)o->string);
2474 			free(o->string);
2475 		}
2476 
2477 		t = o;
2478 		o = o->free;
2479 		free(t);
2480 //		object_count--;
2481 	}
2482 //	printf("object_count = %d\n", object_count);
2483 }
2484 
2485 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2486 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2487 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2488 
2489 static void
2490 rememberObject(parser_state_t *state, int tag, OSObject *o)
2491 {
2492 	char key[16];
2493 	snprintf(key, 16, "%u", tag);
2494 
2495 //	printf("remember key %s\n", key);
2496 
2497 	state->tags->setObject(key, o);
2498 }
2499 
2500 static object_t *
2501 retrieveObject(parser_state_t *state, int tag)
2502 {
2503 	OSObject *ref;
2504 	object_t *o;
2505 	char key[16];
2506 	snprintf(key, 16, "%u", tag);
2507 
2508 //	printf("retrieve key '%s'\n", key);
2509 
2510 	ref = state->tags->getObject(key);
2511 	if (!ref) return 0;
2512 
2513 	o = newObject(state);
2514 	o->object = ref;
2515 	return o;
2516 }
2517 
2518 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2519 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2520 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2521 
2522 object_t *
2523 buildDictionary(parser_state_t *state, object_t * header)
2524 {
2525 	object_t *o, *t;
2526 	int count = 0;
2527 	OSDictionary *dict;
2528 
2529 	// get count and reverse order
2530 	o = header->elements;
2531 	header->elements = 0;
2532 	while (o) {
2533 		count++;
2534 		t = o;
2535 		o = o->next;
2536 
2537 		t->next = header->elements;
2538 		header->elements = t;
2539 	}
2540 
2541 	dict = OSDictionary::withCapacity(count);
2542 	if (header->idref >= 0) rememberObject(state, header->idref, dict);
2543 
2544 	o = header->elements;
2545 	while (o) {
2546 		dict->setObject(o->key, o->object);
2547 
2548 		o->key->release();
2549 		o->object->release();
2550 		o->key = 0;
2551 		o->object = 0;
2552 
2553 		t = o;
2554 		o = o->next;
2555 		freeObject(state, t);
2556 	}
2557 	o = header;
2558 	o->object = dict;
2559 	return o;
2560 };
2561 
2562 object_t *
2563 buildArray(parser_state_t *state, object_t * header)
2564 {
2565 	object_t *o, *t;
2566 	int count = 0;
2567 	OSArray *array;
2568 
2569 	// get count and reverse order
2570 	o = header->elements;
2571 	header->elements = 0;
2572 	while (o) {
2573 		count++;
2574 		t = o;
2575 		o = o->next;
2576 
2577 		t->next = header->elements;
2578 		header->elements = t;
2579 	}
2580 
2581 	array = OSArray::withCapacity(count);
2582 	if (header->idref >= 0) rememberObject(state, header->idref, array);
2583 
2584 	o = header->elements;
2585 	while (o) {
2586 		array->setObject(o->object);
2587 
2588 		o->object->release();
2589 		o->object = 0;
2590 
2591 		t = o;
2592 		o = o->next;
2593 		freeObject(state, t);
2594 	}
2595 	o = header;
2596 	o->object = array;
2597 	return o;
2598 };
2599 
2600 object_t *
2601 buildSet(parser_state_t *state, object_t *header)
2602 {
2603 	object_t *o = buildArray(state, header);
2604 
2605 	OSArray *array = (OSArray *)o->object;
2606 	OSSet *set = OSSet::withArray(array, array->getCapacity());
2607 
2608 	// write over the reference created in buildArray
2609 	if (header->idref >= 0) rememberObject(state, header->idref, set);
2610 
2611 	array->release();
2612 	o->object = set;
2613 	return o;
2614 };
2615 
2616 object_t *
2617 buildString(parser_state_t *state, object_t *o)
2618 {
2619 	OSString *string;
2620 
2621 	string = OSString::withCString(o->string);
2622 	if (o->idref >= 0) rememberObject(state, o->idref, string);
2623 
2624 	free(o->string);
2625 	o->string = 0;
2626 	o->object = string;
2627 
2628 	return o;
2629 };
2630 
2631 object_t *
2632 buildData(parser_state_t *state, object_t *o)
2633 {
2634 	OSData *data;
2635 
2636 	if (o->size) {
2637 		data = OSData::withBytes(o->data, o->size);
2638 	} else {
2639 		data = OSData::withCapacity(0);
2640 	}
2641 	if (o->idref >= 0) rememberObject(state, o->idref, data);
2642 
2643 	if (o->size) free(o->data);
2644 	o->data = 0;
2645 	o->object = data;
2646 	return o;
2647 };
2648 
2649 object_t *
2650 buildNumber(parser_state_t *state, object_t *o)
2651 {
2652 	OSNumber *number = OSNumber::withNumber(o->number, o->size);
2653 
2654 	if (o->idref >= 0) rememberObject(state, o->idref, number);
2655 
2656 	o->object = number;
2657 	return o;
2658 };
2659 
2660 object_t *
2661 buildBoolean(parser_state_t *state, object_t *o)
2662 {
2663 	o->object = ((o->number == 0) ? kOSBooleanFalse : kOSBooleanTrue);
2664 	o->object->retain();
2665 	return o;
2666 };
2667 
2668 OSObject*
2669 OSUnserializeXML(const char *buffer, OSString **errorString)
2670 {
2671 	OSObject *object;
2672 	parser_state_t *state = (parser_state_t *)malloc(sizeof(parser_state_t));
2673 
2674 	if ((!state) || (!buffer)) return 0;
2675 
2676 	// just in case
2677 	if (errorString) *errorString = NULL;
2678 
2679 	state->parseBuffer = buffer;
2680 	state->parseBufferIndex = 0;
2681 	state->lineNumber = 1;
2682 	state->objects = 0;
2683 	state->freeObjects = 0;
2684 	state->tags = OSDictionary::withCapacity(128);
2685 	state->errorString = errorString;
2686 	state->parsedObject = 0;
2687 
2688 	(void)yyparse((void *)state);
2689 
2690 	object = state->parsedObject;
2691 
2692 	cleanupObjects(state);
2693 	state->tags->release();
2694 	free(state);
2695 
2696 	return object;
2697 }
2698 
2699 
2700 //
2701 //
2702 //
2703 //
2704 //
2705 //		 DO NOT EDIT OSUnserializeXML.cpp!
2706 //
2707 //			this means you!
2708 //
2709 //
2710 //
2711 //
2712 //
2713 
2714