2010-01-30 23:24:23 +00:00
/*
* This file is part of MPlayer .
*
* MPlayer is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* MPlayer is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with MPlayer ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
2006-04-24 19:20:04 +00:00
/// \file
/// \ingroup Options
2002-11-12 01:56:42 +00:00
# include "config.h"
# include <stdlib.h>
# include <string.h>
# include <math.h>
# include <stdio.h>
# include <stdarg.h>
# include <inttypes.h>
2002-11-24 01:03:16 +00:00
# include <unistd.h>
2011-07-28 08:07:47 +00:00
# include <assert.h>
2002-11-12 01:56:42 +00:00
2011-07-03 17:04:21 +00:00
# include "talloc.h"
2002-11-12 01:56:42 +00:00
# include "m_option.h"
# include "mp_msg.h"
2006-07-31 17:39:17 +00:00
# include "stream/url.h"
2007-07-05 22:01:07 +00:00
# include "libavutil/avstring.h"
2002-11-12 01:56:42 +00:00
2011-07-29 04:52:29 +00:00
char * m_option_strerror ( int code )
{
switch ( code ) {
case M_OPT_UNKNOWN :
return mp_gtext ( " Unrecognized option name " ) ;
case M_OPT_MISSING_PARAM :
return mp_gtext ( " Required parameter for option missing " ) ;
case M_OPT_INVALID :
return mp_gtext ( " Option parameter could not be parsed " ) ;
case M_OPT_OUT_OF_RANGE :
return mp_gtext ( " Parameter is outside values allowed for option " ) ;
case M_OPT_PARSER_ERR :
return mp_gtext ( " Parser error " ) ;
default :
return NULL ;
}
}
2011-07-28 08:07:47 +00:00
static const struct m_option * m_option_list_findb ( const struct m_option * list ,
struct bstr name )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
for ( int i = 0 ; list [ i ] . name ; i + + ) {
struct bstr lname = bstr ( list [ i ] . name ) ;
2011-07-03 12:42:04 +00:00
if ( ( list [ i ] . type - > flags & M_OPT_TYPE_ALLOW_WILDCARD )
2011-07-28 08:07:47 +00:00
& & bstr_endswith0 ( lname , " * " ) ) {
lname . len - - ;
if ( bstrcasecmp ( bstr_splice ( name , 0 , lname . len ) , lname ) = = 0 )
2011-07-03 12:42:04 +00:00
return & list [ i ] ;
2011-07-28 08:07:47 +00:00
} else if ( bstrcasecmp ( lname , name ) = = 0 )
2011-07-03 12:42:04 +00:00
return & list [ i ] ;
}
return NULL ;
2003-03-15 18:01:02 +00:00
}
2011-07-28 08:07:47 +00:00
const m_option_t * m_option_list_find ( const m_option_t * list , const char * name )
{
return m_option_list_findb ( list , bstr ( name ) ) ;
}
2003-08-17 13:51:04 +00:00
// Default function that just does a memcpy
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
static void copy_opt ( const m_option_t * opt , void * dst , const void * src )
{
if ( dst & & src )
memcpy ( dst , src , opt - > type - > size ) ;
2002-11-12 01:56:42 +00:00
}
// Flag
2011-07-03 12:42:04 +00:00
# define VAL(x) (*(int *)(x))
2011-07-28 08:07:47 +00:00
static int parse_flag ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
if ( param . len & & ! ambiguous_param ) {
char * const enable [ ] = { " yes " , " on " , " ja " , " si " , " igen " , " y " , " j " ,
" i " , " tak " , " ja " , " true " , " 1 " } ;
for ( int i = 0 ; i < sizeof ( enable ) / sizeof ( enable [ 0 ] ) ; i + + ) {
if ( ! bstrcasecmp0 ( param , enable [ i ] ) ) {
if ( dst )
VAL ( dst ) = opt - > max ;
return 1 ;
}
2011-07-03 12:42:04 +00:00
}
2011-07-28 08:07:47 +00:00
char * const disable [ ] = { " no " , " off " , " nein " , " nicht " , " nem " , " n " ,
" nie " , " nej " , " false " , " 0 " } ;
for ( int i = 0 ; i < sizeof ( disable ) / sizeof ( disable [ 0 ] ) ; i + + ) {
if ( ! bstrcasecmp0 ( param , disable [ i ] ) ) {
if ( dst )
VAL ( dst ) = opt - > min ;
return 1 ;
}
}
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
" Invalid parameter for %.*s flag: %.*s \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
return M_OPT_INVALID ;
2002-11-12 01:56:42 +00:00
} else {
2011-07-03 12:42:04 +00:00
if ( dst )
VAL ( dst ) = opt - > max ;
return 0 ;
2002-11-12 01:56:42 +00:00
}
}
2011-07-03 12:42:04 +00:00
static char * print_flag ( const m_option_t * opt , const void * val )
{
if ( VAL ( val ) = = opt - > min )
2011-07-03 17:04:21 +00:00
return talloc_strdup ( NULL , " no " ) ;
2011-07-03 12:42:04 +00:00
else
2011-07-03 17:04:21 +00:00
return talloc_strdup ( NULL , " yes " ) ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_flag = {
2011-07-03 12:42:04 +00:00
" Flag " ,
" need yes or no in config files " ,
sizeof ( int ) ,
0 ,
parse_flag ,
print_flag ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2002-11-12 01:56:42 +00:00
} ;
// Integer
2011-07-28 08:07:47 +00:00
static int parse_longlong ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
struct bstr rest ;
long long tmp_int = bstrtoll ( param , & rest , 10 ) ;
if ( rest . len )
tmp_int = bstrtoll ( param , & rest , 0 ) ;
if ( rest . len ) {
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" The %.*s option must be an integer: %.*s \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( ( opt - > flags & M_OPT_MIN ) & & ( tmp_int < opt - > min ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" The %.*s option must be >= %d: %.*s \n " ,
BSTR_P ( name ) , ( int ) opt - > min , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_OUT_OF_RANGE ;
}
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( ( opt - > flags & M_OPT_MAX ) & & ( tmp_int > opt - > max ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" The %.*s option must be <= %d: %.*s \n " ,
BSTR_P ( name ) , ( int ) opt - > max , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_OUT_OF_RANGE ;
}
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
if ( dst )
* ( long long * ) dst = tmp_int ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
return 1 ;
2002-11-12 01:56:42 +00:00
}
2011-07-28 08:07:47 +00:00
static int parse_int ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
{
long long tmp ;
int r = parse_longlong ( opt , name , param , false , & tmp ) ;
if ( r > = 0 & & dst )
* ( int * ) dst = tmp ;
return r ;
}
static int parse_int64 ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
{
long long tmp ;
int r = parse_longlong ( opt , name , param , false , & tmp ) ;
if ( r > = 0 & & dst )
* ( int64_t * ) dst = tmp ;
return r ;
}
2011-07-03 12:42:04 +00:00
static char * print_int ( const m_option_t * opt , const void * val )
{
if ( opt - > type - > size = = sizeof ( int64_t ) )
2011-07-03 17:04:21 +00:00
return talloc_asprintf ( NULL , " % " PRId64 , * ( const int64_t * ) val ) ;
return talloc_asprintf ( NULL , " %d " , VAL ( val ) ) ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_int = {
2011-07-03 12:42:04 +00:00
" Integer " ,
" " ,
sizeof ( int ) ,
0 ,
parse_int ,
print_int ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2002-11-12 01:56:42 +00:00
} ;
2009-03-02 11:17:50 +00:00
const m_option_type_t m_option_type_int64 = {
2011-07-03 12:42:04 +00:00
" Integer64 " ,
" " ,
sizeof ( int64_t ) ,
0 ,
2011-07-28 08:07:47 +00:00
parse_int64 ,
2011-07-03 12:42:04 +00:00
print_int ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2009-03-02 11:17:50 +00:00
} ;
2011-07-28 08:07:47 +00:00
static int parse_intpair ( const struct m_option * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2010-04-24 17:09:31 +00:00
{
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2010-04-24 17:09:31 +00:00
return M_OPT_MISSING_PARAM ;
2011-07-28 08:07:47 +00:00
struct bstr s = param ;
2010-04-24 17:09:31 +00:00
int end = - 1 ;
2011-07-28 08:07:47 +00:00
int start = bstrtoll ( s , & s , 10 ) ;
if ( s . len = = param . len )
goto bad ;
if ( s . len > 0 ) {
if ( ! bstr_startswith0 ( s , " - " ) )
2010-04-24 17:09:31 +00:00
goto bad ;
2011-07-28 08:07:47 +00:00
s = bstr_cut ( s , 1 ) ;
2010-04-24 17:09:31 +00:00
}
2011-07-28 08:07:47 +00:00
if ( s . len > 0 )
end = bstrtoll ( s , & s , 10 ) ;
if ( s . len > 0 )
2010-04-24 17:09:31 +00:00
goto bad ;
if ( dst ) {
int * p = dst ;
p [ 0 ] = start ;
p [ 1 ] = end ;
}
return 1 ;
2011-07-03 12:42:04 +00:00
bad :
2010-04-24 17:09:31 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Invalid integer range "
2011-07-28 08:07:47 +00:00
" specification for option %.*s: %.*s \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
2010-04-24 17:09:31 +00:00
return M_OPT_INVALID ;
}
const struct m_option_type m_option_type_intpair = {
. name = " Int[-Int] " ,
. size = sizeof ( int [ 2 ] ) ,
. parse = parse_intpair ,
2010-12-17 23:00:28 +00:00
. save = copy_opt ,
. set = copy_opt ,
} ;
2011-07-28 08:07:47 +00:00
static int parse_choice ( const struct m_option * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2010-12-17 23:00:28 +00:00
{
2012-01-06 21:26:21 +00:00
bool allow_empty = opt - > flags & M_OPT_IMPLICIT_DEFAULT ;
int ret ;
struct m_opt_choice_alternatives * alt = opt - > priv ;
if ( param . len = = 0 | | ( ambiguous_param & & allow_empty ) ) {
if ( ! allow_empty )
return M_OPT_MISSING_PARAM ;
ret = 0 ;
} else {
for ( ; alt - > name ; alt + + )
if ( ! bstrcasecmp0 ( param , alt - > name ) )
break ;
ret = 1 ;
}
2010-12-17 23:00:28 +00:00
if ( ! alt - > name ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
" Invalid value for option %.*s: %.*s \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
2010-12-17 23:00:28 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Valid values are: " ) ;
for ( alt = opt - > priv ; alt - > name ; alt + + )
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " %s " , alt - > name ) ;
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " \n " ) ;
return M_OPT_INVALID ;
}
if ( dst )
* ( int * ) dst = alt - > value ;
2012-01-06 21:26:21 +00:00
return ret ;
2010-12-17 23:00:28 +00:00
}
2011-07-03 12:42:04 +00:00
static char * print_choice ( const m_option_t * opt , const void * val )
2010-12-17 23:00:28 +00:00
{
int v = * ( int * ) val ;
struct m_opt_choice_alternatives * alt ;
for ( alt = opt - > priv ; alt - > name ; alt + + )
if ( alt - > value = = v )
2011-07-03 17:04:21 +00:00
return talloc_strdup ( NULL , alt - > name ) ;
2010-12-17 23:00:28 +00:00
abort ( ) ;
}
const struct m_option_type m_option_type_choice = {
. name = " String " , // same as arbitrary strings in option list for now
. size = sizeof ( int ) ,
. parse = parse_choice ,
. print = print_choice ,
2010-04-24 17:09:31 +00:00
. save = copy_opt ,
. set = copy_opt ,
} ;
2002-11-12 01:56:42 +00:00
// Float
# undef VAL
2011-07-03 12:42:04 +00:00
# define VAL(x) (*(double *)(x))
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
static int parse_double ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
struct bstr rest ;
double tmp_float = bstrtod ( param , & rest ) ;
2011-07-03 12:42:04 +00:00
2011-07-28 08:07:47 +00:00
switch ( rest . len ? rest . start [ 0 ] : 0 ) {
2011-07-03 12:42:04 +00:00
case ' : ' :
case ' / ' :
2011-07-28 08:07:47 +00:00
tmp_float / = bstrtod ( bstr_cut ( rest , 1 ) , & rest ) ;
2011-07-03 12:42:04 +00:00
break ;
case ' . ' :
case ' , ' :
/* we also handle floats specified with
* non - locale decimal point : : atmos
*/
2011-07-28 08:07:47 +00:00
rest = bstr_cut ( rest , 1 ) ;
2011-07-03 12:42:04 +00:00
if ( tmp_float < 0 )
2011-07-28 08:07:47 +00:00
tmp_float - = 1.0 / pow ( 10 , rest . len ) * bstrtod ( rest , & rest ) ;
2011-07-03 12:42:04 +00:00
else
2011-07-28 08:07:47 +00:00
tmp_float + = 1.0 / pow ( 10 , rest . len ) * bstrtod ( rest , & rest ) ;
2011-07-03 12:42:04 +00:00
break ;
2002-11-12 01:56:42 +00:00
}
2011-07-28 08:07:47 +00:00
if ( rest . len ) {
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" The %.*s option must be a floating point number or a "
" ratio (numerator[:/]denominator): %.*s \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
if ( opt - > flags & M_OPT_MIN )
if ( tmp_float < opt - > min ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" The %.*s option must be >= %f: %.*s \n " ,
BSTR_P ( name ) , opt - > min , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_OUT_OF_RANGE ;
}
if ( opt - > flags & M_OPT_MAX )
if ( tmp_float > opt - > max ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" The %.*s option must be <= %f: %.*s \n " ,
BSTR_P ( name ) , opt - > max , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_OUT_OF_RANGE ;
}
if ( dst )
VAL ( dst ) = tmp_float ;
return 1 ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
static char * print_double ( const m_option_t * opt , const void * val )
{
opt = NULL ;
2011-07-03 17:04:21 +00:00
return talloc_asprintf ( NULL , " %f " , VAL ( val ) ) ;
2004-02-10 14:32:06 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_double = {
2011-07-03 12:42:04 +00:00
" Double " ,
" double precision floating point number or ratio (numerator[:/]denominator) " ,
sizeof ( double ) ,
0 ,
parse_double ,
print_double ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2004-02-10 14:32:06 +00:00
} ;
# undef VAL
2011-07-03 12:42:04 +00:00
# define VAL(x) (*(float *)(x))
2004-02-10 14:32:06 +00:00
2011-07-28 08:07:47 +00:00
static int parse_float ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2004-02-10 14:32:06 +00:00
double tmp ;
2011-07-27 17:59:44 +00:00
int r = parse_double ( opt , name , param , false , & tmp ) ;
2011-07-03 12:42:04 +00:00
if ( r = = 1 & & dst )
VAL ( dst ) = tmp ;
2004-02-10 22:58:30 +00:00
return r ;
2004-02-10 14:32:06 +00:00
}
2011-07-03 12:42:04 +00:00
static char * print_float ( const m_option_t * opt , const void * val )
{
opt = NULL ;
2011-07-03 17:04:21 +00:00
return talloc_asprintf ( NULL , " %f " , VAL ( val ) ) ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_float = {
2011-07-03 12:42:04 +00:00
" Float " ,
" floating point number or ratio (numerator[:/]denominator) " ,
sizeof ( float ) ,
0 ,
parse_float ,
print_float ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2002-11-12 01:56:42 +00:00
} ;
///////////// Position
# undef VAL
2011-07-03 12:42:04 +00:00
# define VAL(x) (*(off_t *)(x))
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
static int parse_position ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
long long tmp ;
int r = parse_longlong ( opt , name , param , false , & tmp ) ;
if ( r > = 0 & & dst )
* ( off_t * ) dst = tmp ;
return r ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
static char * print_position ( const m_option_t * opt , const void * val )
{
2011-07-03 17:04:21 +00:00
return talloc_asprintf ( NULL , " % " PRId64 , ( int64_t ) VAL ( val ) ) ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_position = {
2011-07-03 12:42:04 +00:00
" Position " ,
" Integer (off_t) " ,
sizeof ( off_t ) ,
0 ,
parse_position ,
print_position ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2002-11-12 01:56:42 +00:00
} ;
///////////// String
# undef VAL
2011-07-03 12:42:04 +00:00
# define VAL(x) (*(char **)(x))
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
static int parse_str ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
if ( ( opt - > flags & M_OPT_MIN ) & & ( param . len < opt - > min ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
" Parameter must be >= %d chars: %.*s \n " ,
( int ) opt - > min , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_OUT_OF_RANGE ;
}
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
if ( ( opt - > flags & M_OPT_MAX ) & & ( param . len > opt - > max ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
" Parameter must be <= %d chars: %.*s \n " ,
( int ) opt - > max , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_OUT_OF_RANGE ;
}
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( dst ) {
2011-07-05 22:24:24 +00:00
talloc_free ( VAL ( dst ) ) ;
2011-07-28 08:07:47 +00:00
VAL ( dst ) = bstrdup0 ( NULL , param ) ;
2011-07-03 12:42:04 +00:00
}
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
return 1 ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
static char * print_str ( const m_option_t * opt , const void * val )
{
2011-07-03 17:04:21 +00:00
return ( val & & VAL ( val ) ) ? talloc_strdup ( NULL , VAL ( val ) ) : NULL ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
static void copy_str ( const m_option_t * opt , void * dst , const void * src )
{
if ( dst & & src ) {
2011-07-05 22:24:24 +00:00
talloc_free ( VAL ( dst ) ) ;
VAL ( dst ) = talloc_strdup ( NULL , VAL ( src ) ) ;
2011-07-03 12:42:04 +00:00
}
2002-11-12 01:56:42 +00:00
}
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
static void free_str ( void * src )
{
if ( src & & VAL ( src ) ) {
2011-07-05 22:24:24 +00:00
talloc_free ( VAL ( src ) ) ;
2011-07-03 12:42:04 +00:00
VAL ( src ) = NULL ;
}
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_string = {
2011-07-03 12:42:04 +00:00
" String " ,
" " ,
sizeof ( char * ) ,
M_OPT_TYPE_DYNAMIC ,
parse_str ,
print_str ,
copy_str ,
copy_str ,
copy_str ,
free_str
2002-11-12 01:56:42 +00:00
} ;
2009-07-06 23:26:13 +00:00
2002-11-12 01:56:42 +00:00
//////////// String list
# undef VAL
2011-07-03 12:42:04 +00:00
# define VAL(x) (*(char ***)(x))
2002-11-12 01:56:42 +00:00
# define OP_NONE 0
# define OP_ADD 1
# define OP_PRE 2
# define OP_DEL 3
# define OP_CLR 4
2011-07-03 12:42:04 +00:00
static void free_str_list ( void * dst )
{
char * * d ;
int i ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( ! dst | | ! VAL ( dst ) )
return ;
d = VAL ( dst ) ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
for ( i = 0 ; d [ i ] ! = NULL ; i + + )
2011-07-05 22:24:24 +00:00
talloc_free ( d [ i ] ) ;
talloc_free ( d ) ;
2011-07-03 12:42:04 +00:00
VAL ( dst ) = NULL ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
static int str_list_add ( char * * add , int n , void * dst , int pre )
{
char * * lst = VAL ( dst ) ;
int ln ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( ! dst )
return M_OPT_PARSER_ERR ;
lst = VAL ( dst ) ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
for ( ln = 0 ; lst & & lst [ ln ] ; ln + + )
/**/ ;
2002-11-12 01:56:42 +00:00
2011-07-05 22:24:24 +00:00
lst = talloc_realloc ( NULL , lst , char * , n + ln + 1 ) ;
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
if ( pre ) {
memmove ( & lst [ n ] , lst , ln * sizeof ( char * ) ) ;
memcpy ( lst , add , n * sizeof ( char * ) ) ;
} else
memcpy ( & lst [ ln ] , add , n * sizeof ( char * ) ) ;
// (re-)add NULL-termination
lst [ ln + n ] = NULL ;
2002-11-12 01:56:42 +00:00
2011-07-05 22:24:24 +00:00
talloc_free ( add ) ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
VAL ( dst ) = lst ;
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
return 1 ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
static int str_list_del ( char * * del , int n , void * dst )
{
2011-07-05 22:24:24 +00:00
char * * lst , * ep ;
2011-07-03 12:42:04 +00:00
int i , ln , s ;
long idx ;
if ( ! dst )
return M_OPT_PARSER_ERR ;
lst = VAL ( dst ) ;
for ( ln = 0 ; lst & & lst [ ln ] ; ln + + )
/**/ ;
s = ln ;
for ( i = 0 ; del [ i ] ! = NULL ; i + + ) {
idx = strtol ( del [ i ] , & ep , 0 ) ;
if ( * ep ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Invalid index: %s \n " , del [ i ] ) ;
2011-07-05 22:24:24 +00:00
talloc_free ( del [ i ] ) ;
2011-07-03 12:42:04 +00:00
continue ;
}
2011-07-05 22:24:24 +00:00
talloc_free ( del [ i ] ) ;
2011-07-03 12:42:04 +00:00
if ( idx < 0 | | idx > = ln ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
" Index %ld is out of range. \n " , idx ) ;
continue ;
} else if ( ! lst [ idx ] )
continue ;
2011-07-05 22:24:24 +00:00
talloc_free ( lst [ idx ] ) ;
2011-07-03 12:42:04 +00:00
lst [ idx ] = NULL ;
s - - ;
}
2011-07-05 22:24:24 +00:00
talloc_free ( del ) ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( s = = 0 ) {
2011-07-05 22:24:24 +00:00
talloc_free ( lst ) ;
2011-07-03 12:42:04 +00:00
VAL ( dst ) = NULL ;
return 1 ;
}
2002-11-12 01:56:42 +00:00
2011-07-05 22:24:24 +00:00
// Don't bother shrinking the list allocation
2011-07-03 12:42:04 +00:00
for ( i = 0 , n = 0 ; i < ln ; i + + ) {
if ( ! lst [ i ] )
continue ;
2011-07-05 22:24:24 +00:00
lst [ n ] = lst [ i ] ;
2011-07-03 12:42:04 +00:00
n + + ;
}
2011-07-05 22:24:24 +00:00
lst [ s ] = NULL ;
2011-07-03 12:42:04 +00:00
return 1 ;
2002-11-12 01:56:42 +00:00
}
2009-07-06 23:26:13 +00:00
2011-07-28 08:07:47 +00:00
static struct bstr get_nextsep ( struct bstr * ptr , char sep , bool modify )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
struct bstr str = * ptr ;
struct bstr orig = str ;
2011-07-03 12:42:04 +00:00
for ( ; ; ) {
2011-07-28 08:07:47 +00:00
int idx = bstrchr ( str , sep ) ;
if ( idx > 0 & & str . start [ idx - 1 ] = = ' \\ ' ) {
if ( modify ) {
memmove ( str . start + idx - 1 , str . start + idx , str . len - idx ) ;
str . len - - ;
str = bstr_cut ( str , idx ) ;
} else
str = bstr_cut ( str , idx + 1 ) ;
} else {
str = bstr_cut ( str , idx < 0 ? str . len : idx ) ;
2007-02-05 18:03:12 +00:00
break ;
2011-07-28 08:07:47 +00:00
}
2007-02-05 18:03:12 +00:00
}
2011-07-28 08:07:47 +00:00
* ptr = str ;
return bstr_splice ( orig , 0 , str . start - orig . start ) ;
2007-02-05 18:03:12 +00:00
}
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
static int parse_str_list ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
char * * res ;
2011-07-03 12:42:04 +00:00
int op = OP_NONE ;
2011-07-28 08:07:47 +00:00
int len = strlen ( opt - > name ) ;
if ( opt - > name [ len - 1 ] = = ' * ' & & ( name . len > len - 1 ) ) {
struct bstr suffix = bstr_cut ( name , len - 1 ) ;
if ( bstrcasecmp0 ( suffix , " -add " ) = = 0 )
2011-07-03 12:42:04 +00:00
op = OP_ADD ;
2011-07-28 08:07:47 +00:00
else if ( bstrcasecmp0 ( suffix , " -pre " ) = = 0 )
2011-07-03 12:42:04 +00:00
op = OP_PRE ;
2011-07-28 08:07:47 +00:00
else if ( bstrcasecmp0 ( suffix , " -del " ) = = 0 )
2011-07-03 12:42:04 +00:00
op = OP_DEL ;
2011-07-28 08:07:47 +00:00
else if ( bstrcasecmp0 ( suffix , " -clr " ) = = 0 )
2011-07-03 12:42:04 +00:00
op = OP_CLR ;
else
return M_OPT_UNKNOWN ;
}
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
// Clear the list ??
if ( op = = OP_CLR ) {
if ( dst )
free_str_list ( dst ) ;
return 0 ;
}
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
// All other ops need a param
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
// custom type for "profile" calls this but uses ->priv for something else
char separator = opt - > type = = & m_option_type_string_list & & opt - > priv ?
* ( char * ) opt - > priv : OPTION_LIST_SEPARATOR ;
2011-07-28 08:07:47 +00:00
int n = 0 ;
struct bstr str = param ;
while ( str . len ) {
get_nextsep ( & str , separator , 0 ) ;
str = bstr_cut ( str , 1 ) ;
2011-07-03 12:42:04 +00:00
n + + ;
}
if ( n = = 0 )
return M_OPT_INVALID ;
if ( ( ( opt - > flags & M_OPT_MIN ) & & ( n < opt - > min ) ) | |
( ( opt - > flags & M_OPT_MAX ) & & ( n > opt - > max ) ) )
return M_OPT_OUT_OF_RANGE ;
if ( ! dst )
return 1 ;
2011-07-05 22:24:24 +00:00
res = talloc_array ( NULL , char * , n + 2 ) ;
2011-07-28 08:07:47 +00:00
str = bstrdup ( NULL , param ) ;
char * ptr = str . start ;
2011-07-03 12:42:04 +00:00
n = 0 ;
2011-07-31 17:25:22 +00:00
while ( 1 ) {
2011-07-28 08:07:47 +00:00
struct bstr el = get_nextsep ( & str , separator , 1 ) ;
res [ n ] = bstrdup0 ( NULL , el ) ;
2011-07-03 12:42:04 +00:00
n + + ;
2011-07-31 17:25:22 +00:00
if ( ! str . len )
break ;
str = bstr_cut ( str , 1 ) ;
2011-07-03 12:42:04 +00:00
}
res [ n ] = NULL ;
2011-07-28 08:07:47 +00:00
talloc_free ( ptr ) ;
2011-07-03 12:42:04 +00:00
switch ( op ) {
case OP_ADD :
return str_list_add ( res , n , dst , 0 ) ;
case OP_PRE :
return str_list_add ( res , n , dst , 1 ) ;
case OP_DEL :
return str_list_del ( res , n , dst ) ;
}
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( VAL ( dst ) )
free_str_list ( dst ) ;
VAL ( dst ) = res ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
return 1 ;
}
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
static void copy_str_list ( const m_option_t * opt , void * dst , const void * src )
{
int n ;
char * * d , * * s ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( ! ( dst & & src ) )
return ;
s = VAL ( src ) ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( VAL ( dst ) )
free_str_list ( dst ) ;
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
if ( ! s ) {
VAL ( dst ) = NULL ;
return ;
}
2002-11-12 12:39:05 +00:00
2011-07-03 12:42:04 +00:00
for ( n = 0 ; s [ n ] ! = NULL ; n + + )
/* NOTHING */ ;
2011-07-05 22:24:24 +00:00
d = talloc_array ( NULL , char * , n + 1 ) ;
2011-07-03 12:42:04 +00:00
for ( ; n > = 0 ; n - - )
2011-07-05 22:24:24 +00:00
d [ n ] = talloc_strdup ( NULL , s [ n ] ) ;
2011-07-03 12:42:04 +00:00
VAL ( dst ) = d ;
}
static char * print_str_list ( const m_option_t * opt , const void * src )
{
char * * lst = NULL ;
2011-07-03 17:04:21 +00:00
char * ret = NULL ;
2011-07-03 12:42:04 +00:00
if ( ! ( src & & VAL ( src ) ) )
return NULL ;
lst = VAL ( src ) ;
2011-07-03 17:04:21 +00:00
for ( int i = 0 ; lst [ i ] ; i + + ) {
if ( ret )
ret = talloc_strdup_append_buffer ( ret , " , " ) ;
ret = talloc_strdup_append_buffer ( ret , lst [ i ] ) ;
2011-07-03 12:42:04 +00:00
}
return ret ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_string_list = {
2011-07-03 12:42:04 +00:00
" String list " ,
" A list of strings separated by ',' \n "
" Option with a name ending in an * permits using the following suffix: \n "
" \t -add: Add the given parameters at the end of the list. \n "
" \t -pre: Add the given parameters at the beginning of the list. \n "
" \t -del: Remove the entry at the given indices. \n "
" \t -clr: Clear the list. \n "
" e.g: -vf-add flip,mirror -vf-del 2,5 \n " ,
sizeof ( char * * ) ,
M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD ,
parse_str_list ,
print_str_list ,
copy_str_list ,
copy_str_list ,
copy_str_list ,
free_str_list
2002-11-12 01:56:42 +00:00
} ;
2009-07-06 23:26:13 +00:00
2002-11-12 01:56:42 +00:00
/////////////////// Func based options
2011-01-31 03:13:29 +00:00
// A chained list to save the various calls for func_param
2002-11-12 01:56:42 +00:00
struct m_func_save {
2011-07-05 22:24:24 +00:00
struct m_func_save * next ;
2011-07-03 12:42:04 +00:00
char * name ;
char * param ;
2002-11-12 01:56:42 +00:00
} ;
# undef VAL
2011-07-05 22:24:24 +00:00
# define VAL(x) (*(struct m_func_save **)(x))
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
static void free_func_pf ( void * src )
{
2011-07-05 22:24:24 +00:00
struct m_func_save * s , * n ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( ! src )
return ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
s = VAL ( src ) ;
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
while ( s ) {
n = s - > next ;
2011-07-05 22:24:24 +00:00
talloc_free ( s - > name ) ;
talloc_free ( s - > param ) ;
talloc_free ( s ) ;
2011-07-03 12:42:04 +00:00
s = n ;
}
VAL ( src ) = NULL ;
2002-11-12 01:56:42 +00:00
}
2011-01-31 03:13:29 +00:00
// Parser for func_param
2011-07-28 08:07:47 +00:00
static int parse_func_pf ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-05 22:24:24 +00:00
struct m_func_save * s , * p ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( ! dst )
return 1 ;
2002-11-12 01:56:42 +00:00
2011-07-05 22:24:24 +00:00
s = talloc_zero ( NULL , struct m_func_save ) ;
2011-07-28 08:07:47 +00:00
s - > name = bstrdup0 ( NULL , name ) ;
s - > param = bstrdup0 ( NULL , param ) ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
p = VAL ( dst ) ;
if ( p ) {
for ( ; p - > next ! = NULL ; p = p - > next )
/**/ ;
p - > next = s ;
} else
VAL ( dst ) = s ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
return 1 ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
static void copy_func_pf ( const m_option_t * opt , void * dst , const void * src )
{
2011-07-05 22:24:24 +00:00
struct m_func_save * d = NULL , * s , * last = NULL ;
2011-07-03 12:42:04 +00:00
if ( ! ( dst & & src ) )
return ;
s = VAL ( src ) ;
if ( VAL ( dst ) )
free_func_pf ( dst ) ;
while ( s ) {
2011-07-05 22:24:24 +00:00
d = talloc_zero ( NULL , struct m_func_save ) ;
d - > name = talloc_strdup ( NULL , s - > name ) ;
d - > param = talloc_strdup ( NULL , s - > param ) ;
2011-07-03 12:42:04 +00:00
if ( last )
last - > next = d ;
else
VAL ( dst ) = d ;
last = d ;
s = s - > next ;
}
2009-07-06 23:26:13 +00:00
2002-11-12 01:56:42 +00:00
}
/////////////////// Func_param
2011-07-03 12:42:04 +00:00
static void set_func_param ( const m_option_t * opt , void * dst , const void * src )
{
2011-07-05 22:24:24 +00:00
struct m_func_save * s ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
if ( ! src )
return ;
s = VAL ( src ) ;
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
if ( ! s )
return ;
2002-11-12 01:56:42 +00:00
2011-07-03 12:42:04 +00:00
for ( ; s ! = NULL ; s = s - > next )
( ( m_opt_func_param_t ) opt - > p ) ( opt , s - > param ) ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_func_param = {
2011-07-03 12:42:04 +00:00
" Func param " ,
" " ,
2011-07-05 22:24:24 +00:00
sizeof ( struct m_func_save * ) ,
2011-07-03 12:42:04 +00:00
M_OPT_TYPE_INDIRECT ,
parse_func_pf ,
NULL ,
NULL , // Nothing to do on save
set_func_param ,
copy_func_pf ,
free_func_pf
2002-11-12 01:56:42 +00:00
} ;
/////////////// Func
# undef VAL
2011-07-28 08:07:47 +00:00
static int parse_func ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
return 0 ;
2002-11-12 01:56:42 +00:00
}
2011-07-03 12:42:04 +00:00
static void set_func ( const m_option_t * opt , void * dst , const void * src )
{
2002-11-12 01:56:42 +00:00
( ( m_opt_func_t ) opt - > p ) ( opt ) ;
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_func = {
2011-07-03 12:42:04 +00:00
" Func " ,
" " ,
sizeof ( int ) ,
M_OPT_TYPE_INDIRECT ,
parse_func ,
NULL ,
NULL , // Nothing to do on save
set_func ,
NULL ,
NULL
2002-11-12 01:56:42 +00:00
} ;
/////////////////// Print
2011-07-28 08:07:47 +00:00
static int parse_print ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
if ( opt - > type = = CONF_TYPE_PRINT_INDIRECT )
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " %s " , * ( char * * ) opt - > p ) ;
2011-07-28 08:07:47 +00:00
else if ( opt - > type = = CONF_TYPE_PRINT_FUNC ) {
char * name0 = bstrdup0 ( NULL , name ) ;
char * param0 = bstrdup0 ( NULL , param ) ;
int r = ( ( m_opt_func_full_t ) opt - > p ) ( opt , name0 , param0 ) ;
talloc_free ( name0 ) ;
talloc_free ( param0 ) ;
return r ;
} else
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " %s " , mp_gtext ( opt - > p ) ) ;
if ( opt - > priv = = NULL )
return M_OPT_EXIT ;
return 0 ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_print = {
2011-07-03 12:42:04 +00:00
" Print " ,
" " ,
0 ,
0 ,
parse_print ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL
2002-11-12 01:56:42 +00:00
} ;
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_print_indirect = {
2011-07-03 12:42:04 +00:00
" Print " ,
" " ,
0 ,
0 ,
parse_print ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL
2003-01-03 12:40:10 +00:00
} ;
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_print_func = {
2011-07-03 12:42:04 +00:00
" Print " ,
" " ,
0 ,
M_OPT_TYPE_ALLOW_WILDCARD ,
parse_print ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL
2006-01-24 11:14:13 +00:00
} ;
2003-01-03 12:40:10 +00:00
2002-11-12 01:56:42 +00:00
/////////////////////// Subconfig
# undef VAL
2011-07-03 12:42:04 +00:00
# define VAL(x) (*(char ***)(x))
2011-07-28 08:07:47 +00:00
static int parse_subconf ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
int nr = 0 , i ;
2011-07-03 12:42:04 +00:00
char * * lst = NULL ;
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2011-07-28 08:07:47 +00:00
struct bstr p = param ;
const struct m_option * subopts = opt - > p ;
while ( p . len ) {
int optlen = bstrcspn ( p , " := " ) ;
struct bstr subopt = bstr_splice ( p , 0 , optlen ) ;
struct bstr subparam = bstr ( NULL ) ;
p = bstr_cut ( p , optlen ) ;
if ( bstr_startswith0 ( p , " = " ) ) {
p = bstr_cut ( p , 1 ) ;
if ( bstr_startswith0 ( p , " \" " ) ) {
p = bstr_cut ( p , 1 ) ;
optlen = bstrcspn ( p , " \" " ) ;
subparam = bstr_splice ( p , 0 , optlen ) ;
p = bstr_cut ( p , optlen ) ;
if ( ! bstr_startswith0 ( p , " \" " ) ) {
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Terminating ' \" ' missing for '%.*s' \n " ,
BSTR_P ( subopt ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
2011-07-28 08:07:47 +00:00
p = bstr_cut ( p , 1 ) ;
} else if ( bstr_startswith0 ( p , " % " ) ) {
p = bstr_cut ( p , 1 ) ;
optlen = bstrtoll ( p , & p , 0 ) ;
if ( ! bstr_startswith0 ( p , " % " ) | | ( optlen > p . len - 1 ) ) {
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Invalid length %d for '%.*s' \n " ,
optlen , BSTR_P ( subopt ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
2011-07-28 08:07:47 +00:00
subparam = bstr_splice ( p , 1 , optlen + 1 ) ;
p = bstr_cut ( p , optlen + 1 ) ;
2011-07-03 12:42:04 +00:00
} else {
2011-07-28 08:07:47 +00:00
optlen = bstrcspn ( p , " : " ) ;
subparam = bstr_splice ( p , 0 , optlen ) ;
p = bstr_cut ( p , optlen ) ;
2011-07-03 12:42:04 +00:00
}
}
2011-07-28 08:07:47 +00:00
if ( bstr_startswith0 ( p , " : " ) )
p = bstr_cut ( p , 1 ) ;
else if ( p . len > 0 ) {
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Incorrect termination for '%.*s' \n " , BSTR_P ( subopt ) ) ;
2005-10-12 16:35:37 +00:00
return M_OPT_INVALID ;
}
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
for ( i = 0 ; subopts [ i ] . name ; i + + )
if ( ! bstrcmp0 ( subopt , subopts [ i ] . name ) )
break ;
if ( ! subopts [ i ] . name ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
" Option %.*s: Unknown suboption %.*s \n " ,
BSTR_P ( name ) , BSTR_P ( subopt ) ) ;
return M_OPT_UNKNOWN ;
}
int r = m_option_parse ( & subopts [ i ] , subopt , subparam , false , NULL ) ;
if ( r < 0 )
return r ;
if ( dst ) {
lst = talloc_realloc ( NULL , lst , char * , 2 * ( nr + 2 ) ) ;
lst [ 2 * nr ] = bstrdup0 ( NULL , subopt ) ;
lst [ 2 * nr + 1 ] = subparam . len = = 0 ? NULL :
bstrdup0 ( NULL , subparam ) ;
memset ( & lst [ 2 * ( nr + 1 ) ] , 0 , 2 * sizeof ( char * ) ) ;
nr + + ;
2011-07-03 12:42:04 +00:00
}
}
if ( dst )
VAL ( dst ) = lst ;
return 1 ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_subconfig = {
2011-07-03 12:42:04 +00:00
" Subconfig " ,
" The syntax is -option opt1=foo:flag:opt2=blah " ,
sizeof ( int ) ,
M_OPT_TYPE_HAS_CHILD ,
parse_subconf ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL
2002-11-12 01:56:42 +00:00
} ;
# include "libmpcodecs/img_format.h"
2003-03-15 20:49:39 +00:00
2003-08-31 21:11:35 +00:00
/* FIXME: snyc with img_format.h */
2003-03-15 20:49:39 +00:00
static struct {
2011-07-03 12:42:04 +00:00
const char * name ;
unsigned int fmt ;
2003-03-15 20:49:39 +00:00
} mp_imgfmt_list [ ] = {
2011-07-03 12:42:04 +00:00
{ " 444p16le " , IMGFMT_444P16_LE } ,
{ " 444p16be " , IMGFMT_444P16_BE } ,
{ " 444p10le " , IMGFMT_444P10_LE } ,
{ " 444p10be " , IMGFMT_444P10_BE } ,
{ " 444p9le " , IMGFMT_444P9_LE } ,
{ " 444p9be " , IMGFMT_444P9_BE } ,
{ " 422p16le " , IMGFMT_422P16_LE } ,
{ " 422p16be " , IMGFMT_422P16_BE } ,
{ " 422p10le " , IMGFMT_422P10_LE } ,
{ " 422p10be " , IMGFMT_422P10_BE } ,
{ " 420p16le " , IMGFMT_420P16_LE } ,
{ " 420p16be " , IMGFMT_420P16_BE } ,
{ " 420p10le " , IMGFMT_420P10_LE } ,
{ " 420p10be " , IMGFMT_420P10_BE } ,
{ " 420p9le " , IMGFMT_420P9_LE } ,
{ " 420p9be " , IMGFMT_420P9_BE } ,
{ " 444p16 " , IMGFMT_444P16 } ,
{ " 444p10 " , IMGFMT_444P10 } ,
{ " 444p9 " , IMGFMT_444P9 } ,
{ " 422p16 " , IMGFMT_422P16 } ,
{ " 422p10 " , IMGFMT_422P10 } ,
{ " 420p10 " , IMGFMT_420P10 } ,
{ " 420p9 " , IMGFMT_420P9 } ,
{ " 420p16 " , IMGFMT_420P16 } ,
{ " 420a " , IMGFMT_420A } ,
{ " 444p " , IMGFMT_444P } ,
{ " 422p " , IMGFMT_422P } ,
{ " 411p " , IMGFMT_411P } ,
{ " 440p " , IMGFMT_440P } ,
{ " yuy2 " , IMGFMT_YUY2 } ,
2011-06-21 19:34:00 +00:00
{ " yvyu " , IMGFMT_YVYU } ,
2011-07-03 12:42:04 +00:00
{ " uyvy " , IMGFMT_UYVY } ,
{ " yvu9 " , IMGFMT_YVU9 } ,
{ " if09 " , IMGFMT_IF09 } ,
{ " yv12 " , IMGFMT_YV12 } ,
{ " i420 " , IMGFMT_I420 } ,
{ " iyuv " , IMGFMT_IYUV } ,
{ " clpl " , IMGFMT_CLPL } ,
{ " hm12 " , IMGFMT_HM12 } ,
{ " y800 " , IMGFMT_Y800 } ,
{ " y8 " , IMGFMT_Y8 } ,
{ " nv12 " , IMGFMT_NV12 } ,
{ " nv21 " , IMGFMT_NV21 } ,
{ " bgr24 " , IMGFMT_BGR24 } ,
{ " bgr32 " , IMGFMT_BGR32 } ,
{ " bgr16 " , IMGFMT_BGR16 } ,
{ " bgr15 " , IMGFMT_BGR15 } ,
{ " bgr12 " , IMGFMT_BGR12 } ,
{ " bgr8 " , IMGFMT_BGR8 } ,
{ " bgr4 " , IMGFMT_BGR4 } ,
{ " bg4b " , IMGFMT_BG4B } ,
{ " bgr1 " , IMGFMT_BGR1 } ,
{ " rgb48be " , IMGFMT_RGB48BE } ,
{ " rgb48le " , IMGFMT_RGB48LE } ,
{ " rgb48ne " , IMGFMT_RGB48NE } ,
{ " rgb24 " , IMGFMT_RGB24 } ,
{ " rgb32 " , IMGFMT_RGB32 } ,
{ " rgb16 " , IMGFMT_RGB16 } ,
{ " rgb15 " , IMGFMT_RGB15 } ,
{ " rgb12 " , IMGFMT_RGB12 } ,
{ " rgb8 " , IMGFMT_RGB8 } ,
{ " rgb4 " , IMGFMT_RGB4 } ,
{ " rg4b " , IMGFMT_RG4B } ,
{ " rgb1 " , IMGFMT_RGB1 } ,
{ " rgba " , IMGFMT_RGBA } ,
{ " argb " , IMGFMT_ARGB } ,
{ " bgra " , IMGFMT_BGRA } ,
{ " abgr " , IMGFMT_ABGR } ,
2012-03-25 21:12:25 +00:00
{ " gbrp " , IMGFMT_GBRP } ,
2011-07-03 12:42:04 +00:00
{ " mjpeg " , IMGFMT_MJPEG } ,
{ " mjpg " , IMGFMT_MJPEG } ,
{ NULL , 0 }
2003-03-15 20:49:39 +00:00
} ;
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
static int parse_imgfmt ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
uint32_t fmt = 0 ;
int i ;
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
if ( ! bstrcmp0 ( param , " help " ) ) {
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " Available formats: " ) ;
for ( i = 0 ; mp_imgfmt_list [ i ] . name ; i + + )
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " %s " , mp_imgfmt_list [ i ] . name ) ;
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " \n " ) ;
return M_OPT_EXIT - 1 ;
}
2002-11-12 01:56:42 +00:00
2011-07-28 08:07:47 +00:00
if ( bstr_startswith0 ( param , " 0x " ) )
fmt = bstrtoll ( param , NULL , 16 ) ;
else {
2011-07-03 12:42:04 +00:00
for ( i = 0 ; mp_imgfmt_list [ i ] . name ; i + + ) {
2011-07-28 08:07:47 +00:00
if ( ! bstrcasecmp0 ( param , mp_imgfmt_list [ i ] . name ) ) {
2011-07-03 12:42:04 +00:00
fmt = mp_imgfmt_list [ i ] . fmt ;
break ;
}
}
if ( ! mp_imgfmt_list [ i ] . name ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: unknown format name: '%.*s' \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
}
if ( dst )
* ( ( uint32_t * ) dst ) = fmt ;
return 1 ;
2002-11-12 01:56:42 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_imgfmt = {
2011-07-03 12:42:04 +00:00
" Image format " ,
" Please report any missing colorspaces. " ,
sizeof ( uint32_t ) ,
0 ,
parse_imgfmt ,
NULL ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2002-11-12 01:56:42 +00:00
} ;
2004-12-27 17:32:54 +00:00
# include "libaf/af_format.h"
/* FIXME: snyc with af_format.h */
static struct {
2011-07-03 12:42:04 +00:00
const char * name ;
unsigned int fmt ;
2004-12-27 17:32:54 +00:00
} mp_afmt_list [ ] = {
2011-07-03 12:42:04 +00:00
// SPECIAL
{ " mulaw " , AF_FORMAT_MU_LAW } ,
{ " alaw " , AF_FORMAT_A_LAW } ,
{ " mpeg2 " , AF_FORMAT_MPEG2 } ,
{ " ac3le " , AF_FORMAT_AC3_LE } ,
{ " ac3be " , AF_FORMAT_AC3_BE } ,
{ " ac3ne " , AF_FORMAT_AC3_NE } ,
{ " imaadpcm " , AF_FORMAT_IMA_ADPCM } ,
// ORDINARY
{ " u8 " , AF_FORMAT_U8 } ,
{ " s8 " , AF_FORMAT_S8 } ,
{ " u16le " , AF_FORMAT_U16_LE } ,
{ " u16be " , AF_FORMAT_U16_BE } ,
{ " u16ne " , AF_FORMAT_U16_NE } ,
{ " s16le " , AF_FORMAT_S16_LE } ,
{ " s16be " , AF_FORMAT_S16_BE } ,
{ " s16ne " , AF_FORMAT_S16_NE } ,
{ " u24le " , AF_FORMAT_U24_LE } ,
{ " u24be " , AF_FORMAT_U24_BE } ,
{ " u24ne " , AF_FORMAT_U24_NE } ,
{ " s24le " , AF_FORMAT_S24_LE } ,
{ " s24be " , AF_FORMAT_S24_BE } ,
{ " s24ne " , AF_FORMAT_S24_NE } ,
{ " u32le " , AF_FORMAT_U32_LE } ,
{ " u32be " , AF_FORMAT_U32_BE } ,
{ " u32ne " , AF_FORMAT_U32_NE } ,
{ " s32le " , AF_FORMAT_S32_LE } ,
{ " s32be " , AF_FORMAT_S32_BE } ,
{ " s32ne " , AF_FORMAT_S32_NE } ,
{ " floatle " , AF_FORMAT_FLOAT_LE } ,
{ " floatbe " , AF_FORMAT_FLOAT_BE } ,
{ " floatne " , AF_FORMAT_FLOAT_NE } ,
{ NULL , 0 }
2004-12-27 17:32:54 +00:00
} ;
2011-07-28 08:07:47 +00:00
static int parse_afmt ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
uint32_t fmt = 0 ;
int i ;
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2011-07-28 08:07:47 +00:00
if ( ! bstrcmp0 ( param , " help " ) ) {
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " Available formats: " ) ;
for ( i = 0 ; mp_afmt_list [ i ] . name ; i + + )
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " %s " , mp_afmt_list [ i ] . name ) ;
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " \n " ) ;
return M_OPT_EXIT - 1 ;
}
2011-07-28 08:07:47 +00:00
if ( bstr_startswith0 ( param , " 0x " ) )
fmt = bstrtoll ( param , NULL , 16 ) ;
else {
2011-07-03 12:42:04 +00:00
for ( i = 0 ; mp_afmt_list [ i ] . name ; i + + ) {
2011-07-28 08:07:47 +00:00
if ( ! bstrcasecmp0 ( param , mp_afmt_list [ i ] . name ) ) {
2011-07-03 12:42:04 +00:00
fmt = mp_afmt_list [ i ] . fmt ;
break ;
}
}
if ( ! mp_afmt_list [ i ] . name ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: unknown format name: '%.*s' \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
}
2004-12-27 17:32:54 +00:00
2011-07-03 12:42:04 +00:00
if ( dst )
* ( ( uint32_t * ) dst ) = fmt ;
2004-12-27 17:32:54 +00:00
2011-07-03 12:42:04 +00:00
return 1 ;
2004-12-27 17:32:54 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_afmt = {
2011-07-03 12:42:04 +00:00
" Audio format " ,
" Please report any missing formats. " ,
sizeof ( uint32_t ) ,
0 ,
parse_afmt ,
NULL ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2004-12-27 17:32:54 +00:00
} ;
2011-07-28 08:07:47 +00:00
static int parse_timestring ( struct bstr str , double * time , char endchar )
2007-02-24 07:11:57 +00:00
{
2011-07-03 12:42:04 +00:00
int a , b , len ;
double d ;
* time = 0 ; /* ensure initialization for error cases */
2011-07-28 08:07:47 +00:00
if ( bstr_sscanf ( str , " %d:%d:%lf%n " , & a , & b , & d , & len ) > = 3 )
2011-07-03 12:42:04 +00:00
* time = 3600 * a + 60 * b + d ;
2011-07-28 08:07:47 +00:00
else if ( bstr_sscanf ( str , " %d:%lf%n " , & a , & d , & len ) > = 2 )
2011-07-03 12:42:04 +00:00
* time = 60 * a + d ;
2011-07-28 08:07:47 +00:00
else if ( bstr_sscanf ( str , " %lf%n " , & d , & len ) > = 1 )
2011-07-03 12:42:04 +00:00
* time = d ;
else
return 0 ; /* unsupported time format */
2011-07-28 08:07:47 +00:00
if ( len < str . len & & str . start [ len ] ! = endchar )
2011-07-03 12:42:04 +00:00
return 0 ; /* invalid extra characters at the end */
return len ;
2007-02-24 07:11:57 +00:00
}
2009-07-06 23:26:13 +00:00
2007-02-24 07:11:57 +00:00
2011-07-28 08:07:47 +00:00
static int parse_time ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2007-02-24 07:11:57 +00:00
{
2011-07-03 12:42:04 +00:00
double time ;
2007-02-28 09:18:42 +00:00
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
if ( ! parse_timestring ( param , & time , 0 ) ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: invalid time: '%.*s' \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
if ( dst )
* ( double * ) dst = time ;
return 1 ;
2007-02-24 07:11:57 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_time = {
2011-07-03 12:42:04 +00:00
" Time " ,
" " ,
sizeof ( double ) ,
0 ,
parse_time ,
print_double ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2007-02-24 07:11:57 +00:00
} ;
2006-09-25 16:47:56 +00:00
// Time or size (-endpos)
2011-07-28 08:07:47 +00:00
static int parse_time_size ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
m_time_size_t ts ;
char unit [ 4 ] ;
double end_at ;
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2006-09-25 16:47:56 +00:00
2011-07-03 12:42:04 +00:00
ts . pos = 0 ;
/* End at size parsing */
2011-07-28 08:07:47 +00:00
if ( bstr_sscanf ( param , " %lf%3s " , & end_at , unit ) = = 2 ) {
2011-07-03 12:42:04 +00:00
ts . type = END_AT_SIZE ;
if ( ! strcasecmp ( unit , " b " ) )
;
else if ( ! strcasecmp ( unit , " kb " ) )
end_at * = 1024 ;
else if ( ! strcasecmp ( unit , " mb " ) )
end_at * = 1024 * 1024 ;
else if ( ! strcasecmp ( unit , " gb " ) )
end_at * = 1024 * 1024 * 1024 ;
else
ts . type = END_AT_NONE ;
if ( ts . type = = END_AT_SIZE ) {
ts . pos = end_at ;
goto out ;
}
2006-09-25 16:47:56 +00:00
}
2011-07-03 12:42:04 +00:00
/* End at time parsing. This has to be last because the parsing accepts
* even a number followed by garbage */
if ( ! parse_timestring ( param , & end_at , 0 ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: invalid time or size: '%.*s' \n " ,
BSTR_P ( name ) , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
ts . type = END_AT_TIME ;
ts . pos = end_at ;
2006-09-29 23:23:41 +00:00
out :
2011-07-03 12:42:04 +00:00
if ( dst )
* ( m_time_size_t * ) dst = ts ;
return 1 ;
2006-09-25 16:47:56 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_time_size = {
2011-07-03 12:42:04 +00:00
" Time or size " ,
" " ,
sizeof ( m_time_size_t ) ,
0 ,
parse_time_size ,
NULL ,
copy_opt ,
copy_opt ,
NULL ,
NULL
2006-09-25 16:47:56 +00:00
} ;
2009-07-06 23:26:13 +00:00
2003-08-17 13:51:04 +00:00
//// Objects (i.e. filters, etc) settings
2003-03-15 18:01:02 +00:00
# include "m_struct.h"
# undef VAL
2011-07-03 12:42:04 +00:00
# define VAL(x) (*(m_obj_settings_t **)(x))
2003-03-15 18:01:02 +00:00
2011-07-28 08:07:47 +00:00
static int find_obj_desc ( struct bstr name , const m_obj_list_t * l ,
2011-07-03 12:42:04 +00:00
const m_struct_t * * ret )
{
int i ;
char * n ;
for ( i = 0 ; l - > list [ i ] ; i + + ) {
n = M_ST_MB ( char * , l - > list [ i ] , l - > name_off ) ;
2011-07-28 08:07:47 +00:00
if ( ! bstrcmp0 ( name , n ) ) {
2011-07-03 12:42:04 +00:00
* ret = M_ST_MB ( m_struct_t * , l - > list [ i ] , l - > desc_off ) ;
return 1 ;
}
2003-03-15 18:01:02 +00:00
}
2011-07-03 12:42:04 +00:00
return 0 ;
2003-03-15 18:01:02 +00:00
}
2011-07-28 08:07:47 +00:00
static int get_obj_param ( struct bstr opt_name , struct bstr obj_name ,
const m_struct_t * desc , struct bstr str , int * nold ,
2011-07-03 12:42:04 +00:00
int oldmax , char * * dst )
{
const m_option_t * opt ;
int r ;
2011-07-28 08:07:47 +00:00
int eq = bstrchr ( str , ' = ' ) ;
2011-07-03 12:42:04 +00:00
2011-07-28 08:07:47 +00:00
if ( eq > 0 ) { // eq == 0 ignored
struct bstr p = bstr_cut ( str , eq + 1 ) ;
str = bstr_splice ( str , 0 , eq ) ;
opt = m_option_list_findb ( desc - > fields , str ) ;
2011-07-03 12:42:04 +00:00
if ( ! opt ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: %.*s doesn't have a %.*s parameter. \n " ,
BSTR_P ( opt_name ) , BSTR_P ( obj_name ) , BSTR_P ( str ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_UNKNOWN ;
}
2011-07-27 17:59:44 +00:00
r = m_option_parse ( opt , str , p , false , NULL ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
if ( r > M_OPT_EXIT )
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: "
" Error while parsing %.*s parameter %.*s (%.*s) \n " ,
BSTR_P ( opt_name ) , BSTR_P ( obj_name ) , BSTR_P ( str ) ,
BSTR_P ( p ) ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
if ( dst ) {
2011-07-28 08:07:47 +00:00
dst [ 0 ] = bstrdup0 ( NULL , str ) ;
dst [ 1 ] = bstrdup0 ( NULL , p ) ;
2011-07-03 12:42:04 +00:00
}
} else {
if ( ( * nold ) > = oldmax ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: %.*s has only %d params, so you can't give more than %d unnamed params. \n " ,
BSTR_P ( opt_name ) , BSTR_P ( obj_name ) , oldmax , oldmax ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_OUT_OF_RANGE ;
}
opt = & desc - > fields [ ( * nold ) ] ;
2011-07-28 08:07:47 +00:00
r = m_option_parse ( opt , bstr ( opt - > name ) , str , false , NULL ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
if ( r > M_OPT_EXIT )
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: "
" Error while parsing %.*s parameter %s (%.*s) \n " ,
BSTR_P ( opt_name ) , BSTR_P ( obj_name ) , opt - > name ,
BSTR_P ( str ) ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
if ( dst ) {
2011-07-05 22:24:24 +00:00
dst [ 0 ] = talloc_strdup ( NULL , opt - > name ) ;
2011-07-28 08:07:47 +00:00
dst [ 1 ] = bstrdup0 ( NULL , str ) ;
2011-07-03 12:42:04 +00:00
}
( * nold ) + + ;
}
2005-06-17 08:15:08 +00:00
return 1 ;
2003-03-15 18:01:02 +00:00
}
2011-07-28 08:07:47 +00:00
static int get_obj_params ( struct bstr opt_name , struct bstr name ,
struct bstr params , const m_struct_t * desc ,
char separator , char * * * _ret )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
int n = 0 , nold = 0 , nopts ;
2011-07-03 12:42:04 +00:00
char * * ret ;
2011-07-28 08:07:47 +00:00
if ( ! bstrcmp0 ( params , " help " ) ) { // Help
2011-07-03 12:42:04 +00:00
char min [ 50 ] , max [ 50 ] ;
if ( ! desc - > fields ) {
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO ,
" %.*s doesn't have any options. \n \n " , BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_EXIT - 1 ;
}
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO ,
" \n Name Type Min Max \n \n " ) ;
2011-07-03 12:42:04 +00:00
for ( n = 0 ; desc - > fields [ n ] . name ; n + + ) {
const m_option_t * opt = & desc - > fields [ n ] ;
if ( opt - > type - > flags & M_OPT_TYPE_HAS_CHILD )
continue ;
if ( opt - > flags & M_OPT_MIN )
sprintf ( min , " %-8.0f " , opt - > min ) ;
else
strcpy ( min , " No " ) ;
if ( opt - > flags & M_OPT_MAX )
sprintf ( max , " %-8.0f " , opt - > max ) ;
else
strcpy ( max , " No " ) ;
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO ,
" %-20.20s %-15.15s %-10.10s %-10.10s \n " ,
opt - > name , opt - > type - > name , min , max ) ;
2011-07-03 12:42:04 +00:00
}
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " \n " ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_EXIT - 1 ;
}
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
for ( nopts = 0 ; desc - > fields [ nopts ] . name ; nopts + + )
/* NOP */ ;
// TODO : Check that each opt can be parsed
2011-07-28 08:07:47 +00:00
struct bstr s = params ;
while ( 1 ) {
bool end = false ;
int idx = bstrchr ( s , separator ) ;
if ( idx < 0 ) {
idx = s . len ;
end = true ;
2011-07-03 12:42:04 +00:00
}
2011-07-28 08:07:47 +00:00
struct bstr field = bstr_splice ( s , 0 , idx ) ;
s = bstr_cut ( s , idx + 1 ) ;
if ( field . len = = 0 ) { // Empty field, count it and go on
2011-07-03 12:42:04 +00:00
nold + + ;
2011-07-28 08:07:47 +00:00
} else {
int r = get_obj_param ( opt_name , name , desc , field , & nold , nopts ,
NULL ) ;
if ( r < 0 )
return r ;
n + + ;
2011-07-03 12:42:04 +00:00
}
2011-07-28 08:07:47 +00:00
if ( end )
2011-07-03 12:42:04 +00:00
break ;
}
if ( nold > nopts ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Too many options for %.*s \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_OUT_OF_RANGE ;
}
if ( ! _ret ) // Just test
return 1 ;
if ( n = = 0 ) // No options or only empty options
return 1 ;
2011-07-05 22:24:24 +00:00
ret = talloc_array ( NULL , char * , ( n + 2 ) * 2 ) ;
2011-07-03 12:42:04 +00:00
n = nold = 0 ;
2011-07-28 08:07:47 +00:00
s = params ;
while ( s . len > 0 ) {
int idx = bstrchr ( s , separator ) ;
if ( idx < 0 )
idx = s . len ;
struct bstr field = bstr_splice ( s , 0 , idx ) ;
s = bstr_cut ( s , idx + 1 ) ;
if ( field . len = = 0 ) { // Empty field, count it and go on
nold + + ;
} else {
get_obj_param ( opt_name , name , desc , field , & nold , nopts ,
2011-07-03 12:42:04 +00:00
& ret [ n * 2 ] ) ;
n + + ;
}
}
ret [ n * 2 ] = ret [ n * 2 + 1 ] = NULL ;
* _ret = ret ;
2009-07-06 23:26:13 +00:00
2005-06-17 08:15:08 +00:00
return 1 ;
2011-07-03 12:42:04 +00:00
}
2011-07-28 08:07:47 +00:00
static int parse_obj_params ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
char * * opts ;
int r ;
m_obj_params_t * p = opt - > priv ;
const m_struct_t * desc ;
// We need the object desc
if ( ! p )
return M_OPT_INVALID ;
2003-04-02 16:11:15 +00:00
2011-07-03 12:42:04 +00:00
desc = p - > desc ;
2011-07-28 08:07:47 +00:00
r = get_obj_params ( name , bstr ( desc - > name ) , param , desc , p - > separator ,
2011-07-03 12:42:04 +00:00
dst ? & opts : NULL ) ;
if ( r < 0 )
return r ;
if ( ! dst )
return 1 ;
if ( ! opts ) // no arguments given
return 1 ;
for ( r = 0 ; opts [ r ] ; r + = 2 )
2011-07-28 08:07:47 +00:00
m_struct_set ( desc , dst , opts [ r ] , bstr ( opts [ r + 1 ] ) ) ;
2003-04-02 16:11:15 +00:00
2011-07-03 12:42:04 +00:00
return 1 ;
2003-04-02 16:11:15 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_obj_params = {
2011-07-03 12:42:04 +00:00
" Object params " ,
" " ,
0 ,
0 ,
parse_obj_params ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL
2003-04-02 16:11:15 +00:00
} ;
2003-08-17 13:51:04 +00:00
/// Some predefined types as a definition would be quite lengthy
2003-04-02 16:11:15 +00:00
/// Span arguments
2011-07-03 12:42:04 +00:00
static const m_span_t m_span_params_dflts = {
- 1 , - 1
} ;
2007-11-09 06:50:53 +00:00
static const m_option_t m_span_params_fields [ ] = {
2011-07-03 12:42:04 +00:00
{ " start " , M_ST_OFF ( m_span_t , start ) , CONF_TYPE_INT , M_OPT_MIN , 1 , 0 , NULL } ,
{ " end " , M_ST_OFF ( m_span_t , end ) , CONF_TYPE_INT , M_OPT_MIN , 1 , 0 , NULL } ,
{ NULL , NULL , 0 , 0 , 0 , 0 , NULL }
2003-04-02 16:11:15 +00:00
} ;
2007-11-09 06:50:53 +00:00
static const struct m_struct_st m_span_opts = {
2011-07-03 12:42:04 +00:00
" m_span " ,
sizeof ( m_span_t ) ,
& m_span_params_dflts ,
m_span_params_fields
2003-04-02 16:11:15 +00:00
} ;
2007-11-09 06:50:53 +00:00
const m_obj_params_t m_span_params_def = {
2011-07-03 12:42:04 +00:00
& m_span_opts ,
' - '
2003-04-02 16:11:15 +00:00
} ;
2003-03-15 18:01:02 +00:00
2011-07-28 08:07:47 +00:00
static int parse_obj_settings ( struct bstr opt , struct bstr str ,
2011-07-03 12:42:04 +00:00
const m_obj_list_t * list ,
m_obj_settings_t * * _ret , int ret_n )
{
int r ;
2011-07-28 08:07:47 +00:00
char * * plist = NULL ;
2011-07-03 12:42:04 +00:00
const m_struct_t * desc ;
m_obj_settings_t * ret = _ret ? * _ret : NULL ;
2011-07-28 08:07:47 +00:00
struct bstr param = bstr ( NULL ) ;
int idx = bstrchr ( str , ' = ' ) ;
if ( idx > = 0 ) {
param = bstr_cut ( str , idx + 1 ) ;
str = bstr_splice ( str , 0 , idx ) ;
2011-07-03 12:42:04 +00:00
}
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
if ( ! find_obj_desc ( str , list , & desc ) ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: %.*s doesn't exist. \n " ,
BSTR_P ( opt ) , BSTR_P ( str ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
2003-03-15 18:01:02 +00:00
2011-07-28 08:07:47 +00:00
if ( param . start ) {
2011-07-03 12:42:04 +00:00
if ( ! desc & & _ret ) {
2011-07-28 08:07:47 +00:00
if ( ! bstrcmp0 ( param , " help " ) ) {
2011-07-03 12:42:04 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO ,
2011-07-28 08:07:47 +00:00
" Option %.*s: %.*s have no option description. \n " ,
BSTR_P ( opt ) , BSTR_P ( str ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_EXIT - 1 ;
}
2011-07-05 22:24:24 +00:00
plist = talloc_zero_array ( NULL , char * , 4 ) ;
plist [ 0 ] = talloc_strdup ( NULL , " _oldargs_ " ) ;
2011-07-28 08:07:47 +00:00
plist [ 1 ] = bstrdup0 ( NULL , param ) ;
2011-07-03 12:42:04 +00:00
} else if ( desc ) {
r = get_obj_params ( opt , str , param , desc , ' : ' ,
_ret ? & plist : NULL ) ;
if ( r < 0 )
return r ;
}
}
if ( ! _ret )
return 1 ;
2003-03-15 18:01:02 +00:00
2011-07-05 22:24:24 +00:00
ret = talloc_realloc ( NULL , ret , struct m_obj_settings , ret_n + 2 ) ;
2011-07-03 12:42:04 +00:00
memset ( & ret [ ret_n ] , 0 , 2 * sizeof ( m_obj_settings_t ) ) ;
2011-07-28 08:07:47 +00:00
ret [ ret_n ] . name = bstrdup0 ( NULL , str ) ;
2011-07-03 12:42:04 +00:00
ret [ ret_n ] . attribs = plist ;
2003-03-15 18:01:02 +00:00
2011-07-03 12:42:04 +00:00
* _ret = ret ;
2003-03-15 18:01:02 +00:00
return 1 ;
}
2011-07-28 08:07:47 +00:00
static int obj_settings_list_del ( struct bstr opt_name , struct bstr param ,
2011-07-27 17:59:44 +00:00
bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
char * * str_list = NULL ;
int r , i , idx_max = 0 ;
char * rem_id = " _removed_marker_ " ;
2011-07-28 08:07:47 +00:00
char name [ 100 ] ;
assert ( opt_name . len < 100 ) ;
memcpy ( name , opt_name . start , opt_name . len ) ;
name [ opt_name . len ] = 0 ;
2011-07-03 12:42:04 +00:00
const m_option_t list_opt = {
2011-07-28 08:07:47 +00:00
name , NULL , CONF_TYPE_STRING_LIST ,
2011-07-03 12:42:04 +00:00
0 , 0 , 0 , NULL
} ;
m_obj_settings_t * obj_list = dst ? VAL ( dst ) : NULL ;
if ( dst & & ! obj_list ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_WARN , " Option %.*s: the list is empty. \n " ,
BSTR_P ( opt_name ) ) ;
2011-07-03 12:42:04 +00:00
return 1 ;
} else if ( obj_list ) {
for ( idx_max = 0 ; obj_list [ idx_max ] . name ! = NULL ; idx_max + + )
/* NOP */ ;
}
2003-04-12 13:45:43 +00:00
2011-07-27 17:59:44 +00:00
r = m_option_parse ( & list_opt , opt_name , param , false , & str_list ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 | | ! str_list )
return r ;
for ( r = 0 ; str_list [ r ] ; r + + ) {
int id ;
char * endptr ;
id = strtol ( str_list [ r ] , & endptr , 0 ) ;
if ( endptr = = str_list [ r ] ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: invalid parameter. We need a list of integers which are the indices of the elements to remove. \n " , BSTR_P ( opt_name ) ) ;
2011-07-03 12:42:04 +00:00
m_option_free ( & list_opt , & str_list ) ;
return M_OPT_INVALID ;
}
if ( ! obj_list )
continue ;
if ( id > = idx_max | | id < - idx_max ) {
mp_msg ( MSGT_CFGPARSER , MSGL_WARN ,
2011-07-28 08:07:47 +00:00
" Option %.*s: Index %d is out of range. \n " ,
BSTR_P ( opt_name ) , id ) ;
2011-07-03 12:42:04 +00:00
continue ;
}
if ( id < 0 )
id = idx_max + id ;
2011-07-05 22:24:24 +00:00
talloc_free ( obj_list [ id ] . name ) ;
2011-07-03 12:42:04 +00:00
free_str_list ( & ( obj_list [ id ] . attribs ) ) ;
obj_list [ id ] . name = rem_id ;
}
2003-04-12 13:45:43 +00:00
2011-07-03 12:42:04 +00:00
if ( ! dst ) {
m_option_free ( & list_opt , & str_list ) ;
return 1 ;
}
2003-04-12 13:45:43 +00:00
2011-07-03 12:42:04 +00:00
for ( i = 0 ; obj_list [ i ] . name ; i + + ) {
while ( obj_list [ i ] . name = = rem_id ) {
memmove ( & obj_list [ i ] , & obj_list [ i + 1 ] ,
sizeof ( m_obj_settings_t ) * ( idx_max - i ) ) ;
idx_max - - ;
}
2003-04-12 13:45:43 +00:00
}
2011-07-05 22:24:24 +00:00
obj_list = talloc_realloc ( NULL , obj_list , struct m_obj_settings ,
idx_max + 1 ) ;
2011-07-03 12:42:04 +00:00
VAL ( dst ) = obj_list ;
2003-04-12 13:45:43 +00:00
2011-07-03 12:42:04 +00:00
return 1 ;
2003-04-12 13:45:43 +00:00
}
2003-03-15 18:01:02 +00:00
2011-07-03 12:42:04 +00:00
static void free_obj_settings_list ( void * dst )
{
int n ;
m_obj_settings_t * d ;
2010-10-01 18:29:35 +00:00
2011-07-03 12:42:04 +00:00
if ( ! dst | | ! VAL ( dst ) )
return ;
2010-10-01 18:29:35 +00:00
2011-07-03 12:42:04 +00:00
d = VAL ( dst ) ;
for ( n = 0 ; d [ n ] . name ; n + + ) {
2011-07-05 22:24:24 +00:00
talloc_free ( d [ n ] . name ) ;
2011-07-03 12:42:04 +00:00
free_str_list ( & ( d [ n ] . attribs ) ) ;
}
2011-07-05 22:24:24 +00:00
talloc_free ( d ) ;
2011-07-03 12:42:04 +00:00
VAL ( dst ) = NULL ;
2010-10-01 18:29:35 +00:00
}
2011-07-28 08:07:47 +00:00
static int parse_obj_settings_list ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param ,
2011-07-27 17:59:44 +00:00
void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
int len = strlen ( opt - > name ) ;
2011-07-03 12:42:04 +00:00
m_obj_settings_t * res = NULL , * queue = NULL , * head = NULL ;
int op = OP_NONE ;
// We need the objects list
if ( ! opt - > priv )
return M_OPT_INVALID ;
2003-03-15 18:01:02 +00:00
2011-07-28 08:07:47 +00:00
if ( opt - > name [ len - 1 ] = = ' * ' & & ( name . len > len - 1 ) ) {
struct bstr suffix = bstr_cut ( name , len - 1 ) ;
if ( bstrcasecmp0 ( suffix , " -add " ) = = 0 )
2011-07-03 12:42:04 +00:00
op = OP_ADD ;
2011-07-28 08:07:47 +00:00
else if ( bstrcasecmp0 ( suffix , " -pre " ) = = 0 )
2011-07-03 12:42:04 +00:00
op = OP_PRE ;
2011-07-28 08:07:47 +00:00
else if ( bstrcasecmp0 ( suffix , " -del " ) = = 0 )
2011-07-03 12:42:04 +00:00
op = OP_DEL ;
2011-07-28 08:07:47 +00:00
else if ( bstrcasecmp0 ( suffix , " -clr " ) = = 0 )
2011-07-03 12:42:04 +00:00
op = OP_CLR ;
else {
char prefix [ len ] ;
strncpy ( prefix , opt - > name , len - 1 ) ;
prefix [ len - 1 ] = ' \0 ' ;
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
" Option %.*s: unknown postfix %.*s \n "
2011-07-03 12:42:04 +00:00
" Supported postfixes are: \n "
" %s-add \n "
" Append the given list to the current list \n \n "
" %s-pre \n "
" Prepend the given list to the current list \n \n "
" %s-del x,y,... \n "
" Remove the given elements. Take the list element index (starting from 0). \n "
" Negative index can be used (i.e. -1 is the last element) \n \n "
" %s-clr \n "
" Clear the current list. \n " ,
2011-07-28 08:07:47 +00:00
BSTR_P ( name ) , BSTR_P ( suffix ) , prefix , prefix , prefix , prefix ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_UNKNOWN ;
}
}
2003-03-15 18:01:02 +00:00
2011-07-03 12:42:04 +00:00
// Clear the list ??
if ( op = = OP_CLR ) {
if ( dst )
free_obj_settings_list ( dst ) ;
return 0 ;
}
2003-03-15 18:01:02 +00:00
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
switch ( op ) {
case OP_ADD :
if ( dst )
head = VAL ( dst ) ;
break ;
case OP_PRE :
if ( dst )
queue = VAL ( dst ) ;
break ;
case OP_DEL :
2011-07-27 17:59:44 +00:00
return obj_settings_list_del ( name , param , false , dst ) ;
2011-07-03 12:42:04 +00:00
case OP_NONE :
if ( dst & & VAL ( dst ) )
free_obj_settings_list ( dst ) ;
break ;
default :
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: FIXME \n " , BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_UNKNOWN ;
2009-07-06 23:26:13 +00:00
}
2011-07-03 12:42:04 +00:00
2011-07-28 08:07:47 +00:00
if ( ! bstrcmp0 ( param , " help " ) ) {
2011-07-03 12:42:04 +00:00
m_obj_list_t * ol = opt - > priv ;
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " Available video filters: \n " ) ;
2011-07-28 08:07:47 +00:00
for ( int n = 0 ; ol - > list [ n ] ; n + + )
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " %-15s: %s \n " ,
2011-07-03 12:42:04 +00:00
M_ST_MB ( char * , ol - > list [ n ] , ol - > name_off ) ,
M_ST_MB ( char * , ol - > list [ n ] , ol - > info_off ) ) ;
2011-07-31 17:40:05 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " \n " ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_EXIT - 1 ;
}
2011-07-28 08:07:47 +00:00
struct bstr s = bstrdup ( NULL , param ) ;
char * allocptr = s . start ;
int n = 0 ;
while ( s . len > 0 ) {
struct bstr el = get_nextsep ( & s , OPTION_LIST_SEPARATOR , 1 ) ;
int r = parse_obj_settings ( name , el , opt - > priv , dst ? & res : NULL , n ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
2011-07-28 08:07:47 +00:00
talloc_free ( allocptr ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
2011-07-28 08:07:47 +00:00
s = bstr_cut ( s , 1 ) ;
2011-07-03 12:42:04 +00:00
n + + ;
}
2011-07-28 08:07:47 +00:00
talloc_free ( allocptr ) ;
2011-07-03 12:42:04 +00:00
if ( n = = 0 )
return M_OPT_INVALID ;
if ( ( ( opt - > flags & M_OPT_MIN ) & & ( n < opt - > min ) ) | |
( ( opt - > flags & M_OPT_MAX ) & & ( n > opt - > max ) ) )
return M_OPT_OUT_OF_RANGE ;
if ( dst ) {
if ( queue ) {
int qsize ;
for ( qsize = 0 ; queue [ qsize ] . name ; qsize + + )
/* NOP */ ;
2011-07-05 22:24:24 +00:00
res = talloc_realloc ( NULL , res , struct m_obj_settings ,
qsize + n + 1 ) ;
2011-07-03 12:42:04 +00:00
memcpy ( & res [ n ] , queue , ( qsize + 1 ) * sizeof ( m_obj_settings_t ) ) ;
n + = qsize ;
2011-07-05 22:24:24 +00:00
talloc_free ( queue ) ;
2011-07-03 12:42:04 +00:00
}
if ( head ) {
int hsize ;
for ( hsize = 0 ; head [ hsize ] . name ; hsize + + )
/* NOP */ ;
2011-07-05 22:24:24 +00:00
head = talloc_realloc ( NULL , head , struct m_obj_settings ,
hsize + n + 1 ) ;
2011-07-03 12:42:04 +00:00
memcpy ( & head [ hsize ] , res , ( n + 1 ) * sizeof ( m_obj_settings_t ) ) ;
2011-07-05 22:24:24 +00:00
talloc_free ( res ) ;
2011-07-03 12:42:04 +00:00
res = head ;
}
VAL ( dst ) = res ;
}
return 1 ;
2003-03-15 18:01:02 +00:00
}
2011-07-03 12:42:04 +00:00
static void copy_obj_settings_list ( const m_option_t * opt , void * dst ,
const void * src )
{
m_obj_settings_t * d , * s ;
int n ;
2003-03-15 18:01:02 +00:00
2011-07-03 12:42:04 +00:00
if ( ! ( dst & & src ) )
return ;
2003-03-15 18:01:02 +00:00
2011-07-03 12:42:04 +00:00
s = VAL ( src ) ;
2003-03-15 18:01:02 +00:00
2011-07-03 12:42:04 +00:00
if ( VAL ( dst ) )
free_obj_settings_list ( dst ) ;
if ( ! s )
return ;
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
for ( n = 0 ; s [ n ] . name ; n + + )
/* NOP */ ;
2011-07-05 22:24:24 +00:00
d = talloc_array ( NULL , struct m_obj_settings , n + 1 ) ;
2011-07-03 12:42:04 +00:00
for ( n = 0 ; s [ n ] . name ; n + + ) {
2011-07-05 22:24:24 +00:00
d [ n ] . name = talloc_strdup ( NULL , s [ n ] . name ) ;
2011-07-03 12:42:04 +00:00
d [ n ] . attribs = NULL ;
copy_str_list ( NULL , & ( d [ n ] . attribs ) , & ( s [ n ] . attribs ) ) ;
}
d [ n ] . name = NULL ;
2003-03-15 18:01:02 +00:00
d [ n ] . attribs = NULL ;
2011-07-03 12:42:04 +00:00
VAL ( dst ) = d ;
2003-03-15 18:01:02 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_obj_settings_list = {
2011-07-03 12:42:04 +00:00
" Object settings list " ,
" " ,
sizeof ( m_obj_settings_t * ) ,
M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD ,
parse_obj_settings_list ,
NULL ,
copy_obj_settings_list ,
copy_obj_settings_list ,
copy_obj_settings_list ,
free_obj_settings_list ,
2003-03-15 18:01:02 +00:00
} ;
2011-07-28 08:07:47 +00:00
static int parse_obj_presets ( const m_option_t * opt , struct bstr name ,
struct bstr param , bool ambiguous_param ,
2011-07-27 17:59:44 +00:00
void * dst )
2011-07-03 12:42:04 +00:00
{
m_obj_presets_t * obj_p = ( m_obj_presets_t * ) opt - > priv ;
const m_struct_t * in_desc ;
const m_struct_t * out_desc ;
int s , i ;
const unsigned char * pre ;
char * pre_name = NULL ;
if ( ! obj_p ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: Presets need a "
" pointer to a m_obj_presets_t in the priv field. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_PARSER_ERR ;
}
2011-07-28 08:07:47 +00:00
if ( param . len = = 0 )
2011-07-03 12:42:04 +00:00
return M_OPT_MISSING_PARAM ;
2003-03-15 18:01:02 +00:00
2011-07-03 12:42:04 +00:00
pre = obj_p - > presets ;
in_desc = obj_p - > in_desc ;
out_desc = obj_p - > out_desc ? obj_p - > out_desc : obj_p - > in_desc ;
s = in_desc - > size ;
2011-07-28 08:07:47 +00:00
if ( ! bstrcmp0 ( param , " help " ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_INFO , " Available presets for %s->%.*s: " ,
out_desc - > name , BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
for ( pre = obj_p - > presets ;
( pre_name = M_ST_MB ( char * , pre , obj_p - > name_off ) ) ; pre + = s )
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " %s " , pre_name ) ;
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " \n " ) ;
return M_OPT_EXIT - 1 ;
}
2009-07-06 23:26:13 +00:00
2011-07-03 12:42:04 +00:00
for ( pre_name = M_ST_MB ( char * , pre , obj_p - > name_off ) ; pre_name ;
pre + = s , pre_name = M_ST_MB ( char * , pre , obj_p - > name_off ) )
2011-07-28 08:07:47 +00:00
if ( ! bstrcmp0 ( param , pre_name ) )
2011-07-03 12:42:04 +00:00
break ;
if ( ! pre_name ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: There is no preset named %.*s \n "
" Available presets are: " , BSTR_P ( name ) , BSTR_P ( param ) ) ;
2011-07-03 12:42:04 +00:00
for ( pre = obj_p - > presets ;
( pre_name = M_ST_MB ( char * , pre , obj_p - > name_off ) ) ; pre + = s )
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " %s " , pre_name ) ;
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " \n " ) ;
return M_OPT_INVALID ;
2003-03-15 18:01:02 +00:00
}
2011-07-03 12:42:04 +00:00
if ( ! dst )
return 1 ;
for ( i = 0 ; in_desc - > fields [ i ] . name ; i + + ) {
const m_option_t * out_opt = m_option_list_find ( out_desc - > fields ,
in_desc - > fields [ i ] . name ) ;
if ( ! out_opt ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: Unable to find the target option for field %s. \n "
" Please report this to the developers. \n " ,
BSTR_P ( name ) , in_desc - > fields [ i ] . name ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_PARSER_ERR ;
}
m_option_copy ( out_opt , M_ST_MB_P ( dst , out_opt - > p ) ,
M_ST_MB_P ( pre , in_desc - > fields [ i ] . p ) ) ;
}
return 1 ;
2003-03-15 18:01:02 +00:00
}
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_obj_presets = {
2011-07-03 12:42:04 +00:00
" Object presets " ,
" " ,
0 ,
0 ,
parse_obj_presets ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL
2003-03-15 18:01:02 +00:00
} ;
2011-07-28 08:07:47 +00:00
static int parse_custom_url ( const m_option_t * opt , struct bstr name ,
struct bstr url , bool ambiguous_param , void * dst )
2011-07-03 12:42:04 +00:00
{
2011-07-28 08:07:47 +00:00
int r ;
2011-07-03 12:42:04 +00:00
m_struct_t * desc = opt - > priv ;
if ( ! desc ) {
2011-07-28 08:07:47 +00:00
mp_msg ( MSGT_CFGPARSER , MSGL_ERR , " Option %.*s: Custom URL needs "
" a pointer to a m_struct_t in the priv field. \n " , BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_PARSER_ERR ;
}
// extract the protocol
2011-07-28 08:07:47 +00:00
int idx = bstr_find0 ( url , " :// " ) ;
if ( idx < 0 ) {
2011-07-03 12:42:04 +00:00
// Filename only
if ( m_option_list_find ( desc - > fields , " filename " ) ) {
m_struct_set ( desc , dst , " filename " , url ) ;
return 1 ;
}
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: URL doesn't have a valid protocol! \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return M_OPT_INVALID ;
}
2011-07-28 08:07:47 +00:00
struct bstr ptr1 = bstr_cut ( url , idx + 3 ) ;
2011-07-03 12:42:04 +00:00
if ( m_option_list_find ( desc - > fields , " string " ) ) {
2011-07-28 08:07:47 +00:00
if ( ptr1 . len > 0 ) {
m_struct_set ( desc , dst , " string " , ptr1 ) ;
2011-07-03 12:42:04 +00:00
return 1 ;
}
}
if ( dst & & m_option_list_find ( desc - > fields , " protocol " ) ) {
2011-07-28 08:07:47 +00:00
r = m_struct_set ( desc , dst , " protocol " , bstr_splice ( url , 0 , idx ) ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: Error while setting protocol. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
}
// check if a username:password is given
2011-07-28 08:07:47 +00:00
idx = bstrchr ( ptr1 , ' / ' ) ;
if ( idx < 0 )
idx = ptr1 . len ;
struct bstr hostpart = bstr_splice ( ptr1 , 0 , idx ) ;
struct bstr path = bstr_cut ( ptr1 , idx ) ;
idx = bstrchr ( hostpart , ' @ ' ) ;
if ( idx > = 0 ) {
2011-07-03 12:42:04 +00:00
// We got something, at least a username...
if ( ! m_option_list_find ( desc - > fields , " username " ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_WARN ,
2011-07-28 08:07:47 +00:00
" Option %.*s: This URL doesn't have a username part. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
// skip
} else {
2011-07-28 08:07:47 +00:00
struct bstr userpass = bstr_splice ( hostpart , 0 , idx ) ;
idx = bstrchr ( userpass , ' : ' ) ;
if ( idx > = 0 ) {
2011-07-03 12:42:04 +00:00
// We also have a password
if ( ! m_option_list_find ( desc - > fields , " password " ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_WARN ,
2011-07-28 08:07:47 +00:00
" Option %.*s: This URL doesn't have a password part. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
// skip
} else { // Username and password
if ( dst ) {
2011-07-28 08:07:47 +00:00
r = m_struct_set ( desc , dst , " username " ,
bstr_splice ( userpass , 0 , idx ) ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: Error while setting username. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
2011-07-28 08:07:47 +00:00
r = m_struct_set ( desc , dst , " password " ,
bstr_splice ( userpass , idx + 1 ,
userpass . len ) ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: Error while setting password. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
}
}
} else { // User name only
2011-07-28 08:07:47 +00:00
r = m_struct_set ( desc , dst , " username " , userpass ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: Error while setting username. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
}
}
2011-07-28 08:07:47 +00:00
hostpart = bstr_cut ( hostpart , idx + 1 ) ;
2011-07-03 12:42:04 +00:00
}
// Before looking for a port number check if we have an IPv6 type
// numeric address.
// In an IPv6 URL the numeric address should be inside square braces.
2011-07-28 08:07:47 +00:00
int idx1 = bstrchr ( hostpart , ' [ ' ) ;
int idx2 = bstrchr ( hostpart , ' ] ' ) ;
struct bstr portstr = hostpart ;
bool v6addr = false ;
if ( idx1 > = 0 & & idx2 > = 0 & & idx1 < idx2 ) {
2011-07-03 12:42:04 +00:00
// we have an IPv6 numeric address
2011-07-28 08:07:47 +00:00
portstr = bstr_cut ( hostpart , idx2 ) ;
hostpart = bstr_splice ( hostpart , idx1 + 1 , idx2 ) ;
v6addr = true ;
}
idx = bstrchr ( portstr , ' : ' ) ;
if ( idx > = 0 ) {
if ( ! v6addr )
hostpart = bstr_splice ( hostpart , 0 , idx ) ;
2011-07-03 12:42:04 +00:00
// We have an URL beginning like http://www.hostname.com:1212
// Get the port number
if ( ! m_option_list_find ( desc - > fields , " port " ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_WARN ,
2011-07-28 08:07:47 +00:00
" Option %.*s: This URL doesn't have a port part. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
// skip
} else {
if ( dst ) {
2011-07-28 08:07:47 +00:00
int p = bstrtoll ( bstr_cut ( portstr , idx + 1 ) , NULL , 0 ) ;
2011-07-03 12:42:04 +00:00
char tmp [ 100 ] ;
snprintf ( tmp , 99 , " %d " , p ) ;
2011-07-28 08:07:47 +00:00
r = m_struct_set ( desc , dst , " port " , bstr ( tmp ) ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: Error while setting port. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
}
}
}
// Get the hostname
2011-07-28 08:07:47 +00:00
if ( hostpart . len > 0 ) {
2011-07-03 12:42:04 +00:00
if ( ! m_option_list_find ( desc - > fields , " hostname " ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_WARN ,
2011-07-28 08:07:47 +00:00
" Option %.*s: This URL doesn't have a hostname part. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
// skip
} else {
2011-07-28 08:07:47 +00:00
r = m_struct_set ( desc , dst , " hostname " , hostpart ) ;
2011-07-03 12:42:04 +00:00
if ( r < 0 ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
2011-07-28 08:07:47 +00:00
" Option %.*s: Error while setting hostname. \n " ,
BSTR_P ( name ) ) ;
2011-07-03 12:42:04 +00:00
return r ;
}
}
}
2003-04-02 16:11:15 +00:00
// Look if a path is given
2011-07-28 08:07:47 +00:00
if ( path . len > 1 ) { // not just "/"
// copy the path/filename in the URL container
if ( ! m_option_list_find ( desc - > fields , " filename " ) ) {
mp_msg ( MSGT_CFGPARSER , MSGL_WARN ,
" Option %.*s: This URL doesn't have a filename part. \n " ,
BSTR_P ( name ) ) ;
// skip
} else {
if ( dst ) {
char * fname = bstrdup0 ( NULL , bstr_cut ( path , 1 ) ) ;
url_unescape_string ( fname , fname ) ;
r = m_struct_set ( desc , dst , " filename " , bstr ( fname ) ) ;
talloc_free ( fname ) ;
if ( r < 0 ) {
mp_msg ( MSGT_CFGPARSER , MSGL_ERR ,
" Option %.*s: Error while setting filename. \n " ,
BSTR_P ( name ) ) ;
return r ;
2011-07-03 12:42:04 +00:00
}
}
}
}
return 1 ;
2003-04-02 16:11:15 +00:00
}
/// TODO : Write the other needed funcs for 'normal' options
2007-11-09 06:50:53 +00:00
const m_option_type_t m_option_type_custom_url = {
2011-07-03 12:42:04 +00:00
" Custom URL " ,
" " ,
0 ,
0 ,
parse_custom_url ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL
2009-07-06 23:26:13 +00:00
} ;