|
|
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.