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