]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSUnserializeXML.cpp
xnu-1456.1.26.tar.gz
[apple/xnu.git] / libkern / c++ / OSUnserializeXML.cpp
1 /*
2 * Copyright (c) 1999-2009 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 YYSTYPE object_t *
163 #define YYPARSE_PARAM state
164 #define YYLEX_PARAM (parser_state_t *)state
165
166 // this is the internal struct used to hold objects on parser stack
167 // it represents objects both before and after they have been created
168 typedef struct object {
169 struct object *next;
170 struct object *free;
171 struct object *elements;
172 OSObject *object;
173 OSString *key; // for dictionary
174 int size;
175 void *data; // for data
176 char *string; // for string & symbol
177 long long number; // for number
178 int idref;
179 } object_t;
180
181 // this code is reentrant, this structure contains all
182 // state information for the parsing of a single buffer
183 typedef struct parser_state {
184 const char *parseBuffer; // start of text to be parsed
185 int parseBufferIndex; // current index into text
186 int lineNumber; // current line number
187 object_t *objects; // internal objects in use
188 object_t *freeObjects; // internal objects that are free
189 OSDictionary *tags; // used to remember "ID" tags
190 OSString **errorString; // parse error with line
191 OSObject *parsedObject; // resultant object of parsed text
192 } parser_state_t;
193
194 #define STATE ((parser_state_t *)state)
195
196 #undef yyerror
197 #define yyerror(s) OSUnserializeerror(STATE, (s))
198 static int OSUnserializeerror(parser_state_t *state, const char *s);
199
200 static int yylex(YYSTYPE *lvalp, parser_state_t *state);
201
202 static object_t *newObject(parser_state_t *state);
203 static void freeObject(parser_state_t *state, object_t *o);
204 static void rememberObject(parser_state_t *state, int tag, OSObject *o);
205 static object_t *retrieveObject(parser_state_t *state, int tag);
206 static void cleanupObjects(parser_state_t *state);
207
208 static object_t *buildDictionary(parser_state_t *state, object_t *o);
209 static object_t *buildArray(parser_state_t *state, object_t *o);
210 static object_t *buildSet(parser_state_t *state, object_t *o);
211 static object_t *buildString(parser_state_t *state, object_t *o);
212 static object_t *buildData(parser_state_t *state, object_t *o);
213 static object_t *buildNumber(parser_state_t *state, object_t *o);
214 static object_t *buildBoolean(parser_state_t *state, object_t *o);
215
216 extern "C" {
217 extern void *kern_os_malloc(size_t size);
218 extern void *kern_os_realloc(void * addr, size_t size);
219 extern void kern_os_free(void * addr);
220
221 } /* extern "C" */
222
223 #define malloc(s) kern_os_malloc(s)
224 #define realloc(a, s) kern_os_realloc(a, s)
225 #define free(a) kern_os_free((void *)a)
226
227
228
229 /* Enabling traces. */
230 #ifndef YYDEBUG
231 # define YYDEBUG 0
232 #endif
233
234 /* Enabling verbose error messages. */
235 #ifdef YYERROR_VERBOSE
236 # undef YYERROR_VERBOSE
237 # define YYERROR_VERBOSE 1
238 #else
239 # define YYERROR_VERBOSE 0
240 #endif
241
242 /* Enabling the token table. */
243 #ifndef YYTOKEN_TABLE
244 # define YYTOKEN_TABLE 0
245 #endif
246
247 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
248 typedef int YYSTYPE;
249 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
250 # define YYSTYPE_IS_DECLARED 1
251 # define YYSTYPE_IS_TRIVIAL 1
252 #endif
253
254
255
256 /* Copy the second part of user declarations. */
257
258
259 /* Line 216 of yacc.c. */
260 #line 211 "OSUnserializeXML.tab.c"
261
262 #ifdef short
263 # undef short
264 #endif
265
266 #ifdef YYTYPE_UINT8
267 typedef YYTYPE_UINT8 yytype_uint8;
268 #else
269 typedef unsigned char yytype_uint8;
270 #endif
271
272 #ifdef YYTYPE_INT8
273 typedef YYTYPE_INT8 yytype_int8;
274 #elif (defined __STDC__ || defined __C99__FUNC__ \
275 || defined __cplusplus || defined _MSC_VER)
276 typedef signed char yytype_int8;
277 #else
278 typedef short int yytype_int8;
279 #endif
280
281 #ifdef YYTYPE_UINT16
282 typedef YYTYPE_UINT16 yytype_uint16;
283 #else
284 typedef unsigned short int yytype_uint16;
285 #endif
286
287 #ifdef YYTYPE_INT16
288 typedef YYTYPE_INT16 yytype_int16;
289 #else
290 typedef short int yytype_int16;
291 #endif
292
293 #ifndef YYSIZE_T
294 # ifdef __SIZE_TYPE__
295 # define YYSIZE_T __SIZE_TYPE__
296 # elif defined size_t
297 # define YYSIZE_T size_t
298 # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
299 || defined __cplusplus || defined _MSC_VER)
300 # include <stddef.h> /* INFRINGES ON USER NAME SPACE */
301 # define YYSIZE_T size_t
302 # else
303 # define YYSIZE_T unsigned int
304 # endif
305 #endif
306
307 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
308
309 #ifndef YY_
310 # if defined YYENABLE_NLS && YYENABLE_NLS
311 # if ENABLE_NLS
312 # include <libintl.h> /* INFRINGES ON USER NAME SPACE */
313 # define YY_(msgid) dgettext ("bison-runtime", msgid)
314 # endif
315 # endif
316 # ifndef YY_
317 # define YY_(msgid) msgid
318 # endif
319 #endif
320
321 /* Suppress unused-variable warnings by "using" E. */
322 #if ! defined lint || defined __GNUC__
323 # define YYUSE(e) ((void) (e))
324 #else
325 # define YYUSE(e) /* empty */
326 #endif
327
328 /* Identity function, used to suppress warnings about constant conditions. */
329 #ifndef lint
330 # define YYID(n) (n)
331 #else
332 #if (defined __STDC__ || defined __C99__FUNC__ \
333 || defined __cplusplus || defined _MSC_VER)
334 static int
335 YYID (int i)
336 #else
337 static int
338 YYID (i)
339 int i;
340 #endif
341 {
342 return i;
343 }
344 #endif
345
346 #if ! defined yyoverflow || YYERROR_VERBOSE
347
348 /* The parser invokes alloca or malloc; define the necessary symbols. */
349
350 # ifdef YYSTACK_USE_ALLOCA
351 # if YYSTACK_USE_ALLOCA
352 # ifdef __GNUC__
353 # define YYSTACK_ALLOC __builtin_alloca
354 # elif defined __BUILTIN_VA_ARG_INCR
355 # include <alloca.h> /* INFRINGES ON USER NAME SPACE */
356 # elif defined _AIX
357 # define YYSTACK_ALLOC __alloca
358 # elif defined _MSC_VER
359 # include <malloc.h> /* INFRINGES ON USER NAME SPACE */
360 # define alloca _alloca
361 # else
362 # define YYSTACK_ALLOC alloca
363 # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
364 || defined __cplusplus || defined _MSC_VER)
365 # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
366 # ifndef _STDLIB_H
367 # define _STDLIB_H 1
368 # endif
369 # endif
370 # endif
371 # endif
372 # endif
373
374 # ifdef YYSTACK_ALLOC
375 /* Pacify GCC's `empty if-body' warning. */
376 # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
377 # ifndef YYSTACK_ALLOC_MAXIMUM
378 /* The OS might guarantee only one guard page at the bottom of the stack,
379 and a page size can be as small as 4096 bytes. So we cannot safely
380 invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
381 to allow for a few compiler-allocated temporary stack slots. */
382 # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
383 # endif
384 # else
385 # define YYSTACK_ALLOC YYMALLOC
386 # define YYSTACK_FREE YYFREE
387 # ifndef YYSTACK_ALLOC_MAXIMUM
388 # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
389 # endif
390 # if (defined __cplusplus && ! defined _STDLIB_H \
391 && ! ((defined YYMALLOC || defined malloc) \
392 && (defined YYFREE || defined free)))
393 # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
394 # ifndef _STDLIB_H
395 # define _STDLIB_H 1
396 # endif
397 # endif
398 # ifndef YYMALLOC
399 # define YYMALLOC malloc
400 # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
401 || defined __cplusplus || defined _MSC_VER)
402 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
403 # endif
404 # endif
405 # ifndef YYFREE
406 # define YYFREE free
407 # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
408 || defined __cplusplus || defined _MSC_VER)
409 void free (void *); /* INFRINGES ON USER NAME SPACE */
410 # endif
411 # endif
412 # endif
413 #endif /* ! defined yyoverflow || YYERROR_VERBOSE */
414
415
416 #if (! defined yyoverflow \
417 && (! defined __cplusplus \
418 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
419
420 /* A type that is properly aligned for any stack member. */
421 union yyalloc
422 {
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_uint8 yyrline[] =
551 {
552 0, 145, 145, 148, 153, 158, 159, 160, 161, 162,
553 163, 164, 165, 178, 181, 184, 187, 188, 193, 202,
554 207, 210, 213, 216, 219, 222, 225, 228, 235, 238,
555 241, 244, 247
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 # ifdef YYPRINT
817 if (yytype < YYNTOKENS)
818 YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
819 # else
820 YYUSE (yyoutput);
821 # endif
822 switch (yytype)
823 {
824 default:
825 break;
826 }
827 }
828
829
830 /*--------------------------------.
831 | Print this symbol on YYOUTPUT. |
832 `--------------------------------*/
833
834 #if (defined __STDC__ || defined __C99__FUNC__ \
835 || defined __cplusplus || defined _MSC_VER)
836 static void
837 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
838 #else
839 static void
840 yy_symbol_print (yyoutput, yytype, yyvaluep)
841 FILE *yyoutput;
842 int yytype;
843 YYSTYPE const * const yyvaluep;
844 #endif
845 {
846 if (yytype < YYNTOKENS)
847 YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
848 else
849 YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
850
851 yy_symbol_value_print (yyoutput, yytype, yyvaluep);
852 YYFPRINTF (yyoutput, ")");
853 }
854
855 /*------------------------------------------------------------------.
856 | yy_stack_print -- Print the state stack from its BOTTOM up to its |
857 | TOP (included). |
858 `------------------------------------------------------------------*/
859
860 #if (defined __STDC__ || defined __C99__FUNC__ \
861 || defined __cplusplus || defined _MSC_VER)
862 static void
863 yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
864 #else
865 static void
866 yy_stack_print (bottom, top)
867 yytype_int16 *bottom;
868 yytype_int16 *top;
869 #endif
870 {
871 YYFPRINTF (stderr, "Stack now");
872 for (; bottom <= top; ++bottom)
873 YYFPRINTF (stderr, " %d", *bottom);
874 YYFPRINTF (stderr, "\n");
875 }
876
877 # define YY_STACK_PRINT(Bottom, Top) \
878 do { \
879 if (yydebug) \
880 yy_stack_print ((Bottom), (Top)); \
881 } while (YYID (0))
882
883
884 /*------------------------------------------------.
885 | Report that the YYRULE is going to be reduced. |
886 `------------------------------------------------*/
887
888 #if (defined __STDC__ || defined __C99__FUNC__ \
889 || defined __cplusplus || defined _MSC_VER)
890 static void
891 yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
892 #else
893 static void
894 yy_reduce_print (yyvsp, yyrule)
895 YYSTYPE *yyvsp;
896 int yyrule;
897 #endif
898 {
899 int yynrhs = yyr2[yyrule];
900 int yyi;
901 unsigned long int yylno = yyrline[yyrule];
902 YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
903 yyrule - 1, yylno);
904 /* The symbols being reduced. */
905 for (yyi = 0; yyi < yynrhs; yyi++)
906 {
907 fprintf (stderr, " $%d = ", yyi + 1);
908 yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
909 &(yyvsp[(yyi + 1) - (yynrhs)])
910 );
911 fprintf (stderr, "\n");
912 }
913 }
914
915 # define YY_REDUCE_PRINT(Rule) \
916 do { \
917 if (yydebug) \
918 yy_reduce_print (yyvsp, Rule); \
919 } while (YYID (0))
920
921 /* Nonzero means print parse trace. It is left uninitialized so that
922 multiple parsers can coexist. */
923 int yydebug;
924 #else /* !YYDEBUG */
925 # define YYDPRINTF(Args)
926 # define YY_SYMBOL_PRINT(Title, Type, Value, Location)
927 # define YY_STACK_PRINT(Bottom, Top)
928 # define YY_REDUCE_PRINT(Rule)
929 #endif /* !YYDEBUG */
930
931
932 /* YYINITDEPTH -- initial size of the parser's stacks. */
933 #ifndef YYINITDEPTH
934 # define YYINITDEPTH 200
935 #endif
936
937 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
938 if the built-in stack extension method is used).
939
940 Do not make this value too large; the results are undefined if
941 YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
942 evaluated with infinite-precision integer arithmetic. */
943
944 #ifndef YYMAXDEPTH
945 # define YYMAXDEPTH 10000
946 #endif
947
948 \f
949
950 #if YYERROR_VERBOSE
951
952 # ifndef yystrlen
953 # if defined __GLIBC__ && defined _STRING_H
954 # define yystrlen strlen
955 # else
956 /* Return the length of YYSTR. */
957 #if (defined __STDC__ || defined __C99__FUNC__ \
958 || defined __cplusplus || defined _MSC_VER)
959 static YYSIZE_T
960 yystrlen (const char *yystr)
961 #else
962 static YYSIZE_T
963 yystrlen (yystr)
964 const char *yystr;
965 #endif
966 {
967 YYSIZE_T yylen;
968 for (yylen = 0; yystr[yylen]; yylen++)
969 continue;
970 return yylen;
971 }
972 # endif
973 # endif
974
975 # ifndef yystpcpy
976 # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
977 # define yystpcpy stpcpy
978 # else
979 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
980 YYDEST. */
981 #if (defined __STDC__ || defined __C99__FUNC__ \
982 || defined __cplusplus || defined _MSC_VER)
983 static char *
984 yystpcpy (char *yydest, const char *yysrc)
985 #else
986 static char *
987 yystpcpy (yydest, yysrc)
988 char *yydest;
989 const char *yysrc;
990 #endif
991 {
992 char *yyd = yydest;
993 const char *yys = yysrc;
994
995 while ((*yyd++ = *yys++) != '\0')
996 continue;
997
998 return yyd - 1;
999 }
1000 # endif
1001 # endif
1002
1003 # ifndef yytnamerr
1004 /* Copy to YYRES the contents of YYSTR after stripping away unnecessary
1005 quotes and backslashes, so that it's suitable for yyerror. The
1006 heuristic is that double-quoting is unnecessary unless the string
1007 contains an apostrophe, a comma, or backslash (other than
1008 backslash-backslash). YYSTR is taken from yytname. If YYRES is
1009 null, do not copy; instead, return the length of what the result
1010 would have been. */
1011 static YYSIZE_T
1012 yytnamerr (char *yyres, const char *yystr)
1013 {
1014 if (*yystr == '"')
1015 {
1016 YYSIZE_T yyn = 0;
1017 char const *yyp = yystr;
1018
1019 for (;;)
1020 switch (*++yyp)
1021 {
1022 case '\'':
1023 case ',':
1024 goto do_not_strip_quotes;
1025
1026 case '\\':
1027 if (*++yyp != '\\')
1028 goto do_not_strip_quotes;
1029 /* Fall through. */
1030 default:
1031 if (yyres)
1032 yyres[yyn] = *yyp;
1033 yyn++;
1034 break;
1035
1036 case '"':
1037 if (yyres)
1038 yyres[yyn] = '\0';
1039 return yyn;
1040 }
1041 do_not_strip_quotes: ;
1042 }
1043
1044 if (! yyres)
1045 return yystrlen (yystr);
1046
1047 return yystpcpy (yyres, yystr) - yyres;
1048 }
1049 # endif
1050
1051 /* Copy into YYRESULT an error message about the unexpected token
1052 YYCHAR while in state YYSTATE. Return the number of bytes copied,
1053 including the terminating null byte. If YYRESULT is null, do not
1054 copy anything; just return the number of bytes that would be
1055 copied. As a special case, return 0 if an ordinary "syntax error"
1056 message will do. Return YYSIZE_MAXIMUM if overflow occurs during
1057 size calculation. */
1058 static YYSIZE_T
1059 yysyntax_error (char *yyresult, int yystate, int yychar)
1060 {
1061 int yyn = yypact[yystate];
1062
1063 if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
1064 return 0;
1065 else
1066 {
1067 int yytype = YYTRANSLATE (yychar);
1068 YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
1069 YYSIZE_T yysize = yysize0;
1070 YYSIZE_T yysize1;
1071 int yysize_overflow = 0;
1072 enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
1073 char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
1074 int yyx;
1075
1076 # if 0
1077 /* This is so xgettext sees the translatable formats that are
1078 constructed on the fly. */
1079 YY_("syntax error, unexpected %s");
1080 YY_("syntax error, unexpected %s, expecting %s");
1081 YY_("syntax error, unexpected %s, expecting %s or %s");
1082 YY_("syntax error, unexpected %s, expecting %s or %s or %s");
1083 YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
1084 # endif
1085 char *yyfmt;
1086 char const *yyf;
1087 static char const yyunexpected[] = "syntax error, unexpected %s";
1088 static char const yyexpecting[] = ", expecting %s";
1089 static char const yyor[] = " or %s";
1090 char yyformat[sizeof yyunexpected
1091 + sizeof yyexpecting - 1
1092 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
1093 * (sizeof yyor - 1))];
1094 char const *yyprefix = yyexpecting;
1095
1096 /* Start YYX at -YYN if negative to avoid negative indexes in
1097 YYCHECK. */
1098 int yyxbegin = yyn < 0 ? -yyn : 0;
1099
1100 /* Stay within bounds of both yycheck and yytname. */
1101 int yychecklim = YYLAST - yyn + 1;
1102 int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
1103 int yycount = 1;
1104
1105 yyarg[0] = yytname[yytype];
1106 yyfmt = yystpcpy (yyformat, yyunexpected);
1107
1108 for (yyx = yyxbegin; yyx < yyxend; ++yyx)
1109 if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
1110 {
1111 if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
1112 {
1113 yycount = 1;
1114 yysize = yysize0;
1115 yyformat[sizeof yyunexpected - 1] = '\0';
1116 break;
1117 }
1118 yyarg[yycount++] = yytname[yyx];
1119 yysize1 = yysize + yytnamerr (0, yytname[yyx]);
1120 yysize_overflow |= (yysize1 < yysize);
1121 yysize = yysize1;
1122 yyfmt = yystpcpy (yyfmt, yyprefix);
1123 yyprefix = yyor;
1124 }
1125
1126 yyf = YY_(yyformat);
1127 yysize1 = yysize + yystrlen (yyf);
1128 yysize_overflow |= (yysize1 < yysize);
1129 yysize = yysize1;
1130
1131 if (yysize_overflow)
1132 return YYSIZE_MAXIMUM;
1133
1134 if (yyresult)
1135 {
1136 /* Avoid sprintf, as that infringes on the user's name space.
1137 Don't have undefined behavior even if the translation
1138 produced a string with the wrong number of "%s"s. */
1139 char *yyp = yyresult;
1140 int yyi = 0;
1141 while ((*yyp = *yyf) != '\0')
1142 {
1143 if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
1144 {
1145 yyp += yytnamerr (yyp, yyarg[yyi++]);
1146 yyf += 2;
1147 }
1148 else
1149 {
1150 yyp++;
1151 yyf++;
1152 }
1153 }
1154 }
1155 return yysize;
1156 }
1157 }
1158 #endif /* YYERROR_VERBOSE */
1159 \f
1160
1161 /*-----------------------------------------------.
1162 | Release the memory associated to this symbol. |
1163 `-----------------------------------------------*/
1164
1165 /*ARGSUSED*/
1166 #if (defined __STDC__ || defined __C99__FUNC__ \
1167 || defined __cplusplus || defined _MSC_VER)
1168 static void
1169 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
1170 #else
1171 static void
1172 yydestruct (yymsg, yytype, yyvaluep)
1173 const char *yymsg;
1174 int yytype;
1175 YYSTYPE *yyvaluep;
1176 #endif
1177 {
1178 YYUSE (yyvaluep);
1179
1180 if (!yymsg)
1181 yymsg = "Deleting";
1182 YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
1183
1184 switch (yytype)
1185 {
1186
1187 default:
1188 break;
1189 }
1190 }
1191 \f
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 {
1326 /* Get the current used size of the three stacks, in elements. */
1327 YYSIZE_T yysize = yyssp - yyss + 1;
1328
1329 #ifdef yyoverflow
1330 {
1331 /* Give user a chance to reallocate the stack. Use copies of
1332 these so that the &'s don't force the real ones into
1333 memory. */
1334 YYSTYPE *yyvs1 = yyvs;
1335 yytype_int16 *yyss1 = yyss;
1336
1337
1338 /* Each stack pointer address is followed by the size of the
1339 data in use in that stack, in bytes. This used to be a
1340 conditional around just the two extra args, but that might
1341 be undefined if yyoverflow is a macro. */
1342 yyoverflow (YY_("memory exhausted"),
1343 &yyss1, yysize * sizeof (*yyssp),
1344 &yyvs1, yysize * sizeof (*yyvsp),
1345
1346 &yystacksize);
1347
1348 yyss = yyss1;
1349 yyvs = yyvs1;
1350 }
1351 #else /* no yyoverflow */
1352 # ifndef YYSTACK_RELOCATE
1353 goto yyexhaustedlab;
1354 # else
1355 /* Extend the stack our own way. */
1356 if (YYMAXDEPTH <= yystacksize)
1357 goto yyexhaustedlab;
1358 yystacksize *= 2;
1359 if (YYMAXDEPTH < yystacksize)
1360 yystacksize = YYMAXDEPTH;
1361
1362 {
1363 yytype_int16 *yyss1 = yyss;
1364 union yyalloc *yyptr =
1365 (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
1366 if (! yyptr)
1367 goto yyexhaustedlab;
1368 YYSTACK_RELOCATE (yyss);
1369 YYSTACK_RELOCATE (yyvs);
1370
1371 # undef YYSTACK_RELOCATE
1372 if (yyss1 != yyssa)
1373 YYSTACK_FREE (yyss1);
1374 }
1375 # endif
1376 #endif /* no yyoverflow */
1377
1378 yyssp = yyss + yysize - 1;
1379 yyvsp = yyvs + yysize - 1;
1380
1381
1382 YYDPRINTF ((stderr, "Stack size increased to %lu\n",
1383 (unsigned long int) yystacksize));
1384
1385 if (yyss + yystacksize - 1 <= yyssp)
1386 YYABORT;
1387 }
1388
1389 YYDPRINTF ((stderr, "Entering state %d\n", yystate));
1390
1391 goto yybackup;
1392
1393 /*-----------.
1394 | yybackup. |
1395 `-----------*/
1396 yybackup:
1397
1398 /* Do appropriate processing given the current state. Read a
1399 look-ahead token if we need one and don't already have one. */
1400
1401 /* First try to decide what to do without reference to look-ahead token. */
1402 yyn = yypact[yystate];
1403 if (yyn == YYPACT_NINF)
1404 goto yydefault;
1405
1406 /* Not known => get a look-ahead token if don't already have one. */
1407
1408 /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
1409 if (yychar == YYEMPTY)
1410 {
1411 YYDPRINTF ((stderr, "Reading a token: "));
1412 yychar = YYLEX;
1413 }
1414
1415 if (yychar <= YYEOF)
1416 {
1417 yychar = yytoken = YYEOF;
1418 YYDPRINTF ((stderr, "Now at end of input.\n"));
1419 }
1420 else
1421 {
1422 yytoken = YYTRANSLATE (yychar);
1423 YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
1424 }
1425
1426 /* If the proper action on seeing token YYTOKEN is to reduce or to
1427 detect an error, take that action. */
1428 yyn += yytoken;
1429 if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
1430 goto yydefault;
1431 yyn = yytable[yyn];
1432 if (yyn <= 0)
1433 {
1434 if (yyn == 0 || yyn == YYTABLE_NINF)
1435 goto yyerrlab;
1436 yyn = -yyn;
1437 goto yyreduce;
1438 }
1439
1440 if (yyn == YYFINAL)
1441 YYACCEPT;
1442
1443 /* Count tokens shifted since error; after three, turn off error
1444 status. */
1445 if (yyerrstatus)
1446 yyerrstatus--;
1447
1448 /* Shift the look-ahead token. */
1449 YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
1450
1451 /* Discard the shifted token unless it is eof. */
1452 if (yychar != YYEOF)
1453 yychar = YYEMPTY;
1454
1455 yystate = yyn;
1456 *++yyvsp = yylval;
1457
1458 goto yynewstate;
1459
1460
1461 /*-----------------------------------------------------------.
1462 | yydefault -- do the default action for the current state. |
1463 `-----------------------------------------------------------*/
1464 yydefault:
1465 yyn = yydefact[yystate];
1466 if (yyn == 0)
1467 goto yyerrlab;
1468 goto yyreduce;
1469
1470
1471 /*-----------------------------.
1472 | yyreduce -- Do a reduction. |
1473 `-----------------------------*/
1474 yyreduce:
1475 /* yyn is the number of a rule to reduce with. */
1476 yylen = yyr2[yyn];
1477
1478 /* If YYLEN is nonzero, implement the default value of the action:
1479 `$$ = $1'.
1480
1481 Otherwise, the following line sets YYVAL to garbage.
1482 This behavior is undocumented and Bison
1483 users should not rely upon it. Assigning to YYVAL
1484 unconditionally makes the parser a bit smaller, and it avoids a
1485 GCC warning that YYVAL may be used uninitialized. */
1486 yyval = yyvsp[1-yylen];
1487
1488
1489 YY_REDUCE_PRINT (yyn);
1490 switch (yyn)
1491 {
1492 case 2:
1493 #line 145 "OSUnserializeXML.y"
1494 { yyerror("unexpected end of buffer");
1495 YYERROR;
1496 ;}
1497 break;
1498
1499 case 3:
1500 #line 148 "OSUnserializeXML.y"
1501 { STATE->parsedObject = (yyvsp[(1) - (1)])->object;
1502 (yyvsp[(1) - (1)])->object = 0;
1503 freeObject(STATE, (yyvsp[(1) - (1)]));
1504 YYACCEPT;
1505 ;}
1506 break;
1507
1508 case 4:
1509 #line 153 "OSUnserializeXML.y"
1510 { yyerror("syntax error");
1511 YYERROR;
1512 ;}
1513 break;
1514
1515 case 5:
1516 #line 158 "OSUnserializeXML.y"
1517 { (yyval) = buildDictionary(STATE, (yyvsp[(1) - (1)])); ;}
1518 break;
1519
1520 case 6:
1521 #line 159 "OSUnserializeXML.y"
1522 { (yyval) = buildArray(STATE, (yyvsp[(1) - (1)])); ;}
1523 break;
1524
1525 case 7:
1526 #line 160 "OSUnserializeXML.y"
1527 { (yyval) = buildSet(STATE, (yyvsp[(1) - (1)])); ;}
1528 break;
1529
1530 case 8:
1531 #line 161 "OSUnserializeXML.y"
1532 { (yyval) = buildString(STATE, (yyvsp[(1) - (1)])); ;}
1533 break;
1534
1535 case 9:
1536 #line 162 "OSUnserializeXML.y"
1537 { (yyval) = buildData(STATE, (yyvsp[(1) - (1)])); ;}
1538 break;
1539
1540 case 10:
1541 #line 163 "OSUnserializeXML.y"
1542 { (yyval) = buildNumber(STATE, (yyvsp[(1) - (1)])); ;}
1543 break;
1544
1545 case 11:
1546 #line 164 "OSUnserializeXML.y"
1547 { (yyval) = buildBoolean(STATE, (yyvsp[(1) - (1)])); ;}
1548 break;
1549
1550 case 12:
1551 #line 165 "OSUnserializeXML.y"
1552 { (yyval) = retrieveObject(STATE, (yyvsp[(1) - (1)])->idref);
1553 if ((yyval)) {
1554 (yyval)->object->retain();
1555 } else {
1556 yyerror("forward reference detected");
1557 YYERROR;
1558 }
1559 freeObject(STATE, (yyvsp[(1) - (1)]));
1560 ;}
1561 break;
1562
1563 case 13:
1564 #line 178 "OSUnserializeXML.y"
1565 { (yyval) = (yyvsp[(1) - (2)]);
1566 (yyval)->elements = NULL;
1567 ;}
1568 break;
1569
1570 case 14:
1571 #line 181 "OSUnserializeXML.y"
1572 { (yyval) = (yyvsp[(1) - (3)]);
1573 (yyval)->elements = (yyvsp[(2) - (3)]);
1574 ;}
1575 break;
1576
1577 case 17:
1578 #line 188 "OSUnserializeXML.y"
1579 { (yyval) = (yyvsp[(2) - (2)]);
1580 (yyval)->next = (yyvsp[(1) - (2)]);
1581 ;}
1582 break;
1583
1584 case 18:
1585 #line 193 "OSUnserializeXML.y"
1586 { (yyval) = (yyvsp[(1) - (2)]);
1587 (yyval)->key = (OSString *)(yyval)->object;
1588 (yyval)->object = (yyvsp[(2) - (2)])->object;
1589 (yyval)->next = NULL;
1590 (yyvsp[(2) - (2)])->object = 0;
1591 freeObject(STATE, (yyvsp[(2) - (2)]));
1592 ;}
1593 break;
1594
1595 case 19:
1596 #line 202 "OSUnserializeXML.y"
1597 { (yyval) = buildString(STATE, (yyvsp[(1) - (1)])); ;}
1598 break;
1599
1600 case 20:
1601 #line 207 "OSUnserializeXML.y"
1602 { (yyval) = (yyvsp[(1) - (2)]);
1603 (yyval)->elements = NULL;
1604 ;}
1605 break;
1606
1607 case 21:
1608 #line 210 "OSUnserializeXML.y"
1609 { (yyval) = (yyvsp[(1) - (3)]);
1610 (yyval)->elements = (yyvsp[(2) - (3)]);
1611 ;}
1612 break;
1613
1614 case 23:
1615 #line 216 "OSUnserializeXML.y"
1616 { (yyval) = (yyvsp[(1) - (2)]);
1617 (yyval)->elements = NULL;
1618 ;}
1619 break;
1620
1621 case 24:
1622 #line 219 "OSUnserializeXML.y"
1623 { (yyval) = (yyvsp[(1) - (3)]);
1624 (yyval)->elements = (yyvsp[(2) - (3)]);
1625 ;}
1626 break;
1627
1628 case 26:
1629 #line 225 "OSUnserializeXML.y"
1630 { (yyval) = (yyvsp[(1) - (1)]);
1631 (yyval)->next = NULL;
1632 ;}
1633 break;
1634
1635 case 27:
1636 #line 228 "OSUnserializeXML.y"
1637 { (yyval) = (yyvsp[(2) - (2)]);
1638 (yyval)->next = (yyvsp[(1) - (2)]);
1639 ;}
1640 break;
1641
1642
1643 /* Line 1267 of yacc.c. */
1644 #line 1595 "OSUnserializeXML.tab.c"
1645 default: break;
1646 }
1647 YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
1648
1649 YYPOPSTACK (yylen);
1650 yylen = 0;
1651 YY_STACK_PRINT (yyss, yyssp);
1652
1653 *++yyvsp = yyval;
1654
1655
1656 /* Now `shift' the result of the reduction. Determine what state
1657 that goes to, based on the state we popped back to and the rule
1658 number reduced by. */
1659
1660 yyn = yyr1[yyn];
1661
1662 yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
1663 if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1664 yystate = yytable[yystate];
1665 else
1666 yystate = yydefgoto[yyn - YYNTOKENS];
1667
1668 goto yynewstate;
1669
1670
1671 /*------------------------------------.
1672 | yyerrlab -- here on detecting error |
1673 `------------------------------------*/
1674 yyerrlab:
1675 /* If not already recovering from an error, report this error. */
1676 if (!yyerrstatus)
1677 {
1678 ++yynerrs;
1679 #if ! YYERROR_VERBOSE
1680 yyerror (YY_("syntax error"));
1681 #else
1682 {
1683 YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
1684 if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
1685 {
1686 YYSIZE_T yyalloc = 2 * yysize;
1687 if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
1688 yyalloc = YYSTACK_ALLOC_MAXIMUM;
1689 if (yymsg != yymsgbuf)
1690 YYSTACK_FREE (yymsg);
1691 yymsg = (char *) YYSTACK_ALLOC (yyalloc);
1692 if (yymsg)
1693 yymsg_alloc = yyalloc;
1694 else
1695 {
1696 yymsg = yymsgbuf;
1697 yymsg_alloc = sizeof yymsgbuf;
1698 }
1699 }
1700
1701 if (0 < yysize && yysize <= yymsg_alloc)
1702 {
1703 (void) yysyntax_error (yymsg, yystate, yychar);
1704 yyerror (yymsg);
1705 }
1706 else
1707 {
1708 yyerror (YY_("syntax error"));
1709 if (yysize != 0)
1710 goto yyexhaustedlab;
1711 }
1712 }
1713 #endif
1714 }
1715
1716
1717
1718 if (yyerrstatus == 3)
1719 {
1720 /* If just tried and failed to reuse look-ahead token after an
1721 error, discard it. */
1722
1723 if (yychar <= YYEOF)
1724 {
1725 /* Return failure if at end of input. */
1726 if (yychar == YYEOF)
1727 YYABORT;
1728 }
1729 else
1730 {
1731 yydestruct ("Error: discarding",
1732 yytoken, &yylval);
1733 yychar = YYEMPTY;
1734 }
1735 }
1736
1737 /* Else will try to reuse look-ahead token after shifting the error
1738 token. */
1739 goto yyerrlab1;
1740
1741
1742 /*---------------------------------------------------.
1743 | yyerrorlab -- error raised explicitly by YYERROR. |
1744 `---------------------------------------------------*/
1745 yyerrorlab:
1746
1747 /* Pacify compilers like GCC when the user code never invokes
1748 YYERROR and the label yyerrorlab therefore never appears in user
1749 code. */
1750 if (/*CONSTCOND*/ 0)
1751 goto yyerrorlab;
1752
1753 /* Do not reclaim the symbols of the rule which action triggered
1754 this YYERROR. */
1755 YYPOPSTACK (yylen);
1756 yylen = 0;
1757 YY_STACK_PRINT (yyss, yyssp);
1758 yystate = *yyssp;
1759 goto yyerrlab1;
1760
1761
1762 /*-------------------------------------------------------------.
1763 | yyerrlab1 -- common code for both syntax error and YYERROR. |
1764 `-------------------------------------------------------------*/
1765 yyerrlab1:
1766 yyerrstatus = 3; /* Each real token shifted decrements this. */
1767
1768 for (;;)
1769 {
1770 yyn = yypact[yystate];
1771 if (yyn != YYPACT_NINF)
1772 {
1773 yyn += YYTERROR;
1774 if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
1775 {
1776 yyn = yytable[yyn];
1777 if (0 < yyn)
1778 break;
1779 }
1780 }
1781
1782 /* Pop the current state because it cannot handle the error token. */
1783 if (yyssp == yyss)
1784 YYABORT;
1785
1786
1787 yydestruct ("Error: popping",
1788 yystos[yystate], yyvsp);
1789 YYPOPSTACK (1);
1790 yystate = *yyssp;
1791 YY_STACK_PRINT (yyss, yyssp);
1792 }
1793
1794 if (yyn == YYFINAL)
1795 YYACCEPT;
1796
1797 *++yyvsp = yylval;
1798
1799
1800 /* Shift the error token. */
1801 YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
1802
1803 yystate = yyn;
1804 goto yynewstate;
1805
1806
1807 /*-------------------------------------.
1808 | yyacceptlab -- YYACCEPT comes here. |
1809 `-------------------------------------*/
1810 yyacceptlab:
1811 yyresult = 0;
1812 goto yyreturn;
1813
1814 /*-----------------------------------.
1815 | yyabortlab -- YYABORT comes here. |
1816 `-----------------------------------*/
1817 yyabortlab:
1818 yyresult = 1;
1819 goto yyreturn;
1820
1821 #ifndef yyoverflow
1822 /*-------------------------------------------------.
1823 | yyexhaustedlab -- memory exhaustion comes here. |
1824 `-------------------------------------------------*/
1825 yyexhaustedlab:
1826 yyerror (YY_("memory exhausted"));
1827 yyresult = 2;
1828 /* Fall through. */
1829 #endif
1830
1831 yyreturn:
1832 if (yychar != YYEOF && yychar != YYEMPTY)
1833 yydestruct ("Cleanup: discarding lookahead",
1834 yytoken, &yylval);
1835 /* Do not reclaim the symbols of the rule which action triggered
1836 this YYABORT or YYACCEPT. */
1837 YYPOPSTACK (yylen);
1838 YY_STACK_PRINT (yyss, yyssp);
1839 while (yyssp != yyss)
1840 {
1841 yydestruct ("Cleanup: popping",
1842 yystos[*yyssp], yyvsp);
1843 YYPOPSTACK (1);
1844 }
1845 #ifndef yyoverflow
1846 if (yyss != yyssa)
1847 YYSTACK_FREE (yyss);
1848 #endif
1849 #if YYERROR_VERBOSE
1850 if (yymsg != yymsgbuf)
1851 YYSTACK_FREE (yymsg);
1852 #endif
1853 /* Make sure YYID is used. */
1854 return YYID (yyresult);
1855 }
1856
1857
1858 #line 250 "OSUnserializeXML.y"
1859
1860
1861 int
1862 OSUnserializeerror(parser_state_t * state, const char *s) /* Called by yyparse on errors */
1863 {
1864 if (state->errorString) {
1865 char tempString[128];
1866 snprintf(tempString, 128, "OSUnserializeXML: %s near line %d\n", s, state->lineNumber);
1867 *(state->errorString) = OSString::withCString(tempString);
1868 }
1869
1870 return 0;
1871 }
1872
1873 #define TAG_MAX_LENGTH 32
1874 #define TAG_MAX_ATTRIBUTES 32
1875 #define TAG_BAD 0
1876 #define TAG_START 1
1877 #define TAG_END 2
1878 #define TAG_EMPTY 3
1879 #define TAG_IGNORE 4
1880
1881 #define currentChar() (state->parseBuffer[state->parseBufferIndex])
1882 #define nextChar() (state->parseBuffer[++state->parseBufferIndex])
1883 #define prevChar() (state->parseBuffer[state->parseBufferIndex - 1])
1884
1885 #define isSpace(c) ((c) == ' ' || (c) == '\t')
1886 #define isAlpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
1887 #define isDigit(c) ((c) >= '0' && (c) <= '9')
1888 #define isAlphaDigit(c) ((c) >= 'a' && (c) <= 'f')
1889 #define isHexDigit(c) (isDigit(c) || isAlphaDigit(c))
1890 #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-'))
1891
1892 static int
1893 getTag(parser_state_t *state,
1894 char tag[TAG_MAX_LENGTH],
1895 int *attributeCount,
1896 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH],
1897 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] )
1898 {
1899 int length = 0;
1900 int c = currentChar();
1901 int tagType = TAG_START;
1902
1903 *attributeCount = 0;
1904
1905 if (c != '<') return TAG_BAD;
1906 c = nextChar(); // skip '<'
1907
1908
1909 // <!TAG declarations >
1910 // <!-- comments -->
1911 if (c == '!') {
1912 c = nextChar();
1913 bool isComment = (c == '-') && ((c = nextChar()) != 0) && (c == '-');
1914 if (!isComment && !isAlpha(c)) return TAG_BAD; // <!1, <!-A, <!eos
1915
1916 while (c && (c = nextChar()) != 0) {
1917 if (c == '\n') state->lineNumber++;
1918 if (isComment) {
1919 if (c != '-') continue;
1920 c = nextChar();
1921 if (c != '-') continue;
1922 c = nextChar();
1923 }
1924 if (c == '>') {
1925 (void)nextChar();
1926 return TAG_IGNORE;
1927 }
1928 if (isComment) break;
1929 }
1930 return TAG_BAD;
1931 }
1932
1933 else
1934
1935 // <? Processing Instructions ?>
1936 if (c == '?') {
1937 while ((c = nextChar()) != 0) {
1938 if (c == '\n') state->lineNumber++;
1939 if (c != '?') continue;
1940 c = nextChar();
1941 if (c == '>') {
1942 (void)nextChar();
1943 return TAG_IGNORE;
1944 }
1945 }
1946 return TAG_BAD;
1947 }
1948
1949 else
1950
1951 // </ end tag >
1952 if (c == '/') {
1953 c = nextChar(); // skip '/'
1954 tagType = TAG_END;
1955 }
1956 if (!isAlpha(c)) return TAG_BAD;
1957
1958 /* find end of tag while copying it */
1959 while (isAlphaNumeric(c)) {
1960 tag[length++] = c;
1961 c = nextChar();
1962 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1963 }
1964
1965 tag[length] = 0;
1966
1967 // printf("tag %s, type %d\n", tag, tagType);
1968
1969 // look for attributes of the form attribute = "value" ...
1970 while ((c != '>') && (c != '/')) {
1971 while (isSpace(c)) c = nextChar();
1972
1973 length = 0;
1974 while (isAlphaNumeric(c)) {
1975 attributes[*attributeCount][length++] = c;
1976 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1977 c = nextChar();
1978 }
1979 attributes[*attributeCount][length] = 0;
1980
1981 while (isSpace(c)) c = nextChar();
1982
1983 if (c != '=') return TAG_BAD;
1984 c = nextChar();
1985
1986 while (isSpace(c)) c = nextChar();
1987
1988 if (c != '"') return TAG_BAD;
1989 c = nextChar();
1990 length = 0;
1991 while (c != '"') {
1992 values[*attributeCount][length++] = c;
1993 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
1994 c = nextChar();
1995 }
1996 values[*attributeCount][length] = 0;
1997
1998 c = nextChar(); // skip closing quote
1999
2000 // printf(" attribute '%s' = '%s', nextchar = '%c'\n",
2001 // attributes[*attributeCount], values[*attributeCount], c);
2002
2003 (*attributeCount)++;
2004 if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD;
2005 }
2006
2007 if (c == '/') {
2008 c = nextChar(); // skip '/'
2009 tagType = TAG_EMPTY;
2010 }
2011 if (c != '>') return TAG_BAD;
2012 c = nextChar(); // skip '>'
2013
2014 return tagType;
2015 }
2016
2017 static char *
2018 getString(parser_state_t *state)
2019 {
2020 int c = currentChar();
2021 int start, length, i, j;
2022 char * tempString;
2023
2024 start = state->parseBufferIndex;
2025 /* find end of string */
2026
2027 while (c != 0) {
2028 if (c == '\n') state->lineNumber++;
2029 if (c == '<') {
2030 break;
2031 }
2032 c = nextChar();
2033 }
2034
2035 if (c != '<') return 0;
2036
2037 length = state->parseBufferIndex - start;
2038
2039 /* copy to null terminated buffer */
2040 tempString = (char *)malloc(length + 1);
2041 if (tempString == 0) {
2042 printf("OSUnserializeXML: can't alloc temp memory\n");
2043 goto error;
2044 }
2045
2046 // copy out string in tempString
2047 // "&amp;" -> '&', "&lt;" -> '<', "&gt;" -> '>'
2048
2049 i = j = 0;
2050 while (i < length) {
2051 c = state->parseBuffer[start + i++];
2052 if (c != '&') {
2053 tempString[j++] = c;
2054 } else {
2055 if ((i+3) > length) goto error;
2056 c = state->parseBuffer[start + i++];
2057 if (c == 'l') {
2058 if (state->parseBuffer[start + i++] != 't') goto error;
2059 if (state->parseBuffer[start + i++] != ';') goto error;
2060 tempString[j++] = '<';
2061 continue;
2062 }
2063 if (c == 'g') {
2064 if (state->parseBuffer[start + i++] != 't') goto error;
2065 if (state->parseBuffer[start + i++] != ';') goto error;
2066 tempString[j++] = '>';
2067 continue;
2068 }
2069 if ((i+3) > length) goto error;
2070 if (c == 'a') {
2071 if (state->parseBuffer[start + i++] != 'm') goto error;
2072 if (state->parseBuffer[start + i++] != 'p') goto error;
2073 if (state->parseBuffer[start + i++] != ';') goto error;
2074 tempString[j++] = '&';
2075 continue;
2076 }
2077 goto error;
2078 }
2079 }
2080 tempString[j] = 0;
2081
2082 // printf("string %s\n", tempString);
2083
2084 return tempString;
2085
2086 error:
2087 if (tempString) free(tempString);
2088 return 0;
2089 }
2090
2091 static long long
2092 getNumber(parser_state_t *state)
2093 {
2094 unsigned long long n = 0;
2095 int base = 10;
2096 bool negate = false;
2097 int c = currentChar();
2098
2099 if (c == '0') {
2100 c = nextChar();
2101 if (c == 'x') {
2102 base = 16;
2103 c = nextChar();
2104 }
2105 }
2106 if (base == 10) {
2107 if (c == '-') {
2108 negate = true;
2109 c = nextChar();
2110 }
2111 while(isDigit(c)) {
2112 n = (n * base + c - '0');
2113 c = nextChar();
2114 }
2115 if (negate) {
2116 n = (unsigned long long)((long long)n * (long long)-1);
2117 }
2118 } else {
2119 while(isHexDigit(c)) {
2120 if (isDigit(c)) {
2121 n = (n * base + c - '0');
2122 } else {
2123 n = (n * base + 0xa + c - 'a');
2124 }
2125 c = nextChar();
2126 }
2127 }
2128 // printf("number 0x%x\n", (unsigned long)n);
2129 return n;
2130 }
2131
2132 // taken from CFXMLParsing/CFPropertyList.c
2133
2134 static const signed char __CFPLDataDecodeTable[128] = {
2135 /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
2136 /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
2137 /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
2138 /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
2139 /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
2140 /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
2141 /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
2142 /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1,
2143 /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6,
2144 /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14,
2145 /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
2146 /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
2147 /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
2148 /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
2149 /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
2150 /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
2151 };
2152
2153 #define DATA_ALLOC_SIZE 4096
2154
2155 static void *
2156 getCFEncodedData(parser_state_t *state, unsigned int *size)
2157 {
2158 int numeq = 0, acc = 0, cntr = 0;
2159 int tmpbufpos = 0, tmpbuflen = 0;
2160 unsigned char *tmpbuf = (unsigned char *)malloc(DATA_ALLOC_SIZE);
2161
2162 int c = currentChar();
2163 *size = 0;
2164
2165 while (c != '<') {
2166 c &= 0x7f;
2167 if (c == 0) {
2168 free(tmpbuf);
2169 return 0;
2170 }
2171 if (c == '=') numeq++; else numeq = 0;
2172 if (c == '\n') state->lineNumber++;
2173 if (__CFPLDataDecodeTable[c] < 0) {
2174 c = nextChar();
2175 continue;
2176 }
2177 cntr++;
2178 acc <<= 6;
2179 acc += __CFPLDataDecodeTable[c];
2180 if (0 == (cntr & 0x3)) {
2181 if (tmpbuflen <= tmpbufpos + 2) {
2182 tmpbuflen += DATA_ALLOC_SIZE;
2183 tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen);
2184 }
2185 tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
2186 if (numeq < 2)
2187 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
2188 if (numeq < 1)
2189 tmpbuf[tmpbufpos++] = acc & 0xff;
2190 }
2191 c = nextChar();
2192 }
2193 *size = tmpbufpos;
2194 if (*size == 0) {
2195 free(tmpbuf);
2196 return 0;
2197 }
2198 return tmpbuf;
2199 }
2200
2201 static void *
2202 getHexData(parser_state_t *state, unsigned int *size)
2203 {
2204 int c;
2205 unsigned char *d, *start, *lastStart;
2206
2207 start = lastStart = d = (unsigned char *)malloc(DATA_ALLOC_SIZE);
2208 c = currentChar();
2209
2210 while (c != '<') {
2211
2212 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
2213 if (c == '\n') {
2214 state->lineNumber++;
2215 c = nextChar();
2216 continue;
2217 }
2218
2219 // get high nibble
2220 if (isDigit(c)) {
2221 *d = (c - '0') << 4;
2222 } else if (isAlphaDigit(c)) {
2223 *d = (0xa + (c - 'a')) << 4;
2224 } else {
2225 goto error;
2226 }
2227
2228 // get low nibble
2229 c = nextChar();
2230 if (isDigit(c)) {
2231 *d |= c - '0';
2232 } else if (isAlphaDigit(c)) {
2233 *d |= 0xa + (c - 'a');
2234 } else {
2235 goto error;
2236 }
2237
2238 d++;
2239 if ((d - lastStart) >= DATA_ALLOC_SIZE) {
2240 int oldsize = d - start;
2241 start = (unsigned char *)realloc(start, oldsize + DATA_ALLOC_SIZE);
2242 d = lastStart = start + oldsize;
2243 }
2244 c = nextChar();
2245 }
2246
2247 *size = d - start;
2248 return start;
2249
2250 error:
2251
2252 *size = 0;
2253 free(start);
2254 return 0;
2255 }
2256
2257 static int
2258 yylex(YYSTYPE *lvalp, parser_state_t *state)
2259 {
2260 int c, i;
2261 int tagType;
2262 char tag[TAG_MAX_LENGTH];
2263 int attributeCount;
2264 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
2265 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
2266 object_t *object;
2267
2268 top:
2269 c = currentChar();
2270
2271 /* skip white space */
2272 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
2273
2274 /* keep track of line number, don't return \n's */
2275 if (c == '\n') {
2276 STATE->lineNumber++;
2277 (void)nextChar();
2278 goto top;
2279 }
2280
2281 // end of the buffer?
2282 if (!c) return 0;
2283
2284 tagType = getTag(STATE, tag, &attributeCount, attributes, values);
2285 if (tagType == TAG_BAD) return SYNTAX_ERROR;
2286 if (tagType == TAG_IGNORE) goto top;
2287
2288 // handle allocation and check for "ID" and "IDREF" tags up front
2289 *lvalp = object = newObject(STATE);
2290 object->idref = -1;
2291 for (i=0; i < attributeCount; i++) {
2292 if (attributes[i][0] == 'I' && attributes[i][1] == 'D') {
2293 // check for idref's, note: we ignore the tag, for
2294 // this to work correctly, all idrefs must be unique
2295 // across the whole serialization
2296 if (attributes[i][2] == 'R' && attributes[i][3] == 'E' &&
2297 attributes[i][4] == 'F' && !attributes[i][5]) {
2298 if (tagType != TAG_EMPTY) return SYNTAX_ERROR;
2299 object->idref = strtol(values[i], NULL, 0);
2300 return IDREF;
2301 }
2302 // check for id's
2303 if (!attributes[i][2]) {
2304 object->idref = strtol(values[i], NULL, 0);
2305 } else {
2306 return SYNTAX_ERROR;
2307 }
2308 }
2309 }
2310
2311 switch (*tag) {
2312 case 'a':
2313 if (!strcmp(tag, "array")) {
2314 if (tagType == TAG_EMPTY) {
2315 object->elements = NULL;
2316 return ARRAY;
2317 }
2318 return (tagType == TAG_START) ? '(' : ')';
2319 }
2320 break;
2321 case 'd':
2322 if (!strcmp(tag, "dict")) {
2323 if (tagType == TAG_EMPTY) {
2324 object->elements = NULL;
2325 return DICTIONARY;
2326 }
2327 return (tagType == TAG_START) ? '{' : '}';
2328 }
2329 if (!strcmp(tag, "data")) {
2330 unsigned int size;
2331 if (tagType == TAG_EMPTY) {
2332 object->data = NULL;
2333 object->size = 0;
2334 return DATA;
2335 }
2336
2337 bool isHexFormat = false;
2338 for (i=0; i < attributeCount; i++) {
2339 if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) {
2340 isHexFormat = true;
2341 break;
2342 }
2343 }
2344 // CF encoded is the default form
2345 if (isHexFormat) {
2346 object->data = getHexData(STATE, &size);
2347 } else {
2348 object->data = getCFEncodedData(STATE, &size);
2349 }
2350 object->size = size;
2351 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) {
2352 return SYNTAX_ERROR;
2353 }
2354 return DATA;
2355 }
2356 break;
2357 case 'f':
2358 if (!strcmp(tag, "false")) {
2359 if (tagType == TAG_EMPTY) {
2360 object->number = 0;
2361 return BOOLEAN;
2362 }
2363 }
2364 break;
2365 case 'i':
2366 if (!strcmp(tag, "integer")) {
2367 object->size = 64; // default
2368 for (i=0; i < attributeCount; i++) {
2369 if (!strcmp(attributes[i], "size")) {
2370 object->size = strtoul(values[i], NULL, 0);
2371 }
2372 }
2373 if (tagType == TAG_EMPTY) {
2374 object->number = 0;
2375 return NUMBER;
2376 }
2377 object->number = getNumber(STATE);
2378 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) {
2379 return SYNTAX_ERROR;
2380 }
2381 return NUMBER;
2382 }
2383 break;
2384 case 'k':
2385 if (!strcmp(tag, "key")) {
2386 if (tagType == TAG_EMPTY) return SYNTAX_ERROR;
2387 object->string = getString(STATE);
2388 if (!object->string) {
2389 return SYNTAX_ERROR;
2390 }
2391 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
2392 || strcmp(tag, "key")) {
2393 return SYNTAX_ERROR;
2394 }
2395 return KEY;
2396 }
2397 break;
2398 case 'p':
2399 if (!strcmp(tag, "plist")) {
2400 freeObject(STATE, object);
2401 goto top;
2402 }
2403 break;
2404 case 's':
2405 if (!strcmp(tag, "string")) {
2406 if (tagType == TAG_EMPTY) {
2407 object->string = (char *)malloc(1);
2408 object->string[0] = 0;
2409 return STRING;
2410 }
2411 object->string = getString(STATE);
2412 if (!object->string) {
2413 return SYNTAX_ERROR;
2414 }
2415 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END)
2416 || strcmp(tag, "string")) {
2417 return SYNTAX_ERROR;
2418 }
2419 return STRING;
2420 }
2421 if (!strcmp(tag, "set")) {
2422 if (tagType == TAG_EMPTY) {
2423 object->elements = NULL;
2424 return SET;;
2425 }
2426 if (tagType == TAG_START) {
2427 return '[';
2428 } else {
2429 return ']';
2430 }
2431 }
2432 break;
2433 case 't':
2434 if (!strcmp(tag, "true")) {
2435 if (tagType == TAG_EMPTY) {
2436 object->number = 1;
2437 return BOOLEAN;
2438 }
2439 }
2440 break;
2441 }
2442
2443 return SYNTAX_ERROR;
2444 }
2445
2446 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2447 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2448 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2449
2450 // "java" like allocation, if this code hits a syntax error in the
2451 // the middle of the parsed string we just bail with pointers hanging
2452 // all over place, this code helps keeps it all together
2453
2454 //static int object_count = 0;
2455
2456 object_t *
2457 newObject(parser_state_t *state)
2458 {
2459 object_t *o;
2460
2461 if (state->freeObjects) {
2462 o = state->freeObjects;
2463 state->freeObjects = state->freeObjects->next;
2464 } else {
2465 o = (object_t *)malloc(sizeof(object_t));
2466 // object_count++;
2467 bzero(o, sizeof(object_t));
2468 o->free = state->objects;
2469 state->objects = o;
2470 }
2471
2472 return o;
2473 }
2474
2475 void
2476 freeObject(parser_state_t * state, object_t *o)
2477 {
2478 o->next = state->freeObjects;
2479 state->freeObjects = o;
2480 }
2481
2482 void
2483 cleanupObjects(parser_state_t *state)
2484 {
2485 object_t *t, *o = state->objects;
2486
2487 while (o) {
2488 if (o->object) {
2489 // printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object);
2490 o->object->release();
2491 }
2492 if (o->data) {
2493 // printf("OSUnserializeXML: freeing object o=%x data=%x\n", (int)o, (int)o->data);
2494 free(o->data);
2495 }
2496 if (o->key) {
2497 // printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key);
2498 o->key->release();
2499 }
2500 if (o->string) {
2501 // printf("OSUnserializeXML: freeing object o=%x string=%x\n", (int)o, (int)o->string);
2502 free(o->string);
2503 }
2504
2505 t = o;
2506 o = o->free;
2507 free(t);
2508 // object_count--;
2509 }
2510 // printf("object_count = %d\n", object_count);
2511 }
2512
2513 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2514 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2515 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2516
2517 static void
2518 rememberObject(parser_state_t *state, int tag, OSObject *o)
2519 {
2520 char key[16];
2521 snprintf(key, 16, "%u", tag);
2522
2523 // printf("remember key %s\n", key);
2524
2525 state->tags->setObject(key, o);
2526 }
2527
2528 static object_t *
2529 retrieveObject(parser_state_t *state, int tag)
2530 {
2531 OSObject *ref;
2532 object_t *o;
2533 char key[16];
2534 snprintf(key, 16, "%u", tag);
2535
2536 // printf("retrieve key '%s'\n", key);
2537
2538 ref = state->tags->getObject(key);
2539 if (!ref) return 0;
2540
2541 o = newObject(state);
2542 o->object = ref;
2543 return o;
2544 }
2545
2546 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2547 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2548 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
2549
2550 object_t *
2551 buildDictionary(parser_state_t *state, object_t * header)
2552 {
2553 object_t *o, *t;
2554 int count = 0;
2555 OSDictionary *dict;
2556
2557 // get count and reverse order
2558 o = header->elements;
2559 header->elements = 0;
2560 while (o) {
2561 count++;
2562 t = o;
2563 o = o->next;
2564
2565 t->next = header->elements;
2566 header->elements = t;
2567 }
2568
2569 dict = OSDictionary::withCapacity(count);
2570 if (header->idref >= 0) rememberObject(state, header->idref, dict);
2571
2572 o = header->elements;
2573 while (o) {
2574 dict->setObject(o->key, o->object);
2575
2576 o->key->release();
2577 o->object->release();
2578 o->key = 0;
2579 o->object = 0;
2580
2581 t = o;
2582 o = o->next;
2583 freeObject(state, t);
2584 }
2585 o = header;
2586 o->object = dict;
2587 return o;
2588 };
2589
2590 object_t *
2591 buildArray(parser_state_t *state, object_t * header)
2592 {
2593 object_t *o, *t;
2594 int count = 0;
2595 OSArray *array;
2596
2597 // get count and reverse order
2598 o = header->elements;
2599 header->elements = 0;
2600 while (o) {
2601 count++;
2602 t = o;
2603 o = o->next;
2604
2605 t->next = header->elements;
2606 header->elements = t;
2607 }
2608
2609 array = OSArray::withCapacity(count);
2610 if (header->idref >= 0) rememberObject(state, header->idref, array);
2611
2612 o = header->elements;
2613 while (o) {
2614 array->setObject(o->object);
2615
2616 o->object->release();
2617 o->object = 0;
2618
2619 t = o;
2620 o = o->next;
2621 freeObject(state, t);
2622 }
2623 o = header;
2624 o->object = array;
2625 return o;
2626 };
2627
2628 object_t *
2629 buildSet(parser_state_t *state, object_t *header)
2630 {
2631 object_t *o = buildArray(state, header);
2632
2633 OSArray *array = (OSArray *)o->object;
2634 OSSet *set = OSSet::withArray(array, array->getCapacity());
2635
2636 // write over the reference created in buildArray
2637 if (header->idref >= 0) rememberObject(state, header->idref, set);
2638
2639 array->release();
2640 o->object = set;
2641 return o;
2642 };
2643
2644 object_t *
2645 buildString(parser_state_t *state, object_t *o)
2646 {
2647 OSString *string;
2648
2649 string = OSString::withCString(o->string);
2650 if (o->idref >= 0) rememberObject(state, o->idref, string);
2651
2652 free(o->string);
2653 o->string = 0;
2654 o->object = string;
2655
2656 return o;
2657 };
2658
2659 object_t *
2660 buildData(parser_state_t *state, object_t *o)
2661 {
2662 OSData *data;
2663
2664 if (o->size) {
2665 data = OSData::withBytes(o->data, o->size);
2666 } else {
2667 data = OSData::withCapacity(0);
2668 }
2669 if (o->idref >= 0) rememberObject(state, o->idref, data);
2670
2671 if (o->size) free(o->data);
2672 o->data = 0;
2673 o->object = data;
2674 return o;
2675 };
2676
2677 object_t *
2678 buildNumber(parser_state_t *state, object_t *o)
2679 {
2680 OSNumber *number = OSNumber::withNumber(o->number, o->size);
2681
2682 if (o->idref >= 0) rememberObject(state, o->idref, number);
2683
2684 o->object = number;
2685 return o;
2686 };
2687
2688 object_t *
2689 buildBoolean(parser_state_t *state __unused, object_t *o)
2690 {
2691 o->object = ((o->number == 0) ? kOSBooleanFalse : kOSBooleanTrue);
2692 o->object->retain();
2693 return o;
2694 };
2695
2696 OSObject*
2697 OSUnserializeXML(const char *buffer, OSString **errorString)
2698 {
2699 OSObject *object;
2700 parser_state_t *state = (parser_state_t *)malloc(sizeof(parser_state_t));
2701
2702 if ((!state) || (!buffer)) return 0;
2703
2704 // just in case
2705 if (errorString) *errorString = NULL;
2706
2707 state->parseBuffer = buffer;
2708 state->parseBufferIndex = 0;
2709 state->lineNumber = 1;
2710 state->objects = 0;
2711 state->freeObjects = 0;
2712 state->tags = OSDictionary::withCapacity(128);
2713 state->errorString = errorString;
2714 state->parsedObject = 0;
2715
2716 (void)yyparse((void *)state);
2717
2718 object = state->parsedObject;
2719
2720 cleanupObjects(state);
2721 state->tags->release();
2722 free(state);
2723
2724 return object;
2725 }
2726
2727
2728 //
2729 //
2730 //
2731 //
2732 //
2733 // DO NOT EDIT OSUnserializeXML.cpp!
2734 //
2735 // this means you!
2736 //
2737 //
2738 //
2739 //
2740 //
2741