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