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