~ubuntu-branches/ubuntu/precise/libmpc/precise

« back to all changes in this revision

Viewing changes to mpcchap/iniparser.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2009-03-04 10:08:01 UTC
  • Revision ID: james.westby@ubuntu.com-20090304100801-k5vtj8jz06nomhlu
Tags: upstream-0.1~r435
Import upstream version 0.1~r435

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*-------------------------------------------------------------------------*/
 
3
/**
 
4
   @file    iniparser.c
 
5
   @author  N. Devillard
 
6
   @date    Sep 2007
 
7
   @version 3.0
 
8
   @brief   Parser for ini files.
 
9
*/
 
10
/*--------------------------------------------------------------------------*/
 
11
/*
 
12
    $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $
 
13
    $Revision: 2.18 $
 
14
    $Date: 2008-01-03 18:35:39 $
 
15
*/
 
16
/*---------------------------- Includes ------------------------------------*/
 
17
#include <ctype.h>
 
18
#include "iniparser.h"
 
19
 
 
20
/*---------------------------- Defines -------------------------------------*/
 
21
#define ASCIILINESZ         (1024)
 
22
#define INI_INVALID_KEY     ((char*)-1)
 
23
 
 
24
/*---------------------------------------------------------------------------
 
25
                        Private to this module
 
26
 ---------------------------------------------------------------------------*/
 
27
/**
 
28
 * This enum stores the status for each parsed line (internal use only).
 
29
 */
 
30
typedef enum _line_status_ {
 
31
    LINE_UNPROCESSED,
 
32
    LINE_ERROR,
 
33
    LINE_EMPTY,
 
34
    LINE_COMMENT,
 
35
    LINE_SECTION,
 
36
    LINE_VALUE
 
37
} line_status ;
 
38
 
 
39
/*-------------------------------------------------------------------------*/
 
40
/**
 
41
  @brief        Convert a string to lowercase.
 
42
  @param        s       String to convert.
 
43
  @return       ptr to statically allocated string.
 
44
 
 
45
  This function returns a pointer to a statically allocated string
 
46
  containing a lowercased version of the input string. Do not free
 
47
  or modify the returned string! Since the returned string is statically
 
48
  allocated, it will be modified at each function call (not re-entrant).
 
49
 */
 
50
/*--------------------------------------------------------------------------*/
 
51
static char * strlwc(const char * s)
 
52
{
 
53
    static char l[ASCIILINESZ+1];
 
54
    int i ;
 
55
 
 
56
    if (s==NULL) return NULL ;
 
57
    memset(l, 0, ASCIILINESZ+1);
 
58
    i=0 ;
 
59
    while (s[i] && i<ASCIILINESZ) {
 
60
        l[i] = (char)tolower((int)s[i]);
 
61
        i++ ;
 
62
    }
 
63
    l[ASCIILINESZ]=(char)0;
 
64
    return l ;
 
65
}
 
66
 
 
67
/*-------------------------------------------------------------------------*/
 
68
/**
 
69
  @brief        Remove blanks at the beginning and the end of a string.
 
70
  @param        s       String to parse.
 
71
  @return       ptr to statically allocated string.
 
72
 
 
73
  This function returns a pointer to a statically allocated string,
 
74
  which is identical to the input string, except that all blank
 
75
  characters at the end and the beg. of the string have been removed.
 
76
  Do not free or modify the returned string! Since the returned string
 
77
  is statically allocated, it will be modified at each function call
 
78
  (not re-entrant).
 
79
 */
 
80
/*--------------------------------------------------------------------------*/
 
81
static char * strstrip(char * s)
 
82
{
 
83
    static char l[ASCIILINESZ+1];
 
84
        char * last ;
 
85
 
 
86
    if (s==NULL) return NULL ;
 
87
 
 
88
        while (isspace((int)*s) && *s) s++;
 
89
        memset(l, 0, ASCIILINESZ+1);
 
90
        strcpy(l, s);
 
91
        last = l + strlen(l);
 
92
        while (last > l) {
 
93
                if (!isspace((int)*(last-1)))
 
94
                        break ;
 
95
                last -- ;
 
96
        }
 
97
        *last = (char)0;
 
98
        return (char*)l ;
 
99
}
 
100
 
 
101
/*-------------------------------------------------------------------------*/
 
102
/**
 
103
  @brief    Get number of sections in a dictionary
 
104
  @param    d   Dictionary to examine
 
105
  @return   int Number of sections found in dictionary
 
106
 
 
107
  This function returns the number of sections found in a dictionary.
 
108
  The test to recognize sections is done on the string stored in the
 
109
  dictionary: a section name is given as "section" whereas a key is
 
110
  stored as "section:key", thus the test looks for entries that do not
 
111
  contain a colon.
 
112
 
 
113
  This clearly fails in the case a section name contains a colon, but
 
114
  this should simply be avoided.
 
115
 
 
116
  This function returns -1 in case of error.
 
117
 */
 
118
/*--------------------------------------------------------------------------*/
 
119
int iniparser_getnsec(dictionary * d)
 
120
{
 
121
    int i ;
 
122
    int nsec ;
 
123
 
 
124
    if (d==NULL) return -1 ;
 
125
    nsec=0 ;
 
126
    for (i=0 ; i<d->size ; i++) {
 
127
        if (d->key[i]==NULL)
 
128
            continue ;
 
129
        if (strchr(d->key[i], ':')==NULL) {
 
130
            nsec ++ ;
 
131
        }
 
132
    }
 
133
    return nsec ;
 
134
}
 
135
 
 
136
/*-------------------------------------------------------------------------*/
 
137
/**
 
138
  @brief    Get name for section n in a dictionary.
 
139
  @param    d   Dictionary to examine
 
140
  @param    n   Section number (from 0 to nsec-1).
 
141
  @return   Pointer to char string
 
142
 
 
143
  This function locates the n-th section in a dictionary and returns
 
144
  its name as a pointer to a string statically allocated inside the
 
145
  dictionary. Do not free or modify the returned string!
 
146
 
 
147
  This function returns NULL in case of error.
 
148
 */
 
149
/*--------------------------------------------------------------------------*/
 
150
char * iniparser_getsecname(dictionary * d, int n)
 
151
{
 
152
    int i ;
 
153
    int foundsec ;
 
154
 
 
155
    if (d==NULL || n<0) return NULL ;
 
156
    foundsec=0 ;
 
157
    for (i=0 ; i<d->size ; i++) {
 
158
        if (d->key[i]==NULL)
 
159
            continue ;
 
160
        if (strchr(d->key[i], ':')==NULL) {
 
161
            foundsec++ ;
 
162
            if (foundsec>n)
 
163
                break ;
 
164
        }
 
165
    }
 
166
    if (foundsec<=n) {
 
167
        return NULL ;
 
168
    }
 
169
    return d->key[i] ;
 
170
}
 
171
 
 
172
/*-------------------------------------------------------------------------*/
 
173
/**
 
174
  @brief    Get number of keys for section n in a dictionary.
 
175
  @param    d   Dictionary to examine
 
176
  @param    n   Section number (from 0 to nsec-1).
 
177
  @return   Number of keys in section
 
178
 
 
179
  This function locates the n-th section in a dictionary and returns
 
180
  the number of keys in this section.
 
181
 
 
182
  This function returns -1 in case of error.
 
183
 */
 
184
/*--------------------------------------------------------------------------*/
 
185
int iniparser_getnkey(dictionary * d, int n)
 
186
{
 
187
        int i, i_sec, cnt = 0 ;
 
188
 
 
189
        if (d==NULL) return -1 ;
 
190
        for (i_sec=i=0 ; i<d->size ; i++) {
 
191
                if (d->key[i]==NULL)
 
192
                        continue ;
 
193
                if (strchr(d->key[i], ':')==NULL) {
 
194
                        if (n == -1)
 
195
                                break;
 
196
                        n -- ;
 
197
                }
 
198
                if (n == -1)
 
199
                        cnt ++;
 
200
        }
 
201
        return (cnt - 1);
 
202
}
 
203
 
 
204
/*-------------------------------------------------------------------------*/
 
205
/**
 
206
  @brief    Get key and string for key nkey in section nsec in a dictionary.
 
207
  @param    d   Dictionary to examine
 
208
  @param    nsec   Section number.
 
209
  @param    nkey   Key number.
 
210
  @param    string   Pointer where the string will be returned.
 
211
  @return   Pointer to char string
 
212
 
 
213
  This function locates the nkey-th key in the nsec-th section in a dictionary
 
214
  and returns the key name and the key string as a pointer to strings
 
215
  statically allocated inside the dictionary.
 
216
  Do not free or modify the returned strings!
 
217
 
 
218
  This function returns NULL in case of error.
 
219
 */
 
220
/*--------------------------------------------------------------------------*/
 
221
char * iniparser_getkeyname(dictionary * d, int nsec, int nkey, char ** string)
 
222
{
 
223
        int i, keylen;
 
224
 
 
225
        if (d==NULL) return 0 ;
 
226
        for (i=0 ; i<d->size ; i++) {
 
227
                if (d->key[i]==NULL)
 
228
                        continue ;
 
229
                if (strchr(d->key[i], ':')==NULL) {
 
230
                        if (nsec == 0)
 
231
                                break;
 
232
                        nsec -- ;
 
233
                }
 
234
        }
 
235
        keylen = strlen(d->key[i]) + 1;
 
236
        i++;
 
237
        for (; i<d->size ; i++) {
 
238
                if (d->key[i]==NULL)
 
239
                        continue ;
 
240
                if (nkey == 0)
 
241
                        break;
 
242
                nkey--;
 
243
        }
 
244
 
 
245
        *string = d->val[i];
 
246
        return d->key[i] + keylen;
 
247
}
 
248
 
 
249
/*-------------------------------------------------------------------------*/
 
250
/**
 
251
  @brief    Dump a dictionary to an opened file pointer.
 
252
  @param    d   Dictionary to dump.
 
253
  @param    f   Opened file pointer to dump to.
 
254
  @return   void
 
255
 
 
256
  This function prints out the contents of a dictionary, one element by
 
257
  line, onto the provided file pointer. It is OK to specify @c stderr
 
258
  or @c stdout as output files. This function is meant for debugging
 
259
  purposes mostly.
 
260
 */
 
261
/*--------------------------------------------------------------------------*/
 
262
void iniparser_dump(dictionary * d, FILE * f)
 
263
{
 
264
    int     i ;
 
265
 
 
266
    if (d==NULL || f==NULL) return ;
 
267
    for (i=0 ; i<d->size ; i++) {
 
268
        if (d->key[i]==NULL)
 
269
            continue ;
 
270
        if (d->val[i]!=NULL) {
 
271
            fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
 
272
        } else {
 
273
            fprintf(f, "[%s]=UNDEF\n", d->key[i]);
 
274
        }
 
275
    }
 
276
    return ;
 
277
}
 
278
 
 
279
/*-------------------------------------------------------------------------*/
 
280
/**
 
281
  @brief    Save a dictionary to a loadable ini file
 
282
  @param    d   Dictionary to dump
 
283
  @param    f   Opened file pointer to dump to
 
284
  @return   void
 
285
 
 
286
  This function dumps a given dictionary into a loadable ini file.
 
287
  It is Ok to specify @c stderr or @c stdout as output files.
 
288
 */
 
289
/*--------------------------------------------------------------------------*/
 
290
void iniparser_dump_ini(dictionary * d, FILE * f)
 
291
{
 
292
    int     i, j ;
 
293
    char    keym[ASCIILINESZ+1];
 
294
    int     nsec ;
 
295
    char *  secname ;
 
296
    int     seclen ;
 
297
 
 
298
    if (d==NULL || f==NULL) return ;
 
299
 
 
300
    nsec = iniparser_getnsec(d);
 
301
    if (nsec<1) {
 
302
        /* No section in file: dump all keys as they are */
 
303
        for (i=0 ; i<d->size ; i++) {
 
304
            if (d->key[i]==NULL)
 
305
                continue ;
 
306
            fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
 
307
        }
 
308
        return ;
 
309
    }
 
310
    for (i=0 ; i<nsec ; i++) {
 
311
        secname = iniparser_getsecname(d, i) ;
 
312
        seclen  = (int)strlen(secname);
 
313
        fprintf(f, "\n[%s]\n", secname);
 
314
        sprintf(keym, "%s:", secname);
 
315
        for (j=0 ; j<d->size ; j++) {
 
316
            if (d->key[j]==NULL)
 
317
                continue ;
 
318
            if (!strncmp(d->key[j], keym, seclen+1)) {
 
319
                fprintf(f,
 
320
                        "%-30s = %s\n",
 
321
                        d->key[j]+seclen+1,
 
322
                        d->val[j] ? d->val[j] : "");
 
323
            }
 
324
        }
 
325
    }
 
326
    fprintf(f, "\n");
 
327
    return ;
 
328
}
 
329
 
 
330
/*-------------------------------------------------------------------------*/
 
331
/**
 
332
  @brief    Get the string associated to a key
 
333
  @param    d       Dictionary to search
 
334
  @param    key     Key string to look for
 
335
  @param    def     Default value to return if key not found.
 
336
  @return   pointer to statically allocated character string
 
337
 
 
338
  This function queries a dictionary for a key. A key as read from an
 
339
  ini file is given as "section:key". If the key cannot be found,
 
340
  the pointer passed as 'def' is returned.
 
341
  The returned char pointer is pointing to a string allocated in
 
342
  the dictionary, do not free or modify it.
 
343
 */
 
344
/*--------------------------------------------------------------------------*/
 
345
char * iniparser_getstring(dictionary * d, const char * key, char * def)
 
346
{
 
347
    char * lc_key ;
 
348
    char * sval ;
 
349
 
 
350
    if (d==NULL || key==NULL)
 
351
        return def ;
 
352
 
 
353
    lc_key = strlwc(key);
 
354
    sval = dictionary_get(d, lc_key, def);
 
355
    return sval ;
 
356
}
 
357
 
 
358
/*-------------------------------------------------------------------------*/
 
359
/**
 
360
  @brief    Get the string associated to a key, convert to an int
 
361
  @param    d Dictionary to search
 
362
  @param    key Key string to look for
 
363
  @param    notfound Value to return in case of error
 
364
  @return   integer
 
365
 
 
366
  This function queries a dictionary for a key. A key as read from an
 
367
  ini file is given as "section:key". If the key cannot be found,
 
368
  the notfound value is returned.
 
369
 
 
370
  Supported values for integers include the usual C notation
 
371
  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
 
372
  are supported. Examples:
 
373
 
 
374
  "42"      ->  42
 
375
  "042"     ->  34 (octal -> decimal)
 
376
  "0x42"    ->  66 (hexa  -> decimal)
 
377
 
 
378
  Warning: the conversion may overflow in various ways. Conversion is
 
379
  totally outsourced to strtol(), see the associated man page for overflow
 
380
  handling.
 
381
 
 
382
  Credits: Thanks to A. Becker for suggesting strtol()
 
383
 */
 
384
/*--------------------------------------------------------------------------*/
 
385
int iniparser_getint(dictionary * d, const char * key, int notfound)
 
386
{
 
387
    char    *   str ;
 
388
 
 
389
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
 
390
    if (str==INI_INVALID_KEY) return notfound ;
 
391
    return (int)strtol(str, NULL, 0);
 
392
}
 
393
 
 
394
/*-------------------------------------------------------------------------*/
 
395
/**
 
396
  @brief    Get the string associated to a key, convert to a double
 
397
  @param    d Dictionary to search
 
398
  @param    key Key string to look for
 
399
  @param    notfound Value to return in case of error
 
400
  @return   double
 
401
 
 
402
  This function queries a dictionary for a key. A key as read from an
 
403
  ini file is given as "section:key". If the key cannot be found,
 
404
  the notfound value is returned.
 
405
 */
 
406
/*--------------------------------------------------------------------------*/
 
407
double iniparser_getdouble(dictionary * d, char * key, double notfound)
 
408
{
 
409
    char    *   str ;
 
410
 
 
411
    str = iniparser_getstring(d, key, INI_INVALID_KEY);
 
412
    if (str==INI_INVALID_KEY) return notfound ;
 
413
    return atof(str);
 
414
}
 
415
 
 
416
/*-------------------------------------------------------------------------*/
 
417
/**
 
418
  @brief    Get the string associated to a key, convert to a boolean
 
419
  @param    d Dictionary to search
 
420
  @param    key Key string to look for
 
421
  @param    notfound Value to return in case of error
 
422
  @return   integer
 
423
 
 
424
  This function queries a dictionary for a key. A key as read from an
 
425
  ini file is given as "section:key". If the key cannot be found,
 
426
  the notfound value is returned.
 
427
 
 
428
  A true boolean is found if one of the following is matched:
 
429
 
 
430
  - A string starting with 'y'
 
431
  - A string starting with 'Y'
 
432
  - A string starting with 't'
 
433
  - A string starting with 'T'
 
434
  - A string starting with '1'
 
435
 
 
436
  A false boolean is found if one of the following is matched:
 
437
 
 
438
  - A string starting with 'n'
 
439
  - A string starting with 'N'
 
440
  - A string starting with 'f'
 
441
  - A string starting with 'F'
 
442
  - A string starting with '0'
 
443
 
 
444
  The notfound value returned if no boolean is identified, does not
 
445
  necessarily have to be 0 or 1.
 
446
 */
 
447
/*--------------------------------------------------------------------------*/
 
448
int iniparser_getboolean(dictionary * d, const char * key, int notfound)
 
449
{
 
450
    char    *   c ;
 
451
    int         ret ;
 
452
 
 
453
    c = iniparser_getstring(d, key, INI_INVALID_KEY);
 
454
    if (c==INI_INVALID_KEY) return notfound ;
 
455
    if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
 
456
        ret = 1 ;
 
457
    } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
 
458
        ret = 0 ;
 
459
    } else {
 
460
        ret = notfound ;
 
461
    }
 
462
    return ret;
 
463
}
 
464
 
 
465
/*-------------------------------------------------------------------------*/
 
466
/**
 
467
  @brief    Finds out if a given entry exists in a dictionary
 
468
  @param    ini     Dictionary to search
 
469
  @param    entry   Name of the entry to look for
 
470
  @return   integer 1 if entry exists, 0 otherwise
 
471
 
 
472
  Finds out if a given entry exists in the dictionary. Since sections
 
473
  are stored as keys with NULL associated values, this is the only way
 
474
  of querying for the presence of sections in a dictionary.
 
475
 */
 
476
/*--------------------------------------------------------------------------*/
 
477
int iniparser_find_entry(
 
478
    dictionary  *   ini,
 
479
    char        *   entry
 
480
)
 
481
{
 
482
    int found=0 ;
 
483
    if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
 
484
        found = 1 ;
 
485
    }
 
486
    return found ;
 
487
}
 
488
 
 
489
/*-------------------------------------------------------------------------*/
 
490
/**
 
491
  @brief    Set an entry in a dictionary.
 
492
  @param    ini     Dictionary to modify.
 
493
  @param    entry   Entry to modify (entry name)
 
494
  @param    val     New value to associate to the entry.
 
495
  @return   int 0 if Ok, -1 otherwise.
 
496
 
 
497
  If the given entry can be found in the dictionary, it is modified to
 
498
  contain the provided value. If it cannot be found, -1 is returned.
 
499
  It is Ok to set val to NULL.
 
500
 */
 
501
/*--------------------------------------------------------------------------*/
 
502
int iniparser_set(dictionary * ini, char * entry, char * val)
 
503
{
 
504
    return dictionary_set(ini, strlwc(entry), val) ;
 
505
}
 
506
 
 
507
/*-------------------------------------------------------------------------*/
 
508
/**
 
509
  @brief    Delete an entry in a dictionary
 
510
  @param    ini     Dictionary to modify
 
511
  @param    entry   Entry to delete (entry name)
 
512
  @return   void
 
513
 
 
514
  If the given entry can be found, it is deleted from the dictionary.
 
515
 */
 
516
/*--------------------------------------------------------------------------*/
 
517
void iniparser_unset(dictionary * ini, char * entry)
 
518
{
 
519
    dictionary_unset(ini, strlwc(entry));
 
520
}
 
521
 
 
522
/*-------------------------------------------------------------------------*/
 
523
/**
 
524
  @brief        Load a single line from an INI file
 
525
  @param    input_line  Input line, may be concatenated multi-line input
 
526
  @param    section     Output space to store section
 
527
  @param    key         Output space to store key
 
528
  @param    value       Output space to store value
 
529
  @return   line_status value
 
530
 */
 
531
/*--------------------------------------------------------------------------*/
 
532
static line_status iniparser_line(
 
533
    char * input_line,
 
534
    char * section,
 
535
    char * key,
 
536
    char * value)
 
537
{
 
538
    line_status sta ;
 
539
    char        line[ASCIILINESZ+1];
 
540
    int         len ;
 
541
 
 
542
    strcpy(line, strstrip(input_line));
 
543
    len = (int)strlen(line);
 
544
 
 
545
    sta = LINE_UNPROCESSED ;
 
546
    if (len<1) {
 
547
        /* Empty line */
 
548
        sta = LINE_EMPTY ;
 
549
    } else if (line[0]=='#' || line[0]==';') {
 
550
        /* Comment line */
 
551
        sta = LINE_COMMENT ;
 
552
    } else if (line[0]=='[' && line[len-1]==']') {
 
553
        /* Section name */
 
554
        sscanf(line, "[%[^]]", section);
 
555
        strcpy(section, strstrip(section));
 
556
        strcpy(section, section);
 
557
        sta = LINE_SECTION ;
 
558
    } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
 
559
           ||  sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2
 
560
           ||  sscanf (line, "%[^=] = %[^;#]",     key, value) == 2) {
 
561
        /* Usual key=value, with or without comments */
 
562
        strcpy(key, strstrip(key));
 
563
        strcpy(key, key);
 
564
        strcpy(value, strstrip(value));
 
565
        /*
 
566
         * sscanf cannot handle '' or "" as empty values
 
567
         * this is done here
 
568
         */
 
569
        if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
 
570
            value[0]=0 ;
 
571
        }
 
572
        sta = LINE_VALUE ;
 
573
    } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
 
574
           ||  sscanf(line, "%[^=] %[=]", key, value) == 2) {
 
575
        /*
 
576
         * Special cases:
 
577
         * key=
 
578
         * key=;
 
579
         * key=#
 
580
         */
 
581
        strcpy(key, strstrip(key));
 
582
        strcpy(key, key);
 
583
        value[0]=0 ;
 
584
        sta = LINE_VALUE ;
 
585
    } else {
 
586
        /* Generate syntax error */
 
587
        sta = LINE_ERROR ;
 
588
    }
 
589
    return sta ;
 
590
}
 
591
 
 
592
/*-------------------------------------------------------------------------*/
 
593
/**
 
594
  @brief    Parse an ini file and return an allocated dictionary object
 
595
  @param    ininame Name of the ini file to read.
 
596
  @return   Pointer to newly allocated dictionary
 
597
 
 
598
  This is the parser for ini files. This function is called, providing
 
599
  the name of the file to be read. It returns a dictionary object that
 
600
  should not be accessed directly, but through accessor functions
 
601
  instead.
 
602
 
 
603
  The returned dictionary must be freed using iniparser_freedict().
 
604
 */
 
605
/*--------------------------------------------------------------------------*/
 
606
dictionary * iniparser_load(const char * ininame)
 
607
{
 
608
    FILE * in ;
 
609
 
 
610
    char line    [ASCIILINESZ+1] ;
 
611
    char section [ASCIILINESZ+1] ;
 
612
    char key     [ASCIILINESZ+1] ;
 
613
    char tmp     [ASCIILINESZ+1] ;
 
614
    char val     [ASCIILINESZ+1] ;
 
615
 
 
616
    int  last=0 ;
 
617
    int  len ;
 
618
    int  lineno=0 ;
 
619
    int  errs=0;
 
620
 
 
621
    dictionary * dict ;
 
622
 
 
623
    if ((in=fopen(ininame, "r"))==NULL) {
 
624
        fprintf(stderr, "iniparser: cannot open %s\n", ininame);
 
625
        return NULL ;
 
626
    }
 
627
 
 
628
    dict = dictionary_new(0) ;
 
629
    if (!dict) {
 
630
        fclose(in);
 
631
        return NULL ;
 
632
    }
 
633
 
 
634
    memset(line,    0, ASCIILINESZ);
 
635
    memset(section, 0, ASCIILINESZ);
 
636
    memset(key,     0, ASCIILINESZ);
 
637
    memset(val,     0, ASCIILINESZ);
 
638
    last=0 ;
 
639
 
 
640
    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
 
641
        lineno++ ;
 
642
        len = (int)strlen(line)-1;
 
643
        /* Safety check against buffer overflows */
 
644
        if (line[len]!='\n') {
 
645
            fprintf(stderr,
 
646
                    "iniparser: input line too long in %s (%d)\n",
 
647
                    ininame,
 
648
                    lineno);
 
649
            dictionary_del(dict);
 
650
            fclose(in);
 
651
            return NULL ;
 
652
        }
 
653
        /* Get rid of \n and spaces at end of line */
 
654
        while ((len>=0) &&
 
655
                ((line[len]=='\n') || (isspace(line[len])))) {
 
656
            line[len]=0 ;
 
657
            len-- ;
 
658
        }
 
659
        /* Detect multi-line */
 
660
        if (line[len]=='\\') {
 
661
            /* Multi-line value */
 
662
            last=len ;
 
663
            continue ;
 
664
        } else {
 
665
            last=0 ;
 
666
        }
 
667
        switch (iniparser_line(line, section, key, val)) {
 
668
            case LINE_EMPTY:
 
669
            case LINE_COMMENT:
 
670
            break ;
 
671
 
 
672
            case LINE_SECTION:
 
673
            errs = dictionary_set(dict, section, NULL);
 
674
            break ;
 
675
 
 
676
            case LINE_VALUE:
 
677
            sprintf(tmp, "%s:%s", section, key);
 
678
            errs = dictionary_set(dict, tmp, val) ;
 
679
            break ;
 
680
 
 
681
            case LINE_ERROR:
 
682
            fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
 
683
                    ininame,
 
684
                    lineno);
 
685
            fprintf(stderr, "-> %s\n", line);
 
686
            errs++ ;
 
687
            break;
 
688
 
 
689
            default:
 
690
            break ;
 
691
        }
 
692
        memset(line, 0, ASCIILINESZ);
 
693
        last=0;
 
694
        if (errs<0) {
 
695
            fprintf(stderr, "iniparser: memory allocation failure\n");
 
696
            break ;
 
697
        }
 
698
    }
 
699
    if (errs) {
 
700
        dictionary_del(dict);
 
701
        dict = NULL ;
 
702
    }
 
703
    fclose(in);
 
704
    return dict ;
 
705
}
 
706
 
 
707
/*-------------------------------------------------------------------------*/
 
708
/**
 
709
  @brief    Free all memory associated to an ini dictionary
 
710
  @param    d Dictionary to free
 
711
  @return   void
 
712
 
 
713
  Free all memory associated to an ini dictionary.
 
714
  It is mandatory to call this function before the dictionary object
 
715
  gets out of the current context.
 
716
 */
 
717
/*--------------------------------------------------------------------------*/
 
718
void iniparser_freedict(dictionary * d)
 
719
{
 
720
    dictionary_del(d);
 
721
}
 
722
 
 
723
/* vim: set ts=4 et sw=4 tw=75 */