]> git.saurik.com Git - apple/boot.git/blob - gen/libsaio/stringTable.c
boot-80.1.tar.gz
[apple/boot.git] / gen / libsaio / stringTable.c
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.1 (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 * Copyright 1993 NeXT, Inc.
26 * All rights reserved.
27 */
28
29 #import "libsaio.h"
30 #import "kernBootStruct.h"
31 #import <driverkit/configTablePrivate.h>
32
33 extern KERNBOOTSTRUCT *kernBootStruct;
34 extern char *Language;
35 extern char *LoadableFamilies;
36
37 static void eatThru(char val, char **table_p);
38
39 static inline int isspace(char c)
40 {
41 return (c == ' ' || c == '\t');
42 }
43
44 /*
45 * Compare a string to a key with quoted characters
46 */
47 static inline int
48 keyncmp(char *str, char *key, int n)
49 {
50 int c;
51 while (n--) {
52 c = *key++;
53 if (c == '\\') {
54 switch(c = *key++) {
55 case 'n':
56 c = '\n';
57 break;
58 case 'r':
59 c = '\r';
60 break;
61 case 't':
62 c = '\t';
63 break;
64 default:
65 break;
66 }
67 } else if (c == '\"') {
68 /* Premature end of key */
69 return 1;
70 }
71 if (c != *str++) {
72 return 1;
73 }
74 }
75 return 0;
76 }
77
78 static void eatThru(char val, char **table_p)
79 {
80 register char *table = *table_p;
81 register BOOL found = NO;
82
83 while (*table && !found)
84 {
85 if (*table == '\\') table += 2;
86 else
87 {
88 if (*table == val) found = YES;
89 table++;
90 }
91 }
92 *table_p = table;
93 }
94
95 char *
96 newStringFromList(
97 char **list,
98 int *size
99 )
100 {
101 char *begin = *list, *end;
102 char *newstr;
103 int newsize = *size;
104
105 while (*begin && newsize && isspace(*begin)) {
106 begin++;
107 newsize--;
108 }
109 end = begin;
110 while (*end && newsize && !isspace(*end)) {
111 end++;
112 newsize--;
113 }
114 if (begin == end)
115 return 0;
116 newstr = malloc(end - begin + 1);
117 strncpy(newstr, begin, end - begin);
118 *list = end;
119 *size = newsize;
120 return newstr;
121 }
122
123 /*
124 * compress == compress escaped characters to one character
125 */
126 int stringLength(char *table, int compress)
127 {
128 int ret = 0;
129
130 while (*table)
131 {
132 if (*table == '\\')
133 {
134 table += 2;
135 ret += 1 + (compress ? 0 : 1);
136 }
137 else
138 {
139 if (*table == '\"') return ret;
140 ret++;
141 table++;
142 }
143 }
144 return ret;
145 }
146
147
148 // looks in table for strings of format << "key" = "value"; >>
149 // or << "key"; >>
150 BOOL getValueForStringTableKey(char *table, char *key, char **val, int *size)
151 {
152 int keyLength;
153 char *tableKey;
154
155 do
156 {
157 eatThru('\"',&table);
158 tableKey = table;
159 keyLength = strlen(key);
160 if (keyLength &&
161 (stringLength(table,1) == keyLength) &&
162 (keyncmp(key, table, keyLength) == 0))
163 {
164 int c;
165
166 /* found the key; now look for either
167 * '=' or ';'
168 */
169 while (c = *table) {
170 ++table;
171 if (c == '\\') {
172 ++table;
173 continue;
174 } else if (c == '=' || c == ';') {
175 break;
176 }
177 }
178 if (c == ';') {
179 table = tableKey;
180 } else {
181 eatThru('\"',&table);
182 }
183 *val = table;
184 *size = stringLength(table,0);
185 return YES;
186 }
187
188 eatThru(';',&table);
189
190 } while (*table);
191
192 return NO;
193 }
194
195
196 /*
197 * Returns a new malloc'ed string if one is found
198 * in the string table matching 'key'. Also translates
199 * \n escapes in the string.
200 */
201 char *newStringForStringTableKey(
202 char *table,
203 char *key
204 )
205 {
206 char *val, *newstr, *p;
207 int size;
208
209 if (getValueForStringTableKey(table, key, &val, &size)) {
210 newstr = malloc(size+1);
211 for (p = newstr; size; size--, p++, val++) {
212 if ((*p = *val) == '\\') {
213 switch (*++val) {
214 case 'r':
215 *p = '\r';
216 break;
217 case 'n':
218 *p = '\n';
219 break;
220 case 't':
221 *p = '\t';
222 break;
223 default:
224 *p = *val;
225 break;
226 }
227 size--;
228 }
229 }
230 *p = '\0';
231 return newstr;
232 } else {
233 return 0;
234 }
235 }
236
237 char *
238 newStringForKey(char *key)
239 {
240 char *val, *newstr;
241 int size;
242
243 if (getValueForKey(key, &val, &size) && size) {
244 newstr = malloc(size + 1);
245 strncpy(newstr, val, size);
246 return newstr;
247 } else {
248 return 0;
249 }
250 }
251
252 /* parse a command line
253 * in the form: [<argument> ...] [<option>=<value> ...]
254 * both <option> and <value> must be either composed of
255 * non-whitespace characters, or enclosed in quotes.
256 */
257
258 static char *getToken(char *line, char **begin, int *len)
259 {
260 if (*line == '\"') {
261 *begin = ++line;
262 while (*line && *line != '\"')
263 line++;
264 *len = line++ - *begin;
265 } else {
266 *begin = line;
267 while (*line && !isspace(*line) && *line != '=')
268 line++;
269 *len = line - *begin;
270 }
271 return line;
272 }
273
274 BOOL getValueForBootKey(char *line, char *match, char **matchval, int *len)
275 {
276 char *key, *value;
277 int key_len, value_len;
278
279 while (*line) {
280 /* look for keyword or argument */
281 while (isspace(*line)) line++;
282
283 /* now look for '=' or whitespace */
284 line = getToken(line, &key, &key_len);
285 /* line now points to '=' or space */
286 if (!isspace(*line++)) {
287 line = getToken(line, &value, &value_len);
288 if ((strlen(match) == key_len)
289 && strncmp(match, key, key_len) == 0) {
290 *matchval = value;
291 *len = value_len;
292 return YES;
293 }
294 }
295 }
296 return NO;
297 }
298
299 BOOL getBoolForKey(
300 char *key
301 )
302 {
303 char *val;
304 int size;
305
306 if (getValueForKey(key, &val, &size) && (size >= 1) &&
307 val[0] == 'Y' || val[0] == 'y')
308 return YES;
309 return NO;
310 }
311
312 BOOL getValueForKey(
313 char *key,
314 char **val,
315 int *size
316 )
317 {
318 if (getValueForBootKey(kernBootStruct->bootString, key, val, size))
319 return YES;
320 else if (getValueForStringTableKey(kernBootStruct->config, key, val, size))
321 return YES;
322
323 return NO;
324 }
325
326 #define LOCALIZABLE \
327 "/usr/Devices/%s.config/%s.lproj/Localizable.strings"
328
329 char *
330 loadLocalizableStrings(
331 char *name
332 )
333 {
334 char buf[256], *config;
335 register int count, fd;
336
337 sprintf(buf, LOCALIZABLE, name, Language);
338 if ((fd = open(buf,0)) < 0) {
339 sprintf(buf, LOCALIZABLE, name, "English");
340 if ((fd = open(buf,0)) < 0)
341 return 0;
342 }
343 count = file_size(fd);
344 config = malloc(count);
345 count = read(fd, config, count);
346 close(fd);
347 if (count <= 0) {
348 free(config);
349 return 0;
350 }
351 return config;
352 }
353
354 char *
355 bundleLongName(
356 char *bundleName
357 )
358 {
359 char *table, *name, *val;
360 int size;
361
362 if ((table = loadLocalizableStrings(bundleName)) != 0 &&
363 getValueForStringTableKey(table,"Long Name", &val, &size) == YES) {
364 name = malloc(size+1);
365 strncpy(name, val, size);
366 free(table);
367 } else {
368 name = newString(bundleName);
369 }
370 return name;
371 }
372
373 int sysConfigValid;
374
375
376 /*
377 * Returns 0 if file loaded OK,
378 * -1 if file was not loaded
379 * Does not print error messages.
380 * Returns pointer to table in memory in *table.
381 */
382 int
383 loadConfigFile( char *configFile, char **table, int allocTable)
384 {
385 char *configPtr = kernBootStruct->configEnd;
386 int fd, count;
387
388 /* Read config file into memory */
389 if ((fd = open(configFile, 0)) >= 0)
390 {
391 if (allocTable) {
392 configPtr = malloc(file_size(fd)+2);
393 } else {
394 if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) {
395 error("No room in memory for config file %s\n",configFile);
396 close(fd);
397 return -1;
398 }
399 localPrintf("Reading config: %s\n",configFile);
400 }
401 if (table) *table = configPtr;
402 count = read(fd, configPtr, IO_CONFIG_DATA_SIZE);
403 close(fd);
404
405 configPtr += count;
406 *configPtr++ = 0;
407 *configPtr = 0;
408 if (!allocTable)
409 kernBootStruct->configEnd = configPtr;
410
411 return 0;
412 } else {
413 return -1;
414 }
415 }
416
417 /* Returns 0 if requested config files were loaded,
418 * 1 if default files were loaded,
419 * -1 if no files were loaded.
420 * Prints error message if files cannot be loaded.
421 */
422
423 int
424 loadConfigDir(
425 char *bundleName, // bundle directory name (e.g. "System.config")
426 int useDefault, // use Default.table instead of instance tables
427 char **table, // returns pointer to config table
428 int allocTable // malloc the table and return in *table
429 )
430 {
431 char *buf;
432 int i, ret;
433
434 buf = malloc(256);
435 ret = 0;
436
437 // load up to 99 instance tables
438 for (i=0; i < 99; i++) {
439 sprintf(buf, "%s%s.config/Instance%d.table", IO_CONFIG_DIR,
440 bundleName, i);
441 if (useDefault || (loadConfigFile(buf, table, allocTable) != 0)) {
442 if (i == 0) {
443 // couldn't load first instance table;
444 // try the default table
445 sprintf(buf, "%s%s.config/%s", IO_CONFIG_DIR, bundleName,
446 IO_DEFAULT_TABLE_FILENAME);
447 if (loadConfigFile(buf, table, allocTable) == 0) {
448 ret = 1;
449 } else {
450 if (!allocTable)
451 error("Config file \"%s\" not found\n", buf);
452 ret = -1;
453 }
454 }
455 // we must be done.
456 break;
457 }
458 }
459 free(buf);
460 return ret;
461 }
462
463
464 #define SYSTEM_DEFAULT_FILE \
465 IO_SYSTEM_CONFIG_DIR IO_DEFAULT_TABLE_FILENAME
466 #define SYSTEM_CONFIG "System"
467 #define LP '('
468 #define RP ')'
469
470 /* Returns 0 if requested config files were loaded,
471 * 1 if default files were loaded,
472 * -1 if no files were loaded.
473 * Prints error message if files cannot be loaded.
474 */
475 int
476 loadSystemConfig(
477 char *which,
478 int size
479 )
480 {
481 char *buf, *bp, *cp;
482 int ret, len, doDefault=0;
483
484 buf = bp = malloc(256);
485 if (which && size)
486 {
487 for(cp = which, len = size; len && *cp && *cp != LP; cp++, len--) ;
488 if (*cp == LP) {
489 while (len-- && *cp && *cp++ != RP) ;
490 /* cp now points past device */
491 strncpy(buf,which,cp - which);
492 bp += cp - which;
493 } else {
494 cp = which;
495 len = size;
496 }
497 if (*cp != '/') {
498 strcpy(bp, IO_SYSTEM_CONFIG_DIR);
499 strncat(bp, cp, len);
500 if (strncmp(cp + len - strlen(IO_TABLE_EXTENSION),
501 IO_TABLE_EXTENSION, strlen(IO_TABLE_EXTENSION)) != 0)
502 strcat(bp, IO_TABLE_EXTENSION);
503 } else {
504 strncpy(bp, cp, len);
505 bp[size] = '\0';
506 }
507 if (strcmp(bp, SYSTEM_DEFAULT_FILE) == 0)
508 doDefault = 1;
509 ret = loadConfigFile(bp = buf, 0, 0);
510 } else {
511 ret = loadConfigDir((bp = SYSTEM_CONFIG), 0, 0, 0);
512 }
513 if (ret < 0) {
514 error("System config file '%s' not found\n", bp);
515 } else
516 sysConfigValid = 1;
517 free(buf);
518 return (ret < 0 ? ret : doDefault);
519 }
520
521
522 int
523 loadOtherConfigs(
524 int useDefault
525 )
526 {
527 char *val, *table;
528 int count;
529 char *string;
530 int fd, ret;
531
532 if (getValueForKey( "Boot Drivers", &val, &count))
533 {
534 while (string = newStringFromList(&val, &count)) {
535 ret = loadConfigDir(string, useDefault, &table, 0);
536 if (ret >= 0) {
537 if ((fd = openDriverReloc(string)) >= 0) {
538 localPrintf("Loading binary for %s\n",string);
539 if (loadDriver(string, fd) < 0)
540 error("Error loading driver %s\n",string);
541 close(fd);
542 }
543 driverWasLoaded(string, table);
544 free(string);
545 } else {
546 driverIsMissing(string);
547 }
548 if (ret == 1)
549 useDefault = 1; // use defaults from now on
550 }
551 } else {
552 error("Warning: No active drivers specified in system config\n");
553 }
554
555 kernBootStruct->first_addr0 =
556 (int)kernBootStruct->configEnd + 1024;
557 return 0;
558 }
559
560
561
562
563
564
565
566
567
568
569
570