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