1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2001 *
9 * by Stan Seibert <volsung@xiph.org> AND OTHER CONTRIBUTORS *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 last mod: $Id: cfgfile_options.c,v 1.3 2002/01/26 11:06:37 segher Exp $
16 ********************************************************************/
19 /* if strcasecmp is giving you problems, switch to strcmp or the appropriate
20 * function for your platform / compiler.
30 #include <limits.h> /* for LONG_MAX / LONG_MIN */
33 #include "cfgfile_options.h"
37 /* ------------------- Private Functions ---------------------- */
39 int print_space (FILE *f
, int s
, int c
)
50 int parse_error (parse_code_t pcode
, int lineno
, const char *filename
,
53 if (pcode
== parse_syserr
) {
54 if (errno
!= EEXIST
&& errno
!= ENOENT
)
55 perror (_("System error"));
58 status_error (_("=== Parse error: %s on line %d of %s (%s)\n"),
59 parse_error_string(pcode
),
60 lineno
, filename
, line
);
66 /* ------------------- Public Interface ----------------------- */
68 void file_options_init (file_option_t opts
[])
71 while (opts
&& opts
->name
) {
82 *(char *) opts
->ptr
= *(char*) opts
->dfl
;
86 *(char **) opts
->ptr
= *(char **) opts
->dfl
;
91 *(long int *) opts
->ptr
= *(int *) opts
->dfl
;
95 *(float *) opts
->ptr
= *(float *) opts
->dfl
;
99 *(double *) opts
->ptr
= *(double *) opts
->dfl
;
109 /* DescribeOptions - describe available options to outfile */
110 void file_options_describe (file_option_t opts
[], FILE *f
)
112 /* name | description | type | default */
113 int colWidths
[] = {0, 0, 7, 7};
115 file_option_t
*opt
= opts
;
118 int len
= strlen (opt
->name
) + 1;
119 if (len
> colWidths
[0])
126 int len
= strlen (opt
->desc
) + 1;
127 if (len
> colWidths
[1])
134 totalWidth
+= fprintf (f
, "%-*s", colWidths
[0], _("Name"));
137 totalWidth
+= fprintf (f
, "%-*s", colWidths
[1], _("Description"));
140 totalWidth
+= fprintf (f
, "%-*s", colWidths
[2], _("Type"));
143 totalWidth
+= fprintf (f
, "%-*s", colWidths
[3], _("Default"));
148 print_space (f
, totalWidth
, '-');
156 int w
= colWidths
[0];
157 w
-= fprintf (f
, "%s", opt
->name
);
158 print_space (f
, w
, ' ');
162 w
-= fprintf (f
, "%s", opt
->desc
);
163 print_space (f
, w
, ' ');
169 w
-= fprintf (f
, _("none"));
172 w
-= fprintf (f
, _("bool"));
175 w
-= fprintf (f
, _("char"));
177 case opt_type_string
:
178 w
-= fprintf (f
, _("string"));
181 w
-= fprintf (f
, _("int"));
184 w
-= fprintf (f
, _("float"));
186 case opt_type_double
:
187 w
-= fprintf (f
, _("double"));
190 w
-= fprintf (f
, _("other"));
192 print_space (f
, w
, ' ');
195 if (opt
->dfl
== NULL
)
196 fputs (_("(NULL)"), f
);
200 fputs (_("(none)"), f
);
203 fputc (*(char *) opt
->dfl
, f
);
205 case opt_type_string
:
206 fputs (*(char **) opt
->dfl
, f
);
210 fprintf (f
, "%ld", *(long int *) opt
->dfl
);
213 fprintf (f
, "%f", (double) (*(float *) opt
->dfl
));
215 case opt_type_double
:
216 fprintf (f
, "%f", *(double *) opt
->dfl
);
226 parse_code_t
parse_line (file_option_t opts
[], char *line
)
228 char *equals
, *value
= "";
232 /* skip leading whitespace */
233 while (line
[0] == ' ')
236 /* remove comments */
237 equals
= strchr (line
, '#');
241 /* return if only whitespace on line */
242 if (!line
[0] || line
[0] == '#')
245 /* check for an '=' and set to \0 */
246 equals
= strchr (line
, '=');
252 /* cut trailing whitespace from key (line = key now) */
253 while ((equals
= strrchr(line
, ' ')))
256 /* remove this if you want a zero-length key */
257 if (strlen(line
) == 0)
261 /* cut leading whitespace from value */
262 while (*value
== ' ')
265 /* cut trailing whitespace from value */
266 len
= strlen (value
);
267 while (len
> 0 && value
[len
-1] == ' ') {
273 /* now key is in line and value is in value. Search for a matching option. */
276 if (!strcasecmp (opt
->name
, line
)) {
280 /* found the key. now set the value. */
283 if (value
!= NULL
|| strlen(value
) > 0)
284 return parse_badvalue
;
289 if (!value
|| *value
== '\0')
290 return parse_badvalue
;
292 /* Maybe this is a numeric bool */
293 tmpl
= strtol (value
, &endptr
, 0);
295 if ( strncasecmp(value
, "y", 1) == 0
296 || strcasecmp(value
, "true")
297 || (*endptr
== '\0' && tmpl
) )
298 *(long int *) opt
->ptr
= 1;
299 else if ( strncasecmp(value
, "n", 1) == 0
300 || strcasecmp(value
, "false")
301 || (*endptr
== '\0' && !tmpl
) )
302 *(long int *) opt
->ptr
= 0;
304 return parse_badvalue
;
308 if (strlen(value
) != 1)
309 return parse_badvalue
;
311 *(char *) opt
->ptr
= value
[0];
314 case opt_type_string
:
316 if (*(char **)opt
->ptr
) free(*(char **)opt
->ptr
);
317 *(char **) opt
->ptr
= strdup (value
);
321 if (!value
|| *value
== '\0')
322 return parse_badvalue
;
323 tmpl
= strtol (value
, &endptr
, 0);
324 if (((tmpl
== LONG_MIN
|| tmpl
== LONG_MAX
) && errno
== ERANGE
)
325 || (*endptr
!= '\0'))
326 return parse_badvalue
;
328 *(long int *) opt
->ptr
= tmpl
;
332 if (!value
|| *value
== '\0')
333 return parse_badvalue
;
335 *(float *) opt
->ptr
= atof (value
);
338 case opt_type_double
:
339 if (!value
|| *value
== '\0')
340 return parse_badvalue
;
342 *(double *) opt
->ptr
= atof (value
);
346 return parse_badtype
;
352 return parse_keynotfound
;
356 parse_code_t
parse_config_file (file_option_t opts
[], const char *filename
)
359 char *line
= malloc(len
);
360 int readoffset
, thischar
, lineno
;
366 parse_error(parse_syserr
, 0, empty
, empty
);
370 file
= fopen (filename
, "r");
372 parse_error (parse_syserr
, 0, empty
, empty
);
378 while (!feof (file
)) {
382 memset (line
, 0, len
);
384 while ((thischar
= fgetc(file
)) != EOF
) {
386 if (readoffset
+ 1 > len
) {
388 line
= realloc (line
, len
);
391 parse_error(parse_syserr
, 0, empty
, empty
);
397 if (thischar
== '\n') {
398 line
[readoffset
] = '\0';
402 line
[readoffset
] = (unsigned char) thischar
;
407 pcode
= parse_line (opts
, line
);
409 if (pcode
!= parse_ok
)
410 if (!parse_error(pcode
, lineno
, filename
, line
)) {
421 /* ParseErr - returns a string corresponding to parse code pcode */
422 const char *parse_error_string (parse_code_t pcode
)
428 return strerror(errno
);
429 case parse_keynotfound
:
430 return _("Key not found");
434 return _("Bad value");
436 return _("Bad type in options list");
438 return _("Unknown error");
443 void parse_std_configs (file_option_t opts
[])
445 char filename
[FILENAME_MAX
];
446 char *homedir
= getenv("HOME");
448 parse_config_file(opts
, "/etc/ogg123rc");
449 if (homedir
&& strlen(homedir
) < FILENAME_MAX
- 10) {
451 strncpy(filename
, homedir
, FILENAME_MAX
);
452 strcat(filename
, "/.ogg123rc");
453 parse_config_file(opts
, filename
);