Annotation of XNU/libkern/c++/OSUnserialize.y, revision 1.1.1.1

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: //

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.