2 * cfg.c - Handling and parsing of yaboot.conf
4 * Copyright (C) 1995 Werner Almesberger
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #define prom_printf printf
31 #define prom_putchar putchar
32 #define prom_vprintf vprintf
34 /* Imported functions */
35 extern int strcasecmp(const char *s1, const char *s2);
38 cft_strg, cft_flag, cft_end
48 #define MAX_VAR_NAME MAX_TOKEN
49 char *cfg_get_default (void);
53 {cft_strg, "device", NULL},
54 {cft_strg, "partition", NULL},
55 {cft_strg, "default", NULL},
56 {cft_strg, "timeout", NULL},
57 {cft_strg, "password", NULL},
58 {cft_flag, "restricted", NULL},
59 {cft_strg, "message", NULL},
60 {cft_strg, "root", NULL},
61 {cft_strg, "ramdisk", NULL},
62 {cft_flag, "read-only", NULL},
63 {cft_flag, "read-write", NULL},
64 {cft_strg, "append", NULL},
65 {cft_strg, "initrd", NULL},
66 {cft_flag, "initrd-prompt", NULL},
67 {cft_strg, "initrd-size", NULL},
68 {cft_flag, "pause-after", NULL},
69 {cft_strg, "pause-message", NULL},
70 {cft_strg, "init-code", NULL},
71 {cft_strg, "init-message", NULL},
72 {cft_strg, "fgcolor", NULL},
73 {cft_strg, "bgcolor", NULL},
74 {cft_strg, "ptypewarning", NULL},
75 {cft_end, NULL, NULL}};
79 {cft_strg, "image", NULL},
80 {cft_strg, "label", NULL},
81 {cft_strg, "alias", NULL},
82 {cft_flag, "single-key", NULL},
83 {cft_flag, "restricted", NULL},
84 {cft_strg, "device", NULL},
85 {cft_strg, "partition", NULL},
86 {cft_strg, "root", NULL},
87 {cft_strg, "ramdisk", NULL},
88 {cft_flag, "read-only", NULL},
89 {cft_flag, "read-write", NULL},
90 {cft_strg, "append", NULL},
91 {cft_strg, "literal", NULL},
92 {cft_strg, "initrd", NULL},
93 {cft_flag, "initrd-prompt", NULL},
94 {cft_strg, "initrd-size", NULL},
95 {cft_flag, "pause-after", NULL},
96 {cft_strg, "pause-message", NULL},
97 {cft_flag, "novideo", NULL},
98 {cft_strg, "sysmap", NULL},
99 {cft_end, NULL, NULL}};
101 static char flag_set;
102 static char *last_token = NULL, *last_item = NULL, *last_value = NULL;
104 static int back = 0; /* can go back by one char */
105 static char *currp = NULL;
106 static char *endp = NULL;
107 static char *file_name = NULL;
108 static CONFIG *curr_table = cf_options;
111 static struct IMAGES {
112 CONFIG table[sizeof (cf_image) / sizeof (cf_image[0])];
116 void cfg_error (char *msg,...)
121 prom_printf ("Config file error: ");
122 prom_vprintf (msg, ap);
124 prom_printf (" near line %d in file %s\n", line_num, file_name);
128 void cfg_warn (char *msg,...)
133 prom_printf ("Config file warning: ");
134 prom_vprintf (msg, ap);
136 prom_printf (" near line %d in file %s\n", line_num, file_name);
139 inline int cfg_getc ()
146 #define next_raw next
147 static int next (void)
158 static void again (int ch)
163 static char *cfg_get_token (void)
165 char buf[MAX_TOKEN + 1];
175 while (ch = next (), ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
176 if (ch == '\n' || ch == '\r')
178 if (ch == EOF || ch == (int)NULL)
182 while (ch = next_raw (), (ch != '\n' && ch != '\r'))
191 while (here - buf < MAX_TOKEN) {
192 if ((ch = next ()) == EOF)
193 cfg_error ("EOF in quoted string");
206 while ((ch = next ()), ch == ' ' || ch == '\t');
216 cfg_error ("Bad use of \\ in quoted string");
218 } else if ((ch == '\n') || (ch == '\r'))
219 cfg_error ("newline is not allowed in quoted strings");
222 cfg_error ("Quoted string is too long");
223 return 0; /* not reached */
227 while (here - buf < MAX_TOKEN) {
230 cfg_error ("\\ precedes EOF");
234 *here++ = ch == '\t' ? ' ' : ch;
237 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '#' ||
238 ch == '=' || ch == EOF) {
243 if (!(escaped = (ch == '\\')))
248 cfg_error ("Token is too long");
249 return 0; /* not reached */
252 static void cfg_return_token (char *token)
257 static int cfg_next (char **item, char **value)
268 if (!(*item = cfg_get_token ()))
270 if (!strcmp (*item, "="))
271 cfg_error ("Syntax error");
272 if (!(this = cfg_get_token ()))
274 if (strcmp (this, "=")) {
275 cfg_return_token (this);
278 if (!(*value = cfg_get_token ()))
279 cfg_error ("Value expected at EOF");
280 if (!strcmp (*value, "="))
281 cfg_error ("Syntax error after %s", *item);
286 // The one and only call to this procedure is commented out
287 // below, so we don't need this unless we decide to use it again.
288 static void cfg_return (char *item, char *value)
295 static int cfg_set (char *item, char *value)
299 if (!strcasecmp (item, "image")) {
300 struct IMAGES **p = &images;
304 *p = (struct IMAGES *)malloc (sizeof (struct IMAGES));
306 prom_printf("malloc error in cfg_set\n");
310 curr_table = ((*p)->table);
311 memcpy (curr_table, cf_image, sizeof (cf_image));
313 for (walk = curr_table; walk->type != cft_end; walk++) {
314 if (walk->name && !strcasecmp (walk->name, item)) {
315 if (value && walk->type != cft_strg)
316 cfg_warn ("'%s' doesn't have a value", walk->name);
317 else if (!value && walk->type == cft_strg)
318 cfg_warn ("Value expected for '%s'", walk->name);
321 cfg_warn ("Duplicate entry '%s'", walk->name);
322 if (walk->type == cft_flag)
323 walk->data = &flag_set;
324 else if (walk->type == cft_strg)
330 if (walk->type != cft_end)
332 // cfg_return (item, value);
336 int cfg_parse (char *cfg_file, char *buff, int len)
340 file_name = cfg_file;
347 if (!cfg_next (&item, &value))
349 if (!cfg_set (item, value)) {
351 prom_printf("Can't set item %s to value %s\n", item, value);
358 static char *cfg_get_strg_i (CONFIG * table, char *item)
362 for (walk = table; walk->type != cft_end; walk++)
363 if (walk->name && !strcasecmp (walk->name, item))
368 char *cfg_get_strg (char *image, char *item)
375 return cfg_get_strg_i (cf_options, item);
376 for (p = images; p; p = p->next) {
377 label = cfg_get_strg_i (p->table, "label");
379 label = cfg_get_strg_i (p->table, "image");
380 alias = strrchr (label, '/');
384 alias = cfg_get_strg_i (p->table, "alias");
385 if (!strcmp (label, image) || (alias && !strcmp (alias, image))) {
386 ret = cfg_get_strg_i (p->table, item);
388 ret = cfg_get_strg_i (cf_options, item);
395 int cfg_get_flag (char *image, char *item)
397 return !!cfg_get_strg (image, item);
400 static int printl_count = 0;
401 static void printlabel (char *label, int defflag)
403 int len = strlen (label);
407 prom_printf ("%s %s",defflag?"*":" ", label);
411 if (printl_count == 3)
415 void cfg_print_images (void)
420 char *ret = cfg_get_default();//strg_i (cf_options, "default");
424 for (p = images; p; p = p->next) {
425 label = cfg_get_strg_i (p->table, "label");
427 label = cfg_get_strg_i (p->table, "image");
428 alias = strrchr (label, '/');
432 if(!strcmp(ret,label))
436 alias = cfg_get_strg_i (p->table, "alias");
437 printlabel (label, defflag);
439 printlabel (alias, 0);
444 char *cfg_get_default (void)
447 char *ret = cfg_get_strg_i (cf_options, "default");
453 ret = cfg_get_strg_i (images->table, "label");
455 ret = cfg_get_strg_i (images->table, "image");
456 label = strrchr (ret, '/');
463 char *cfg_next_image(char *prev)
472 for (p = images; p; p = p->next) {
473 label = cfg_get_strg_i (p->table, "label");
475 label = cfg_get_strg_i (p->table, "image");
476 alias = strrchr (label, '/');
482 if (!strcmp(prev, label))
489 * c-file-style: "k&r"