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