1 /*
2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_LICENSE_HEADER_START@
5  *
6  * The contents of this file constitute Original Code as defined in and
7  * are subject to the Apple Public Source License Version 1.1 (the
8  * "License").  You may not use this file except in compliance with the
9  * License.  Please obtain a copy of the License at
10  * http://www.apple.com/publicsource and read it before using this file.
11  *
12  * This Original Code and all software distributed under the License are
13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17  * License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * @APPLE_LICENSE_HEADER_END@
21  */
22 
23 /*  OSUnserializeXML.y created by rsulack on Tue Oct 12 1999 */
24 
25 // 		XML parser for unserializing OSContainer objects
26 //
27 // to build :
28 //	bison -p OSUnserializeXML OSUnserializeXML.y
29 //	head -50 OSUnserializeXML.y > OSUnserializeXML.cpp
30 //	sed -e "s/stdio.h/stddef.h/" < OSUnserializeXML.tab.c >> OSUnserializeXML.cpp
31 //
32 //	when changing code check in both OSUnserializeXML.y and OSUnserializeXML.cpp
33 //
34 //
35 //
36 //
37 //
38 //
39 //
40 //		 DO NOT EDIT OSUnserializeXML.cpp!
41 //
42 //			this means you!
43 //
44 //
45 //
46 //
47 //
48 //
49 //
50 
51 
52 /*  A Bison parser, made from OSUnserializeXML.y
53     by GNU Bison version 1.28  */
54 
55 #define YYBISON 1  /* Identify Bison output.  */
56 
57 #define yyparse OSUnserializeXMLparse
58 #define yylex OSUnserializeXMLlex
59 #define yyerror OSUnserializeXMLerror
60 #define yylval OSUnserializeXMLlval
61 #define yychar OSUnserializeXMLchar
62 #define yydebug OSUnserializeXMLdebug
63 #define yynerrs OSUnserializeXMLnerrs
64 #define	ARRAY	257
65 #define	BOOLEAN	258
66 #define	DATA	259
67 #define	DICTIONARY	260
68 #define	IDREF	261
69 #define	KEY	262
70 #define	NUMBER	263
71 #define	SET	264
72 #define	STRING	265
73 #define	SYNTAX_ERROR	266
74 
75 #line 52 "OSUnserializeXML.y"
76 
77 #include <string.h>
78 #include <libkern/c++/OSMetaClass.h>
79 #include <libkern/c++/OSContainers.h>
80 #include <libkern/c++/OSLib.h>
81 
82 typedef	struct object {
83 	struct object	*next;
84 	struct object	*free;
85 	struct object	*elements;
86 	OSObject	*object;
87 	const OSSymbol	*key;		// for dictionary
88 	int		size;
89 	void		*data;		// for data
90 	char		*string;	// for string & symbol
91 	long long 	number;		// for number
92 	int		idref;
93 } object_t;
94 
95 static int yyparse();
96 static int yyerror(char *s);
97 static int yylex();
98 
99 static object_t * newObject();
100 static void freeObject(object_t *o);
101 
102 static object_t *buildOSDictionary(object_t *);
103 static object_t *buildOSArray(object_t *);
104 static object_t *buildOSSet(object_t *);
105 static object_t *buildOSString(object_t *);
106 static object_t *buildKey(object_t *);
107 static object_t *buildOSData(object_t *);
108 static object_t *buildOSNumber(object_t *);
109 static object_t *buildOSBoolean(object_t *o);
110 
111 static void rememberObject(int, OSObject *);
112 static object_t *retrieveObject(int);
113 
114 // resultant object of parsed text
115 static OSObject	*parsedObject;
116 
117 #define YYSTYPE object_t *
118 
119 extern "C" {
120 extern void *kern_os_malloc(size_t size);
121 extern void *kern_os_realloc(void * addr, size_t size);
122 extern void kern_os_free(void * addr);
123 
124 //XXX shouldn't have to define these
125 extern long strtol(const char *, char **, int);
126 extern unsigned long strtoul(const char *, char **, int);
127 
128 } /* extern "C" */
129 
130 #define malloc(s) kern_os_malloc(s)
131 #define realloc(a, s) kern_os_realloc(a, s)
132 #define free(a) kern_os_free(a)
133 
134 #ifndef YYSTYPE
135 #define YYSTYPE int
136 #endif
137 #include <stddef.h>
138 
139 #ifndef __cplusplus
140 #ifndef __STDC__
141 #define const
142 #endif
143 #endif
144 
145 
146 
147 #define	YYFINAL		40
148 #define	YYFLAG		-32768
149 #define	YYNTBASE	19
150 
151 #define YYTRANSLATE(x) ((unsigned)(x) <= 266 ? yytranslate[x] : 33)
152 
153 static const char yytranslate[] = {     0,
154      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
155      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
156      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
157      2,     2,     2,     2,     2,     2,     2,     2,     2,    15,
158     16,     2,     2,     2,     2,     2,     2,     2,     2,     2,
159      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
160      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
161      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
162      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
163     17,     2,    18,     2,     2,     2,     2,     2,     2,     2,
164      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
165      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
166      2,     2,    13,     2,    14,     2,     2,     2,     2,     2,
167      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
168      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
169      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
170      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
171      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
172      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
173      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
174      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
175      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
176      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
177      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
178      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
179      2,     2,     2,     2,     2,     1,     3,     4,     5,     6,
180      7,     8,     9,    10,    11,    12
181 };
182 
183 #if YYDEBUG != 0
184 static const short yyprhs[] = {     0,
185      0,     1,     3,     5,     7,     9,    11,    13,    15,    17,
186     19,    21,    24,    28,    30,    32,    35,    38,    40,    43,
187     47,    49,    52,    56,    58,    60,    63,    65,    67,    69,
188     71
189 };
190 
191 static const short yyrhs[] = {    -1,
192     20,     0,    12,     0,    21,     0,    25,     0,    26,     0,
193     32,     0,    29,     0,    31,     0,    28,     0,    30,     0,
194     13,    14,     0,    13,    22,    14,     0,     6,     0,    23,
195      0,    22,    23,     0,    24,    20,     0,     8,     0,    15,
196     16,     0,    15,    27,    16,     0,     3,     0,    17,    18,
197      0,    17,    27,    18,     0,    10,     0,    20,     0,    27,
198     20,     0,     4,     0,     5,     0,     7,     0,     9,     0,
199     11,     0
200 };
201 
202 #endif
203 
204 #if YYDEBUG != 0
205 static const short yyrline[] = { 0,
206    123,   124,   129,   135,   136,   137,   138,   139,   140,   141,
207    142,   155,   158,   161,   164,   165,   170,   178,   183,   186,
208    189,   192,   195,   198,   201,   204,   211,   214,   217,   220,
209    223
210 };
211 #endif
212 
213 
214 #if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
215 
216 static const char * const yytname[] = {   "$","error","$undefined.","ARRAY",
217 "BOOLEAN","DATA","DICTIONARY","IDREF","KEY","NUMBER","SET","STRING","SYNTAX_ERROR",
218 "'{'","'}'","'('","')'","'['","']'","input","object","dict","pairs","pair","key",
219 "array","set","elements","boolean","data","idref","number","string", NULL
220 };
221 #endif
222 
223 static const short yyr1[] = {     0,
224     19,    19,    19,    20,    20,    20,    20,    20,    20,    20,
225     20,    21,    21,    21,    22,    22,    23,    24,    25,    25,
226     25,    26,    26,    26,    27,    27,    28,    29,    30,    31,
227     32
228 };
229 
230 static const short yyr2[] = {     0,
231      0,     1,     1,     1,     1,     1,     1,     1,     1,     1,
232      1,     2,     3,     1,     1,     2,     2,     1,     2,     3,
233      1,     2,     3,     1,     1,     2,     1,     1,     1,     1,
234      1
235 };
236 
237 static const short yydefact[] = {     1,
238     21,    27,    28,    14,    29,    30,    24,    31,     3,     0,
239      0,     0,     2,     4,     5,     6,    10,     8,    11,     9,
240      7,    18,    12,     0,    15,     0,    19,    25,     0,    22,
241      0,    13,    16,    17,    20,    26,    23,     0,     0,     0
242 };
243 
244 static const short yydefgoto[] = {    38,
245     28,    14,    24,    25,    26,    15,    16,    29,    17,    18,
246     19,    20,    21
247 };
248 
249 static const short yypact[] = {    45,
250 -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,     4,
251     60,    -2,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
252 -32768,-32768,-32768,     6,-32768,    90,-32768,-32768,    75,-32768,
253     29,-32768,-32768,-32768,-32768,-32768,-32768,    10,    17,-32768
254 };
255 
256 static const short yypgoto[] = {-32768,
257      0,-32768,-32768,   -18,-32768,-32768,-32768,     7,-32768,-32768,
258 -32768,-32768,-32768
259 };
260 
261 
262 #define	YYLAST		107
263 
264 
265 static const short yytable[] = {    13,
266      1,     2,     3,     4,     5,    33,     6,     7,     8,    39,
267     10,    22,    11,    22,    12,    30,    40,    23,    31,    32,
268      0,     0,     0,     0,     0,    34,     0,     0,    36,     0,
269     36,     1,     2,     3,     4,     5,     0,     6,     7,     8,
270      0,    10,     0,    11,     0,    12,    37,     1,     2,     3,
271      4,     5,     0,     6,     7,     8,     9,    10,     0,    11,
272      0,    12,     1,     2,     3,     4,     5,     0,     6,     7,
273      8,     0,    10,     0,    11,    27,    12,     1,     2,     3,
274      4,     5,     0,     6,     7,     8,     0,    10,     0,    11,
275     35,    12,     1,     2,     3,     4,     5,     0,     6,     7,
276      8,     0,    10,     0,    11,     0,    12
277 };
278 
279 static const short yycheck[] = {     0,
280      3,     4,     5,     6,     7,    24,     9,    10,    11,     0,
281     13,     8,    15,     8,    17,    18,     0,    14,    12,    14,
282     -1,    -1,    -1,    -1,    -1,    26,    -1,    -1,    29,    -1,
283     31,     3,     4,     5,     6,     7,    -1,     9,    10,    11,
284     -1,    13,    -1,    15,    -1,    17,    18,     3,     4,     5,
285      6,     7,    -1,     9,    10,    11,    12,    13,    -1,    15,
286     -1,    17,     3,     4,     5,     6,     7,    -1,     9,    10,
287     11,    -1,    13,    -1,    15,    16,    17,     3,     4,     5,
288      6,     7,    -1,     9,    10,    11,    -1,    13,    -1,    15,
289     16,    17,     3,     4,     5,     6,     7,    -1,     9,    10,
290     11,    -1,    13,    -1,    15,    -1,    17
291 };
292 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
293 #line 3 "/usr/share/bison.simple"
294 /* This file comes from bison-1.28.  */
295 
296 /* Skeleton output parser for bison,
297    Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
298 
299    This program is free software; you can redistribute it and/or modify
300    it under the terms of the GNU General Public License as published by
301    the Free Software Foundation; either version 2, or (at your option)
302    any later version.
303 
304    This program is distributed in the hope that it will be useful,
305    but WITHOUT ANY WARRANTY; without even the implied warranty of
306    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
307    GNU General Public License for more details.
308 
309    You should have received a copy of the GNU General Public License
310    along with this program; if not, write to the Free Software
311    Foundation, Inc., 59 Temple Place - Suite 330,
312    Boston, MA 02111-1307, USA.  */
313 
314 /* As a special exception, when this file is copied by Bison into a
315    Bison output file, you may use that output file without restriction.
316    This special exception was added by the Free Software Foundation
317    in version 1.24 of Bison.  */
318 
319 /* This is the parser code that is written into each bison parser
320   when the %semantic_parser declaration is not specified in the grammar.
321   It was written by Richard Stallman by simplifying the hairy parser
322   used when %semantic_parser is specified.  */
323 
324 #ifndef YYSTACK_USE_ALLOCA
325 #ifdef alloca
326 #define YYSTACK_USE_ALLOCA
327 #else /* alloca not defined */
328 #ifdef __GNUC__
329 #define YYSTACK_USE_ALLOCA
330 #define alloca __builtin_alloca
331 #else /* not GNU C.  */
332 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
333 #define YYSTACK_USE_ALLOCA
334 #include <alloca.h>
335 #else /* not sparc */
336 /* We think this test detects Watcom and Microsoft C.  */
337 /* This used to test MSDOS, but that is a bad idea
338    since that symbol is in the user namespace.  */
339 #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
340 #if 0 /* No need for malloc.h, which pollutes the namespace;
341 	 instead, just don't use alloca.  */
342 #include <malloc.h>
343 #endif
344 #else /* not MSDOS, or __TURBOC__ */
345 #if defined(_AIX)
346 /* I don't know what this was needed for, but it pollutes the namespace.
347    So I turned it off.   rms, 2 May 1997.  */
348 /* #include <malloc.h>  */
349  #pragma alloca
350 #define YYSTACK_USE_ALLOCA
351 #else /* not MSDOS, or __TURBOC__, or _AIX */
352 #if 0
353 #ifdef __hpux /* [email protected] says this works for HPUX 9.05 and up,
354 		 and on HPUX 10.  Eventually we can turn this on.  */
355 #define YYSTACK_USE_ALLOCA
356 #define alloca __builtin_alloca
357 #endif /* __hpux */
358 #endif
359 #endif /* not _AIX */
360 #endif /* not MSDOS, or __TURBOC__ */
361 #endif /* not sparc */
362 #endif /* not GNU C */
363 #endif /* alloca not defined */
364 #endif /* YYSTACK_USE_ALLOCA not defined */
365 
366 #ifdef YYSTACK_USE_ALLOCA
367 #define YYSTACK_ALLOC alloca
368 #else
369 #define YYSTACK_ALLOC malloc
370 #endif
371 
372 /* Note: there must be only one dollar sign in this file.
373    It is replaced by the list of actions, each action
374    as one case of the switch.  */
375 
376 #define yyerrok		(yyerrstatus = 0)
377 #define yyclearin	(yychar = YYEMPTY)
378 #define YYEMPTY		-2
379 #define YYEOF		0
380 #define YYACCEPT	goto yyacceptlab
381 #define YYABORT 	goto yyabortlab
382 #define YYERROR		goto yyerrlab1
383 /* Like YYERROR except do call yyerror.
384    This remains here temporarily to ease the
385    transition to the new meaning of YYERROR, for GCC.
386    Once GCC version 2 has supplanted version 1, this can go.  */
387 #define YYFAIL		goto yyerrlab
388 #define YYRECOVERING()  (!!yyerrstatus)
389 #define YYBACKUP(token, value) \
390 do								\
391   if (yychar == YYEMPTY && yylen == 1)				\
392     { yychar = (token), yylval = (value);			\
393       yychar1 = YYTRANSLATE (yychar);				\
394       YYPOPSTACK;						\
395       goto yybackup;						\
396     }								\
397   else								\
398     { yyerror ("syntax error: cannot back up"); YYERROR; }	\
399 while (0)
400 
401 #define YYTERROR	1
402 #define YYERRCODE	256
403 
404 #ifndef YYPURE
405 #define YYLEX		yylex()
406 #endif
407 
408 #ifdef YYPURE
409 #ifdef YYLSP_NEEDED
410 #ifdef YYLEX_PARAM
411 #define YYLEX		yylex(&yylval, &yylloc, YYLEX_PARAM)
412 #else
413 #define YYLEX		yylex(&yylval, &yylloc)
414 #endif
415 #else /* not YYLSP_NEEDED */
416 #ifdef YYLEX_PARAM
417 #define YYLEX		yylex(&yylval, YYLEX_PARAM)
418 #else
419 #define YYLEX		yylex(&yylval)
420 #endif
421 #endif /* not YYLSP_NEEDED */
422 #endif
423 
424 /* If nonreentrant, generate the variables here */
425 
426 #ifndef YYPURE
427 
428 int	yychar;			/*  the lookahead symbol		*/
429 YYSTYPE	yylval;			/*  the semantic value of the		*/
430 				/*  lookahead symbol			*/
431 
432 #ifdef YYLSP_NEEDED
433 YYLTYPE yylloc;			/*  location data for the lookahead	*/
434 				/*  symbol				*/
435 #endif
436 
437 int yynerrs;			/*  number of parse errors so far       */
438 #endif  /* not YYPURE */
439 
440 #if YYDEBUG != 0
441 int yydebug;			/*  nonzero means print parse trace	*/
442 /* Since this is uninitialized, it does not stop multiple parsers
443    from coexisting.  */
444 #endif
445 
446 /*  YYINITDEPTH indicates the initial size of the parser's stacks	*/
447 
448 #ifndef	YYINITDEPTH
449 #define YYINITDEPTH 200
450 #endif
451 
452 /*  YYMAXDEPTH is the maximum size the stacks can grow to
453     (effective only if the built-in stack extension method is used).  */
454 
455 #if YYMAXDEPTH == 0
456 #undef YYMAXDEPTH
457 #endif
458 
459 #ifndef YYMAXDEPTH
460 #define YYMAXDEPTH 10000
461 #endif
462 
463 /* Define __yy_memcpy.  Note that the size argument
464    should be passed with type unsigned int, because that is what the non-GCC
465    definitions require.  With GCC, __builtin_memcpy takes an arg
466    of type size_t, but it can handle unsigned int.  */
467 
468 #if __GNUC__ > 1		/* GNU C and GNU C++ define this.  */
469 #define __yy_memcpy(TO,FROM,COUNT)	__builtin_memcpy(TO,FROM,COUNT)
470 #else				/* not GNU C or C++ */
471 #ifndef __cplusplus
472 
473 /* This is the most reliable way to avoid incompatibilities
474    in available built-in functions on various systems.  */
475 static void
476 __yy_memcpy (to, from, count)
477      char *to;
478      char *from;
479      unsigned int count;
480 {
481   register char *f = from;
482   register char *t = to;
483   register int i = count;
484 
485   while (i-- > 0)
486     *t++ = *f++;
487 }
488 
489 #else /* __cplusplus */
490 
491 /* This is the most reliable way to avoid incompatibilities
492    in available built-in functions on various systems.  */
493 static void
494 __yy_memcpy (char *to, char *from, unsigned int count)
495 {
496   register char *t = to;
497   register char *f = from;
498   register int i = count;
499 
500   while (i-- > 0)
501     *t++ = *f++;
502 }
503 
504 #endif
505 #endif
506 
507 #line 217 "/usr/share/bison.simple"
508 
509 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
510    into yyparse.  The argument should have type void *.
511    It should actually point to an object.
512    Grammar actions can access the variable by casting it
513    to the proper pointer type.  */
514 
515 #ifdef YYPARSE_PARAM
516 #ifdef __cplusplus
517 #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
518 #define YYPARSE_PARAM_DECL
519 #else /* not __cplusplus */
520 #define YYPARSE_PARAM_ARG YYPARSE_PARAM
521 #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
522 #endif /* not __cplusplus */
523 #else /* not YYPARSE_PARAM */
524 #define YYPARSE_PARAM_ARG
525 #define YYPARSE_PARAM_DECL
526 #endif /* not YYPARSE_PARAM */
527 
528 /* Prevent warning if -Wstrict-prototypes.  */
529 #ifdef __GNUC__
530 #ifdef YYPARSE_PARAM
531 int yyparse (void *);
532 #else
533 int yyparse (void);
534 #endif
535 #endif
536 
537 int
538 yyparse(YYPARSE_PARAM_ARG)
539      YYPARSE_PARAM_DECL
540 {
541   register int yystate;
542   register int yyn;
543   register short *yyssp;
544   register YYSTYPE *yyvsp;
545   int yyerrstatus;	/*  number of tokens to shift before error messages enabled */
546   int yychar1 = 0;		/*  lookahead token as an internal (translated) token number */
547 
548   short	yyssa[YYINITDEPTH];	/*  the state stack			*/
549   YYSTYPE yyvsa[YYINITDEPTH];	/*  the semantic value stack		*/
550 
551   short *yyss = yyssa;		/*  refer to the stacks thru separate pointers */
552   YYSTYPE *yyvs = yyvsa;	/*  to allow yyoverflow to reallocate them elsewhere */
553 
554 #ifdef YYLSP_NEEDED
555   YYLTYPE yylsa[YYINITDEPTH];	/*  the location stack			*/
556   YYLTYPE *yyls = yylsa;
557   YYLTYPE *yylsp;
558 
559 #define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
560 #else
561 #define YYPOPSTACK   (yyvsp--, yyssp--)
562 #endif
563 
564   int yystacksize = YYINITDEPTH;
565   int yyfree_stacks = 0;
566 
567 #ifdef YYPURE
568   int yychar;
569   YYSTYPE yylval;
570   int yynerrs;
571 #ifdef YYLSP_NEEDED
572   YYLTYPE yylloc;
573 #endif
574 #endif
575 
576   YYSTYPE yyval;		/*  the variable used to return		*/
577 				/*  semantic values from the action	*/
578 				/*  routines				*/
579 
580   int yylen;
581 
582 #if YYDEBUG != 0
583   if (yydebug)
584     fprintf(stderr, "Starting parse\n");
585 #endif
586 
587   yystate = 0;
588   yyerrstatus = 0;
589   yynerrs = 0;
590   yychar = YYEMPTY;		/* Cause a token to be read.  */
591 
592   /* Initialize stack pointers.
593      Waste one element of value and location stack
594      so that they stay on the same level as the state stack.
595      The wasted elements are never initialized.  */
596 
597   yyssp = yyss - 1;
598   yyvsp = yyvs;
599 #ifdef YYLSP_NEEDED
600   yylsp = yyls;
601 #endif
602 
603 /* Push a new state, which is found in  yystate  .  */
604 /* In all cases, when you get here, the value and location stacks
605    have just been pushed. so pushing a state here evens the stacks.  */
606 yynewstate:
607 
608   *++yyssp = yystate;
609 
610   if (yyssp >= yyss + yystacksize - 1)
611     {
612       /* Give user a chance to reallocate the stack */
613       /* Use copies of these so that the &'s don't force the real ones into memory. */
614       YYSTYPE *yyvs1 = yyvs;
615       short *yyss1 = yyss;
616 #ifdef YYLSP_NEEDED
617       YYLTYPE *yyls1 = yyls;
618 #endif
619 
620       /* Get the current used size of the three stacks, in elements.  */
621       int size = yyssp - yyss + 1;
622 
623 #ifdef yyoverflow
624       /* Each stack pointer address is followed by the size of
625 	 the data in use in that stack, in bytes.  */
626 #ifdef YYLSP_NEEDED
627       /* This used to be a conditional around just the two extra args,
628 	 but that might be undefined if yyoverflow is a macro.  */
629       yyoverflow("parser stack overflow",
630 		 &yyss1, size * sizeof (*yyssp),
631 		 &yyvs1, size * sizeof (*yyvsp),
632 		 &yyls1, size * sizeof (*yylsp),
633 		 &yystacksize);
634 #else
635       yyoverflow("parser stack overflow",
636 		 &yyss1, size * sizeof (*yyssp),
637 		 &yyvs1, size * sizeof (*yyvsp),
638 		 &yystacksize);
639 #endif
640 
641       yyss = yyss1; yyvs = yyvs1;
642 #ifdef YYLSP_NEEDED
643       yyls = yyls1;
644 #endif
645 #else /* no yyoverflow */
646       /* Extend the stack our own way.  */
647       if (yystacksize >= YYMAXDEPTH)
648 	{
649 	  yyerror("parser stack overflow");
650 	  if (yyfree_stacks)
651 	    {
652 	      free (yyss);
653 	      free (yyvs);
654 #ifdef YYLSP_NEEDED
655 	      free (yyls);
656 #endif
657 	    }
658 	  return 2;
659 	}
660       yystacksize *= 2;
661       if (yystacksize > YYMAXDEPTH)
662 	yystacksize = YYMAXDEPTH;
663 #ifndef YYSTACK_USE_ALLOCA
664       yyfree_stacks = 1;
665 #endif
666       yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
667       __yy_memcpy ((char *)yyss, (char *)yyss1,
668 		   size * (unsigned int) sizeof (*yyssp));
669       yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
670       __yy_memcpy ((char *)yyvs, (char *)yyvs1,
671 		   size * (unsigned int) sizeof (*yyvsp));
672 #ifdef YYLSP_NEEDED
673       yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
674       __yy_memcpy ((char *)yyls, (char *)yyls1,
675 		   size * (unsigned int) sizeof (*yylsp));
676 #endif
677 #endif /* no yyoverflow */
678 
679       yyssp = yyss + size - 1;
680       yyvsp = yyvs + size - 1;
681 #ifdef YYLSP_NEEDED
682       yylsp = yyls + size - 1;
683 #endif
684 
685 #if YYDEBUG != 0
686       if (yydebug)
687 	fprintf(stderr, "Stack size increased to %d\n", yystacksize);
688 #endif
689 
690       if (yyssp >= yyss + yystacksize - 1)
691 	YYABORT;
692     }
693 
694 #if YYDEBUG != 0
695   if (yydebug)
696     fprintf(stderr, "Entering state %d\n", yystate);
697 #endif
698 
699   goto yybackup;
700  yybackup:
701 
702 /* Do appropriate processing given the current state.  */
703 /* Read a lookahead token if we need one and don't already have one.  */
704 /* yyresume: */
705 
706   /* First try to decide what to do without reference to lookahead token.  */
707 
708   yyn = yypact[yystate];
709   if (yyn == YYFLAG)
710     goto yydefault;
711 
712   /* Not known => get a lookahead token if don't already have one.  */
713 
714   /* yychar is either YYEMPTY or YYEOF
715      or a valid token in external form.  */
716 
717   if (yychar == YYEMPTY)
718     {
719 #if YYDEBUG != 0
720       if (yydebug)
721 	fprintf(stderr, "Reading a token: ");
722 #endif
723       yychar = YYLEX;
724     }
725 
726   /* Convert token to internal form (in yychar1) for indexing tables with */
727 
728   if (yychar <= 0)		/* This means end of input. */
729     {
730       yychar1 = 0;
731       yychar = YYEOF;		/* Don't call YYLEX any more */
732 
733 #if YYDEBUG != 0
734       if (yydebug)
735 	fprintf(stderr, "Now at end of input.\n");
736 #endif
737     }
738   else
739     {
740       yychar1 = YYTRANSLATE(yychar);
741 
742 #if YYDEBUG != 0
743       if (yydebug)
744 	{
745 	  fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
746 	  /* Give the individual parser a way to print the precise meaning
747 	     of a token, for further debugging info.  */
748 #ifdef YYPRINT
749 	  YYPRINT (stderr, yychar, yylval);
750 #endif
751 	  fprintf (stderr, ")\n");
752 	}
753 #endif
754     }
755 
756   yyn += yychar1;
757   if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
758     goto yydefault;
759 
760   yyn = yytable[yyn];
761 
762   /* yyn is what to do for this token type in this state.
763      Negative => reduce, -yyn is rule number.
764      Positive => shift, yyn is new state.
765        New state is final state => don't bother to shift,
766        just return success.
767      0, or most negative number => error.  */
768 
769   if (yyn < 0)
770     {
771       if (yyn == YYFLAG)
772 	goto yyerrlab;
773       yyn = -yyn;
774       goto yyreduce;
775     }
776   else if (yyn == 0)
777     goto yyerrlab;
778 
779   if (yyn == YYFINAL)
780     YYACCEPT;
781 
782   /* Shift the lookahead token.  */
783 
784 #if YYDEBUG != 0
785   if (yydebug)
786     fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
787 #endif
788 
789   /* Discard the token being shifted unless it is eof.  */
790   if (yychar != YYEOF)
791     yychar = YYEMPTY;
792 
793   *++yyvsp = yylval;
794 #ifdef YYLSP_NEEDED
795   *++yylsp = yylloc;
796 #endif
797 
798   /* count tokens shifted since error; after three, turn off error status.  */
799   if (yyerrstatus) yyerrstatus--;
800 
801   yystate = yyn;
802   goto yynewstate;
803 
804 /* Do the default action for the current state.  */
805 yydefault:
806 
807   yyn = yydefact[yystate];
808   if (yyn == 0)
809     goto yyerrlab;
810 
811 /* Do a reduction.  yyn is the number of a rule to reduce with.  */
812 yyreduce:
813   yylen = yyr2[yyn];
814   if (yylen > 0)
815     yyval = yyvsp[1-yylen]; /* implement default value of the action */
816 
817 #if YYDEBUG != 0
818   if (yydebug)
819     {
820       int i;
821 
822       fprintf (stderr, "Reducing via rule %d (line %d), ",
823 	       yyn, yyrline[yyn]);
824 
825       /* Print the symbols being reduced, and their result.  */
826       for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
827 	fprintf (stderr, "%s ", yytname[yyrhs[i]]);
828       fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
829     }
830 #endif
831 
832 
833   switch (yyn) {
834 
835 case 1:
836 #line 123 "OSUnserializeXML.y"
837 { parsedObject = (OSObject *)NULL; YYACCEPT; ;
838     break;}
839 case 2:
840 #line 124 "OSUnserializeXML.y"
841 { parsedObject = yyvsp[0]->object;
842 				  yyvsp[0]->object = 0;
843 				  freeObject(yyvsp[0]);
844 				  YYACCEPT;
845 				;
846     break;}
847 case 3:
848 #line 129 "OSUnserializeXML.y"
849 {
850 				  yyerror("syntax error");
851 				  YYERROR;
852 				;
853     break;}
854 case 4:
855 #line 135 "OSUnserializeXML.y"
856 { yyval = buildOSDictionary(yyvsp[0]); ;
857     break;}
858 case 5:
859 #line 136 "OSUnserializeXML.y"
860 { yyval = buildOSArray(yyvsp[0]); ;
861     break;}
862 case 6:
863 #line 137 "OSUnserializeXML.y"
864 { yyval = buildOSSet(yyvsp[0]); ;
865     break;}
866 case 7:
867 #line 138 "OSUnserializeXML.y"
868 { yyval = buildOSString(yyvsp[0]); ;
869     break;}
870 case 8:
871 #line 139 "OSUnserializeXML.y"
872 { yyval = buildOSData(yyvsp[0]); ;
873     break;}
874 case 9:
875 #line 140 "OSUnserializeXML.y"
876 { yyval = buildOSNumber(yyvsp[0]); ;
877     break;}
878 case 10:
879 #line 141 "OSUnserializeXML.y"
880 { yyval = buildOSBoolean(yyvsp[0]); ;
881     break;}
882 case 11:
883 #line 142 "OSUnserializeXML.y"
884 { yyval = retrieveObject(yyvsp[0]->idref);
885 				  if (yyval) {
886 				    yyval->object->retain();
887 				  } else {
888 				    yyerror("forward reference detected");
889 				    YYERROR;
890 				  }
891 				  freeObject(yyvsp[0]);
892 				;
893     break;}
894 case 12:
895 #line 155 "OSUnserializeXML.y"
896 { yyval = yyvsp[-1];
897 				  yyval->elements = NULL;
898 				;
899     break;}
900 case 13:
901 #line 158 "OSUnserializeXML.y"
902 { yyval = yyvsp[-2];
903 				  yyval->elements = yyvsp[-1];
904 				;
905     break;}
906 case 16:
907 #line 165 "OSUnserializeXML.y"
908 { yyval = yyvsp[0];
909 				  yyval->next = yyvsp[-1];
910 				;
911     break;}
912 case 17:
913 #line 170 "OSUnserializeXML.y"
914 { yyval = yyvsp[-1];
915 				  yyval->next = NULL;
916 				  yyval->object = yyvsp[0]->object;
917 				  yyvsp[0]->object = 0;
918 				  freeObject(yyvsp[0]);
919 				;
920     break;}
921 case 18:
922 #line 178 "OSUnserializeXML.y"
923 { yyval = buildKey(yyvsp[0]); ;
924     break;}
925 case 19:
926 #line 183 "OSUnserializeXML.y"
927 { yyval = yyvsp[-1];
928 				  yyval->elements = NULL;
929 				;
930     break;}
931 case 20:
932 #line 186 "OSUnserializeXML.y"
933 { yyval = yyvsp[-2];
934 				  yyval->elements = yyvsp[-1];
935 				;
936     break;}
937 case 22:
938 #line 192 "OSUnserializeXML.y"
939 { yyval = yyvsp[-1];
940 				  yyval->elements = NULL;
941 				;
942     break;}
943 case 23:
944 #line 195 "OSUnserializeXML.y"
945 { yyval = yyvsp[-2];
946 				  yyval->elements = yyvsp[-1];
947 				;
948     break;}
949 case 25:
950 #line 201 "OSUnserializeXML.y"
951 { yyval = yyvsp[0];
952 				  yyval->next = NULL;
953 				;
954     break;}
955 case 26:
956 #line 204 "OSUnserializeXML.y"
957 { yyval = yyvsp[0];
958 				  yyval->next = yyvsp[-1];
959 				;
960     break;}
961 }
962    /* the action file gets copied in in place of this dollarsign */
963 #line 543 "/usr/share/bison.simple"
964 
965   yyvsp -= yylen;
966   yyssp -= yylen;
967 #ifdef YYLSP_NEEDED
968   yylsp -= yylen;
969 #endif
970 
971 #if YYDEBUG != 0
972   if (yydebug)
973     {
974       short *ssp1 = yyss - 1;
975       fprintf (stderr, "state stack now");
976       while (ssp1 != yyssp)
977 	fprintf (stderr, " %d", *++ssp1);
978       fprintf (stderr, "\n");
979     }
980 #endif
981 
982   *++yyvsp = yyval;
983 
984 #ifdef YYLSP_NEEDED
985   yylsp++;
986   if (yylen == 0)
987     {
988       yylsp->first_line = yylloc.first_line;
989       yylsp->first_column = yylloc.first_column;
990       yylsp->last_line = (yylsp-1)->last_line;
991       yylsp->last_column = (yylsp-1)->last_column;
992       yylsp->text = 0;
993     }
994   else
995     {
996       yylsp->last_line = (yylsp+yylen-1)->last_line;
997       yylsp->last_column = (yylsp+yylen-1)->last_column;
998     }
999 #endif
1000 
1001   /* Now "shift" the result of the reduction.
1002      Determine what state that goes to,
1003      based on the state we popped back to
1004      and the rule number reduced by.  */
1005 
1006   yyn = yyr1[yyn];
1007 
1008   yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
1009   if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1010     yystate = yytable[yystate];
1011   else
1012     yystate = yydefgoto[yyn - YYNTBASE];
1013 
1014   goto yynewstate;
1015 
1016 yyerrlab:   /* here on detecting error */
1017 
1018   if (! yyerrstatus)
1019     /* If not already recovering from an error, report this error.  */
1020     {
1021       ++yynerrs;
1022 
1023 #ifdef YYERROR_VERBOSE
1024       yyn = yypact[yystate];
1025 
1026       if (yyn > YYFLAG && yyn < YYLAST)
1027 	{
1028 	  int size = 0;
1029 	  char *msg;
1030 	  int x, count;
1031 
1032 	  count = 0;
1033 	  /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
1034 	  for (x = (yyn < 0 ? -yyn : 0);
1035 	       x < (sizeof(yytname) / sizeof(char *)); x++)
1036 	    if (yycheck[x + yyn] == x)
1037 	      size += strlen(yytname[x]) + 15, count++;
1038 	  msg = (char *) malloc(size + 15);
1039 	  if (msg != 0)
1040 	    {
1041 	      strcpy(msg, "parse error");
1042 
1043 	      if (count < 5)
1044 		{
1045 		  count = 0;
1046 		  for (x = (yyn < 0 ? -yyn : 0);
1047 		       x < (sizeof(yytname) / sizeof(char *)); x++)
1048 		    if (yycheck[x + yyn] == x)
1049 		      {
1050 			strcat(msg, count == 0 ? ", expecting `" : " or `");
1051 			strcat(msg, yytname[x]);
1052 			strcat(msg, "'");
1053 			count++;
1054 		      }
1055 		}
1056 	      yyerror(msg);
1057 	      free(msg);
1058 	    }
1059 	  else
1060 	    yyerror ("parse error; also virtual memory exceeded");
1061 	}
1062       else
1063 #endif /* YYERROR_VERBOSE */
1064 	yyerror("parse error");
1065     }
1066 
1067   goto yyerrlab1;
1068 yyerrlab1:   /* here on error raised explicitly by an action */
1069 
1070   if (yyerrstatus == 3)
1071     {
1072       /* if just tried and failed to reuse lookahead token after an error, discard it.  */
1073 
1074       /* return failure if at end of input */
1075       if (yychar == YYEOF)
1076 	YYABORT;
1077 
1078 #if YYDEBUG != 0
1079       if (yydebug)
1080 	fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
1081 #endif
1082 
1083       yychar = YYEMPTY;
1084     }
1085 
1086   /* Else will try to reuse lookahead token
1087      after shifting the error token.  */
1088 
1089   yyerrstatus = 3;		/* Each real token shifted decrements this */
1090 
1091   goto yyerrhandle;
1092 
1093 yyerrdefault:  /* current state does not do anything special for the error token. */
1094 
1095 #if 0
1096   /* This is wrong; only states that explicitly want error tokens
1097      should shift them.  */
1098   yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
1099   if (yyn) goto yydefault;
1100 #endif
1101 
1102 yyerrpop:   /* pop the current state because it cannot handle the error token */
1103 
1104   if (yyssp == yyss) YYABORT;
1105   yyvsp--;
1106   yystate = *--yyssp;
1107 #ifdef YYLSP_NEEDED
1108   yylsp--;
1109 #endif
1110 
1111 #if YYDEBUG != 0
1112   if (yydebug)
1113     {
1114       short *ssp1 = yyss - 1;
1115       fprintf (stderr, "Error: state stack now");
1116       while (ssp1 != yyssp)
1117 	fprintf (stderr, " %d", *++ssp1);
1118       fprintf (stderr, "\n");
1119     }
1120 #endif
1121 
1122 yyerrhandle:
1123 
1124   yyn = yypact[yystate];
1125   if (yyn == YYFLAG)
1126     goto yyerrdefault;
1127 
1128   yyn += YYTERROR;
1129   if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
1130     goto yyerrdefault;
1131 
1132   yyn = yytable[yyn];
1133   if (yyn < 0)
1134     {
1135       if (yyn == YYFLAG)
1136 	goto yyerrpop;
1137       yyn = -yyn;
1138       goto yyreduce;
1139     }
1140   else if (yyn == 0)
1141     goto yyerrpop;
1142 
1143   if (yyn == YYFINAL)
1144     YYACCEPT;
1145 
1146 #if YYDEBUG != 0
1147   if (yydebug)
1148     fprintf(stderr, "Shifting error token, ");
1149 #endif
1150 
1151   *++yyvsp = yylval;
1152 #ifdef YYLSP_NEEDED
1153   *++yylsp = yylloc;
1154 #endif
1155 
1156   yystate = yyn;
1157   goto yynewstate;
1158 
1159  yyacceptlab:
1160   /* YYACCEPT comes here.  */
1161   if (yyfree_stacks)
1162     {
1163       free (yyss);
1164       free (yyvs);
1165 #ifdef YYLSP_NEEDED
1166       free (yyls);
1167 #endif
1168     }
1169   return 0;
1170 
1171  yyabortlab:
1172   /* YYABORT comes here.  */
1173   if (yyfree_stacks)
1174     {
1175       free (yyss);
1176       free (yyvs);
1177 #ifdef YYLSP_NEEDED
1178       free (yyls);
1179 #endif
1180     }
1181   return 1;
1182 }
1183 #line 226 "OSUnserializeXML.y"
1184 
1185 
1186 static int		lineNumber = 0;
1187 static const char	*parseBuffer;
1188 static int		parseBufferIndex;
1189 
1190 #define currentChar()	(parseBuffer[parseBufferIndex])
1191 #define nextChar()	(parseBuffer[++parseBufferIndex])
1192 #define prevChar()	(parseBuffer[parseBufferIndex - 1])
1193 
1194 #define isSpace(c)	((c) == ' ' || (c) == '\t')
1195 #define isAlpha(c)	(((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
1196 #define isDigit(c)	((c) >= '0' && (c) <= '9')
1197 #define isAlphaDigit(c)	((c) >= 'a' && (c) <= 'f')
1198 #define isHexDigit(c)	(isDigit(c) || isAlphaDigit(c))
1199 #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-'))
1200 
1201 static char yyerror_message[128];
1202 
1203 int
1204 yyerror(char *s)  /* Called by yyparse on error */
1205 {
1206 	sprintf(yyerror_message, "OSUnserializeXML: %s near line %d\n", s, lineNumber);
1207 	return 0;
1208 }
1209 
1210 #define TAG_MAX_LENGTH		32
1211 #define TAG_MAX_ATTRIBUTES	32
1212 #define TAG_BAD			0
1213 #define TAG_START		1
1214 #define TAG_END			2
1215 #define TAG_EMPTY		3
1216 #define TAG_COMMENT		4
1217 
1218 static int
1219 getTag(char tag[TAG_MAX_LENGTH],
1220        int *attributeCount,
1221        char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH],
1222        char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] )
1223 {
1224 	int length = 0;;
1225 	int c = currentChar();
1226 	int tagType = TAG_START;
1227 
1228 	*attributeCount = 0;
1229 
1230 	if (c != '<') return TAG_BAD;
1231         c = nextChar();		// skip '<'
1232 
1233         if (c == '?' || c == '!') {
1234                 while ((c = nextChar()) != 0) {
1235                         if (c == '\n') lineNumber++;
1236                         if (c == '>') {
1237                                 (void)nextChar();
1238                                 return TAG_COMMENT;
1239                         }
1240                 }
1241         }
1242 
1243 	if (c == '/') {
1244 		c = nextChar();		// skip '/'
1245 		tagType = TAG_END;
1246 	}
1247         if (!isAlpha(c)) return TAG_BAD;
1248 
1249 	/* find end of tag while copying it */
1250 	while (isAlphaNumeric(c)) {
1251 		tag[length++] = c;
1252 		c = nextChar();
1253 		if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1254 	}
1255 
1256 	tag[length] = 0;
1257 
1258 //printf("tag %s, type %d\n", tag, tagType);
1259 
1260 	// look for attributes of the form attribute = "value" ...
1261 	while ((c != '>') && (c != '/')) {
1262 		while (isSpace(c)) c = nextChar();
1263 
1264 		length = 0;
1265 		while (isAlphaNumeric(c)) {
1266 			attributes[*attributeCount][length++] = c;
1267 			if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1268 			c = nextChar();
1269 		}
1270 		attributes[*attributeCount][length] = 0;
1271 
1272 		while (isSpace(c)) c = nextChar();
1273 
1274 		if (c != '=') return TAG_BAD;
1275 		c = nextChar();
1276 
1277 		while (isSpace(c)) c = nextChar();
1278 
1279 		if (c != '"') return TAG_BAD;
1280 		c = nextChar();
1281 		length = 0;
1282 		while (c != '"') {
1283 			values[*attributeCount][length++] = c;
1284 			if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1285 			c = nextChar();
1286 		}
1287 		values[*attributeCount][length] = 0;
1288 
1289 		c = nextChar(); // skip closing quote
1290 
1291 //printf("	attribute '%s' = '%s', nextchar = '%c'\n", attributes[*attributeCount], values[*attributeCount], c);
1292 
1293 		(*attributeCount)++;
1294 		if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD;
1295 	}
1296 
1297 	if (c == '/') {
1298 		c = nextChar();		// skip '/'
1299 		tagType = TAG_EMPTY;
1300 	}
1301 	if (c != '>') return TAG_BAD;
1302 	c = nextChar();		// skip '>'
1303 
1304 	return tagType;
1305 }
1306 
1307 static char *
1308 getString()
1309 {
1310 	int c = currentChar();
1311 
1312 	int start, length, i, j;;
1313 	char * tempString;
1314 
1315 	start = parseBufferIndex;
1316 	/* find end of string */
1317 
1318 	while (c != 0) {
1319 		if (c == '\n') lineNumber++;
1320 		if (c == '<') {
1321 			break;
1322 		}
1323 		c = nextChar();
1324 	}
1325 
1326 	if (c != '<') return 0;
1327 
1328 	length = parseBufferIndex - start;
1329 
1330 	/* copy to null terminated buffer */
1331 	tempString = (char *)malloc(length + 1);
1332 	if (tempString == 0) {
1333 		printf("OSUnserializeXML: can't alloc temp memory\n");
1334 		return 0;
1335 	}
1336 
1337 	// copy out string in tempString
1338 	// "&amp;" -> '&', "&lt;" -> '<', "&gt;" -> '>'
1339 
1340 	i = j = 0;
1341 	while (i < length) {
1342 		c = parseBuffer[start + i++];
1343 		if (c != '&') {
1344 			tempString[j++] = c;
1345 		} else {
1346 			if ((i+3) > length) goto error;
1347 			c = parseBuffer[start + i++];
1348 			if (c == 'l') {
1349 				if (parseBuffer[start + i++] != 't') goto error;
1350 				if (parseBuffer[start + i++] != ';') goto error;
1351 				tempString[j++] = '<';
1352 				continue;
1353 			}
1354 			if (c == 'g') {
1355 				if (parseBuffer[start + i++] != 't') goto error;
1356 				if (parseBuffer[start + i++] != ';') goto error;
1357 				tempString[j++] = '>';
1358 				continue;
1359 			}
1360 			if ((i+3) > length) goto error;
1361 			if (c == 'a') {
1362 				if (parseBuffer[start + i++] != 'm') goto error;
1363 				if (parseBuffer[start + i++] != 'p') goto error;
1364 				if (parseBuffer[start + i++] != ';') goto error;
1365 				tempString[j++] = '&';
1366 				continue;
1367 			}
1368 			goto error;
1369 		}
1370 	}
1371 	tempString[j] = 0;
1372 
1373 //printf("string %s\n", tempString);
1374 
1375 	return tempString;
1376 
1377 error:
1378 	if (tempString) free(tempString);
1379 	return 0;
1380 }
1381 
1382 static long long
1383 getNumber()
1384 {
1385 	unsigned long long n = 0;
1386 	int base = 10;
1387 	int c = currentChar();
1388 
1389 	if (!isDigit (c)) return 0;
1390 
1391 	if (c == '0') {
1392 		c = nextChar();
1393 		if (c == 'x') {
1394 			base = 16;
1395 			c = nextChar();
1396 		}
1397 	}
1398 	if (base == 10) {
1399 		while(isDigit(c)) {
1400 			n = (n * base + c - '0');
1401 			c = nextChar();
1402 		}
1403 	} else {
1404 		while(isHexDigit(c)) {
1405 			if (isDigit(c)) {
1406 				n = (n * base + c - '0');
1407 			} else {
1408 				n = (n * base + 0xa + c - 'a');
1409 			}
1410 			c = nextChar();
1411 		}
1412 	}
1413 //printf("number 0x%x\n", (unsigned long)n);
1414 	return n;
1415 }
1416 
1417 // taken from CFXMLParsing/CFPropertyList.c
1418 
1419 static const signed char __CFPLDataDecodeTable[128] = {
1420     /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
1421     /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
1422     /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
1423     /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
1424     /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
1425     /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
1426     /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
1427     /* '8' */ 60, 61, -1, -1, -1,  0, -1, -1,
1428     /* '@' */ -1,  0,  1,  2,  3,  4,  5,  6,
1429     /* 'H' */  7,  8,  9, 10, 11, 12, 13, 14,
1430     /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
1431     /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
1432     /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
1433     /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
1434     /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
1435     /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
1436 };
1437 
1438 #define OSDATA_ALLOC_SIZE 4096
1439 
1440 static void *
1441 getCFEncodedData(unsigned int *size)
1442 {
1443     int numeq = 0, acc = 0, cntr = 0;
1444     int tmpbufpos = 0, tmpbuflen = 0;
1445     unsigned char *tmpbuf = (unsigned char *)malloc(OSDATA_ALLOC_SIZE);
1446 
1447     int c = currentChar();
1448     *size = 0;
1449 
1450     while (c != '<') {
1451         c &= 0x7f;
1452 	if (c == 0) {
1453 		free(tmpbuf);
1454 		return 0;
1455 	}
1456 	if (c == '=') numeq++; else numeq = 0;
1457 	if (c == '\n') lineNumber++;
1458         if (__CFPLDataDecodeTable[c] < 0) {
1459 	    c = nextChar();
1460             continue;
1461 	}
1462         cntr++;
1463         acc <<= 6;
1464         acc += __CFPLDataDecodeTable[c];
1465         if (0 == (cntr & 0x3)) {
1466             if (tmpbuflen <= tmpbufpos + 2) {
1467                 tmpbuflen += OSDATA_ALLOC_SIZE;
1468 		tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen);
1469             }
1470             tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
1471             if (numeq < 2)
1472                 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
1473             if (numeq < 1)
1474                 tmpbuf[tmpbufpos++] = acc & 0xff;
1475         }
1476 	c = nextChar();
1477     }
1478     *size = tmpbufpos;
1479     return tmpbuf;
1480 }
1481 
1482 static void *
1483 getHexData(unsigned int *size)
1484 {
1485     int c;
1486     unsigned char *d, *start, *lastStart;
1487 
1488     start = lastStart = d = (unsigned char *)malloc(OSDATA_ALLOC_SIZE);
1489     c = currentChar();
1490 
1491     while (c != '<') {
1492 
1493 	if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
1494 	if (c == '\n') {
1495 	    lineNumber++;
1496 	    c = nextChar();
1497 	    continue;
1498 	}
1499 
1500 	// get high nibble
1501 	if (isDigit(c)) {
1502 	    *d = (c - '0') << 4;
1503 	} else if (isAlphaDigit(c)) {
1504 	    *d =  (0xa + (c - 'a')) << 4;
1505 	} else {
1506 	    goto error;
1507 	}
1508 
1509 	// get low nibble
1510 	c = nextChar();
1511 	if (isDigit(c)) {
1512 	    *d |= c - '0';
1513 	} else if (isAlphaDigit(c)) {
1514 	    *d |= 0xa + (c - 'a');
1515 	} else {
1516 	    goto error;
1517 	}
1518 
1519 	d++;
1520 	if ((d - lastStart) >= OSDATA_ALLOC_SIZE) {
1521 	    int oldsize = d - start;
1522 	    start = (unsigned char *)realloc(start, oldsize + OSDATA_ALLOC_SIZE);
1523 	    d = lastStart = start + oldsize;
1524 	}
1525 	c = nextChar();
1526     }
1527 
1528     *size = d - start;
1529     return start;
1530 
1531  error:
1532 
1533     *size = 0;
1534     free(start);
1535     return 0;
1536 }
1537 
1538 static int
1539 yylex()
1540 {
1541 	int c;
1542 	int tagType;
1543 	char tag[TAG_MAX_LENGTH];
1544 	int attributeCount;
1545 	char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
1546 	char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
1547 
1548 	if (parseBufferIndex == 0) lineNumber = 1;
1549 
1550  top:
1551 	c = currentChar();
1552 
1553 	/* skip white space  */
1554 	if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
1555 
1556 	/* keep track of line number, don't return \n's */
1557 	if (c == '\n') {
1558 		lineNumber++;
1559 		(void)nextChar();
1560 		goto top;
1561 	}
1562 
1563 	if (!c)	return c;
1564 
1565 	tagType = getTag(tag, &attributeCount, attributes, values);
1566 	if (tagType == TAG_BAD) return SYNTAX_ERROR;
1567 	if (tagType == TAG_COMMENT) goto top;
1568 
1569 	// handle allocation and check for "ID" and "IDREF" tags up front
1570 	yylval = newObject();
1571 	yylval->idref = -1;
1572 	for (int i=0; i < attributeCount; i++) {
1573 	    if (attributes[i][0] == 'I' && attributes[i][1] == 'D') {
1574 		// check for idref's, note: we ignore the tag, for
1575 		// this to work correctly, all idrefs must be unique
1576 		// across the whole serialization
1577 		if (attributes[i][2] == 'R' && attributes[i][3] == 'E' &&
1578 		    attributes[i][4] == 'F' && !attributes[i][5]) {
1579 		    if (tagType != TAG_EMPTY) return SYNTAX_ERROR;
1580 		    yylval->idref = strtol(values[i], NULL, 0);
1581 		    return IDREF;
1582 		}
1583 		// check for id's
1584 		if (!attributes[i][2]) {
1585 		    yylval->idref = strtol(values[i], NULL, 0);
1586 		} else {
1587 		    return SYNTAX_ERROR;
1588 		}
1589 	    }
1590 	}
1591 
1592 	switch (*tag) {
1593 	case 'a':
1594 		if (!strcmp(tag, "array")) {
1595 			if (tagType == TAG_EMPTY) {
1596 				yylval->elements = NULL;
1597 				return ARRAY;
1598 			}
1599 			return (tagType == TAG_START) ? '(' : ')';
1600 		}
1601 		break;
1602 	case 'd':
1603 		if (!strcmp(tag, "dict")) {
1604 			if (tagType == TAG_EMPTY) {
1605 				yylval->elements = NULL;
1606 				return DICTIONARY;
1607 			}
1608 			return (tagType == TAG_START) ? '{' : '}';
1609 		}
1610 		if (!strcmp(tag, "data")) {
1611 			unsigned int size;
1612 			int readable = 0;
1613 			if (tagType == TAG_EMPTY) {
1614 				yylval->data = NULL;
1615 				yylval->size = 0;
1616 				return DATA;
1617 			}
1618 			for (int i=0; i < attributeCount; i++) {
1619 				if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) {
1620 					readable++;
1621 					break;
1622 				}
1623 			}
1624 			// CF encoded is the default form
1625 			if (readable) {
1626 			    yylval->data = getHexData(&size);
1627 			} else {
1628 			    yylval->data = getCFEncodedData(&size);
1629 			}
1630 			yylval->size = size;
1631 			if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) {
1632 				return SYNTAX_ERROR;
1633 			}
1634 			return DATA;
1635 		}
1636 		break;
1637 	case 'f':
1638 		if (!strcmp(tag, "false")) {
1639 			if (tagType == TAG_EMPTY) {
1640 				yylval->number = 0;
1641 				return BOOLEAN;
1642 			}
1643 		}
1644 		break;
1645 	case 'i':
1646 		if (!strcmp(tag, "integer")) {
1647 			yylval->size = 64;	// default
1648 			for (int i=0; i < attributeCount; i++) {
1649 				if (!strcmp(attributes[i], "size")) {
1650 					yylval->size = strtoul(values[i], NULL, 0);
1651 				}
1652 			}
1653 			if (tagType == TAG_EMPTY) {
1654 				yylval->number = 0;
1655 				return NUMBER;
1656 			}
1657 			yylval->number = getNumber();
1658 			if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) {
1659 				return SYNTAX_ERROR;
1660 			}
1661 			return NUMBER;
1662 		}
1663 		break;
1664 	case 'k':
1665 		if (!strcmp(tag, "key")) {
1666 			if (tagType == TAG_EMPTY) return SYNTAX_ERROR;
1667 			yylval->string = getString();
1668 			if (!yylval->string) {
1669 				return SYNTAX_ERROR;
1670 			}
1671 			if ((getTag(tag, &attributeCount, attributes, values) != TAG_END)
1672 			   || strcmp(tag, "key")) {
1673 				return SYNTAX_ERROR;
1674 			}
1675 			return KEY;
1676 		}
1677 		break;
1678 	case 'p':
1679 		if (!strcmp(tag, "plist")) {
1680 			freeObject(yylval);
1681 			goto top;
1682 		}
1683 		break;
1684 	case 's':
1685 		if (!strcmp(tag, "string")) {
1686 			if (tagType == TAG_EMPTY) {
1687 			    	yylval->string = (char *)malloc(1);
1688 			    	*yylval->string = 0;
1689 				return STRING;
1690 			}
1691 			yylval->string = getString();
1692 			if (!yylval->string) {
1693 				return SYNTAX_ERROR;
1694 			}
1695 			if ((getTag(tag, &attributeCount, attributes, values) != TAG_END)
1696 			   || strcmp(tag, "string")) {
1697 				return SYNTAX_ERROR;
1698 			}
1699 			return STRING;
1700 		}
1701 		if (!strcmp(tag, "set")) {
1702 			if (tagType == TAG_EMPTY) {
1703 				yylval->elements = NULL;
1704 				return SET;;
1705 			}
1706 			if (tagType == TAG_START) {
1707 				return '[';
1708 			} else {
1709 				return ']';
1710 			}
1711 		}
1712 		break;
1713 	case 't':
1714 		if (!strcmp(tag, "true")) {
1715 			if (tagType == TAG_EMPTY) {
1716 				yylval->number = 1;
1717 				return BOOLEAN;
1718 			}
1719 		}
1720 		break;
1721 
1722 	default:
1723 		// XXX should we ignore invalid tags?
1724 		return SYNTAX_ERROR;
1725 		break;
1726 	}
1727 
1728 	return 0;
1729 }
1730 
1731 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1732 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1733 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1734 
1735 // "java" like allocation, if this code hits a syntax error in the
1736 // the middle of the parsed string we just bail with pointers hanging
1737 // all over place, so this code helps keeps all together
1738 
1739 static object_t *objects = 0;
1740 static object_t *freeObjects = 0;
1741 
1742 object_t *
1743 newObject()
1744 {
1745 	object_t *o;
1746 
1747 	if (freeObjects) {
1748 		o = freeObjects;
1749 		freeObjects = freeObjects->next;
1750 	} else {
1751 		o = (object_t *)malloc(sizeof(object_t));
1752 		bzero(o, sizeof(object_t));
1753 		o->free = objects;
1754 		objects = o;
1755 	}
1756 
1757 	return o;
1758 }
1759 
1760 void
1761 freeObject(object_t *o)
1762 {
1763 	o->next = freeObjects;
1764 	freeObjects = o;
1765 }
1766 
1767 void
1768 cleanupObjects()
1769 {
1770 	object_t *t, *o = objects;
1771 
1772 	while (o) {
1773 		if (o->object) {
1774 			printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object);
1775 			o->object->release();
1776 		}
1777 		if (o->data) {
1778 			printf("OSUnserializeXML: freeing   object o=%x data=%x\n", (int)o, (int)o->data);
1779 			free(o->data);
1780 		}
1781 		if (o->key) {
1782 			printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key);
1783 			o->key->release();
1784 		}
1785 		if (o->string) {
1786 			printf("OSUnserializeXML: freeing   object o=%x string=%x\n", (int)o, (int)o->string);
1787 			free(o->string);
1788 		}
1789 
1790 		t = o;
1791 		o = o->free;
1792 		free(t);
1793 	}
1794 }
1795 
1796 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1797 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1798 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1799 
1800 static OSDictionary *tags;
1801 
1802 static void
1803 rememberObject(int tag, OSObject *o)
1804 {
1805 	char key[16];
1806 	sprintf(key, "%u", tag);
1807 
1808 //printf("remember key %s\n", key);
1809 
1810 	tags->setObject(key, o);
1811 }
1812 
1813 static object_t *
1814 retrieveObject(int tag)
1815 {
1816 	char key[16];
1817 	sprintf(key, "%u", tag);
1818 
1819 //printf("retrieve key '%s'\n", key);
1820 
1821 	OSObject *ref = tags->getObject(key);
1822 	if (!ref) return 0;
1823 
1824 	object_t *o = newObject();
1825 	o->object = ref;
1826 	return o;
1827 }
1828 
1829 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1830 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1831 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
1832 
1833 object_t *
1834 buildOSDictionary(object_t * header)
1835 {
1836 	object_t *o, *t;
1837 	int count = 0;
1838 
1839 	// get count and reverse order
1840 	o = header->elements;
1841 	header->elements = 0;
1842 	while (o) {
1843 		count++;
1844 		t = o;
1845 		o = o->next;
1846 
1847 		t->next = header->elements;
1848 		header->elements = t;
1849 	}
1850 
1851 	OSDictionary *d = OSDictionary::withCapacity(count);
1852 
1853 	if (header->idref >= 0) rememberObject(header->idref, d);
1854 
1855 	o = header->elements;
1856 	while (o) {
1857 		d->setObject(o->key, o->object);
1858 		o->object->release();
1859 		o->object = 0;
1860 		o->key->release();
1861 		o->key = 0;
1862 		t = o;
1863 		o = o->next;
1864 		freeObject(t);
1865 	}
1866 	o = header;
1867 	o->object = d;
1868 	return o;
1869 };
1870 
1871 object_t *
1872 buildOSArray(object_t * header)
1873 {
1874 	object_t *o, *t;
1875 	int count = 0;
1876 
1877 	// get count and reverse order
1878 	o = header->elements;
1879 	header->elements = 0;
1880 	while (o) {
1881 		count++;
1882 		t = o;
1883 		o = o->next;
1884 
1885 		t->next = header->elements;
1886 		header->elements = t;
1887 	}
1888 
1889 	OSArray *a = OSArray::withCapacity(count);
1890 
1891 	if (header->idref >= 0) rememberObject(header->idref, a);
1892 
1893 	o = header->elements;
1894 	while (o) {
1895 		a->setObject(o->object);
1896 		o->object->release();
1897 		o->object = 0;
1898 		t = o;
1899 		o = o->next;
1900 		freeObject(t);
1901 	}
1902 	o = header;
1903 	o->object = a;
1904 	return o;
1905 };
1906 
1907 object_t *
1908 buildOSSet(object_t *o)
1909 {
1910 	o = buildOSArray(o);
1911 	OSArray *a = (OSArray *)o->object;
1912 
1913 	OSSet *s = OSSet::withArray(a, a->getCapacity());
1914 
1915 	//write over reference created in array
1916 	if (o->idref >= 0) rememberObject(o->idref, s);
1917 
1918 	a->release();
1919 	o->object = s;
1920 	return o;
1921 };
1922 
1923 object_t *
1924 buildOSString(object_t *o)
1925 {
1926 	OSString *s = OSString::withCString(o->string);
1927 
1928 	if (o->idref >= 0) rememberObject(o->idref, s);
1929 
1930 	free(o->string);
1931 	o->string = 0;
1932 	o->object = s;
1933 
1934 	return o;
1935 };
1936 
1937 object_t *
1938 buildKey(object_t *o)
1939 {
1940 	const OSSymbol *s = OSSymbol::withCString(o->string);
1941 
1942 	free(o->string);
1943 	o->string = 0;
1944 	o->key = s;
1945 
1946 	return o;
1947 };
1948 
1949 object_t *
1950 buildOSData(object_t *o)
1951 {
1952 	OSData *d;
1953 
1954 	if (o->size) {
1955 		d = OSData::withBytes(o->data, o->size);
1956 		free(o->data);
1957 	} else {
1958 		d = OSData::withCapacity(0);
1959 	}
1960 	if (o->idref >= 0) rememberObject(o->idref, d);
1961 
1962 	o->data = 0;
1963 	o->object = d;
1964 	return o;
1965 };
1966 
1967 object_t *
1968 buildOSNumber(object_t *o)
1969 {
1970 	OSNumber *n = OSNumber::withNumber(o->number, o->size);
1971 
1972 	if (o->idref >= 0) rememberObject(o->idref, n);
1973 
1974 	o->object = n;
1975 	return o;
1976 };
1977 
1978 object_t *
1979 buildOSBoolean(object_t *o)
1980 {
1981 	OSBoolean *b = OSBoolean::withBoolean(o->number != 0);
1982 	o->object = b;
1983 	return o;
1984 };
1985 
1986 __BEGIN_DECLS
1987 #include <kern/lock.h>
1988 __END_DECLS
1989 
1990 static mutex_t *lock = 0;
1991 
1992 OSObject*
1993 OSUnserializeXML(const char *buffer, OSString **errorString)
1994 {
1995 	OSObject *object;
1996 
1997 	if (!lock) {
1998 		lock = mutex_alloc(ETAP_IO_AHA);
1999 		mutex_lock(lock);
2000 	} else {
2001 		mutex_lock(lock);
2002 
2003 	}
2004 
2005 	objects = 0;
2006 	freeObjects = 0;
2007 	yyerror_message[0] = 0;		//just in case
2008 	parseBuffer = buffer;
2009 	parseBufferIndex = 0;
2010 	tags = OSDictionary::withCapacity(128);
2011 	if (yyparse() == 0) {
2012 		object = parsedObject;
2013 		if (errorString) *errorString = 0;
2014 	} else {
2015 		object = 0;
2016 		if (errorString)
2017 			*errorString = OSString::withCString(yyerror_message);
2018 	}
2019 
2020 	cleanupObjects();
2021 	tags->release();
2022 	mutex_unlock(lock);
2023 
2024 	return object;
2025 }
2026 
2027 
2028 //
2029 //
2030 //
2031 //
2032 //
2033 //		 DO NOT EDIT OSUnserializeXML.cpp!
2034 //
2035 //			this means you!
2036 //
2037 //
2038 //
2039 //
2040 //
2041