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