testing/mozbase/mozprocess/tests/iniparser/iniparser.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial