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