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