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