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