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