]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSUnserializeXML.cpp
xnu-3789.31.2.tar.gz
[apple/xnu.git] / libkern / c++ / OSUnserializeXML.cpp
1 /*
2 * Copyright (c) 1999-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /*
30 * HISTORY
31 *
32 * OSUnserializeXML.y created by rsulack on Tue Oct 12 1999
33 */
34
35 // parser for unserializing OSContainer objects serialized to XML
36 //
37 // to build :
38 // bison -p OSUnserializeXML OSUnserializeXML.y
39 // head -50 OSUnserializeXML.y > OSUnserializeXML.cpp
40 // sed -e "s/#include <stdio.h>//" < OSUnserializeXML.tab.c >> OSUnserializeXML.cpp
41 //
42 // when changing code check in both OSUnserializeXML.y and OSUnserializeXML.cpp
43 //
44 //
45 //
46 //
47 //
48 // DO NOT EDIT OSUnserializeXML.cpp!
49 //
50 // this means you!
51 /* A Bison parser, made by GNU Bison 2.3. */
52
53 /* Skeleton implementation for Bison's Yacc-like parsers in C
54
55 Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
56 Free Software Foundation, Inc.
57
58 This program is free software; you can redistribute it and/or modify
59 it under the terms of the GNU General Public License as published by
60 the Free Software Foundation; either version 2, or (at your option)
61 any later version.
62
63 This program is distributed in the hope that it will be useful,
64 but WITHOUT ANY WARRANTY; without even the implied warranty of
65 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66 GNU General Public License for more details.
67
68 You should have received a copy of the GNU General Public License
69 along with this program; if not, write to the Free Software
70 Foundation, Inc., 51 Franklin Street, Fifth Floor,
71 Boston, MA 02110-1301, USA. */
72
73 /* As a special exception, you may create a larger work that contains
74 part or all of the Bison parser skeleton and distribute that work
75 under terms of your choice, so long as that work isn't itself a
76 parser generator using the skeleton or a modified version thereof
77 as a parser skeleton. Alternatively, if you modify or redistribute
78 the parser skeleton itself, you may (at your option) remove this
79 special exception, which will cause the skeleton and the resulting
80 Bison output files to be licensed under the GNU General Public
81 License without this special exception.
82
83 This special exception was added by the Free Software Foundation in
84 version 2.2 of Bison. */
85
86 /* C LALR(1) parser skeleton written by Richard Stallman, by
87 simplifying the original so-called "semantic" parser. */
88
89 /* All symbols defined below should begin with yy or YY, to avoid
90 infringing on user name space. This should be done even for local
91 variables, as they might otherwise be expanded by user macros.
92 There are some unavoidable exceptions within include files to
93 define necessary library symbols; they are noted "INFRINGES ON
94 USER NAME SPACE" below. */
95
96 /* Identify Bison output. */
97 #define YYBISON 1
98
99 /* Bison version. */
100 #define YYBISON_VERSION "2.3"
101
102 /* Skeleton name. */
103 #define YYSKELETON_NAME "yacc.c"
104
105 /* Pure parsers. */
106 #define YYPURE 1
107
108 /* Using locations. */
109 #define YYLSP_NEEDED 0
110
111 /* Substitute the variable and function names. */
112 #define yyparse OSUnserializeXMLparse
113 #define yylex OSUnserializeXMLlex
114 #define yyerror OSUnserializeXMLerror
115 #define yylval OSUnserializeXMLlval
116 #define yychar OSUnserializeXMLchar
117 #define yydebug OSUnserializeXMLdebug
118 #define yynerrs OSUnserializeXMLnerrs
119
120
121 /* Tokens. */
122 #ifndef YYTOKENTYPE
123 # define YYTOKENTYPE
124 /* Put the tokens into the symbol table, so that GDB and other debuggers
125 know about them. */
126 enum yytokentype {
127 ARRAY = 258,
128 BOOLEAN = 259,
129 DATA = 260,
130 DICTIONARY = 261,
131 IDREF = 262,
132 KEY = 263,
133 NUMBER = 264,
134 SET = 265,
135 STRING = 266,
136 SYNTAX_ERROR = 267
137 };
138 #endif
139 /* Tokens. */
140 #define ARRAY 258
141 #define BOOLEAN 259
142 #define DATA 260
143 #define DICTIONARY 261
144 #define IDREF 262
145 #define KEY 263
146 #define NUMBER 264
147 #define SET 265
148 #define STRING 266
149 #define SYNTAX_ERROR 267
150
151
152
153
154 /* Copy the first part of user declarations. */
155 #line 61 "OSUnserializeXML.y"
156
157 #include <string.h>
158 #include <libkern/c++/OSMetaClass.h>
159 #include <libkern/c++/OSContainers.h>
160 #include <libkern/c++/OSLib.h>
161
162 #define MAX_OBJECTS 65535
163
164 #define YYSTYPE object_t *
165 #define YYPARSE_PARAM state
166 #define YYLEX_PARAM (parser_state_t *)state
167
168 // this is the internal struct used to hold objects on parser stack
169 // it represents objects both before and after they have been created
170 typedef struct object {
171 struct object *next;
172 struct object *free;
173 struct object *elements;
174 OSObject *object;
175 OSSymbol *key; // for dictionary
176 int size;
177 void *data; // for data
178 char *string; // for string & symbol
179 long long number; // for number
180 int idref;
181 } object_t;
182
183 // this code is reentrant, this structure contains all
184 // state information for the parsing of a single buffer
185 typedef struct parser_state {
186 const char *parseBuffer; // start of text to be parsed
187 int parseBufferIndex; // current index into text
188 int lineNumber; // current line number
189 object_t *objects; // internal objects in use
190 object_t *freeObjects; // internal objects that are free
191 OSDictionary *tags; // used to remember "ID" tags
192 OSString **errorString; // parse error with line
193 OSObject *parsedObject; // resultant object of parsed text
194 int parsedObjectCount;
195 } parser_state_t;
196
197 #define STATE ((parser_state_t *)state)
198
199 #undef yyerror
200 #define yyerror(s) OSUnserializeerror(STATE, (s))
201 static int OSUnserializeerror(parser_state_t *state, const char *s);
202
203 static int yylex(YYSTYPE *lvalp, parser_state_t *state);
204
205 static object_t *newObject(parser_state_t *state);
206 static void freeObject(parser_state_t *state, object_t *o);
207 static void rememberObject(parser_state_t *state, int tag, OSObject *o);
208 static object_t *retrieveObject(parser_state_t *state, int tag);
209 static void cleanupObjects(parser_state_t *state);
210
211 static object_t *buildDictionary(parser_state_t *state, object_t *o);
212 static object_t *buildArray(parser_state_t *state, object_t *o);
213 static object_t *buildSet(parser_state_t *state, object_t *o);
214 static object_t *buildString(parser_state_t *state, object_t *o);
215 static object_t *buildSymbol(parser_state_t *state, object_t *o);
216 static object_t *buildData(parser_state_t *state, object_t *o);
217 static object_t *buildNumber(parser_state_t *state, object_t *o);
218 static object_t *buildBoolean(parser_state_t *state, object_t *o);
219
220 extern "C" {
221 extern void *kern_os_malloc(size_t size);
222 extern void *kern_os_realloc(void * addr, size_t size);
223 extern void kern_os_free(void * addr);
224
225 } /* extern "C" */
226
227 #define malloc(s) kern_os_malloc(s)
228 #define realloc(a, s) kern_os_realloc(a, s)
229 #define free(a) kern_os_free((void *)a)
230
231
232
233 /* Enabling traces. */
234 #ifndef YYDEBUG
235 # define YYDEBUG 0
236 #endif
237
238 /* Enabling verbose error messages. */
239 #ifdef YYERROR_VERBOSE
240 # undef YYERROR_VERBOSE
241 # define YYERROR_VERBOSE 1
242 #else
243 # define YYERROR_VERBOSE 0
244 #endif
245
246 /* Enabling the token table. */
247 #ifndef YYTOKEN_TABLE
248 # define YYTOKEN_TABLE 0
249 #endif
250
251 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
252 typedef int YYSTYPE;
253 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
254 # define YYSTYPE_IS_DECLARED 1
255 # define YYSTYPE_IS_TRIVIAL 1
256 #endif
257
258
259
260 /* Copy the second part of user declarations. */
261
262
263 /* Line 216 of yacc.c. */
264 #line 215 "OSUnserializeXML.tab.c"
265
266 #ifdef short
267 # undef short
268 #endif
269
270 #ifdef YYTYPE_UINT8
271 typedef YYTYPE_UINT8 yytype_uint8;
272 #else
273 typedef unsigned char yytype_uint8;
274 #endif
275
276 #ifdef YYTYPE_INT8
277 typedef YYTYPE_INT8 yytype_int8;
278 #elif (defined __STDC__ || defined __C99__FUNC__ \
279 || defined __cplusplus || defined _MSC_VER)
280 typedef signed char yytype_int8;
281 #else
282 typedef short int yytype_int8;
283 #endif
284
285 #ifdef YYTYPE_UINT16
286 typedef YYTYPE_UINT16 yytype_uint16;
287 #else
288 typedef unsigned short int yytype_uint16;
289 #endif
290
291 #ifdef YYTYPE_INT16
292 typedef YYTYPE_INT16 yytype_int16;
293 #else
294 typedef short int yytype_int16;
295 #endif
296
297 #ifndef YYSIZE_T
298 # ifdef __SIZE_TYPE__
299 # define YYSIZE_T __SIZE_TYPE__
300 # elif defined size_t
301 # define YYSIZE_T size_t
302 # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
303 || defined __cplusplus || defined _MSC_VER)
304 # include <stddef.h> /* INFRINGES ON USER NAME SPACE */
305 # define YYSIZE_T size_t
306 # else
307 # define YYSIZE_T unsigned int
308 # endif
309 #endif
310
311 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
312
313 #ifndef YY_
314 # if defined YYENABLE_NLS && YYENABLE_NLS
315 # if ENABLE_NLS
316 # include <libintl.h> /* INFRINGES ON USER NAME SPACE */
317 # define YY_(msgid) dgettext ("bison-runtime", msgid)
318 # endif
319 # endif
320 # ifndef YY_
321 # define YY_(msgid) msgid
322 # endif
323 #endif
324
325 /* Suppress unused-variable warnings by "using" E. */
326 #if ! defined lint || defined __GNUC__
327 # define YYUSE(e) ((void) (e))
328 #else
329 # define YYUSE(e) /* empty */
330 #endif
331
332 /* Identity function, used to suppress warnings about constant conditions. */
333 #ifndef lint
334 # define YYID(n) (n)
335 #else
336 #if (defined __STDC__ || defined __C99__FUNC__ \
337 || defined __cplusplus || defined _MSC_VER)
338 static int
339 YYID (int i)
340 #else
341 static int
342 YYID (i)
343 int i;
344 #endif
345 {
346 return i;
347 }
348 #endif
349
350 #if ! defined yyoverflow || YYERROR_VERBOSE
351
352 /* The parser invokes alloca or malloc; define the necessary symbols. */
353
354 # ifdef YYSTACK_USE_ALLOCA
355 # if YYSTACK_USE_ALLOCA
356 # ifdef __GNUC__
357 # define YYSTACK_ALLOC __builtin_alloca
358 # elif defined __BUILTIN_VA_ARG_INCR
359 # include <alloca.h> /* INFRINGES ON USER NAME SPACE */
360 # elif defined _AIX
361 # define YYSTACK_ALLOC __alloca
362 # elif defined _MSC_VER
363 # include <malloc.h> /* INFRINGES ON USER NAME SPACE */
364 # define alloca _alloca
365 # else
366 # define YYSTACK_ALLOC alloca
367 # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
368 || defined __cplusplus || defined _MSC_VER)
369 # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
370 # ifndef _STDLIB_H
371 # define _STDLIB_H 1
372 # endif
373 # endif
374 # endif
375 # endif
376 # endif
377
378 # ifdef YYSTACK_ALLOC
379 /* Pacify GCC's `empty if-body' warning. */
380 # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
381 # ifndef YYSTACK_ALLOC_MAXIMUM
382 /* The OS might guarantee only one guard page at the bottom of the stack,
383 and a page size can be as small as 4096 bytes. So we cannot safely
384 invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
385 to allow for a few compiler-allocated temporary stack slots. */
386 # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
387 # endif
388 # else
389 # define YYSTACK_ALLOC YYMALLOC
390 # define YYSTACK_FREE YYFREE
391 # ifndef YYSTACK_ALLOC_MAXIMUM
392 # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
393 # endif
394 # if (defined __cplusplus && ! defined _STDLIB_H \
395 && ! ((defined YYMALLOC || defined malloc) \
396 && (defined YYFREE || defined free)))
397 # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
398 # ifndef _STDLIB_H
399 # define _STDLIB_H 1
400 # endif
401 # endif
402 # ifndef YYMALLOC
403 # define YYMALLOC malloc
404 # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
405 || defined __cplusplus || defined _MSC_VER)
406 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
407 # endif
408 # endif
409 # ifndef YYFREE
410 # define YYFREE free
411 # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
412 || defined __cplusplus || defined _MSC_VER)
413 void free (void *); /* INFRINGES ON USER NAME SPACE */
414 # endif
415 # endif
416 # endif
417 #endif /* ! defined yyoverflow || YYERROR_VERBOSE */
418
419
420 #if (! defined yyoverflow \
421 && (! defined __cplusplus \
422 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
423
424 /* A type that is properly aligned for any stack member. */
425 union yyalloc
426 {
427 yytype_int16 yyss;
428 YYSTYPE yyvs;
429 };
430
431 /* The size of the maximum gap between one aligned stack and the next. */
432 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
433
434 /* The size of an array large to enough to hold all stacks, each with
435 N elements. */
436 # define YYSTACK_BYTES(N) \
437 ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
438 + YYSTACK_GAP_MAXIMUM)
439
440 /* Copy COUNT objects from FROM to TO. The source and destination do
441 not overlap. */
442 # ifndef YYCOPY
443 # if defined __GNUC__ && 1 < __GNUC__
444 # define YYCOPY(To, From, Count) \
445 __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
446 # else
447 # define YYCOPY(To, From, Count) \
448 do \
449 { \
450 YYSIZE_T yyi; \
451 for (yyi = 0; yyi < (Count); yyi++) \
452 (To)[yyi] = (From)[yyi]; \
453 } \
454 while (YYID (0))
455 # endif
456 # endif
457
458 /* Relocate STACK from its old location to the new one. The
459 local variables YYSIZE and YYSTACKSIZE give the old and new number of
460 elements in the stack, and YYPTR gives the new location of the
461 stack. Advance YYPTR to a properly aligned location for the next
462 stack. */
463 # define YYSTACK_RELOCATE(Stack) \
464 do \
465 { \
466 YYSIZE_T yynewbytes; \
467 YYCOPY (&yyptr->Stack, Stack, yysize); \
468 Stack = &yyptr->Stack; \
469 yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
470 yyptr += yynewbytes / sizeof (*yyptr); \
471 } \
472 while (YYID (0))
473
474 #endif
475
476 /* YYFINAL -- State number of the termination state. */
477 #define YYFINAL 33
478 /* YYLAST -- Last index in YYTABLE. */
479 #define YYLAST 108
480
481 /* YYNTOKENS -- Number of terminals. */
482 #define YYNTOKENS 19
483 /* YYNNTS -- Number of nonterminals. */
484 #define YYNNTS 15
485 /* YYNRULES -- Number of rules. */
486 #define YYNRULES 32
487 /* YYNRULES -- Number of states. */
488 #define YYNSTATES 40
489
490 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
491 #define YYUNDEFTOK 2
492 #define YYMAXUTOK 267
493
494 #define YYTRANSLATE(YYX) \
495 ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
496
497 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
498 static const yytype_uint8 yytranslate[] =
499 {
500 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
501 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
502 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
503 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
504 15, 16, 2, 2, 2, 2, 2, 2, 2, 2,
505 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
506 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
507 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
508 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
509 2, 17, 2, 18, 2, 2, 2, 2, 2, 2,
510 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
511 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
512 2, 2, 2, 13, 2, 14, 2, 2, 2, 2,
513 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
514 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
515 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
516 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
517 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
518 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
519 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
520 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
521 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
522 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
523 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
524 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
525 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
526 5, 6, 7, 8, 9, 10, 11, 12
527 };
528
529 #if YYDEBUG
530 /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
531 YYRHS. */
532 static const yytype_uint8 yyprhs[] =
533 {
534 0, 0, 3, 4, 6, 8, 10, 12, 14, 16,
535 18, 20, 22, 24, 27, 31, 33, 35, 38, 41,
536 43, 46, 50, 52, 55, 59, 61, 63, 66, 68,
537 70, 72, 74
538 };
539
540 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
541 static const yytype_int8 yyrhs[] =
542 {
543 20, 0, -1, -1, 21, -1, 12, -1, 22, -1,
544 26, -1, 27, -1, 33, -1, 30, -1, 32, -1,
545 29, -1, 31, -1, 13, 14, -1, 13, 23, 14,
546 -1, 6, -1, 24, -1, 23, 24, -1, 25, 21,
547 -1, 8, -1, 15, 16, -1, 15, 28, 16, -1,
548 3, -1, 17, 18, -1, 17, 28, 18, -1, 10,
549 -1, 21, -1, 28, 21, -1, 4, -1, 5, -1,
550 7, -1, 9, -1, 11, -1
551 };
552
553 /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
554 static const yytype_uint16 yyrline[] =
555 {
556 0, 149, 149, 152, 157, 162, 174, 186, 198, 210,
557 222, 234, 246, 265, 268, 271, 274, 275, 290, 299,
558 311, 314, 317, 320, 323, 326, 329, 332, 339, 342,
559 345, 348, 351
560 };
561 #endif
562
563 #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
564 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
565 First, the terminals, then, starting at YYNTOKENS, nonterminals. */
566 static const char *const yytname[] =
567 {
568 "$end", "error", "$undefined", "ARRAY", "BOOLEAN", "DATA", "DICTIONARY",
569 "IDREF", "KEY", "NUMBER", "SET", "STRING", "SYNTAX_ERROR", "'{'", "'}'",
570 "'('", "')'", "'['", "']'", "$accept", "input", "object", "dict",
571 "pairs", "pair", "key", "array", "set", "elements", "boolean", "data",
572 "idref", "number", "string", 0
573 };
574 #endif
575
576 # ifdef YYPRINT
577 /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
578 token YYLEX-NUM. */
579 static const yytype_uint16 yytoknum[] =
580 {
581 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
582 265, 266, 267, 123, 125, 40, 41, 91, 93
583 };
584 # endif
585
586 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
587 static const yytype_uint8 yyr1[] =
588 {
589 0, 19, 20, 20, 20, 21, 21, 21, 21, 21,
590 21, 21, 21, 22, 22, 22, 23, 23, 24, 25,
591 26, 26, 26, 27, 27, 27, 28, 28, 29, 30,
592 31, 32, 33
593 };
594
595 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
596 static const yytype_uint8 yyr2[] =
597 {
598 0, 2, 0, 1, 1, 1, 1, 1, 1, 1,
599 1, 1, 1, 2, 3, 1, 1, 2, 2, 1,
600 2, 3, 1, 2, 3, 1, 1, 2, 1, 1,
601 1, 1, 1
602 };
603
604 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
605 STATE-NUM when YYTABLE doesn't specify something else to do. Zero
606 means the default is an error. */
607 static const yytype_uint8 yydefact[] =
608 {
609 2, 22, 28, 29, 15, 30, 31, 25, 32, 4,
610 0, 0, 0, 0, 3, 5, 6, 7, 11, 9,
611 12, 10, 8, 19, 13, 0, 16, 0, 20, 26,
612 0, 23, 0, 1, 14, 17, 18, 21, 27, 24
613 };
614
615 /* YYDEFGOTO[NTERM-NUM]. */
616 static const yytype_int8 yydefgoto[] =
617 {
618 -1, 13, 29, 15, 25, 26, 27, 16, 17, 30,
619 18, 19, 20, 21, 22
620 };
621
622 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
623 STATE-NUM. */
624 #define YYPACT_NINF -20
625 static const yytype_int8 yypact[] =
626 {
627 46, -20, -20, -20, -20, -20, -20, -20, -20, -20,
628 4, 61, -2, 10, -20, -20, -20, -20, -20, -20,
629 -20, -20, -20, -20, -20, 6, -20, 91, -20, -20,
630 76, -20, 30, -20, -20, -20, -20, -20, -20, -20
631 };
632
633 /* YYPGOTO[NTERM-NUM]. */
634 static const yytype_int8 yypgoto[] =
635 {
636 -20, -20, 0, -20, -20, -19, -20, -20, -20, 5,
637 -20, -20, -20, -20, -20
638 };
639
640 /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
641 positive, shift that token. If negative, reduce the rule which
642 number is the opposite. If zero, do what YYDEFACT says.
643 If YYTABLE_NINF, syntax error. */
644 #define YYTABLE_NINF -1
645 static const yytype_uint8 yytable[] =
646 {
647 14, 1, 2, 3, 4, 5, 35, 6, 7, 8,
648 33, 10, 23, 11, 23, 12, 31, 32, 24, 0,
649 34, 0, 0, 0, 0, 0, 0, 36, 0, 0,
650 38, 0, 38, 1, 2, 3, 4, 5, 0, 6,
651 7, 8, 0, 10, 0, 11, 0, 12, 39, 1,
652 2, 3, 4, 5, 0, 6, 7, 8, 9, 10,
653 0, 11, 0, 12, 1, 2, 3, 4, 5, 0,
654 6, 7, 8, 0, 10, 0, 11, 28, 12, 1,
655 2, 3, 4, 5, 0, 6, 7, 8, 0, 10,
656 0, 11, 37, 12, 1, 2, 3, 4, 5, 0,
657 6, 7, 8, 0, 10, 0, 11, 0, 12
658 };
659
660 static const yytype_int8 yycheck[] =
661 {
662 0, 3, 4, 5, 6, 7, 25, 9, 10, 11,
663 0, 13, 8, 15, 8, 17, 18, 12, 14, -1,
664 14, -1, -1, -1, -1, -1, -1, 27, -1, -1,
665 30, -1, 32, 3, 4, 5, 6, 7, -1, 9,
666 10, 11, -1, 13, -1, 15, -1, 17, 18, 3,
667 4, 5, 6, 7, -1, 9, 10, 11, 12, 13,
668 -1, 15, -1, 17, 3, 4, 5, 6, 7, -1,
669 9, 10, 11, -1, 13, -1, 15, 16, 17, 3,
670 4, 5, 6, 7, -1, 9, 10, 11, -1, 13,
671 -1, 15, 16, 17, 3, 4, 5, 6, 7, -1,
672 9, 10, 11, -1, 13, -1, 15, -1, 17
673 };
674
675 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
676 symbol of state STATE-NUM. */
677 static const yytype_uint8 yystos[] =
678 {
679 0, 3, 4, 5, 6, 7, 9, 10, 11, 12,
680 13, 15, 17, 20, 21, 22, 26, 27, 29, 30,
681 31, 32, 33, 8, 14, 23, 24, 25, 16, 21,
682 28, 18, 28, 0, 14, 24, 21, 16, 21, 18
683 };
684
685 #define yyerrok (yyerrstatus = 0)
686 #define yyclearin (yychar = YYEMPTY)
687 #define YYEMPTY (-2)
688 #define YYEOF 0
689
690 #define YYACCEPT goto yyacceptlab
691 #define YYABORT goto yyabortlab
692 #define YYERROR goto yyerrorlab
693
694
695 /* Like YYERROR except do call yyerror. This remains here temporarily
696 to ease the transition to the new meaning of YYERROR, for GCC.
697 Once GCC version 2 has supplanted version 1, this can go. */
698
699 #define YYFAIL goto yyerrlab
700
701 #define YYRECOVERING() (!!yyerrstatus)
702
703 #define YYBACKUP(Token, Value) \
704 do \
705 if (yychar == YYEMPTY && yylen == 1) \
706 { \
707 yychar = (Token); \
708 yylval = (Value); \
709 yytoken = YYTRANSLATE (yychar); \
710 YYPOPSTACK (1); \
711 goto yybackup; \
712 } \
713 else \
714 { \
715 yyerror (YY_("syntax error: cannot back up")); \
716 YYERROR; \
717 } \
718 while (YYID (0))
719
720
721 #define YYTERROR 1
722 #define YYERRCODE 256
723
724
725 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
726 If N is 0, then set CURRENT to the empty location which ends
727 the previous symbol: RHS[0] (always defined). */
728
729 #define YYRHSLOC(Rhs, K) ((Rhs)[K])
730 #ifndef YYLLOC_DEFAULT
731 # define YYLLOC_DEFAULT(Current, Rhs, N) \
732 do \
733 if (YYID (N)) \
734 { \
735 (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
736 (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
737 (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
738 (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
739 } \
740 else \
741 { \
742 (Current).first_line = (Current).last_line = \
743 YYRHSLOC (Rhs, 0).last_line; \
744 (Current).first_column = (Current).last_column = \
745 YYRHSLOC (Rhs, 0).last_column; \
746 } \
747 while (YYID (0))
748 #endif
749
750
751 /* YY_LOCATION_PRINT -- Print the location on the stream.
752 This macro was not mandated originally: define only if we know
753 we won't break user code: when these are the locations we know. */
754
755 #ifndef YY_LOCATION_PRINT
756 # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
757 # define YY_LOCATION_PRINT(File, Loc) \
758 fprintf (File, "%d.%d-%d.%d", \
759 (Loc).first_line, (Loc).first_column, \
760 (Loc).last_line, (Loc).last_column)
761 # else
762 # define YY_LOCATION_PRINT(File, Loc) ((void) 0)
763 # endif
764 #endif
765
766
767 /* YYLEX -- calling `yylex' with the right arguments. */
768
769 #ifdef YYLEX_PARAM
770 # define YYLEX yylex (&yylval, YYLEX_PARAM)
771 #else
772 # define YYLEX yylex (&yylval)
773 #endif
774
775 /* Enable debugging if requested. */
776 #if YYDEBUG
777
778 # ifndef YYFPRINTF
779 # include <stdio.h> /* INFRINGES ON USER NAME SPACE */
780 # define YYFPRINTF fprintf
781 # endif
782
783 # define YYDPRINTF(Args) \
784 do { \
785 if (yydebug) \
786 YYFPRINTF Args; \
787 } while (YYID (0))
788
789 # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
790 do { \
791 if (yydebug) \
792 { \
793 YYFPRINTF (stderr, "%s ", Title); \
794 yy_symbol_print (stderr, \
795 Type, Value); \
796 YYFPRINTF (stderr, "\n"); \
797 } \
798 } while (YYID (0))
799
800
801 /*--------------------------------.
802 | Print this symbol on YYOUTPUT. |
803 `--------------------------------*/
804
805 /*ARGSUSED*/
806 #if (defined __STDC__ || defined __C99__FUNC__ \
807 || defined __cplusplus || defined _MSC_VER)
808 static void
809 yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
810 #else
811 static void
812 yy_symbol_value_print (yyoutput, yytype, yyvaluep)
813 FILE *yyoutput;
814 int yytype;
815 YYSTYPE const * const yyvaluep;
816 #endif
817 {
818 if (!yyvaluep)
819 return;
820 # ifdef YYPRINT
821 if (yytype < YYNTOKENS)
822 YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
823 # else
824 YYUSE (yyoutput);
825 # endif
826 switch (yytype)
827 {
828 default:
829 break;
830 }
831 }
832
833
834 /*--------------------------------.
835 | Print this symbol on YYOUTPUT. |
836 `--------------------------------*/
837
838 #if (defined __STDC__ || defined __C99__FUNC__ \
839 || defined __cplusplus || defined _MSC_VER)
840 static void
841 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
842 #else
843 static void
844 yy_symbol_print (yyoutput, yytype, yyvaluep)
845 FILE *yyoutput;
846 int yytype;
847 YYSTYPE const * const yyvaluep;
848 #endif
849 {
850 if (yytype < YYNTOKENS)
851 YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
852 else
853 YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
854
855 yy_symbol_value_print (yyoutput, yytype, yyvaluep);
856 YYFPRINTF (yyoutput, ")");
857 }
858
859 /*------------------------------------------------------------------.
860 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
861 | TOP (included). |
862 `------------------------------------------------------------------*/
863
864 #if (defined __STDC__ || defined __C99__FUNC__ \
865 || defined __cplusplus || defined _MSC_VER)
866 static void
867 yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
868 #else
869 static void
870 yy_stack_print (bottom, top)
871 yytype_int16 *bottom;
872 yytype_int16 *top;
873 #endif
874 {
875 YYFPRINTF (stderr, "Stack now");
876 for (; bottom <= top; ++bottom)
877 YYFPRINTF (stderr, " %d", *bottom);
878 YYFPRINTF (stderr, "\n");
879 }
880
881 # define YY_STACK_PRINT(Bottom, Top) \
882 do { \
883 if (yydebug) \
884 yy_stack_print ((Bottom), (Top)); \
885 } while (YYID (0))
886
887
888 /*------------------------------------------------.
889 | Report that the YYRULE is going to be reduced. |
890 `------------------------------------------------*/
891
892 #if (defined __STDC__ || defined __C99__FUNC__ \
893 || defined __cplusplus || defined _MSC_VER)
894 static void
895 yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
896 #else
897 static void
898 yy_reduce_print (yyvsp, yyrule)
899 YYSTYPE *yyvsp;
900 int yyrule;
901 #endif
902 {
903 int yynrhs = yyr2[yyrule];
904 int yyi;
905 unsigned long int yylno = yyrline[yyrule];
906 YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
907 yyrule - 1, yylno);
908 /* The symbols being reduced. */
909 for (yyi = 0; yyi < yynrhs; yyi++)
910 {
911 fprintf (stderr, " $%d = ", yyi + 1);
912 yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
913 &(yyvsp[(yyi + 1) - (yynrhs)])
914 );
915 fprintf (stderr, "\n");
916 }
917 }
918
919 # define YY_REDUCE_PRINT(Rule) \
920 do { \
921 if (yydebug) \
922 yy_reduce_print (yyvsp, Rule); \
923 } while (YYID (0))
924
925 /* Nonzero means print parse trace. It is left uninitialized so that
926 multiple parsers can coexist. */
927 int yydebug;
928 #else /* !YYDEBUG */
929 # define YYDPRINTF(Args)
930 # define YY_SYMBOL_PRINT(Title, Type, Value, Location)
931 # define YY_STACK_PRINT(Bottom, Top)
932 # define YY_REDUCE_PRINT(Rule)
933 #endif /* !YYDEBUG */
934
935
936 /* YYINITDEPTH -- initial size of the parser's stacks. */
937 #ifndef YYINITDEPTH
938 # define YYINITDEPTH 64
939 #endif
940
941 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
942 if the built-in stack extension method is used).
943
944 Do not make this value too large; the results are undefined if
945 YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
946 evaluated with infinite-precision integer arithmetic. */
947
948 #ifndef YYMAXDEPTH
949 # define YYMAXDEPTH 10000
950 #endif
951
952 \f
953
954 #if YYERROR_VERBOSE
955
956 # ifndef yystrlen
957 # if defined __GLIBC__ && defined _STRING_H
958 # define yystrlen strlen
959 # else
960 /* Return the length of YYSTR. */
961 #if (defined __STDC__ || defined __C99__FUNC__ \
962 || defined __cplusplus || defined _MSC_VER)
963 static YYSIZE_T
964 yystrlen (const char *yystr)
965 #else
966 static YYSIZE_T
967 yystrlen (yystr)
968 const char *yystr;
969 #endif
970 {
971 YYSIZE_T yylen;
972 for (yylen = 0; yystr[yylen]; yylen++)
973 continue;
974 return yylen;
975 }
976 # endif
977 # endif
978
979 # ifndef yystpcpy
980 # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
981 # define yystpcpy stpcpy
982 # else
983 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
984 YYDEST. */
985 #if (defined __STDC__ || defined __C99__FUNC__ \
986 || defined __cplusplus || defined _MSC_VER)
987 static char *
988 yystpcpy (char *yydest, const char *yysrc)
989 #else
990 static char *
991 yystpcpy (yydest, yysrc)
992 char *yydest;
993 const char *yysrc;
994 #endif
995 {
996 char *yyd = yydest;
997 const char *yys = yysrc;
998
999 while ((*yyd++ = *yys++) != '\0')
1000 continue;
1001
1002 return yyd - 1;
1003 }
1004 # endif
1005 # endif
1006
1007 # ifndef yytnamerr
1008 /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
1009 quotes and backslashes, so that it's suitable for yyerror. The
1010 heuristic is that double-quoting is unnecessary unless the string
1011 contains an apostrophe, a comma, or backslash (other than
1012 backslash-backslash). YYSTR is taken from yytname. If YYRES is
1013 null, do not copy; instead, return the length of what the result
1014 would have been. */
1015 static YYSIZE_T
1016 yytnamerr (char *yyres, const char *yystr)
1017 {
1018 if (*yystr == '"')
1019 {
1020 YYSIZE_T yyn = 0;
1021 char const *yyp = yystr;
1022
1023 for (;;)
1024 switch (*++yyp)
1025 {
1026 case '\'':
1027 case ',':
1028 goto do_not_strip_quotes;
1029
1030 case '\\':
1031 if (*++yyp != '\\')
1032 goto do_not_strip_quotes;
1033 /* Fall through. */
1034 default:
1035 if (yyres)
1036 yyres[yyn] = *yyp;
1037 yyn++;
1038 break;
1039
1040 case '"':
1041 if (yyres)
1042 yyres[yyn] = '\0';
1043 return yyn;
1044 }
1045 do_not_strip_quotes: ;
1046 }
1047
1048 if (! yyres)
1049 return yystrlen (yystr);
1050
1051 return yystpcpy (yyres, yystr) - yyres;
1052 }
1053 # endif
1054
1055 /* Copy into YYRESULT an error message about the unexpected token
1056 YYCHAR while in state YYSTATE. Return the number of bytes copied,
1057 including the terminating null byte. If YYRESULT is null, do not
1058 copy anything; just return the number of bytes that would be
1059 copied. As a special case, return 0 if an ordinary "syntax error"
1060 message will do. Return YYSIZE_MAXIMUM if overflow occurs during
1061 size calculation. */
1062 static YYSIZE_T
1063 yysyntax_error (char *yyresult, int yystate, int yychar)
1064 {
1065 int yyn = yypact[yystate];
1066
1067 if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
1068 return 0;
1069 else
1070 {
1071 int yytype = YYTRANSLATE (yychar);
1072 YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
1073 YYSIZE_T yysize = yysize0;
1074 YYSIZE_T yysize1;
1075 int yysize_overflow = 0;
1076 enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
1077 char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
1078 int yyx;
1079
1080 # if 0
1081 /* This is so xgettext sees the translatable formats that are
1082 constructed on the fly. */
1083 YY_("syntax error, unexpected %s");
1084 YY_("syntax error, unexpected %s, expecting %s");
1085 YY_("syntax error, unexpected %s, expecting %s or %s");
1086 YY_("syntax error, unexpected %s, expecting %s or %s or %s");
1087 YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
1088 # endif
1089 char *yyfmt;
1090 char const *yyf;
1091 static char const yyunexpected[] = "syntax error, unexpected %s";
1092 static char const yyexpecting[] = ", expecting %s";
1093 static char const yyor[] = " or %s";
1094 char yyformat[sizeof yyunexpected
1095 + sizeof yyexpecting - 1
1096 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
1097 * (sizeof yyor - 1))];
1098 char const *yyprefix = yyexpecting;
1099
1100 /* Start YYX at -YYN if negative to avoid negative indexes in
1101 YYCHECK. */
1102 int yyxbegin = yyn < 0 ? -yyn : 0;
1103
1104 /* Stay within bounds of both yycheck and yytname. */
1105 int yychecklim = YYLAST - yyn + 1;
1106 int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
1107 int yycount = 1;
1108
1109 yyarg[0] = yytname[yytype];
1110 yyfmt = yystpcpy (yyformat, yyunexpected);
1111
1112 for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1113 if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1114 {
1115 if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
1116 {
1117 yycount = 1;
1118 yysize = yysize0;
1119 yyformat[sizeof yyunexpected - 1] = '\0';
1120 break;
1121 }
1122 yyarg[yycount++] = yytname[yyx];
1123 yysize1 = yysize + yytnamerr (0, yytname[yyx]);
1124 yysize_overflow |= (yysize1 < yysize);
1125 yysize = yysize1;
1126 yyfmt = yystpcpy (yyfmt, yyprefix);
1127 yyprefix = yyor;
1128 }
1129
1130 yyf = YY_(yyformat);
1131 yysize1 = yysize + yystrlen (yyf);
1132 yysize_overflow |= (yysize1 < yysize);
1133 yysize = yysize1;
1134
1135 if (yysize_overflow)
1136 return YYSIZE_MAXIMUM;
1137
1138 if (yyresult)
1139 {
1140 /* Avoid sprintf, as that infringes on the user's name space.
1141 Don't have undefined behavior even if the translation
1142 produced a string with the wrong number of "%s"s. */
1143 char *yyp = yyresult;
1144 int yyi = 0;
1145 while ((*yyp = *yyf) != '\0')
1146 {
1147 if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
1148 {
1149 yyp += yytnamerr (yyp, yyarg[yyi++]);
1150 yyf += 2;
1151 }
1152 else
1153 {
1154 yyp++;
1155 yyf++;
1156 }
1157 }
1158 }
1159 return yysize;
1160 }
1161 }
1162 #endif /* YYERROR_VERBOSE */
1163 \f
1164
1165 /*-----------------------------------------------.
1166 | Release the memory associated to this symbol. |
1167 `-----------------------------------------------*/
1168
1169 /*ARGSUSED*/
1170 #if (defined __STDC__ || defined __C99__FUNC__ \
1171 || defined __cplusplus || defined _MSC_VER)
1172 static void
1173 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
1174 #else
1175 static void
1176 yydestruct (yymsg, yytype, yyvaluep)
1177 const char *yymsg;
1178 int yytype;
1179 YYSTYPE *yyvaluep;
1180 #endif
1181 {
1182 YYUSE (yyvaluep);
1183
1184 if (!yymsg)
1185 yymsg = "Deleting";
1186 YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
1187
1188 switch (yytype)
1189 {
1190
1191 default:
1192 break;
1193 }
1194 }
1195 \f
1196
1197 /* Prevent warnings from -Wmissing-prototypes. */
1198
1199 #ifdef YYPARSE_PARAM
1200 #if defined __STDC__ || defined __cplusplus
1201 int yyparse (void *YYPARSE_PARAM);
1202 #else
1203 int yyparse ();
1204 #endif
1205 #else /* ! YYPARSE_PARAM */
1206 #if defined __STDC__ || defined __cplusplus
1207 int yyparse (void);
1208 #else
1209 int yyparse ();
1210 #endif
1211 #endif /* ! YYPARSE_PARAM */
1212
1213
1214
1215
1216
1217
1218 /*----------.
1219 | yyparse. |
1220 `----------*/
1221
1222 #ifdef YYPARSE_PARAM
1223 #if (defined __STDC__ || defined __C99__FUNC__ \
1224 || defined __cplusplus || defined _MSC_VER)
1225 int
1226 yyparse (void *YYPARSE_PARAM)
1227 #else
1228 int
1229 yyparse (YYPARSE_PARAM)
1230 void *YYPARSE_PARAM;
1231 #endif
1232 #else /* ! YYPARSE_PARAM */
1233 #if (defined __STDC__ || defined __C99__FUNC__ \
1234 || defined __cplusplus || defined _MSC_VER)
1235 int
1236 yyparse (void)
1237 #else
1238 int
1239 yyparse ()
1240
1241 #endif
1242 #endif
1243 {
1244 /* The look-ahead symbol. */
1245 int yychar;
1246
1247 /* The semantic value of the look-ahead symbol. */
1248 YYSTYPE yylval;
1249
1250 /* Number of syntax errors so far. */
1251 int yynerrs;
1252
1253 int yystate;
1254 int yyn;
1255 int yyresult;
1256 /* Number of tokens to shift before error messages enabled. */
1257 int yyerrstatus;
1258 /* Look-ahead token as an internal (translated) token number. */
1259 int yytoken = 0;
1260 #if YYERROR_VERBOSE
1261 /* Buffer for error messages, and its allocated size. */
1262 char yymsgbuf[128];
1263 char *yymsg = yymsgbuf;
1264 YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
1265 #endif
1266
1267 /* Three stacks and their tools:
1268 `yyss': related to states,
1269 `yyvs': related to semantic values,
1270 `yyls': related to locations.
1271
1272 Refer to the stacks thru separate pointers, to allow yyoverflow
1273 to reallocate them elsewhere. */
1274
1275 /* The state stack. */
1276 yytype_int16 yyssa[YYINITDEPTH];
1277 yytype_int16 *yyss = yyssa;
1278 yytype_int16 *yyssp;
1279
1280 /* The semantic value stack. */
1281 YYSTYPE yyvsa[YYINITDEPTH];
1282 YYSTYPE *yyvs = yyvsa;
1283 YYSTYPE *yyvsp;
1284
1285
1286
1287 #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
1288
1289 YYSIZE_T yystacksize = YYINITDEPTH;
1290
1291 /* The variables used to return semantic value and location from the
1292 action routines. */
1293 YYSTYPE yyval;
1294
1295
1296 /* The number of symbols on the RHS of the reduced rule.
1297 Keep to zero when no symbol should be popped. */
1298 int yylen = 0;
1299
1300 YYDPRINTF ((stderr, "Starting parse\n"));
1301
1302 yystate = 0;
1303 yyerrstatus = 0;
1304 yynerrs = 0;
1305 yychar = YYEMPTY; /* Cause a token to be read. */
1306
1307 /* Initialize stack pointers.
1308 Waste one element of value and location stack
1309 so that they stay on the same level as the state stack.
1310 The wasted elements are never initialized. */
1311
1312 yyssp = yyss;
1313 yyvsp = yyvs;
1314
1315 goto yysetstate;
1316
1317 /*------------------------------------------------------------.
1318 | yynewstate -- Push a new state, which is found in yystate. |
1319 `------------------------------------------------------------*/
1320 yynewstate:
1321 /* In all cases, when you get here, the value and location stacks
1322 have just been pushed. So pushing a state here evens the stacks. */
1323 yyssp++;
1324
1325 yysetstate:
1326 *yyssp = yystate;
1327
1328 if (yyss + yystacksize - 1 <= yyssp)
1329 {
1330 /* Get the current used size of the three stacks, in elements. */
1331 YYSIZE_T yysize = yyssp - yyss + 1;
1332
1333 #ifdef yyoverflow
1334 {
1335 /* Give user a chance to reallocate the stack. Use copies of
1336 these so that the &'s don't force the real ones into
1337 memory. */
1338 YYSTYPE *yyvs1 = yyvs;
1339 yytype_int16 *yyss1 = yyss;
1340
1341
1342 /* Each stack pointer address is followed by the size of the
1343 data in use in that stack, in bytes. This used to be a
1344 conditional around just the two extra args, but that might
1345 be undefined if yyoverflow is a macro. */
1346 yyoverflow (YY_("memory exhausted"),
1347 &yyss1, yysize * sizeof (*yyssp),
1348 &yyvs1, yysize * sizeof (*yyvsp),
1349
1350 &yystacksize);
1351
1352 yyss = yyss1;
1353 yyvs = yyvs1;
1354 }
1355 #else /* no yyoverflow */
1356 # ifndef YYSTACK_RELOCATE
1357 goto yyexhaustedlab;
1358 # else
1359 /* Extend the stack our own way. */
1360 if (YYMAXDEPTH <= yystacksize)
1361 goto yyexhaustedlab;
1362 yystacksize *= 2;
1363 if (YYMAXDEPTH < yystacksize)
1364 yystacksize = YYMAXDEPTH;
1365
1366 {
1367 yytype_int16 *yyss1 = yyss;
1368 union yyalloc *yyptr =
1369 (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
1370 if (! yyptr)
1371 goto yyexhaustedlab;
1372 YYSTACK_RELOCATE (yyss);
1373 YYSTACK_RELOCATE (yyvs);
1374
1375 # undef YYSTACK_RELOCATE
1376 if (yyss1 != yyssa)
1377 YYSTACK_FREE (yyss1);
1378 }
1379 # endif
1380 #endif /* no yyoverflow */
1381
1382 yyssp = yyss + yysize - 1;
1383 yyvsp = yyvs + yysize - 1;
1384
1385
1386 YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1387 (unsigned long int) yystacksize));
1388
1389 if (yyss + yystacksize - 1 <= yyssp)
1390 YYABORT;
1391 }
1392
1393 YYDPRINTF ((stderr, "Entering state %d\n", yystate));
1394
1395 goto yybackup;
1396
1397 /*-----------.
1398 | yybackup. |
1399 `-----------*/
1400 yybackup:
1401
1402 /* Do appropriate processing given the current state. Read a
1403 look-ahead token if we need one and don't already have one. */
1404
1405 /* First try to decide what to do without reference to look-ahead token. */
1406 yyn = yypact[yystate];
1407 if (yyn == YYPACT_NINF)
1408 goto yydefault;
1409
1410 /* Not known => get a look-ahead token if don't already have one. */
1411
1412 /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
1413 if (yychar == YYEMPTY)
1414 {
1415 YYDPRINTF ((stderr, "Reading a token: "));
1416 yychar = YYLEX;
1417 }
1418
1419 if (yychar <= YYEOF)
1420 {
1421 yychar = yytoken = YYEOF;
1422 YYDPRINTF ((stderr, "Now at end of input.\n"));
1423 }
1424 else
1425 {
1426 yytoken = YYTRANSLATE (yychar);
1427 YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
1428 }
1429
1430 /* If the proper action on seeing token YYTOKEN is to reduce or to
1431 detect an error, take that action. */
1432 yyn += yytoken;
1433 if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
1434 goto yydefault;
1435 yyn = yytable[yyn];
1436 if (yyn <= 0)
1437 {
1438 if (yyn == 0 || yyn == YYTABLE_NINF)
1439 goto yyerrlab;
1440 yyn = -yyn;
1441 goto yyreduce;
1442 }
1443
1444 if (yyn == YYFINAL)
1445 YYACCEPT;
1446
1447 /* Count tokens shifted since error; after three, turn off error
1448 status. */
1449 if (yyerrstatus)
1450 yyerrstatus--;
1451
1452 /* Shift the look-ahead token. */
1453 YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
1454
1455 /* Discard the shifted token unless it is eof. */
1456 if (yychar != YYEOF)
1457 yychar = YYEMPTY;
1458
1459 yystate = yyn;
1460 *++yyvsp = yylval;
1461
1462 goto yynewstate;
1463
1464
1465 /*-----------------------------------------------------------.
1466 | yydefault -- do the default action for the current state. |
1467 `-----------------------------------------------------------*/
1468 yydefault:
1469 yyn = yydefact[yystate];
1470 if (yyn == 0)
1471 goto yyerrlab;
1472 goto yyreduce;
1473
1474
1475 /*-----------------------------.
1476 | yyreduce -- Do a reduction. |
1477 `-----------------------------*/
1478 yyreduce:
1479 /* yyn is the number of a rule to reduce with. */
1480 yylen = yyr2[yyn];
1481
1482 /* If YYLEN is nonzero, implement the default value of the action:
1483 `$$ = $1'.
1484
1485 Otherwise, the following line sets YYVAL to garbage.
1486 This behavior is undocumented and Bison
1487 users should not rely upon it. Assigning to YYVAL
1488 unconditionally makes the parser a bit smaller, and it avoids a
1489 GCC warning that YYVAL may be used uninitialized. */
1490 yyval = yyvsp[1-yylen];
1491
1492
1493 YY_REDUCE_PRINT (yyn);
1494 switch (yyn)
1495 {
1496 case 2:
1497 #line 149 "OSUnserializeXML.y"
1498 { yyerror("unexpected end of buffer");
1499 YYERROR;
1500 ;}
1501 break;
1502
1503 case 3:
1504 #line 152 "OSUnserializeXML.y"
1505 { STATE->parsedObject = (yyvsp[(1) - (1)])->object;
1506 (yyvsp[(1) - (1)])->object = 0;
1507 freeObject(STATE, (yyvsp[(1) - (1)]));
1508 YYACCEPT;
1509 ;}
1510 break;
1511
1512 case 4:
1513 #line 157 "OSUnserializeXML.y"
1514 { yyerror("syntax error");
1515 YYERROR;
1516 ;}
1517 break;
1518
1519 case 5:
1520 #line 162 "OSUnserializeXML.y"
1521 { (yyval) = buildDictionary(STATE, (yyvsp[(1) - (1)]));
1522
1523 if (!yyval->object) {
1524 yyerror("buildDictionary");
1525 YYERROR;
1526 }
1527 STATE->parsedObjectCount++;
1528 if (STATE->parsedObjectCount > MAX_OBJECTS) {
1529 yyerror("maximum object count");
1530 YYERROR;
1531 }
1532 ;}
1533 break;
1534
1535 case 6:
1536 #line 174 "OSUnserializeXML.y"
1537 { (yyval) = buildArray(STATE, (yyvsp[(1) - (1)]));
1538
1539 if (!yyval->object) {
1540 yyerror("buildArray");
1541 YYERROR;
1542 }
1543 STATE->parsedObjectCount++;
1544 if (STATE->parsedObjectCount > MAX_OBJECTS) {
1545 yyerror("maximum object count");
1546 YYERROR;
1547 }
1548 ;}
1549 break;
1550
1551 case 7:
1552 #line 186 "OSUnserializeXML.y"
1553 { (yyval) = buildSet(STATE, (yyvsp[(1) - (1)]));
1554
1555 if (!yyval->object) {
1556 yyerror("buildSet");
1557 YYERROR;
1558 }
1559 STATE->parsedObjectCount++;
1560 if (STATE->parsedObjectCount > MAX_OBJECTS) {
1561 yyerror("maximum object count");
1562 YYERROR;
1563 }
1564 ;}
1565 break;
1566
1567 case 8:
1568 #line 198 "OSUnserializeXML.y"
1569 { (yyval) = buildString(STATE, (yyvsp[(1) - (1)]));
1570
1571 if (!yyval->object) {
1572 yyerror("buildString");
1573 YYERROR;
1574 }
1575 STATE->parsedObjectCount++;
1576 if (STATE->parsedObjectCount > MAX_OBJECTS) {
1577 yyerror("maximum object count");
1578 YYERROR;
1579 }
1580 ;}
1581 break;
1582
1583 case 9:
1584 #line 210 "OSUnserializeXML.y"
1585 { (yyval) = buildData(STATE, (yyvsp[(1) - (1)]));
1586
1587 if (!yyval->object) {
1588 yyerror("buildData");
1589 YYERROR;
1590 }
1591 STATE->parsedObjectCount++;
1592 if (STATE->parsedObjectCount > MAX_OBJECTS) {
1593 yyerror("maximum object count");
1594 YYERROR;
1595 }
1596 ;}
1597 break;
1598
1599 case 10:
1600 #line 222 "OSUnserializeXML.y"
1601 { (yyval) = buildNumber(STATE, (yyvsp[(1) - (1)]));
1602
1603 if (!yyval->object) {
1604 yyerror("buildNumber");
1605 YYERROR;
1606 }
1607 STATE->parsedObjectCount++;
1608 if (STATE->parsedObjectCount > MAX_OBJECTS) {
1609 yyerror("maximum object count");
1610 YYERROR;
1611 }
1612 ;}
1613 break;
1614
1615 case 11:
1616 #line 234 "OSUnserializeXML.y"
1617 { (yyval) = buildBoolean(STATE, (yyvsp[(1) - (1)]));
1618
1619 if (!yyval->object) {
1620 yyerror("buildBoolean");
1621 YYERROR;
1622 }
1623 STATE->parsedObjectCount++;
1624 if (STATE->parsedObjectCount > MAX_OBJECTS) {
1625 yyerror("maximum object count");
1626 YYERROR;
1627 }
1628 ;}
1629 break;
1630
1631 case 12:
1632 #line 246 "OSUnserializeXML.y"
1633 { (yyval) = retrieveObject(STATE, (yyvsp[(1) - (1)])->idref);
1634 if ((yyval)) {
1635 (yyval)->object->retain();
1636 } else {
1637 yyerror("forward reference detected");
1638 YYERROR;
1639 }
1640 freeObject(STATE, (yyvsp[(1) - (1)]));
1641
1642 STATE->parsedObjectCount++;
1643 if (STATE->parsedObjectCount > MAX_OBJECTS) {
1644 yyerror("maximum object count");
1645 YYERROR;
1646 }
1647 ;}
1648 break;
1649
1650 case 13:
1651 #line 265 "OSUnserializeXML.y"
1652 { (yyval) = (yyvsp[(1) - (2)]);
1653 (yyval)->elements = NULL;
1654 ;}
1655 break;
1656
1657 case 14:
1658 #line 268 "OSUnserializeXML.y"
1659 { (yyval) = (yyvsp[(1) - (3)]);
1660 (yyval)->elements = (yyvsp[(2) - (3)]);
1661 ;}
1662 break;
1663
1664 case 17:
1665 #line 275 "OSUnserializeXML.y"
1666 { (yyval) = (yyvsp[(2) - (2)]);
1667 (yyval)->next = (yyvsp[(1) - (2)]);
1668
1669 object_t *o;
1670 o = (yyval)->next;
1671 while (o) {
1672 if (o->key == (yyval)->key) {
1673 yyerror("duplicate dictionary key");
1674 YYERROR;
1675 }
1676 o = o->next;
1677 }
1678 ;}
1679 break;
1680
1681 case 18:
1682 #line 290 "OSUnserializeXML.y"
1683 { (yyval) = (yyvsp[(1) - (2)]);
1684 (yyval)->key = (OSSymbol *)(yyval)->object;
1685 (yyval)->object = (yyvsp[(2) - (2)])->object;
1686 (yyval)->next = NULL;
1687 (yyvsp[(2) - (2)])->object = 0;
1688 freeObject(STATE, (yyvsp[(2) - (2)]));
1689 ;}
1690 break;
1691
1692 case 19:
1693 #line 299 "OSUnserializeXML.y"
1694 { (yyval) = buildSymbol(STATE, (yyvsp[(1) - (1)]));
1695
1696 // STATE->parsedObjectCount++;
1697 // if (STATE->parsedObjectCount > MAX_OBJECTS) {
1698 // yyerror("maximum object count");
1699 // YYERROR;
1700 // }
1701 ;}
1702 break;
1703
1704 case 20:
1705 #line 311 "OSUnserializeXML.y"
1706 { (yyval) = (yyvsp[(1) - (2)]);
1707 (yyval)->elements = NULL;
1708 ;}
1709 break;
1710
1711 case 21:
1712 #line 314 "OSUnserializeXML.y"
1713 { (yyval) = (yyvsp[(1) - (3)]);
1714 (yyval)->elements = (yyvsp[(2) - (3)]);
1715 ;}
1716 break;
1717
1718 case 23:
1719 #line 320 "OSUnserializeXML.y"
1720 { (yyval) = (yyvsp[(1) - (2)]);
1721 (yyval)->elements = NULL;
1722 ;}
1723 break;
1724
1725 case 24:
1726 #line 323 "OSUnserializeXML.y"
1727 { (yyval) = (yyvsp[(1) - (3)]);
1728 (yyval)->elements = (yyvsp[(2) - (3)]);
1729 ;}
1730 break;
1731
1732 case 26:
1733 #line 329 "OSUnserializeXML.y"
1734 { (yyval) = (yyvsp[(1) - (1)]);
1735 (yyval)->next = NULL;
1736 ;}
1737 break;
1738
1739 case 27:
1740 #line 332 "OSUnserializeXML.y"
1741 { (yyval) = (yyvsp[(2) - (2)]);
1742 (yyval)->next = (yyvsp[(1) - (2)]);
1743 ;}
1744 break;
1745
1746
1747 /* Line 1267 of yacc.c. */
1748 #line 1699 "OSUnserializeXML.tab.c"
1749 default: break;
1750 }
1751 YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
1752
1753 YYPOPSTACK (yylen);
1754 yylen = 0;
1755 YY_STACK_PRINT (yyss, yyssp);
1756
1757 *++yyvsp = yyval;
1758
1759
1760 /* Now `shift' the result of the reduction. Determine what state
1761 that goes to, based on the state we popped back to and the rule
1762 number reduced by. */
1763
1764 yyn = yyr1[yyn];
1765
1766 yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
1767 if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1768 yystate = yytable[yystate];
1769 else
1770 yystate = yydefgoto[yyn - YYNTOKENS];
1771
1772 goto yynewstate;
1773
1774
1775 /*------------------------------------.
1776 | yyerrlab -- here on detecting error |
1777 `------------------------------------*/
1778 yyerrlab:
1779 /* If not already recovering from an error, report this error. */
1780 if (!yyerrstatus)
1781 {
1782 ++yynerrs;
1783 #if ! YYERROR_VERBOSE
1784 yyerror (YY_("syntax error"));
1785 #else
1786 {
1787 YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
1788 if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
1789 {
1790 YYSIZE_T yyalloc = 2 * yysize;
1791 if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
1792 yyalloc = YYSTACK_ALLOC_MAXIMUM;
1793 if (yymsg != yymsgbuf)
1794 YYSTACK_FREE (yymsg);
1795 yymsg = (char *) YYSTACK_ALLOC (yyalloc);
1796 if (yymsg)
1797 yymsg_alloc = yyalloc;
1798 else
1799 {
1800 yymsg = yymsgbuf;
1801 yymsg_alloc = sizeof yymsgbuf;
1802 }
1803 }
1804
1805 if (0 < yysize && yysize <= yymsg_alloc)
1806 {
1807 (void) yysyntax_error (yymsg, yystate, yychar);
1808 yyerror (yymsg);
1809 }
1810 else
1811 {
1812 yyerror (YY_("syntax error"));
1813 if (yysize != 0)
1814 goto yyexhaustedlab;
1815 }
1816 }
1817 #endif
1818 }
1819
1820
1821
1822 if (yyerrstatus == 3)
1823 {
1824 /* If just tried and failed to reuse look-ahead token after an
1825 error, discard it. */
1826
1827 if (yychar <= YYEOF)
1828 {
1829 /* Return failure if at end of input. */
1830 if (yychar == YYEOF)
1831 YYABORT;
1832 }
1833 else
1834 {
1835 yydestruct ("Error: discarding",
1836 yytoken, &yylval);
1837 yychar = YYEMPTY;
1838 }
1839 }
1840
1841 /* Else will try to reuse look-ahead token after shifting the error
1842 token. */
1843 goto yyerrlab1;
1844
1845
1846 /*---------------------------------------------------.
1847 | yyerrorlab -- error raised explicitly by YYERROR. |
1848 `---------------------------------------------------*/
1849 yyerrorlab:
1850
1851 /* Pacify compilers like GCC when the user code never invokes
1852 YYERROR and the label yyerrorlab therefore never appears in user
1853 code. */
1854 if (/*CONSTCOND*/ 0)
1855 goto yyerrorlab;
1856
1857 /* Do not reclaim the symbols of the rule which action triggered
1858 this YYERROR. */
1859 YYPOPSTACK (yylen);
1860 yylen = 0;
1861 YY_STACK_PRINT (yyss, yyssp);
1862 yystate = *yyssp;
1863 goto yyerrlab1;
1864
1865
1866 /*-------------------------------------------------------------.
1867 | yyerrlab1 -- common code for both syntax error and YYERROR. |
1868 `-------------------------------------------------------------*/
1869 yyerrlab1:
1870 yyerrstatus = 3; /* Each real token shifted decrements this. */
1871
1872 for (;;)
1873 {
1874 yyn = yypact[yystate];
1875 if (yyn != YYPACT_NINF)
1876 {
1877 yyn += YYTERROR;
1878 if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
1879 {
1880 yyn = yytable[yyn];
1881 if (0 < yyn)
1882 break;
1883 }
1884 }
1885
1886 /* Pop the current state because it cannot handle the error token. */
1887 if (yyssp == yyss)
1888 YYABORT;
1889
1890
1891 yydestruct ("Error: popping",
1892 yystos[yystate], yyvsp);
1893 YYPOPSTACK (1);
1894 yystate = *yyssp;
1895 YY_STACK_PRINT (yyss, yyssp);
1896 }
1897
1898 if (yyn == YYFINAL)
1899 YYACCEPT;
1900
1901 *++yyvsp = yylval;
1902
1903
1904 /* Shift the error token. */
1905 YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
1906
1907 yystate = yyn;
1908 goto yynewstate;
1909
1910
1911 /*-------------------------------------.
1912 | yyacceptlab -- YYACCEPT comes here. |
1913 `-------------------------------------*/
1914 yyacceptlab:
1915 yyresult = 0;
1916 goto yyreturn;
1917
1918 /*-----------------------------------.
1919 | yyabortlab -- YYABORT comes here. |
1920 `-----------------------------------*/
1921 yyabortlab:
1922 yyresult = 1;
1923 goto yyreturn;
1924
1925 #ifndef yyoverflow
1926 /*-------------------------------------------------.
1927 | yyexhaustedlab -- memory exhaustion comes here. |
1928 `-------------------------------------------------*/
1929 yyexhaustedlab:
1930 yyerror (YY_("memory exhausted"));
1931 yyresult = 2;
1932 /* Fall through. */
1933 #endif
1934
1935 yyreturn:
1936 if (yychar != YYEOF && yychar != YYEMPTY)
1937 yydestruct ("Cleanup: discarding lookahead",
1938 yytoken, &yylval);
1939 /* Do not reclaim the symbols of the rule which action triggered
1940 this YYABORT or YYACCEPT. */
1941 YYPOPSTACK (yylen);
1942 YY_STACK_PRINT (yyss, yyssp);
1943 while (yyssp != yyss)
1944 {
1945 yydestruct ("Cleanup: popping",
1946 yystos[*yyssp], yyvsp);
1947 YYPOPSTACK (1);
1948 }
1949 #ifndef yyoverflow
1950 if (yyss != yyssa)
1951 YYSTACK_FREE (yyss);
1952 #endif
1953 #if YYERROR_VERBOSE
1954 if (yymsg != yymsgbuf)
1955 YYSTACK_FREE (yymsg);
1956 #endif
1957 /* Make sure YYID is used. */
1958 return YYID (yyresult);
1959 }
1960
1961
1962 #line 354 "OSUnserializeXML.y"
1963
1964
1965 int
1966 OSUnserializeerror(parser_state_t * state, const char *s) /* Called by yyparse on errors */
1967 {
1968 if (state->errorString) {
1969 char tempString[128];
1970 snprintf(tempString, 128, "OSUnserializeXML: %s near line %d\n", s, state->lineNumber);
1971 *(state->errorString) = OSString::withCString(tempString);
1972 }
1973
1974 return 0;
1975 }
1976
1977 #define TAG_MAX_LENGTH 32
1978 #define TAG_MAX_ATTRIBUTES 32
1979 #define TAG_BAD 0
1980 #define TAG_START 1
1981 #define TAG_END 2
1982 #define TAG_EMPTY 3
1983 #define TAG_IGNORE 4
1984
1985 #define currentChar() (state->parseBuffer[state->parseBufferIndex])
1986 #define nextChar() (state->parseBuffer[++state->parseBufferIndex])
1987 #define prevChar() (state->parseBuffer[state->parseBufferIndex - 1])
1988
1989 #define isSpace(c) ((c) == ' ' || (c) == '\t')
1990 #define isAlpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
1991 #define isDigit(c) ((c) >= '0' && (c) <= '9')
1992 #define isAlphaDigit(c) ((c) >= 'a' && (c) <= 'f')
1993 #define isHexDigit(c) (isDigit(c) || isAlphaDigit(c))
1994 #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-'))
1995
1996 static int
1997 getTag(parser_state_t *state,
1998 char tag[TAG_MAX_LENGTH],
1999 int *attributeCount,
2000 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH],
2001 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] )
2002 {
2003 int length = 0;
2004 int c = currentChar();
2005 int tagType = TAG_START;
2006
2007 *attributeCount = 0;
2008
2009 if (c != '<') return TAG_BAD;
2010 c = nextChar(); // skip '<'
2011
2012
2013 // <!TAG declarations >
2014 // <!-- comments -->
2015 if (c == '!') {
2016 c = nextChar();
2017 bool isComment = (c == '-') && ((c = nextChar()) != 0) && (c == '-');
2018 if (!isComment && !isAlpha(c)) return TAG_BAD; // <!1, <!-A, <!eos
2019
2020 while (c && (c = nextChar()) != 0) {
2021 if (c == '\n') state->lineNumber++;
2022 if (isComment) {
2023 if (c != '-') continue;
2024 c = nextChar();
2025 if (c != '-') continue;
2026 c = nextChar();
2027 }
2028 if (c == '>') {
2029 (void)nextChar();
2030 return TAG_IGNORE;
2031 }
2032 if (isComment) break;
2033 }
2034 return TAG_BAD;
2035 }
2036
2037 else
2038
2039 // <? Processing Instructions ?>
2040 if (c == '?') {
2041 while ((c = nextChar()) != 0) {
2042 if (c == '\n') state->lineNumber++;
2043 if (c != '?') continue;
2044 c = nextChar();
2045 if (!c) return TAG_IGNORE;
2046 if (c == '>') {
2047 (void)nextChar();
2048 return TAG_IGNORE;
2049 }
2050 }
2051 return TAG_BAD;
2052 }
2053
2054 else
2055
2056 // </ end tag >
2057 if (c == '/') {
2058 c = nextChar(); // skip '/'
2059 tagType = TAG_END;
2060 }
2061 if (!isAlpha(c)) return TAG_BAD;
2062
2063 /* find end of tag while copying it */
2064 while (isAlphaNumeric(c)) {
2065 tag[length++] = c;
2066 c = nextChar();
2067 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
2068 }
2069
2070 tag[length] = 0;
2071
2072 // printf("tag %s, type %d\n", tag, tagType);
2073
2074 // look for attributes of the form attribute = "value" ...
2075 while ((c != '>') && (c != '/')) {
2076 while (isSpace(c)) c = nextChar();
2077
2078 length = 0;
2079 while (isAlphaNumeric(c)) {
2080 attributes[*attributeCount][length++] = c;
2081 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
2082 c = nextChar();
2083 }
2084 attributes[*attributeCount][length] = 0;
2085
2086 while (isSpace(c)) c = nextChar();
2087
2088 if (c != '=') return TAG_BAD;
2089 c = nextChar();
2090
2091 while (isSpace(c)) c = nextChar();
2092
2093 if (c != '"') return TAG_BAD;
2094 c = nextChar();
2095 length = 0;
2096 while (c != '"') {
2097 values[*attributeCount][length++] = c;
2098 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
2099 c = nextChar();
2100 if (!c) return TAG_BAD;
2101 }
2102 values[*attributeCount][length] = 0;
2103
2104 c = nextChar(); // skip closing quote
2105
2106 // printf(" attribute '%s' = '%s', nextchar = '%c'\n",
2107 // attributes[*attributeCount], values[*attributeCount], c);
2108
2109 (*attributeCount)++;
2110 if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD;
2111 }
2112
2113 if (c == '/') {
2114 c = nextChar(); // skip '/'
2115 tagType = TAG_EMPTY;
2116 }
2117 if (c != '>') return TAG_BAD;
2118 c = nextChar(); // skip '>'
2119
2120 return tagType;
2121 }
2122
2123 static char *
2124 getString(parser_state_t *state)
2125 {
2126 int c = currentChar();
2127 int start, length, i, j;
2128 char * tempString;
2129
2130 start = state->parseBufferIndex;
2131 /* find end of string */
2132
2133 while (c != 0) {
2134 if (c == '\n') state->lineNumber++;
2135 if (c == '<') {
2136 break;
2137 }
2138 c = nextChar();
2139 }
2140
2141 if (c != '<') return 0;
2142
2143 length = state->parseBufferIndex - start;
2144
2145 /* copy to null terminated buffer */
2146 tempString = (char *)malloc(length + 1);
2147 if (tempString == 0) {
2148 printf("OSUnserializeXML: can't alloc temp memory\n");
2149 goto error;
2150 }
2151
2152 // copy out string in tempString
2153 // "&amp;" -> '&', "&lt;" -> '<', "&gt;" -> '>'
2154
2155 i = j = 0;
2156 while (i < length) {
2157 c = state->parseBuffer[start + i++];
2158 if (c != '&') {
2159 tempString[j++] = c;
2160 } else {
2161 if ((i+3) > length) goto error;
2162 c = state->parseBuffer[start + i++];
2163 if (c == 'l') {
2164 if (state->parseBuffer[start + i++] != 't') goto error;
2165 if (state->parseBuffer[start + i++] != ';') goto error;
2166 tempString[j++] = '<';
2167 continue;
2168 }
2169 if (c == 'g') {
2170 if (state->parseBuffer[start + i++] != 't') goto error;
2171 if (state->parseBuffer[start + i++] != ';') goto error;
2172 tempString[j++] = '>';
2173 continue;
2174 }
2175 if ((i+3) > length) goto error;
2176 if (c == 'a') {
2177 if (state->parseBuffer[start + i++] != 'm') goto error;
2178 if (state->parseBuffer[start + i++] != 'p') goto error;
2179 if (state->parseBuffer[start + i++] != ';') goto error;
2180 tempString[j++] = '&';
2181 continue;
2182 }
2183 goto error;
2184 }
2185 }
2186 tempString[j] = 0;
2187
2188 // printf("string %s\n", tempString);
2189
2190 return tempString;
2191
2192 error:
2193 if (tempString) free(tempString);
2194 return 0;
2195 }
2196
2197 static long long
2198 getNumber(parser_state_t *state)
2199 {
2200 unsigned long long n = 0;
2201 int base = 10;
2202 bool negate = false;
2203 int c = currentChar();
2204
2205 if (c == '0') {
2206 c = nextChar();
2207 if (c == 'x') {
2208 base = 16;
2209 c = nextChar();
2210 }
2211 }
2212 if (base == 10) {
2213 if (c == '-') {
2214 negate = true;
2215 c = nextChar();
2216 }
2217 while(isDigit(c)) {
2218 n = (n * base + c - '0');
2219 c = nextChar();
2220 }
2221 if (negate) {
2222 n = (unsigned long long)((long long)n * (long long)-1);
2223 }
2224 } else {
2225 while(isHexDigit(c)) {
2226 if (isDigit(c)) {
2227 n = (n * base + c - '0');
2228 } else {
2229 n = (n * base + 0xa + c - 'a');
2230 }
2231 c = nextChar();
2232 }
2233 }
2234 // printf("number 0x%x\n", (unsigned long)n);
2235 return n;
2236 }
2237
2238 // taken from CFXMLParsing/CFPropertyList.c
2239
2240 static const signed char __CFPLDataDecodeTable[128] = {
2241 /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
2242 /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
2243 /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
2244 /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
2245 /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
2246 /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
2247 /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
2248 /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1,
2249 /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6,
2250 /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14,
2251 /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
2252 /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
2253 /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
2254 /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
2255 /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
2256 /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
2257 };
2258
2259 #define DATA_ALLOC_SIZE 4096
2260
2261 static void *
2262 getCFEncodedData(parser_state_t *state, unsigned int *size)
2263 {
2264 int numeq = 0, acc = 0, cntr = 0;
2265 int tmpbufpos = 0, tmpbuflen = 0;
2266 unsigned char *tmpbuf = (unsigned char *)malloc(DATA_ALLOC_SIZE);
2267
2268 int c = currentChar();
2269 *size = 0;
2270
2271 while (c != '<') {
2272 c &= 0x7f;
2273 if (c == 0) {
2274 free(tmpbuf);
2275 return 0;
2276 }
2277 if (c == '=') numeq++; else numeq = 0;
2278 if (c == '\n') state->lineNumber++;
2279 if (__CFPLDataDecodeTable[c] < 0) {
2280 c = nextChar();
2281 continue;
2282 }
2283 cntr++;
2284 acc <<= 6;
2285 acc += __CFPLDataDecodeTable[c];
2286 if (0 == (cntr & 0x3)) {
2287 if (tmpbuflen <= tmpbufpos + 2) {
2288 tmpbuflen += DATA_ALLOC_SIZE;
2289 tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen);
2290 }
2291 tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
2292 if (numeq < 2)
2293 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
2294 if (numeq < 1)
2295 tmpbuf[tmpbufpos++] = acc & 0xff;
2296 }
2297 c = nextChar();
2298 }
2299 *size = tmpbufpos;
2300 if (*size == 0) {
2301 free(tmpbuf);
2302 return 0;
2303 }
2304 return tmpbuf;
2305 }
2306
2307 static void *
2308 getHexData(parser_state_t *state, unsigned int *size)
2309 {
2310 int c;
2311 unsigned char *d, *start, *lastStart;
2312
2313 start = lastStart = d = (unsigned char *)malloc(DATA_ALLOC_SIZE);
2314 c = currentChar();
2315
2316 while (c != '<') {
2317
2318 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
2319 if (c == '\n') {
2320 state->lineNumber++;
2321 c = nextChar();
2322 continue;
2323 }
2324
2325 // get high nibble
2326 if (isDigit(c)) {
2327 *d = (c - '0') << 4;
2328 } else if (isAlphaDigit(c)) {
2329 *d = (0xa + (c - 'a')) << 4;
2330 } else {
2331 goto error;
2332 }
2333
2334 // get low nibble
2335 c = nextChar();
2336 if (isDigit(c)) {
2337 *d |= c - '0';
2338 } else if (isAlphaDigit(c)) {
2339 *d |= 0xa + (c - 'a');
2340 } else {
2341 goto error;
2342 }
2343
2344 d++;
2345 if ((d - lastStart) >= DATA_ALLOC_SIZE) {
2346 int oldsize = d - start;
2347 start = (unsigned char *)realloc(start, oldsize + DATA_ALLOC_SIZE);
2348 d = lastStart = start + oldsize;
2349 }
2350 c = nextChar();
2351 }
2352
2353 *size = d - start;
2354 return start;
2355
2356 error:
2357
2358 *size = 0;
2359 free(start);
2360 return 0;
2361 }
2362
2363 static int
2364 yylex(YYSTYPE *lvalp, parser_state_t *state)
2365 {
2366 int c, i;
2367 int tagType;
2368 char tag[TAG_MAX_LENGTH];
2369 int attributeCount;
2370 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
2371 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
2372 object_t *object;
2373
2374 top:
2375 c = currentChar();
2376
2377 /* skip white space */
2378 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
2379
2380 /* keep track of line number, don't return \n's */
2381 if (c == '\n') {
2382 STATE->lineNumber++;
2383 (void)nextChar();
2384 goto top;
2385 }
2386
2387 // end of the buffer?
2388 if (!c) return 0;
2389
2390 tagType = getTag(STATE, tag, &attributeCount, attributes, values);
2391 if (tagType == TAG_BAD) return SYNTAX_ERROR;
2392 if (tagType == TAG_IGNORE) goto top;
2393
2394 // handle allocation and check for "ID" and "IDREF" tags up front
2395 *lvalp = object = newObject(STATE);
2396 object->idref = -1;
2397 for (i=0; i < attributeCount; i++) {
2398 if (attributes[i][0] == 'I' && attributes[i][1] == 'D') {
2399 // check for idref's, note: we ignore the tag, for
2400 // this to work correctly, all idrefs must be unique
2401 // across the whole serialization
2402 if (attributes[i][2] == 'R' && attributes[i][3] == 'E' &&
2403 attributes[i][4] == 'F' && !attributes[i][5]) {
2404 if (tagType != TAG_EMPTY) return SYNTAX_ERROR;
2405 object->idref = strtol(values[i], NULL, 0);
2406 return IDREF;
2407 }
2408 // check for id's
2409 if (!attributes[i][2]) {
2410 object->idref = strtol(values[i], NULL, 0);
2411 } else {
2412 return SYNTAX_ERROR;
2413 }
2414 }
2415 }
2416
2417 switch (*tag) {
2418 case 'a':
2419 if (!strcmp(tag, "array")) {
2420 if (tagType == TAG_EMPTY) {
2421 object->elements = NULL;
2422 return ARRAY;
2423 }
2424 return (tagType == TAG_START) ? '(' : ')';
2425 }
2426 break;
2427 case 'd':
2428 if (!strcmp(tag, "dict")) {
2429 if (tagType == TAG_EMPTY) {
2430 object->elements = NULL;
2431 return DICTIONARY;
2432 }
2433 return (tagType == TAG_START) ? '{' : '}';
2434 }
2435 if (!strcmp(tag, "data")) {
2436 unsigned int size;
2437 if (tagType == TAG_EMPTY) {
2438 object->data = NULL;
2439 object->size = 0;
2440 return DATA;
2441 }
2442
2443 bool isHexFormat = false;
2444 for (i=0; i < attributeCount; i++) {
2445 if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) {
2446 isHexFormat = true;
2447 break;
2448 }
2449 }
2450 // CF encoded is the default form
2451 if (isHexFormat) {
2452 object->data = getHexData(STATE, &size);
2453 } else {
2454 object->data = getCFEncodedData(STATE, &size);
2455 }
2456 object->size = size;
2457 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) {
2458 return SYNTAX_ERROR;
2459 }
2460 return DATA;
2461 }
2462 break;
2463 case 'f':
2464 if (!strcmp(tag, "false")) {
2465 if (tagType == TAG_EMPTY) {
2466 object->number = 0;
2467 return BOOLEAN;
2468 }
2469 }
2470 break;
2471 case 'i':
2472 if (!strcmp(tag, "integer")) {
2473 object->size = 64; // default
2474 for (i=0; i < attributeCount; i++) {
2475 if (!strcmp(attributes[i], "size")) {
2476 object->size = strtoul(values[i], NULL, 0);
2477 }
2478 }
2479 if (tagType == TAG_EMPTY) {
2480 object->number = 0;
2481 return NUMBER;
2482 }
2483 object->number = getNumber(STATE);
2484 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) {
2485 return SYNTAX_ERROR;
2486 }
2487 return NUMBER;
2488 }
2489 break;
2490 case 'k':
2491 if (!strcmp(tag, "key")) {
2492 if (tagType == TAG_EMPTY) return SYNTAX_ERROR;
2493 object->string = getString(STATE);
2494 if (!object->string) {
2495 return SYNTAX_ERROR;
2496 }
2497 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
2498 || strcmp(tag, "key")) {
2499 return SYNTAX_ERROR;
2500 }
2501 return KEY;
2502 }
2503 break;
2504 case 'p':
2505 if (!strcmp(tag, "plist")) {
2506 freeObject(STATE, object);
2507 goto top;
2508 }
2509 break;
2510 case 's':
2511 if (!strcmp(tag, "string")) {
2512 if (tagType == TAG_EMPTY) {
2513 object->string = (char *)malloc(1);
2514 object->string[0] = 0;
2515 return STRING;
2516 }
2517 object->string = getString(STATE);
2518 if (!object->string) {
2519 return SYNTAX_ERROR;
2520 }
2521 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
2522 || strcmp(tag, "string")) {
2523 return SYNTAX_ERROR;
2524 }
2525 return STRING;
2526 }
2527 if (!strcmp(tag, "set")) {
2528 if (tagType == TAG_EMPTY) {
2529 object->elements = NULL;
2530 return SET;;
2531 }
2532 if (tagType == TAG_START) {
2533 return '[';
2534 } else {
2535 return ']';
2536 }
2537 }
2538 break;
2539 case 't':
2540 if (!strcmp(tag, "true")) {
2541 if (tagType == TAG_EMPTY) {
2542 object->number = 1;
2543 return BOOLEAN;
2544 }
2545 }
2546 break;
2547 }
2548
2549 return SYNTAX_ERROR;
2550 }
2551
2552 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2553 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2554 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2555
2556 // "java" like allocation, if this code hits a syntax error in the
2557 // the middle of the parsed string we just bail with pointers hanging
2558 // all over place, this code helps keeps it all together
2559
2560 //static int object_count = 0;
2561
2562 object_t *
2563 newObject(parser_state_t *state)
2564 {
2565 object_t *o;
2566
2567 if (state->freeObjects) {
2568 o = state->freeObjects;
2569 state->freeObjects = state->freeObjects->next;
2570 } else {
2571 o = (object_t *)malloc(sizeof(object_t));
2572 // object_count++;
2573 bzero(o, sizeof(object_t));
2574 o->free = state->objects;
2575 state->objects = o;
2576 }
2577
2578 return o;
2579 }
2580
2581 void
2582 freeObject(parser_state_t * state, object_t *o)
2583 {
2584 o->next = state->freeObjects;
2585 state->freeObjects = o;
2586 }
2587
2588 void
2589 cleanupObjects(parser_state_t *state)
2590 {
2591 object_t *t, *o = state->objects;
2592
2593 while (o) {
2594 if (o->object) {
2595 // printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object);
2596 o->object->release();
2597 }
2598 if (o->data) {
2599 // printf("OSUnserializeXML: freeing object o=%x data=%x\n", (int)o, (int)o->data);
2600 free(o->data);
2601 }
2602 if (o->key) {
2603 // printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key);
2604 o->key->release();
2605 }
2606 if (o->string) {
2607 // printf("OSUnserializeXML: freeing object o=%x string=%x\n", (int)o, (int)o->string);
2608 free(o->string);
2609 }
2610
2611 t = o;
2612 o = o->free;
2613 free(t);
2614 // object_count--;
2615 }
2616 // printf("object_count = %d\n", object_count);
2617 }
2618
2619 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2620 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2621 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2622
2623 static void
2624 rememberObject(parser_state_t *state, int tag, OSObject *o)
2625 {
2626 char key[16];
2627 snprintf(key, 16, "%u", tag);
2628
2629 // printf("remember key %s\n", key);
2630
2631 state->tags->setObject(key, o);
2632 }
2633
2634 static object_t *
2635 retrieveObject(parser_state_t *state, int tag)
2636 {
2637 OSObject *ref;
2638 object_t *o;
2639 char key[16];
2640 snprintf(key, 16, "%u", tag);
2641
2642 // printf("retrieve key '%s'\n", key);
2643
2644 ref = state->tags->getObject(key);
2645 if (!ref) return 0;
2646
2647 o = newObject(state);
2648 o->object = ref;
2649 return o;
2650 }
2651
2652 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2653 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2654 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2655
2656 object_t *
2657 buildDictionary(parser_state_t *state, object_t * header)
2658 {
2659 object_t *o, *t;
2660 int count = 0;
2661 OSDictionary *dict;
2662
2663 // get count and reverse order
2664 o = header->elements;
2665 header->elements = 0;
2666 while (o) {
2667 count++;
2668 t = o;
2669 o = o->next;
2670
2671 t->next = header->elements;
2672 header->elements = t;
2673 }
2674
2675 dict = OSDictionary::withCapacity(count);
2676 if (header->idref >= 0) rememberObject(state, header->idref, dict);
2677
2678 o = header->elements;
2679 while (o) {
2680 dict->setObject(o->key, o->object);
2681
2682 o->key->release();
2683 o->object->release();
2684 o->key = 0;
2685 o->object = 0;
2686
2687 t = o;
2688 o = o->next;
2689 freeObject(state, t);
2690 }
2691 o = header;
2692 o->object = dict;
2693 return o;
2694 };
2695
2696 object_t *
2697 buildArray(parser_state_t *state, object_t * header)
2698 {
2699 object_t *o, *t;
2700 int count = 0;
2701 OSArray *array;
2702
2703 // get count and reverse order
2704 o = header->elements;
2705 header->elements = 0;
2706 while (o) {
2707 count++;
2708 t = o;
2709 o = o->next;
2710
2711 t->next = header->elements;
2712 header->elements = t;
2713 }
2714
2715 array = OSArray::withCapacity(count);
2716 if (header->idref >= 0) rememberObject(state, header->idref, array);
2717
2718 o = header->elements;
2719 while (o) {
2720 array->setObject(o->object);
2721
2722 o->object->release();
2723 o->object = 0;
2724
2725 t = o;
2726 o = o->next;
2727 freeObject(state, t);
2728 }
2729 o = header;
2730 o->object = array;
2731 return o;
2732 };
2733
2734 object_t *
2735 buildSet(parser_state_t *state, object_t *header)
2736 {
2737 object_t *o = buildArray(state, header);
2738
2739 OSArray *array = (OSArray *)o->object;
2740 OSSet *set = OSSet::withArray(array, array->getCapacity());
2741
2742 // write over the reference created in buildArray
2743 if (header->idref >= 0) rememberObject(state, header->idref, set);
2744
2745 array->release();
2746 o->object = set;
2747 return o;
2748 };
2749
2750 object_t *
2751 buildString(parser_state_t *state, object_t *o)
2752 {
2753 OSString *string;
2754
2755 string = OSString::withCString(o->string);
2756 if (o->idref >= 0) rememberObject(state, o->idref, string);
2757
2758 free(o->string);
2759 o->string = 0;
2760 o->object = string;
2761
2762 return o;
2763 };
2764
2765 object_t *
2766 buildSymbol(parser_state_t *state, object_t *o)
2767 {
2768 OSSymbol *symbol;
2769
2770 symbol = (OSSymbol *)OSSymbol::withCString(o->string);
2771 if (o->idref >= 0) rememberObject(state, o->idref, symbol);
2772
2773 free(o->string);
2774 o->string = 0;
2775 o->object = symbol;
2776
2777 return o;
2778 };
2779
2780 object_t *
2781 buildData(parser_state_t *state, object_t *o)
2782 {
2783 OSData *data;
2784
2785 if (o->size) {
2786 data = OSData::withBytes(o->data, o->size);
2787 } else {
2788 data = OSData::withCapacity(0);
2789 }
2790 if (o->idref >= 0) rememberObject(state, o->idref, data);
2791
2792 if (o->size) free(o->data);
2793 o->data = 0;
2794 o->object = data;
2795 return o;
2796 };
2797
2798 object_t *
2799 buildNumber(parser_state_t *state, object_t *o)
2800 {
2801 OSNumber *number = OSNumber::withNumber(o->number, o->size);
2802
2803 if (o->idref >= 0) rememberObject(state, o->idref, number);
2804
2805 o->object = number;
2806 return o;
2807 };
2808
2809 object_t *
2810 buildBoolean(parser_state_t *state __unused, object_t *o)
2811 {
2812 o->object = ((o->number == 0) ? kOSBooleanFalse : kOSBooleanTrue);
2813 o->object->retain();
2814 return o;
2815 };
2816
2817 OSObject*
2818 OSUnserializeXML(const char *buffer, OSString **errorString)
2819 {
2820 OSObject *object;
2821
2822 if (!buffer) return 0;
2823 parser_state_t *state = (parser_state_t *)malloc(sizeof(parser_state_t));
2824 if (!state) return 0;
2825
2826 // just in case
2827 if (errorString) *errorString = NULL;
2828
2829 state->parseBuffer = buffer;
2830 state->parseBufferIndex = 0;
2831 state->lineNumber = 1;
2832 state->objects = 0;
2833 state->freeObjects = 0;
2834 state->tags = OSDictionary::withCapacity(128);
2835 state->errorString = errorString;
2836 state->parsedObject = 0;
2837 state->parsedObjectCount = 0;
2838
2839 (void)yyparse((void *)state);
2840
2841 object = state->parsedObject;
2842
2843 cleanupObjects(state);
2844 state->tags->release();
2845 free(state);
2846
2847 return object;
2848 }
2849
2850 #include <libkern/OSSerializeBinary.h>
2851
2852 OSObject*
2853 OSUnserializeXML(const char *buffer, size_t bufferSize, OSString **errorString)
2854 {
2855 if (!buffer) return (0);
2856 if (bufferSize < sizeof(kOSSerializeBinarySignature)) return (0);
2857
2858 if (!strcmp(kOSSerializeBinarySignature, buffer)) return OSUnserializeBinary(buffer, bufferSize, errorString);
2859
2860 // XML must be null terminated
2861 if (buffer[bufferSize - 1]) return 0;
2862
2863 return OSUnserializeXML(buffer, errorString);
2864 }
2865
2866
2867 //
2868 //
2869 //
2870 //
2871 //
2872 // DO NOT EDIT OSUnserializeXML.cpp!
2873 //
2874 // this means you!
2875 //
2876 //
2877 //
2878 //
2879 //
2880