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