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