/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights * Reserved. * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 2.0 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include "config.h" #include "bootstruct.h" #include "libsaio.h" #include "sl.h" #include "xml.h" #if DEBUG_XML #define DBG(x...) printf(x) #else #define DBG(x...) #endif string_ref *ref_strings = NULL; string_ref *ref_integer = NULL; /// TODO: remove below static char *buffer_start = NULL; // TODO: redo the next two functions void SaveRefString(char *string, int id) { //printf("Adding Ref String %d (%s)\n", id, string); string_ref *tmp = ref_strings; while(tmp) { if(tmp->id == id) { tmp->string = malloc(strlen(string)+1); strncpy(tmp->string, string, strlen(string)+1); return; } tmp = tmp->next; } string_ref *new_ref = malloc(sizeof(string_ref)); new_ref->string = malloc(strlen(string)+1); strncpy(new_ref->string, string, (strlen(string)+1)* sizeof(char)); new_ref->id = id; new_ref->next = ref_strings; ref_strings = new_ref; } void SaveRefInteger(int integer, int id) { //printf("Adding Ref Integer %d (%s)\n", id, integer); string_ref *tmp = ref_integer; while(tmp) { if(tmp->id == id) { tmp->string = (char*)integer; return; } tmp = tmp->next; } string_ref *new_ref = malloc(sizeof(string_ref)); new_ref->string = (char*)integer; new_ref->id = id; new_ref->next = ref_integer; ref_integer = new_ref; } char *GetRefString(int id) { string_ref *tmp = ref_strings; while(tmp) { if(tmp->id == id) return tmp->string; tmp = tmp->next; } //verbose("Unable to locate Ref String %d\n", id); return "Unknown"; } int GetRefInteger(int id) { string_ref *tmp = ref_integer; while(tmp) { if(tmp->id == id) return (int)tmp->string; tmp = tmp->next; } //verbose("Unable to locate Ref String %d\n", id); return 0; } struct Module { struct Module *nextModule; long willLoad; TagPtr dict; char *plistAddr; long plistLength; char *driverPath; }; typedef struct Module Module, *ModulePtr; struct DriverInfo { char *plistAddr; long plistLength; void *moduleAddr; long moduleLength; }; typedef struct DriverInfo DriverInfo, *DriverInfoPtr; #define kDriverPackageSignature1 'MKXT' #define kDriverPackageSignature2 'MOSX' struct DriversPackage { unsigned long signature1; unsigned long signature2; unsigned long length; unsigned long adler32; unsigned long version; unsigned long numDrivers; unsigned long reserved1; unsigned long reserved2; }; typedef struct DriversPackage DriversPackage; enum { kCFBundleType2, kCFBundleType3 }; #define DOFREE 1 static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty); static long ParseTagKey(char *buffer, TagPtr *tag); static long ParseTagString(char *buffer, TagPtr *tag); static long ParseTagInteger(char *buffer, TagPtr *tag); static long ParseTagData(char *buffer, TagPtr *tag); static long ParseTagDate(char *buffer, TagPtr *tag); //static long ParseTagBoolean(char *buffer, TagPtr *tag, long type); static long GetNextTag(char *buffer, char **tag, long *start); static long FixDataMatchingTag(char *buffer, char *tag); static TagPtr NewTag(void); static char *NewSymbol(char *string); #if DOFREE static void FreeSymbol(char *string); #endif //========================================================================== // XMLGetProperty TagPtr XMLGetProperty(TagPtr dict, const char *key) { TagPtr tagList, tag; if (dict->type != kTagTypeDict) { return NULL; } tag = 0; tagList = dict->tag; while (tagList) { tag = tagList; tagList = tag->tagNext; if ((tag->type != kTagTypeKey) || (tag->string == 0)) { continue; } if (!strcmp(tag->string, key)) { return tag->tag; } } return NULL; } //========================================================================== // XMLGetProperty TagPtr XMLGetKey( TagPtr dict, int id ) { TagPtr tagList, tag; if (dict->type != kTagTypeDict) { return 0; } tag = 0; int element = 0; tagList = dict->tag; while (tagList && element != id) { tag = tagList; tagList = tag->tagNext; if ((tag->type != kTagTypeKey) || (tag->string == 0)) { continue; } element++; if(id == element) { return tag; } } return 0; } TagPtr XMLGetValueForKey(TagPtr key) { if (!key || key->type != kTagTypeKey) { return 0; } return key->tag; } // XMLGetTag(int index) // XMLTagCount( TagPtr dict ) int XMLTagCount( TagPtr dict ) { int count = 0; TagPtr tagList, tag; if (dict->type != kTagTypeDict && dict->type != kTagTypeArray) { return 0; } tag = 0; tagList = dict->tag; while (tagList) { tag = tagList; tagList = tag->tagNext; if (((tag->type != kTagTypeKey) && ((tag->string == 0) || (tag->string[0] == 0))) && (dict->type != kTagTypeArray) // If we are an array, any element is valid ) { continue; } //if(tag->type == kTagTypeKey) printf("Located key %s\n", tag->string); count++; } return count; } TagPtr XMLGetElement( TagPtr dict, int id ) { if(dict->type != kTagTypeArray) { return 0; } int element = 0; TagPtr tmp = dict->tag; while(element < id) { element++; tmp = tmp->tagNext; } return tmp; } typedef const struct XMLEntity { const char *name; size_t nameLen; char value; } XMLEntity; /* This is ugly, but better than specifying the lengths by hand */ #define _e(str,c) {str,sizeof(str)-1,c} const XMLEntity ents[] = { _e("quot;",'"'), // double quotation mark _e("apos;",'\''), // apostrophe (apostrophe-quote) _e("lt;", '<'), // less-than sign _e("gt;", '>'), // greater-than sign _e("amp;", '&') // ampersand }; /* Function for basic XML character entities parsing */ char *XMLDecode(const char *src) { size_t len; const char *s; char *out, *o; if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) ) { return 0; } o = out; s = src; while (s <= src+len) /* Make sure the terminator is also copied */ { if ( *s == '&' ) { bool entFound = false; int i; s++; for ( i = 0; i < sizeof(ents)/sizeof(ents[0]); i++) { if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 ) { entFound = true; break; } } if ( entFound ) { *o++ = ents[i].value; s += ents[i].nameLen; continue; } } *o++ = *s++; } return out; } //========================================================================== // XMLParseFile // Expects to see one dictionary in the XML file, the final pos will be returned // If the pos is not equal to the strlen, then there are multiple dicts // Puts the first dictionary it finds in the // tag pointer and returns the end of the dic, or returns -1 if not found. // long XMLParseFile( char * buffer, TagPtr *dict ) { long length; long pos = 0; TagPtr tag; char *configBuffer; int strlength = strlen(buffer); configBuffer = malloc(strlength+1); bcopy(buffer, configBuffer, strlength); configBuffer[strlength] = 0; buffer_start = configBuffer; while (1) { length = XMLParseNextTag(configBuffer + pos, &tag); if (length == -1) break; pos += length; if (tag == 0) { continue; } if (tag->type == kTagTypeDict) { break; } XMLFreeTag(tag); } free(configBuffer); if (length < 0) { return -1; } *dict = tag; return pos; } //========================================================================== // ParseNextTag // TODO: cleanup long XMLParseNextTag( char *buffer, TagPtr *tag ) { long length = 0; long pos = 0; char *tagName = NULL; length = GetNextTag(buffer, &tagName, 0); if (length == -1) { return -1; } pos = length; if (!strncmp(tagName, kXMLTagPList, 6)) { length = 0; // just a header; nothing to parse // return-via-reference tag should be left alone } /***** dict ****/ else if (!strncmp(tagName, kXMLTagDict, sizeof(kXMLTagDict))) { length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0); } else if (!strncmp(tagName, kXMLTagDict, strlen(kXMLTagDict)) && tagName[strlen(tagName)-1] == '/') { length = ParseTagList(buffer + pos, tag, kTagTypeDict, 1); } else if (!strncmp(tagName, kXMLTagDict " ", strlen(kXMLTagDict " "))) { length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0); } /***** key ****/ else if (!strncmp(tagName, kXMLTagKey, sizeof(kXMLTagKey))) { length = ParseTagKey(buffer + pos, tag); } /***** string ****/ else if (!strncmp(tagName, kXMLTagString, sizeof(kXMLTagString))) { length = ParseTagString(buffer + pos, tag); } else if (!strncmp(tagName, kXMLTagString " ", strlen(kXMLTagString " "))) { // TODO: save tag if if found if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringID, strlen(kXMLStringID))) { // ID= int id = 0; int cnt = strlen(kXMLTagString " " kXMLStringID "\"") + 1; while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++; tagName[cnt] = 0; char* val = tagName + strlen(kXMLTagString " " kXMLStringID "\""); while(*val) { if ((*val >= '0' && *val <= '9')) // 0 - 9 { id = (id * 10) + (*val++ - '0'); } else { printf("ParseStringID error (0x%x)\n", *val); getchar(); return -1; } } length = ParseTagString(buffer + pos, tag); SaveRefString(buffer + pos, id); } else if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringIDRef, strlen(kXMLStringIDRef))) { // IDREF= int id = 0; int cnt = strlen(kXMLTagString " " kXMLStringIDRef "\"") + 1; while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++; tagName[cnt] = 0; char* val = tagName + strlen(kXMLTagString " " kXMLStringIDRef "\""); while(*val) { if ((*val >= '0' && *val <= '9')) // 0 - 9 { id = (id * 10) + (*val++ - '0'); } else { printf("ParseStringIDREF error (0x%x)\n", *val); getchar(); return -1; } } char* str = GetRefString(id); TagPtr tmpTag = NewTag(); tmpTag->type = kTagTypeString; tmpTag->string = str; tmpTag->tag = 0; tmpTag->tagNext = 0; tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0; *tag = tmpTag; length = 0; //printf("Located IDREF, id = %d, string = %s\n", id, str); } } /***** integer ****/ else if (!strncmp(tagName, kXMLTagInteger, sizeof(kXMLTagInteger))) { length = ParseTagInteger(buffer + pos, tag); } else if (!strncmp(tagName, kXMLTagInteger " ", strlen(kXMLTagInteger " "))) { if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringID, strlen(kXMLStringID))) { // ID= int id = 0; int cnt = strlen(kXMLTagInteger " " kXMLStringID "\"") + 1; while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++; tagName[cnt] = 0; char* val = tagName + strlen(kXMLTagInteger " " kXMLStringID "\""); while(*val) { if ((*val >= '0' && *val <= '9')) // 0 - 9 { id = (id * 10) + (*val++ - '0'); } else { printf("ParseIntegerID error (0x%x)\n", *val); getchar(); return -1; } } length = ParseTagInteger(buffer + pos, tag); SaveRefInteger((int)(*tag)->string, id); } else if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringIDRef, strlen(kXMLStringIDRef))) { // IDREF= int id = 0; int cnt = strlen(kXMLTagInteger " " kXMLStringIDRef "\"") + 1; while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++; tagName[cnt] = 0; char* val = tagName + strlen(kXMLTagInteger " " kXMLStringIDRef "\""); while(*val) { if ((*val >= '0' && *val <= '9')) // 0 - 9 { id = (id * 10) + (*val++ - '0'); } else { printf("ParseStringIDREF error (0x%x)\n", *val); getchar(); return -1; } } int integer = GetRefInteger(id); TagPtr tmpTag = NewTag(); if (tmpTag == 0) { return -1; } tmpTag->type = kTagTypeInteger; tmpTag->string = (char*) integer; tmpTag->tag = 0; tmpTag->tagNext = 0; tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0; *tag = tmpTag; length = 0; //printf("Located IDREF, id = %d, string = %s\n", id, str); } else { length = ParseTagInteger(buffer + pos, tag); } } /***** data ****/ else if (!strncmp(tagName, kXMLTagData, sizeof(kXMLTagData))) { length = ParseTagData(buffer + pos, tag); } else if (!strncmp(tagName, kXMLTagData " ", strlen(kXMLTagData " "))) { length = ParseTagData(buffer + pos, tag); } else if (!strncmp(tagName, kXMLTagDate, sizeof(kXMLTagDate))) { length = ParseTagDate(buffer + pos, tag); } /***** date ****/ else if (!strncmp(tagName, kXMLTagDate " ", strlen(kXMLTagDate " "))) { length = ParseTagDate(buffer + pos, tag); } /***** false ****/ else if (!strncmp(tagName, kXMLTagFalse, sizeof(kXMLTagFalse))) { length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse); } /***** true ****/ else if (!strncmp(tagName, kXMLTagTrue, sizeof(kXMLTagTrue))) { length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue); } /***** array ****/ else if (!strncmp(tagName, kXMLTagArray, sizeof(kXMLTagArray) )) { length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0); } else if (!strncmp(tagName, kXMLTagArray " ", strlen(kXMLTagArray " "))) { length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0); } else if (!strncmp(tagName, kXMLTagArray "/", strlen(kXMLTagArray "/"))) { length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1); } /***** unknown ****/ else { // it wasn't parsed so we consumed no additional characters *tag = NULL; length = 0; } if (length == -1) { return -1; } return pos + length; } //========================================================================== // ParseTagList static long ParseTagList( char *buffer, TagPtr *tag, long type, long empty ) { long pos = 0; long length = 0; TagPtr tagList = NULL; TagPtr tmpTag; if (!empty) { while (1) { length = XMLParseNextTag(buffer + pos, &tmpTag); if (length == -1) { break; } pos += length; // detect end of list if (tmpTag == NULL) { break; } tmpTag->tagNext = tagList; tagList = tmpTag; } if (length == -1) { XMLFreeTag(tagList); return -1; } } tmpTag = NewTag(); if (tmpTag == NULL) { XMLFreeTag(tagList); return -1; } tmpTag->type = type; tmpTag->string = 0; tmpTag->offset = buffer_start ? buffer - buffer_start : 0; tmpTag->tag = tagList; tmpTag->tagNext = 0; *tag = tmpTag; return pos; } //========================================================================== // ParseTagKey static long ParseTagKey( char *buffer, TagPtr *tag ) { long length = 0; long length2 = 0; char *string; TagPtr tmpTag; TagPtr subTag; length = FixDataMatchingTag(buffer, kXMLTagKey); if (length == -1) { return -1; } length2 = XMLParseNextTag(buffer + length, &subTag); if (length2 == -1) { return -1; } tmpTag = NewTag(); if (tmpTag == NULL) { XMLFreeTag(subTag); return -1; } string = NewSymbol(buffer); if (string == NULL) { XMLFreeTag(subTag); XMLFreeTag(tmpTag); return -1; } tmpTag->type = kTagTypeKey; tmpTag->string = string; tmpTag->tag = subTag; tmpTag->offset = buffer_start ? buffer - buffer_start: 0; tmpTag->tagNext = 0; *tag = tmpTag; return length + length2; } //========================================================================== // ParseTagString static long ParseTagString( char *buffer, TagPtr *tag ) { long length = 0; char *string; length = FixDataMatchingTag(buffer, kXMLTagString); if (length == -1) { return -1; } TagPtr tmpTag = NewTag(); if (tmpTag == NULL) { return -1; } string = NewSymbol(buffer); if (string == NULL) { XMLFreeTag(tmpTag); return -1; } tmpTag->type = kTagTypeString; tmpTag->string = string; tmpTag->tag = NULL; tmpTag->tagNext = NULL; tmpTag->offset = buffer_start ? buffer - buffer_start: 0; *tag = tmpTag; return length; } //========================================================================== // ParseTagInteger static long ParseTagInteger( char *buffer, TagPtr *tag ) { long length, integer; bool negative = false; TagPtr tmpTag; char* val = buffer; int size; if(buffer[0] == '<') { printf("Warning integer is non existant\n"); getchar(); tmpTag = NewTag(); tmpTag->type = kTagTypeInteger; tmpTag->string = 0; tmpTag->tag = 0; tmpTag->offset = 0; tmpTag->tagNext = 0; *tag = tmpTag; return 0; } size = length = FixDataMatchingTag(buffer, kXMLTagInteger); if (length == -1) { return -1; } tmpTag = NewTag(); if (tmpTag == 0) { return -1; } integer = 0; if(size > 1 && (val[1] == 'x' || val[1] == 'X')) // Hex value { val += 2; while(*val) { if ((*val >= '0' && *val <= '9')) // 0 - 9 { integer = (integer * 16) + (*val++ - '0'); } else if ((*val >= 'a' && *val <= 'f')) // a - f { integer = (integer * 16) + (*val++ - 'a' + 10); } else if ((*val >= 'A' && *val <= 'F')) // A - F { integer = (integer * 16) + (*val++ - 'A' + 10); } else { printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer); getchar(); XMLFreeTag(tmpTag); return -1; } } } else if ( size ) // Decimal value { if (*val == '-') { negative = true; val++; size--; } for (integer = 0; size > 0; size--) { if(*val) // UGLY HACK, fix me. { if (*val < '0' || *val > '9') { printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer); getchar(); return -1; } integer = (integer * 10) + (*val++ - '0'); } } if (negative) { integer = -integer; } } tmpTag->type = kTagTypeInteger; tmpTag->string = (char *)integer; tmpTag->tag = NULL; tmpTag->offset = buffer_start ? buffer - buffer_start: 0; tmpTag->tagNext = NULL; *tag = tmpTag; return length; } //========================================================================== // ParseTagData static long ParseTagData( char *buffer, TagPtr *tag) { //int actuallen = 0; int len = 0; long length = 0; TagPtr tmpTag; char *tmpString; length = FixDataMatchingTag(buffer, kXMLTagData); if (length == -1) { return -1; } tmpTag = NewTag(); if (tmpTag == NULL) { return -1; } tmpString = NewSymbol(buffer); tmpTag->type = kTagTypeData; tmpTag->string = tmpString; tmpTag->data = (UInt8 *)BASE64Decode(buffer, strlen(buffer), &len); tmpTag->dataLen = len; tmpTag->tag = NULL; tmpTag->offset = /* actuallen; */ buffer_start ? buffer - buffer_start: 0; tmpTag->tagNext = NULL; *tag = tmpTag; return length; } //========================================================================== // ParseTagDate static long ParseTagDate( char *buffer, TagPtr *tag ) { long length = 0; TagPtr tmpTag; length = FixDataMatchingTag(buffer, kXMLTagDate); if (length == -1) { return -1; } tmpTag = NewTag(); if (tmpTag == NULL) { return -1; } // printf("ParseTagDate unimplimented\n"); // getchar(); tmpTag->type = kTagTypeDate; tmpTag->string = NULL; tmpTag->tag = NULL; tmpTag->tagNext = NULL; tmpTag->offset = buffer_start ? buffer - buffer_start: 0; *tag = tmpTag; return length; } //========================================================================== // ParseTagBoolean long ParseTagBoolean( char *buffer, TagPtr *tag, long type ) { TagPtr tmpTag; tmpTag = NewTag(); if (tmpTag == NULL) { return -1; } tmpTag->type = type; tmpTag->string = NULL; tmpTag->tag = NULL; tmpTag->tagNext = NULL; tmpTag->offset = buffer_start ? buffer - buffer_start: 0; *tag = tmpTag; return 0; } //========================================================================== // GetNextTag static long GetNextTag( char *buffer, char **tag, long *start ) { long cnt; long cnt2; if (tag == NULL) { return -1; } // Find the start of the tag. cnt = 0; while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) { cnt++; } if (buffer[cnt] == '\0') { return -1; } // Find the end of the tag. cnt2 = cnt + 1; while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) { cnt2++; } if (buffer[cnt2] == '\0') { return -1; } // Fix the tag data. *tag = buffer + cnt + 1; buffer[cnt2] = '\0'; if (start) { *start = cnt; } return cnt2 + 1; } //========================================================================== // FixDataMatchingTag // Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'. // Returns the length of the data found, counting the end tag, // or -1 if the end tag was not found. static long FixDataMatchingTag( char *buffer, char *tag ) { long length; long start; long stop; char *endTag; start = 0; while (1) { length = GetNextTag(buffer + start, &endTag, &stop); if (length == -1) { return -1; } if ((*endTag == '/') && !strcmp(endTag + 1, tag)) { break; } start += length; } buffer[start + stop] = '\0'; return start + length; } //========================================================================== // NewTag #define kTagsPerBlock (0x1000) static TagPtr gTagsFree = NULL; static TagPtr NewTag( void ) { long cnt; TagPtr tag; if (gTagsFree == NULL) { tag = (TagPtr)malloc(kTagsPerBlock *sizeof(Tag)); if (tag == NULL) { return NULL; } // Initalize the new tags. for (cnt = 0; cnt < kTagsPerBlock; cnt++) { tag[cnt].type = kTagTypeNone; tag[cnt].string = 0; tag[cnt].data = 0; tag[cnt].dataLen = 0; tag[cnt].tag = 0; tag[cnt].tagNext = tag + cnt + 1; } tag[kTagsPerBlock - 1].tagNext = 0; gTagsFree = tag; } tag = gTagsFree; gTagsFree = tag->tagNext; return tag; } //========================================================================== // XMLFreeTag void XMLFreeTag( TagPtr tag ) { #if DOFREE if (tag == NULL) { return; } if (!XMLIsInteger(tag) && tag->string) { FreeSymbol(tag->string); } XMLFreeTag(tag->tag); XMLFreeTag(tag->tagNext); // Clear and free the tag. tag->type = kTagTypeNone; tag->string = NULL; tag->data = NULL; tag->dataLen = 0; tag->tag = NULL; tag->offset = 0; tag->tagNext = gTagsFree; gTagsFree = tag; #else return; #endif } //========================================================================== // Symbol object. struct Symbol { long refCount; struct Symbol *next; char string[]; }; typedef struct Symbol Symbol, *SymbolPtr; static SymbolPtr FindSymbol(char *string, SymbolPtr *prevSymbol); static SymbolPtr gSymbolsHead = NULL; //========================================================================== // NewSymbol static char *NewSymbol( char *string ) { static SymbolPtr lastGuy = 0; SymbolPtr symbol; // Look for string in the list of symbols. symbol = FindSymbol(string, 0); // Add the new symbol. if (symbol == NULL) { symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string)); if (symbol == NULL) { stop("NULL symbol!"); return NULL; } // Set the symbol's data. symbol->refCount = 0; strcpy(symbol->string, string); // Add the symbol to the list. symbol->next = gSymbolsHead; gSymbolsHead = symbol; } // Update the refCount and return the string. symbol->refCount++; if (lastGuy && lastGuy->next != 0) { stop("last guy not last!"); } return symbol->string; } //========================================================================== // FreeSymbol #if DOFREE static void FreeSymbol( char *string ) { SymbolPtr symbol, prev; prev = NULL; // Look for string in the list of symbols. symbol = FindSymbol(string, &prev); if (symbol == NULL) { return; } // Update the refCount. symbol->refCount--; if (symbol->refCount != 0) { return; } // Remove the symbol from the list. if (prev != NULL) { prev->next = symbol->next; } else { gSymbolsHead = symbol->next; } // Free the symbol's memory. free(symbol); } #endif //========================================================================== // FindSymbol static SymbolPtr FindSymbol( char *string, SymbolPtr *prevSymbol ) { SymbolPtr symbol, prev; if (string == NULL) { return NULL; } symbol = gSymbolsHead; prev = NULL; while (symbol != NULL) { if (!strcmp(symbol->string, string)) { break; } prev = symbol; symbol = symbol->next; } if ((symbol != NULL) && (prevSymbol != NULL)) { *prevSymbol = prev; } return symbol; } bool XMLIsType(TagPtr dict, enum xmltype type) { if(!dict) { return (type == kTagTypeNone); } return (dict->type == type); } /*** Cast functions ***/ bool XMLIsArray(TagPtr entry) { return entry && (entry->type == kTagTypeArray); } TagPtr XMLCastArray(TagPtr dict) { if(!dict) { return NULL; } if(dict->type == kTagTypeArray) { return dict; } else { return NULL; } } bool XMLIsDict(TagPtr entry) { return entry && (entry->type == kTagTypeDict); } bool XMLIsData(TagPtr entry) { return entry && (entry->type == kTagTypeData); } TagPtr XMLCastDict(TagPtr dict) { if(!dict) { return NULL; } if(dict->type == kTagTypeDict) { return dict; } else { return NULL; } } bool XMLIsString(TagPtr entry) { return entry && ((entry->type == kTagTypeString) || (entry->type == kTagTypeKey)); } char *XMLCastString(TagPtr dict) { if(!dict) { return NULL; } if((dict->type == kTagTypeString) || (dict->type == kTagTypeKey)) { return dict->string; } return NULL; } char *XMLCastData(TagPtr dict, int* length) { if(!dict) { return NULL; } if((dict->type == kTagTypeData) || (dict->type == kTagTypeKey)) { *length = dict->offset; return dict->string; } *length = 0; return NULL; } long XMLCastStringOffset(TagPtr dict) { if(dict && ((dict->type == kTagTypeString) || (dict->type == kTagTypeKey))) { return dict->offset; } else { return -1; } } bool XMLIsBoolean(TagPtr entry) { return entry && ((entry->type == kTagTypeTrue) || (entry->type == kTagTypeFalse)); } bool XMLCastBoolean(TagPtr dict) { if(!dict) { return false; } if(dict->type == kTagTypeTrue) { return true; } return false; } bool XMLIsInteger(TagPtr entry) { return entry && (entry->type == kTagTypeInteger); } int XMLCastInteger(TagPtr dict) { if(!dict) { //printf("XMLCastInteger: null dict\n"); return 0; } if(dict->type == kTagTypeInteger) { return (int)(dict->string); } return 0; } bool XMLAddTagToDictionary(TagPtr dict, char *key, TagPtr value) { if (!dict || dict->type != kTagTypeDict) { return false; } TagPtr tmpTag; char* string; tmpTag = NewTag(); if (tmpTag == 0) { return false; } string = NewSymbol(key); if (string == 0) { XMLFreeTag(tmpTag); return false; } tmpTag->type = kTagTypeKey; tmpTag->string = string; tmpTag->tag = value; tmpTag->offset = 0; tmpTag->tagNext = 0; TagPtr tagList = dict->tag; if(!tagList) { // First tag dict->tag = tmpTag; return true; } while(tagList && tagList->tagNext) tagList = tagList->tagNext; if(tagList) { tagList->tagNext = tmpTag; return true; } XMLFreeTag(tmpTag); return false; }