-
/*-------------------------------------------------------------------------*/
/**
@file iniparser.c
@version 3.0
@brief Parser for ini files.
*/
-/*--------------------------------------------------------------------------*/
-/*
- $Id: iniparser.c,v 2.19 2011-03-02 20:15:13 ndevilla Exp $
- $Revision: 2.19 $
- $Date: 2011-03-02 20:15:13 $
-*/
+
/*---------------------------- Includes ------------------------------------*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
#include <ctype.h>
-#include "iniparser.h"
+
+#include <atalk/iniparser.h>
+#include <atalk/logger.h>
/*---------------------------- Defines -------------------------------------*/
#define ASCIILINESZ (1024)
/*-------------------------------------------------------------------------*/
/**
- @brief Convert a string to lowercase.
- @param s String to convert.
- @return ptr to statically allocated string.
-
- This function returns a pointer to a statically allocated string
- containing a lowercased version of the input string. Do not free
- or modify the returned string! Since the returned string is statically
- allocated, it will be modified at each function call (not re-entrant).
- */
-/*--------------------------------------------------------------------------*/
-static char * strlwc(char * s)
-{
- static char l[ASCIILINESZ+1];
- int i ;
-
- if (s==NULL) return NULL ;
- memset(l, 0, ASCIILINESZ+1);
- i=0 ;
- while (s[i] && i<ASCIILINESZ) {
- l[i] = (char)tolower((int)s[i]);
- i++ ;
- }
- l[ASCIILINESZ]=(char)0;
- return l ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
- @brief Remove blanks at the beginning and the end of a string.
- @param s String to parse.
- @return ptr to statically allocated string.
+ @brief Remove blanks at the beginning and the end of a string.
+ @param s String to parse.
+ @return ptr to statically allocated string.
This function returns a pointer to a statically allocated string,
which is identical to the input string, except that all blank
static char * strstrip(char * s)
{
static char l[ASCIILINESZ+1];
- char * last ;
-
+ char * last ;
+
if (s==NULL) return NULL ;
-
- while (isspace((int)*s) && *s) s++;
- memset(l, 0, ASCIILINESZ+1);
- strcpy(l, s);
- last = l + strlen(l);
- while (last > l) {
- if (!isspace((int)*(last-1)))
- break ;
- last -- ;
- }
- *last = (char)0;
- return (char*)l ;
+
+ while (isspace((int)*s) && *s) s++;
+ memset(l, 0, ASCIILINESZ+1);
+ strcpy(l, s);
+ last = l + strlen(l);
+ while (last > l) {
+ if (!isspace((int)*(last-1)))
+ break ;
+ last -- ;
+ }
+ *last = (char)0;
+ return (char*)l ;
}
/*-------------------------------------------------------------------------*/
This function returns -1 in case of error.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getnsec(dictionary * d)
+int atalk_iniparser_getnsec(const dictionary * d)
{
int i ;
int nsec ;
This function returns NULL in case of error.
*/
/*--------------------------------------------------------------------------*/
-char * iniparser_getsecname(dictionary * d, int n)
+const char * atalk_iniparser_getsecname(const dictionary * d, int n)
{
int i ;
int foundsec ;
purposes mostly.
*/
/*--------------------------------------------------------------------------*/
-void iniparser_dump(dictionary * d, FILE * f)
+void atalk_iniparser_dump(const dictionary * d, FILE * f)
{
int i ;
It is Ok to specify @c stderr or @c stdout as output files.
*/
/*--------------------------------------------------------------------------*/
-void iniparser_dump_ini(dictionary * d, FILE * f)
+void atalk_iniparser_dump_ini(const dictionary * d, FILE * f)
{
int i, j ;
char keym[ASCIILINESZ+1];
int nsec ;
- char * secname ;
+ const char * secname ;
int seclen ;
if (d==NULL || f==NULL) return ;
- nsec = iniparser_getnsec(d);
+ nsec = atalk_iniparser_getnsec(d);
if (nsec<1) {
/* No section in file: dump all keys as they are */
for (i=0 ; i<d->size ; i++) {
return ;
}
for (i=0 ; i<nsec ; i++) {
- secname = iniparser_getsecname(d, i) ;
+ secname = atalk_iniparser_getsecname(d, i) ;
seclen = (int)strlen(secname);
fprintf(f, "\n[%s]\n", secname);
sprintf(keym, "%s:", secname);
/**
@brief Get the string associated to a key
@param d Dictionary to search
+ @param section Section to search
@param key Key string to look for
@param def Default value to return if key not found.
@return pointer to statically allocated character string
the dictionary, do not free or modify it.
*/
/*--------------------------------------------------------------------------*/
-char * iniparser_getstring(dictionary * d, char * key, char * def)
+const char * atalk_iniparser_getstring(const dictionary * d, const char *section, const char * key, const char * def)
{
- char * lc_key ;
- char * sval ;
+ const char * sval ;
if (d==NULL || key==NULL)
return def ;
- lc_key = strlwc(key);
- sval = dictionary_get(d, lc_key, def);
+ sval = atalkdict_get(d, section, key, def);
return sval ;
}
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key
+ @param d Dictionary to search
+ @param section Section to search
+ @param key Key string to look for
+ @param def Default value to return if key not found.
+ @return pointer to statically allocated character string
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the pointer passed as 'def' is returned.
+ The returned char pointer a strdup'ed allocated string, so the caller must free it.
+ */
+/*--------------------------------------------------------------------------*/
+char * atalk_iniparser_getstrdup(const dictionary * d, const char *section, const char * key, const char * def)
+{
+ const char * sval ;
+
+ if (d==NULL || key==NULL)
+ return NULL;
+
+ if ((sval = atalkdict_get(d, section, key, def)))
+ return strdup(sval);
+ return NULL;
+}
+
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to an int
- @param d Dictionary to search
- @param key Key string to look for
+ @param d Dictionary to search
+ @param section Section to search
+ @param key Key string to look for
@param notfound Value to return in case of error
@return integer
Credits: Thanks to A. Becker for suggesting strtol()
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getint(dictionary * d, char * key, int notfound)
+int atalk_iniparser_getint(const dictionary * d, const char *section, const char * key, int notfound)
{
- char * str ;
+ const char * str ;
- str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ str = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY);
if (str==INI_INVALID_KEY) return notfound ;
return (int)strtol(str, NULL, 0);
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to a double
- @param d Dictionary to search
- @param key Key string to look for
+ @param d Dictionary to search
+ @param section Section to search
+ @param key Key string to look for
@param notfound Value to return in case of error
@return double
the notfound value is returned.
*/
/*--------------------------------------------------------------------------*/
-double iniparser_getdouble(dictionary * d, char * key, double notfound)
+double atalk_iniparser_getdouble(const dictionary * d, const char *section, const char * key, double notfound)
{
- char * str ;
+ const char * str ;
- str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ str = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY);
if (str==INI_INVALID_KEY) return notfound ;
return atof(str);
}
/*-------------------------------------------------------------------------*/
/**
@brief Get the string associated to a key, convert to a boolean
- @param d Dictionary to search
- @param key Key string to look for
+ @param d Dictionary to search
+ @param section Section to search
+ @param key Key string to look for
@param notfound Value to return in case of error
@return integer
necessarily have to be 0 or 1.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_getboolean(dictionary * d, char * key, int notfound)
+int atalk_iniparser_getboolean(const dictionary * d, const char *section, const char * key, int notfound)
{
- char * c ;
+ const char * c ;
int ret ;
- c = iniparser_getstring(d, key, INI_INVALID_KEY);
+ c = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY);
if (c==INI_INVALID_KEY) return notfound ;
if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
ret = 1 ;
of querying for the presence of sections in a dictionary.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_find_entry(
- dictionary * ini,
- char * entry
-)
+int atalk_iniparser_find_entry(const dictionary *ini, const char *entry)
{
int found=0 ;
- if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
+ if (atalk_iniparser_getstring(ini, entry, NULL, INI_INVALID_KEY)!=INI_INVALID_KEY) {
found = 1 ;
}
return found ;
/**
@brief Set an entry in a dictionary.
@param ini Dictionary to modify.
- @param entry Entry to modify (entry name)
+ @param section Entry to modify (entry section)
+ @param key Entry to modify (entry key)
@param val New value to associate to the entry.
@return int 0 if Ok, -1 otherwise.
It is Ok to set val to NULL.
*/
/*--------------------------------------------------------------------------*/
-int iniparser_set(dictionary * ini, char * entry, char * val)
+int atalk_iniparser_set(dictionary * ini, char *section, char * key, char * val)
{
- return dictionary_set(ini, strlwc(entry), val) ;
+ return atalkdict_set(ini, section, key, val) ;
}
/*-------------------------------------------------------------------------*/
/**
@brief Delete an entry in a dictionary
@param ini Dictionary to modify
- @param entry Entry to delete (entry name)
+ @param section Entry to delete (entry section)
+ @param key Entry to delete (entry key)
@return void
If the given entry can be found, it is deleted from the dictionary.
*/
/*--------------------------------------------------------------------------*/
-void iniparser_unset(dictionary * ini, char * entry)
+void atalk_iniparser_unset(dictionary * ini, char *section, char * key)
{
- dictionary_unset(ini, strlwc(entry));
+ atalkdict_unset(ini, section, key);
}
/*-------------------------------------------------------------------------*/
/**
- @brief Load a single line from an INI file
+ @brief Load a single line from an INI file
@param input_line Input line, may be concatenated multi-line input
@param section Output space to store section
@param key Output space to store key
@return line_status value
*/
/*--------------------------------------------------------------------------*/
-static line_status iniparser_line(
+static line_status atalk_iniparser_line(
char * input_line,
char * section,
char * key,
char * value)
-{
+{
line_status sta ;
char line[ASCIILINESZ+1];
int len ;
sta = LINE_EMPTY ;
} else if (line[0]=='#' || line[0]==';') {
/* Comment line */
- sta = LINE_COMMENT ;
+ sta = LINE_COMMENT ;
} else if (line[0]=='[' && line[len-1]==']') {
/* Section name */
sscanf(line, "[%[^]]", section);
strcpy(section, strstrip(section));
- strcpy(section, strlwc(section));
+ strcpy(section, section);
sta = LINE_SECTION ;
- } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
- || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2
+ } else if (sscanf (line, "%[^=] = '%[^\']'", key, value) == 2
|| sscanf (line, "%[^=] = %[^;#]", key, value) == 2) {
/* Usual key=value, with or without comments */
strcpy(key, strstrip(key));
- strcpy(key, strlwc(key));
+ strcpy(key, key);
strcpy(value, strstrip(value));
/*
* sscanf cannot handle '' or "" as empty values
* key=#
*/
strcpy(key, strstrip(key));
- strcpy(key, strlwc(key));
+ strcpy(key, key);
value[0]=0 ;
sta = LINE_VALUE ;
} else {
should not be accessed directly, but through accessor functions
instead.
- The returned dictionary must be freed using iniparser_freedict().
+ The returned dictionary must be freed using atalk_iniparser_freedict().
*/
/*--------------------------------------------------------------------------*/
-dictionary * iniparser_load(char * ininame)
+dictionary * atalk_iniparser_load(const char * ininame)
{
- FILE * in ;
+ FILE *in, *include = NULL, *inifile;
char line [ASCIILINESZ+1] ;
char section [ASCIILINESZ+1] ;
char key [ASCIILINESZ+1] ;
- char tmp [ASCIILINESZ+1] ;
char val [ASCIILINESZ+1] ;
int last=0 ;
dictionary * dict ;
- if ((in=fopen(ininame, "r"))==NULL) {
- fprintf(stderr, "iniparser: cannot open %s\n", ininame);
+ if ((inifile=fopen(ininame, "r"))==NULL) {
+ LOG(log_error, logtype_default, "iniparser: cannot open \"%s\"", ininame);
return NULL ;
}
- dict = dictionary_new(0) ;
+ dict = atalkdict_new(0) ;
if (!dict) {
- fclose(in);
+ fclose(inifile);
return NULL ;
}
memset(val, 0, ASCIILINESZ);
last=0 ;
- while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
+ in = inifile;
+ while (1) {
+ if (fgets(line+last, ASCIILINESZ-last, in) == NULL) {
+ if (include) {
+ fclose(include);
+ include = NULL;
+ in = inifile;
+ continue;
+ }
+ break;
+ }
lineno++ ;
len = (int)strlen(line)-1;
if (len==0)
continue;
- /* Safety check against buffer overflows */
- if (line[len]!='\n') {
- fprintf(stderr,
- "iniparser: input line too long in %s (%d)\n",
- ininame,
- lineno);
- dictionary_del(dict);
- fclose(in);
- return NULL ;
- }
/* Get rid of \n and spaces at end of line */
while ((len>=0) &&
((line[len]=='\n') || (isspace(line[len])))) {
} else {
last=0 ;
}
- switch (iniparser_line(line, section, key, val)) {
- case LINE_EMPTY:
- case LINE_COMMENT:
+ switch (atalk_iniparser_line(line, section, key, val)) {
+ case LINE_EMPTY:
+ case LINE_COMMENT:
break ;
-
- case LINE_SECTION:
- errs = dictionary_set(dict, section, NULL);
+ case LINE_SECTION:
+ if (strchr(section, ':') != NULL)
+ LOG(log_error, logtype_default, "iniparser: syntax error \"%s\" section name must not contain \":\".", section);
+ errs = atalkdict_set(dict, section, NULL, NULL);
break ;
-
- case LINE_VALUE:
- sprintf(tmp, "%s:%s", section, key);
- errs = dictionary_set(dict, tmp, val) ;
+ case LINE_VALUE:
+ if (strcmp(key, "include") == 0) {
+ errs = atalkdict_set(dict, section, key, val);
+ if (errs < 0) {
+ LOG(log_error, logtype_default, "iniparser: memory allocation failure");
+ }
+ if ((include = fopen(val, "r")) == NULL) {
+ LOG(log_error, logtype_default, "iniparser: cannot open \"%s\"", val);
+ continue;
+ }
+ in = include;
+ continue;
+ }
+ errs = atalkdict_set(dict, section, key, val) ;
break ;
-
- case LINE_ERROR:
- fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
- ininame,
- lineno);
- fprintf(stderr, "-> %s\n", line);
+ case LINE_ERROR:
+ LOG(log_error, logtype_default, "iniparser: syntax error in %s (lineno: %d): %s",
+ ininame, lineno, line);
errs++ ;
break;
-
- default:
+ default:
break ;
}
memset(line, 0, ASCIILINESZ);
last=0;
if (errs<0) {
- fprintf(stderr, "iniparser: memory allocation failure\n");
+ LOG(log_error, logtype_default, "iniparser: memory allocation failure");
break ;
}
}
if (errs) {
- dictionary_del(dict);
+ atalkdict_del(dict);
dict = NULL ;
}
fclose(in);
gets out of the current context.
*/
/*--------------------------------------------------------------------------*/
-void iniparser_freedict(dictionary * d)
+void atalk_iniparser_freedict(dictionary * d)
{
- dictionary_del(d);
+ atalkdict_del(d);
}
-/* vim: set ts=4 et sw=4 tw=75 */