Recognizes if input is ogg or not.
[xiph.git] / vorbis-tools / ogg123 / cfgfile_options.c
blob232ea2c887280d7eb1808962a0aaec3f312b511c
1 /********************************************************************
2 * *
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. *
7 * *
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/ *
11 * *
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.
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <limits.h> /* for INT/LONG_MIN/MAX */
31 #include <errno.h>
33 #include "cfgfile_options.h"
34 #include "status.h"
35 #include "i18n.h"
37 /* ------------------- Private Functions ---------------------- */
39 int print_space (FILE *f, int s, int c)
41 int tmp = 0;
42 do {
43 fputc (c, f);
44 tmp++;
45 } while (--s > 0);
46 return tmp;
50 int parse_error (parse_code_t pcode, int lineno, const char *filename,
51 char *line)
53 if (pcode == parse_syserr) {
54 if (errno != EEXIST && errno != ENOENT)
55 perror (_("System error"));
56 return -1;
57 } else {
58 status_error (_("=== Parse error: %s on line %d of %s (%s)\n"),
59 parse_error_string(pcode),
60 lineno, filename, line);
61 return 0;
66 /* ------------------- Public Interface ----------------------- */
68 void file_options_init (file_option_t opts[])
71 while (opts && opts->name) {
73 opts->found = 0;
75 if (opts->dfl) {
76 switch (opts->type) {
77 case opt_type_none:
78 /* do nothing */
79 break;
81 case opt_type_char:
82 *(char *) opts->ptr = *(char*) opts->dfl;
83 break;
85 case opt_type_string:
86 *(char **) opts->ptr = *(char **) opts->dfl;
87 break;
89 case opt_type_bool:
90 case opt_type_int:
91 *(int *) opts->ptr = *(int *) opts->dfl;
92 break;
94 case opt_type_float:
95 *(float *) opts->ptr = *(float *) opts->dfl;
96 break;
98 case opt_type_double:
99 *(double *) opts->ptr = *(double *) opts->dfl;
100 break;
104 opts++;
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};
114 int totalWidth = 0;
115 file_option_t *opt = opts;
117 while (opt->name) {
118 int len = strlen (opt->name) + 1;
119 if (len > colWidths[0])
120 colWidths[0] = len;
121 opt++;
124 opt = opts;
125 while (opt->name) {
126 int len = strlen (opt->desc) + 1;
127 if (len > colWidths[1])
128 colWidths[1] = len;
129 opt++;
132 /* Column headers */
133 /* Name */
134 totalWidth += fprintf (f, "%-*s", colWidths[0], _("Name"));
136 /* Description */
137 totalWidth += fprintf (f, "%-*s", colWidths[1], _("Description"));
139 /* Type */
140 totalWidth += fprintf (f, "%-*s", colWidths[2], _("Type"));
142 /* Default */
143 totalWidth += fprintf (f, "%-*s", colWidths[3], _("Default"));
145 fputc ('\n', f);
147 /* Divider */
148 print_space (f, totalWidth, '-');
150 fputc ('\n', f);
152 opt = opts;
153 while (opt->name)
155 /* name */
156 int w = colWidths[0];
157 w -= fprintf (f, "%s", opt->name);
158 print_space (f, w, ' ');
160 /* description */
161 w = colWidths[1];
162 w -= fprintf (f, "%s", opt->desc);
163 print_space (f, w, ' ');
165 /* type */
166 w = colWidths[2];
167 switch (opt->type) {
168 case opt_type_none:
169 w -= fprintf (f, _("none"));
170 break;
171 case opt_type_bool:
172 w -= fprintf (f, _("bool"));
173 break;
174 case opt_type_char:
175 w -= fprintf (f, _("char"));
176 break;
177 case opt_type_string:
178 w -= fprintf (f, _("string"));
179 break;
180 case opt_type_int:
181 w -= fprintf (f, _("int"));
182 break;
183 case opt_type_float:
184 w -= fprintf (f, _("float"));
185 break;
186 case opt_type_double:
187 w -= fprintf (f, _("double"));
188 break;
189 default:
190 w -= fprintf (f, _("other"));
192 print_space (f, w, ' ');
194 /* default */
195 if (opt->dfl == NULL)
196 fputs (_("(NULL)"), f);
197 else {
198 switch (opt->type) {
199 case opt_type_none:
200 fputs (_("(none)"), f);
201 break;
202 case opt_type_char:
203 fputc (*(char *) opt->dfl, f);
204 break;
205 case opt_type_string:
206 fputs (*(char **) opt->dfl, f);
207 break;
208 case opt_type_bool:
209 case opt_type_int:
210 fprintf (f, "%d", *(int *) opt->dfl);
211 break;
212 case opt_type_float:
213 fprintf (f, "%f", (double) (*(float *) opt->dfl));
214 break;
215 case opt_type_double:
216 fprintf (f, "%f", *(double *) opt->dfl);
217 break;
220 fputc ('\n', f);
221 opt++;
226 parse_code_t parse_line (file_option_t opts[], char *line)
228 char *equals, *value = "";
229 file_option_t *opt;
230 int len;
232 /* skip leading whitespace */
233 while (line[0] == ' ')
234 line++;
236 /* remove comments */
237 equals = strchr (line, '#');
238 if (equals)
239 *equals = '\0';
241 /* return if only whitespace on line */
242 if (!line[0] || line[0] == '#')
243 return parse_ok;
245 /* check for an '=' and set to \0 */
246 equals = strchr (line, '=');
247 if (equals) {
248 value = equals + 1;
249 *equals = '\0';
252 /* cut trailing whitespace from key (line = key now) */
253 while ((equals = strrchr(line, ' ')))
254 *equals = '\0';
256 /* remove this if you want a zero-length key */
257 if (strlen(line) == 0)
258 return parse_nokey;
260 if (value) {
261 /* cut leading whitespace from value */
262 while (*value == ' ')
263 value++;
265 /* cut trailing whitespace from value */
266 len = strlen (value);
267 while (len > 0 && value[len-1] == ' ') {
268 len--;
269 value[len] = '\0';
273 /* now key is in line and value is in value. Search for a matching option. */
274 opt = opts;
275 while (opt->name) {
276 if (!strcasecmp (opt->name, line)) {
277 long tmpl;
278 char *endptr;
280 /* found the key. now set the value. */
281 switch (opt->type) {
282 case opt_type_none:
283 if (value != NULL || strlen(value) > 0)
284 return parse_badvalue;
285 opt->found++;
286 break;
288 case opt_type_bool:
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 *(int *) opt->ptr = 1;
299 else if ( strncasecmp(value, "n", 1) == 0
300 || strcasecmp(value, "false")
301 || (*endptr == '\0' && !tmpl) )
302 *(int *) opt->ptr = 0;
303 else
304 return parse_badvalue;
305 break;
307 case opt_type_char:
308 if (strlen(value) != 1)
309 return parse_badvalue;
310 opt->found++;
311 *(char *) opt->ptr = value[0];
312 break;
314 case opt_type_string:
315 opt->found++;
316 if (*(char **)opt->ptr) free(*(char **)opt->ptr);
317 *(char **) opt->ptr = strdup (value);
318 break;
320 case opt_type_int:
321 if (!value || *value == '\0')
322 return parse_badvalue;
323 errno = 0;
324 tmpl = strtol (value, &endptr, 0);
325 if (((tmpl == LONG_MIN || tmpl == LONG_MAX) && errno == ERANGE)
326 || (*endptr != '\0'))
327 return parse_badvalue;
328 if ((tmpl > INT_MAX) || (tmpl < INT_MIN))
329 return parse_badvalue;
330 opt->found++;
331 *(int *) opt->ptr = tmpl;
332 break;
334 case opt_type_float:
335 if (!value || *value == '\0')
336 return parse_badvalue;
337 opt->found++;
338 *(float *) opt->ptr = atof (value);
339 break;
341 case opt_type_double:
342 if (!value || *value == '\0')
343 return parse_badvalue;
344 opt->found++;
345 *(double *) opt->ptr = atof (value);
346 break;
348 default:
349 return parse_badtype;
351 return parse_ok;
353 opt++;
355 return parse_keynotfound;
359 parse_code_t parse_config_file (file_option_t opts[], const char *filename)
361 unsigned int len=80;
362 char *line = malloc(len);
363 int readoffset, thischar, lineno;
364 FILE *file;
365 parse_code_t pcode;
366 char empty[] = "";
368 if (!line) {
369 parse_error(parse_syserr, 0, empty, empty);
370 return parse_syserr;
373 file = fopen (filename, "r");
374 if (!file) {
375 parse_error (parse_syserr, 0, empty, empty);
376 free (line);
377 return parse_syserr;
380 lineno = 0;
381 while (!feof (file)) {
383 lineno++;
384 readoffset = 0;
385 memset (line, 0, len);
387 while ((thischar = fgetc(file)) != EOF) {
389 if (readoffset + 1 > len) {
390 len *= 2;
391 line = realloc (line, len);
392 if (!line)
394 parse_error(parse_syserr, 0, empty, empty);
395 fclose (file);
396 return parse_syserr;
400 if (thischar == '\n') {
401 line[readoffset] = '\0';
402 break;
404 else
405 line[readoffset] = (unsigned char) thischar;
406 readoffset++;
410 pcode = parse_line (opts, line);
412 if (pcode != parse_ok)
413 if (!parse_error(pcode, lineno, filename, line)) {
414 free (line);
415 return pcode;
420 free (line);
421 return parse_ok;
424 /* ParseErr - returns a string corresponding to parse code pcode */
425 const char *parse_error_string (parse_code_t pcode)
427 switch (pcode) {
428 case parse_ok:
429 return _("Success");
430 case parse_syserr:
431 return strerror(errno);
432 case parse_keynotfound:
433 return _("Key not found");
434 case parse_nokey:
435 return _("No key");
436 case parse_badvalue:
437 return _("Bad value");
438 case parse_badtype:
439 return _("Bad type in options list");
440 default:
441 return _("Unknown error");
446 void parse_std_configs (file_option_t opts[])
448 char filename[FILENAME_MAX];
449 char *homedir = getenv("HOME");
451 parse_config_file(opts, SYSCONFDIR "/ogg123rc");
452 if (homedir && strlen(homedir) < FILENAME_MAX - 10) {
453 /* Try ~/.ogg123 */
454 strncpy(filename, homedir, FILENAME_MAX);
455 strcat(filename, "/.ogg123rc");
456 parse_config_file(opts, filename);