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