1 /* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23 /* OSUnserializeXML.y created by rsulack on Tue Oct 12 1999 */ 24 25 // XML parser for unserializing OSContainer objects 26 // 27 // to build : 28 // bison -p OSUnserializeXML OSUnserializeXML.y 29 // head -50 OSUnserializeXML.y > OSUnserializeXML.cpp 30 // sed -e "s/stdio.h/stddef.h/" < OSUnserializeXML.tab.c >> OSUnserializeXML.cpp 31 // 32 // when changing code check in both OSUnserializeXML.y and OSUnserializeXML.cpp 33 // 34 // 35 // 36 // 37 // 38 // 39 // 40 // DO NOT EDIT OSUnserializeXML.cpp! 41 // 42 // this means you! 43 // 44 // 45 // 46 // 47 // 48 // 49 // 50 51 52 /* A Bison parser, made from OSUnserializeXML.y 53 by GNU Bison version 1.28 */ 54 55 #define YYBISON 1 /* Identify Bison output. */ 56 57 #define yyparse OSUnserializeXMLparse 58 #define yylex OSUnserializeXMLlex 59 #define yyerror OSUnserializeXMLerror 60 #define yylval OSUnserializeXMLlval 61 #define yychar OSUnserializeXMLchar 62 #define yydebug OSUnserializeXMLdebug 63 #define yynerrs OSUnserializeXMLnerrs 64 #define ARRAY 257 65 #define BOOLEAN 258 66 #define DATA 259 67 #define DICTIONARY 260 68 #define IDREF 261 69 #define KEY 262 70 #define NUMBER 263 71 #define SET 264 72 #define STRING 265 73 #define SYNTAX_ERROR 266 74 75 #line 52 "OSUnserializeXML.y" 76 77 #include <string.h> 78 #include <libkern/c++/OSMetaClass.h> 79 #include <libkern/c++/OSContainers.h> 80 #include <libkern/c++/OSLib.h> 81 82 typedef struct object { 83 struct object *next; 84 struct object *free; 85 struct object *elements; 86 OSObject *object; 87 const OSSymbol *key; // for dictionary 88 int size; 89 void *data; // for data 90 char *string; // for string & symbol 91 long long number; // for number 92 int idref; 93 } object_t; 94 95 static int yyparse(); 96 static int yyerror(char *s); 97 static int yylex(); 98 99 static object_t * newObject(); 100 static void freeObject(object_t *o); 101 102 static object_t *buildOSDictionary(object_t *); 103 static object_t *buildOSArray(object_t *); 104 static object_t *buildOSSet(object_t *); 105 static object_t *buildOSString(object_t *); 106 static object_t *buildKey(object_t *); 107 static object_t *buildOSData(object_t *); 108 static object_t *buildOSNumber(object_t *); 109 static object_t *buildOSBoolean(object_t *o); 110 111 static void rememberObject(int, OSObject *); 112 static object_t *retrieveObject(int); 113 114 // resultant object of parsed text 115 static OSObject *parsedObject; 116 117 #define YYSTYPE object_t * 118 119 extern "C" { 120 extern void *kern_os_malloc(size_t size); 121 extern void *kern_os_realloc(void * addr, size_t size); 122 extern void kern_os_free(void * addr); 123 124 //XXX shouldn't have to define these 125 extern long strtol(const char *, char **, int); 126 extern unsigned long strtoul(const char *, char **, int); 127 128 } /* extern "C" */ 129 130 #define malloc(s) kern_os_malloc(s) 131 #define realloc(a, s) kern_os_realloc(a, s) 132 #define free(a) kern_os_free(a) 133 134 #ifndef YYSTYPE 135 #define YYSTYPE int 136 #endif 137 #include <stddef.h> 138 139 #ifndef __cplusplus 140 #ifndef __STDC__ 141 #define const 142 #endif 143 #endif 144 145 146 147 #define YYFINAL 40 148 #define YYFLAG -32768 149 #define YYNTBASE 19 150 151 #define YYTRANSLATE(x) ((unsigned)(x) <= 266 ? yytranslate[x] : 33) 152 153 static const char yytranslate[] = { 0, 154 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 155 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 156 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 157 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 158 16, 2, 2, 2, 2, 2, 2, 2, 2, 2, 159 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 160 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 161 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 162 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 163 17, 2, 18, 2, 2, 2, 2, 2, 2, 2, 164 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 165 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 166 2, 2, 13, 2, 14, 2, 2, 2, 2, 2, 167 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 168 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 169 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 170 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 171 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 172 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 173 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 174 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 175 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 176 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 177 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 178 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 179 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, 180 7, 8, 9, 10, 11, 12 181 }; 182 183 #if YYDEBUG != 0 184 static const short yyprhs[] = { 0, 185 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 186 19, 21, 24, 28, 30, 32, 35, 38, 40, 43, 187 47, 49, 52, 56, 58, 60, 63, 65, 67, 69, 188 71 189 }; 190 191 static const short yyrhs[] = { -1, 192 20, 0, 12, 0, 21, 0, 25, 0, 26, 0, 193 32, 0, 29, 0, 31, 0, 28, 0, 30, 0, 194 13, 14, 0, 13, 22, 14, 0, 6, 0, 23, 195 0, 22, 23, 0, 24, 20, 0, 8, 0, 15, 196 16, 0, 15, 27, 16, 0, 3, 0, 17, 18, 197 0, 17, 27, 18, 0, 10, 0, 20, 0, 27, 198 20, 0, 4, 0, 5, 0, 7, 0, 9, 0, 199 11, 0 200 }; 201 202 #endif 203 204 #if YYDEBUG != 0 205 static const short yyrline[] = { 0, 206 123, 124, 129, 135, 136, 137, 138, 139, 140, 141, 207 142, 155, 158, 161, 164, 165, 170, 178, 183, 186, 208 189, 192, 195, 198, 201, 204, 211, 214, 217, 220, 209 223 210 }; 211 #endif 212 213 214 #if YYDEBUG != 0 || defined (YYERROR_VERBOSE) 215 216 static const char * const yytname[] = { "$","error","$undefined.","ARRAY", 217 "BOOLEAN","DATA","DICTIONARY","IDREF","KEY","NUMBER","SET","STRING","SYNTAX_ERROR", 218 "'{'","'}'","'('","')'","'['","']'","input","object","dict","pairs","pair","key", 219 "array","set","elements","boolean","data","idref","number","string", NULL 220 }; 221 #endif 222 223 static const short yyr1[] = { 0, 224 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 225 20, 21, 21, 21, 22, 22, 23, 24, 25, 25, 226 25, 26, 26, 26, 27, 27, 28, 29, 30, 31, 227 32 228 }; 229 230 static const short yyr2[] = { 0, 231 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 232 1, 2, 3, 1, 1, 2, 2, 1, 2, 3, 233 1, 2, 3, 1, 1, 2, 1, 1, 1, 1, 234 1 235 }; 236 237 static const short yydefact[] = { 1, 238 21, 27, 28, 14, 29, 30, 24, 31, 3, 0, 239 0, 0, 2, 4, 5, 6, 10, 8, 11, 9, 240 7, 18, 12, 0, 15, 0, 19, 25, 0, 22, 241 0, 13, 16, 17, 20, 26, 23, 0, 0, 0 242 }; 243 244 static const short yydefgoto[] = { 38, 245 28, 14, 24, 25, 26, 15, 16, 29, 17, 18, 246 19, 20, 21 247 }; 248 249 static const short yypact[] = { 45, 250 -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 4, 251 60, -2,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 252 -32768,-32768,-32768, 6,-32768, 90,-32768,-32768, 75,-32768, 253 29,-32768,-32768,-32768,-32768,-32768,-32768, 10, 17,-32768 254 }; 255 256 static const short yypgoto[] = {-32768, 257 0,-32768,-32768, -18,-32768,-32768,-32768, 7,-32768,-32768, 258 -32768,-32768,-32768 259 }; 260 261 262 #define YYLAST 107 263 264 265 static const short yytable[] = { 13, 266 1, 2, 3, 4, 5, 33, 6, 7, 8, 39, 267 10, 22, 11, 22, 12, 30, 40, 23, 31, 32, 268 0, 0, 0, 0, 0, 34, 0, 0, 36, 0, 269 36, 1, 2, 3, 4, 5, 0, 6, 7, 8, 270 0, 10, 0, 11, 0, 12, 37, 1, 2, 3, 271 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, 272 0, 12, 1, 2, 3, 4, 5, 0, 6, 7, 273 8, 0, 10, 0, 11, 27, 12, 1, 2, 3, 274 4, 5, 0, 6, 7, 8, 0, 10, 0, 11, 275 35, 12, 1, 2, 3, 4, 5, 0, 6, 7, 276 8, 0, 10, 0, 11, 0, 12 277 }; 278 279 static const short yycheck[] = { 0, 280 3, 4, 5, 6, 7, 24, 9, 10, 11, 0, 281 13, 8, 15, 8, 17, 18, 0, 14, 12, 14, 282 -1, -1, -1, -1, -1, 26, -1, -1, 29, -1, 283 31, 3, 4, 5, 6, 7, -1, 9, 10, 11, 284 -1, 13, -1, 15, -1, 17, 18, 3, 4, 5, 285 6, 7, -1, 9, 10, 11, 12, 13, -1, 15, 286 -1, 17, 3, 4, 5, 6, 7, -1, 9, 10, 287 11, -1, 13, -1, 15, 16, 17, 3, 4, 5, 288 6, 7, -1, 9, 10, 11, -1, 13, -1, 15, 289 16, 17, 3, 4, 5, 6, 7, -1, 9, 10, 290 11, -1, 13, -1, 15, -1, 17 291 }; 292 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ 293 #line 3 "/usr/share/bison.simple" 294 /* This file comes from bison-1.28. */ 295 296 /* Skeleton output parser for bison, 297 Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. 298 299 This program is free software; you can redistribute it and/or modify 300 it under the terms of the GNU General Public License as published by 301 the Free Software Foundation; either version 2, or (at your option) 302 any later version. 303 304 This program is distributed in the hope that it will be useful, 305 but WITHOUT ANY WARRANTY; without even the implied warranty of 306 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 307 GNU General Public License for more details. 308 309 You should have received a copy of the GNU General Public License 310 along with this program; if not, write to the Free Software 311 Foundation, Inc., 59 Temple Place - Suite 330, 312 Boston, MA 02111-1307, USA. */ 313 314 /* As a special exception, when this file is copied by Bison into a 315 Bison output file, you may use that output file without restriction. 316 This special exception was added by the Free Software Foundation 317 in version 1.24 of Bison. */ 318 319 /* This is the parser code that is written into each bison parser 320 when the %semantic_parser declaration is not specified in the grammar. 321 It was written by Richard Stallman by simplifying the hairy parser 322 used when %semantic_parser is specified. */ 323 324 #ifndef YYSTACK_USE_ALLOCA 325 #ifdef alloca 326 #define YYSTACK_USE_ALLOCA 327 #else /* alloca not defined */ 328 #ifdef __GNUC__ 329 #define YYSTACK_USE_ALLOCA 330 #define alloca __builtin_alloca 331 #else /* not GNU C. */ 332 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) 333 #define YYSTACK_USE_ALLOCA 334 #include <alloca.h> 335 #else /* not sparc */ 336 /* We think this test detects Watcom and Microsoft C. */ 337 /* This used to test MSDOS, but that is a bad idea 338 since that symbol is in the user namespace. */ 339 #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) 340 #if 0 /* No need for malloc.h, which pollutes the namespace; 341 instead, just don't use alloca. */ 342 #include <malloc.h> 343 #endif 344 #else /* not MSDOS, or __TURBOC__ */ 345 #if defined(_AIX) 346 /* I don't know what this was needed for, but it pollutes the namespace. 347 So I turned it off. rms, 2 May 1997. */ 348 /* #include <malloc.h> */ 349 #pragma alloca 350 #define YYSTACK_USE_ALLOCA 351 #else /* not MSDOS, or __TURBOC__, or _AIX */ 352 #if 0 353 #ifdef __hpux /* [email protected] says this works for HPUX 9.05 and up, 354 and on HPUX 10. Eventually we can turn this on. */ 355 #define YYSTACK_USE_ALLOCA 356 #define alloca __builtin_alloca 357 #endif /* __hpux */ 358 #endif 359 #endif /* not _AIX */ 360 #endif /* not MSDOS, or __TURBOC__ */ 361 #endif /* not sparc */ 362 #endif /* not GNU C */ 363 #endif /* alloca not defined */ 364 #endif /* YYSTACK_USE_ALLOCA not defined */ 365 366 #ifdef YYSTACK_USE_ALLOCA 367 #define YYSTACK_ALLOC alloca 368 #else 369 #define YYSTACK_ALLOC malloc 370 #endif 371 372 /* Note: there must be only one dollar sign in this file. 373 It is replaced by the list of actions, each action 374 as one case of the switch. */ 375 376 #define yyerrok (yyerrstatus = 0) 377 #define yyclearin (yychar = YYEMPTY) 378 #define YYEMPTY -2 379 #define YYEOF 0 380 #define YYACCEPT goto yyacceptlab 381 #define YYABORT goto yyabortlab 382 #define YYERROR goto yyerrlab1 383 /* Like YYERROR except do call yyerror. 384 This remains here temporarily to ease the 385 transition to the new meaning of YYERROR, for GCC. 386 Once GCC version 2 has supplanted version 1, this can go. */ 387 #define YYFAIL goto yyerrlab 388 #define YYRECOVERING() (!!yyerrstatus) 389 #define YYBACKUP(token, value) \ 390 do \ 391 if (yychar == YYEMPTY && yylen == 1) \ 392 { yychar = (token), yylval = (value); \ 393 yychar1 = YYTRANSLATE (yychar); \ 394 YYPOPSTACK; \ 395 goto yybackup; \ 396 } \ 397 else \ 398 { yyerror ("syntax error: cannot back up"); YYERROR; } \ 399 while (0) 400 401 #define YYTERROR 1 402 #define YYERRCODE 256 403 404 #ifndef YYPURE 405 #define YYLEX yylex() 406 #endif 407 408 #ifdef YYPURE 409 #ifdef YYLSP_NEEDED 410 #ifdef YYLEX_PARAM 411 #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) 412 #else 413 #define YYLEX yylex(&yylval, &yylloc) 414 #endif 415 #else /* not YYLSP_NEEDED */ 416 #ifdef YYLEX_PARAM 417 #define YYLEX yylex(&yylval, YYLEX_PARAM) 418 #else 419 #define YYLEX yylex(&yylval) 420 #endif 421 #endif /* not YYLSP_NEEDED */ 422 #endif 423 424 /* If nonreentrant, generate the variables here */ 425 426 #ifndef YYPURE 427 428 int yychar; /* the lookahead symbol */ 429 YYSTYPE yylval; /* the semantic value of the */ 430 /* lookahead symbol */ 431 432 #ifdef YYLSP_NEEDED 433 YYLTYPE yylloc; /* location data for the lookahead */ 434 /* symbol */ 435 #endif 436 437 int yynerrs; /* number of parse errors so far */ 438 #endif /* not YYPURE */ 439 440 #if YYDEBUG != 0 441 int yydebug; /* nonzero means print parse trace */ 442 /* Since this is uninitialized, it does not stop multiple parsers 443 from coexisting. */ 444 #endif 445 446 /* YYINITDEPTH indicates the initial size of the parser's stacks */ 447 448 #ifndef YYINITDEPTH 449 #define YYINITDEPTH 200 450 #endif 451 452 /* YYMAXDEPTH is the maximum size the stacks can grow to 453 (effective only if the built-in stack extension method is used). */ 454 455 #if YYMAXDEPTH == 0 456 #undef YYMAXDEPTH 457 #endif 458 459 #ifndef YYMAXDEPTH 460 #define YYMAXDEPTH 10000 461 #endif 462 463 /* Define __yy_memcpy. Note that the size argument 464 should be passed with type unsigned int, because that is what the non-GCC 465 definitions require. With GCC, __builtin_memcpy takes an arg 466 of type size_t, but it can handle unsigned int. */ 467 468 #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ 469 #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) 470 #else /* not GNU C or C++ */ 471 #ifndef __cplusplus 472 473 /* This is the most reliable way to avoid incompatibilities 474 in available built-in functions on various systems. */ 475 static void 476 __yy_memcpy (to, from, count) 477 char *to; 478 char *from; 479 unsigned int count; 480 { 481 register char *f = from; 482 register char *t = to; 483 register int i = count; 484 485 while (i-- > 0) 486 *t++ = *f++; 487 } 488 489 #else /* __cplusplus */ 490 491 /* This is the most reliable way to avoid incompatibilities 492 in available built-in functions on various systems. */ 493 static void 494 __yy_memcpy (char *to, char *from, unsigned int count) 495 { 496 register char *t = to; 497 register char *f = from; 498 register int i = count; 499 500 while (i-- > 0) 501 *t++ = *f++; 502 } 503 504 #endif 505 #endif 506 507 #line 217 "/usr/share/bison.simple" 508 509 /* The user can define YYPARSE_PARAM as the name of an argument to be passed 510 into yyparse. The argument should have type void *. 511 It should actually point to an object. 512 Grammar actions can access the variable by casting it 513 to the proper pointer type. */ 514 515 #ifdef YYPARSE_PARAM 516 #ifdef __cplusplus 517 #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM 518 #define YYPARSE_PARAM_DECL 519 #else /* not __cplusplus */ 520 #define YYPARSE_PARAM_ARG YYPARSE_PARAM 521 #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; 522 #endif /* not __cplusplus */ 523 #else /* not YYPARSE_PARAM */ 524 #define YYPARSE_PARAM_ARG 525 #define YYPARSE_PARAM_DECL 526 #endif /* not YYPARSE_PARAM */ 527 528 /* Prevent warning if -Wstrict-prototypes. */ 529 #ifdef __GNUC__ 530 #ifdef YYPARSE_PARAM 531 int yyparse (void *); 532 #else 533 int yyparse (void); 534 #endif 535 #endif 536 537 int 538 yyparse(YYPARSE_PARAM_ARG) 539 YYPARSE_PARAM_DECL 540 { 541 register int yystate; 542 register int yyn; 543 register short *yyssp; 544 register YYSTYPE *yyvsp; 545 int yyerrstatus; /* number of tokens to shift before error messages enabled */ 546 int yychar1 = 0; /* lookahead token as an internal (translated) token number */ 547 548 short yyssa[YYINITDEPTH]; /* the state stack */ 549 YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ 550 551 short *yyss = yyssa; /* refer to the stacks thru separate pointers */ 552 YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ 553 554 #ifdef YYLSP_NEEDED 555 YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ 556 YYLTYPE *yyls = yylsa; 557 YYLTYPE *yylsp; 558 559 #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) 560 #else 561 #define YYPOPSTACK (yyvsp--, yyssp--) 562 #endif 563 564 int yystacksize = YYINITDEPTH; 565 int yyfree_stacks = 0; 566 567 #ifdef YYPURE 568 int yychar; 569 YYSTYPE yylval; 570 int yynerrs; 571 #ifdef YYLSP_NEEDED 572 YYLTYPE yylloc; 573 #endif 574 #endif 575 576 YYSTYPE yyval; /* the variable used to return */ 577 /* semantic values from the action */ 578 /* routines */ 579 580 int yylen; 581 582 #if YYDEBUG != 0 583 if (yydebug) 584 fprintf(stderr, "Starting parse\n"); 585 #endif 586 587 yystate = 0; 588 yyerrstatus = 0; 589 yynerrs = 0; 590 yychar = YYEMPTY; /* Cause a token to be read. */ 591 592 /* Initialize stack pointers. 593 Waste one element of value and location stack 594 so that they stay on the same level as the state stack. 595 The wasted elements are never initialized. */ 596 597 yyssp = yyss - 1; 598 yyvsp = yyvs; 599 #ifdef YYLSP_NEEDED 600 yylsp = yyls; 601 #endif 602 603 /* Push a new state, which is found in yystate . */ 604 /* In all cases, when you get here, the value and location stacks 605 have just been pushed. so pushing a state here evens the stacks. */ 606 yynewstate: 607 608 *++yyssp = yystate; 609 610 if (yyssp >= yyss + yystacksize - 1) 611 { 612 /* Give user a chance to reallocate the stack */ 613 /* Use copies of these so that the &'s don't force the real ones into memory. */ 614 YYSTYPE *yyvs1 = yyvs; 615 short *yyss1 = yyss; 616 #ifdef YYLSP_NEEDED 617 YYLTYPE *yyls1 = yyls; 618 #endif 619 620 /* Get the current used size of the three stacks, in elements. */ 621 int size = yyssp - yyss + 1; 622 623 #ifdef yyoverflow 624 /* Each stack pointer address is followed by the size of 625 the data in use in that stack, in bytes. */ 626 #ifdef YYLSP_NEEDED 627 /* This used to be a conditional around just the two extra args, 628 but that might be undefined if yyoverflow is a macro. */ 629 yyoverflow("parser stack overflow", 630 &yyss1, size * sizeof (*yyssp), 631 &yyvs1, size * sizeof (*yyvsp), 632 &yyls1, size * sizeof (*yylsp), 633 &yystacksize); 634 #else 635 yyoverflow("parser stack overflow", 636 &yyss1, size * sizeof (*yyssp), 637 &yyvs1, size * sizeof (*yyvsp), 638 &yystacksize); 639 #endif 640 641 yyss = yyss1; yyvs = yyvs1; 642 #ifdef YYLSP_NEEDED 643 yyls = yyls1; 644 #endif 645 #else /* no yyoverflow */ 646 /* Extend the stack our own way. */ 647 if (yystacksize >= YYMAXDEPTH) 648 { 649 yyerror("parser stack overflow"); 650 if (yyfree_stacks) 651 { 652 free (yyss); 653 free (yyvs); 654 #ifdef YYLSP_NEEDED 655 free (yyls); 656 #endif 657 } 658 return 2; 659 } 660 yystacksize *= 2; 661 if (yystacksize > YYMAXDEPTH) 662 yystacksize = YYMAXDEPTH; 663 #ifndef YYSTACK_USE_ALLOCA 664 yyfree_stacks = 1; 665 #endif 666 yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); 667 __yy_memcpy ((char *)yyss, (char *)yyss1, 668 size * (unsigned int) sizeof (*yyssp)); 669 yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); 670 __yy_memcpy ((char *)yyvs, (char *)yyvs1, 671 size * (unsigned int) sizeof (*yyvsp)); 672 #ifdef YYLSP_NEEDED 673 yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); 674 __yy_memcpy ((char *)yyls, (char *)yyls1, 675 size * (unsigned int) sizeof (*yylsp)); 676 #endif 677 #endif /* no yyoverflow */ 678 679 yyssp = yyss + size - 1; 680 yyvsp = yyvs + size - 1; 681 #ifdef YYLSP_NEEDED 682 yylsp = yyls + size - 1; 683 #endif 684 685 #if YYDEBUG != 0 686 if (yydebug) 687 fprintf(stderr, "Stack size increased to %d\n", yystacksize); 688 #endif 689 690 if (yyssp >= yyss + yystacksize - 1) 691 YYABORT; 692 } 693 694 #if YYDEBUG != 0 695 if (yydebug) 696 fprintf(stderr, "Entering state %d\n", yystate); 697 #endif 698 699 goto yybackup; 700 yybackup: 701 702 /* Do appropriate processing given the current state. */ 703 /* Read a lookahead token if we need one and don't already have one. */ 704 /* yyresume: */ 705 706 /* First try to decide what to do without reference to lookahead token. */ 707 708 yyn = yypact[yystate]; 709 if (yyn == YYFLAG) 710 goto yydefault; 711 712 /* Not known => get a lookahead token if don't already have one. */ 713 714 /* yychar is either YYEMPTY or YYEOF 715 or a valid token in external form. */ 716 717 if (yychar == YYEMPTY) 718 { 719 #if YYDEBUG != 0 720 if (yydebug) 721 fprintf(stderr, "Reading a token: "); 722 #endif 723 yychar = YYLEX; 724 } 725 726 /* Convert token to internal form (in yychar1) for indexing tables with */ 727 728 if (yychar <= 0) /* This means end of input. */ 729 { 730 yychar1 = 0; 731 yychar = YYEOF; /* Don't call YYLEX any more */ 732 733 #if YYDEBUG != 0 734 if (yydebug) 735 fprintf(stderr, "Now at end of input.\n"); 736 #endif 737 } 738 else 739 { 740 yychar1 = YYTRANSLATE(yychar); 741 742 #if YYDEBUG != 0 743 if (yydebug) 744 { 745 fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); 746 /* Give the individual parser a way to print the precise meaning 747 of a token, for further debugging info. */ 748 #ifdef YYPRINT 749 YYPRINT (stderr, yychar, yylval); 750 #endif 751 fprintf (stderr, ")\n"); 752 } 753 #endif 754 } 755 756 yyn += yychar1; 757 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) 758 goto yydefault; 759 760 yyn = yytable[yyn]; 761 762 /* yyn is what to do for this token type in this state. 763 Negative => reduce, -yyn is rule number. 764 Positive => shift, yyn is new state. 765 New state is final state => don't bother to shift, 766 just return success. 767 0, or most negative number => error. */ 768 769 if (yyn < 0) 770 { 771 if (yyn == YYFLAG) 772 goto yyerrlab; 773 yyn = -yyn; 774 goto yyreduce; 775 } 776 else if (yyn == 0) 777 goto yyerrlab; 778 779 if (yyn == YYFINAL) 780 YYACCEPT; 781 782 /* Shift the lookahead token. */ 783 784 #if YYDEBUG != 0 785 if (yydebug) 786 fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); 787 #endif 788 789 /* Discard the token being shifted unless it is eof. */ 790 if (yychar != YYEOF) 791 yychar = YYEMPTY; 792 793 *++yyvsp = yylval; 794 #ifdef YYLSP_NEEDED 795 *++yylsp = yylloc; 796 #endif 797 798 /* count tokens shifted since error; after three, turn off error status. */ 799 if (yyerrstatus) yyerrstatus--; 800 801 yystate = yyn; 802 goto yynewstate; 803 804 /* Do the default action for the current state. */ 805 yydefault: 806 807 yyn = yydefact[yystate]; 808 if (yyn == 0) 809 goto yyerrlab; 810 811 /* Do a reduction. yyn is the number of a rule to reduce with. */ 812 yyreduce: 813 yylen = yyr2[yyn]; 814 if (yylen > 0) 815 yyval = yyvsp[1-yylen]; /* implement default value of the action */ 816 817 #if YYDEBUG != 0 818 if (yydebug) 819 { 820 int i; 821 822 fprintf (stderr, "Reducing via rule %d (line %d), ", 823 yyn, yyrline[yyn]); 824 825 /* Print the symbols being reduced, and their result. */ 826 for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) 827 fprintf (stderr, "%s ", yytname[yyrhs[i]]); 828 fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); 829 } 830 #endif 831 832 833 switch (yyn) { 834 835 case 1: 836 #line 123 "OSUnserializeXML.y" 837 { parsedObject = (OSObject *)NULL; YYACCEPT; ; 838 break;} 839 case 2: 840 #line 124 "OSUnserializeXML.y" 841 { parsedObject = yyvsp[0]->object; 842 yyvsp[0]->object = 0; 843 freeObject(yyvsp[0]); 844 YYACCEPT; 845 ; 846 break;} 847 case 3: 848 #line 129 "OSUnserializeXML.y" 849 { 850 yyerror("syntax error"); 851 YYERROR; 852 ; 853 break;} 854 case 4: 855 #line 135 "OSUnserializeXML.y" 856 { yyval = buildOSDictionary(yyvsp[0]); ; 857 break;} 858 case 5: 859 #line 136 "OSUnserializeXML.y" 860 { yyval = buildOSArray(yyvsp[0]); ; 861 break;} 862 case 6: 863 #line 137 "OSUnserializeXML.y" 864 { yyval = buildOSSet(yyvsp[0]); ; 865 break;} 866 case 7: 867 #line 138 "OSUnserializeXML.y" 868 { yyval = buildOSString(yyvsp[0]); ; 869 break;} 870 case 8: 871 #line 139 "OSUnserializeXML.y" 872 { yyval = buildOSData(yyvsp[0]); ; 873 break;} 874 case 9: 875 #line 140 "OSUnserializeXML.y" 876 { yyval = buildOSNumber(yyvsp[0]); ; 877 break;} 878 case 10: 879 #line 141 "OSUnserializeXML.y" 880 { yyval = buildOSBoolean(yyvsp[0]); ; 881 break;} 882 case 11: 883 #line 142 "OSUnserializeXML.y" 884 { yyval = retrieveObject(yyvsp[0]->idref); 885 if (yyval) { 886 yyval->object->retain(); 887 } else { 888 yyerror("forward reference detected"); 889 YYERROR; 890 } 891 freeObject(yyvsp[0]); 892 ; 893 break;} 894 case 12: 895 #line 155 "OSUnserializeXML.y" 896 { yyval = yyvsp[-1]; 897 yyval->elements = NULL; 898 ; 899 break;} 900 case 13: 901 #line 158 "OSUnserializeXML.y" 902 { yyval = yyvsp[-2]; 903 yyval->elements = yyvsp[-1]; 904 ; 905 break;} 906 case 16: 907 #line 165 "OSUnserializeXML.y" 908 { yyval = yyvsp[0]; 909 yyval->next = yyvsp[-1]; 910 ; 911 break;} 912 case 17: 913 #line 170 "OSUnserializeXML.y" 914 { yyval = yyvsp[-1]; 915 yyval->next = NULL; 916 yyval->object = yyvsp[0]->object; 917 yyvsp[0]->object = 0; 918 freeObject(yyvsp[0]); 919 ; 920 break;} 921 case 18: 922 #line 178 "OSUnserializeXML.y" 923 { yyval = buildKey(yyvsp[0]); ; 924 break;} 925 case 19: 926 #line 183 "OSUnserializeXML.y" 927 { yyval = yyvsp[-1]; 928 yyval->elements = NULL; 929 ; 930 break;} 931 case 20: 932 #line 186 "OSUnserializeXML.y" 933 { yyval = yyvsp[-2]; 934 yyval->elements = yyvsp[-1]; 935 ; 936 break;} 937 case 22: 938 #line 192 "OSUnserializeXML.y" 939 { yyval = yyvsp[-1]; 940 yyval->elements = NULL; 941 ; 942 break;} 943 case 23: 944 #line 195 "OSUnserializeXML.y" 945 { yyval = yyvsp[-2]; 946 yyval->elements = yyvsp[-1]; 947 ; 948 break;} 949 case 25: 950 #line 201 "OSUnserializeXML.y" 951 { yyval = yyvsp[0]; 952 yyval->next = NULL; 953 ; 954 break;} 955 case 26: 956 #line 204 "OSUnserializeXML.y" 957 { yyval = yyvsp[0]; 958 yyval->next = yyvsp[-1]; 959 ; 960 break;} 961 } 962 /* the action file gets copied in in place of this dollarsign */ 963 #line 543 "/usr/share/bison.simple" 964 965 yyvsp -= yylen; 966 yyssp -= yylen; 967 #ifdef YYLSP_NEEDED 968 yylsp -= yylen; 969 #endif 970 971 #if YYDEBUG != 0 972 if (yydebug) 973 { 974 short *ssp1 = yyss - 1; 975 fprintf (stderr, "state stack now"); 976 while (ssp1 != yyssp) 977 fprintf (stderr, " %d", *++ssp1); 978 fprintf (stderr, "\n"); 979 } 980 #endif 981 982 *++yyvsp = yyval; 983 984 #ifdef YYLSP_NEEDED 985 yylsp++; 986 if (yylen == 0) 987 { 988 yylsp->first_line = yylloc.first_line; 989 yylsp->first_column = yylloc.first_column; 990 yylsp->last_line = (yylsp-1)->last_line; 991 yylsp->last_column = (yylsp-1)->last_column; 992 yylsp->text = 0; 993 } 994 else 995 { 996 yylsp->last_line = (yylsp+yylen-1)->last_line; 997 yylsp->last_column = (yylsp+yylen-1)->last_column; 998 } 999 #endif 1000 1001 /* Now "shift" the result of the reduction. 1002 Determine what state that goes to, 1003 based on the state we popped back to 1004 and the rule number reduced by. */ 1005 1006 yyn = yyr1[yyn]; 1007 1008 yystate = yypgoto[yyn - YYNTBASE] + *yyssp; 1009 if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) 1010 yystate = yytable[yystate]; 1011 else 1012 yystate = yydefgoto[yyn - YYNTBASE]; 1013 1014 goto yynewstate; 1015 1016 yyerrlab: /* here on detecting error */ 1017 1018 if (! yyerrstatus) 1019 /* If not already recovering from an error, report this error. */ 1020 { 1021 ++yynerrs; 1022 1023 #ifdef YYERROR_VERBOSE 1024 yyn = yypact[yystate]; 1025 1026 if (yyn > YYFLAG && yyn < YYLAST) 1027 { 1028 int size = 0; 1029 char *msg; 1030 int x, count; 1031 1032 count = 0; 1033 /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ 1034 for (x = (yyn < 0 ? -yyn : 0); 1035 x < (sizeof(yytname) / sizeof(char *)); x++) 1036 if (yycheck[x + yyn] == x) 1037 size += strlen(yytname[x]) + 15, count++; 1038 msg = (char *) malloc(size + 15); 1039 if (msg != 0) 1040 { 1041 strcpy(msg, "parse error"); 1042 1043 if (count < 5) 1044 { 1045 count = 0; 1046 for (x = (yyn < 0 ? -yyn : 0); 1047 x < (sizeof(yytname) / sizeof(char *)); x++) 1048 if (yycheck[x + yyn] == x) 1049 { 1050 strcat(msg, count == 0 ? ", expecting `" : " or `"); 1051 strcat(msg, yytname[x]); 1052 strcat(msg, "'"); 1053 count++; 1054 } 1055 } 1056 yyerror(msg); 1057 free(msg); 1058 } 1059 else 1060 yyerror ("parse error; also virtual memory exceeded"); 1061 } 1062 else 1063 #endif /* YYERROR_VERBOSE */ 1064 yyerror("parse error"); 1065 } 1066 1067 goto yyerrlab1; 1068 yyerrlab1: /* here on error raised explicitly by an action */ 1069 1070 if (yyerrstatus == 3) 1071 { 1072 /* if just tried and failed to reuse lookahead token after an error, discard it. */ 1073 1074 /* return failure if at end of input */ 1075 if (yychar == YYEOF) 1076 YYABORT; 1077 1078 #if YYDEBUG != 0 1079 if (yydebug) 1080 fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); 1081 #endif 1082 1083 yychar = YYEMPTY; 1084 } 1085 1086 /* Else will try to reuse lookahead token 1087 after shifting the error token. */ 1088 1089 yyerrstatus = 3; /* Each real token shifted decrements this */ 1090 1091 goto yyerrhandle; 1092 1093 yyerrdefault: /* current state does not do anything special for the error token. */ 1094 1095 #if 0 1096 /* This is wrong; only states that explicitly want error tokens 1097 should shift them. */ 1098 yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ 1099 if (yyn) goto yydefault; 1100 #endif 1101 1102 yyerrpop: /* pop the current state because it cannot handle the error token */ 1103 1104 if (yyssp == yyss) YYABORT; 1105 yyvsp--; 1106 yystate = *--yyssp; 1107 #ifdef YYLSP_NEEDED 1108 yylsp--; 1109 #endif 1110 1111 #if YYDEBUG != 0 1112 if (yydebug) 1113 { 1114 short *ssp1 = yyss - 1; 1115 fprintf (stderr, "Error: state stack now"); 1116 while (ssp1 != yyssp) 1117 fprintf (stderr, " %d", *++ssp1); 1118 fprintf (stderr, "\n"); 1119 } 1120 #endif 1121 1122 yyerrhandle: 1123 1124 yyn = yypact[yystate]; 1125 if (yyn == YYFLAG) 1126 goto yyerrdefault; 1127 1128 yyn += YYTERROR; 1129 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) 1130 goto yyerrdefault; 1131 1132 yyn = yytable[yyn]; 1133 if (yyn < 0) 1134 { 1135 if (yyn == YYFLAG) 1136 goto yyerrpop; 1137 yyn = -yyn; 1138 goto yyreduce; 1139 } 1140 else if (yyn == 0) 1141 goto yyerrpop; 1142 1143 if (yyn == YYFINAL) 1144 YYACCEPT; 1145 1146 #if YYDEBUG != 0 1147 if (yydebug) 1148 fprintf(stderr, "Shifting error token, "); 1149 #endif 1150 1151 *++yyvsp = yylval; 1152 #ifdef YYLSP_NEEDED 1153 *++yylsp = yylloc; 1154 #endif 1155 1156 yystate = yyn; 1157 goto yynewstate; 1158 1159 yyacceptlab: 1160 /* YYACCEPT comes here. */ 1161 if (yyfree_stacks) 1162 { 1163 free (yyss); 1164 free (yyvs); 1165 #ifdef YYLSP_NEEDED 1166 free (yyls); 1167 #endif 1168 } 1169 return 0; 1170 1171 yyabortlab: 1172 /* YYABORT comes here. */ 1173 if (yyfree_stacks) 1174 { 1175 free (yyss); 1176 free (yyvs); 1177 #ifdef YYLSP_NEEDED 1178 free (yyls); 1179 #endif 1180 } 1181 return 1; 1182 } 1183 #line 226 "OSUnserializeXML.y" 1184 1185 1186 static int lineNumber = 0; 1187 static const char *parseBuffer; 1188 static int parseBufferIndex; 1189 1190 #define currentChar() (parseBuffer[parseBufferIndex]) 1191 #define nextChar() (parseBuffer[++parseBufferIndex]) 1192 #define prevChar() (parseBuffer[parseBufferIndex - 1]) 1193 1194 #define isSpace(c) ((c) == ' ' || (c) == '\t') 1195 #define isAlpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) 1196 #define isDigit(c) ((c) >= '0' && (c) <= '9') 1197 #define isAlphaDigit(c) ((c) >= 'a' && (c) <= 'f') 1198 #define isHexDigit(c) (isDigit(c) || isAlphaDigit(c)) 1199 #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-')) 1200 1201 static char yyerror_message[128]; 1202 1203 int 1204 yyerror(char *s) /* Called by yyparse on error */ 1205 { 1206 sprintf(yyerror_message, "OSUnserializeXML: %s near line %d\n", s, lineNumber); 1207 return 0; 1208 } 1209 1210 #define TAG_MAX_LENGTH 32 1211 #define TAG_MAX_ATTRIBUTES 32 1212 #define TAG_BAD 0 1213 #define TAG_START 1 1214 #define TAG_END 2 1215 #define TAG_EMPTY 3 1216 #define TAG_COMMENT 4 1217 1218 static int 1219 getTag(char tag[TAG_MAX_LENGTH], 1220 int *attributeCount, 1221 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH], 1222 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] ) 1223 { 1224 int length = 0;; 1225 int c = currentChar(); 1226 int tagType = TAG_START; 1227 1228 *attributeCount = 0; 1229 1230 if (c != '<') return TAG_BAD; 1231 c = nextChar(); // skip '<' 1232 1233 if (c == '?' || c == '!') { 1234 while ((c = nextChar()) != 0) { 1235 if (c == '\n') lineNumber++; 1236 if (c == '>') { 1237 (void)nextChar(); 1238 return TAG_COMMENT; 1239 } 1240 } 1241 } 1242 1243 if (c == '/') { 1244 c = nextChar(); // skip '/' 1245 tagType = TAG_END; 1246 } 1247 if (!isAlpha(c)) return TAG_BAD; 1248 1249 /* find end of tag while copying it */ 1250 while (isAlphaNumeric(c)) { 1251 tag[length++] = c; 1252 c = nextChar(); 1253 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; 1254 } 1255 1256 tag[length] = 0; 1257 1258 //printf("tag %s, type %d\n", tag, tagType); 1259 1260 // look for attributes of the form attribute = "value" ... 1261 while ((c != '>') && (c != '/')) { 1262 while (isSpace(c)) c = nextChar(); 1263 1264 length = 0; 1265 while (isAlphaNumeric(c)) { 1266 attributes[*attributeCount][length++] = c; 1267 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; 1268 c = nextChar(); 1269 } 1270 attributes[*attributeCount][length] = 0; 1271 1272 while (isSpace(c)) c = nextChar(); 1273 1274 if (c != '=') return TAG_BAD; 1275 c = nextChar(); 1276 1277 while (isSpace(c)) c = nextChar(); 1278 1279 if (c != '"') return TAG_BAD; 1280 c = nextChar(); 1281 length = 0; 1282 while (c != '"') { 1283 values[*attributeCount][length++] = c; 1284 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; 1285 c = nextChar(); 1286 } 1287 values[*attributeCount][length] = 0; 1288 1289 c = nextChar(); // skip closing quote 1290 1291 //printf(" attribute '%s' = '%s', nextchar = '%c'\n", attributes[*attributeCount], values[*attributeCount], c); 1292 1293 (*attributeCount)++; 1294 if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD; 1295 } 1296 1297 if (c == '/') { 1298 c = nextChar(); // skip '/' 1299 tagType = TAG_EMPTY; 1300 } 1301 if (c != '>') return TAG_BAD; 1302 c = nextChar(); // skip '>' 1303 1304 return tagType; 1305 } 1306 1307 static char * 1308 getString() 1309 { 1310 int c = currentChar(); 1311 1312 int start, length, i, j;; 1313 char * tempString; 1314 1315 start = parseBufferIndex; 1316 /* find end of string */ 1317 1318 while (c != 0) { 1319 if (c == '\n') lineNumber++; 1320 if (c == '<') { 1321 break; 1322 } 1323 c = nextChar(); 1324 } 1325 1326 if (c != '<') return 0; 1327 1328 length = parseBufferIndex - start; 1329 1330 /* copy to null terminated buffer */ 1331 tempString = (char *)malloc(length + 1); 1332 if (tempString == 0) { 1333 printf("OSUnserializeXML: can't alloc temp memory\n"); 1334 return 0; 1335 } 1336 1337 // copy out string in tempString 1338 // "&" -> '&', "<" -> '<', ">" -> '>' 1339 1340 i = j = 0; 1341 while (i < length) { 1342 c = parseBuffer[start + i++]; 1343 if (c != '&') { 1344 tempString[j++] = c; 1345 } else { 1346 if ((i+3) > length) goto error; 1347 c = parseBuffer[start + i++]; 1348 if (c == 'l') { 1349 if (parseBuffer[start + i++] != 't') goto error; 1350 if (parseBuffer[start + i++] != ';') goto error; 1351 tempString[j++] = '<'; 1352 continue; 1353 } 1354 if (c == 'g') { 1355 if (parseBuffer[start + i++] != 't') goto error; 1356 if (parseBuffer[start + i++] != ';') goto error; 1357 tempString[j++] = '>'; 1358 continue; 1359 } 1360 if ((i+3) > length) goto error; 1361 if (c == 'a') { 1362 if (parseBuffer[start + i++] != 'm') goto error; 1363 if (parseBuffer[start + i++] != 'p') goto error; 1364 if (parseBuffer[start + i++] != ';') goto error; 1365 tempString[j++] = '&'; 1366 continue; 1367 } 1368 goto error; 1369 } 1370 } 1371 tempString[j] = 0; 1372 1373 //printf("string %s\n", tempString); 1374 1375 return tempString; 1376 1377 error: 1378 if (tempString) free(tempString); 1379 return 0; 1380 } 1381 1382 static long long 1383 getNumber() 1384 { 1385 unsigned long long n = 0; 1386 int base = 10; 1387 int c = currentChar(); 1388 1389 if (!isDigit (c)) return 0; 1390 1391 if (c == '0') { 1392 c = nextChar(); 1393 if (c == 'x') { 1394 base = 16; 1395 c = nextChar(); 1396 } 1397 } 1398 if (base == 10) { 1399 while(isDigit(c)) { 1400 n = (n * base + c - '0'); 1401 c = nextChar(); 1402 } 1403 } else { 1404 while(isHexDigit(c)) { 1405 if (isDigit(c)) { 1406 n = (n * base + c - '0'); 1407 } else { 1408 n = (n * base + 0xa + c - 'a'); 1409 } 1410 c = nextChar(); 1411 } 1412 } 1413 //printf("number 0x%x\n", (unsigned long)n); 1414 return n; 1415 } 1416 1417 // taken from CFXMLParsing/CFPropertyList.c 1418 1419 static const signed char __CFPLDataDecodeTable[128] = { 1420 /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1, 1421 /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1, 1422 /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1, 1423 /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1, 1424 /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1, 1425 /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63, 1426 /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59, 1427 /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1, 1428 /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6, 1429 /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14, 1430 /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22, 1431 /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1, 1432 /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32, 1433 /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40, 1434 /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48, 1435 /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1 1436 }; 1437 1438 #define OSDATA_ALLOC_SIZE 4096 1439 1440 static void * 1441 getCFEncodedData(unsigned int *size) 1442 { 1443 int numeq = 0, acc = 0, cntr = 0; 1444 int tmpbufpos = 0, tmpbuflen = 0; 1445 unsigned char *tmpbuf = (unsigned char *)malloc(OSDATA_ALLOC_SIZE); 1446 1447 int c = currentChar(); 1448 *size = 0; 1449 1450 while (c != '<') { 1451 c &= 0x7f; 1452 if (c == 0) { 1453 free(tmpbuf); 1454 return 0; 1455 } 1456 if (c == '=') numeq++; else numeq = 0; 1457 if (c == '\n') lineNumber++; 1458 if (__CFPLDataDecodeTable[c] < 0) { 1459 c = nextChar(); 1460 continue; 1461 } 1462 cntr++; 1463 acc <<= 6; 1464 acc += __CFPLDataDecodeTable[c]; 1465 if (0 == (cntr & 0x3)) { 1466 if (tmpbuflen <= tmpbufpos + 2) { 1467 tmpbuflen += OSDATA_ALLOC_SIZE; 1468 tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen); 1469 } 1470 tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff; 1471 if (numeq < 2) 1472 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff; 1473 if (numeq < 1) 1474 tmpbuf[tmpbufpos++] = acc & 0xff; 1475 } 1476 c = nextChar(); 1477 } 1478 *size = tmpbufpos; 1479 return tmpbuf; 1480 } 1481 1482 static void * 1483 getHexData(unsigned int *size) 1484 { 1485 int c; 1486 unsigned char *d, *start, *lastStart; 1487 1488 start = lastStart = d = (unsigned char *)malloc(OSDATA_ALLOC_SIZE); 1489 c = currentChar(); 1490 1491 while (c != '<') { 1492 1493 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {}; 1494 if (c == '\n') { 1495 lineNumber++; 1496 c = nextChar(); 1497 continue; 1498 } 1499 1500 // get high nibble 1501 if (isDigit(c)) { 1502 *d = (c - '0') << 4; 1503 } else if (isAlphaDigit(c)) { 1504 *d = (0xa + (c - 'a')) << 4; 1505 } else { 1506 goto error; 1507 } 1508 1509 // get low nibble 1510 c = nextChar(); 1511 if (isDigit(c)) { 1512 *d |= c - '0'; 1513 } else if (isAlphaDigit(c)) { 1514 *d |= 0xa + (c - 'a'); 1515 } else { 1516 goto error; 1517 } 1518 1519 d++; 1520 if ((d - lastStart) >= OSDATA_ALLOC_SIZE) { 1521 int oldsize = d - start; 1522 start = (unsigned char *)realloc(start, oldsize + OSDATA_ALLOC_SIZE); 1523 d = lastStart = start + oldsize; 1524 } 1525 c = nextChar(); 1526 } 1527 1528 *size = d - start; 1529 return start; 1530 1531 error: 1532 1533 *size = 0; 1534 free(start); 1535 return 0; 1536 } 1537 1538 static int 1539 yylex() 1540 { 1541 int c; 1542 int tagType; 1543 char tag[TAG_MAX_LENGTH]; 1544 int attributeCount; 1545 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH]; 1546 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH]; 1547 1548 if (parseBufferIndex == 0) lineNumber = 1; 1549 1550 top: 1551 c = currentChar(); 1552 1553 /* skip white space */ 1554 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {}; 1555 1556 /* keep track of line number, don't return \n's */ 1557 if (c == '\n') { 1558 lineNumber++; 1559 (void)nextChar(); 1560 goto top; 1561 } 1562 1563 if (!c) return c; 1564 1565 tagType = getTag(tag, &attributeCount, attributes, values); 1566 if (tagType == TAG_BAD) return SYNTAX_ERROR; 1567 if (tagType == TAG_COMMENT) goto top; 1568 1569 // handle allocation and check for "ID" and "IDREF" tags up front 1570 yylval = newObject(); 1571 yylval->idref = -1; 1572 for (int i=0; i < attributeCount; i++) { 1573 if (attributes[i][0] == 'I' && attributes[i][1] == 'D') { 1574 // check for idref's, note: we ignore the tag, for 1575 // this to work correctly, all idrefs must be unique 1576 // across the whole serialization 1577 if (attributes[i][2] == 'R' && attributes[i][3] == 'E' && 1578 attributes[i][4] == 'F' && !attributes[i][5]) { 1579 if (tagType != TAG_EMPTY) return SYNTAX_ERROR; 1580 yylval->idref = strtol(values[i], NULL, 0); 1581 return IDREF; 1582 } 1583 // check for id's 1584 if (!attributes[i][2]) { 1585 yylval->idref = strtol(values[i], NULL, 0); 1586 } else { 1587 return SYNTAX_ERROR; 1588 } 1589 } 1590 } 1591 1592 switch (*tag) { 1593 case 'a': 1594 if (!strcmp(tag, "array")) { 1595 if (tagType == TAG_EMPTY) { 1596 yylval->elements = NULL; 1597 return ARRAY; 1598 } 1599 return (tagType == TAG_START) ? '(' : ')'; 1600 } 1601 break; 1602 case 'd': 1603 if (!strcmp(tag, "dict")) { 1604 if (tagType == TAG_EMPTY) { 1605 yylval->elements = NULL; 1606 return DICTIONARY; 1607 } 1608 return (tagType == TAG_START) ? '{' : '}'; 1609 } 1610 if (!strcmp(tag, "data")) { 1611 unsigned int size; 1612 int readable = 0; 1613 if (tagType == TAG_EMPTY) { 1614 yylval->data = NULL; 1615 yylval->size = 0; 1616 return DATA; 1617 } 1618 for (int i=0; i < attributeCount; i++) { 1619 if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) { 1620 readable++; 1621 break; 1622 } 1623 } 1624 // CF encoded is the default form 1625 if (readable) { 1626 yylval->data = getHexData(&size); 1627 } else { 1628 yylval->data = getCFEncodedData(&size); 1629 } 1630 yylval->size = size; 1631 if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) { 1632 return SYNTAX_ERROR; 1633 } 1634 return DATA; 1635 } 1636 break; 1637 case 'f': 1638 if (!strcmp(tag, "false")) { 1639 if (tagType == TAG_EMPTY) { 1640 yylval->number = 0; 1641 return BOOLEAN; 1642 } 1643 } 1644 break; 1645 case 'i': 1646 if (!strcmp(tag, "integer")) { 1647 yylval->size = 64; // default 1648 for (int i=0; i < attributeCount; i++) { 1649 if (!strcmp(attributes[i], "size")) { 1650 yylval->size = strtoul(values[i], NULL, 0); 1651 } 1652 } 1653 if (tagType == TAG_EMPTY) { 1654 yylval->number = 0; 1655 return NUMBER; 1656 } 1657 yylval->number = getNumber(); 1658 if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) { 1659 return SYNTAX_ERROR; 1660 } 1661 return NUMBER; 1662 } 1663 break; 1664 case 'k': 1665 if (!strcmp(tag, "key")) { 1666 if (tagType == TAG_EMPTY) return SYNTAX_ERROR; 1667 yylval->string = getString(); 1668 if (!yylval->string) { 1669 return SYNTAX_ERROR; 1670 } 1671 if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) 1672 || strcmp(tag, "key")) { 1673 return SYNTAX_ERROR; 1674 } 1675 return KEY; 1676 } 1677 break; 1678 case 'p': 1679 if (!strcmp(tag, "plist")) { 1680 freeObject(yylval); 1681 goto top; 1682 } 1683 break; 1684 case 's': 1685 if (!strcmp(tag, "string")) { 1686 if (tagType == TAG_EMPTY) { 1687 yylval->string = (char *)malloc(1); 1688 *yylval->string = 0; 1689 return STRING; 1690 } 1691 yylval->string = getString(); 1692 if (!yylval->string) { 1693 return SYNTAX_ERROR; 1694 } 1695 if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) 1696 || strcmp(tag, "string")) { 1697 return SYNTAX_ERROR; 1698 } 1699 return STRING; 1700 } 1701 if (!strcmp(tag, "set")) { 1702 if (tagType == TAG_EMPTY) { 1703 yylval->elements = NULL; 1704 return SET;; 1705 } 1706 if (tagType == TAG_START) { 1707 return '['; 1708 } else { 1709 return ']'; 1710 } 1711 } 1712 break; 1713 case 't': 1714 if (!strcmp(tag, "true")) { 1715 if (tagType == TAG_EMPTY) { 1716 yylval->number = 1; 1717 return BOOLEAN; 1718 } 1719 } 1720 break; 1721 1722 default: 1723 // XXX should we ignore invalid tags? 1724 return SYNTAX_ERROR; 1725 break; 1726 } 1727 1728 return 0; 1729 } 1730 1731 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1732 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1733 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1734 1735 // "java" like allocation, if this code hits a syntax error in the 1736 // the middle of the parsed string we just bail with pointers hanging 1737 // all over place, so this code helps keeps all together 1738 1739 static object_t *objects = 0; 1740 static object_t *freeObjects = 0; 1741 1742 object_t * 1743 newObject() 1744 { 1745 object_t *o; 1746 1747 if (freeObjects) { 1748 o = freeObjects; 1749 freeObjects = freeObjects->next; 1750 } else { 1751 o = (object_t *)malloc(sizeof(object_t)); 1752 bzero(o, sizeof(object_t)); 1753 o->free = objects; 1754 objects = o; 1755 } 1756 1757 return o; 1758 } 1759 1760 void 1761 freeObject(object_t *o) 1762 { 1763 o->next = freeObjects; 1764 freeObjects = o; 1765 } 1766 1767 void 1768 cleanupObjects() 1769 { 1770 object_t *t, *o = objects; 1771 1772 while (o) { 1773 if (o->object) { 1774 printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object); 1775 o->object->release(); 1776 } 1777 if (o->data) { 1778 printf("OSUnserializeXML: freeing object o=%x data=%x\n", (int)o, (int)o->data); 1779 free(o->data); 1780 } 1781 if (o->key) { 1782 printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key); 1783 o->key->release(); 1784 } 1785 if (o->string) { 1786 printf("OSUnserializeXML: freeing object o=%x string=%x\n", (int)o, (int)o->string); 1787 free(o->string); 1788 } 1789 1790 t = o; 1791 o = o->free; 1792 free(t); 1793 } 1794 } 1795 1796 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1797 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1798 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1799 1800 static OSDictionary *tags; 1801 1802 static void 1803 rememberObject(int tag, OSObject *o) 1804 { 1805 char key[16]; 1806 sprintf(key, "%u", tag); 1807 1808 //printf("remember key %s\n", key); 1809 1810 tags->setObject(key, o); 1811 } 1812 1813 static object_t * 1814 retrieveObject(int tag) 1815 { 1816 char key[16]; 1817 sprintf(key, "%u", tag); 1818 1819 //printf("retrieve key '%s'\n", key); 1820 1821 OSObject *ref = tags->getObject(key); 1822 if (!ref) return 0; 1823 1824 object_t *o = newObject(); 1825 o->object = ref; 1826 return o; 1827 } 1828 1829 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1830 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1831 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 1832 1833 object_t * 1834 buildOSDictionary(object_t * header) 1835 { 1836 object_t *o, *t; 1837 int count = 0; 1838 1839 // get count and reverse order 1840 o = header->elements; 1841 header->elements = 0; 1842 while (o) { 1843 count++; 1844 t = o; 1845 o = o->next; 1846 1847 t->next = header->elements; 1848 header->elements = t; 1849 } 1850 1851 OSDictionary *d = OSDictionary::withCapacity(count); 1852 1853 if (header->idref >= 0) rememberObject(header->idref, d); 1854 1855 o = header->elements; 1856 while (o) { 1857 d->setObject(o->key, o->object); 1858 o->object->release(); 1859 o->object = 0; 1860 o->key->release(); 1861 o->key = 0; 1862 t = o; 1863 o = o->next; 1864 freeObject(t); 1865 } 1866 o = header; 1867 o->object = d; 1868 return o; 1869 }; 1870 1871 object_t * 1872 buildOSArray(object_t * header) 1873 { 1874 object_t *o, *t; 1875 int count = 0; 1876 1877 // get count and reverse order 1878 o = header->elements; 1879 header->elements = 0; 1880 while (o) { 1881 count++; 1882 t = o; 1883 o = o->next; 1884 1885 t->next = header->elements; 1886 header->elements = t; 1887 } 1888 1889 OSArray *a = OSArray::withCapacity(count); 1890 1891 if (header->idref >= 0) rememberObject(header->idref, a); 1892 1893 o = header->elements; 1894 while (o) { 1895 a->setObject(o->object); 1896 o->object->release(); 1897 o->object = 0; 1898 t = o; 1899 o = o->next; 1900 freeObject(t); 1901 } 1902 o = header; 1903 o->object = a; 1904 return o; 1905 }; 1906 1907 object_t * 1908 buildOSSet(object_t *o) 1909 { 1910 o = buildOSArray(o); 1911 OSArray *a = (OSArray *)o->object; 1912 1913 OSSet *s = OSSet::withArray(a, a->getCapacity()); 1914 1915 //write over reference created in array 1916 if (o->idref >= 0) rememberObject(o->idref, s); 1917 1918 a->release(); 1919 o->object = s; 1920 return o; 1921 }; 1922 1923 object_t * 1924 buildOSString(object_t *o) 1925 { 1926 OSString *s = OSString::withCString(o->string); 1927 1928 if (o->idref >= 0) rememberObject(o->idref, s); 1929 1930 free(o->string); 1931 o->string = 0; 1932 o->object = s; 1933 1934 return o; 1935 }; 1936 1937 object_t * 1938 buildKey(object_t *o) 1939 { 1940 const OSSymbol *s = OSSymbol::withCString(o->string); 1941 1942 free(o->string); 1943 o->string = 0; 1944 o->key = s; 1945 1946 return o; 1947 }; 1948 1949 object_t * 1950 buildOSData(object_t *o) 1951 { 1952 OSData *d; 1953 1954 if (o->size) { 1955 d = OSData::withBytes(o->data, o->size); 1956 free(o->data); 1957 } else { 1958 d = OSData::withCapacity(0); 1959 } 1960 if (o->idref >= 0) rememberObject(o->idref, d); 1961 1962 o->data = 0; 1963 o->object = d; 1964 return o; 1965 }; 1966 1967 object_t * 1968 buildOSNumber(object_t *o) 1969 { 1970 OSNumber *n = OSNumber::withNumber(o->number, o->size); 1971 1972 if (o->idref >= 0) rememberObject(o->idref, n); 1973 1974 o->object = n; 1975 return o; 1976 }; 1977 1978 object_t * 1979 buildOSBoolean(object_t *o) 1980 { 1981 OSBoolean *b = OSBoolean::withBoolean(o->number != 0); 1982 o->object = b; 1983 return o; 1984 }; 1985 1986 __BEGIN_DECLS 1987 #include <kern/lock.h> 1988 __END_DECLS 1989 1990 static mutex_t *lock = 0; 1991 1992 OSObject* 1993 OSUnserializeXML(const char *buffer, OSString **errorString) 1994 { 1995 OSObject *object; 1996 1997 if (!lock) { 1998 lock = mutex_alloc(ETAP_IO_AHA); 1999 mutex_lock(lock); 2000 } else { 2001 mutex_lock(lock); 2002 2003 } 2004 2005 objects = 0; 2006 freeObjects = 0; 2007 yyerror_message[0] = 0; //just in case 2008 parseBuffer = buffer; 2009 parseBufferIndex = 0; 2010 tags = OSDictionary::withCapacity(128); 2011 if (yyparse() == 0) { 2012 object = parsedObject; 2013 if (errorString) *errorString = 0; 2014 } else { 2015 object = 0; 2016 if (errorString) 2017 *errorString = OSString::withCString(yyerror_message); 2018 } 2019 2020 cleanupObjects(); 2021 tags->release(); 2022 mutex_unlock(lock); 2023 2024 return object; 2025 } 2026 2027 2028 // 2029 // 2030 // 2031 // 2032 // 2033 // DO NOT EDIT OSUnserializeXML.cpp! 2034 // 2035 // this means you! 2036 // 2037 // 2038 // 2039 // 2040 // 2041