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