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