Design opinions/urls/snippets requested; parsing simplistic config files

J

John Doe

I've been doing some reading/research on parsing simple configuration
files through C, and have heard various opinions on the matter. I'd like
to solicit some opinions and design criteria (as well as "gotchas") for
doing this.

I'm implementing a program that needs to read a standard configuration
file, in key=value pairs for starters (though I'm open to other ideas).
Basically it would be no more than about 20 lines total, one key per line.
Something like the following:

foo = bar
port = /dev/ttyS0
user = John Q. Public
backup = $HOME/backup

I've also seen suggestions about breaking this up into the "Windows'y"
..ini file syntax, so that could be reconstructed to be something like:

[global]
foo = bar

[ports]
port = /dev/ttyS0

[user]
user = John Q. Public

[path]
backup = $HOME/backup

Either method of storage is fine, though it gets a bit harder parsing out
global blocks. The other thing that could get complicated, is the presence
of /etc/foo/foorc and $HOME/.foorc. Which overrides which? What about
merging settings?

I've looked at the following links, but they're all MUCH larger than I
need for this project:

Coman - LGPL - http://www.digitaltunnel.com/~lepware/coman/ChangeLog
GConf - LGPL - http://cvs.gnome.org/lxr/source/gconf/ChangeLog
Conf - GPL - http://www.cs.vu.nl/~bernsti/conf/index.html
dot.conf - GPL - http://www.azzit.de/dotconf/
Keeper - LGPL - http://www.inf.bme.hu/~mszeredi/keeper/
libconf - GPL - http://metalab.unc.edu/pub/Linux/libs/
libproplist - LGPL - http://www.windowmaker.org/src/lPL/ChangeLog
parsecfg - LGPL - http://www.enjoy.ne.jp/~gm/program/parsecfg/

Another option that was thrown my way, was to use lexx/yacc to create the
parser and logic for this. I'm completely unfamiliar with lexx/yacc for
this, so I don't know where to start. An hour of googling didn't produce
much of anything I could use for an jumping point to get me started.

Lastly, the old standby.. XML. In this case, XML would be a good storage
method for my config variables, but my project would then require an
additional dependancy on libxml or expat (which isn't a validating
parser).

Ideas? Code snippets? URLs I can check for insight?

Thanks in advance.
 
B

Bertrand Mollinier Toublet

John said:
I've been doing some reading/research on parsing simple configuration
files through C, and have heard various opinions on the matter. I'd like
to solicit some opinions and design criteria (as well as "gotchas") for
doing this.

I'm implementing a program that needs to read a standard configuration
file, in key=value pairs for starters (though I'm open to other ideas).
Basically it would be no more than about 20 lines total, one key per line.
Something like the following:

foo = bar
port = /dev/ttyS0
user = John Q. Public
backup = $HOME/backup

I've also seen suggestions about breaking this up into the "Windows'y"
..ini file syntax, so that could be reconstructed to be something like:

[global]
foo = bar

[ports]
port = /dev/ttyS0

[user]
user = John Q. Public

[path]
backup = $HOME/backup

Either method of storage is fine, though it gets a bit harder parsing out
global blocks. The other thing that could get complicated, is the presence
of /etc/foo/foorc and $HOME/.foorc. Which overrides which? What about
merging settings?
Looks like your files are small/simple enough that you want to do the
reading/writing module yourself.

As far as merging/overriding, you might want to take a look at Java's
old java.util.Properties, which presents a (IMHO) good concept.

My $0.02...
 
J

John Doe

Looks like your files are small/simple enough that you want to do the
reading/writing module yourself.

This is what I've come up with so far, but I've run into a snag.. it
doesn't like a value with spaces in it, like:

name = John Q. Public

Which only grabs "John" from the RHS. Ideas? Code below:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define CONFIG_FILE ".foorc"

char cfg[PATH_MAX];

int main(void)
{
char buff[256],
key[100],
val[100];

int line,
status = EXIT_FAILURE;

FILE *fp;

sprintf(cfg, "%s/%s", getenv("HOME"), CONFIG_FILE);
if ((fp = fopen(cfg, "r")) == NULL) {
printf("Cannot open file %s\n", CONFIG_FILE);
exit(status);
}

for (line = 1; fgets(buff, sizeof(buff), fp); line++) {
if (sscanf(buff, "%s = %s", &key, &val) != 2) {
printf("Scanf() failure on line %d\n", line);
(void) fclose(fp);
exit(status);
}
printf("Line %d:\t %s = %s\n", line, key, val);
}
if (feof(fp))
status = EXIT_SUCCESS;
else
printf("Error reading file %s, line %d\n", CONFIG_FILE,
line);
(void) fclose(fp);

return status;
}
 
S

Sandeep

For simple cases, using environment variables might be a better solution.
You can just use the standard c function getenv(). This way you
don't have to write any code to parse the configuration parameters.

Sandeep
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top