ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/prefs.cpp
Revision: 1.18
Committed: 2009-07-23T19:19:14Z (15 years, 4 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.17: +3 -3 lines
Log Message:
BasiliskII side of changes to support .sheepvm bundles for SheepShaver

File Contents

# Content
1 /*
2 * prefs.cpp - Preferences handling
3 *
4 * Basilisk II (C) 1997-2008 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <ctype.h>
25
26 #include "sysdeps.h"
27 #include "sys.h"
28 #include "prefs.h"
29
30
31 // Prefs items are stored in a linked list of these nodes
32 struct prefs_node {
33 prefs_node *next;
34 const char *name;
35 prefs_type type;
36 void *data;
37 };
38
39 // List of prefs nodes
40 static prefs_node *the_prefs = NULL;
41
42 // Prototypes
43 static const prefs_desc *find_prefs_desc(const char *name);
44
45
46 /*
47 * Initialize preferences
48 */
49
50 void PrefsInit(const char *vmdir, int &argc, char **&argv)
51 {
52 // Set defaults
53 AddPrefsDefaults();
54 AddPlatformPrefsDefaults();
55
56 // Load preferences from settings file
57 LoadPrefs(vmdir);
58
59 // Override prefs with command line options
60 for (int i=1; i<argc; i++) {
61
62 // Options are of the form '--keyword'
63 const char *option = argv[i];
64 if (!option || strlen(option) < 3 || option[0] != '-' || option[1] != '-')
65 continue;
66 const char *keyword = option + 2;
67
68 // Find descriptor for keyword
69 const prefs_desc *d = find_prefs_desc(keyword);
70 if (d == NULL)
71 continue;
72 argv[i] = NULL;
73
74 // Get value
75 i++;
76 if (i >= argc) {
77 fprintf(stderr, "Option '%s' must be followed by a value\n", option);
78 continue;
79 }
80 const char *value = argv[i];
81 argv[i] = NULL;
82
83 // Add/replace prefs item
84 switch (d->type) {
85 case TYPE_STRING:
86 if (d->multiple)
87 PrefsAddString(keyword, value);
88 else
89 PrefsReplaceString(keyword, value);
90 break;
91
92 case TYPE_BOOLEAN: {
93 if (!strcmp(value, "true") || !strcmp(value, "on") || !strcmp(value, "yes"))
94 PrefsReplaceBool(keyword, true);
95 else if (!strcmp(value, "false") || !strcmp(value, "off") || !strcmp(value, "no"))
96 PrefsReplaceBool(keyword, false);
97 else
98 fprintf(stderr, "Value for option '%s' must be 'true' or 'false'\n", option);
99 break;
100 }
101
102 case TYPE_INT32:
103 PrefsReplaceInt32(keyword, atoi(value));
104 break;
105
106 default:
107 break;
108 }
109 }
110
111 // Remove processed arguments
112 for (int i=1; i<argc; i++) {
113 int k;
114 for (k=i; k<argc; k++)
115 if (argv[k] != NULL)
116 break;
117 if (k > i) {
118 k -= i;
119 for (int j=i+k; j<argc; j++)
120 argv[j-k] = argv[j];
121 argc -= k;
122 }
123 }
124
125 #ifdef SHEEPSHAVER
126 // System specific initialization
127 prefs_init();
128 #endif
129 }
130
131
132 /*
133 * Deinitialize preferences
134 */
135
136 void PrefsExit(void)
137 {
138 #ifdef SHEEPSHAVER
139 // System specific deinitialization
140 prefs_exit();
141 #endif
142
143 // Free prefs list
144 prefs_node *p = the_prefs, *next;
145 while (p) {
146 next = p->next;
147 free((void *)p->name);
148 free(p->data);
149 delete p;
150 p = next;
151 }
152 the_prefs = NULL;
153 }
154
155
156 /*
157 * Print preferences options help
158 */
159
160 static void print_options(const prefs_desc *list)
161 {
162 while (list->type != TYPE_END) {
163 if (list->help) {
164 const char *typestr, *defstr;
165 char numstr[32];
166 switch (list->type) {
167 case TYPE_STRING:
168 typestr = "STRING";
169 defstr = PrefsFindString(list->name);
170 if (defstr == NULL)
171 defstr = "none";
172 break;
173 case TYPE_BOOLEAN:
174 typestr = "BOOL";
175 if (PrefsFindBool(list->name))
176 defstr = "true";
177 else
178 defstr = "false";
179 break;
180 case TYPE_INT32:
181 typestr = "NUMBER";
182 sprintf(numstr, "%d", PrefsFindInt32(list->name));
183 defstr = numstr;
184 break;
185 default:
186 typestr = "<unknown>";
187 defstr = "none";
188 break;
189 }
190 printf(" --%s %s\n %s [default=%s]\n", list->name, typestr, list->help, defstr);
191 }
192 list++;
193 }
194 }
195
196 void PrefsPrintUsage(void)
197 {
198 printf("\nGeneral options:\n");
199 print_options(common_prefs_items);
200 printf("\nPlatform-specific options:\n");
201 print_options(platform_prefs_items);
202 printf("\nBoolean options are specified as '--OPTION true|on|yes' or\n'--OPTION false|off|no'.\n");
203 }
204
205
206 /*
207 * Find preferences descriptor by keyword
208 */
209
210 static const prefs_desc *find_prefs_desc(const char *name, const prefs_desc *list)
211 {
212 while (list->type != TYPE_ANY) {
213 if (strcmp(list->name, name) == 0)
214 return list;
215 list++;
216 }
217 return NULL;
218 }
219
220 static const prefs_desc *find_prefs_desc(const char *name)
221 {
222 const prefs_desc *d = find_prefs_desc(name, common_prefs_items);
223 if (d == NULL)
224 d = find_prefs_desc(name, platform_prefs_items);
225 return d;
226 }
227
228
229 /*
230 * Set prefs items
231 */
232
233 static void add_data(const char *name, prefs_type type, void *data, int size)
234 {
235 void *d = malloc(size);
236 if (d == NULL)
237 return;
238 memcpy(d, data, size);
239 prefs_node *p = new prefs_node;
240 p->next = 0;
241 p->name = strdup(name);
242 p->type = type;
243 p->data = d;
244 if (the_prefs) {
245 prefs_node *prev = the_prefs;
246 while (prev->next)
247 prev = prev->next;
248 prev->next = p;
249 } else
250 the_prefs = p;
251 }
252
253 void PrefsAddString(const char *name, const char *s)
254 {
255 add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
256 }
257
258 void PrefsAddBool(const char *name, bool b)
259 {
260 add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
261 }
262
263 void PrefsAddInt32(const char *name, int32 val)
264 {
265 add_data(name, TYPE_INT32, &val, sizeof(int32));
266 }
267
268
269 /*
270 * Replace prefs items
271 */
272
273 static prefs_node *find_node(const char *name, prefs_type type, int index = 0)
274 {
275 prefs_node *p = the_prefs;
276 int i = 0;
277 while (p) {
278 if ((type == TYPE_ANY || p->type == type) && !strcmp(p->name, name)) {
279 if (i == index)
280 return p;
281 else
282 i++;
283 }
284 p = p->next;
285 }
286 return NULL;
287 }
288
289 void PrefsReplaceString(const char *name, const char *s, int index)
290 {
291 prefs_node *p = find_node(name, TYPE_STRING, index);
292 if (p) {
293 free(p->data);
294 p->data = strdup(s);
295 } else
296 add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
297 }
298
299 void PrefsReplaceBool(const char *name, bool b)
300 {
301 prefs_node *p = find_node(name, TYPE_BOOLEAN);
302 if (p)
303 *(bool *)(p->data) = b;
304 else
305 add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
306 }
307
308 void PrefsReplaceInt32(const char *name, int32 val)
309 {
310 prefs_node *p = find_node(name, TYPE_INT32);
311 if (p)
312 *(int32 *)(p->data) = val;
313 else
314 add_data(name, TYPE_INT32, &val, sizeof(int32));
315 }
316
317
318 /*
319 * Get prefs items
320 */
321
322 const char *PrefsFindString(const char *name, int index)
323 {
324 prefs_node *p = find_node(name, TYPE_STRING, index);
325 if (p)
326 return (char *)(p->data);
327 else
328 return NULL;
329 }
330
331 bool PrefsFindBool(const char *name)
332 {
333 prefs_node *p = find_node(name, TYPE_BOOLEAN, 0);
334 if (p)
335 return *(bool *)(p->data);
336 else
337 return false;
338 }
339
340 int32 PrefsFindInt32(const char *name)
341 {
342 prefs_node *p = find_node(name, TYPE_INT32, 0);
343 if (p)
344 return *(int32 *)(p->data);
345 else
346 return 0;
347 }
348
349
350 /*
351 * Remove prefs items
352 */
353
354 void PrefsRemoveItem(const char *name, int index)
355 {
356 prefs_node *p = find_node(name, TYPE_ANY, index);
357 if (p) {
358 free((void *)p->name);
359 free(p->data);
360 prefs_node *q = the_prefs;
361 if (q == p) {
362 the_prefs = NULL;
363 delete p;
364 return;
365 }
366 while (q) {
367 if (q->next == p) {
368 q->next = p->next;
369 delete p;
370 return;
371 }
372 q = q->next;
373 }
374 }
375 }
376
377
378 /*
379 * Load prefs from stream (utility function for LoadPrefs() implementation)
380 */
381
382 void LoadPrefsFromStream(FILE *f)
383 {
384 char line[256];
385 while(fgets(line, 255, f)) {
386 // Read line
387 int len = strlen(line);
388 if (len == 0)
389 continue;
390 line[len-1] = 0;
391
392 // Comments begin with "#" or ";"
393 if (line[0] == '#' || line[0] == ';')
394 continue;
395
396 // Terminate string after keyword
397 char *p = line;
398 while (!isspace(*p)) p++;
399 *p++ = 0;
400
401 // Skip whitespace until value
402 while (isspace(*p)) p++;
403 char *keyword = line;
404 char *value = p;
405 int32 i = atol(value);
406
407 // Look for keyword first in prefs item list
408 const prefs_desc *desc = find_prefs_desc(keyword);
409 if (desc == NULL) {
410 printf("WARNING: Unknown preferences keyword '%s'\n", keyword);
411 continue;
412 }
413
414 // Add item to prefs
415 switch (desc->type) {
416 case TYPE_STRING:
417 if (desc->multiple)
418 PrefsAddString(keyword, value);
419 else
420 PrefsReplaceString(keyword, value);
421 break;
422 case TYPE_BOOLEAN:
423 PrefsReplaceBool(keyword, !strcmp(value, "true"));
424 break;
425 case TYPE_INT32:
426 PrefsReplaceInt32(keyword, i);
427 break;
428 default:
429 break;
430 }
431 }
432 }
433
434
435 /*
436 * Save settings to stream (utility function for SavePrefs() implementation)
437 */
438
439 static void write_prefs(FILE *f, const prefs_desc *list)
440 {
441 while (list->type != TYPE_ANY) {
442 switch (list->type) {
443 case TYPE_STRING: {
444 int index = 0;
445 const char *str;
446 while ((str = PrefsFindString(list->name, index++)) != NULL)
447 fprintf(f, "%s %s\n", list->name, str);
448 break;
449 }
450 case TYPE_BOOLEAN:
451 fprintf(f, "%s %s\n", list->name, PrefsFindBool(list->name) ? "true" : "false");
452 break;
453 case TYPE_INT32:
454 fprintf(f, "%s %d\n", list->name, PrefsFindInt32(list->name));
455 break;
456 default:
457 break;
458 }
459 list++;
460 }
461 }
462
463 void SavePrefsToStream(FILE *f)
464 {
465 write_prefs(f, common_prefs_items);
466 write_prefs(f, platform_prefs_items);
467 }