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