Chameleon

Chameleon Svn Source Tree

Root/branches/danielkza/i386/libsaio/xml.c

1/*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights
7 * Reserved.
8 * The contents of this file constitute Original Code as defined in and
9 * are subject to the Apple Public Source License Version 2.0 (the
10 * "License"). You may not use this file except in compliance with the
11 * License. Please obtain a copy of the License at
12 * http://www.apple.com/publicsource and read it before using this file.
13 *
14 * This Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include "bootstruct.h"
26#include "libsaio.h"
27#include "sl.h"
28#include "xml.h"
29
30struct Module {
31 struct Module *nextModule;
32 long willLoad;
33 TagPtr dict;
34 char *plistAddr;
35 long plistLength;
36 char *driverPath;
37};
38typedef struct Module Module, *ModulePtr;
39
40struct DriverInfo {
41 char *plistAddr;
42 long plistLength;
43 void *moduleAddr;
44 long moduleLength;
45};
46typedef struct DriverInfo DriverInfo, *DriverInfoPtr;
47
48#define kDriverPackageSignature1 'MKXT'
49#define kDriverPackageSignature2 'MOSX'
50
51struct DriversPackage {
52 unsigned long signature1;
53 unsigned long signature2;
54 unsigned long length;
55 unsigned long alder32;
56 unsigned long version;
57 unsigned long numDrivers;
58 unsigned long reserved1;
59 unsigned long reserved2;
60};
61typedef struct DriversPackage DriversPackage;
62
63enum {
64 kCFBundleType2,
65 kCFBundleType3
66};
67
68
69#define USEMALLOC 1
70#define DOFREE 1
71
72static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty);
73static long ParseTagKey(char *buffer, TagPtr *tag);
74static long ParseTagString(char *buffer, TagPtr *tag);
75static long ParseTagInteger(char *buffer, TagPtr *tag);
76static long ParseTagData(char *buffer, TagPtr *tag);
77static long ParseTagDate(char *buffer, TagPtr *tag);
78static long ParseTagBoolean(char *buffer, TagPtr *tag, long type);
79static long GetNextTag(char *buffer, char **tag, long *start);
80static long FixDataMatchingTag(char *buffer, char *tag);
81static TagPtr NewTag(void);
82static char *NewSymbol(char *string);
83#if DOFREE
84static void FreeSymbol(char *string);
85#endif
86
87
88//==========================================================================
89// XMLGetProperty
90
91TagPtr
92XMLGetProperty( TagPtr dict, const char * key )
93{
94 TagPtr tagList, tag;
95
96 if (dict->type != kTagTypeDict) return 0;
97
98 tag = 0;
99 tagList = dict->tag;
100 while (tagList)
101 {
102 tag = tagList;
103 tagList = tag->tagNext;
104
105 if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue;
106
107 if (!strcmp(tag->string, key)) return tag->tag;
108 }
109
110 return 0;
111}
112
113/* Function for basic XML entity replacement. It *does not* handle unicode escapes */
114
115char*
116XMLDecode(const char* src)
117{
118 typedef const struct XMLEntity {
119 char* name;
120 size_t nameLen;
121 char value;
122 } XMLEntity;
123
124 /* This is ugly, but better than specifying the lengths by hand */
125 #define _e(str,c) {str,sizeof(str)-1,c}
126 const XMLEntity ents[] = {
127 _e("quot;",'"'), _e("apos;",'\''),
128 _e("lt;", '<'), _e("gt;", '>'),
129 _e("amp;", '&')
130 };
131
132 size_t len;
133 const char *s;
134 char *out, *o;
135
136 if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) )
137 return 0;
138
139 o = out;
140 s = src;
141 while (s <= src+len) /* Make sure the terminator is also copied */
142 {
143 if ( *s == '&' )
144 {
145 bool entFound = false;
146 XMLEntity* ent;
147 int i = 0;
148
149 s++;
150 for ( ent=&ents[0]; i < sizeof(ents); ent = &ents[i++] )
151 {
152 if ( strncmp(s, ent->name, ent->nameLen) == 0 )
153 {
154 entFound = true;
155 break;
156 }
157 }
158 if ( entFound )
159 {
160 *o++ = ent->value;
161 s += ent->nameLen;
162 continue;
163 }
164 }
165
166 *o++ = *s++;
167 }
168
169 return out;
170}
171
172#if UNUSED
173//==========================================================================
174// XMLParseFile
175// Expects to see one dictionary in the XML file.
176// Puts the first dictionary it finds in the
177// tag pointer and returns 0, or returns -1 if not found.
178//
179long
180XMLParseFile( char * buffer, TagPtr * dict )
181{
182 long length, pos;
183 TagPtr tag;
184 pos = 0;
185
186 while (1)
187 {
188 length = XMLParseNextTag(buffer + pos, &tag);
189 if (length == -1) break;
190
191 pos += length;
192
193 if (tag == 0) continue;
194 if (tag->type == kTagTypeDict) break;
195
196 XMLFreeTag(tag);
197 }
198 if (length < 0) {
199 return -1;
200 }
201 *dict = tag;
202 return 0;
203}
204#endif /* UNUSED */
205
206//==========================================================================
207// ParseNextTag
208
209long
210XMLParseNextTag( char * buffer, TagPtr * tag )
211{
212long length, pos;
213char * tagName;
214
215 length = GetNextTag(buffer, &tagName, 0);
216 if (length == -1) return -1;
217
218pos = length;
219 if (!strncmp(tagName, kXMLTagPList, 6))
220 {
221 length = 0;
222 }
223 else if (!strcmp(tagName, kXMLTagDict))
224 {
225 length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
226 }
227 else if (!strcmp(tagName, kXMLTagDict "/"))
228 {
229 length = ParseTagList(buffer + pos, tag, kTagTypeDict, 1);
230 }
231 else if (!strcmp(tagName, kXMLTagKey))
232 {
233 length = ParseTagKey(buffer + pos, tag);
234 }
235 else if (!strcmp(tagName, kXMLTagString))
236 {
237 length = ParseTagString(buffer + pos, tag);
238 }
239 else if (!strcmp(tagName, kXMLTagInteger))
240 {
241 length = ParseTagInteger(buffer + pos, tag);
242 }
243 else if (!strcmp(tagName, kXMLTagData))
244 {
245 length = ParseTagData(buffer + pos, tag);
246 }
247 else if (!strcmp(tagName, kXMLTagDate))
248 {
249 length = ParseTagDate(buffer + pos, tag);
250 }
251 else if (!strcmp(tagName, kXMLTagFalse))
252 {
253 length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
254 }
255 else if (!strcmp(tagName, kXMLTagTrue))
256 {
257 length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
258 }
259 else if (!strcmp(tagName, kXMLTagArray))
260 {
261 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
262 }
263 else if (!strcmp(tagName, kXMLTagArray "/"))
264 {
265 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);
266 }
267 else
268 {
269 *tag = 0;
270 length = 0;
271 }
272
273 if (length == -1) return -1;
274
275 return pos + length;
276}
277
278//==========================================================================
279// ParseTagList
280
281static long
282ParseTagList( char * buffer, TagPtr * tag, long type, long empty )
283{
284long length, pos;
285TagPtr tagList, tmpTag;
286
287 tagList = 0;
288 pos = 0;
289
290 if (!empty)
291 {
292 while (1)
293 {
294 length = XMLParseNextTag(buffer + pos, &tmpTag);
295 if (length == -1) break;
296
297 pos += length;
298
299 if (tmpTag == 0) break;
300 tmpTag->tagNext = tagList;
301 tagList = tmpTag;
302 }
303
304 if (length == -1)
305 {
306 XMLFreeTag(tagList);
307 return -1;
308 }
309 }
310
311 tmpTag = NewTag();
312 if (tmpTag == 0)
313 {
314 XMLFreeTag(tagList);
315 return -1;
316 }
317
318 tmpTag->type = type;
319 tmpTag->string = 0;
320 tmpTag->tag = tagList;
321 tmpTag->tagNext = 0;
322
323 *tag = tmpTag;
324
325 return pos;
326}
327
328//==========================================================================
329// ParseTagKey
330
331static long
332ParseTagKey( char * buffer, TagPtr * tag )
333{
334 long length, length2;
335 char *string;
336 TagPtr tmpTag, subTag;
337
338 length = FixDataMatchingTag(buffer, kXMLTagKey);
339 if (length == -1) return -1;
340
341 length2 = XMLParseNextTag(buffer + length, &subTag);
342 if (length2 == -1) return -1;
343
344 tmpTag = NewTag();
345 if (tmpTag == 0)
346 {
347 XMLFreeTag(subTag);
348 return -1;
349 }
350
351 string = NewSymbol(buffer);
352 if (string == 0)
353 {
354 XMLFreeTag(subTag);
355 XMLFreeTag(tmpTag);
356 return -1;
357 }
358
359 tmpTag->type = kTagTypeKey;
360 tmpTag->string = string;
361 tmpTag->tag = subTag;
362 tmpTag->tagNext = 0;
363
364 *tag = tmpTag;
365
366 return length + length2;
367}
368
369//==========================================================================
370// ParseTagString
371
372static long
373ParseTagString( char * buffer, TagPtr * tag )
374{
375 long length;
376 char * string;
377 TagPtr tmpTag;
378
379 length = FixDataMatchingTag(buffer, kXMLTagString);
380 if (length == -1) return -1;
381
382 tmpTag = NewTag();
383 if (tmpTag == 0) return -1;
384
385 string = NewSymbol(buffer);
386 if (string == 0)
387 {
388 XMLFreeTag(tmpTag);
389 return -1;
390 }
391
392 tmpTag->type = kTagTypeString;
393 tmpTag->string = string;
394 tmpTag->tag = 0;
395 tmpTag->tagNext = 0;
396
397 *tag = tmpTag;
398 return length;
399}
400
401//==========================================================================
402// ParseTagInteger
403
404static long
405ParseTagInteger( char * buffer, TagPtr * tag )
406{
407 long length, integer;
408 TagPtr tmpTag;
409
410 length = FixDataMatchingTag(buffer, kXMLTagInteger);
411 if (length == -1) return -1;
412
413 tmpTag = NewTag();
414 if (tmpTag == 0) return -1;
415
416 integer = 0;
417
418 tmpTag->type = kTagTypeInteger;
419 tmpTag->string = (char *)integer;
420 tmpTag->tag = 0;
421 tmpTag->tagNext = 0;
422
423 *tag = tmpTag;
424
425 return length;
426}
427
428//==========================================================================
429// ParseTagData
430
431static long
432ParseTagData( char * buffer, TagPtr * tag )
433{
434 long length;
435 TagPtr tmpTag;
436
437 length = FixDataMatchingTag(buffer, kXMLTagData);
438 if (length == -1) return -1;
439
440 tmpTag = NewTag();
441 if (tmpTag == 0) return -1;
442
443 tmpTag->type = kTagTypeData;
444 tmpTag->string = 0;
445 tmpTag->tag = 0;
446 tmpTag->tagNext = 0;
447
448 *tag = tmpTag;
449
450 return length;
451}
452
453//==========================================================================
454// ParseTagDate
455
456static long
457ParseTagDate( char * buffer, TagPtr * tag )
458{
459 long length;
460 TagPtr tmpTag;
461
462 length = FixDataMatchingTag(buffer, kXMLTagDate);
463 if (length == -1) return -1;
464
465 tmpTag = NewTag();
466 if (tmpTag == 0) return -1;
467
468 tmpTag->type = kTagTypeDate;
469 tmpTag->string = 0;
470 tmpTag->tag = 0;
471 tmpTag->tagNext = 0;
472
473 *tag = tmpTag;
474
475 return length;
476}
477
478//==========================================================================
479// ParseTagBoolean
480
481static long
482ParseTagBoolean( char * buffer, TagPtr * tag, long type )
483{
484 TagPtr tmpTag;
485
486 tmpTag = NewTag();
487 if (tmpTag == 0) return -1;
488
489 tmpTag->type = type;
490 tmpTag->string = 0;
491 tmpTag->tag = 0;
492 tmpTag->tagNext = 0;
493
494 *tag = tmpTag;
495
496 return 0;
497}
498
499//==========================================================================
500// GetNextTag
501
502static long
503GetNextTag( char * buffer, char ** tag, long * start )
504{
505 long cnt, cnt2;
506
507 if (tag == 0) return -1;
508
509 // Find the start of the tag.
510 cnt = 0;
511 while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;
512 if (buffer[cnt] == '\0') return -1;
513
514 // Find the end of the tag.
515 cnt2 = cnt + 1;
516 while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;
517 if (buffer[cnt2] == '\0') return -1;
518
519 // Fix the tag data.
520 *tag = buffer + cnt + 1;
521 buffer[cnt2] = '\0';
522 if (start) *start = cnt;
523
524 return cnt2 + 1;
525}
526
527//==========================================================================
528// FixDataMatchingTag
529// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
530// Returns the length of the data found, counting the end tag,
531// or -1 if the end tag was not found.
532
533static long
534FixDataMatchingTag( char * buffer, char * tag )
535{
536 long length, start, stop;
537 char * endTag;
538
539 start = 0;
540 while (1)
541 {
542 length = GetNextTag(buffer + start, &endTag, &stop);
543 if (length == -1) return -1;
544
545 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
546 start += length;
547 }
548
549 buffer[start + stop] = '\0';
550
551 return start + length;
552}
553
554//==========================================================================
555// NewTag
556
557#define kTagsPerBlock (0x1000)
558
559static TagPtr gTagsFree;
560
561static TagPtr
562NewTag( void )
563{
564long cnt;
565TagPtr tag;
566
567 if (gTagsFree == 0)
568 {
569#if USEMALLOC
570 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
571#else
572 tag = (TagPtr)AllocateBootXMemory(kTagsPerBlock * sizeof(Tag));
573#endif
574 if (tag == 0) return 0;
575
576 // Initalize the new tags.
577 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
578 {
579 tag[cnt].type = kTagTypeNone;
580 tag[cnt].string = 0;
581 tag[cnt].tag = 0;
582 tag[cnt].tagNext = tag + cnt + 1;
583 }
584 tag[kTagsPerBlock - 1].tagNext = 0;
585
586 gTagsFree = tag;
587 }
588
589 tag = gTagsFree;
590 gTagsFree = tag->tagNext;
591
592 return tag;
593}
594
595//==========================================================================
596// XMLFreeTag
597
598void
599XMLFreeTag( TagPtr tag )
600{
601#if DOFREE
602 if (tag == 0) return;
603
604 if (tag->string) FreeSymbol(tag->string);
605
606 XMLFreeTag(tag->tag);
607 XMLFreeTag(tag->tagNext);
608
609 // Clear and free the tag.
610 tag->type = kTagTypeNone;
611 tag->string = 0;
612 tag->tag = 0;
613 tag->tagNext = gTagsFree;
614 gTagsFree = tag;
615#else
616 return;
617#endif
618}
619
620//==========================================================================
621// Symbol object.
622
623struct Symbol
624{
625 long refCount;
626 struct Symbol *next;
627 char string[];
628};
629typedef struct Symbol Symbol, *SymbolPtr;
630
631static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
632
633static SymbolPtr gSymbolsHead;
634
635//==========================================================================
636// NewSymbol
637
638static char *
639NewSymbol( char * string )
640{
641static SymbolPtr lastGuy = 0;
642SymbolPtr symbol;
643
644 // Look for string in the list of symbols.
645 symbol = FindSymbol(string, 0);
646
647 // Add the new symbol.
648 if (symbol == 0)
649 {
650#if USEMALLOC
651 symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
652#else
653 symbol = (SymbolPtr)AllocateBootXMemory(sizeof(Symbol) + 1 + strlen(string));
654#endif
655 if (symbol == 0) //return 0;
656 stop("NULL symbol!");
657
658 // Set the symbol's data.
659 symbol->refCount = 0;
660 strcpy(symbol->string, string);
661
662 // Add the symbol to the list.
663 symbol->next = gSymbolsHead;
664 gSymbolsHead = symbol;
665 }
666
667 // Update the refCount and return the string.
668 symbol->refCount++;
669
670 if (lastGuy && lastGuy->next != 0) stop("last guy not last!");
671 return symbol->string;
672}
673
674//==========================================================================
675// FreeSymbol
676
677#if DOFREE
678static void
679FreeSymbol( char * string )
680{
681 SymbolPtr symbol, prev;
682prev = 0;
683
684 // Look for string in the list of symbols.
685 symbol = FindSymbol(string, &prev);
686 if (symbol == 0) return;
687
688 // Update the refCount.
689 symbol->refCount--;
690
691 if (symbol->refCount != 0) return;
692
693 // Remove the symbol from the list.
694 if (prev != 0) prev->next = symbol->next;
695 else gSymbolsHead = symbol->next;
696
697 // Free the symbol's memory.
698 free(symbol);
699}
700#endif
701
702//==========================================================================
703// FindSymbol
704
705static SymbolPtr
706FindSymbol( char * string, SymbolPtr * prevSymbol )
707{
708 SymbolPtr symbol, prev;
709
710 symbol = gSymbolsHead;
711 prev = 0;
712
713 while (symbol != 0) {
714 if (!strcmp(symbol->string, string)) break;
715
716 prev = symbol;
717 symbol = symbol->next;
718 }
719
720 if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev;
721
722 return symbol;
723}
724

Archive Download this file

Revision: 289