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