2 /*-------------------------------------------------------------------------*/
8 @brief Parser for ini files.
10 /*--------------------------------------------------------------------------*/
12 $Id: iniparser.c,v 1.1.2.1 2010-02-12 10:19:23 kleplat Exp $
14 $Date: 2010-02-12 10:19:23 $
16 /*---------------------------- Includes ------------------------------------*/
18 #include "iniparser.h"
20 #include <VP_Os/vp_os_print.h>
22 #include <Maths/matrices.h>
25 #undef ARDRONE_CONFIG_KEY_IMM
26 #undef ARDRONE_CONFIG_KEY_REF
27 #undef ARDRONE_CONFIG_KEY_STR
28 #define ARDRONE_CONFIG_KEY_IMM(KEY, NAME, INI_TYPE, C_TYPE, C_TYPE_PTR, RW, DEFAULT, CALLBACK)
29 #define ARDRONE_CONFIG_KEY_REF(KEY, NAME, INI_TYPE, C_TYPE, C_TYPE_PTR, RW, DEFAULT, CALLBACK)
30 #define ARDRONE_CONFIG_KEY_STR(KEY, NAME, INI_TYPE, C_TYPE, C_TYPE_PTR, RW, DEFAULT, CALLBACK)
31 #include <config_keys.h>
33 /*---------------------------- Defines -------------------------------------*/
34 #define ASCIILINESZ (1024)
35 #define INI_INVALID_KEY ((char*)-1)
37 /*---------------------------------------------------------------------------
38 Private to this module
39 ---------------------------------------------------------------------------*/
41 * This enum stores the status for each parsed line (internal use only).
43 typedef enum _line_status_ {
52 /*-------------------------------------------------------------------------*/
54 @brief Convert a string to lowercase.
55 @param s String to convert.
56 @return ptr to statically allocated string.
58 This function returns a pointer to a statically allocated string
59 containing a lowercased version of the input string. Do not free
60 or modify the returned string! Since the returned string is statically
61 allocated, it will be modified at each function call (not re-entrant).
63 /*--------------------------------------------------------------------------*/
64 static char * strlwc(const char * s)
66 static char l[ASCIILINESZ+1];
69 if (s==NULL) return NULL ;
70 memset(l, 0, sizeof(l));
72 while (s[i] && i<ASCIILINESZ) {
73 l[i] = (char)tolower((int)s[i]);
76 l[ASCIILINESZ]=(char)0;
80 /*-------------------------------------------------------------------------*/
82 @brief Remove blanks at the beginning and the end of a string.
83 @param s String to parse.
84 @return ptr to statically allocated string.
86 This function returns a pointer to a statically allocated string,
87 which is identical to the input string, except that all blank
88 characters at the end and the beg. of the string have been removed.
89 Do not free or modify the returned string! Since the returned string
90 is statically allocated, it will be modified at each function call
93 /*--------------------------------------------------------------------------*/
94 static char * strstrip(char * s)
96 static char l[ASCIILINESZ+1];
99 if (s==NULL) return NULL ;
101 while (isspace((int)*s) && *s) s++;
102 memset(l, 0, ASCIILINESZ+1);
104 last = l + strlen(l);
106 if (!isspace((int)*(last-1)))
114 /*-------------------------------------------------------------------------*/
116 @brief Get number of sections in a dictionary
117 @param d Dictionary to examine
118 @return int Number of sections found in dictionary
120 This function returns the number of sections found in a dictionary.
121 The test to recognize sections is done on the string stored in the
122 dictionary: a section name is given as "section" whereas a key is
123 stored as "section:key", thus the test looks for entries that do not
126 This clearly fails in the case a section name contains a colon, but
127 this should simply be avoided.
129 This function returns -1 in case of error.
131 /*--------------------------------------------------------------------------*/
132 int iniparser_getnsec(dictionary * d)
137 if (d==NULL) return -1 ;
139 for (i=0 ; i<d->size ; i++) {
142 if (/*strchr(d->key[i], ':')*/d->values[i].type==INI_SECTION) {
149 /*-------------------------------------------------------------------------*/
151 @brief Get name for section n in a dictionary.
152 @param d Dictionary to examine
153 @param n Section number (from 0 to nsec-1).
154 @return Pointer to char string
156 This function locates the n-th section in a dictionary and returns
157 its name as a pointer to a string statically allocated inside the
158 dictionary. Do not free or modify the returned string!
160 This function returns NULL in case of error.
162 /*--------------------------------------------------------------------------*/
163 char * iniparser_getsecname(dictionary * d, int n)
168 if (d==NULL || n<0) return NULL ;
170 for (i=0 ; i<d->size ; i++) {
173 if (/*strchr(d->key[i], ':')==NULL*/ d->values[i].type==INI_SECTION) {
185 /*-------------------------------------------------------------------------*/
187 @brief Duplicate a string
188 @param s String to duplicate
189 @return Pointer to a newly allocated string, to be freed with free()
191 This is a replacement for strdup(). This implementation is provided
192 for systems that do not have it.
194 /*--------------------------------------------------------------------------*/
195 static char * xstrdup(const char * s)
200 t = malloc(strlen(s)+1) ;
207 void iniparser_ptr2val(dictionary_value* value)
209 if( value && value->ptr != NULL )
217 switch( value->type )
220 value->val = xstrdup(value->ptr);
224 value->val = malloc(64);
225 sprintf(value->val, "%d", *(int*)(value->ptr));
229 value->val = malloc(64);
230 sprintf(value->val, "%.7e", *(float*)(value->ptr));
234 value->val = malloc(64);
235 sprintf(value->val, "%.16e", *(double*)(value->ptr));
239 value->val = malloc(64);
240 sprintf(value->val, "%s", ( *(int*)(value->ptr) ? "TRUE" : "FALSE" ) );
244 value->val = malloc(256);
245 sprintf(value->val, "{ %.7e %.7e %.7e }", ((vector31_t*)value->ptr)->x, ((vector31_t*)value->ptr)->y, ((vector31_t*)value->ptr)->z);
249 value->val = malloc(256);
250 sprintf(value->val, "{ %.7e %.7e }", ((vector21_t*)value->ptr)->x, ((vector21_t*)value->ptr)->y);
254 value->val = malloc(1024);
255 sprintf(value->val, "{ %.7e %.7e %.7e %.7e %.7e %.7e %.7e %.7e %.7e }",
256 ((matrix33_t*)value->ptr)->m11, ((matrix33_t*)value->ptr)->m12, ((matrix33_t*)value->ptr)->m13,
257 ((matrix33_t*)value->ptr)->m21, ((matrix33_t*)value->ptr)->m22, ((matrix33_t*)value->ptr)->m23,
258 ((matrix33_t*)value->ptr)->m31, ((matrix33_t*)value->ptr)->m32, ((matrix33_t*)value->ptr)->m33 );
268 void iniparser_val2ptr(dictionary_value* value)
272 if( value->ptr != NULL && value->val != NULL )
274 switch( value->type )
277 strcpy(value->ptr, value->val);
281 *(int*)(value->ptr) = (int)strtol(value->val, NULL, 0);
285 *(float*)(value->ptr) = (float)atof(value->val);
289 *(double*)(value->ptr) = (double)atof(value->val);
295 char c = value->val[0];
297 if( c=='y' || c=='Y' || c=='1' || c=='t' || c=='T') {
299 } else if (c=='n' || c=='N' || c=='0' || c=='f' || c=='F') {
306 *(int*)(value->ptr) = ret;
311 sscanf(value->val, "{ %e %e %e }", &((vector31_t*)value->ptr)->x, &((vector31_t*)value->ptr)->y, &((vector31_t*)value->ptr)->z);
315 sscanf(value->val, "{ %e %e }", &((vector21_t*)value->ptr)->x, &((vector21_t*)value->ptr)->y);
319 sscanf(value->val, "{ %e %e %e %e %e %e %e %e %e }",
320 &((matrix33_t*)value->ptr)->m11, &((matrix33_t*)value->ptr)->m12, &((matrix33_t*)value->ptr)->m13,
321 &((matrix33_t*)value->ptr)->m21, &((matrix33_t*)value->ptr)->m22, &((matrix33_t*)value->ptr)->m23,
322 &((matrix33_t*)value->ptr)->m31, &((matrix33_t*)value->ptr)->m32, &((matrix33_t*)value->ptr)->m33 );
335 /*-------------------------------------------------------------------------*/
337 @brief Transfer values from the dictionary to the bound variables
338 @param d Dictionary to dump.
339 @param scope Scope for which values must be transfered (set to -1 to tranfer all values)
342 /*--------------------------------------------------------------------------*/
343 void iniparser_vals2ptrs(dictionary * d , int scope)
347 if (d==NULL) return ;
348 for (i=0 ; i<d->size ; i++) {
353 if( d->values[i].ptr != NULL ) {
354 if (scope==-1 || d->values[i].scope==scope) {
355 iniparser_val2ptr(&d->values[i]);
364 /*-------------------------------------------------------------------------*/
366 @brief Transfer values from the bound variables to the dictionary.
367 @param d Dictionary to fill.
368 @param scope Scope for which values must be transfered (set to -1 to tranfer all values)
371 /*--------------------------------------------------------------------------*/
372 void iniparser_ptrs2vals(dictionary * d , int scope)
376 if (d==NULL) return ;
377 for (i=0 ; i<d->size ; i++) {
382 if( d->values[i].ptr != NULL ) {
383 if (scope==-1 || d->values[i].scope==scope) {
384 iniparser_ptr2val(&d->values[i]);
392 /*-------------------------------------------------------------------------*/
394 @brief Dump a dictionary to an opened file pointer.
395 @param d Dictionary to dump.
396 @param f Opened file pointer to dump to.
399 This function prints out the contents of a dictionary, one element by
400 line, onto the provided file pointer. It is OK to specify @c stderr
401 or @c stdout as output files. This function is meant for debugging
404 /*--------------------------------------------------------------------------*/
405 void iniparser_dump(dictionary * d)
409 if (d==NULL) return ;
410 for (i=0 ; i<d->size ; i++) {
413 if( d->values[i].ptr != NULL ) {
414 switch(d->values[i].type)
417 PRINT("%s= %s [STRING]\n", d->key[i], d->values[i].val);
421 PRINT("%s= %d [INT]\n", d->key[i], *(int*)d->values[i].ptr);
425 PRINT("%s= %f [FLOAT]\n", d->key[i], *(float*)d->values[i].ptr);
429 PRINT("%s= %lf [DOUBLE]\n", d->key[i], *(double*)d->values[i].ptr);
433 PRINT("%s= %d [BOOLEAN]\n", d->key[i], *(int*)d->values[i].ptr);
437 PRINT("%s= { %f %f %f } [VECTOR]\n", d->key[i], ((vector31_t*)d->values[i].ptr)->x,
438 ((vector31_t*)d->values[i].ptr)->y,
439 ((vector31_t*)d->values[i].ptr)->z);
443 PRINT("%s= { %f %f } [VECTOR21]\n", d->key[i], ((vector21_t*)d->values[i].ptr)->x,
444 ((vector21_t*)d->values[i].ptr)->y);
448 PRINT("%s= { %f %f %f %f %f %f %f %f %f } [MATRIX]\n", d->key[i],
449 ((matrix33_t*)d->values[i].ptr)->m11, ((matrix33_t*)d->values[i].ptr)->m12, ((matrix33_t*)d->values[i].ptr)->m13,
450 ((matrix33_t*)d->values[i].ptr)->m21, ((matrix33_t*)d->values[i].ptr)->m22, ((matrix33_t*)d->values[i].ptr)->m23,
451 ((matrix33_t*)d->values[i].ptr)->m31, ((matrix33_t*)d->values[i].ptr)->m32, ((matrix33_t*)d->values[i].ptr)->m33 );
456 PRINT("%s=[%s]\n", d->key[i], d->values[i].val);
459 // fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
461 if (d->values[i].val!=NULL) {
462 PRINT("%s=[%s]\n", d->key[i], d->values[i].val);
465 if( d->values[i].type == INI_SECTION )
466 PRINT("[%s]\n", d->key[i]);
468 PRINT("%s=UNDEF\n", d->key[i]);
469 // fprintf(f, "[%s]=UNDEF\n", d->key[i]);
476 /*-------------------------------------------------------------------------*/
478 @brief Save a dictionary to a loadable ini file
479 @param d Dictionary to dump
480 @param f Opened file pointer to dump to
481 @param flag_dump_k_shallows If true, K_SHALLOW values are written on disk
484 This function dumps a given dictionary into a loadable ini file.
485 It is Ok to specify @c stderr or @c stdout as output files.
487 /*--------------------------------------------------------------------------*/
488 void iniparser_dump_ini(dictionary * d, FILE * f)
489 { iniparser_dump_ini_a4(d,f,0,1); }
490 void iniparser_dump_ini_a3(dictionary * d, FILE * f , int flag_dump_k_shallows)
491 { iniparser_dump_ini_a4(d,f,flag_dump_k_shallows,1); }
493 void iniparser_dump_ini_a4(dictionary * d, FILE * f , int flag_dump_k_shallows , int update_values_from_memory)
496 char keym[ASCIILINESZ+1];
501 if (d==NULL || f==NULL) return ;
503 nsec = iniparser_getnsec(d);
505 /* No section in file: dump all keys as they are */
506 for (i=0 ; i<d->size ; i++) {
509 /* Stephane - add K_SHALLOW support */
510 if (!flag_dump_k_shallows)
511 if ((d->values[i].rw&K_SHALLOW)!=0)
513 if(update_values_from_memory)
514 iniparser_ptr2val(&d->values[i]); // Make sure we are synchro before dump
515 fprintf(f, "%s = %s\n", d->key[i], d->values[i].val);
519 for (i=0 ; i<nsec ; i++) {
520 secname = iniparser_getsecname(d, i) ;
521 seclen = (int)strlen(secname);
522 fprintf(f, "\n[%s]\n", secname);
523 sprintf(keym, "%s:", secname);
524 for (j=0 ; j<d->size ; j++) {
527 /* Stephane - add K_SHALLOW support */
528 if (!flag_dump_k_shallows)
529 if ((d->values[j].rw&K_SHALLOW)!=0)
531 if (!strncmp(d->key[j], strlwc(keym), seclen+1)) {
532 if(update_values_from_memory)
533 iniparser_ptr2val(&d->values[j]); // Make sure we are synchro before dump
537 d->values[j].val ? d->values[j].val : "");
545 static dictionary_value* iniparser_getdictionaryvalue(dictionary * d, const char * key)
549 if (d==NULL || key==NULL)
552 lc_key = strlwc(key);
553 return dictionary_get(d, lc_key);
556 int iniparser_alias_ex(dictionary * d, const char* kkey, int type, void* ptr, void (*cb)(void), char rw,int scope);
557 int iniparser_alias(dictionary * d, const char* kkey, int type, void* ptr, void (*cb)(void), char rw)
558 { return iniparser_alias_ex(d,kkey,type,ptr,cb,rw,CAT_COMMON); }
560 int iniparser_alias_ex(dictionary * d, const char* kkey, int type, void* ptr, void (*cb)(void), char rw,int scope)
562 dictionary_value* value;
564 char key[ASCIILINESZ];
566 strcpy(&key[0], kkey);
568 // Create a new section ?
569 pos = strchr(key, ':');
573 value = iniparser_getdictionaryvalue(d, key);
575 dictionary_set(d, key, NULL, INI_SECTION, NULL,NULL);
583 value = iniparser_getdictionaryvalue(d, key);
585 // TODO: change hardcoded value
590 // Create a new value
591 value = dictionary_set(d, strlwc(key), NULL, type, ptr, cb);
592 value->callback = cb;
594 value->scope = scope;
595 iniparser_ptr2val(value);
609 // setup existing value
612 value->callback = cb;
614 value->scope = scope;
618 iniparser_ptr2val(value);
622 iniparser_val2ptr(value);
630 dictionary_unset(d, key);
637 /*-------------------------------------------------------------------------*/
639 @brief Get the string associated to a key
640 @param d Dictionary to search
641 @param key Key string to look for
642 @param def Default value to return if key not found.
643 @return pointer to statically allocated character string
645 This function queries a dictionary for a key. A key as read from an
646 ini file is given as "section:key". If the key cannot be found,
647 the pointer passed as 'def' is returned.
648 The returned char pointer is pointing to a string allocated in
649 the dictionary, do not free or modify it.
651 /*--------------------------------------------------------------------------*/
652 char * iniparser_getstring(dictionary * d, const char * key, char * def)
654 dictionary_value* value = iniparser_getdictionaryvalue(d, key);
662 /*-------------------------------------------------------------------------*/
664 @brief Get the string associated to a key, convert to an int
665 @param d Dictionary to search
666 @param key Key string to look for
667 @param notfound Value to return in case of error
670 This function queries a dictionary for a key. A key as read from an
671 ini file is given as "section:key". If the key cannot be found,
672 the notfound value is returned.
674 Supported values for integers include the usual C notation
675 so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
676 are supported. Examples:
679 "042" -> 34 (octal -> decimal)
680 "0x42" -> 66 (hexa -> decimal)
682 Warning: the conversion may overflow in various ways. Conversion is
683 totally outsourced to strtol(), see the associated man page for overflow
686 Credits: Thanks to A. Becker for suggesting strtol()
688 /*--------------------------------------------------------------------------*/
689 int iniparser_getint(dictionary * d, const char * key, int notfound)
693 dictionary_value* value = iniparser_getdictionaryvalue(d, key);
700 i = *(int*)(value->ptr);
704 i = strtol(value->val, NULL, 0);
710 /*-------------------------------------------------------------------------*/
712 @brief Get the string associated to a key, convert to a double
713 @param d Dictionary to search
714 @param key Key string to look for
715 @param notfound Value to return in case of error
718 This function queries a dictionary for a key. A key as read from an
719 ini file is given as "section:key". If the key cannot be found,
720 the notfound value is returned.
722 /*--------------------------------------------------------------------------*/
723 double iniparser_getdouble(dictionary * dict, char * key, double notfound)
726 dictionary_value* value = iniparser_getdictionaryvalue(dict, key);
733 switch( value->type )
736 d = (double)*(float*)(value->ptr);
739 d = *(double*)(value->ptr);
748 d = (int)atof(value->val);
754 /*-------------------------------------------------------------------------*/
756 @brief Get the string associated to a key, convert to a boolean
757 @param d Dictionary to search
758 @param key Key string to look for
759 @param notfound Value to return in case of error
762 This function queries a dictionary for a key. A key as read from an
763 ini file is given as "section:key". If the key cannot be found,
764 the notfound value is returned.
766 A true boolean is found if one of the following is matched:
768 - A string starting with 'y'
769 - A string starting with 'Y'
770 - A string starting with 't'
771 - A string starting with 'T'
772 - A string starting with '1'
774 A false boolean is found if one of the following is matched:
776 - A string starting with 'n'
777 - A string starting with 'N'
778 - A string starting with 'f'
779 - A string starting with 'F'
780 - A string starting with '0'
782 The notfound value returned if no boolean is identified, does not
783 necessarily have to be 0 or 1.
785 /*--------------------------------------------------------------------------*/
786 int iniparser_getboolean(dictionary* dict, const char* key, int notfound)
790 dictionary_value* value = iniparser_getdictionaryvalue(dict, key);
797 ret = *(int*)(value->ptr);
801 char c = value->val[0];
803 if( c=='y' || c=='Y' || c=='1' || c=='t' || c=='T') {
805 } else if (c=='n' || c=='N' || c=='0' || c=='f' || c=='F') {
815 /*-------------------------------------------------------------------------*/
817 @brief Finds out if a given entry exists in a dictionary
818 @param ini Dictionary to search
819 @param entry Name of the entry to look for
820 @return integer 1 if entry exists, 0 otherwise
822 Finds out if a given entry exists in the dictionary. Since sections
823 are stored as keys with NULL associated values, this is the only way
824 of querying for the presence of sections in a dictionary.
826 /*--------------------------------------------------------------------------*/
827 int iniparser_find_entry( dictionary * ini, char* entry )
829 return iniparser_getstring(ini, entry, INI_INVALID_KEY) != INI_INVALID_KEY ? 1 : 0;
832 /*-------------------------------------------------------------------------*/
834 @brief Set an entry in a dictionary.
835 @param ini Dictionary to modify.
836 @param entry Entry to modify (entry name)
837 @param val New value to associate to the entry.
838 @return int 0 if Ok, -1 otherwise.
840 If the given entry can be found in the dictionary, it is modified to
841 contain the provided value. If it cannot be found, -1 is returned.
842 It is Ok to set val to NULL.
844 /*--------------------------------------------------------------------------*/
846 int iniparser_setstring(dictionary * ini, const char * entry, const char * val)
847 { return iniparser_setstring_a4(ini,entry,val,1); }
849 int iniparser_setstring_a4(dictionary * ini,const char * entry, const char * val , int trigger_callback)
851 dictionary_value* value = dictionary_set(ini, strlwc(entry), val, INI_UNKNOW, NULL,NULL);
856 iniparser_val2ptr(value);
858 if( (trigger_callback) && (value->callback) )
864 /*-------------------------------------------------------------------------*/
866 @brief Delete an entry in a dictionary
867 @param ini Dictionary to modify
868 @param entry Entry to delete (entry name)
871 If the given entry can be found, it is deleted from the dictionary.
873 /*--------------------------------------------------------------------------*/
874 void iniparser_unset(dictionary * ini, char * entry)
876 dictionary_unset(ini, strlwc(entry));
879 /*-------------------------------------------------------------------------*/
881 @brief Load a single line from an INI file
882 @param input_line Input line, may be concatenated multi-line input
883 @param section Output space to store section
884 @param key Output space to store key
885 @param value Output space to store value
886 @return line_status value
888 /*--------------------------------------------------------------------------*/
889 static line_status iniparser_line(
896 char line[ASCIILINESZ+1];
899 strcpy(line, strstrip(input_line));
900 len = (int)strlen(line);
902 sta = LINE_UNPROCESSED ;
906 } else if (line[0]=='#') {
909 } else if (line[0]=='[' && line[len-1]==']') {
911 sscanf(line, "[%[^]]", section);
912 strcpy(section, strstrip(section));
913 strcpy(section, strlwc(section));
915 } else if ((sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
916 || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2
917 || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) /*&& (strcmp(section,""))*/) {
918 /* Usual key=value, with or without comments */
919 strcpy(key, strstrip(key));
920 strcpy(key, strlwc(key));
921 strcpy(value, strstrip(value));
923 * sscanf cannot handle '' or "" as empty values
926 if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
930 } else if ((sscanf(line, "%[^=] = %[;#]", key, value)==2
931 || sscanf(line, "%[^=] %[=]", key, value) == 2) /*&& (strcmp(section,""))*/) {
938 strcpy(key, strstrip(key));
939 strcpy(key, strlwc(key));
943 /* Generate syntax error */
949 /*-------------------------------------------------------------------------*/
951 @brief Parse an ini file and return an allocated dictionary object
952 @param ininame Name of the ini file to read.
953 @return Pointer to newly allocated dictionary
955 This is the parser for ini files. This function is called, providing
956 the name of the file to be read. It returns a dictionary object that
957 should not be accessed directly, but through accessor functions
960 The returned dictionary must be freed using iniparser_freedict().
962 /*--------------------------------------------------------------------------*/
963 dictionary * iniparser_load(FILE* in, dictionary * dict )
965 char line [ASCIILINESZ+1] ;
966 char section [ASCIILINESZ+1] ;
967 char key [ASCIILINESZ+1] ;
968 char tmp [ASCIILINESZ+1] ;
969 char val [ASCIILINESZ+1] ;
976 if ((in=fopen(ininame, "r"))==NULL) {
977 fprintf(stderr, "iniparser: cannot open %s\n", ininame);
982 dict = dictionary_new(0) ;
989 memset(line, 0, ASCIILINESZ);
990 memset(section, 0, ASCIILINESZ);
991 memset(key, 0, ASCIILINESZ);
992 memset(val, 0, ASCIILINESZ);
995 while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
997 len = (int)strlen(line)-1;
998 /* Safety check against buffer overflows */
999 if (line[len]!='\n') {
1001 "iniparser: input line too long in file (line %d)\n",
1004 dictionary_del(dict);
1009 /* Get rid of \n and spaces at end of line */
1011 ((line[len]=='\n') || (isspace(line[len])))) {
1015 /* Detect multi-line */
1016 if (line[len]=='\\') {
1017 /* Multi-line value */
1023 switch (iniparser_line(line, section, key, val)) {
1029 errs = dictionary_set(dict, section, NULL, INI_SECTION, NULL,NULL) != NULL ? 0 : -1;
1033 if (strcmp(section,"")!=0)
1034 sprintf(tmp, "%s:%s", section, key);
1037 errs = iniparser_setstring(dict, tmp, val);
1038 // errs = dictionary_set(dict, tmp, val, UNKNOW, NULL) != NULL ? 0 : -1;
1042 fprintf(stderr, "iniparser: syntax error in file (%d):\n",
1045 fprintf(stderr, "-> %s\n", line);
1052 memset(line, 0, ASCIILINESZ);
1055 fprintf(stderr, "iniparser: memory allocation failure\n");
1060 dictionary_del(dict);
1067 /*-------------------------------------------------------------------------*/
1069 @brief Free all memory associated to an ini dictionary
1070 @param d Dictionary to free
1073 Free all memory associated to an ini dictionary.
1074 It is mandatory to call this function before the dictionary object
1075 gets out of the current context.
1077 /*--------------------------------------------------------------------------*/
1078 void iniparser_freedict(dictionary * d)
1083 /* vim: set ts=4 et sw=4 tw=75 */