configuration.c 59.2 KB
Newer Older
Gildas Bazin's avatar
 
Gildas Bazin committed
1 2 3
/*****************************************************************************
 * configuration.c management of the modules configuration
 *****************************************************************************
4
 * Copyright (C) 2001-2004 the VideoLAN team
5
 * $Id$
Gildas Bazin's avatar
 
Gildas Bazin committed
6
 *
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
Gildas Bazin's avatar
 
Gildas Bazin committed
8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
Gildas Bazin's avatar
 
Gildas Bazin committed
22
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
23

24
#include <vlc/vlc.h>
25
#include "vlc_keys.h"
Clément Stenac's avatar
Clément Stenac committed
26
#include "vlc_charset.h"
Gildas Bazin's avatar
 
Gildas Bazin committed
27

Gildas Bazin's avatar
 
Gildas Bazin committed
28
#include <stdio.h>                                              /* sprintf() */
Gildas Bazin's avatar
 
Gildas Bazin committed
29
#include <stdlib.h>                                      /* free(), strtol() */
Gildas Bazin's avatar
 
Gildas Bazin committed
30
#include <string.h>                                              /* strdup() */
31
#include <errno.h>                                                  /* errno */
Gildas Bazin's avatar
 
Gildas Bazin committed
32

Antoine Cellerier's avatar
Antoine Cellerier committed
33 34 35 36
#ifdef HAVE_LIMITS_H
#   include <limits.h>
#endif

Gildas Bazin's avatar
 
Gildas Bazin committed
37 38 39
#ifdef HAVE_UNISTD_H
#    include <unistd.h>                                          /* getuid() */
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
40

Gildas Bazin's avatar
 
Gildas Bazin committed
41 42 43 44 45
#ifdef HAVE_GETOPT_LONG
#   ifdef HAVE_GETOPT_H
#       include <getopt.h>                                       /* getopt() */
#   endif
#else
46
#   include "../extras/getopt.h"
Gildas Bazin's avatar
 
Gildas Bazin committed
47 48 49
#endif

#if defined(HAVE_GETPWUID)
50
#   include <pwd.h>                                            /* getpwuid() */
Gildas Bazin's avatar
 
Gildas Bazin committed
51 52
#endif

53 54 55 56 57 58
#if defined( HAVE_SYS_STAT_H )
#   include <sys/stat.h>
#endif
#if defined( HAVE_SYS_TYPES_H )
#   include <sys/types.h>
#endif
59 60 61 62 63
#if defined( WIN32 )
#   if !defined( UNDER_CE )
#       include <direct.h>
#   endif
#include <tchar.h>
64
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
65

Clément Stenac's avatar
Clément Stenac committed
66 67
#include "configuration.h"

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
68
static int ConfigStringToKey( const char * );
69
static char *ConfigKeyToString( int );
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
static inline void freenull (const void *p)
{
    if (p != NULL)
        free ((void *)p);
}

static inline char *strdupnull (const char *src)
{
    if (src == NULL)
        return NULL;
    return strdup (src);
}

static inline char *_strdupnull (const char *src)
{
    if (src == NULL)
        return NULL;
    return strdup (_(src));
}


Gildas Bazin's avatar
 
Gildas Bazin committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
/*****************************************************************************
 * config_GetType: get the type of a variable (bool, int, float, string)
 *****************************************************************************
 * This function is used to get the type of a variable from its name.
 * Beware, this is quite slow.
 *****************************************************************************/
int __config_GetType( vlc_object_t *p_this, const char *psz_name )
{
    module_config_t *p_config;
    int i_type;

    p_config = config_FindConfig( p_this, psz_name );

    /* sanity checks */
    if( !p_config )
    {
        return 0;
    }

    switch( p_config->i_type )
    {
    case CONFIG_ITEM_BOOL:
        i_type = VLC_VAR_BOOL;
        break;

    case CONFIG_ITEM_INTEGER:
        i_type = VLC_VAR_INTEGER;
        break;

    case CONFIG_ITEM_FLOAT:
        i_type = VLC_VAR_FLOAT;
        break;

    case CONFIG_ITEM_MODULE:
126 127 128
    case CONFIG_ITEM_MODULE_CAT:
    case CONFIG_ITEM_MODULE_LIST:
    case CONFIG_ITEM_MODULE_LIST_CAT:
Gildas Bazin's avatar
 
Gildas Bazin committed
129 130 131
        i_type = VLC_VAR_MODULE;
        break;

Gildas Bazin's avatar
 
Gildas Bazin committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    case CONFIG_ITEM_STRING:
        i_type = VLC_VAR_STRING;
        break;

    case CONFIG_ITEM_FILE:
        i_type = VLC_VAR_FILE;
        break;

    case CONFIG_ITEM_DIRECTORY:
        i_type = VLC_VAR_DIRECTORY;
        break;

    default:
        i_type = 0;
        break;
    }

    return i_type;
}

Gildas Bazin's avatar
 
Gildas Bazin committed
152
/*****************************************************************************
153
 * config_GetInt: get the value of an int variable
Gildas Bazin's avatar
 
Gildas Bazin committed
154 155
 *****************************************************************************
 * This function is used to get the value of variables which are internally
Gildas Bazin's avatar
 
Gildas Bazin committed
156 157
 * represented by an integer (CONFIG_ITEM_INTEGER and
 * CONFIG_ITEM_BOOL).
Gildas Bazin's avatar
 
Gildas Bazin committed
158
 *****************************************************************************/
159
int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
Gildas Bazin's avatar
 
Gildas Bazin committed
160 161 162
{
    module_config_t *p_config;

163
    p_config = config_FindConfig( p_this, psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
164 165 166 167

    /* sanity checks */
    if( !p_config )
    {
168
        msg_Err( p_this, "option %s does not exist", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
169 170
        return -1;
    }
171 172

    if (!IsConfigIntegerType (p_config->i_type))
Gildas Bazin's avatar
 
Gildas Bazin committed
173
    {
174
        msg_Err( p_this, "option %s does not refer to an int", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
175 176 177
        return -1;
    }

178
    return p_config->value.i;
Gildas Bazin's avatar
 
Gildas Bazin committed
179 180
}

Gildas Bazin's avatar
 
Gildas Bazin committed
181
/*****************************************************************************
182
 * config_GetFloat: get the value of a float variable
Gildas Bazin's avatar
 
Gildas Bazin committed
183 184
 *****************************************************************************
 * This function is used to get the value of variables which are internally
Gildas Bazin's avatar
 
Gildas Bazin committed
185
 * represented by a float (CONFIG_ITEM_FLOAT).
Gildas Bazin's avatar
 
Gildas Bazin committed
186
 *****************************************************************************/
187
float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
Gildas Bazin's avatar
 
Gildas Bazin committed
188 189 190
{
    module_config_t *p_config;

191
    p_config = config_FindConfig( p_this, psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
192 193 194 195

    /* sanity checks */
    if( !p_config )
    {
196
        msg_Err( p_this, "option %s does not exist", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
197 198
        return -1;
    }
199 200

    if (!IsConfigFloatType (p_config->i_type))
Gildas Bazin's avatar
 
Gildas Bazin committed
201
    {
202
        msg_Err( p_this, "option %s does not refer to a float", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
203 204 205
        return -1;
    }

206
    return p_config->value.f;
Gildas Bazin's avatar
 
Gildas Bazin committed
207 208
}

Gildas Bazin's avatar
 
Gildas Bazin committed
209
/*****************************************************************************
210
 * config_GetPsz: get the string value of a string variable
Gildas Bazin's avatar
 
Gildas Bazin committed
211 212
 *****************************************************************************
 * This function is used to get the value of variables which are internally
Gildas Bazin's avatar
 
Gildas Bazin committed
213
 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
Gildas Bazin's avatar
 
Gildas Bazin committed
214
 * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
Gildas Bazin's avatar
 
Gildas Bazin committed
215
 *
Gildas Bazin's avatar
 
Gildas Bazin committed
216 217 218
 * Important note: remember to free() the returned char* because it's a
 *   duplicate of the actual value. It isn't safe to return a pointer to the
 *   actual value as it can be modified at any time.
Gildas Bazin's avatar
 
Gildas Bazin committed
219
 *****************************************************************************/
220
char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
Gildas Bazin's avatar
 
Gildas Bazin committed
221 222 223
{
    module_config_t *p_config;

224
    p_config = config_FindConfig( p_this, psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
225 226 227 228

    /* sanity checks */
    if( !p_config )
    {
229
        msg_Err( p_this, "option %s does not exist", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
230 231
        return NULL;
    }
232 233

    if (!IsConfigStringType (p_config->i_type))
Gildas Bazin's avatar
 
Gildas Bazin committed
234
    {
235
        msg_Err( p_this, "option %s does not refer to a string", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
236 237 238 239
        return NULL;
    }

    /* return a copy of the string */
Gildas Bazin's avatar
 
Gildas Bazin committed
240
    vlc_mutex_lock( p_config->p_lock );
241
    char *psz_value = strdupnull (p_config->value.psz);
Gildas Bazin's avatar
 
Gildas Bazin committed
242
    vlc_mutex_unlock( p_config->p_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
243 244 245 246 247

    return psz_value;
}

/*****************************************************************************
248
 * config_PutPsz: set the string value of a string variable
Gildas Bazin's avatar
 
Gildas Bazin committed
249 250
 *****************************************************************************
 * This function is used to set the value of variables which are internally
Gildas Bazin's avatar
 
Gildas Bazin committed
251
 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
Gildas Bazin's avatar
 
Gildas Bazin committed
252
 * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
Gildas Bazin's avatar
 
Gildas Bazin committed
253
 *****************************************************************************/
254
void __config_PutPsz( vlc_object_t *p_this,
255
                      const char *psz_name, const char *psz_value )
Gildas Bazin's avatar
 
Gildas Bazin committed
256 257
{
    module_config_t *p_config;
Gildas Bazin's avatar
 
Gildas Bazin committed
258
    vlc_value_t oldval, val;
Gildas Bazin's avatar
 
Gildas Bazin committed
259

260
    p_config = config_FindConfig( p_this, psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
261

Clément Stenac's avatar
Clément Stenac committed
262

Gildas Bazin's avatar
 
Gildas Bazin committed
263 264 265
    /* sanity checks */
    if( !p_config )
    {
266
        msg_Warn( p_this, "option %s does not exist", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
267 268
        return;
    }
269 270

    if (!IsConfigStringType (p_config->i_type))
Gildas Bazin's avatar
 
Gildas Bazin committed
271
    {
272
        msg_Err( p_this, "option %s does not refer to a string", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
273 274 275
        return;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
276 277
    vlc_mutex_lock( p_config->p_lock );

Gildas Bazin's avatar
 
Gildas Bazin committed
278
    /* backup old value */
279
    oldval.psz_string = (char *)p_config->value.psz;
Gildas Bazin's avatar
 
Gildas Bazin committed
280

281 282 283 284
    if ((psz_value != NULL) && *psz_value)
        p_config->value.psz = strdup (psz_value);
    else
        p_config->value.psz = NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
285

286 287
    p_config->b_dirty = VLC_TRUE;

288
    val.psz_string = (char *)p_config->value.psz;
Gildas Bazin's avatar
 
Gildas Bazin committed
289

Gildas Bazin's avatar
 
Gildas Bazin committed
290
    vlc_mutex_unlock( p_config->p_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
291

292
    if( p_config->pf_callback )
293
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
294 295
        p_config->pf_callback( p_this, psz_name, oldval, val,
                               p_config->p_callback_data );
296
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
297 298 299

    /* free old string */
    if( oldval.psz_string ) free( oldval.psz_string );
Gildas Bazin's avatar
 
Gildas Bazin committed
300 301 302
}

/*****************************************************************************
303
 * config_PutInt: set the integer value of an int variable
Gildas Bazin's avatar
 
Gildas Bazin committed
304 305
 *****************************************************************************
 * This function is used to set the value of variables which are internally
Gildas Bazin's avatar
 
Gildas Bazin committed
306 307
 * represented by an integer (CONFIG_ITEM_INTEGER and
 * CONFIG_ITEM_BOOL).
Gildas Bazin's avatar
 
Gildas Bazin committed
308
 *****************************************************************************/
309
void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
Gildas Bazin's avatar
 
Gildas Bazin committed
310 311
{
    module_config_t *p_config;
Gildas Bazin's avatar
 
Gildas Bazin committed
312
    vlc_value_t oldval, val;
Gildas Bazin's avatar
 
Gildas Bazin committed
313

314
    p_config = config_FindConfig( p_this, psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
315 316 317 318

    /* sanity checks */
    if( !p_config )
    {
319
        msg_Warn( p_this, "option %s does not exist", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
320 321
        return;
    }
322 323

    if (!IsConfigIntegerType (p_config->i_type))
Gildas Bazin's avatar
 
Gildas Bazin committed
324
    {
325
        msg_Err( p_this, "option %s does not refer to an int", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
326 327 328
        return;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
329
    /* backup old value */
330
    oldval.i_int = p_config->value.i;
Gildas Bazin's avatar
 
Gildas Bazin committed
331

332
    /* if i_min == i_max == 0, then do not use them */
333
    if ((p_config->min.i == 0) && (p_config->max.i == 0))
334
    {
335
        p_config->value.i = i_value;
336
    }
337
    else if (i_value < p_config->min.i)
338
    {
339
        p_config->value.i = p_config->min.i;
340
    }
341
    else if (i_value > p_config->max.i)
342
    {
343
        p_config->value.i = p_config->max.i;
344 345 346
    }
    else
    {
347
        p_config->value.i = i_value;
348
    }
349

350 351
    p_config->b_dirty = VLC_TRUE;

352
    val.i_int = p_config->value.i;
Gildas Bazin's avatar
 
Gildas Bazin committed
353

354
    if( p_config->pf_callback )
355
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
356 357
        p_config->pf_callback( p_this, psz_name, oldval, val,
                               p_config->p_callback_data );
358
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
359 360
}

Gildas Bazin's avatar
 
Gildas Bazin committed
361
/*****************************************************************************
362
 * config_PutFloat: set the value of a float variable
Gildas Bazin's avatar
 
Gildas Bazin committed
363 364
 *****************************************************************************
 * This function is used to set the value of variables which are internally
Gildas Bazin's avatar
 
Gildas Bazin committed
365
 * represented by a float (CONFIG_ITEM_FLOAT).
Gildas Bazin's avatar
 
Gildas Bazin committed
366
 *****************************************************************************/
367 368
void __config_PutFloat( vlc_object_t *p_this,
                        const char *psz_name, float f_value )
Gildas Bazin's avatar
 
Gildas Bazin committed
369 370
{
    module_config_t *p_config;
Gildas Bazin's avatar
 
Gildas Bazin committed
371
    vlc_value_t oldval, val;
Gildas Bazin's avatar
 
Gildas Bazin committed
372

373
    p_config = config_FindConfig( p_this, psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
374 375 376 377

    /* sanity checks */
    if( !p_config )
    {
378
        msg_Warn( p_this, "option %s does not exist", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
379 380
        return;
    }
381 382

    if (!IsConfigFloatType (p_config->i_type))
Gildas Bazin's avatar
 
Gildas Bazin committed
383
    {
384
        msg_Err( p_this, "option %s does not refer to a float", psz_name );
Gildas Bazin's avatar
 
Gildas Bazin committed
385 386 387
        return;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
388
    /* backup old value */
389
    oldval.f_float = p_config->value.f;
Gildas Bazin's avatar
 
Gildas Bazin committed
390

391
    /* if f_min == f_max == 0, then do not use them */
392
    if ((p_config->min.f == 0) && (p_config->max.f == 0))
393
    {
394
        p_config->value.f = f_value;
395
    }
396
    else if (f_value < p_config->min.f)
397
    {
398
        p_config->value.f = p_config->min.f;
399
    }
400
    else if (f_value > p_config->max.f)
401
    {
402
        p_config->value.f = p_config->max.f;
403 404 405
    }
    else
    {
406
        p_config->value.f = f_value;
407
    }
408

409 410
    p_config->b_dirty = VLC_TRUE;

411
    val.f_float = p_config->value.f;
Gildas Bazin's avatar
 
Gildas Bazin committed
412

413
    if( p_config->pf_callback )
414
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
415 416
        p_config->pf_callback( p_this, psz_name, oldval, val,
                               p_config->p_callback_data );
417
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
418 419
}

Gildas Bazin's avatar
 
Gildas Bazin committed
420 421 422 423
/*****************************************************************************
 * config_FindConfig: find the config structure associated with an option.
 *****************************************************************************
 * FIXME: This function really needs to be optimized.
424
 * FIXME: And now even more.
Gildas Bazin's avatar
 
Gildas Bazin committed
425
 *****************************************************************************/
426
module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
Gildas Bazin's avatar
 
Gildas Bazin committed
427
{
428
    vlc_list_t *p_list;
Gildas Bazin's avatar
 
Gildas Bazin committed
429
    int i_index;
Gildas Bazin's avatar
 
Gildas Bazin committed
430 431 432

    if( !psz_name ) return NULL;

433
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
434

435
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
436
    {
437 438
        module_config_t *p_item, *p_end;
        module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object;
Gildas Bazin's avatar
 
Gildas Bazin committed
439 440

        if( !p_parser->i_config_items )
441 442
            continue;

443 444
        for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
             p_item < p_end;
Sam Hocevar's avatar
 
Sam Hocevar committed
445
             p_item++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
446
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
447
            if( p_item->i_type & CONFIG_HINT )
Gildas Bazin's avatar
 
Gildas Bazin committed
448
                /* ignore hints */
Gildas Bazin's avatar
 
Gildas Bazin committed
449
                continue;
Sam Hocevar's avatar
 
Sam Hocevar committed
450
            if( !strcmp( psz_name, p_item->psz_name ) )
451
            {
452
                vlc_list_release( p_list );
Sam Hocevar's avatar
 
Sam Hocevar committed
453
                return p_item;
454
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
455 456 457
        }
    }

458
    vlc_list_release( p_list );
459

Gildas Bazin's avatar
 
Gildas Bazin committed
460 461 462
    return NULL;
}

463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
/*****************************************************************************
 * config_FindModule: find a specific module structure.
 *****************************************************************************/
module_t *config_FindModule( vlc_object_t *p_this, const char *psz_name )
{
    vlc_list_t *p_list;
    module_t *p_module, *p_result = NULL;
    int i_index;

    if( !psz_name ) return NULL;

    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

    for( i_index = 0; i_index < p_list->i_count; i_index++ )
    {
        p_module = (module_t *)p_list->p_values[i_index].p_object;
        if( !strcmp( p_module->psz_object_name, psz_name ) )
        {
             p_result = p_module;
             break;
        }
    }

    vlc_list_release( p_list );

    return p_result;
}

Gildas Bazin's avatar
 
Gildas Bazin committed
491 492 493 494 495 496 497
/*****************************************************************************
 * config_Duplicate: creates a duplicate of a module's configuration data.
 *****************************************************************************
 * Unfortunatly we cannot work directly with the module's config data as
 * this module might be unloaded from memory at any time (remember HideModule).
 * This is why we need to create an exact copy of the config data.
 *****************************************************************************/
498 499
int config_Duplicate( module_t *p_module, const module_config_t *p_orig,
                      size_t n )
Gildas Bazin's avatar
 
Gildas Bazin committed
500
{
501 502
    int j;
    const module_config_t *p_item, *p_end = p_orig + n;
Gildas Bazin's avatar
 
Gildas Bazin committed
503

Sam Hocevar's avatar
 
Sam Hocevar committed
504
    /* Calculate the structure length */
505 506 507
    p_module->i_config_items = 0;
    p_module->i_bool_items = 0;

508
    for( p_item = p_orig; p_item < p_end; p_item++ )
509
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
510
        if( p_item->i_type & CONFIG_ITEM )
511 512 513 514
        {
            p_module->i_config_items++;
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
515
        if( p_item->i_type == CONFIG_ITEM_BOOL )
516 517 518 519
        {
            p_module->i_bool_items++;
        }
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
520 521

    /* Allocate memory */
522
    p_module->p_config = (module_config_t *)calloc( n, sizeof(*p_orig) );
523
    if( p_module->p_config == NULL )
Gildas Bazin's avatar
 
Gildas Bazin committed
524
    {
525
        msg_Err( p_module, "config error: can't duplicate p_config" );
526
        return VLC_ENOMEM;
Gildas Bazin's avatar
 
Gildas Bazin committed
527
    }
528
    p_module->confsize = n;
Gildas Bazin's avatar
 
Gildas Bazin committed
529

Sam Hocevar's avatar
 
Sam Hocevar committed
530
    /* Do the duplication job */
531
    for( size_t i = 0; i < n ; i++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
532
    {
533
        p_module->p_config[i] = p_orig[i];
Sam Hocevar's avatar
 
Sam Hocevar committed
534

535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
        if (IsConfigIntegerType (p_module->p_config[i].i_type))
        {
            p_module->p_config[i].orig.i = p_orig[i].value.i;
            p_module->p_config[i].saved.i = p_orig[i].value.i;
        }
        else
        if (IsConfigFloatType (p_module->p_config[i].i_type))
        {
            p_module->p_config[i].orig.f = p_orig[i].value.f;
            p_module->p_config[i].saved.f = p_orig[i].value.f;
        }
        else
        if (IsConfigStringType (p_module->p_config[i].i_type))
        {
            p_module->p_config[i].value.psz = strdupnull (p_orig[i].value.psz);
            p_module->p_config[i].orig.psz = strdupnull (p_orig[i].value.psz);
            p_module->p_config[i].saved.psz = NULL;
        }

        p_module->p_config[i].psz_type = strdupnull (p_orig[i].psz_type);
        p_module->p_config[i].psz_name = strdupnull (p_orig[i].psz_name);
        p_module->p_config[i].psz_current = strdupnull (p_orig[i].psz_current);
        p_module->p_config[i].psz_text = _strdupnull (p_orig[i].psz_text);
        p_module->p_config[i].psz_longtext = _strdupnull (p_orig[i].psz_longtext);
Gildas Bazin's avatar
 
Gildas Bazin committed
559

Sam Hocevar's avatar
Sam Hocevar committed
560
        p_module->p_config[i].p_lock = &p_module->object_lock;
561

Gildas Bazin's avatar
 
Gildas Bazin committed
562
        /* duplicate the string list */
563
        if( p_orig[i].i_list )
Gildas Bazin's avatar
 
Gildas Bazin committed
564
        {
565
            if( p_orig[i].ppsz_list )
Gildas Bazin's avatar
 
Gildas Bazin committed
566
            {
567 568 569 570 571
                p_module->p_config[i].ppsz_list =
                    malloc( (p_orig[i].i_list + 1) * sizeof(char *) );
                if( p_module->p_config[i].ppsz_list )
                {
                    for( j = 0; j < p_orig[i].i_list; j++ )
572 573
                        p_module->p_config[i].ppsz_list[j] =
                                strdupnull (p_orig[i].ppsz_list[j]);
574 575 576 577 578 579
                    p_module->p_config[i].ppsz_list[j] = NULL;
                }
            }
            if( p_orig[i].ppsz_list_text )
            {
                p_module->p_config[i].ppsz_list_text =
580
                    calloc( (p_orig[i].i_list + 1), sizeof(char *) );
581 582 583
                if( p_module->p_config[i].ppsz_list_text )
                {
                    for( j = 0; j < p_orig[i].i_list; j++ )
584 585
                        p_module->p_config[i].ppsz_list_text[j] =
                                strdupnull (_(p_orig[i].ppsz_list_text[j]));
586 587 588 589 590 591 592 593 594 595 596 597 598
                    p_module->p_config[i].ppsz_list_text[j] = NULL;
                }
            }
            if( p_orig[i].pi_list )
            {
                p_module->p_config[i].pi_list =
                    malloc( (p_orig[i].i_list + 1) * sizeof(int) );
                if( p_module->p_config[i].pi_list )
                {
                    for( j = 0; j < p_orig[i].i_list; j++ )
                        p_module->p_config[i].pi_list[j] =
                            p_orig[i].pi_list[j];
                }
Gildas Bazin's avatar
 
Gildas Bazin committed
599 600 601
            }
        }

602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
        /* duplicate the actions list */
        if( p_orig[i].i_action )
        {
            int j;

            p_module->p_config[i].ppf_action =
                malloc( p_orig[i].i_action * sizeof(void *) );
            p_module->p_config[i].ppsz_action_text =
                malloc( p_orig[i].i_action * sizeof(char *) );

            for( j = 0; j < p_orig[i].i_action; j++ )
            {
                p_module->p_config[i].ppf_action[j] =
                    p_orig[i].ppf_action[j];
                p_module->p_config[i].ppsz_action_text[j] =
617
                    strdupnull (p_orig[i].ppsz_action_text[j]);
618 619 620
            }
        }

621
        p_module->p_config[i].pf_callback = p_orig[i].pf_callback;
Gildas Bazin's avatar
 
Gildas Bazin committed
622
    }
623
    return VLC_SUCCESS;
624 625
}

626

627 628 629 630 631 632 633
/*****************************************************************************
 * config_Free: frees a duplicated module's configuration data.
 *****************************************************************************
 * This function frees all the data duplicated by config_Duplicate.
 *****************************************************************************/
void config_Free( module_t *p_module )
{
Gildas Bazin's avatar
 
Gildas Bazin committed
634
    int i;
635

636
    for (size_t j = 0; j < p_module->confsize; j++)
637
    {
638
        module_config_t *p_item = p_module->p_config + j;
639

640 641 642 643 644
        free( (char*) p_item->psz_type );
        free( (char*) p_item->psz_name );
        free( (char*) p_item->psz_current );
        free( (char*) p_item->psz_text );
        free( (char*) p_item->psz_longtext );
645

646 647 648 649 650 651
        if (IsConfigStringType (p_item->i_type))
        {
            freenull (p_item->value.psz);
            freenull (p_item->orig.psz);
            freenull (p_item->saved.psz);
        }
652

653
        if( p_item->i_list )
Gildas Bazin's avatar
 
Gildas Bazin committed
654
        {
655 656 657
            for( i = 0; i < p_item->i_list; i++ )
            {
                if( p_item->ppsz_list && p_item->ppsz_list[i] )
658
                    free( (char*) p_item->ppsz_list[i] );
659
                if( p_item->ppsz_list_text && p_item->ppsz_list_text[i] )
660
                    free( (char*) p_item->ppsz_list_text[i] );
661 662 663 664
            }
            if( p_item->ppsz_list ) free( p_item->ppsz_list );
            if( p_item->ppsz_list_text ) free( p_item->ppsz_list_text );
            if( p_item->pi_list ) free( p_item->pi_list );
Gildas Bazin's avatar
 
Gildas Bazin committed
665
        }
666 667 668 669 670

        if( p_item->i_action )
        {
            for( i = 0; i < p_item->i_action; i++ )
            {
671
                free( (char*) p_item->ppsz_action_text[i] );
672 673 674 675
            }
            if( p_item->ppf_action ) free( p_item->ppf_action );
            if( p_item->ppsz_action_text ) free( p_item->ppsz_action_text );
        }
676 677
    }

678 679 680 681 682
    if (p_module->p_config != NULL)
    {
        free (p_module->p_config);
        p_module->p_config = NULL;
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
683
}
Gildas Bazin's avatar
 
Gildas Bazin committed
684

685 686 687 688 689 690 691
/*****************************************************************************
 * config_SetCallbacks: sets callback functions in the duplicate p_config.
 *****************************************************************************
 * Unfortunatly we cannot work directly with the module's config data as
 * this module might be unloaded from memory at any time (remember HideModule).
 * This is why we need to duplicate callbacks each time we reload the module.
 *****************************************************************************/
692 693
void config_SetCallbacks( module_config_t *p_new, module_config_t *p_orig,
                          size_t n )
694
{
695
    for (size_t i = 0; i < n; i++)
696
    {
697
        p_new->pf_callback = p_orig->pf_callback;
698 699 700 701 702 703 704 705 706 707
        p_new++;
        p_orig++;
    }
}

/*****************************************************************************
 * config_UnsetCallbacks: unsets callback functions in the duplicate p_config.
 *****************************************************************************
 * We simply undo what we did in config_SetCallbacks.
 *****************************************************************************/
708
void config_UnsetCallbacks( module_config_t *p_new, size_t n )
709
{
710
    for (size_t i = 0; i < n; i++)
711
    {
712
        p_new->pf_callback = NULL;
713 714 715 716
        p_new++;
    }
}

Gildas Bazin's avatar
 
Gildas Bazin committed
717 718 719 720 721
/*****************************************************************************
 * config_ResetAll: reset the configuration data for all the modules.
 *****************************************************************************/
void __config_ResetAll( vlc_object_t *p_this )
{
722
    int i_index;
Gildas Bazin's avatar
 
Gildas Bazin committed
723 724 725 726
    vlc_list_t *p_list;
    module_t *p_module;

    /* Acquire config file lock */
727
    vlc_mutex_lock( &p_this->p_libvlc->config_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
728 729 730 731 732 733 734 735

    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

    for( i_index = 0; i_index < p_list->i_count; i_index++ )
    {
        p_module = (module_t *)p_list->p_values[i_index].p_object ;
        if( p_module->b_submodule ) continue;

736
        for (size_t i = 0; i < p_module->confsize; i++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
737
        {
738 739 740 741 742 743 744 745 746 747 748 749
            if (IsConfigIntegerType (p_module->p_config[i].i_type))
                p_module->p_config[i].value.i = p_module->p_config[i].orig.i;
            else
            if (IsConfigFloatType (p_module->p_config[i].i_type))
                p_module->p_config[i].value.f = p_module->p_config[i].orig.f;
            else
            if (IsConfigStringType (p_module->p_config[i].i_type))
            {
                freenull (p_module->p_config[i].value.psz);
                p_module->p_config[i].value.psz =
                        strdupnull (p_module->p_config[i].orig.psz);
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
750 751 752 753
        }
    }

    vlc_list_release( p_list );
754
    vlc_mutex_unlock( &p_this->p_libvlc->config_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
755 756
}

757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792

static FILE *config_OpenConfigFile (vlc_object_t *obj, const char *mode)
{
    static const char subpath[] = DIR_SEP CONFIG_DIR DIR_SEP CONFIG_FILE;
    const char *filename = obj->p_libvlc->psz_configfile;
    const char *homedir;
    size_t buflen = 0;

    if (filename == NULL)
    {
        homedir = obj->p_libvlc->psz_homedir;
        if (homedir == NULL)
        {
            msg_Err (obj, "no home directory defined");
            return NULL;
        }

        buflen = strlen (homedir) + sizeof (subpath);
    }

    char buf[buflen];
    if (filename == NULL)
    {
        sprintf (buf, "%s%s", homedir, subpath);
        filename = buf;
    }

    msg_Dbg (obj, "opening config file (%s)", filename);
    FILE *stream = utf8_fopen (filename, mode);
    if ((stream == NULL) && (errno != ENOENT))
        msg_Err (obj, "cannot open config file (%s): %s", strerror (errno));

    return stream;
}


Gildas Bazin's avatar
 
Gildas Bazin committed
793 794 795 796 797 798
/*****************************************************************************
 * config_LoadConfigFile: loads the configuration file.
 *****************************************************************************
 * This function is called to load the config options stored in the config
 * file.
 *****************************************************************************/
799
int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
Gildas Bazin's avatar
 
Gildas Bazin committed
800
{
801
    vlc_list_t *p_list;
Gildas Bazin's avatar
 
Gildas Bazin committed
802 803
    FILE *file;

804 805 806
    file = config_OpenConfigFile (p_this, "rt");
    if (file == NULL)
        return VLC_EGENERIC;
Gildas Bazin's avatar
 
Gildas Bazin committed
807

808
    /* Acquire config file lock */
809
    vlc_mutex_lock( &p_this->p_libvlc->config_lock );
810

Gildas Bazin's avatar
 
Gildas Bazin committed
811
    /* Look for the selected module, if NULL then save everything */
812
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
813

814 815 816
    /* Look for UTF-8 Byte Order Mark */
    char * (*convert) (const char *) = strdupnull;
    char bom[3];
817

818 819 820 821 822 823
    if ((fread (bom, 1, 3, file) != 3)
     || memcmp (bom, "\xEF\xBB\xBF", 3))
    {
        convert = FromLocaleDup;
        rewind (file); // no BOM, rewind
    }
824

825 826 827
    module_t *module = NULL;
    char line[1024], section[1022];
    section[0] = '\0';
828

829 830 831 832
    while (fgets (line, 1024, file) != NULL)
    {
        // Ignore comments and empty lines
        switch (line[0])
Gildas Bazin's avatar
 
Gildas Bazin committed
833
        {
834 835 836 837
            case '#':
            case '\n':
            case '\0':
                continue;
Gildas Bazin's avatar
 
Gildas Bazin committed
838 839
        }

840
        if (line[0] == '[')
Gildas Bazin's avatar
 
Gildas Bazin committed
841
        {
842 843 844 845
            char *ptr = strchr (line, ']');
            if (ptr == NULL)
                continue; // syntax error;
            *ptr = '\0';
Gildas Bazin's avatar
 
Gildas Bazin committed
846

847 848 849
            // New section ( = a given module)
            strcpy (section, line + 1);
            module = NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
850

851 852
            if ((psz_module_name == NULL)
             || (strcmp (psz_module_name, section) == 0))
853
            {
854
                for (int i = 0; i < p_list->i_count; i++)
Gildas Bazin's avatar
 
Gildas Bazin committed
855
                {
856 857 858 859
                    module_t *m = (module_t *)p_list->p_values[i].p_object;

                    if ((strcmp (section, m->psz_object_name) == 0)
                     && (m->i_config_items > 0)) // ignore config-less modules
Gildas Bazin's avatar
 
Gildas Bazin committed
860
                    {
861 862 863 864 865
                        module = m;
                        if (psz_module_name != NULL)
                            msg_Dbg (p_this,
                                     "loading config for module \"%s\"",
                                     section);
Gildas Bazin's avatar
 
Gildas Bazin committed
866
                        break;
867 868 869
                    }
                }
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
870

871 872
            continue;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
873

874 875
        if (module == NULL)
            continue; // no need to parse if there is no matching module
Gildas Bazin's avatar
 
Gildas Bazin committed
876

877 878 879
        char *ptr = strchr (line, '\n');
        if (ptr != NULL)
            *ptr = '\0';
880

881 882
        /* look for option name */
        const char *psz_option_name = line;
Gildas Bazin's avatar
 
Gildas Bazin committed
883

884 885 886
        ptr = strchr (line, '=');
        if (ptr == NULL)
            continue; // syntax error
Gildas Bazin's avatar
 
Gildas Bazin committed
887

888 889
        *ptr = '\0';
        const char *psz_option_value = ptr + 1;
890

891 892 893 894
        /* try to match this option with one of the module's options */
        for (size_t i = 0; i < module->confsize; i++)
        {
            module_config_t *p_item = module->p_config + i;
Gildas Bazin's avatar
 
Gildas Bazin committed
895

896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
            if ((p_item->i_type & CONFIG_HINT)
             || strcmp (p_item->psz_name, psz_option_name))
                continue;

            /* We found it */
            switch( p_item->i_type )
            {
                case CONFIG_ITEM_BOOL:
                case CONFIG_ITEM_INTEGER:
                    if( !*psz_option_value )
                        break;                    /* ignore empty option */
                    p_item->value.i = strtol( psz_option_value, 0, 0 );
                    p_item->saved.i = p_item->value.i;

                    /*msg_Dbg (p_this, "option \"%s\", value %i",
                             psz_option_name, p_item->value.i);*/
                    break;

                case CONFIG_ITEM_FLOAT:
                    if( !*psz_option_value )
                        break;                    /* ignore empty option */
                    p_item->value.f = (float)i18n_atof( psz_option_value);
                    p_item->saved.f = p_item->value.f;

                    /*msg_Dbg (p_this, "option \"%s\", value %f",
                             psz_option_name, (double)p_item->value.f);*/
                    break;

                case CONFIG_ITEM_KEY:
                    if( !*psz_option_value )
                        break;                    /* ignore empty option */
                    p_item->value.i = ConfigStringToKey(psz_option_value);
                    p_item->saved.i = p_item->value.i;
                    break;

                default:
                    vlc_mutex_lock( p_item->p_lock );

                    /* free old string */
935 936
                    free( (char*) p_item->value.psz );
                    free( (char*) p_item->saved.psz );
937 938 939 940 941 942 943 944 945

                    p_item->value.psz = convert (psz_option_value);
                    p_item->saved.psz = strdupnull (p_item->value.psz);

                    vlc_mutex_unlock( p_item->p_lock );

                    /*msg_Dbg (p_this, "option \"%s\", value \"%s\"",
                             psz_option_name, psz_option_value ?: "");*/
                    break;
Gildas Bazin's avatar
 
Gildas Bazin committed
946 947
            }

948 949
            break;
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
950
    }
951 952

    vlc_list_release( p_list );
953

Gildas Bazin's avatar
 
Gildas Bazin committed
954 955
    fclose( file );

956
    vlc_mutex_unlock( &p_this->p_libvlc->config_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
957 958 959
    return 0;
}

960
/*****************************************************************************
961
 * config_CreateDir: Create configuration directory if it doesn't exist.
962
 *****************************************************************************/
963
int config_CreateDir( vlc_object_t *p_this, const char *psz_dirname )
964 965 966
{
    if( !psz_dirname && !*psz_dirname ) return -1;

967
    if( utf8_mkdir( psz_dirname ) && ( errno != EEXIST ) )
968 969 970
    {
        msg_Err( p_this, "could not create %s (%s)",
                 psz_dirname, strerror(errno) );
971
        return -1;
972 973 974 975 976
    }

    return 0;
}

Gildas Bazin's avatar
 
Gildas Bazin committed
977 978 979 980 981 982 983 984
/*****************************************************************************
 * config_SaveConfigFile: Save a module's config options.
 *****************************************************************************
 * This will save the specified module's config options to the config file.
 * If psz_module_name is NULL then we save all the modules config options.
 * It's no use to save the config options that kept their default values, so
 * we'll try to be a bit clever here.
 *
985
 * When we save we mustn't delete the config options of the modules that
Gildas Bazin's avatar
 
Gildas Bazin committed
986
 * haven't been loaded. So we cannot just create a new config file with the
987
 * config structures we've got in memory.
Gildas Bazin's avatar
 
Gildas Bazin committed
988 989 990 991 992 993 994 995
 * I don't really know how to deal with this nicely, so I will use a completly
 * dumb method ;-)
 * I will load the config file in memory, but skipping all the sections of the
 * modules we want to save. Then I will create a brand new file, dump the file
 * loaded in memory and then append the sections of the modules we want to
 * save.
 * Really stupid no ?
 *****************************************************************************/
996 997
static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
                           vlc_bool_t b_autosave )
Gildas Bazin's avatar
 
Gildas Bazin committed
998
{
Gildas Bazin's avatar
 
Gildas Bazin committed
999
    module_t *p_parser;
1000
    vlc_list_t *p_list;
Gildas Bazin's avatar
 
Gildas Bazin committed
1001 1002
    FILE *file;
    char p_line[1024], *p_index2;
Sam Hocevar's avatar
 
Sam Hocevar committed
1003
    int i_sizebuf = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
1004
    char *p_bigbuffer, *p_index;
1005
    vlc_bool_t b_backup;
Gildas Bazin's avatar
 
Gildas Bazin committed
1006
    int i_index;
Gildas Bazin's avatar
 
Gildas Bazin committed
1007 1008

    /* Acquire config file lock */
1009
    vlc_mutex_lock( &p_this->p_libvlc->config_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
1010

1011
    if (p_this->p_libvlc->psz_configfile == NULL)
Gildas Bazin's avatar
 
Gildas Bazin committed
1012
    {
1013
        const char *psz_homedir = p_this->p_libvlc->psz_homedir;
Gildas Bazin's avatar
 
Gildas Bazin committed
1014 1015
        if( !psz_homedir )
        {
1016
            msg_Err( p_this, "no home directory defined" );
1017
            vlc_mutex_unlock( &p_this->p_libvlc->config_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
1018 1019 1020
            return -1;
        }

1021 1022 1023
        char dirname[strlen (psz_homedir) + sizeof (DIR_SEP CONFIG_DIR)];
        sprintf (dirname, "%s" DIR_SEP CONFIG_DIR, psz_homedir);
        config_CreateDir (p_this, dirname);
Gildas Bazin's avatar
 
Gildas Bazin committed
1024
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
1025

1026 1027
    file = config_OpenConfigFile (p_this, "rt");
    if (file != NULL)
Gildas Bazin's avatar
 
Gildas Bazin committed
1028 1029
    {
        /* look for file size */
1030
        fseek( file, 0L, SEEK_END );
Gildas Bazin's avatar
 
Gildas Bazin committed
1031
        i_sizebuf = ftell( file );
1032
        fseek( file, 0L, SEEK_SET );
Gildas Bazin's avatar
 
Gildas Bazin committed
1033 1034 1035 1036 1037
    }

    p_bigbuffer = p_index = malloc( i_sizebuf+1 );
    if( !p_bigbuffer )
    {
1038
        msg_Err( p_this, "out of memory" );
Gildas Bazin's avatar
 
Gildas Bazin committed
1039
        if( file ) fclose( file );
1040
        vlc_mutex_unlock( &p_this->p_libvlc->config_lock );
Gildas Bazin's avatar
 
Gildas Bazin committed
1041 1042 1043 1044
        return -1;
    }
    p_bigbuffer[0] = 0;

1045
    /* List all available modules */
1046
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1047

Gildas Bazin's avatar
 
Gildas Bazin committed
1048 1049 1050 1051 1052 1053 1054
    /* backup file into memory, we only need to backup the sections we won't
     * save later on */
    b_backup = 0;
    while( file && fgets( p_line, 1024, file ) )
    {
        if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
        {
1055

Gildas Bazin's avatar
 
Gildas Bazin committed
1056
            /* we found a section, check if we need to do a backup */
1057
            for( i_index = 0; i_index < p_list->i_count; i_index++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
1058
            {
1059
                p_parser = (module_t *)p_list->p_values[i_index].p_object ;
Gildas Bazin's avatar
 
Gildas Bazin committed
1060

1061
                if( ((p_index2 - &p_line[1])
Gildas Bazin's avatar
 
Gildas Bazin committed
1062 1063 1064
                       == (int)strlen(p_parser->psz_object_name) )
                    && !memcmp( &p_line[1], p_parser->psz_object_name,
                                strlen(p_parser->psz_object_name) ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
1065 1066 1067