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