|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.0 (the 'License'). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The 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: NXStringTable.m ! 26: Copyright 1990 NeXT, Inc. ! 27: Written by Bertrand Serlet, Jan 89 ! 28: Responsibility: Bertrand Serlet ! 29: */ ! 30: ! 31: #ifndef KERNEL ! 32: #ifdef SHLIB ! 33: #import "shlib.h" ! 34: #endif SHLIB ! 35: ! 36: #import <stdlib.h> ! 37: #import <stdio.h> ! 38: #import <string.h> ! 39: #import "NXStringTable.h" ! 40: ! 41: @implementation NXStringTable ! 42: + new { ! 43: return [self newKeyDesc:"%" valueDesc:"*"]; ! 44: } ! 45: ! 46: - init { ! 47: return [self initKeyDesc:"%" valueDesc:"*"]; ! 48: } ! 49: ! 50: static void noFree (void *item) {} ! 51: static void freeString(void *string) { free(string);} ! 52: - free { ! 53: [self freeKeys:noFree values:freeString]; ! 54: return [super free]; ! 55: } ! 56: ! 57: - (const char *)valueForStringKey:(const char *)aString { ! 58: return (const char *) [super valueForKey:NXUniqueString(aString)]; ! 59: } ! 60: ! 61: static int skipSpace(NXStream *stream) { ! 62: /* return first significant character */ ! 63: int ch; ! 64: while ((ch = NXGetc(stream)) != EOF) { ! 65: if ((ch != ' ') && (ch != '\n') && (ch != '\t')) return ch; ! 66: } ! 67: return ch; ! 68: } ! 69: ! 70: static int parseWord(NXStream *stream, char *word) { ! 71: /* return '"', that is read, or EOF */ ! 72: int length = 0; ! 73: int ch; ! 74: while (((ch = NXGetc(stream)) != EOF) && (ch != '"') && (length < MAX_NXSTRINGTABLE_LENGTH)) { ! 75: word[length++] = ch; ! 76: if (ch == '\\') { ! 77: switch (ch = NXGetc(stream)) { ! 78: case 'a': word[length-1] = '\a'; break; ! 79: case 'b': word[length-1] = '\b'; break; ! 80: case 'f': word[length-1] = '\f'; break; ! 81: case 'n': word[length-1] = '\n'; break; ! 82: case 'r': word[length-1] = '\r'; break; ! 83: case 't': word[length-1] = '\t'; break; ! 84: case 'v': word[length-1] = '\v'; break; ! 85: case '"': word[length-1] = '\"'; break; ! 86: case EOF: break; ! 87: case '\'': word[length-1] = '\''; break; ! 88: case '?': word[length-1] = '?'; break; ! 89: case '\\': word[length-1] = '\\'; break; ! 90: case 'x': ! 91: { ! 92: unsigned char c2 = 0; ! 93: ! 94: while (1) ! 95: { ! 96: ch = NXGetc (stream); ! 97: ! 98: if ('0' <= ch && ch <= '7') ! 99: c2 = (16 * c2) + (ch - '0'); ! 100: else if ('a' <= ch && ch <= 'f') ! 101: c2 = (16 * c2) + (ch - 'a' + 0xa); ! 102: else if ('A' <= ch && ch <= 'F') ! 103: c2 = (16 * c2) + (ch - 'A' + 0xa); ! 104: else ! 105: { ! 106: NXUngetc (stream); ! 107: break; ! 108: } ! 109: } ! 110: ! 111: word[length-1] = c2; ! 112: break; ! 113: } ! 114: ! 115: default: ! 116: if ('0' <= ch && ch <= '7') ! 117: { ! 118: unsigned char c2 = ch - '0'; ! 119: unsigned int i; ! 120: ! 121: for (i = 0; i < 2; i++) ! 122: { ! 123: ch = NXGetc (stream); ! 124: ! 125: if ('0' <= ch && ch <= '7') ! 126: c2 = (8 * c2) + (ch - '0'); ! 127: else ! 128: { ! 129: NXUngetc (stream); ! 130: break; ! 131: } ! 132: } ! 133: ! 134: word[length-1] = c2; ! 135: } ! 136: else ! 137: /* unknown escape sequence */ ! 138: word[length-1] = ch; ! 139: ! 140: break; ! 141: } ! 142: } ! 143: } ! 144: word[length] = 0; ! 145: return ch; ! 146: } ! 147: ! 148: static void writeWord(NXStream *stream, const char *word) { ! 149: int ch; ! 150: NXPutc(stream, '"'); ! 151: while ((ch = *(word++))) { ! 152: switch (ch) { ! 153: case '\a': NXPutc(stream, '\\'); NXPutc(stream, 'a'); break; ! 154: case '\b': NXPutc(stream, '\\'); NXPutc(stream, 'b'); break; ! 155: case '\f': NXPutc(stream, '\\'); NXPutc(stream, 'f'); break; ! 156: case '\n': NXPutc(stream, '\\'); NXPutc(stream, 'n'); break; ! 157: case '\r': NXPutc(stream, '\\'); NXPutc(stream, 'r'); break; ! 158: case '\t': NXPutc(stream, '\\'); NXPutc(stream, 't'); break; ! 159: case '\v': NXPutc(stream, '\\'); NXPutc(stream, 'v'); break; ! 160: case '\"': NXPutc(stream, '\\'); NXPutc(stream, '"'); break; ! 161: case '\\': NXPutc(stream, '\\'); NXPutc(stream, '\\'); break; ! 162: default: NXPutc(stream, ch); ! 163: } ! 164: } ! 165: NXPutc(stream, '"'); ! 166: } ! 167: ! 168: ! 169: - readFromStream:(NXStream *)stream { ! 170: int ch; ! 171: NXZone *zone = [self zone]; ! 172: if (!stream) return nil; ! 173: while ((ch = skipSpace(stream)) != EOF) { ! 174: switch (ch) { ! 175: case '/': ! 176: ch = NXGetc(stream); ! 177: if (ch != '*') goto nope; ! 178: while ((ch = NXGetc(stream)) != EOF) { ! 179: if (ch == '*') { ! 180: ch = NXGetc(stream); ! 181: if (ch == '/') break; ! 182: NXUngetc(stream); ! 183: } ! 184: } ! 185: if (ch == EOF) goto nope; ! 186: break; ! 187: case '"': { ! 188: char key[MAX_NXSTRINGTABLE_LENGTH+1]; ! 189: char value[MAX_NXSTRINGTABLE_LENGTH+1]; ! 190: ch = parseWord(stream, key); ! 191: if (ch != '"') goto nope; ! 192: ch = skipSpace(stream); ! 193: if (ch == '=') { ! 194: ch = skipSpace(stream); ! 195: if (ch != '"') goto nope; ! 196: ch = parseWord(stream, value); ! 197: if (ch != '"') goto nope; ! 198: ch = skipSpace(stream); ! 199: } else { ! 200: strcpy(value, key); ! 201: } ! 202: if (ch != ';') goto nope; ! 203: free([self insertKey:NXUniqueString(key) ! 204: value:NXCopyStringBufferFromZone(value, zone)]); ! 205: break; ! 206: } ! 207: default: goto nope; ! 208: } ! 209: } ! 210: return self; ! 211: nope: ! 212: { ! 213: extern void _NXLogError(const char *format, ...); ! 214: if (ch == EOF) ! 215: _NXLogError ("NXStringTable: parse error before end of stream"); ! 216: else ! 217: _NXLogError ("NXStringTable: parse error before '%c'", ch); ! 218: return nil; ! 219: } ! 220: } ! 221: ! 222: - readFromFile:(const char *)fileName { ! 223: NXStream *stream = NXMapFile(fileName, NX_READONLY); ! 224: id retval = [self readFromStream:stream]; ! 225: if (stream) NXCloseMemory(stream, NX_FREEBUFFER); ! 226: return retval; ! 227: } ! 228: ! 229: + newFromStream:(NXStream *)stream { ! 230: id table; ! 231: if (! stream) return nil; ! 232: table = [self new]; ! 233: if (![table readFromStream:stream]) ! 234: table = [table free]; ! 235: return table; ! 236: } ! 237: ! 238: + newFromFile:(const char *)fileName { ! 239: id table; ! 240: table = [self new]; ! 241: if (![table readFromFile:fileName]) ! 242: table = [table free]; ! 243: return table; ! 244: } ! 245: ! 246: - writeToStream:(NXStream *)stream { ! 247: NXHashState state = [self initState]; ! 248: NXAtom key; ! 249: const char *value; ! 250: while ([self nextState:&state key:(const void **)&key value:(void **)&value]) { ! 251: writeWord(stream, key); ! 252: if (strcmp(key, value)) { ! 253: NXPrintf(stream, "\t= "); ! 254: writeWord(stream, value); ! 255: } ! 256: NXPrintf(stream, ";\n"); ! 257: } ! 258: return self; ! 259: } ! 260: ! 261: - writeToFile:(const char *)fileName { ! 262: NXStream *stream = NXOpenMemory(NULL, 0, NX_WRITEONLY); ! 263: int res; ! 264: [self writeToStream:stream]; ! 265: res = NXSaveToFile(stream, fileName); ! 266: NXCloseMemory(stream, NX_FREEBUFFER); ! 267: return (res) ? nil : self; ! 268: } ! 269: ! 270: @end ! 271: #endif /* KERNEL */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.