Root/
Source at commit 2381 created 10 years 21 days ago. By ifabio, Apply patch: (Credits to Thomas Jansen aka tja) - Reading options from all devices during boot. The options for the boot menu are only read from the devices rd(0,0) or bt(0,0). Consequently, boot menu options (e.g. "Quiet Boot", "Timeout", etc.) in plists on other devices (like most users have) are ignored. This patch extends the list of paths to search for the options plist on all devices that can be found. | |
---|---|
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 | ␊ |
30 | string_ref *ref_strings = NULL;␊ |
31 | ␊ |
32 | /// TODO: remove below␊ |
33 | static char* buffer_start = NULL;␊ |
34 | // TODO: redo the next two functions␊ |
35 | void SaveRefString(char* string, int id)␊ |
36 | {␊ |
37 | ␉//printf("Adding Ref String %d (%s)\n", id, string);␊ |
38 | ␉string_ref* tmp = ref_strings;␊ |
39 | ␉while(tmp)␊ |
40 | ␉{␊ |
41 | ␉␉if(tmp->id == id)␊ |
42 | ␉␉{␊ |
43 | ␉␉␉tmp->string = malloc(strlen(string)+1);␊ |
44 | ␉␉␉sprintf(tmp->string, "%s", string);␊ |
45 | ␉␉␉return;␊ |
46 | ␉␉}␊ |
47 | ␉␉tmp = tmp->next;␊ |
48 | ␉}␊ |
49 | ␉␊ |
50 | ␉string_ref* new_ref = malloc(sizeof(string_ref));␊ |
51 | ␉new_ref->string = malloc(strlen(string)+1);␊ |
52 | ␉sprintf(new_ref->string, "%s", string);␊ |
53 | ␉new_ref->id = id;␊ |
54 | ␉new_ref->next = ref_strings;␊ |
55 | ␉ref_strings = new_ref;␊ |
56 | }␊ |
57 | ␊ |
58 | char* GetRefString(int id)␊ |
59 | {␊ |
60 | ␉string_ref* tmp = ref_strings;␊ |
61 | ␉while(tmp)␊ |
62 | ␉{␊ |
63 | ␉␉if(tmp->id == id) return tmp->string;␊ |
64 | ␉␉tmp = tmp->next;␊ |
65 | ␉}␊ |
66 | ␉//verbose("Unable to locate Ref String %d\n", id);␊ |
67 | ␉return "";␊ |
68 | }␊ |
69 | ␊ |
70 | struct Module {␊ |
71 | struct Module *nextModule;␊ |
72 | long willLoad;␊ |
73 | TagPtr dict;␊ |
74 | char *plistAddr;␊ |
75 | long plistLength;␊ |
76 | char *driverPath;␊ |
77 | };␊ |
78 | typedef struct Module Module, *ModulePtr;␊ |
79 | ␊ |
80 | struct DriverInfo {␊ |
81 | char *plistAddr;␊ |
82 | long plistLength;␊ |
83 | void *moduleAddr;␊ |
84 | long moduleLength;␊ |
85 | };␊ |
86 | typedef struct DriverInfo DriverInfo, *DriverInfoPtr;␊ |
87 | ␊ |
88 | #define kDriverPackageSignature1 'MKXT'␊ |
89 | #define kDriverPackageSignature2 'MOSX'␊ |
90 | ␊ |
91 | struct DriversPackage {␊ |
92 | unsigned long signature1;␊ |
93 | unsigned long signature2;␊ |
94 | unsigned long length;␊ |
95 | unsigned long adler32;␊ |
96 | unsigned long version;␊ |
97 | unsigned long numDrivers;␊ |
98 | unsigned long reserved1;␊ |
99 | unsigned long reserved2;␊ |
100 | };␊ |
101 | typedef struct DriversPackage DriversPackage;␊ |
102 | ␊ |
103 | enum {␊ |
104 | kCFBundleType2,␊ |
105 | kCFBundleType3␊ |
106 | };␊ |
107 | ␊ |
108 | ␊ |
109 | #define DOFREE 1␊ |
110 | ␊ |
111 | static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty);␊ |
112 | static long ParseTagKey(char *buffer, TagPtr *tag);␊ |
113 | static long ParseTagString(char *buffer, TagPtr *tag);␊ |
114 | static long ParseTagInteger(char *buffer, TagPtr *tag);␊ |
115 | static long ParseTagData(char *buffer, TagPtr *tag);␊ |
116 | static long ParseTagDate(char *buffer, TagPtr *tag);␊ |
117 | static long GetNextTag(char *buffer, char **tag, long *start);␊ |
118 | static long FixDataMatchingTag(char *buffer, char *tag);␊ |
119 | static TagPtr NewTag(void);␊ |
120 | static char *NewSymbol(char *string);␊ |
121 | #if DOFREE␊ |
122 | static void FreeSymbol(char *string);␊ |
123 | #endif␊ |
124 | ␊ |
125 | ␊ |
126 | //==========================================================================␊ |
127 | // XMLGetProperty␊ |
128 | ␊ |
129 | TagPtr␊ |
130 | XMLGetProperty( TagPtr dict, const char * key )␊ |
131 | {␊ |
132 | TagPtr tagList, tag;␊ |
133 | ␊ |
134 | if (dict->type != kTagTypeDict) return 0;␊ |
135 | ␊ |
136 | tag = 0;␊ |
137 | tagList = dict->tag;␊ |
138 | while (tagList)␊ |
139 | {␊ |
140 | tag = tagList;␊ |
141 | tagList = tag->tagNext;␊ |
142 | ␊ |
143 | if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue;␊ |
144 | ␊ |
145 | if (!strcmp(tag->string, key)) return tag->tag;␊ |
146 | }␊ |
147 | ␊ |
148 | return 0;␊ |
149 | }␊ |
150 | ␊ |
151 | //==========================================================================␊ |
152 | // XMLGetProperty␊ |
153 | ␊ |
154 | TagPtr␊ |
155 | XMLGetKey( TagPtr dict, int id )␊ |
156 | {␊ |
157 | TagPtr tagList, tag;␊ |
158 | ␊ |
159 | if (dict->type != kTagTypeDict) return 0;␊ |
160 | ␊ |
161 | tag = 0;␊ |
162 | int element = 0;␊ |
163 | tagList = dict->tag;␊ |
164 | while (tagList && element != id)␊ |
165 | {␊ |
166 | tag = tagList;␊ |
167 | tagList = tag->tagNext;␊ |
168 | ␊ |
169 | if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue;␊ |
170 | element++;␊ |
171 | if(id == element) return tag;␊ |
172 | }␊ |
173 | return 0;␊ |
174 | }␊ |
175 | ␊ |
176 | TagPtr XMLGetValueForKey(TagPtr key)␊ |
177 | {␊ |
178 | if (!key ||␊ |
179 | key->type != kTagTypeKey) return 0;␊ |
180 | ␊ |
181 | return key->tag;␊ |
182 | }␊ |
183 | ␊ |
184 | ␊ |
185 | // XMLGetTag(int index)␊ |
186 | ␊ |
187 | // XMLTagCount( TagPtr dict )␊ |
188 | int XMLTagCount( TagPtr dict )␊ |
189 | {␊ |
190 | ␉int count = 0;␊ |
191 | ␉TagPtr tagList, tag;␊ |
192 | ␊ |
193 | if (dict->type != kTagTypeDict && dict->type != kTagTypeArray) return 0;␊ |
194 | ␉tag = 0;␊ |
195 | tagList = dict->tag;␊ |
196 | while (tagList)␊ |
197 | {␊ |
198 | ␉␉tag = tagList;␊ |
199 | tagList = tag->tagNext;␊ |
200 | ␉␉␊ |
201 | ␉␉if (((tag->type != kTagTypeKey) && ((tag->string == 0) || (tag->string[0] == 0)))␊ |
202 | ␉␉␉&& (dict->type != kTagTypeArray)␉// If we are an array, any element is valid␊ |
203 | ␉␉␉) continue;␊ |
204 | ␉␉␊ |
205 | ␉␉//if(tag->type == kTagTypeKey) printf("Located key %s\n", tag->string);␊ |
206 | ␊ |
207 | ␉␉count++;␊ |
208 | }␊ |
209 | ␉␊ |
210 | ␉return count;␊ |
211 | }␊ |
212 | ␊ |
213 | TagPtr XMLGetElement( TagPtr dict, int id )␊ |
214 | {␊ |
215 | ␉if(dict->type != kTagTypeArray) return 0;␊ |
216 | ␉␊ |
217 | ␉int element = 0;␊ |
218 | ␉TagPtr tmp = dict->tag;␊ |
219 | ␊ |
220 | ␉while(element < id)␊ |
221 | ␉{␊ |
222 | ␉␉element++;␊ |
223 | ␉␉tmp = tmp->tagNext;␊ |
224 | ␉}␊ |
225 | ␉␊ |
226 | ␉return tmp;␊ |
227 | }␊ |
228 | /* Function for basic XML character entities parsing */␊ |
229 | ␊ |
230 | char*␊ |
231 | XMLDecode(const char* src)␊ |
232 | {␊ |
233 | typedef const struct XMLEntity {␊ |
234 | const char* name;␊ |
235 | size_t nameLen;␊ |
236 | char value;␊ |
237 | } XMLEntity;␊ |
238 | ␊ |
239 | /* This is ugly, but better than specifying the lengths by hand */␊ |
240 | #define _e(str,c) {str,sizeof(str)-1,c}␊ |
241 | const XMLEntity ents[] = {␊ |
242 | _e("quot;",'"'), _e("apos;",'\''),␊ |
243 | _e("lt;", '<'), _e("gt;", '>'),␊ |
244 | _e("amp;", '&')␊ |
245 | };␊ |
246 | ␊ |
247 | size_t len;␊ |
248 | const char *s;␊ |
249 | char *out, *o;␊ |
250 | ␊ |
251 | if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) )␊ |
252 | return 0;␊ |
253 | ␊ |
254 | o = out;␊ |
255 | s = src;␊ |
256 | while (s <= src+len) /* Make sure the terminator is also copied */␊ |
257 | {␊ |
258 | if ( *s == '&' )␊ |
259 | {␊ |
260 | bool entFound = false;␊ |
261 | int i;␊ |
262 | ␊ |
263 | s++;␊ |
264 | for ( i = 0; i < sizeof(ents)/sizeof(ents[0]); i++)␊ |
265 | {␊ |
266 | if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 )␊ |
267 | {␊ |
268 | entFound = true;␊ |
269 | break;␊ |
270 | }␊ |
271 | }␊ |
272 | if ( entFound )␊ |
273 | {␊ |
274 | *o++ = ents[i].value;␊ |
275 | s += ents[i].nameLen;␊ |
276 | continue;␊ |
277 | }␊ |
278 | }␊ |
279 | ␊ |
280 | *o++ = *s++;␊ |
281 | }␊ |
282 | ␊ |
283 | return out;␊ |
284 | } ␊ |
285 | ␊ |
286 | //#if UNUSED␊ |
287 | //==========================================================================␊ |
288 | // XMLParseFile␊ |
289 | // Expects to see one dictionary in the XML file, the final pos will be returned␊ |
290 | // If the pos is not equal to the strlen, then there are multiple dicts␊ |
291 | // Puts the first dictionary it finds in the␊ |
292 | // tag pointer and returns the end of the dic, or returns -1 if not found.␊ |
293 | //␊ |
294 | long␊ |
295 | XMLParseFile( char * buffer, TagPtr * dict )␊ |
296 | {␊ |
297 | long length, pos;␊ |
298 | TagPtr tag;␊ |
299 | pos = 0;␊ |
300 | ␉char *configBuffer;␊ |
301 | ␉␊ |
302 | int strlength = strlen(buffer);␊ |
303 | configBuffer = malloc(strlength+1);␊ |
304 | bcopy(buffer, configBuffer, strlength);␊ |
305 | configBuffer[strlength] = 0;␊ |
306 | ␊ |
307 | ␉buffer_start = configBuffer;␊ |
308 | ␊ |
309 | while (1)␊ |
310 | {␊ |
311 | length = XMLParseNextTag(configBuffer + pos, &tag);␊ |
312 | if (length == -1) break;␊ |
313 | ␊ |
314 | pos += length;␊ |
315 | ␊ |
316 | if (tag == 0) continue;␊ |
317 | if (tag->type == kTagTypeDict) break;␊ |
318 | ␊ |
319 | XMLFreeTag(tag);␊ |
320 | }␊ |
321 | ␉free(configBuffer);␊ |
322 | ␉if (length < 0) {␊ |
323 | return -1;␊ |
324 | }␊ |
325 | *dict = tag;␊ |
326 | return pos;␊ |
327 | }␊ |
328 | //#endif /* UNUSED */␊ |
329 | ␊ |
330 | //==========================================================================␊ |
331 | // ParseNextTag␊ |
332 | // TODO: cleanup␊ |
333 | long␊ |
334 | XMLParseNextTag( char * buffer, TagPtr * tag )␊ |
335 | {␊ |
336 | ␉long length, pos;␊ |
337 | ␉char * tagName;␊ |
338 | ␉␊ |
339 | ␉length = GetNextTag(buffer, &tagName, 0);␊ |
340 | ␉if (length == -1) return -1;␊ |
341 | ␉␊ |
342 | ␉pos = length;␊ |
343 | ␉if (!strncmp(tagName, kXMLTagPList, 6))␊ |
344 | ␉{␊ |
345 | ␉␉length = 0;␊ |
346 | ␉}␊ |
347 | ␉/***** dict ****/␊ |
348 | ␉else if (!strcmp(tagName, kXMLTagDict))␊ |
349 | ␉{␊ |
350 | ␉␉length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);␊ |
351 | ␉}␊ |
352 | ␉else if (!strncmp(tagName, kXMLTagDict, strlen(kXMLTagDict)) && tagName[strlen(tagName)-1] == '/')␊ |
353 | ␉{␊ |
354 | ␉␉length = ParseTagList(buffer + pos, tag, kTagTypeDict, 1);␊ |
355 | ␉}␊ |
356 | ␉else if (!strncmp(tagName, kXMLTagDict " ", strlen(kXMLTagDict " ")))␊ |
357 | ␉{␊ |
358 | ␉␉length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);␊ |
359 | ␉}␊ |
360 | ␉/***** key ****/␊ |
361 | ␉else if (!strcmp(tagName, kXMLTagKey))␊ |
362 | ␉{␊ |
363 | ␉␉length = ParseTagKey(buffer + pos, tag);␊ |
364 | ␉}␊ |
365 | ␉␊ |
366 | ␉/***** string ****/␊ |
367 | ␉else if (!strcmp(tagName, kXMLTagString))␊ |
368 | ␉{␊ |
369 | ␉␉length = ParseTagString(buffer + pos, tag);␊ |
370 | ␉}␊ |
371 | ␉else if (!strncmp(tagName, kXMLTagString " ", strlen(kXMLTagString " ")))␊ |
372 | ␉{␊ |
373 | ␉␉// TODO: save tag if if found␊ |
374 | ␉␉if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringID, strlen(kXMLStringID)))␊ |
375 | ␉␉{␊ |
376 | ␉␉␉// ID=␊ |
377 | ␉␉␉int id = 0;␊ |
378 | ␉␉␉int cnt = strlen(kXMLTagString " " kXMLStringID "\"") + 1;␊ |
379 | ␉␉␉while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;␊ |
380 | ␉␉␉tagName[cnt] = 0;␊ |
381 | ␉␉␉char* val = tagName + strlen(kXMLTagString " " kXMLStringID "\"");␊ |
382 | ␉␉␉while(*val)␊ |
383 | ␉␉␉{␊ |
384 | ␉␉␉␉if ((*val >= '0' && *val <= '9'))␉// 0 - 9␊ |
385 | ␉␉␉␉{␊ |
386 | ␉␉␉␉␉id = (id * 10) + (*val++ - '0');␊ |
387 | ␉␉␉␉}␊ |
388 | ␉␉␉␉else␊ |
389 | ␉␉␉␉{␊ |
390 | ␉␉␉␉␉printf("ParseStringID error (0x%x)\n", *val);␊ |
391 | ␉␉␉␉␉getchar();␊ |
392 | ␉␉␉␉␉return -1;␊ |
393 | ␉␉␉␉}␊ |
394 | ␉␉␉}␊ |
395 | ␉␉␉length = ParseTagString(buffer + pos, tag);␊ |
396 | ␉␉␉␊ |
397 | ␉␉␉SaveRefString(buffer + pos, id);␊ |
398 | ␉␉}␊ |
399 | ␉␉else if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringIDRef, strlen(kXMLStringIDRef)))␊ |
400 | ␉␉{␊ |
401 | ␉␉␉// IDREF=␊ |
402 | ␉␉␉int id = 0;␊ |
403 | ␉␉␉int cnt = strlen(kXMLTagString " " kXMLStringIDRef "\"") + 1;␊ |
404 | ␉␉␉while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;␊ |
405 | ␉␉␉tagName[cnt] = 0;␊ |
406 | ␉␉␉char* val = tagName + strlen(kXMLTagString " " kXMLStringIDRef "\"");␊ |
407 | ␉␉␉while(*val)␊ |
408 | ␉␉␉{␊ |
409 | ␉␉␉␉if ((*val >= '0' && *val <= '9'))␉// 0 - 9␊ |
410 | ␉␉␉␉{␊ |
411 | ␉␉␉␉␉id = (id * 10) + (*val++ - '0');␊ |
412 | ␉␉␉␉}␊ |
413 | ␉␉␉␉else␊ |
414 | ␉␉␉␉{␊ |
415 | ␉␉␉␉␉printf("ParseStringIDREF error (0x%x)\n", *val);␊ |
416 | ␉␉␉␉␉getchar();␊ |
417 | ␉␉␉␉␉return -1;␊ |
418 | ␉␉␉␉}␊ |
419 | ␉␉␉}␊ |
420 | ␉␉␉char* str = GetRefString(id);␊ |
421 | ␊ |
422 | ␉␉␉TagPtr tmpTag = NewTag();␊ |
423 | ␉␉␉tmpTag->type = kTagTypeString;␊ |
424 | ␉␉␉tmpTag->string = str;␊ |
425 | ␉␉␉tmpTag->tag = 0;␊ |
426 | ␉␉␉tmpTag->tagNext = 0;␊ |
427 | ␉␉␉tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;␊ |
428 | ␉␉␉*tag = tmpTag;␊ |
429 | ␉␉␉␊ |
430 | ␉␉␉length = 0;␊ |
431 | ␉␉␉//printf("Located IDREF, id = %d, string = %s\n", id, str);␊ |
432 | ␉␉}␊ |
433 | ␉}␊ |
434 | ␉␊ |
435 | ␉/***** integer ****/␊ |
436 | ␉else if (!strcmp(tagName, kXMLTagInteger))␊ |
437 | ␉{␊ |
438 | ␉␉length = ParseTagInteger(buffer + pos, tag);␊ |
439 | ␉}␊ |
440 | ␉else if (!strncmp(tagName, kXMLTagInteger " ", strlen(kXMLTagInteger " ")))␊ |
441 | ␉{␊ |
442 | ␉␉if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringID, strlen(kXMLStringID)))␊ |
443 | ␉␉{␊ |
444 | ␉␉␉// ID=␊ |
445 | ␉␉␉int id = 0;␊ |
446 | ␉␉␉int cnt = strlen(kXMLTagInteger " " kXMLStringID "\"") + 1;␊ |
447 | ␉␉␉while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;␊ |
448 | ␉␉␉tagName[cnt] = 0;␊ |
449 | ␉␉␉char* val = tagName + strlen(kXMLTagInteger " " kXMLStringID "\"");␊ |
450 | ␉␉␉while(*val)␊ |
451 | ␉␉␉{␊ |
452 | ␉␉␉␉if ((*val >= '0' && *val <= '9'))␉// 0 - 9␊ |
453 | ␉␉␉␉{␊ |
454 | ␉␉␉␉␉id = (id * 10) + (*val++ - '0');␊ |
455 | ␉␉␉␉}␊ |
456 | ␉␉␉␉else␊ |
457 | ␉␉␉␉{␊ |
458 | ␉␉␉␉␉printf("ParseIntegerID error (0x%x)\n", *val);␊ |
459 | ␉␉␉␉␉getchar();␊ |
460 | ␉␉␉␉␉return -1;␊ |
461 | ␉␉␉␉}␊ |
462 | ␉␉␉}␊ |
463 | ␉␉␉length = ParseTagInteger(buffer + pos, tag);␊ |
464 | ␉␉␉␊ |
465 | ␉␉␉SaveRefString((*tag)->string, id);␊ |
466 | ␉␉}␊ |
467 | ␉␉else if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringIDRef, strlen(kXMLStringIDRef)))␊ |
468 | ␉␉{␊ |
469 | ␉␉␉// IDREF=␊ |
470 | ␉␉␉int id = 0;␊ |
471 | ␉␉␉int cnt = strlen(kXMLTagInteger " " kXMLStringIDRef "\"") + 1;␊ |
472 | ␉␉␉while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;␊ |
473 | ␉␉␉tagName[cnt] = 0;␊ |
474 | ␉␉␉char* val = tagName + strlen(kXMLTagInteger " " kXMLStringIDRef "\"");␊ |
475 | ␉␉␉while(*val)␊ |
476 | ␉␉␉{␊ |
477 | ␉␉␉␉if ((*val >= '0' && *val <= '9'))␉// 0 - 9␊ |
478 | ␉␉␉␉{␊ |
479 | ␉␉␉␉␉id = (id * 10) + (*val++ - '0');␊ |
480 | ␉␉␉␉}␊ |
481 | ␉␉␉␉else␊ |
482 | ␉␉␉␉{␊ |
483 | ␉␉␉␉␉printf("ParseStringIDREF error (0x%x)\n", *val);␊ |
484 | ␉␉␉␉␉getchar();␊ |
485 | ␉␉␉␉␉return -1;␊ |
486 | ␉␉␉␉}␊ |
487 | ␉␉␉}␊ |
488 | ␉␉␉int integer = (int)GetRefString(id);␊ |
489 | ␉␉␉␊ |
490 | ␉␉␉TagPtr tmpTag = NewTag();␊ |
491 | ␉␉␉tmpTag->type = kTagTypeInteger;␊ |
492 | ␉␉␉tmpTag->string = (char*) integer;␊ |
493 | ␉␉␉tmpTag->tag = 0;␊ |
494 | ␉␉␉tmpTag->tagNext = 0;␊ |
495 | ␉␉␉tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;␊ |
496 | ␉␉␉␊ |
497 | ␉␉␉*tag = tmpTag;␊ |
498 | ␉␉␉␊ |
499 | ␉␉␉length = 0;␊ |
500 | ␉␉␉//printf("Located IDREF, id = %d, string = %s\n", id, str);␊ |
501 | ␉␉}␊ |
502 | ␉␉else␊ |
503 | ␉␉{␊ |
504 | ␉␉␉length = ParseTagInteger(buffer + pos, tag);␊ |
505 | ␉␉}␊ |
506 | ␉}␊ |
507 | ␉␊ |
508 | ␉/***** data ****/␊ |
509 | ␉else if (!strcmp(tagName, kXMLTagData))␊ |
510 | ␉{␊ |
511 | ␉␉length = ParseTagData(buffer + pos, tag);␊ |
512 | ␉}␊ |
513 | ␉else if (!strncmp(tagName, kXMLTagData " ", strlen(kXMLTagData " ")))␊ |
514 | ␉{␊ |
515 | ␉␉length = ParseTagData(buffer + pos, tag);␊ |
516 | ␉}␊ |
517 | ␉else if (!strcmp(tagName, kXMLTagDate))␊ |
518 | ␉{␊ |
519 | ␉␉length = ParseTagDate(buffer + pos, tag);␊ |
520 | ␉}␊ |
521 | ␉␊ |
522 | ␉/***** date ****/␊ |
523 | ␉else if (!strncmp(tagName, kXMLTagDate " ", strlen(kXMLTagDate " ")))␊ |
524 | ␉{␊ |
525 | ␉␉length = ParseTagDate(buffer + pos, tag);␊ |
526 | ␉}␊ |
527 | ␉␊ |
528 | ␉/***** false ****/␊ |
529 | ␉else if (!strcmp(tagName, kXMLTagFalse))␊ |
530 | ␉{␊ |
531 | ␉␉length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);␊ |
532 | ␉}␊ |
533 | ␉/***** true ****/␊ |
534 | ␉else if (!strcmp(tagName, kXMLTagTrue))␊ |
535 | ␉{␊ |
536 | ␉␉length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);␊ |
537 | ␉}␊ |
538 | ␉␊ |
539 | ␉/***** array ****/␊ |
540 | ␉else if (!strcmp(tagName, kXMLTagArray))␊ |
541 | ␉{␊ |
542 | ␉␉length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);␊ |
543 | ␉}␊ |
544 | ␉else if (!strncmp(tagName, kXMLTagArray " ", strlen(kXMLTagArray " ")))␊ |
545 | ␉{␊ |
546 | ␉␉length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);␊ |
547 | ␉}␊ |
548 | ␉else if (!strcmp(tagName, kXMLTagArray "/"))␊ |
549 | ␉{␊ |
550 | ␉␉length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);␊ |
551 | ␉}␊ |
552 | ␉␊ |
553 | ␉/***** unknown ****/␊ |
554 | ␉else␊ |
555 | ␉{␊ |
556 | ␉␉*tag = 0;␊ |
557 | ␉␉length = 0;␊ |
558 | ␉}␊ |
559 | ␉␊ |
560 | ␉if (length == -1) return -1;␊ |
561 | ␉␊ |
562 | ␉return pos + length;␊ |
563 | }␊ |
564 | ␊ |
565 | //==========================================================================␊ |
566 | // ParseTagList␊ |
567 | ␊ |
568 | static long␊ |
569 | ParseTagList( char * buffer, TagPtr * tag, long type, long empty )␊ |
570 | {␊ |
571 | ␉long length, pos;␊ |
572 | ␉TagPtr tagList, tmpTag;␊ |
573 | ␊ |
574 | tagList = 0;␊ |
575 | pos = 0;␊ |
576 | ␊ |
577 | if (!empty)␊ |
578 | {␊ |
579 | while (1)␊ |
580 | {␊ |
581 | length = XMLParseNextTag(buffer + pos, &tmpTag);␊ |
582 | if (length == -1) break;␊ |
583 | ␊ |
584 | pos += length;␊ |
585 | ␊ |
586 | if (tmpTag == 0) break;␊ |
587 | tmpTag->tagNext = tagList;␊ |
588 | tagList = tmpTag;␊ |
589 | }␊ |
590 | ␊ |
591 | if (length == -1)␊ |
592 | {␊ |
593 | XMLFreeTag(tagList);␊ |
594 | return -1;␊ |
595 | }␊ |
596 | }␊ |
597 | ␊ |
598 | tmpTag = NewTag();␊ |
599 | if (tmpTag == 0)␊ |
600 | {␊ |
601 | XMLFreeTag(tagList);␊ |
602 | return -1;␊ |
603 | }␊ |
604 | ␊ |
605 | tmpTag->type = type;␊ |
606 | tmpTag->string = 0;␊ |
607 | ␉tmpTag->offset = buffer_start ? buffer - buffer_start : 0;␊ |
608 | tmpTag->tag = tagList;␊ |
609 | tmpTag->tagNext = 0;␊ |
610 | ␊ |
611 | *tag = tmpTag;␊ |
612 | ␊ |
613 | return pos;␊ |
614 | }␊ |
615 | ␊ |
616 | //==========================================================================␊ |
617 | // ParseTagKey␊ |
618 | ␊ |
619 | static long␊ |
620 | ParseTagKey( char * buffer, TagPtr * tag )␊ |
621 | {␊ |
622 | long length, length2;␊ |
623 | char *string;␊ |
624 | TagPtr tmpTag, subTag;␊ |
625 | ␊ |
626 | length = FixDataMatchingTag(buffer, kXMLTagKey);␊ |
627 | if (length == -1) return -1;␊ |
628 | ␊ |
629 | length2 = XMLParseNextTag(buffer + length, &subTag);␊ |
630 | if (length2 == -1) return -1;␊ |
631 | ␊ |
632 | tmpTag = NewTag();␊ |
633 | if (tmpTag == 0)␊ |
634 | {␊ |
635 | XMLFreeTag(subTag);␊ |
636 | return -1;␊ |
637 | }␊ |
638 | ␊ |
639 | string = NewSymbol(buffer);␊ |
640 | if (string == 0)␊ |
641 | {␊ |
642 | XMLFreeTag(subTag);␊ |
643 | XMLFreeTag(tmpTag);␊ |
644 | return -1;␊ |
645 | }␊ |
646 | ␊ |
647 | tmpTag->type = kTagTypeKey;␊ |
648 | tmpTag->string = string;␊ |
649 | tmpTag->tag = subTag;␊ |
650 | ␉tmpTag->offset = buffer_start ? buffer - buffer_start: 0;␊ |
651 | tmpTag->tagNext = 0;␊ |
652 | ␊ |
653 | *tag = tmpTag;␊ |
654 | ␊ |
655 | return length + length2;␊ |
656 | }␊ |
657 | ␊ |
658 | //==========================================================================␊ |
659 | // ParseTagString␊ |
660 | ␊ |
661 | static long␊ |
662 | ParseTagString( char * buffer, TagPtr * tag )␊ |
663 | {␊ |
664 | long length;␊ |
665 | char * string;␊ |
666 | ␊ |
667 | length = FixDataMatchingTag(buffer, kXMLTagString);␊ |
668 | if (length == -1) return -1;␊ |
669 | ␊ |
670 | ␉TagPtr tmpTag = NewTag();␊ |
671 | if (tmpTag == 0) return -1;␊ |
672 | ␊ |
673 | string = NewSymbol(buffer);␊ |
674 | if (string == 0)␊ |
675 | {␊ |
676 | XMLFreeTag(tmpTag);␊ |
677 | return -1;␊ |
678 | }␊ |
679 | ␊ |
680 | tmpTag->type = kTagTypeString;␊ |
681 | tmpTag->string = string;␊ |
682 | tmpTag->tag = 0;␊ |
683 | ␉tmpTag->offset = buffer_start ? buffer - buffer_start: 0;␊ |
684 | tmpTag->tagNext = 0;␊ |
685 | ␊ |
686 | *tag = tmpTag;␊ |
687 | return length;␊ |
688 | }␊ |
689 | ␊ |
690 | //==========================================================================␊ |
691 | // ParseTagInteger␊ |
692 | ␊ |
693 | static long␊ |
694 | ParseTagInteger( char * buffer, TagPtr * tag )␊ |
695 | {␊ |
696 | long length, integer;␊ |
697 | ␉bool negative = false;␊ |
698 | TagPtr tmpTag;␊ |
699 | ␉char* val = buffer;␊ |
700 | int size;␊ |
701 | ␉␊ |
702 | ␉if(buffer[0] == '<')␊ |
703 | ␉{␊ |
704 | ␉␉printf("Warning integer is non existant\n");␊ |
705 | ␉␉getchar();␊ |
706 | ␉␉tmpTag = NewTag();␊ |
707 | ␉␉tmpTag->type = kTagTypeInteger;␊ |
708 | ␉␉tmpTag->string = 0;␊ |
709 | ␉␉tmpTag->tag = 0;␊ |
710 | ␉␉tmpTag->offset = 0;␊ |
711 | ␉␉tmpTag->tagNext = 0;␊ |
712 | ␉␉␊ |
713 | ␉␉*tag = tmpTag;␊ |
714 | ␉␉␊ |
715 | ␉␉return 0;␊ |
716 | ␉}␊ |
717 | ␉␊ |
718 | size = length = FixDataMatchingTag(buffer, kXMLTagInteger);␊ |
719 | if (length == -1) return -1;␊ |
720 | ␊ |
721 | tmpTag = NewTag();␊ |
722 | if (tmpTag == 0) return -1;␊ |
723 | ␊ |
724 | integer = 0;␊ |
725 | ␊ |
726 | ␉if(size > 1 && (val[1] == 'x' || val[1] == 'X'))␉// Hex value␊ |
727 | ␉{␊ |
728 | ␉␉val += 2;␊ |
729 | ␉␉while(*val)␊ |
730 | ␉␉{␊ |
731 | ␉␉␉if ((*val >= '0' && *val <= '9'))␉// 0 - 9␊ |
732 | ␉␉␉{␊ |
733 | ␉␉␉␉integer = (integer * 16) + (*val++ - '0');␊ |
734 | ␉␉␉}␊ |
735 | ␉␉␉else if ((*val >= 'a' && *val <= 'f'))␉// a - f␊ |
736 | ␉␉␉{␊ |
737 | ␉␉␉␉integer = (integer * 16) + (*val++ - 'a' + 10);␊ |
738 | ␉␉␉}␊ |
739 | ␉␉␉else if ((*val >= 'A' && *val <= 'F'))␉// A - F␊ |
740 | ␉␉␉{␊ |
741 | ␉␉␉␉integer = (integer * 16) + (*val++ - 'a' + 10);␊ |
742 | ␉␉␉}␊ |
743 | ␉␉␉else␊ |
744 | ␉␉␉{␊ |
745 | ␉␉␉␉printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer);␊ |
746 | ␉␉␉␉getchar();␊ |
747 | ␉␉␉␉return -1;␊ |
748 | ␉␉␉}␊ |
749 | ␉␉}␊ |
750 | ␉}␊ |
751 | ␉else if ( size )␉// Decimal value␊ |
752 | ␉{␊ |
753 | ␉␉if (*val == '-')␊ |
754 | ␉␉{␊ |
755 | ␉␉␉negative = true;␊ |
756 | ␉␉␉val++;␊ |
757 | ␉␉␉size--;␊ |
758 | ␉␉}␊ |
759 | ␉␉␊ |
760 | ␉␉for (integer = 0; size > 0; size--)␊ |
761 | ␉␉{␊ |
762 | ␉␉␉if(*val) // UGLY HACK, fix me.␊ |
763 | ␉␉␉{␊ |
764 | ␉␉␉␉if (*val < '0' || *val > '9')␊ |
765 | ␉␉␉␉{␊ |
766 | ␉␉␉␉␉printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer);␊ |
767 | ␉␉␉␉␉getchar();␊ |
768 | ␉␉␉␉␉return -1;␊ |
769 | ␉␉␉␉}␊ |
770 | ␉␉␉␉␊ |
771 | ␉␉␉␉integer = (integer * 10) + (*val++ - '0');␊ |
772 | ␉␉␉}␊ |
773 | ␉␉}␊ |
774 | ␉␉␊ |
775 | ␉␉if (negative)␊ |
776 | ␉␉␉integer = -integer;␊ |
777 | ␉}␊ |
778 | ␉␉␊ |
779 | tmpTag->type = kTagTypeInteger;␊ |
780 | ␉tmpTag->string = (char *)integer;␊ |
781 | ␉tmpTag->tag = 0;␊ |
782 | ␉tmpTag->offset = buffer_start ? buffer - buffer_start: 0;␊ |
783 | tmpTag->tagNext = 0;␊ |
784 | ␊ |
785 | *tag = tmpTag;␊ |
786 | ␊ |
787 | return length;␊ |
788 | }␊ |
789 | ␊ |
790 | //==========================================================================␊ |
791 | // ParseTagData␊ |
792 | ␊ |
793 | static long␊ |
794 | ParseTagData( char * buffer, TagPtr * tag )␊ |
795 | {␊ |
796 | long length;␊ |
797 | TagPtr tmpTag;␊ |
798 | ␊ |
799 | length = FixDataMatchingTag(buffer, kXMLTagData);␊ |
800 | if (length == -1) return -1;␊ |
801 | ␊ |
802 | tmpTag = NewTag();␊ |
803 | if (tmpTag == 0) return -1;␊ |
804 | ␊ |
805 | ␉//printf("ParseTagData unimplimented\n");␊ |
806 | ␉//printf("Data: %s\n", buffer);␊ |
807 | ␉//␉getchar();␊ |
808 | ␉␊ |
809 | ␉// TODO: base64 decode␊ |
810 | ␉␊ |
811 | ␉char* string = NewSymbol(buffer);␊ |
812 | tmpTag->type = kTagTypeData;␊ |
813 | tmpTag->string = string;␊ |
814 | tmpTag->tag = 0;␊ |
815 | ␉tmpTag->offset = buffer_start ? buffer - buffer_start: 0;␊ |
816 | tmpTag->tagNext = 0;␊ |
817 | ␊ |
818 | *tag = tmpTag;␊ |
819 | ␊ |
820 | return length;␊ |
821 | }␊ |
822 | ␊ |
823 | //==========================================================================␊ |
824 | // ParseTagDate␊ |
825 | ␊ |
826 | static long␊ |
827 | ParseTagDate( char * buffer, TagPtr * tag )␊ |
828 | {␊ |
829 | long length;␊ |
830 | TagPtr tmpTag;␊ |
831 | ␊ |
832 | length = FixDataMatchingTag(buffer, kXMLTagDate);␊ |
833 | if (length == -1) return -1;␊ |
834 | ␊ |
835 | tmpTag = NewTag();␊ |
836 | if (tmpTag == 0) return -1;␊ |
837 | ␊ |
838 | ␉printf("ParseTagDate unimplimented\n");␊ |
839 | ␉getchar();␊ |
840 | ␉␊ |
841 | tmpTag->type = kTagTypeDate;␊ |
842 | tmpTag->string = 0;␊ |
843 | tmpTag->tag = 0;␊ |
844 | ␉tmpTag->offset = buffer_start ? buffer - buffer_start: 0;␊ |
845 | tmpTag->tagNext = 0;␊ |
846 | ␊ |
847 | *tag = tmpTag;␊ |
848 | ␊ |
849 | return length;␊ |
850 | }␊ |
851 | ␊ |
852 | //==========================================================================␊ |
853 | // ParseTagBoolean␊ |
854 | ␊ |
855 | long␊ |
856 | ParseTagBoolean( char * buffer, TagPtr * tag, long type )␊ |
857 | {␊ |
858 | TagPtr tmpTag;␊ |
859 | ␊ |
860 | tmpTag = NewTag();␊ |
861 | if (tmpTag == 0) return -1;␊ |
862 | ␊ |
863 | tmpTag->type = type;␊ |
864 | tmpTag->string = 0;␊ |
865 | tmpTag->tag = 0;␊ |
866 | ␉tmpTag->offset = buffer_start ? buffer - buffer_start: 0;␊ |
867 | tmpTag->tagNext = 0;␊ |
868 | ␊ |
869 | *tag = tmpTag;␊ |
870 | ␊ |
871 | return 0;␊ |
872 | }␊ |
873 | ␊ |
874 | //==========================================================================␊ |
875 | // GetNextTag␊ |
876 | ␊ |
877 | static long␊ |
878 | GetNextTag( char * buffer, char ** tag, long * start )␊ |
879 | {␊ |
880 | long cnt, cnt2;␊ |
881 | ␊ |
882 | if (tag == 0) return -1;␊ |
883 | ␊ |
884 | // Find the start of the tag.␊ |
885 | cnt = 0;␊ |
886 | while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;␊ |
887 | if (buffer[cnt] == '\0') return -1;␊ |
888 | ␊ |
889 | // Find the end of the tag.␊ |
890 | cnt2 = cnt + 1;␊ |
891 | while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;␊ |
892 | if (buffer[cnt2] == '\0') return -1;␊ |
893 | ␊ |
894 | // Fix the tag data.␊ |
895 | *tag = buffer + cnt + 1;␊ |
896 | buffer[cnt2] = '\0';␊ |
897 | if (start) *start = cnt;␊ |
898 | ␊ |
899 | return cnt2 + 1;␊ |
900 | }␊ |
901 | ␊ |
902 | //==========================================================================␊ |
903 | // FixDataMatchingTag␊ |
904 | // Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.␊ |
905 | // Returns the length of the data found, counting the end tag,␊ |
906 | // or -1 if the end tag was not found.␊ |
907 | ␊ |
908 | static long␊ |
909 | FixDataMatchingTag( char * buffer, char * tag )␊ |
910 | {␊ |
911 | long length, start, stop;␊ |
912 | char * endTag;␊ |
913 | ␊ |
914 | start = 0;␊ |
915 | while (1)␊ |
916 | {␊ |
917 | length = GetNextTag(buffer + start, &endTag, &stop);␊ |
918 | if (length == -1) return -1;␊ |
919 | ␊ |
920 | if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;␊ |
921 | start += length;␊ |
922 | }␊ |
923 | ␊ |
924 | buffer[start + stop] = '\0';␊ |
925 | ␊ |
926 | return start + length;␊ |
927 | }␊ |
928 | ␊ |
929 | //==========================================================================␊ |
930 | // NewTag␊ |
931 | ␊ |
932 | #define kTagsPerBlock (0x1000)␊ |
933 | ␊ |
934 | static TagPtr gTagsFree;␊ |
935 | ␊ |
936 | static TagPtr␊ |
937 | NewTag( void )␊ |
938 | {␊ |
939 | ␉long cnt;␊ |
940 | ␉TagPtr tag;␊ |
941 | ␊ |
942 | if (gTagsFree == 0)␊ |
943 | {␊ |
944 | tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));␊ |
945 | if (tag == 0) return 0;␊ |
946 | ␊ |
947 | // Initalize the new tags.␊ |
948 | for (cnt = 0; cnt < kTagsPerBlock; cnt++)␊ |
949 | {␊ |
950 | tag[cnt].type = kTagTypeNone;␊ |
951 | tag[cnt].string = 0;␊ |
952 | tag[cnt].tag = 0;␊ |
953 | tag[cnt].tagNext = tag + cnt + 1;␊ |
954 | }␊ |
955 | tag[kTagsPerBlock - 1].tagNext = 0;␊ |
956 | ␊ |
957 | gTagsFree = tag;␊ |
958 | }␊ |
959 | ␊ |
960 | tag = gTagsFree;␊ |
961 | gTagsFree = tag->tagNext;␊ |
962 | ␊ |
963 | return tag;␊ |
964 | }␊ |
965 | ␊ |
966 | //==========================================================================␊ |
967 | // XMLFreeTag␊ |
968 | ␊ |
969 | void␊ |
970 | XMLFreeTag( TagPtr tag )␊ |
971 | {␊ |
972 | #if DOFREE␊ |
973 | if (tag == 0) return;␊ |
974 | ␊ |
975 | if (tag->string) FreeSymbol(tag->string);␊ |
976 | ␊ |
977 | XMLFreeTag(tag->tag);␊ |
978 | XMLFreeTag(tag->tagNext);␊ |
979 | ␊ |
980 | // Clear and free the tag.␊ |
981 | tag->type = kTagTypeNone;␊ |
982 | tag->string = 0;␊ |
983 | tag->tag = 0;␊ |
984 | ␉tag->offset = 0;␊ |
985 | tag->tagNext = gTagsFree;␊ |
986 | gTagsFree = tag;␊ |
987 | #else␊ |
988 | return;␊ |
989 | #endif␊ |
990 | }␊ |
991 | ␊ |
992 | //==========================================================================␊ |
993 | // Symbol object.␊ |
994 | ␊ |
995 | struct Symbol␊ |
996 | {␊ |
997 | long refCount;␊ |
998 | struct Symbol *next;␊ |
999 | char string[];␊ |
1000 | };␊ |
1001 | typedef struct Symbol Symbol, *SymbolPtr;␊ |
1002 | ␊ |
1003 | static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);␊ |
1004 | ␊ |
1005 | static SymbolPtr gSymbolsHead;␊ |
1006 | ␊ |
1007 | //==========================================================================␊ |
1008 | // NewSymbol␊ |
1009 | ␊ |
1010 | static char *␊ |
1011 | NewSymbol( char * string )␊ |
1012 | {␊ |
1013 | static SymbolPtr lastGuy = 0;␊ |
1014 | ␉SymbolPtr symbol;␊ |
1015 | ␊ |
1016 | // Look for string in the list of symbols.␊ |
1017 | symbol = FindSymbol(string, 0);␊ |
1018 | ␊ |
1019 | // Add the new symbol.␊ |
1020 | if (symbol == 0)␊ |
1021 | {␊ |
1022 | symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));␊ |
1023 | if (symbol == 0) //return 0;␊ |
1024 | stop("NULL symbol!");␊ |
1025 | ␊ |
1026 | // Set the symbol's data.␊ |
1027 | symbol->refCount = 0;␊ |
1028 | strcpy(symbol->string, string);␊ |
1029 | ␊ |
1030 | // Add the symbol to the list.␊ |
1031 | symbol->next = gSymbolsHead;␊ |
1032 | gSymbolsHead = symbol;␊ |
1033 | }␊ |
1034 | ␊ |
1035 | // Update the refCount and return the string.␊ |
1036 | symbol->refCount++;␊ |
1037 | ␊ |
1038 | if (lastGuy && lastGuy->next != 0) stop("last guy not last!");␊ |
1039 | return symbol->string;␊ |
1040 | }␊ |
1041 | ␊ |
1042 | //==========================================================================␊ |
1043 | // FreeSymbol␊ |
1044 | ␊ |
1045 | #if DOFREE␊ |
1046 | static void␊ |
1047 | FreeSymbol( char * string )␊ |
1048 | {␊ |
1049 | SymbolPtr symbol, prev;␊ |
1050 | ␉prev = 0;␊ |
1051 | ␊ |
1052 | // Look for string in the list of symbols.␊ |
1053 | symbol = FindSymbol(string, &prev);␊ |
1054 | if (symbol == 0) return;␊ |
1055 | ␊ |
1056 | // Update the refCount.␊ |
1057 | symbol->refCount--;␊ |
1058 | ␊ |
1059 | if (symbol->refCount != 0) return;␊ |
1060 | ␊ |
1061 | // Remove the symbol from the list.␊ |
1062 | if (prev != 0) prev->next = symbol->next;␊ |
1063 | else gSymbolsHead = symbol->next;␊ |
1064 | ␊ |
1065 | // Free the symbol's memory.␊ |
1066 | free(symbol);␊ |
1067 | }␊ |
1068 | #endif␊ |
1069 | ␊ |
1070 | //==========================================================================␊ |
1071 | // FindSymbol␊ |
1072 | ␊ |
1073 | static SymbolPtr␊ |
1074 | FindSymbol( char * string, SymbolPtr * prevSymbol )␊ |
1075 | {␊ |
1076 | SymbolPtr symbol, prev;␊ |
1077 | ␊ |
1078 | symbol = gSymbolsHead;␊ |
1079 | prev = 0;␊ |
1080 | ␊ |
1081 | while (symbol != 0) {␊ |
1082 | if (!strcmp(symbol->string, string)) break;␊ |
1083 | ␊ |
1084 | prev = symbol;␊ |
1085 | symbol = symbol->next;␊ |
1086 | }␊ |
1087 | ␊ |
1088 | if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev;␊ |
1089 | ␊ |
1090 | return symbol;␊ |
1091 | }␊ |
1092 | ␊ |
1093 | bool XMLIsType(TagPtr dict, enum xmltype type)␊ |
1094 | {␊ |
1095 | ␉if(!dict) return (type == kTagTypeNone);␊ |
1096 | ␉return (dict->type == type);␊ |
1097 | }␊ |
1098 | ␊ |
1099 | /*** Cast functions ***/␊ |
1100 | bool XMLIsArray(TagPtr entry)␊ |
1101 | {␊ |
1102 | return entry && (entry->type == kTagTypeArray);␊ |
1103 | }␊ |
1104 | ␊ |
1105 | TagPtr XMLCastArray(TagPtr dict)␊ |
1106 | {␊ |
1107 | ␉if(!dict) return NULL;␊ |
1108 | ␉if(dict->type == kTagTypeArray) return dict;␊ |
1109 | ␉else return NULL;␊ |
1110 | }␊ |
1111 | ␊ |
1112 | bool XMLIsDict(TagPtr entry)␊ |
1113 | {␊ |
1114 | return entry && (entry->type == kTagTypeDict);␊ |
1115 | }␊ |
1116 | ␊ |
1117 | ␊ |
1118 | TagPtr XMLCastDict(TagPtr dict)␊ |
1119 | {␊ |
1120 | ␉if(!dict) return NULL;␊ |
1121 | ␉if(dict->type == kTagTypeDict) return dict;␊ |
1122 | ␉else return NULL;␊ |
1123 | }␊ |
1124 | ␊ |
1125 | bool XMLIsString(TagPtr entry)␊ |
1126 | {␊ |
1127 | return entry && ␊ |
1128 | ((entry->type == kTagTypeString) ||␊ |
1129 | (entry->type == kTagTypeKey));␊ |
1130 | }␊ |
1131 | ␊ |
1132 | char* XMLCastString(TagPtr dict)␊ |
1133 | {␊ |
1134 | ␉if(!dict) return NULL;␊ |
1135 | ␊ |
1136 | ␉if((dict->type == kTagTypeString) ||␊ |
1137 | ␉ (dict->type == kTagTypeKey)) return dict->string;␊ |
1138 | ␉␊ |
1139 | ␉return NULL;␊ |
1140 | }␊ |
1141 | ␊ |
1142 | long XMLCastStringOffset(TagPtr dict)␊ |
1143 | {␊ |
1144 | ␉if(dict &&␊ |
1145 | ␉ ((dict->type == kTagTypeString) ||␊ |
1146 | ␉ (dict->type == kTagTypeKey)))␊ |
1147 | ␉{␊ |
1148 | ␉␉return dict->offset;␊ |
1149 | ␉}␊ |
1150 | ␉else ␊ |
1151 | ␉{␊ |
1152 | ␉␉return -1;␊ |
1153 | ␉}␊ |
1154 | }␊ |
1155 | ␊ |
1156 | bool XMLIsBoolean(TagPtr entry)␊ |
1157 | {␊ |
1158 | return entry && ␊ |
1159 | ((entry->type == kTagTypeTrue) ||␊ |
1160 | (entry->type == kTagTypeFalse));␊ |
1161 | }␊ |
1162 | ␊ |
1163 | bool XMLCastBoolean(TagPtr dict)␊ |
1164 | {␊ |
1165 | ␉if(!dict) return false;␊ |
1166 | ␉if(dict->type == kTagTypeTrue) return true;␊ |
1167 | ␉return false;␊ |
1168 | }␊ |
1169 | ␊ |
1170 | bool XMLIsInteger(TagPtr entry)␊ |
1171 | {␊ |
1172 | return entry && (entry->type == kTagTypeInteger);␊ |
1173 | }␊ |
1174 | ␊ |
1175 | int XMLCastInteger(TagPtr dict)␊ |
1176 | {␊ |
1177 | ␉if(!dict)␊ |
1178 | ␉{␊ |
1179 | ␉␉//printf("XMLCastInteger: null dict\n");␊ |
1180 | ␉␉return 0;␊ |
1181 | ␉}␊ |
1182 | ␉if(dict->type == kTagTypeInteger) return (int)(dict->string);␊ |
1183 | ␉return 0;␊ |
1184 | }␊ |
1185 | ␊ |
1186 | bool XMLAddTagToDictionary(TagPtr dict, char* key, TagPtr value)␊ |
1187 | {␊ |
1188 | if (!dict || dict->type != kTagTypeDict) return false;␊ |
1189 | ␊ |
1190 | TagPtr tmpTag;␊ |
1191 | char* string;␊ |
1192 | ␊ |
1193 | tmpTag = NewTag();␊ |
1194 | if (tmpTag == 0)␊ |
1195 | {␊ |
1196 | return false;␊ |
1197 | }␊ |
1198 | ␊ |
1199 | string = NewSymbol(key);␊ |
1200 | if (string == 0)␊ |
1201 | {␊ |
1202 | XMLFreeTag(tmpTag);␊ |
1203 | return false;␊ |
1204 | }␊ |
1205 | ␊ |
1206 | tmpTag->type = kTagTypeKey;␊ |
1207 | tmpTag->string = string;␊ |
1208 | tmpTag->tag = value;␊ |
1209 | ␉tmpTag->offset = 0;␊ |
1210 | tmpTag->tagNext = 0;␊ |
1211 | ␊ |
1212 | TagPtr tagList = dict->tag;␊ |
1213 | if(!tagList)␊ |
1214 | {␊ |
1215 | // First tag␊ |
1216 | dict->tag = tmpTag;␊ |
1217 | return true;␊ |
1218 | }␊ |
1219 | while(tagList && tagList->tagNext) tagList = tagList->tagNext;␊ |
1220 | if(tagList)␊ |
1221 | {␊ |
1222 | tagList->tagNext = tmpTag;␊ |
1223 | return true;␊ |
1224 | }␊ |
1225 | return false;␊ |
1226 | }␊ |
1227 |