1/* 2 * Copyright (c) 1999-2002 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/* 24 * HISTORY 25 * 26 * OSUnserializeXML.y created by rsulack on Tue Oct 12 1999 27 */ 28 29// parser for unserializing OSContainer objects serialized to XML 30// 31// to build : 32// bison -p OSUnserializeXML OSUnserializeXML.y 33// head -50 OSUnserializeXML.y > OSUnserializeXML.cpp 34// sed -e "s/#include <stdio.h>//" < OSUnserializeXML.tab.c >> OSUnserializeXML.cpp 35// 36// when changing code check in both OSUnserializeXML.y and OSUnserializeXML.cpp 37// 38// 39// 40// 41// 42// DO NOT EDIT OSUnserializeXML.cpp! 43// 44// this means you! 45// 46// 47// 48// 49// 50// 51 52 53%pure_parser 54 55%{ 56#include <string.h> 57#include <libkern/c++/OSMetaClass.h> 58#include <libkern/c++/OSContainers.h> 59#include <libkern/c++/OSLib.h> 60 61#define YYSTYPE object_t * 62#define YYPARSE_PARAM state 63#define YYLEX_PARAM state 64 65// this is the internal struct used to hold objects on parser stack 66// it represents objects both before and after they have been created 67typedef struct object { 68 struct object *next; 69 struct object *free; 70 struct object *elements; 71 OSObject *object; 72 OSString *key; // for dictionary 73 int size; 74 void *data; // for data 75 char *string; // for string & symbol 76 long long number; // for number 77 int idref; 78} object_t; 79 80// this code is reentrant, this structure contains all 81// state information for the parsing of a single buffer 82typedef struct parser_state { 83 const char *parseBuffer; // start of text to be parsed 84 int parseBufferIndex; // current index into text 85 int lineNumber; // current line number 86 object_t *objects; // internal objects in use 87 object_t *freeObjects; // internal objects that are free 88 OSDictionary *tags; // used to remember "ID" tags 89 OSString **errorString; // parse error with line 90 OSObject *parsedObject; // resultant object of parsed text 91} parser_state_t; 92 93#define STATE ((parser_state_t *)state) 94 95#undef yyerror 96#define yyerror(s) OSUnserializeerror(STATE, (s)) 97static int OSUnserializeerror(parser_state_t *state, char *s); 98 99static int yylex(YYSTYPE *lvalp, parser_state_t *state); 100static int yyparse(void * state); 101 102static object_t *newObject(parser_state_t *state); 103static void freeObject(parser_state_t *state, object_t *o); 104static void rememberObject(parser_state_t *state, int tag, OSObject *o); 105static object_t *retrieveObject(parser_state_t *state, int tag); 106static void cleanupObjects(parser_state_t *state); 107 108static object_t *buildDictionary(parser_state_t *state, object_t *o); 109static object_t *buildArray(parser_state_t *state, object_t *o); 110static object_t *buildSet(parser_state_t *state, object_t *o); 111static object_t *buildString(parser_state_t *state, object_t *o); 112static object_t *buildData(parser_state_t *state, object_t *o); 113static object_t *buildNumber(parser_state_t *state, object_t *o); 114static object_t *buildBoolean(parser_state_t *state, object_t *o); 115 116extern "C" { 117extern void *kern_os_malloc(size_t size); 118extern void *kern_os_realloc(void * addr, size_t size); 119extern void kern_os_free(void * addr); 120 121//XXX shouldn't have to define these 122extern long strtol(const char *, char **, int); 123extern unsigned long strtoul(const char *, char **, int); 124 125} /* extern "C" */ 126 127#define malloc(s) kern_os_malloc(s) 128#define realloc(a, s) kern_os_realloc(a, s) 129#define free(a) kern_os_free(a) 130 131%} 132%token ARRAY 133%token BOOLEAN 134%token DATA 135%token DICTIONARY 136%token IDREF 137%token KEY 138%token NUMBER 139%token SET 140%token STRING 141%token SYNTAX_ERROR 142%% /* Grammar rules and actions follow */ 143 144input: /* empty */ { yyerror("unexpected end of buffer"); 145 YYERROR; 146 } 147 | object { STATE->parsedObject = $1->object; 148 $1->object = 0; 149 freeObject(STATE, $1); 150 YYACCEPT; 151 } 152 | SYNTAX_ERROR { yyerror("syntax error"); 153 YYERROR; 154 } 155 ; 156 157object: dict { $$ = buildDictionary(STATE, $1); } 158 | array { $$ = buildArray(STATE, $1); } 159 | set { $$ = buildSet(STATE, $1); } 160 | string { $$ = buildString(STATE, $1); } 161 | data { $$ = buildData(STATE, $1); } 162 | number { $$ = buildNumber(STATE, $1); } 163 | boolean { $$ = buildBoolean(STATE, $1); } 164 | idref { $$ = retrieveObject(STATE, $1->idref); 165 if ($$) { 166 $$->object->retain(); 167 } else { 168 yyerror("forward reference detected"); 169 YYERROR; 170 } 171 freeObject(STATE, $1); 172 } 173 ; 174 175//------------------------------------------------------------------------------ 176 177dict: '{' '}' { $$ = $1; 178 $$->elements = NULL; 179 } 180 | '{' pairs '}' { $$ = $1; 181 $$->elements = $2; 182 } 183 | DICTIONARY 184 ; 185 186pairs: pair 187 | pairs pair { $$ = $2; 188 $$->next = $1; 189 } 190 ; 191 192pair: key object { $$ = $1; 193 $$->key = $$->object; 194 $$->object = $2->object; 195 $$->next = NULL; 196 $2->object = 0; 197 freeObject(STATE, $2); 198 } 199 ; 200 201key: KEY { $$ = buildString(STATE, $1); } 202 ; 203 204//------------------------------------------------------------------------------ 205 206array: '(' ')' { $$ = $1; 207 $$->elements = NULL; 208 } 209 | '(' elements ')' { $$ = $1; 210 $$->elements = $2; 211 } 212 | ARRAY 213 ; 214 215set: '[' ']' { $$ = $1; 216 $$->elements = NULL; 217 } 218 | '[' elements ']' { $$ = $1; 219 $$->elements = $2; 220 } 221 | SET 222 ; 223 224elements: object { $$ = $1; 225 $$->next = NULL; 226 } 227 | elements object { $$ = $2; 228 $$->next = $1; 229 } 230 ; 231 232//------------------------------------------------------------------------------ 233 234boolean: BOOLEAN 235 ; 236 237data: DATA 238 ; 239 240idref: IDREF 241 ; 242 243number: NUMBER 244 ; 245 246string: STRING 247 ; 248 249%% 250 251int 252OSUnserializeerror(parser_state_t * state, char *s) /* Called by yyparse on errors */ 253{ 254 char tempString[128]; 255 256 if (state->errorString) { 257 snprintf(tempString, 128, "OSUnserializeXML: %s near line %d\n", s, state->lineNumber); 258 *(state->errorString) = OSString::withCString(tempString); 259 } 260 261 return 0; 262} 263 264#define TAG_MAX_LENGTH 32 265#define TAG_MAX_ATTRIBUTES 32 266#define TAG_BAD 0 267#define TAG_START 1 268#define TAG_END 2 269#define TAG_EMPTY 3 270#define TAG_COMMENT 4 271 272#define currentChar() (state->parseBuffer[state->parseBufferIndex]) 273#define nextChar() (state->parseBuffer[++state->parseBufferIndex]) 274#define prevChar() (state->parseBuffer[state->parseBufferIndex - 1]) 275 276#define isSpace(c) ((c) == ' ' || (c) == '\t') 277#define isAlpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) 278#define isDigit(c) ((c) >= '0' && (c) <= '9') 279#define isAlphaDigit(c) ((c) >= 'a' && (c) <= 'f') 280#define isHexDigit(c) (isDigit(c) || isAlphaDigit(c)) 281#define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-')) 282 283static int 284getTag(parser_state_t *state, 285 char tag[TAG_MAX_LENGTH], 286 int *attributeCount, 287 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH], 288 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] ) 289{ 290 int length = 0; 291 int c = currentChar(); 292 int tagType = TAG_START; 293 294 *attributeCount = 0; 295 296 if (c != '<') return TAG_BAD; 297 c = nextChar(); // skip '<' 298 299 if (c == '?' || c == '!') { 300 while ((c = nextChar()) != 0) { 301 if (c == '\n') state->lineNumber++; 302 if (c == '>') { 303 (void)nextChar(); 304 return TAG_COMMENT; 305 } 306 } 307 } 308 309 if (c == '/') { 310 c = nextChar(); // skip '/' 311 tagType = TAG_END; 312 } 313 if (!isAlpha(c)) return TAG_BAD; 314 315 /* find end of tag while copying it */ 316 while (isAlphaNumeric(c)) { 317 tag[length++] = c; 318 c = nextChar(); 319 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; 320 } 321 322 tag[length] = 0; 323 324// printf("tag %s, type %d\n", tag, tagType); 325 326 // look for attributes of the form attribute = "value" ... 327 while ((c != '>') && (c != '/')) { 328 while (isSpace(c)) c = nextChar(); 329 330 length = 0; 331 while (isAlphaNumeric(c)) { 332 attributes[*attributeCount][length++] = c; 333 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; 334 c = nextChar(); 335 } 336 attributes[*attributeCount][length] = 0; 337 338 while (isSpace(c)) c = nextChar(); 339 340 if (c != '=') return TAG_BAD; 341 c = nextChar(); 342 343 while (isSpace(c)) c = nextChar(); 344 345 if (c != '"') return TAG_BAD; 346 c = nextChar(); 347 length = 0; 348 while (c != '"') { 349 values[*attributeCount][length++] = c; 350 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD; 351 c = nextChar(); 352 } 353 values[*attributeCount][length] = 0; 354 355 c = nextChar(); // skip closing quote 356 357// printf(" attribute '%s' = '%s', nextchar = '%c'\n", 358// attributes[*attributeCount], values[*attributeCount], c); 359 360 (*attributeCount)++; 361 if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD; 362 } 363 364 if (c == '/') { 365 c = nextChar(); // skip '/' 366 tagType = TAG_EMPTY; 367 } 368 if (c != '>') return TAG_BAD; 369 c = nextChar(); // skip '>' 370 371 return tagType; 372} 373 374static char * 375getString(parser_state_t *state) 376{ 377 int c = currentChar(); 378 int start, length, i, j; 379 char * tempString; 380 381 start = state->parseBufferIndex; 382 /* find end of string */ 383 384 while (c != 0) { 385 if (c == '\n') state->lineNumber++; 386 if (c == '<') { 387 break; 388 } 389 c = nextChar(); 390 } 391 392 if (c != '<') return 0; 393 394 length = state->parseBufferIndex - start; 395 396 /* copy to null terminated buffer */ 397 tempString = (char *)malloc(length + 1); 398 if (tempString == 0) { 399 printf("OSUnserializeXML: can't alloc temp memory\n"); 400 goto error; 401 } 402 403 // copy out string in tempString 404 // "&" -> '&', "<" -> '<', ">" -> '>' 405 406 i = j = 0; 407 while (i < length) { 408 c = state->parseBuffer[start + i++]; 409 if (c != '&') { 410 tempString[j++] = c; 411 } else { 412 if ((i+3) > length) goto error; 413 c = state->parseBuffer[start + i++]; 414 if (c == 'l') { 415 if (state->parseBuffer[start + i++] != 't') goto error; 416 if (state->parseBuffer[start + i++] != ';') goto error; 417 tempString[j++] = '<'; 418 continue; 419 } 420 if (c == 'g') { 421 if (state->parseBuffer[start + i++] != 't') goto error; 422 if (state->parseBuffer[start + i++] != ';') goto error; 423 tempString[j++] = '>'; 424 continue; 425 } 426 if ((i+3) > length) goto error; 427 if (c == 'a') { 428 if (state->parseBuffer[start + i++] != 'm') goto error; 429 if (state->parseBuffer[start + i++] != 'p') goto error; 430 if (state->parseBuffer[start + i++] != ';') goto error; 431 tempString[j++] = '&'; 432 continue; 433 } 434 goto error; 435 } 436 } 437 tempString[j] = 0; 438 439// printf("string %s\n", tempString); 440 441 return tempString; 442 443error: 444 if (tempString) free(tempString); 445 return 0; 446} 447 448static long long 449getNumber(parser_state_t *state) 450{ 451 unsigned long long n = 0; 452 int base = 10; 453 bool negate = false; 454 int c = currentChar(); 455 456 if (c == '0') { 457 c = nextChar(); 458 if (c == 'x') { 459 base = 16; 460 c = nextChar(); 461 } 462 } 463 if (base == 10) { 464 if (c == '-') { 465 negate = true; 466 c = nextChar(); 467 } 468 while(isDigit(c)) { 469 n = (n * base + c - '0'); 470 c = nextChar(); 471 } 472 if (negate) { 473 n = (unsigned long long)((long long)n * (long long)-1); 474 } 475 } else { 476 while(isHexDigit(c)) { 477 if (isDigit(c)) { 478 n = (n * base + c - '0'); 479 } else { 480 n = (n * base + 0xa + c - 'a'); 481 } 482 c = nextChar(); 483 } 484 } 485// printf("number 0x%x\n", (unsigned long)n); 486 return n; 487} 488 489// taken from CFXMLParsing/CFPropertyList.c 490 491static const signed char __CFPLDataDecodeTable[128] = { 492 /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1, 493 /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1, 494 /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1, 495 /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1, 496 /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1, 497 /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63, 498 /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59, 499 /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1, 500 /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6, 501 /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14, 502 /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22, 503 /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1, 504 /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32, 505 /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40, 506 /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48, 507 /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1 508}; 509 510#define DATA_ALLOC_SIZE 4096 511 512static void * 513getCFEncodedData(parser_state_t *state, unsigned int *size) 514{ 515 int numeq = 0, acc = 0, cntr = 0; 516 int tmpbufpos = 0, tmpbuflen = 0; 517 unsigned char *tmpbuf = (unsigned char *)malloc(DATA_ALLOC_SIZE); 518 519 int c = currentChar(); 520 *size = 0; 521 522 while (c != '<') { 523 c &= 0x7f; 524 if (c == 0) { 525 free(tmpbuf); 526 return 0; 527 } 528 if (c == '=') numeq++; else numeq = 0; 529 if (c == '\n') state->lineNumber++; 530 if (__CFPLDataDecodeTable[c] < 0) { 531 c = nextChar(); 532 continue; 533 } 534 cntr++; 535 acc <<= 6; 536 acc += __CFPLDataDecodeTable[c]; 537 if (0 == (cntr & 0x3)) { 538 if (tmpbuflen <= tmpbufpos + 2) { 539 tmpbuflen += DATA_ALLOC_SIZE; 540 tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen); 541 } 542 tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff; 543 if (numeq < 2) 544 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff; 545 if (numeq < 1) 546 tmpbuf[tmpbufpos++] = acc & 0xff; 547 } 548 c = nextChar(); 549 } 550 *size = tmpbufpos; 551 if (*size == 0) { 552 free(tmpbuf); 553 return 0; 554 } 555 return tmpbuf; 556} 557 558static void * 559getHexData(parser_state_t *state, unsigned int *size) 560{ 561 int c; 562 unsigned char *d, *start, *lastStart; 563 564 start = lastStart = d = (unsigned char *)malloc(DATA_ALLOC_SIZE); 565 c = currentChar(); 566 567 while (c != '<') { 568 569 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {}; 570 if (c == '\n') { 571 state->lineNumber++; 572 c = nextChar(); 573 continue; 574 } 575 576 // get high nibble 577 if (isDigit(c)) { 578 *d = (c - '0') << 4; 579 } else if (isAlphaDigit(c)) { 580 *d = (0xa + (c - 'a')) << 4; 581 } else { 582 goto error; 583 } 584 585 // get low nibble 586 c = nextChar(); 587 if (isDigit(c)) { 588 *d |= c - '0'; 589 } else if (isAlphaDigit(c)) { 590 *d |= 0xa + (c - 'a'); 591 } else { 592 goto error; 593 } 594 595 d++; 596 if ((d - lastStart) >= DATA_ALLOC_SIZE) { 597 int oldsize = d - start; 598 start = (unsigned char *)realloc(start, oldsize + DATA_ALLOC_SIZE); 599 d = lastStart = start + oldsize; 600 } 601 c = nextChar(); 602 } 603 604 *size = d - start; 605 return start; 606 607 error: 608 609 *size = 0; 610 free(start); 611 return 0; 612} 613 614static int 615yylex(YYSTYPE *lvalp, parser_state_t *state) 616{ 617 int c, i; 618 int tagType; 619 char tag[TAG_MAX_LENGTH]; 620 int attributeCount; 621 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH]; 622 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH]; 623 object_t *object; 624 625 top: 626 c = currentChar(); 627 628 /* skip white space */ 629 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {}; 630 631 /* keep track of line number, don't return \n's */ 632 if (c == '\n') { 633 STATE->lineNumber++; 634 (void)nextChar(); 635 goto top; 636 } 637 638 // end of the buffer? 639 if (!c) return 0; 640 641 tagType = getTag(STATE, tag, &attributeCount, attributes, values); 642 if (tagType == TAG_BAD) return SYNTAX_ERROR; 643 if (tagType == TAG_COMMENT) goto top; 644 645 // handle allocation and check for "ID" and "IDREF" tags up front 646 *lvalp = object = newObject(STATE); 647 object->idref = -1; 648 for (i=0; i < attributeCount; i++) { 649 if (attributes[i][0] == 'I' && attributes[i][1] == 'D') { 650 // check for idref's, note: we ignore the tag, for 651 // this to work correctly, all idrefs must be unique 652 // across the whole serialization 653 if (attributes[i][2] == 'R' && attributes[i][3] == 'E' && 654 attributes[i][4] == 'F' && !attributes[i][5]) { 655 if (tagType != TAG_EMPTY) return SYNTAX_ERROR; 656 object->idref = strtol(values[i], NULL, 0); 657 return IDREF; 658 } 659 // check for id's 660 if (!attributes[i][2]) { 661 object->idref = strtol(values[i], NULL, 0); 662 } else { 663 return SYNTAX_ERROR; 664 } 665 } 666 } 667 668 switch (*tag) { 669 case 'a': 670 if (!strcmp(tag, "array")) { 671 if (tagType == TAG_EMPTY) { 672 object->elements = NULL; 673 return ARRAY; 674 } 675 return (tagType == TAG_START) ? '(' : ')'; 676 } 677 break; 678 case 'd': 679 if (!strcmp(tag, "dict")) { 680 if (tagType == TAG_EMPTY) { 681 object->elements = NULL; 682 return DICTIONARY; 683 } 684 return (tagType == TAG_START) ? '{' : '}'; 685 } 686 if (!strcmp(tag, "data")) { 687 unsigned int size; 688 if (tagType == TAG_EMPTY) { 689 object->data = NULL; 690 object->size = 0; 691 return DATA; 692 } 693 694 bool isHexFormat = false; 695 for (int i=0; i < attributeCount; i++) { 696 if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) { 697 isHexFormat = true; 698 break; 699 } 700 } 701 // CF encoded is the default form 702 if (isHexFormat) { 703 object->data = getHexData(STATE, &size); 704 } else { 705 object->data = getCFEncodedData(STATE, &size); 706 } 707 object->size = size; 708 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) { 709 return SYNTAX_ERROR; 710 } 711 return DATA; 712 } 713 break; 714 case 'f': 715 if (!strcmp(tag, "false")) { 716 if (tagType == TAG_EMPTY) { 717 object->number = 0; 718 return BOOLEAN; 719 } 720 } 721 break; 722 case 'i': 723 if (!strcmp(tag, "integer")) { 724 object->size = 64; // default 725 for (i=0; i < attributeCount; i++) { 726 if (!strcmp(attributes[i], "size")) { 727 object->size = strtoul(values[i], NULL, 0); 728 } 729 } 730 if (tagType == TAG_EMPTY) { 731 object->number = 0; 732 return NUMBER; 733 } 734 object->number = getNumber(STATE); 735 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) { 736 return SYNTAX_ERROR; 737 } 738 return NUMBER; 739 } 740 break; 741 case 'k': 742 if (!strcmp(tag, "key")) { 743 if (tagType == TAG_EMPTY) return SYNTAX_ERROR; 744 object->string = getString(STATE); 745 if (!object->string) { 746 return SYNTAX_ERROR; 747 } 748 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) 749 || strcmp(tag, "key")) { 750 return SYNTAX_ERROR; 751 } 752 return KEY; 753 } 754 break; 755 case 'p': 756 if (!strcmp(tag, "plist")) { 757 freeObject(STATE, object); 758 goto top; 759 } 760 break; 761 case 's': 762 if (!strcmp(tag, "string")) { 763 if (tagType == TAG_EMPTY) { 764 object->string = (char *)malloc(1); 765 object->string[0] = 0; 766 return STRING; 767 } 768 object->string = getString(STATE); 769 if (!object->string) { 770 return SYNTAX_ERROR; 771 } 772 if ((getTag(STATE, tag, &attributeCount, attributes, values) != TAG_END) 773 || strcmp(tag, "string")) { 774 return SYNTAX_ERROR; 775 } 776 return STRING; 777 } 778 if (!strcmp(tag, "set")) { 779 if (tagType == TAG_EMPTY) { 780 object->elements = NULL; 781 return SET;; 782 } 783 if (tagType == TAG_START) { 784 return '['; 785 } else { 786 return ']'; 787 } 788 } 789 break; 790 case 't': 791 if (!strcmp(tag, "true")) { 792 if (tagType == TAG_EMPTY) { 793 object->number = 1; 794 return BOOLEAN; 795 } 796 } 797 break; 798 } 799 800 return SYNTAX_ERROR; 801} 802 803// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 804// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 805// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 806 807// "java" like allocation, if this code hits a syntax error in the 808// the middle of the parsed string we just bail with pointers hanging 809// all over place, this code helps keeps it all together 810 811//static int object_count = 0; 812 813object_t * 814newObject(parser_state_t *state) 815{ 816 object_t *o; 817 818 if (state->freeObjects) { 819 o = state->freeObjects; 820 state->freeObjects = state->freeObjects->next; 821 } else { 822 o = (object_t *)malloc(sizeof(object_t)); 823// object_count++; 824 bzero(o, sizeof(object_t)); 825 o->free = state->objects; 826 state->objects = o; 827 } 828 829 return o; 830} 831 832void 833freeObject(parser_state_t * state, object_t *o) 834{ 835 o->next = state->freeObjects; 836 state->freeObjects = o; 837} 838 839void 840cleanupObjects(parser_state_t *state) 841{ 842 object_t *t, *o = state->objects; 843 844 while (o) { 845 if (o->object) { 846// printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object); 847 o->object->release(); 848 } 849 if (o->data) { 850// printf("OSUnserializeXML: freeing object o=%x data=%x\n", (int)o, (int)o->data); 851 free(o->data); 852 } 853 if (o->key) { 854// printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key); 855 o->key->release(); 856 } 857 if (o->string) { 858// printf("OSUnserializeXML: freeing object o=%x string=%x\n", (int)o, (int)o->string); 859 free(o->string); 860 } 861 862 t = o; 863 o = o->free; 864 free(t); 865// object_count--; 866 } 867// printf("object_count = %d\n", object_count); 868} 869 870// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 871// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 872// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 873 874static void 875rememberObject(parser_state_t *state, int tag, OSObject *o) 876{ 877 char key[16]; 878 snprintf(key, 16, "%u", tag); 879 880// printf("remember key %s\n", key); 881 882 state->tags->setObject(key, o); 883} 884 885static object_t * 886retrieveObject(parser_state_t *state, int tag) 887{ 888 OSObject *ref; 889 object_t *o; 890 char key[16]; 891 snprintf(key, 16, "%u", tag); 892 893// printf("retrieve key '%s'\n", key); 894 895 ref = state->tags->getObject(key); 896 if (!ref) return 0; 897 898 o = newObject(state); 899 o->object = ref; 900 return o; 901} 902 903// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 904// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 905// !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# 906 907object_t * 908buildDictionary(parser_state_t *state, object_t * header) 909{ 910 object_t *o, *t; 911 int count = 0; 912 OSDictionary *dict; 913 914 // get count and reverse order 915 o = header->elements; 916 header->elements = 0; 917 while (o) { 918 count++; 919 t = o; 920 o = o->next; 921 922 t->next = header->elements; 923 header->elements = t; 924 } 925 926 dict = OSDictionary::withCapacity(count); 927 if (header->idref >= 0) rememberObject(state, header->idref, dict); 928 929 o = header->elements; 930 while (o) { 931 dict->setObject(o->key, o->object); 932 933 o->key->release(); 934 o->object->release(); 935 o->key = 0; 936 o->object = 0; 937 938 t = o; 939 o = o->next; 940 freeObject(state, t); 941 } 942 o = header; 943 o->object = dict; 944 return o; 945}; 946 947object_t * 948buildArray(parser_state_t *state, object_t * header) 949{ 950 object_t *o, *t; 951 int count = 0; 952 OSArray *array; 953 954 // get count and reverse order 955 o = header->elements; 956 header->elements = 0; 957 while (o) { 958 count++; 959 t = o; 960 o = o->next; 961 962 t->next = header->elements; 963 header->elements = t; 964 } 965 966 array = OSArray::withCapacity(count); 967 if (header->idref >= 0) rememberObject(state, header->idref, array); 968 969 o = header->elements; 970 while (o) { 971 array->setObject(o->object); 972 973 o->object->release(); 974 o->object = 0; 975 976 t = o; 977 o = o->next; 978 freeObject(state, t); 979 } 980 o = header; 981 o->object = array; 982 return o; 983}; 984 985object_t * 986buildSet(parser_state_t *state, object_t *header) 987{ 988 object_t *o = buildArray(state, header); 989 990 OSArray *array = (OSArray *)o->object; 991 OSSet *set = OSSet::withArray(array, array->getCapacity()); 992 993 // write over the reference created in buildArray 994 if (header->idref >= 0) rememberObject(state, header->idref, set); 995 996 array->release(); 997 o->object = set; 998 return o; 999}; 1000
1001object_t * 1002buildString(parser_state_t *state, object_t *o) 1003{ 1004 OSString *string; 1005 1006 string = OSString::withCString(o->string); 1007 if (o->idref >= 0) rememberObject(state, o->idref, string); 1008 1009 free(o->string); 1010 o->string = 0; 1011 o->object = string; 1012 1013 return o; 1014}; 1015 1016object_t * 1017buildData(parser_state_t *state, object_t *o) 1018{ 1019 OSData *data; 1020 1021 if (o->size) { 1022 data = OSData::withBytes(o->data, o->size); 1023 } else { 1024 data = OSData::withCapacity(0); 1025 } 1026 if (o->idref >= 0) rememberObject(state, o->idref, data); 1027 1028 if (o->size) free(o->data); 1029 o->data = 0; 1030 o->object = data; 1031 return o; 1032}; 1033 1034object_t * 1035buildNumber(parser_state_t *state, object_t *o) 1036{ 1037 OSNumber *number = OSNumber::withNumber(o->number, o->size); 1038 1039 if (o->idref >= 0) rememberObject(state, o->idref, number); 1040 1041 o->object = number; 1042 return o; 1043}; 1044 1045object_t * 1046buildBoolean(parser_state_t *state, object_t *o) 1047{ 1048 o->object = ((o->number == 0) ? kOSBooleanFalse : kOSBooleanTrue); 1049 o->object->retain(); 1050 return o; 1051}; 1052 1053OSObject* 1054OSUnserializeXML(const char *buffer, OSString **errorString) 1055{ 1056 OSObject *object; 1057 parser_state_t *state = (parser_state_t *)malloc(sizeof(parser_state_t)); 1058 1059 if ((!state) || (!buffer)) return 0; 1060 1061 // just in case 1062 if (errorString) *errorString = NULL; 1063 1064 state->parseBuffer = buffer; 1065 state->parseBufferIndex = 0; 1066 state->lineNumber = 1; 1067 state->objects = 0; 1068 state->freeObjects = 0; 1069 state->tags = OSDictionary::withCapacity(128); 1070 state->errorString = errorString; 1071 state->parsedObject = 0; 1072 1073 (void)yyparse((void *)state); 1074 1075 object = state->parsedObject; 1076 1077 cleanupObjects(state); 1078 state->tags->release(); 1079 free(state); 1080 1081 return object; 1082} 1083 1084 1085// 1086// 1087// 1088// 1089// 1090// DO NOT EDIT OSUnserializeXML.cpp! 1091// 1092// this means you! 1093// 1094// 1095// 1096// 1097// 1098

