|
|
1.1 ! root 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: /* OSUnserialize.y created by rsulack on Nov 21 1998 */ ! 24: ! 25: // "classic" parser for unserializing OSContainer objects ! 26: // ! 27: // XXX - this code should really be removed! ! 28: // - the XML format is now prefered ! 29: // - this code leaks on syntax errors, the XML doesn't ! 30: // - "classic" looks, reads, ... much better than XML :-( ! 31: // - well except the XML is more efficent on OSData ! 32: // ! 33: // ! 34: // to build : ! 35: // bison -p OSUnserialize OSUnserialize.y ! 36: // sed -e "s/stdio.h/stddef.h/" < OSUnserialize.tab.c > OSUnserialize.cpp ! 37: // ! 38: // when changing code check in both OSUnserialize.y and OSUnserialize.cpp ! 39: // ! 40: // ! 41: // ! 42: // ! 43: // DO NOT EDIT OSUnserialize.tab.cpp! ! 44: // ! 45: // this means you! ! 46: // ! 47: // ! 48: // ! 49: // ! 50: // ! 51: ! 52: ! 53: %{ ! 54: #include <libkern/c++/OSMetaClass.h> ! 55: #include <libkern/c++/OSContainers.h> ! 56: #include <libkern/c++/OSLib.h> ! 57: ! 58: typedef struct object { ! 59: struct object *next; ! 60: struct object *prev; ! 61: void *object; ! 62: int size; // for data ! 63: union { ! 64: void *key; // for dictionary ! 65: long long offset; // for offset ! 66: } u; ! 67: ! 68: } object_t; ! 69: ! 70: static int yyparse(); ! 71: static int yyerror(char *s); ! 72: static int yylex(); ! 73: ! 74: static object_t * newObject(); ! 75: static void freeObject(object_t *o); ! 76: ! 77: static OSObject *buildOSDictionary(object_t *); ! 78: static OSObject *buildOSArray(object_t *); ! 79: static OSObject *buildOSSet(object_t *); ! 80: static OSObject *buildOSString(object_t *); ! 81: static OSObject *buildOSData(object_t *); ! 82: static OSObject *buildOSOffset(object_t *); ! 83: static OSObject *buildOSBoolean(object_t *o); ! 84: ! 85: static void rememberObject(int, object_t *); ! 86: static OSObject *retrieveObject(int); ! 87: ! 88: // temp variable to use during parsing ! 89: static object_t *o; ! 90: ! 91: // resultant object of parsed text ! 92: static OSObject *parsedObject; ! 93: ! 94: #define YYSTYPE object_t * ! 95: ! 96: extern "C" { ! 97: extern void *kern_os_malloc(size_t size); ! 98: extern void *kern_os_realloc(void * addr, size_t size); ! 99: extern void kern_os_free(void * addr); ! 100: } /* extern "C" */ ! 101: ! 102: #define malloc(s) kern_os_malloc(s) ! 103: #define realloc(a, s) kern_os_realloc(a, s) ! 104: #define free(a) kern_os_free(a) ! 105: ! 106: %} ! 107: %token NUMBER ! 108: %token STRING ! 109: %token DATA ! 110: %token BOOLEAN ! 111: %token SYNTAX_ERROR ! 112: ! 113: %% /* Grammar rules and actions follow */ ! 114: ! 115: input: /* empty */ { parsedObject = (OSObject *)NULL; YYACCEPT; } ! 116: | object { parsedObject = (OSObject *)$1; YYACCEPT; } ! 117: | SYNTAX_ERROR { yyerror("syntax error"); YYERROR; } ! 118: ; ! 119: ! 120: object: dict { $$ = (object_t *)buildOSDictionary($1); } ! 121: | array { $$ = (object_t *)buildOSArray($1); } ! 122: | set { $$ = (object_t *)buildOSSet($1); } ! 123: | string { $$ = (object_t *)buildOSString($1); } ! 124: | data { $$ = (object_t *)buildOSData($1); } ! 125: | offset { $$ = (object_t *)buildOSOffset($1); } ! 126: | boolean { $$ = (object_t *)buildOSBoolean($1); } ! 127: | '@' NUMBER { $$ = (object_t *)retrieveObject($2->u.offset); ! 128: if ($$) { ! 129: ((OSObject *)$$)->retain(); ! 130: } else { ! 131: yyerror("forward reference detected"); ! 132: YYERROR; ! 133: } ! 134: freeObject($2); ! 135: } ! 136: | object '@' NUMBER { $$ = $1; ! 137: rememberObject($3->u.offset, $1); ! 138: freeObject($3); ! 139: } ! 140: ; ! 141: ! 142: //------------------------------------------------------------------------------ ! 143: ! 144: dict: '{' '}' { $$ = NULL; } ! 145: | '{' pairs '}' { $$ = $2; } ! 146: ; ! 147: ! 148: pairs: pair ! 149: | pairs pair { $2->next = $1; $1->prev = $2; $$ = $2; } ! 150: ; ! 151: ! 152: pair: object '=' object ';' { $$ = newObject(); ! 153: $$->next = NULL; ! 154: $$->prev = NULL; ! 155: $$->u.key = $1; ! 156: $$->object = $3; ! 157: } ! 158: ; ! 159: ! 160: //------------------------------------------------------------------------------ ! 161: ! 162: array: '(' ')' { $$ = NULL; } ! 163: | '(' elements ')' { $$ = $2; } ! 164: ; ! 165: ! 166: set: '[' ']' { $$ = NULL; } ! 167: | '[' elements ']' { $$ = $2; } ! 168: ; ! 169: ! 170: elements: object { $$ = newObject(); ! 171: $$->object = $1; ! 172: $$->next = NULL; ! 173: $$->prev = NULL; ! 174: } ! 175: | elements ',' object { o = newObject(); ! 176: o->object = $3; ! 177: o->next = $1; ! 178: o->prev = NULL; ! 179: $1->prev = o; ! 180: $$ = o; ! 181: } ! 182: ; ! 183: ! 184: //------------------------------------------------------------------------------ ! 185: ! 186: offset: NUMBER ':' NUMBER { $$ = $1; ! 187: $$->size = $3->u.offset; ! 188: freeObject($3); ! 189: } ! 190: ; ! 191: ! 192: //------------------------------------------------------------------------------ ! 193: ! 194: data: DATA ! 195: ; ! 196: ! 197: //------------------------------------------------------------------------------ ! 198: ! 199: string: STRING ! 200: ; ! 201: ! 202: //------------------------------------------------------------------------------ ! 203: ! 204: boolean: BOOLEAN ! 205: ; ! 206: ! 207: %% ! 208: ! 209: static int lineNumber = 0; ! 210: static const char *parseBuffer; ! 211: static int parseBufferIndex; ! 212: ! 213: #define currentChar() (parseBuffer[parseBufferIndex]) ! 214: #define nextChar() (parseBuffer[++parseBufferIndex]) ! 215: #define prevChar() (parseBuffer[parseBufferIndex - 1]) ! 216: ! 217: #define isSpace(c) ((c) == ' ' || (c) == '\t') ! 218: #define isAlpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) ! 219: #define isDigit(c) ((c) >= '0' && (c) <= '9') ! 220: #define isAlphaDigit(c) ((c) >= 'a' && (c) <= 'f') ! 221: #define isHexDigit(c) (isDigit(c) || isAlphaDigit(c)) ! 222: #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-')) ! 223: ! 224: static char yyerror_message[128]; ! 225: ! 226: int ! 227: yyerror(char *s) /* Called by yyparse on error */ ! 228: { ! 229: sprintf(yyerror_message, "OSUnserialize: %s near line %d\n", s, lineNumber); ! 230: return 0; ! 231: } ! 232: ! 233: int ! 234: yylex() ! 235: { ! 236: int c; ! 237: ! 238: if (parseBufferIndex == 0) lineNumber = 1; ! 239: ! 240: top: ! 241: c = currentChar(); ! 242: ! 243: /* skip white space */ ! 244: if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {}; ! 245: ! 246: /* skip over comments */ ! 247: if (c == '#') while ((c = nextChar()) != 0 && c != '\n') {}; ! 248: ! 249: /* keep track of line number, don't return \n's */ ! 250: if (c == '\n') { ! 251: lineNumber++; ! 252: (void)nextChar(); ! 253: goto top; ! 254: } ! 255: ! 256: /* parse boolean */ ! 257: if (c == '.') { ! 258: bool boolean = false; ! 259: if (nextChar() == 't') { ! 260: if (nextChar() != 'r') return SYNTAX_ERROR; ! 261: if (nextChar() != 'u') return SYNTAX_ERROR; ! 262: if (nextChar() != 'e') return SYNTAX_ERROR; ! 263: boolean = true; ! 264: } else { ! 265: if (currentChar() != 'f') return SYNTAX_ERROR; ! 266: if (nextChar() != 'a') return SYNTAX_ERROR; ! 267: if (nextChar() != 'l') return SYNTAX_ERROR; ! 268: if (nextChar() != 's') return SYNTAX_ERROR; ! 269: if (nextChar() != 'e') return SYNTAX_ERROR; ! 270: } ! 271: if (nextChar() != '.') return SYNTAX_ERROR; ! 272: /* skip over dot */ ! 273: (void)nextChar(); ! 274: ! 275: yylval = (object_t *)boolean; ! 276: return BOOLEAN; ! 277: } ! 278: ! 279: /* parse unquoted string */ ! 280: if (isAlpha(c)) { ! 281: int start, length; ! 282: char * tempString; ! 283: ! 284: start = parseBufferIndex; ! 285: /* find end of string */ ! 286: while (isAlphaNumeric(c)) { ! 287: c = nextChar(); ! 288: } ! 289: length = parseBufferIndex - start; ! 290: ! 291: /* copy to null terminated buffer */ ! 292: tempString = (char *)malloc(length + 1); ! 293: if (tempString == 0) { ! 294: printf("OSUnserialize: can't alloc temp memory\n"); ! 295: return 0; ! 296: } ! 297: bcopy(&parseBuffer[start], tempString, length); ! 298: tempString[length] = 0; ! 299: yylval = (object_t *)tempString; ! 300: return STRING; ! 301: } ! 302: ! 303: /* parse quoted string */ ! 304: if (c == '"' || c == '\'') { ! 305: int start, length; ! 306: char * tempString; ! 307: char quoteChar = c; ! 308: ! 309: start = parseBufferIndex + 1; // skip quote ! 310: /* find end of string, line, buffer */ ! 311: while ((c = nextChar()) != quoteChar) { ! 312: if (c == '\\') c = nextChar(); ! 313: if (c == '\n') lineNumber++; ! 314: if (c == 0) return SYNTAX_ERROR; ! 315: } ! 316: length = parseBufferIndex - start; ! 317: /* skip over trailing quote */ ! 318: (void)nextChar(); ! 319: /* copy to null terminated buffer */ ! 320: tempString = (char *)malloc(length + 1); ! 321: if (tempString == 0) { ! 322: printf("OSUnserialize: can't alloc temp memory\n"); ! 323: return 0; ! 324: } ! 325: ! 326: int to = 0; ! 327: for (int from=start; from < parseBufferIndex; from++) { ! 328: // hack - skip over backslashes ! 329: if (parseBuffer[from] == '\\') { ! 330: length--; ! 331: continue; ! 332: } ! 333: tempString[to] = parseBuffer[from]; ! 334: to++; ! 335: } ! 336: tempString[length] = 0; ! 337: yylval = (object_t *)tempString; ! 338: return STRING; ! 339: } ! 340: ! 341: /* process numbers */ ! 342: if (isDigit (c)) ! 343: { ! 344: unsigned long long n = 0; ! 345: int base = 10; ! 346: ! 347: if (c == '0') { ! 348: c = nextChar(); ! 349: if (c == 'x') { ! 350: base = 16; ! 351: c = nextChar(); ! 352: } ! 353: } ! 354: if (base == 10) { ! 355: while(isDigit(c)) { ! 356: n = (n * base + c - '0'); ! 357: c = nextChar(); ! 358: } ! 359: } else { ! 360: while(isHexDigit(c)) { ! 361: if (isDigit(c)) { ! 362: n = (n * base + c - '0'); ! 363: } else { ! 364: n = (n * base + 0xa + c - 'a'); ! 365: } ! 366: c = nextChar(); ! 367: } ! 368: } ! 369: ! 370: yylval = newObject(); ! 371: yylval->u.offset = n; ! 372: ! 373: return NUMBER; ! 374: } ! 375: ! 376: #define OSDATA_ALLOC_SIZE 4096 ! 377: ! 378: /* process data */ ! 379: if (c == '<') { ! 380: unsigned char *d, *start, *lastStart; ! 381: ! 382: start = lastStart = d = (unsigned char *)malloc(OSDATA_ALLOC_SIZE); ! 383: c = nextChar(); // skip over '<' ! 384: while (c != 0 && c != '>') { ! 385: ! 386: if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {}; ! 387: if (c == '#') while ((c = nextChar()) != 0 && c != '\n') {}; ! 388: if (c == '\n') { ! 389: lineNumber++; ! 390: c = nextChar(); ! 391: continue; ! 392: } ! 393: ! 394: // get high nibble ! 395: if (!isHexDigit(c)) break; ! 396: if (isDigit(c)) { ! 397: *d = (c - '0') << 4; ! 398: } else { ! 399: *d = (0xa + (c - 'a')) << 4; ! 400: } ! 401: ! 402: // get low nibble ! 403: c = nextChar(); ! 404: if (!isHexDigit(c)) break; ! 405: if (isDigit(c)) { ! 406: *d |= c - '0'; ! 407: } else { ! 408: *d |= 0xa + (c - 'a'); ! 409: } ! 410: ! 411: d++; ! 412: if ((d - lastStart) >= OSDATA_ALLOC_SIZE) { ! 413: int oldsize = d - start; ! 414: start = (unsigned char *)realloc(start, oldsize + OSDATA_ALLOC_SIZE); ! 415: d = lastStart = start + oldsize; ! 416: } ! 417: c = nextChar(); ! 418: } ! 419: if (c != '>' ) { ! 420: free(start); ! 421: return SYNTAX_ERROR; ! 422: } ! 423: ! 424: // got it! ! 425: yylval = newObject(); ! 426: yylval->object = start; ! 427: yylval->size = d - start; ! 428: ! 429: (void)nextChar(); // skip over '>' ! 430: return DATA; ! 431: } ! 432: ! 433: ! 434: /* return single chars, move pointer to next char */ ! 435: (void)nextChar(); ! 436: return c; ! 437: } ! 438: ! 439: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 440: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 441: // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!# ! 442: ! 443: #ifdef DEBUG ! 444: int debugUnserializeAllocCount = 0; ! 445: #endif ! 446: ! 447: object_t * ! 448: newObject() ! 449: { ! 450: #ifdef DEBUG ! 451: debugUnserializeAllocCount++; ! 452: #endif ! 453: return (object_t *)malloc(sizeof(object_t)); ! 454: } ! 455: ! 456: void ! 457: freeObject(object_t *o) ! 458: { ! 459: #ifdef DEBUG ! 460: debugUnserializeAllocCount--; ! 461: #endif ! 462: free(o); ! 463: } ! 464: ! 465: static OSDictionary *tags; ! 466: ! 467: static void ! 468: rememberObject(int tag, object_t *o) ! 469: { ! 470: char key[16]; ! 471: sprintf(key, "%u", tag); ! 472: ! 473: tags->setObject(key, (OSObject *)o); ! 474: } ! 475: ! 476: static OSObject * ! 477: retrieveObject(int tag) ! 478: { ! 479: char key[16]; ! 480: sprintf(key, "%u", tag); ! 481: ! 482: return tags->getObject(key); ! 483: } ! 484: ! 485: OSObject * ! 486: buildOSDictionary(object_t *o) ! 487: { ! 488: object_t *temp, *last = o; ! 489: int count = 0; ! 490: ! 491: // get count and last object ! 492: while (o) { ! 493: count++; ! 494: last = o; ! 495: o = o->next; ! 496: } ! 497: o = last; ! 498: ! 499: OSDictionary *d = OSDictionary::withCapacity(count); ! 500: ! 501: while (o) { ! 502: #ifdef metaclass_stuff_worksXXX ! 503: if (((OSObject *)o->u.key)->metaCast("OSSymbol")) { ! 504: // XXX the evil frontdoor ! 505: d->setObject((OSSymbol *)o->u.key, (OSObject *)o->object); ! 506: } else { ! 507: // If it isn't a symbol, I hope it's a string! ! 508: d->setObject((OSString *)o->u.key, (OSObject *)o->object); ! 509: } ! 510: #else ! 511: d->setObject((OSString *)o->u.key, (OSObject *)o->object); ! 512: #endif ! 513: ((OSObject *)o->object)->release(); ! 514: ((OSObject *)o->u.key)->release(); ! 515: temp = o; ! 516: o = o->prev; ! 517: freeObject(temp); ! 518: } ! 519: return d; ! 520: }; ! 521: ! 522: OSObject * ! 523: buildOSArray(object_t *o) ! 524: { ! 525: object_t *temp, *last = o; ! 526: int count = 0; ! 527: ! 528: // get count and last object ! 529: while (o) { ! 530: count++; ! 531: last = o; ! 532: o = o->next; ! 533: } ! 534: o = last; ! 535: ! 536: OSArray *a = OSArray::withCapacity(count); ! 537: ! 538: while (o) { ! 539: a->setObject((OSObject *)o->object); ! 540: ((OSObject *)o->object)->release(); ! 541: temp = o; ! 542: o = o->prev; ! 543: freeObject(temp); ! 544: } ! 545: return a; ! 546: }; ! 547: ! 548: OSObject * ! 549: buildOSSet(object_t *o) ! 550: { ! 551: OSArray *a = (OSArray *)buildOSArray(o); ! 552: OSSet *s = OSSet::withArray(a, a->getCapacity()); ! 553: ! 554: a->release(); ! 555: return s; ! 556: }; ! 557: ! 558: OSObject * ! 559: buildOSString(object_t *o) ! 560: { ! 561: OSString *s = OSString::withCString((char *)o); ! 562: ! 563: free(o); ! 564: ! 565: return s; ! 566: }; ! 567: ! 568: OSObject * ! 569: buildOSData(object_t *o) ! 570: { ! 571: OSData *d; ! 572: ! 573: if (o->size) { ! 574: d = OSData::withBytes(o->object, o->size); ! 575: } else { ! 576: d = OSData::withCapacity(0); ! 577: } ! 578: free(o->object); ! 579: freeObject(o); ! 580: return d; ! 581: }; ! 582: ! 583: OSObject * ! 584: buildOSOffset(object_t *o) ! 585: { ! 586: OSNumber *off = OSNumber::withNumber(o->u.offset, o->size); ! 587: freeObject(o); ! 588: return off; ! 589: }; ! 590: ! 591: OSObject * ! 592: buildOSBoolean(object_t *o) ! 593: { ! 594: OSBoolean *b = OSBoolean::withBoolean((bool)o); ! 595: return b; ! 596: }; ! 597: ! 598: __BEGIN_DECLS ! 599: #include <kern/lock.h> ! 600: __END_DECLS ! 601: ! 602: static mutex_t *lock = 0; ! 603: ! 604: OSObject* ! 605: OSUnserialize(const char *buffer, OSString **errorString) ! 606: { ! 607: OSObject *object; ! 608: ! 609: if (!lock) { ! 610: lock = mutex_alloc(ETAP_IO_AHA); ! 611: _mutex_lock(lock); ! 612: } else { ! 613: _mutex_lock(lock); ! 614: ! 615: } ! 616: ! 617: #ifdef DEBUG ! 618: debugUnserializeAllocCount = 0; ! 619: #endif ! 620: yyerror_message[0] = 0; //just in case ! 621: parseBuffer = buffer; ! 622: parseBufferIndex = 0; ! 623: tags = OSDictionary::withCapacity(128); ! 624: if (yyparse() == 0) { ! 625: object = parsedObject; ! 626: if (errorString) *errorString = 0; ! 627: } else { ! 628: object = 0; ! 629: if (errorString) ! 630: *errorString = OSString::withCString(yyerror_message); ! 631: } ! 632: ! 633: tags->release(); ! 634: #ifdef DEBUG ! 635: if (debugUnserializeAllocCount) { ! 636: printf("OSUnserialize: allocation check failed, count = %d.\n", ! 637: debugUnserializeAllocCount); ! 638: } ! 639: #endif ! 640: mutex_unlock(lock); ! 641: ! 642: return object; ! 643: } ! 644: ! 645: ! 646: // ! 647: // ! 648: // ! 649: // ! 650: // ! 651: // DO NOT EDIT OSUnserialize.cpp! ! 652: // ! 653: // this means you! ! 654: // ! 655: // ! 656: // ! 657: // ! 658: //
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.