|
|
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.