Statistics
| Branch: | Revision:

ffmpeg / libavutil / opt.c @ 85770f2a

History | View | Annotate | Download (19 KB)

1
/*
2
 * AVOptions
3
 * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at>
4
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * Libav 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 GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with Libav; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

    
22
/**
23
 * @file
24
 * AVOptions
25
 * @author Michael Niedermayer <michaelni@gmx.at>
26
 */
27

    
28
#include "avutil.h"
29
#include "avstring.h"
30
#include "opt.h"
31
#include "eval.h"
32

    
33
//FIXME order them and do a bin search
34
const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags)
35
{
36
    const AVOption *o = NULL;
37

    
38
    while ((o = av_next_option(v, o))) {
39
        if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags)
40
            return o;
41
    }
42
    return NULL;
43
}
44

    
45
const AVOption *av_next_option(void *obj, const AVOption *last)
46
{
47
    if (last && last[1].name) return ++last;
48
    else if (last)            return NULL;
49
    else                      return (*(AVClass**)obj)->option;
50
}
51

    
52
static int av_set_number2(void *obj, const char *name, double num, int den, int64_t intnum, const AVOption **o_out)
53
{
54
    const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
55
    void *dst;
56
    if (o_out)
57
        *o_out= o;
58
    if (!o || o->offset<=0)
59
        return AVERROR_OPTION_NOT_FOUND;
60

    
61
    if (o->max*den < num*intnum || o->min*den > num*intnum) {
62
        av_log(obj, AV_LOG_ERROR, "Value %lf for parameter '%s' out of range\n", num, name);
63
        return AVERROR(ERANGE);
64
    }
65

    
66
    dst= ((uint8_t*)obj) + o->offset;
67

    
68
    switch (o->type) {
69
    case FF_OPT_TYPE_FLAGS:
70
    case FF_OPT_TYPE_INT:   *(int       *)dst= llrint(num/den)*intnum; break;
71
    case FF_OPT_TYPE_INT64: *(int64_t   *)dst= llrint(num/den)*intnum; break;
72
    case FF_OPT_TYPE_FLOAT: *(float     *)dst= num*intnum/den;         break;
73
    case FF_OPT_TYPE_DOUBLE:*(double    *)dst= num*intnum/den;         break;
74
    case FF_OPT_TYPE_RATIONAL:
75
        if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
76
        else                 *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
77
        break;
78
    default:
79
        return AVERROR(EINVAL);
80
    }
81
    return 0;
82
}
83

    
84
static const AVOption *av_set_number(void *obj, const char *name, double num, int den, int64_t intnum)
85
{
86
    const AVOption *o = NULL;
87
    if (av_set_number2(obj, name, num, den, intnum, &o) < 0)
88
        return NULL;
89
    else
90
        return o;
91
}
92

    
93
static const double const_values[] = {
94
    M_PI,
95
    M_E,
96
    FF_QP2LAMBDA,
97
    0
98
};
99

    
100
static const char * const const_names[] = {
101
    "PI",
102
    "E",
103
    "QP2LAMBDA",
104
    0
105
};
106

    
107
static int hexchar2int(char c) {
108
    if (c >= '0' && c <= '9') return c - '0';
109
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
110
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
111
    return -1;
112
}
113

    
114
int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out)
115
{
116
    int ret;
117
    const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
118
    if (o_out)
119
        *o_out = o;
120
    if (!o)
121
        return AVERROR_OPTION_NOT_FOUND;
122
    if (!val || o->offset<=0)
123
        return AVERROR(EINVAL);
124

    
125
    if (o->type == FF_OPT_TYPE_BINARY) {
126
        uint8_t **dst = (uint8_t **)(((uint8_t*)obj) + o->offset);
127
        int *lendst = (int *)(dst + 1);
128
        uint8_t *bin, *ptr;
129
        int len = strlen(val);
130
        av_freep(dst);
131
        *lendst = 0;
132
        if (len & 1) return AVERROR(EINVAL);
133
        len /= 2;
134
        ptr = bin = av_malloc(len);
135
        while (*val) {
136
            int a = hexchar2int(*val++);
137
            int b = hexchar2int(*val++);
138
            if (a < 0 || b < 0) {
139
                av_free(bin);
140
                return AVERROR(EINVAL);
141
            }
142
            *ptr++ = (a << 4) | b;
143
        }
144
        *dst = bin;
145
        *lendst = len;
146
        return 0;
147
    }
148
    if (o->type != FF_OPT_TYPE_STRING) {
149
        int notfirst=0;
150
        for (;;) {
151
            int i;
152
            char buf[256];
153
            int cmd=0;
154
            double d;
155

    
156
            if (*val == '+' || *val == '-')
157
                cmd= *(val++);
158

    
159
            for (i=0; i<sizeof(buf)-1 && val[i] && val[i]!='+' && val[i]!='-'; i++)
160
                buf[i]= val[i];
161
            buf[i]=0;
162

    
163
            {
164
                const AVOption *o_named= av_find_opt(obj, buf, o->unit, 0, 0);
165
                if (o_named && o_named->type == FF_OPT_TYPE_CONST)
166
                    d= o_named->default_val.dbl;
167
                else if (!strcmp(buf, "default")) d= o->default_val.dbl;
168
                else if (!strcmp(buf, "max"    )) d= o->max;
169
                else if (!strcmp(buf, "min"    )) d= o->min;
170
                else if (!strcmp(buf, "none"   )) d= 0;
171
                else if (!strcmp(buf, "all"    )) d= ~0;
172
                else {
173
                    int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj);
174
                    if (res < 0) {
175
                        av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val);
176
                        return res;
177
                    }
178
                }
179
            }
180
            if (o->type == FF_OPT_TYPE_FLAGS) {
181
                if      (cmd=='+') d= av_get_int(obj, name, NULL) | (int64_t)d;
182
                else if (cmd=='-') d= av_get_int(obj, name, NULL) &~(int64_t)d;
183
            } else {
184
                if      (cmd=='+') d= notfirst*av_get_double(obj, name, NULL) + d;
185
                else if (cmd=='-') d= notfirst*av_get_double(obj, name, NULL) - d;
186
            }
187

    
188
            if ((ret = av_set_number2(obj, name, d, 1, 1, o_out)) < 0)
189
                return ret;
190
            val+= i;
191
            if (!*val)
192
                return 0;
193
            notfirst=1;
194
        }
195
        return AVERROR(EINVAL);
196
    }
197

    
198
    if (alloc) {
199
        av_free(*(void**)(((uint8_t*)obj) + o->offset));
200
        val= av_strdup(val);
201
    }
202

    
203
    memcpy(((uint8_t*)obj) + o->offset, &val, sizeof(val));
204
    return 0;
205
}
206

    
207
const AVOption *av_set_double(void *obj, const char *name, double n)
208
{
209
    return av_set_number(obj, name, n, 1, 1);
210
}
211

    
212
const AVOption *av_set_q(void *obj, const char *name, AVRational n)
213
{
214
    return av_set_number(obj, name, n.num, n.den, 1);
215
}
216

    
217
const AVOption *av_set_int(void *obj, const char *name, int64_t n)
218
{
219
    return av_set_number(obj, name, 1, 1, n);
220
}
221

    
222
/**
223
 *
224
 * @param buf a buffer which is used for returning non string values as strings, can be NULL
225
 * @param buf_len allocated length in bytes of buf
226
 */
227
const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len)
228
{
229
    const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
230
    void *dst;
231
    uint8_t *bin;
232
    int len, i;
233
    if (!o || o->offset<=0)
234
        return NULL;
235
    if (o->type != FF_OPT_TYPE_STRING && (!buf || !buf_len))
236
        return NULL;
237

    
238
    dst= ((uint8_t*)obj) + o->offset;
239
    if (o_out) *o_out= o;
240

    
241
    switch (o->type) {
242
    case FF_OPT_TYPE_FLAGS:     snprintf(buf, buf_len, "0x%08X",*(int    *)dst);break;
243
    case FF_OPT_TYPE_INT:       snprintf(buf, buf_len, "%d" , *(int    *)dst);break;
244
    case FF_OPT_TYPE_INT64:     snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break;
245
    case FF_OPT_TYPE_FLOAT:     snprintf(buf, buf_len, "%f" , *(float  *)dst);break;
246
    case FF_OPT_TYPE_DOUBLE:    snprintf(buf, buf_len, "%f" , *(double *)dst);break;
247
    case FF_OPT_TYPE_RATIONAL:  snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
248
    case FF_OPT_TYPE_STRING:    return *(void**)dst;
249
    case FF_OPT_TYPE_BINARY:
250
        len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
251
        if (len >= (buf_len + 1)/2) return NULL;
252
        bin = *(uint8_t**)dst;
253
        for (i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]);
254
        break;
255
    default: return NULL;
256
    }
257
    return buf;
258
}
259

    
260
static int av_get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum)
261
{
262
    const AVOption *o= av_find_opt(obj, name, NULL, 0, 0);
263
    void *dst;
264
    if (!o || o->offset<=0)
265
        goto error;
266

    
267
    dst= ((uint8_t*)obj) + o->offset;
268

    
269
    if (o_out) *o_out= o;
270

    
271
    switch (o->type) {
272
    case FF_OPT_TYPE_FLAGS:     *intnum= *(unsigned int*)dst;return 0;
273
    case FF_OPT_TYPE_INT:       *intnum= *(int    *)dst;return 0;
274
    case FF_OPT_TYPE_INT64:     *intnum= *(int64_t*)dst;return 0;
275
    case FF_OPT_TYPE_FLOAT:     *num=    *(float  *)dst;return 0;
276
    case FF_OPT_TYPE_DOUBLE:    *num=    *(double *)dst;return 0;
277
    case FF_OPT_TYPE_RATIONAL:  *intnum= ((AVRational*)dst)->num;
278
                                *den   = ((AVRational*)dst)->den;
279
                                                        return 0;
280
    }
281
error:
282
    *den=*intnum=0;
283
    return -1;
284
}
285

    
286
double av_get_double(void *obj, const char *name, const AVOption **o_out)
287
{
288
    int64_t intnum=1;
289
    double num=1;
290
    int den=1;
291

    
292
    av_get_number(obj, name, o_out, &num, &den, &intnum);
293
    return num*intnum/den;
294
}
295

    
296
AVRational av_get_q(void *obj, const char *name, const AVOption **o_out)
297
{
298
    int64_t intnum=1;
299
    double num=1;
300
    int den=1;
301

    
302
    av_get_number(obj, name, o_out, &num, &den, &intnum);
303
    if (num == 1.0 && (int)intnum == intnum)
304
        return (AVRational){intnum, den};
305
    else
306
        return av_d2q(num*intnum/den, 1<<24);
307
}
308

    
309
int64_t av_get_int(void *obj, const char *name, const AVOption **o_out)
310
{
311
    int64_t intnum=1;
312
    double num=1;
313
    int den=1;
314

    
315
    av_get_number(obj, name, o_out, &num, &den, &intnum);
316
    return num*intnum/den;
317
}
318

    
319
static void opt_list(void *obj, void *av_log_obj, const char *unit,
320
                     int req_flags, int rej_flags)
321
{
322
    const AVOption *opt=NULL;
323

    
324
    while ((opt= av_next_option(obj, opt))) {
325
        if (!(opt->flags & req_flags) || (opt->flags & rej_flags))
326
            continue;
327

    
328
        /* Don't print CONST's on level one.
329
         * Don't print anything but CONST's on level two.
330
         * Only print items from the requested unit.
331
         */
332
        if (!unit && opt->type==FF_OPT_TYPE_CONST)
333
            continue;
334
        else if (unit && opt->type!=FF_OPT_TYPE_CONST)
335
            continue;
336
        else if (unit && opt->type==FF_OPT_TYPE_CONST && strcmp(unit, opt->unit))
337
            continue;
338
        else if (unit && opt->type == FF_OPT_TYPE_CONST)
339
            av_log(av_log_obj, AV_LOG_INFO, "   %-15s ", opt->name);
340
        else
341
            av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);
342

    
343
        switch (opt->type) {
344
            case FF_OPT_TYPE_FLAGS:
345
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>");
346
                break;
347
            case FF_OPT_TYPE_INT:
348
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int>");
349
                break;
350
            case FF_OPT_TYPE_INT64:
351
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>");
352
                break;
353
            case FF_OPT_TYPE_DOUBLE:
354
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<double>");
355
                break;
356
            case FF_OPT_TYPE_FLOAT:
357
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<float>");
358
                break;
359
            case FF_OPT_TYPE_STRING:
360
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<string>");
361
                break;
362
            case FF_OPT_TYPE_RATIONAL:
363
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>");
364
                break;
365
            case FF_OPT_TYPE_BINARY:
366
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>");
367
                break;
368
            case FF_OPT_TYPE_CONST:
369
            default:
370
                av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "");
371
                break;
372
        }
373
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');
374
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');
375
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM   ) ? 'V' : '.');
376
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM   ) ? 'A' : '.');
377
        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');
378

    
379
        if (opt->help)
380
            av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);
381
        av_log(av_log_obj, AV_LOG_INFO, "\n");
382
        if (opt->unit && opt->type != FF_OPT_TYPE_CONST) {
383
            opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
384
        }
385
    }
386
}
387

    
388
int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
389
{
390
    if (!obj)
391
        return -1;
392

    
393
    av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
394

    
395
    opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
396

    
397
    return 0;
398
}
399

    
400
/** Set the values of the AVCodecContext or AVFormatContext structure.
401
 * They are set to the defaults specified in the according AVOption options
402
 * array default_val field.
403
 *
404
 * @param s AVCodecContext or AVFormatContext for which the defaults will be set
405
 */
406
void av_opt_set_defaults2(void *s, int mask, int flags)
407
{
408
    const AVOption *opt = NULL;
409
    while ((opt = av_next_option(s, opt)) != NULL) {
410
        if ((opt->flags & mask) != flags)
411
            continue;
412
        switch (opt->type) {
413
            case FF_OPT_TYPE_CONST:
414
                /* Nothing to be done here */
415
            break;
416
            case FF_OPT_TYPE_FLAGS:
417
            case FF_OPT_TYPE_INT:
418
            case FF_OPT_TYPE_INT64:
419
                av_set_int(s, opt->name, opt->default_val.i64);
420
                break;
421
            case FF_OPT_TYPE_DOUBLE:
422
            case FF_OPT_TYPE_FLOAT: {
423
                double val;
424
                val = opt->default_val.dbl;
425
                av_set_double(s, opt->name, val);
426
            }
427
            break;
428
            case FF_OPT_TYPE_RATIONAL: {
429
                av_set_q(s, opt->name, opt->default_val.q);
430
            }
431
            break;
432
            case FF_OPT_TYPE_STRING:
433
            case FF_OPT_TYPE_BINARY:
434
                /* Cannot set default for string as default_val is of type * double */
435
            break;
436
            default:
437
                av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
438
        }
439
    }
440
}
441

    
442
void av_opt_set_defaults(void *s)
443
{
444
    av_opt_set_defaults2(s, 0, 0);
445
}
446

    
447
/**
448
 * Store the value in the field in ctx that is named like key.
449
 * ctx must be an AVClass context, storing is done using AVOptions.
450
 *
451
 * @param buf the string to parse, buf will be updated to point at the
452
 * separator just after the parsed key/value pair
453
 * @param key_val_sep a 0-terminated list of characters used to
454
 * separate key from value
455
 * @param pairs_sep a 0-terminated list of characters used to separate
456
 * two pairs from each other
457
 * @return 0 if the key/value pair has been successfully parsed and
458
 * set, or a negative value corresponding to an AVERROR code in case
459
 * of error:
460
 * AVERROR(EINVAL) if the key/value pair cannot be parsed,
461
 * the error code issued by av_set_string3() if the key/value pair
462
 * cannot be set
463
 */
464
static int parse_key_value_pair(void *ctx, const char **buf,
465
                                const char *key_val_sep, const char *pairs_sep)
466
{
467
    char *key = av_get_token(buf, key_val_sep);
468
    char *val;
469
    int ret;
470

    
471
    if (*key && strspn(*buf, key_val_sep)) {
472
        (*buf)++;
473
        val = av_get_token(buf, pairs_sep);
474
    } else {
475
        av_log(ctx, AV_LOG_ERROR, "Missing key or no key/value separator found after key '%s'\n", key);
476
        av_free(key);
477
        return AVERROR(EINVAL);
478
    }
479

    
480
    av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key);
481

    
482
    ret = av_set_string3(ctx, key, val, 1, NULL);
483
    if (ret == AVERROR_OPTION_NOT_FOUND)
484
        av_log(ctx, AV_LOG_ERROR, "Key '%s' not found.\n", key);
485

    
486
    av_free(key);
487
    av_free(val);
488
    return ret;
489
}
490

    
491
int av_set_options_string(void *ctx, const char *opts,
492
                          const char *key_val_sep, const char *pairs_sep)
493
{
494
    int ret, count = 0;
495

    
496
    while (*opts) {
497
        if ((ret = parse_key_value_pair(ctx, &opts, key_val_sep, pairs_sep)) < 0)
498
            return ret;
499
        count++;
500

    
501
        if (*opts)
502
            opts++;
503
    }
504

    
505
    return count;
506
}
507

    
508
#ifdef TEST
509

    
510
#undef printf
511

    
512
typedef struct TestContext
513
{
514
    const AVClass *class;
515
    int num;
516
    int toggle;
517
    char *string;
518
    int flags;
519
    AVRational rational;
520
} TestContext;
521

    
522
#define OFFSET(x) offsetof(TestContext, x)
523

    
524
#define TEST_FLAG_COOL 01
525
#define TEST_FLAG_LAME 02
526
#define TEST_FLAG_MU   04
527

    
528
static const AVOption test_options[]= {
529
{"num",      "set num",        OFFSET(num),      FF_OPT_TYPE_INT,      0,              0,        100                 },
530
{"toggle",   "set toggle",     OFFSET(toggle),   FF_OPT_TYPE_INT,      0,              0,        1                   },
531
{"rational", "set rational",   OFFSET(rational), FF_OPT_TYPE_RATIONAL, 0,              0,        10                  },
532
{"string",   "set string",     OFFSET(string),   FF_OPT_TYPE_STRING,   0,              CHAR_MIN, CHAR_MAX            },
533
{"flags",    "set flags",      OFFSET(flags),    FF_OPT_TYPE_FLAGS,    0,              0,        INT_MAX, 0, "flags" },
534
{"cool",     "set cool flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_COOL, INT_MIN,  INT_MAX, 0, "flags" },
535
{"lame",     "set lame flag ", 0,                FF_OPT_TYPE_CONST,    TEST_FLAG_LAME, INT_MIN,  INT_MAX, 0, "flags" },
536
{"mu",       "set mu flag ",   0,                FF_OPT_TYPE_CONST,    TEST_FLAG_MU,   INT_MIN,  INT_MAX, 0, "flags" },
537
{NULL},
538
};
539

    
540
static const char *test_get_name(void *ctx)
541
{
542
    return "test";
543
}
544

    
545
static const AVClass test_class = {
546
    "TestContext",
547
    test_get_name,
548
    test_options
549
};
550

    
551
int main(void)
552
{
553
    int i;
554

    
555
    printf("\nTesting av_set_options_string()\n");
556
    {
557
        TestContext test_ctx;
558
        const char *options[] = {
559
            "",
560
            ":",
561
            "=",
562
            "foo=:",
563
            ":=foo",
564
            "=foo",
565
            "foo=",
566
            "foo",
567
            "foo=val",
568
            "foo==val",
569
            "toggle=:",
570
            "string=:",
571
            "toggle=1 : foo",
572
            "toggle=100",
573
            "toggle==1",
574
            "flags=+mu-lame : num=42: toggle=0",
575
            "num=42 : string=blahblah",
576
            "rational=0 : rational=1/2 : rational=1/-1",
577
            "rational=-1/0",
578
        };
579

    
580
        test_ctx.class = &test_class;
581
        av_opt_set_defaults2(&test_ctx, 0, 0);
582
        test_ctx.string = av_strdup("default");
583

    
584
        av_log_set_level(AV_LOG_DEBUG);
585

    
586
        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
587
            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
588
            if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
589
                av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
590
            printf("\n");
591
        }
592
    }
593

    
594
    return 0;
595
}
596

    
597
#endif