ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/prefs.cpp
Revision: 1.11
Committed: 2001-04-01T12:11:42Z (23 years, 1 month ago) by cebix
Branch: MAIN
Changes since 1.10: +94 -30 lines
Log Message:
- added help for command line options
- PrefsInit() removes all processed options

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * prefs.cpp - Preferences handling
3     *
4 cebix 1.10 * Basilisk II (C) 1997-2001 Christian Bauer
5 cebix 1.1 *
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 cebix 1.8 // Prefs items are stored in a linked list of these nodes
32 cebix 1.1 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 cebix 1.9 static prefs_node *the_prefs = NULL;
41    
42     // Prototypes
43     static const prefs_desc *find_prefs_desc(const char *name);
44 cebix 1.1
45    
46     /*
47     * Initialize preferences
48     */
49    
50 cebix 1.11 void PrefsInit(int &argc, char **&argv)
51 cebix 1.1 {
52     // Set defaults
53 cebix 1.8 AddPrefsDefaults();
54 cebix 1.1 AddPlatformPrefsDefaults();
55    
56     // Load preferences from settings file
57     LoadPrefs();
58 cebix 1.9
59 cebix 1.11 // 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 (strlen(option) < 3 || option[0] != '-' || option[1] != '-')
65 cebix 1.9 continue;
66 cebix 1.11 const char *keyword = option + 2;
67    
68     // Find descriptor for keyword
69 cebix 1.9 const prefs_desc *d = find_prefs_desc(keyword);
70 cebix 1.11 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 cebix 1.9 continue;
79     }
80 cebix 1.11 const char *value = argv[i];
81     argv[i] = NULL;
82 cebix 1.9
83     // Add/replace prefs item
84     switch (d->type) {
85     case TYPE_STRING:
86     if (d->multiple)
87 cebix 1.11 PrefsAddString(keyword, value);
88 cebix 1.9 else
89 cebix 1.11 PrefsReplaceString(keyword, value);
90 cebix 1.9 break;
91    
92 cebix 1.11 case TYPE_BOOLEAN: {
93     if (!strcmp(value, "true") || !strcmp(value, "on") || !strcmp(value, "yes"))
94 cebix 1.9 PrefsReplaceBool(keyword, true);
95 cebix 1.11 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 cebix 1.9 break;
100 cebix 1.11 }
101 cebix 1.9
102     case TYPE_INT32:
103 cebix 1.11 PrefsReplaceInt32(keyword, atoi(value));
104 cebix 1.9 break;
105    
106     default:
107     break;
108     }
109     }
110 cebix 1.11
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 cebix 1.1 }
125    
126    
127     /*
128     * Deinitialize preferences
129     */
130    
131     void PrefsExit(void)
132     {
133     // Free prefs list
134     prefs_node *p = the_prefs, *next;
135     while (p) {
136     next = p->next;
137     free((void *)p->name);
138     free(p->data);
139     delete p;
140     p = next;
141     }
142 cebix 1.11 }
143    
144    
145     /*
146     * Print preferences options help
147     */
148    
149     static void print_options(const prefs_desc *list)
150     {
151     while (list->type != TYPE_END) {
152     if (list->help) {
153     const char *typestr, *defstr;
154     char numstr[32];
155     switch (list->type) {
156     case TYPE_STRING:
157     typestr = "STRING";
158     defstr = PrefsFindString(list->name);
159     if (defstr == NULL)
160     defstr = "none";
161     break;
162     case TYPE_BOOLEAN:
163     typestr = "BOOL";
164     if (PrefsFindBool(list->name))
165     defstr = "true";
166     else
167     defstr = "false";
168     break;
169     case TYPE_INT32:
170     typestr = "NUMBER";
171     sprintf(numstr, "%d", PrefsFindInt32(list->name));
172     defstr = numstr;
173     break;
174     default:
175     typestr = "<unknown>";
176     defstr = "none";
177     break;
178     }
179     printf(" --%s %s\n %s [default=%s]\n", list->name, typestr, list->help, defstr);
180     }
181     list++;
182     }
183     }
184    
185     void PrefsPrintUsage(void)
186     {
187     printf("\nGeneral options:\n");
188     print_options(common_prefs_items);
189     printf("\nPlatform-specific options:\n");
190     print_options(platform_prefs_items);
191     printf("\nBoolean options are specified as '--OPTION true|on|yes' or\n'--OPTION false|off|no'.\n");
192 cebix 1.1 }
193    
194    
195     /*
196     * Find preferences descriptor by keyword
197     */
198    
199     static const prefs_desc *find_prefs_desc(const char *name, const prefs_desc *list)
200     {
201     while (list->type != TYPE_ANY) {
202     if (strcmp(list->name, name) == 0)
203     return list;
204     list++;
205     }
206     return NULL;
207     }
208    
209 cebix 1.9 static const prefs_desc *find_prefs_desc(const char *name)
210     {
211     const prefs_desc *d = find_prefs_desc(name, common_prefs_items);
212     if (d == NULL)
213     d = find_prefs_desc(name, platform_prefs_items);
214     return d;
215     }
216    
217 cebix 1.1
218     /*
219     * Set prefs items
220     */
221    
222     static void add_data(const char *name, prefs_type type, void *data, int size)
223     {
224     void *d = malloc(size);
225     if (d == NULL)
226     return;
227     memcpy(d, data, size);
228     prefs_node *p = new prefs_node;
229     p->next = 0;
230     p->name = strdup(name);
231     p->type = type;
232     p->data = d;
233     if (the_prefs) {
234     prefs_node *prev = the_prefs;
235     while (prev->next)
236     prev = prev->next;
237     prev->next = p;
238     } else
239     the_prefs = p;
240     }
241    
242     void PrefsAddString(const char *name, const char *s)
243     {
244     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
245     }
246    
247     void PrefsAddBool(const char *name, bool b)
248     {
249     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
250     }
251    
252     void PrefsAddInt32(const char *name, int32 val)
253     {
254     add_data(name, TYPE_INT32, &val, sizeof(int32));
255     }
256    
257    
258     /*
259     * Replace prefs items
260     */
261    
262     static prefs_node *find_node(const char *name, prefs_type type, int index = 0)
263     {
264     prefs_node *p = the_prefs;
265     int i = 0;
266     while (p) {
267     if ((type == TYPE_ANY || p->type == type) && !strcmp(p->name, name)) {
268     if (i == index)
269     return p;
270     else
271     i++;
272     }
273     p = p->next;
274     }
275     return NULL;
276     }
277    
278     void PrefsReplaceString(const char *name, const char *s, int index)
279     {
280     prefs_node *p = find_node(name, TYPE_STRING, index);
281     if (p) {
282     free(p->data);
283     p->data = strdup(s);
284     } else
285     add_data(name, TYPE_STRING, (void *)s, strlen(s) + 1);
286     }
287    
288     void PrefsReplaceBool(const char *name, bool b)
289     {
290     prefs_node *p = find_node(name, TYPE_BOOLEAN);
291     if (p)
292     *(bool *)(p->data) = b;
293     else
294     add_data(name, TYPE_BOOLEAN, &b, sizeof(bool));
295     }
296    
297     void PrefsReplaceInt32(const char *name, int32 val)
298     {
299     prefs_node *p = find_node(name, TYPE_INT32);
300     if (p)
301     *(int32 *)(p->data) = val;
302     else
303     add_data(name, TYPE_INT32, &val, sizeof(int32));
304     }
305    
306    
307     /*
308     * Get prefs items
309     */
310    
311     const char *PrefsFindString(const char *name, int index)
312     {
313     prefs_node *p = find_node(name, TYPE_STRING, index);
314     if (p)
315     return (char *)(p->data);
316     else
317     return NULL;
318     }
319    
320     bool PrefsFindBool(const char *name)
321     {
322     prefs_node *p = find_node(name, TYPE_BOOLEAN, 0);
323     if (p)
324     return *(bool *)(p->data);
325     else
326     return false;
327     }
328    
329     int32 PrefsFindInt32(const char *name)
330     {
331     prefs_node *p = find_node(name, TYPE_INT32, 0);
332     if (p)
333     return *(int32 *)(p->data);
334     else
335     return 0;
336     }
337    
338    
339     /*
340     * Remove prefs items
341     */
342    
343     void PrefsRemoveItem(const char *name, int index)
344     {
345     prefs_node *p = find_node(name, TYPE_ANY, index);
346     if (p) {
347     free((void *)p->name);
348     free(p->data);
349     prefs_node *q = the_prefs;
350     if (q == p) {
351     the_prefs = NULL;
352     delete p;
353     return;
354     }
355     while (q) {
356     if (q->next == p) {
357     q->next = p->next;
358     delete p;
359     return;
360     }
361     q = q->next;
362     }
363     }
364     }
365    
366    
367     /*
368     * Load prefs from stream (utility function for LoadPrefs() implementation)
369     */
370    
371     void LoadPrefsFromStream(FILE *f)
372     {
373     char line[256];
374     while(fgets(line, 255, f)) {
375     // Read line
376     int len = strlen(line);
377     if (len == 0)
378     continue;
379     line[len-1] = 0;
380    
381     // Comments begin with "#" or ";"
382     if (line[0] == '#' || line[0] == ';')
383     continue;
384    
385     // Terminate string after keyword
386     char *p = line;
387     while (!isspace(*p)) p++;
388     *p++ = 0;
389    
390     // Skip whitespace until value
391     while (isspace(*p)) p++;
392     char *keyword = line;
393     char *value = p;
394     int32 i = atol(value);
395    
396 cebix 1.9 // Look for keyword first in prefs item list
397     const prefs_desc *desc = find_prefs_desc(keyword);
398 cebix 1.1 if (desc == NULL) {
399     printf("WARNING: Unknown preferences keyword '%s'\n", keyword);
400     continue;
401     }
402    
403     // Add item to prefs
404     switch (desc->type) {
405     case TYPE_STRING:
406     if (desc->multiple)
407     PrefsAddString(keyword, value);
408     else
409     PrefsReplaceString(keyword, value);
410     break;
411     case TYPE_BOOLEAN:
412     PrefsReplaceBool(keyword, !strcmp(value, "true"));
413     break;
414     case TYPE_INT32:
415     PrefsReplaceInt32(keyword, i);
416     break;
417     default:
418     break;
419     }
420     }
421     }
422    
423    
424     /*
425     * Save settings to stream (utility function for SavePrefs() implementation)
426     */
427    
428     static void write_prefs(FILE *f, const prefs_desc *list)
429     {
430     while (list->type != TYPE_ANY) {
431     switch (list->type) {
432     case TYPE_STRING: {
433     int index = 0;
434     const char *str;
435     while ((str = PrefsFindString(list->name, index++)) != NULL)
436     fprintf(f, "%s %s\n", list->name, str);
437     break;
438     }
439     case TYPE_BOOLEAN:
440     fprintf(f, "%s %s\n", list->name, PrefsFindBool(list->name) ? "true" : "false");
441     break;
442     case TYPE_INT32:
443 cebix 1.7 fprintf(f, "%s %d\n", list->name, PrefsFindInt32(list->name));
444 cebix 1.1 break;
445     default:
446     break;
447     }
448     list++;
449     }
450     }
451    
452     void SavePrefsToStream(FILE *f)
453     {
454     write_prefs(f, common_prefs_items);
455     write_prefs(f, platform_prefs_items);
456     }