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