Reading Configuration File using C (not C++)

A configuration file consists of sections and entries. Each section is defined inside a "[]", and each entry is delimited by an "=" sign. The value of each entry can be either string or an integer, double, alphanumerical or just an empty string.  Comments start with "#" sign.

The following is a sample of the config file:
## This is a sample config file
[Section 1]
Entry1=123456
Entry2=THIS IS A TEST # This is entry 2

[Section 2]
Entry1=rev 0 # This is entry 1
Entry2=TM 2001-12-44 23:20 Ttl 5

Questions:
1. Are there any libraries available that implement the processing of a config file such as the above, preferably licensed by some open source like LGPL, Apache or BSD.? If yes, what is it or where I can find it?

2. If this is to be a custom implementation, how to develop this is C (and not C++) where the config file is parsed, entries are stored in some structure, then the values are assigned to variables or defaule values.
TexanLonghornAsked:
Who is Participating?
 
Infinity08Connect With a Mentor Commented:
Here's a nice library :

        http://ndevilla.free.fr/iniparser/
0
 
evilrixSenior Software Engineer (Avast)Commented:
This looks the same as a INI file. If this is a Window development maybe you could use GetPrivateProfileString() and related functions?

http://msdn2.microsoft.com/en-us/library/ms724353(VS.85).aspx
0
 
evilrixSenior Software Engineer (Avast)Commented:
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
evilrixSenior Software Engineer (Avast)Commented:
This appears to be an open source library capable of reading INI files.
http://sourceforge.net/projects/libini

INI Parser Library: An INI file parser that can read, edit and create large INI files. Usable under Microsoft Windows, DOS, Linux, etc
0
 
Infinity08Commented:
Or this one :

        http://sourceforge.net/projects/libini/
0
 
evilrixConnect With a Mentor Senior Software Engineer (Avast)Commented:
>> Or this one
*cough* #20790602 :)
0
 
Infinity08Commented:
;) I posted both in rapid succession :)
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> I posted both in rapid successio
I know, I'm only kidding :)
So bored -- no Q's tonight!
0
 
Infinity08Commented:
I was planning to put them in the same post, but clicked submit too early lol.

I'm not bored ... I'm chasing mice (heard that there are mice in the building) lol
0
 
evilrixSenior Software Engineer (Avast)Commented:
Mice? Wow. I'm trying to find a cheap holiday and maybe a new job. No mice though, except the one on my desk.
0
 
evilrixSenior Software Engineer (Avast)Commented:
Hi TexanLonghorn. Did these suggestions help you out in anyway or do you need more assistance?

-Rx
0
 
TexanLonghornAuthor Commented:
Appologies for the late responce. But I haven't had the chance to look into this yet. I can tell that the iniParser seem to be more compatible with my source code. I will download the stand-alone Parser library today and keep you posted on my progress.

Thanks for checking Rx.
0
 
TexanLonghornAuthor Commented:
I have downloaded and used the iniParser API with source code. However, I noticed couple of issues with the configuration file processing:

1. There is a memory problem with the code. The iniparser_getstring() function does not allocate memory from the string; so after iniparser_freedict() is called, the memory for all of those strings has been freed. A strdup will need to be done on the string to allocate memory for the data structure I am using to store the values, which my program will be reading from the config file.

2. My software is designed to use the same config file for multiple applications (or stubs). Each application has its own section, i.e. [App1], in the config file, and for simplicity purposes I would not like to use different files for different applications. I need to find the exact name of the running application before I use iniParser to locate its config values. Keeping in mind that the application could be running on Linux or Windows O/S. In which case I will need to have another routine to strip the pathname (e.g. c:\dir\app1 or ~/bin/app1) from the application name (e.g. app1) before using iniparser_getsecname() function to locate the desinated section (e.g. [app1]).
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> I will need to have another routine to strip the pathname
Q&D function below.

After: sPath == "app1 "
#include <string>
 
#ifdef _WIN32
#define PATH_DELIM '\\'
#else
#define PATH_DELIM '/'
#endif
 
int main()
{
	std::string sPath = "c:\\dir\\app1 ";
	std::string::size_type pos = sPath.rfind(PATH_DELIM);
	if(sPath.size() > 1 && pos != std::string::npos) { sPath = sPath.substr(pos + 1); }
 
	return 0;
}

Open in new window

0
 
TexanLonghornAuthor Commented:
evilrix, please let me know if it's possible to get the same source code for the pathname stripper in C, instead of C++. If so can you provide it?
0
 
evilrixConnect With a Mentor Senior Software Engineer (Avast)Commented:
Try this.
#include <string.h>
#include <stdio.h>
 
#ifdef _WIN32
#define PATH_DELIM "\\"
#else
#define PATH_DELIM "/"
#endif
 
void strip_path(char * szPath)
{
	char const * curpos = strtok(szPath, PATH_DELIM);
	char const * pos = NULL;
	while(curpos = strtok(NULL, PATH_DELIM)) { pos = curpos; }
	if(pos) { strcpy(szPath, pos); }
}
 
int main()
{
	char szPath1[] = "c:\\dir\\app1 ";
	char szPath2[] = "app1 ";
 
	strip_path(szPath1);
	printf("Path1: %s\n", szPath1);
 
	strip_path(szPath2);
	printf("Path2: %s\n", szPath2);
 
	return 0;
}

Open in new window

0
 
TexanLonghornAuthor Commented:
Do you believe the following standard function would do the same work as your strip_path() and would work on Windows (_WIN32) and other Unix/Linux like operating systems?
#include <unistd.h>
char * basename (const char *name);
0
 
evilrixSenior Software Engineer (Avast)Commented:
The unistd.h header is a Unix only header so no, I don't think it will be x-platform. I cannot find any reference to this function on the MSDN.

http://opengroup.org/onlinepubs/007908799/xsh/unistd.h.html
http://en.wikipedia.org/wiki/Basename

-Rx.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> I cannot find any reference to this function on the MSDN.
Actually, it's a Unix OS program and not a function, right?
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Actually, it's a Unix OS program and not a function, right?
Maybe it's both -- Posix does have a habit of naming functions the same as programs that offer Shell support via that function :) Anyway, no I don't think it'll be x-platform.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Maybe it's both
I couldn't initially find it as a function on my Linux box but I think I may have mis-typed it, oops! Anyway, found it now :)

Here is the online doc for the function itself.
http://www.opengroup.org/onlinepubs/000095399/functions/basename.html

The header it uses is libgen.h.
http://www.opengroup.org/onlinepubs/007908775/xsh/libgen.h.html

If you are only targetting Unix then this may be a good way to do this, if you are looking to be x-platform you may find split_path() a better choice.

NB. split_path() is not production quality code, I just knocked it up quick so you should test it throughly.

-Rx.
0
 
TexanLonghornAuthor Commented:
I guess what confused me is the #ifndef declarations at the beginning of the basename() source code. see the following:
/* Return the basename of a pathname.
   This file is in the public domain. */
 
/*
NAME
	basename -- return pointer to last component of a pathname
 
SYNOPSIS
	char *basename (const char *name)
 
DESCRIPTION
	Given a pointer to a string containing a typical pathname
	(/usr/src/cmd/ls/ls.c for example), returns a pointer to the
	last component of the pathname ("ls.c" in this case).
 
BUGS
	Presumes a UNIX or DOS/Windows style path with UNIX or DOS/Windows 
	style separators.
*/
 
#include "ansidecl.h"
#include "libiberty.h"
#include "safe-ctype.h"
 
#ifndef DIR_SEPARATOR
#define DIR_SEPARATOR '/'
#endif
 
#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
  defined (__OS2__)
#define HAVE_DOS_BASED_FILE_SYSTEM
#ifndef DIR_SEPARATOR_2 
#define DIR_SEPARATOR_2 '\\'
#endif
#endif
 
/* Define IS_DIR_SEPARATOR.  */
#ifndef DIR_SEPARATOR_2
# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
#else /* DIR_SEPARATOR_2 */
# define IS_DIR_SEPARATOR(ch) \
	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
#endif /* DIR_SEPARATOR_2 */
 
char *
basename (name)
     const char *name;
{
  const char *base;
 
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
  /* Skip over the disk name in MSDOS pathnames. */
  if (ISALPHA (name[0]) && name[1] == ':') 
    name += 2;
#endif
 
  for (base = name; *name; name++)
    {
      if (IS_DIR_SEPARATOR (*name))
	{
	  base = name + 1;
	}
    }
  return (char *) base;
}

Open in new window

0
 
evilrixConnect With a Mentor Senior Software Engineer (Avast)Commented:
>> I guess what confused me is the #ifndef declarations at the beginning of the basename() source code.
Well, it's possible this code can be built to run on a Windows platform and if you're happy to build it as part of your project then that would probably work; however,

(a) as far as I can tell this is not a standard fucntion offered in Windows (I couldn't find anything on the MSDN -- although it's not the easiest thing to search)

(b) since it offers many other functions beyond basename() I suspect distributing it might be over-kill.

(c) You also have to check the licencing for it, if it's (for example) GPL you'd have to make your code also GPL (as far as I understand the GPL licence).

-Rx.
0
 
TexanLonghornAuthor Commented:
Please let me know if you can assist in getting rid of the following warning messages generated during compilation as a result of simple assignments such as

char * s = iniparser_getstring(ini, "[section1]:[entery1]", NULL);

when using the iniParser library:

configuration.c: In function `load_config_lib':
configuration.c:339: warning: passing arg 3 of `iniparser_getint' makes integer from pointer without a cast
configuration.c:340: warning: passing arg 3 of `iniparser_getint' makes integer from pointer without a cast
configuration.c:341: warning: passing arg 3 of `iniparser_getint' makes integer from pointer without a cast
configuration.c:342: warning: passing arg 3 of `iniparser_getint' makes integer from pointer without a cast
configuration.c:346: warning: passing arg 3 of `iniparser_getint' makes integer from pointer without a cast
configuration.c:347: warning: passing arg 3 of `iniparser_getint' makes integer from pointer without a cast
configuration.c:348: warning: passing arg 3 of `iniparser_getint' makes integer from pointer without a cast
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Please let me know if you can assist in getting rid of the following warning messages generated during compilation as a result of simple assignments such as
That should really be opened as a new Q TL. I think the original Q has been answered, no?
0
 
TexanLonghornAuthor Commented:
Thanks for all your assitance.
0
All Courses

From novice to tech pro — start learning today.