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