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