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