]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSUnserializeXML.y
918c683048dcf72e2326c07d1666b28b11d57cf8
[apple/xnu.git] / libkern / c++ / OSUnserializeXML.y
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 /* OSUnserializeXML.y created by rsulack on Tue Oct 12 1999 */
24
25 // XML parser for unserializing OSContainer objects
26 //
27 // to build :
28 // bison -p OSUnserializeXML OSUnserializeXML.y
29 // head -50 OSUnserializeXML.y > OSUnserializeXML.cpp
30 // sed -e "s/stdio.h/stddef.h/" < OSUnserializeXML.tab.c >> OSUnserializeXML.cpp
31 //
32 // when changing code check in both OSUnserializeXML.y and OSUnserializeXML.cpp
33 //
34 //
35 //
36 //
37 //
38 //
39 //
40 // DO NOT EDIT OSUnserializeXML.cpp!
41 //
42 // this means you!
43 //
44 //
45 //
46 //
47 //
48 //
49 //
50
51
52 %{
53 #include <string.h>
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 *free;
61 struct object *elements;
62 OSObject *object;
63 const OSSymbol *key; // for dictionary
64 int size;
65 void *data; // for data
66 char *string; // for string & symbol
67 long long number; // for number
68 int idref;
69 } object_t;
70
71 static int yyparse();
72 static int yyerror(char *s);
73 static int yylex();
74
75 static object_t * newObject();
76 static void freeObject(object_t *o);
77
78 static object_t *buildOSDictionary(object_t *);
79 static object_t *buildOSArray(object_t *);
80 static object_t *buildOSSet(object_t *);
81 static object_t *buildOSString(object_t *);
82 static object_t *buildKey(object_t *);
83 static object_t *buildOSData(object_t *);
84 static object_t *buildOSNumber(object_t *);
85 static object_t *buildOSBoolean(object_t *o);
86
87 static void rememberObject(int, OSObject *);
88 static object_t *retrieveObject(int);
89
90 // resultant object of parsed text
91 static OSObject *parsedObject;
92
93 #define YYSTYPE object_t *
94
95 extern "C" {
96 extern void *kern_os_malloc(size_t size);
97 extern void *kern_os_realloc(void * addr, size_t size);
98 extern void kern_os_free(void * addr);
99
100 //XXX shouldn't have to define these
101 extern long strtol(const char *, char **, int);
102 extern unsigned long strtoul(const char *, char **, int);
103
104 } /* extern "C" */
105
106 #define malloc(s) kern_os_malloc(s)
107 #define realloc(a, s) kern_os_realloc(a, s)
108 #define free(a) kern_os_free(a)
109
110 %}
111 %token ARRAY
112 %token BOOLEAN
113 %token DATA
114 %token DICTIONARY
115 %token IDREF
116 %token KEY
117 %token NUMBER
118 %token SET
119 %token STRING
120 %token SYNTAX_ERROR
121 %% /* Grammar rules and actions follow */
122
123 input: /* empty */ { parsedObject = (OSObject *)NULL; YYACCEPT; }
124 | object { parsedObject = $1->object;
125 $1->object = 0;
126 freeObject($1);
127 YYACCEPT;
128 }
129 | SYNTAX_ERROR {
130 yyerror("syntax error");
131 YYERROR;
132 }
133 ;
134
135 object: dict { $$ = buildOSDictionary($1); }
136 | array { $$ = buildOSArray($1); }
137 | set { $$ = buildOSSet($1); }
138 | string { $$ = buildOSString($1); }
139 | data { $$ = buildOSData($1); }
140 | number { $$ = buildOSNumber($1); }
141 | boolean { $$ = buildOSBoolean($1); }
142 | idref { $$ = retrieveObject($1->idref);
143 if ($$) {
144 $$->object->retain();
145 } else {
146 yyerror("forward reference detected");
147 YYERROR;
148 }
149 freeObject($1);
150 }
151 ;
152
153 //------------------------------------------------------------------------------
154
155 dict: '{' '}' { $$ = $1;
156 $$->elements = NULL;
157 }
158 | '{' pairs '}' { $$ = $1;
159 $$->elements = $2;
160 }
161 | DICTIONARY
162 ;
163
164 pairs: pair
165 | pairs pair { $$ = $2;
166 $$->next = $1;
167 }
168 ;
169
170 pair: key object { $$ = $1;
171 $$->next = NULL;
172 $$->object = $2->object;
173 $2->object = 0;
174 freeObject($2);
175 }
176 ;
177
178 key: KEY { $$ = buildKey($1); }
179 ;
180
181 //------------------------------------------------------------------------------
182
183 array: '(' ')' { $$ = $1;
184 $$->elements = NULL;
185 }
186 | '(' elements ')' { $$ = $1;
187 $$->elements = $2;
188 }
189 | ARRAY
190 ;
191
192 set: '[' ']' { $$ = $1;
193 $$->elements = NULL;
194 }
195 | '[' elements ']' { $$ = $1;
196 $$->elements = $2;
197 }
198 | SET
199 ;
200
201 elements: object { $$ = $1;
202 $$->next = NULL;
203 }
204 | elements object { $$ = $2;
205 $$->next = $1;
206 }
207 ;
208
209 //------------------------------------------------------------------------------
210
211 boolean: BOOLEAN
212 ;
213
214 data: DATA
215 ;
216
217 idref: IDREF
218 ;
219
220 number: NUMBER
221 ;
222
223 string: STRING
224 ;
225
226 %%
227
228 static int lineNumber = 0;
229 static const char *parseBuffer;
230 static int parseBufferIndex;
231
232 #define currentChar() (parseBuffer[parseBufferIndex])
233 #define nextChar() (parseBuffer[++parseBufferIndex])
234 #define prevChar() (parseBuffer[parseBufferIndex - 1])
235
236 #define isSpace(c) ((c) == ' ' || (c) == '\t')
237 #define isAlpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
238 #define isDigit(c) ((c) >= '0' && (c) <= '9')
239 #define isAlphaDigit(c) ((c) >= 'a' && (c) <= 'f')
240 #define isHexDigit(c) (isDigit(c) || isAlphaDigit(c))
241 #define isAlphaNumeric(c) (isAlpha(c) || isDigit(c) || ((c) == '-'))
242
243 static char yyerror_message[128];
244
245 int
246 yyerror(char *s) /* Called by yyparse on error */
247 {
248 sprintf(yyerror_message, "OSUnserializeXML: %s near line %d\n", s, lineNumber);
249 return 0;
250 }
251
252 #define TAG_MAX_LENGTH 32
253 #define TAG_MAX_ATTRIBUTES 32
254 #define TAG_BAD 0
255 #define TAG_START 1
256 #define TAG_END 2
257 #define TAG_EMPTY 3
258 #define TAG_COMMENT 4
259
260 static int
261 getTag(char tag[TAG_MAX_LENGTH],
262 int *attributeCount,
263 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH],
264 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH] )
265 {
266 int length = 0;;
267 int c = currentChar();
268 int tagType = TAG_START;
269
270 *attributeCount = 0;
271
272 if (c != '<') return TAG_BAD;
273 c = nextChar(); // skip '<'
274
275 if (c == '?' || c == '!') {
276 while ((c = nextChar()) != 0) {
277 if (c == '\n') lineNumber++;
278 if (c == '>') {
279 (void)nextChar();
280 return TAG_COMMENT;
281 }
282 }
283 }
284
285 if (c == '/') {
286 c = nextChar(); // skip '/'
287 tagType = TAG_END;
288 }
289 if (!isAlpha(c)) return TAG_BAD;
290
291 /* find end of tag while copying it */
292 while (isAlphaNumeric(c)) {
293 tag[length++] = c;
294 c = nextChar();
295 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
296 }
297
298 tag[length] = 0;
299
300 //printf("tag %s, type %d\n", tag, tagType);
301
302 // look for attributes of the form attribute = "value" ...
303 while ((c != '>') && (c != '/')) {
304 while (isSpace(c)) c = nextChar();
305
306 length = 0;
307 while (isAlphaNumeric(c)) {
308 attributes[*attributeCount][length++] = c;
309 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
310 c = nextChar();
311 }
312 attributes[*attributeCount][length] = 0;
313
314 while (isSpace(c)) c = nextChar();
315
316 if (c != '=') return TAG_BAD;
317 c = nextChar();
318
319 while (isSpace(c)) c = nextChar();
320
321 if (c != '"') return TAG_BAD;
322 c = nextChar();
323 length = 0;
324 while (c != '"') {
325 values[*attributeCount][length++] = c;
326 if (length >= (TAG_MAX_LENGTH - 1)) return TAG_BAD;
327 c = nextChar();
328 }
329 values[*attributeCount][length] = 0;
330
331 c = nextChar(); // skip closing quote
332
333 //printf(" attribute '%s' = '%s', nextchar = '%c'\n", attributes[*attributeCount], values[*attributeCount], c);
334
335 (*attributeCount)++;
336 if (*attributeCount >= TAG_MAX_ATTRIBUTES) return TAG_BAD;
337 }
338
339 if (c == '/') {
340 c = nextChar(); // skip '/'
341 tagType = TAG_EMPTY;
342 }
343 if (c != '>') return TAG_BAD;
344 c = nextChar(); // skip '>'
345
346 return tagType;
347 }
348
349 static char *
350 getString()
351 {
352 int c = currentChar();
353
354 int start, length, i, j;;
355 char * tempString;
356
357 start = parseBufferIndex;
358 /* find end of string */
359
360 while (c != 0) {
361 if (c == '\n') lineNumber++;
362 if (c == '<') {
363 break;
364 }
365 c = nextChar();
366 }
367
368 if (c != '<') return 0;
369
370 length = parseBufferIndex - start;
371
372 /* copy to null terminated buffer */
373 tempString = (char *)malloc(length + 1);
374 if (tempString == 0) {
375 printf("OSUnserializeXML: can't alloc temp memory\n");
376 return 0;
377 }
378
379 // copy out string in tempString
380 // "&amp;" -> '&', "&lt;" -> '<', "&gt;" -> '>'
381
382 i = j = 0;
383 while (i < length) {
384 c = parseBuffer[start + i++];
385 if (c != '&') {
386 tempString[j++] = c;
387 } else {
388 if ((i+3) > length) goto error;
389 c = parseBuffer[start + i++];
390 if (c == 'l') {
391 if (parseBuffer[start + i++] != 't') goto error;
392 if (parseBuffer[start + i++] != ';') goto error;
393 tempString[j++] = '<';
394 continue;
395 }
396 if (c == 'g') {
397 if (parseBuffer[start + i++] != 't') goto error;
398 if (parseBuffer[start + i++] != ';') goto error;
399 tempString[j++] = '>';
400 continue;
401 }
402 if ((i+3) > length) goto error;
403 if (c == 'a') {
404 if (parseBuffer[start + i++] != 'm') goto error;
405 if (parseBuffer[start + i++] != 'p') goto error;
406 if (parseBuffer[start + i++] != ';') goto error;
407 tempString[j++] = '&';
408 continue;
409 }
410 goto error;
411 }
412 }
413 tempString[j] = 0;
414
415 //printf("string %s\n", tempString);
416
417 return tempString;
418
419 error:
420 if (tempString) free(tempString);
421 return 0;
422 }
423
424 static long long
425 getNumber()
426 {
427 unsigned long long n = 0;
428 int base = 10;
429 int c = currentChar();
430
431 if (!isDigit (c)) return 0;
432
433 if (c == '0') {
434 c = nextChar();
435 if (c == 'x') {
436 base = 16;
437 c = nextChar();
438 }
439 }
440 if (base == 10) {
441 while(isDigit(c)) {
442 n = (n * base + c - '0');
443 c = nextChar();
444 }
445 } else {
446 while(isHexDigit(c)) {
447 if (isDigit(c)) {
448 n = (n * base + c - '0');
449 } else {
450 n = (n * base + 0xa + c - 'a');
451 }
452 c = nextChar();
453 }
454 }
455 //printf("number 0x%x\n", (unsigned long)n);
456 return n;
457 }
458
459 // taken from CFXMLParsing/CFPropertyList.c
460
461 static const signed char __CFPLDataDecodeTable[128] = {
462 /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
463 /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
464 /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
465 /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
466 /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
467 /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
468 /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
469 /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1,
470 /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6,
471 /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14,
472 /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
473 /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
474 /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
475 /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
476 /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
477 /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
478 };
479
480 #define OSDATA_ALLOC_SIZE 4096
481
482 static void *
483 getCFEncodedData(unsigned int *size)
484 {
485 int numeq = 0, acc = 0, cntr = 0;
486 int tmpbufpos = 0, tmpbuflen = 0;
487 unsigned char *tmpbuf = (unsigned char *)malloc(OSDATA_ALLOC_SIZE);
488
489 int c = currentChar();
490 *size = 0;
491
492 while (c != '<') {
493 c &= 0x7f;
494 if (c == 0) {
495 free(tmpbuf);
496 return 0;
497 }
498 if (c == '=') numeq++; else numeq = 0;
499 if (c == '\n') lineNumber++;
500 if (__CFPLDataDecodeTable[c] < 0) {
501 c = nextChar();
502 continue;
503 }
504 cntr++;
505 acc <<= 6;
506 acc += __CFPLDataDecodeTable[c];
507 if (0 == (cntr & 0x3)) {
508 if (tmpbuflen <= tmpbufpos + 2) {
509 tmpbuflen += OSDATA_ALLOC_SIZE;
510 tmpbuf = (unsigned char *)realloc(tmpbuf, tmpbuflen);
511 }
512 tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
513 if (numeq < 2)
514 tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
515 if (numeq < 1)
516 tmpbuf[tmpbufpos++] = acc & 0xff;
517 }
518 c = nextChar();
519 }
520 *size = tmpbufpos;
521 return tmpbuf;
522 }
523
524 static void *
525 getHexData(unsigned int *size)
526 {
527 int c;
528 unsigned char *d, *start, *lastStart;
529
530 start = lastStart = d = (unsigned char *)malloc(OSDATA_ALLOC_SIZE);
531 c = currentChar();
532
533 while (c != '<') {
534
535 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
536 if (c == '\n') {
537 lineNumber++;
538 c = nextChar();
539 continue;
540 }
541
542 // get high nibble
543 if (isDigit(c)) {
544 *d = (c - '0') << 4;
545 } else if (isAlphaDigit(c)) {
546 *d = (0xa + (c - 'a')) << 4;
547 } else {
548 goto error;
549 }
550
551 // get low nibble
552 c = nextChar();
553 if (isDigit(c)) {
554 *d |= c - '0';
555 } else if (isAlphaDigit(c)) {
556 *d |= 0xa + (c - 'a');
557 } else {
558 goto error;
559 }
560
561 d++;
562 if ((d - lastStart) >= OSDATA_ALLOC_SIZE) {
563 int oldsize = d - start;
564 start = (unsigned char *)realloc(start, oldsize + OSDATA_ALLOC_SIZE);
565 d = lastStart = start + oldsize;
566 }
567 c = nextChar();
568 }
569
570 *size = d - start;
571 return start;
572
573 error:
574
575 *size = 0;
576 free(start);
577 return 0;
578 }
579
580 static int
581 yylex()
582 {
583 int c;
584 int tagType;
585 char tag[TAG_MAX_LENGTH];
586 int attributeCount;
587 char attributes[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
588 char values[TAG_MAX_ATTRIBUTES][TAG_MAX_LENGTH];
589
590 if (parseBufferIndex == 0) lineNumber = 1;
591
592 top:
593 c = currentChar();
594
595 /* skip white space */
596 if (isSpace(c)) while ((c = nextChar()) != 0 && isSpace(c)) {};
597
598 /* keep track of line number, don't return \n's */
599 if (c == '\n') {
600 lineNumber++;
601 (void)nextChar();
602 goto top;
603 }
604
605 if (!c) return c;
606
607 tagType = getTag(tag, &attributeCount, attributes, values);
608 if (tagType == TAG_BAD) return SYNTAX_ERROR;
609 if (tagType == TAG_COMMENT) goto top;
610
611 // handle allocation and check for "ID" and "IDREF" tags up front
612 yylval = newObject();
613 yylval->idref = -1;
614 for (int i=0; i < attributeCount; i++) {
615 if (attributes[i][0] == 'I' && attributes[i][1] == 'D') {
616 // check for idref's, note: we ignore the tag, for
617 // this to work correctly, all idrefs must be unique
618 // across the whole serialization
619 if (attributes[i][2] == 'R' && attributes[i][3] == 'E' &&
620 attributes[i][4] == 'F' && !attributes[i][5]) {
621 if (tagType != TAG_EMPTY) return SYNTAX_ERROR;
622 yylval->idref = strtol(values[i], NULL, 0);
623 return IDREF;
624 }
625 // check for id's
626 if (!attributes[i][2]) {
627 yylval->idref = strtol(values[i], NULL, 0);
628 } else {
629 return SYNTAX_ERROR;
630 }
631 }
632 }
633
634 switch (*tag) {
635 case 'a':
636 if (!strcmp(tag, "array")) {
637 if (tagType == TAG_EMPTY) {
638 yylval->elements = NULL;
639 return ARRAY;
640 }
641 return (tagType == TAG_START) ? '(' : ')';
642 }
643 break;
644 case 'd':
645 if (!strcmp(tag, "dict")) {
646 if (tagType == TAG_EMPTY) {
647 yylval->elements = NULL;
648 return DICTIONARY;
649 }
650 return (tagType == TAG_START) ? '{' : '}';
651 }
652 if (!strcmp(tag, "data")) {
653 unsigned int size;
654 int readable = 0;
655 if (tagType == TAG_EMPTY) {
656 yylval->data = NULL;
657 yylval->size = 0;
658 return DATA;
659 }
660 for (int i=0; i < attributeCount; i++) {
661 if (!strcmp(attributes[i], "format") && !strcmp(values[i], "hex")) {
662 readable++;
663 break;
664 }
665 }
666 // CF encoded is the default form
667 if (readable) {
668 yylval->data = getHexData(&size);
669 } else {
670 yylval->data = getCFEncodedData(&size);
671 }
672 yylval->size = size;
673 if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "data")) {
674 return SYNTAX_ERROR;
675 }
676 return DATA;
677 }
678 break;
679 case 'f':
680 if (!strcmp(tag, "false")) {
681 if (tagType == TAG_EMPTY) {
682 yylval->number = 0;
683 return BOOLEAN;
684 }
685 }
686 break;
687 case 'i':
688 if (!strcmp(tag, "integer")) {
689 yylval->size = 64; // default
690 for (int i=0; i < attributeCount; i++) {
691 if (!strcmp(attributes[i], "size")) {
692 yylval->size = strtoul(values[i], NULL, 0);
693 }
694 }
695 if (tagType == TAG_EMPTY) {
696 yylval->number = 0;
697 return NUMBER;
698 }
699 yylval->number = getNumber();
700 if ((getTag(tag, &attributeCount, attributes, values) != TAG_END) || strcmp(tag, "integer")) {
701 return SYNTAX_ERROR;
702 }
703 return NUMBER;
704 }
705 break;
706 case 'k':
707 if (!strcmp(tag, "key")) {
708 if (tagType == TAG_EMPTY) return SYNTAX_ERROR;
709 yylval->string = getString();
710 if (!yylval->string) {
711 return SYNTAX_ERROR;
712 }
713 if ((getTag(tag, &attributeCount, attributes, values) != TAG_END)
714 || strcmp(tag, "key")) {
715 return SYNTAX_ERROR;
716 }
717 return KEY;
718 }
719 break;
720 case 'p':
721 if (!strcmp(tag, "plist")) {
722 freeObject(yylval);
723 goto top;
724 }
725 break;
726 case 's':
727 if (!strcmp(tag, "string")) {
728 if (tagType == TAG_EMPTY) {
729 yylval->string = (char *)malloc(1);
730 *yylval->string = 0;
731 return STRING;
732 }
733 yylval->string = getString();
734 if (!yylval->string) {
735 return SYNTAX_ERROR;
736 }
737 if ((getTag(tag, &attributeCount, attributes, values) != TAG_END)
738 || strcmp(tag, "string")) {
739 return SYNTAX_ERROR;
740 }
741 return STRING;
742 }
743 if (!strcmp(tag, "set")) {
744 if (tagType == TAG_EMPTY) {
745 yylval->elements = NULL;
746 return SET;;
747 }
748 if (tagType == TAG_START) {
749 return '[';
750 } else {
751 return ']';
752 }
753 }
754 break;
755 case 't':
756 if (!strcmp(tag, "true")) {
757 if (tagType == TAG_EMPTY) {
758 yylval->number = 1;
759 return BOOLEAN;
760 }
761 }
762 break;
763
764 default:
765 // XXX should we ignore invalid tags?
766 return SYNTAX_ERROR;
767 break;
768 }
769
770 return 0;
771 }
772
773 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
774 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
775 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
776
777 // "java" like allocation, if this code hits a syntax error in the
778 // the middle of the parsed string we just bail with pointers hanging
779 // all over place, so this code helps keeps all together
780
781 static object_t *objects = 0;
782 static object_t *freeObjects = 0;
783
784 object_t *
785 newObject()
786 {
787 object_t *o;
788
789 if (freeObjects) {
790 o = freeObjects;
791 freeObjects = freeObjects->next;
792 } else {
793 o = (object_t *)malloc(sizeof(object_t));
794 bzero(o, sizeof(object_t));
795 o->free = objects;
796 objects = o;
797 }
798
799 return o;
800 }
801
802 void
803 freeObject(object_t *o)
804 {
805 o->next = freeObjects;
806 freeObjects = o;
807 }
808
809 void
810 cleanupObjects()
811 {
812 object_t *t, *o = objects;
813
814 while (o) {
815 if (o->object) {
816 printf("OSUnserializeXML: releasing object o=%x object=%x\n", (int)o, (int)o->object);
817 o->object->release();
818 }
819 if (o->data) {
820 printf("OSUnserializeXML: freeing object o=%x data=%x\n", (int)o, (int)o->data);
821 free(o->data);
822 }
823 if (o->key) {
824 printf("OSUnserializeXML: releasing object o=%x key=%x\n", (int)o, (int)o->key);
825 o->key->release();
826 }
827 if (o->string) {
828 printf("OSUnserializeXML: freeing object o=%x string=%x\n", (int)o, (int)o->string);
829 free(o->string);
830 }
831
832 t = o;
833 o = o->free;
834 free(t);
835 }
836 }
837
838 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
839 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
840 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
841
842 static OSDictionary *tags;
843
844 static void
845 rememberObject(int tag, OSObject *o)
846 {
847 char key[16];
848 sprintf(key, "%u", tag);
849
850 //printf("remember key %s\n", key);
851
852 tags->setObject(key, o);
853 }
854
855 static object_t *
856 retrieveObject(int tag)
857 {
858 char key[16];
859 sprintf(key, "%u", tag);
860
861 //printf("retrieve key '%s'\n", key);
862
863 OSObject *ref = tags->getObject(key);
864 if (!ref) return 0;
865
866 object_t *o = newObject();
867 o->object = ref;
868 return o;
869 }
870
871 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
872 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
873 // !@$&)(^Q$&*^!$(*!@$_(^%_(*Q#$(_*&!$_(*&!$_(*&!#$(*!@&^!@#%!_!#
874
875 object_t *
876 buildOSDictionary(object_t * header)
877 {
878 object_t *o, *t;
879 int count = 0;
880
881 // get count and reverse order
882 o = header->elements;
883 header->elements = 0;
884 while (o) {
885 count++;
886 t = o;
887 o = o->next;
888
889 t->next = header->elements;
890 header->elements = t;
891 }
892
893 OSDictionary *d = OSDictionary::withCapacity(count);
894
895 if (header->idref >= 0) rememberObject(header->idref, d);
896
897 o = header->elements;
898 while (o) {
899 d->setObject(o->key, o->object);
900 o->object->release();
901 o->object = 0;
902 o->key->release();
903 o->key = 0;
904 t = o;
905 o = o->next;
906 freeObject(t);
907 }
908 o = header;
909 o->object = d;
910 return o;
911 };
912
913 object_t *
914 buildOSArray(object_t * header)
915 {
916 object_t *o, *t;
917 int count = 0;
918
919 // get count and reverse order
920 o = header->elements;
921 header->elements = 0;
922 while (o) {
923 count++;
924 t = o;
925 o = o->next;
926
927 t->next = header->elements;
928 header->elements = t;
929 }
930
931 OSArray *a = OSArray::withCapacity(count);
932
933 if (header->idref >= 0) rememberObject(header->idref, a);
934
935 o = header->elements;
936 while (o) {
937 a->setObject(o->object);
938 o->object->release();
939 o->object = 0;
940 t = o;
941 o = o->next;
942 freeObject(t);
943 }
944 o = header;
945 o->object = a;
946 return o;
947 };
948
949 object_t *
950 buildOSSet(object_t *o)
951 {
952 o = buildOSArray(o);
953 OSArray *a = (OSArray *)o->object;
954
955 OSSet *s = OSSet::withArray(a, a->getCapacity());
956
957 //write over reference created in array
958 if (o->idref >= 0) rememberObject(o->idref, s);
959
960 a->release();
961 o->object = s;
962 return o;
963 };
964
965 object_t *
966 buildOSString(object_t *o)
967 {
968 OSString *s = OSString::withCString(o->string);
969
970 if (o->idref >= 0) rememberObject(o->idref, s);
971
972 free(o->string);
973 o->string = 0;
974 o->object = s;
975
976 return o;
977 };
978
979 object_t *
980 buildKey(object_t *o)
981 {
982 const OSSymbol *s = OSSymbol::withCString(o->string);
983
984 free(o->string);
985 o->string = 0;
986 o->key = s;
987
988 return o;
989 };
990
991 object_t *
992 buildOSData(object_t *o)
993 {
994 OSData *d;
995
996 if (o->size) {
997 d = OSData::withBytes(o->data, o->size);
998 free(o->data);
999 } else {
1000 d = OSData::withCapacity(0);
1001 }
1002 if (o->idref >= 0) rememberObject(o->idref, d);
1003
1004 o->data = 0;
1005 o->object = d;
1006 return o;
1007 };
1008
1009 object_t *
1010 buildOSNumber(object_t *o)
1011 {
1012 OSNumber *n = OSNumber::withNumber(o->number, o->size);
1013
1014 if (o->idref >= 0) rememberObject(o->idref, n);
1015
1016 o->object = n;
1017 return o;
1018 };
1019
1020 object_t *
1021 buildOSBoolean(object_t *o)
1022 {
1023 OSBoolean *b = OSBoolean::withBoolean(o->number != 0);
1024 o->object = b;
1025 return o;
1026 };
1027
1028 __BEGIN_DECLS
1029 #include <kern/lock.h>
1030 __END_DECLS
1031
1032 static mutex_t *lock = 0;
1033
1034 OSObject*
1035 OSUnserializeXML(const char *buffer, OSString **errorString)
1036 {
1037 OSObject *object;
1038
1039 if (!lock) {
1040 lock = mutex_alloc(ETAP_IO_AHA);
1041 _mutex_lock(lock);
1042 } else {
1043 _mutex_lock(lock);
1044
1045 }
1046
1047 objects = 0;
1048 freeObjects = 0;
1049 yyerror_message[0] = 0; //just in case
1050 parseBuffer = buffer;
1051 parseBufferIndex = 0;
1052 tags = OSDictionary::withCapacity(128);
1053 if (yyparse() == 0) {
1054 object = parsedObject;
1055 if (errorString) *errorString = 0;
1056 } else {
1057 object = 0;
1058 if (errorString)
1059 *errorString = OSString::withCString(yyerror_message);
1060 }
1061
1062 cleanupObjects();
1063 tags->release();
1064 mutex_unlock(lock);
1065
1066 return object;
1067 }
1068
1069
1070 //
1071 //
1072 //
1073 //
1074 //
1075 // DO NOT EDIT OSUnserializeXML.cpp!
1076 //
1077 // this means you!
1078 //
1079 //
1080 //
1081 //
1082 //