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