diff options
Diffstat (limited to 'configfile.c')
| -rw-r--r-- | configfile.c | 87 | 
1 files changed, 87 insertions, 0 deletions
| diff --git a/configfile.c b/configfile.c new file mode 100644 index 0000000..4908058 --- /dev/null +++ b/configfile.c @@ -0,0 +1,87 @@ +/* configfile.c: parsing of config files + * + * Copyright (C) 2008 Lars Hjemli + * + * Licensed under GNU General Public License v2 + *   (see COPYING for full license text) + */ + +#include <ctype.h> +#include <stdio.h> +#include "configfile.h" + +int next_char(FILE *f) +{ +	int c = fgetc(f); +	if (c=='\r') { +		c = fgetc(f); +		if (c!='\n') { +			ungetc(c, f); +			c = '\r'; +		} +	} +	return c; +} + +void skip_line(FILE *f) +{ +	int c; + +	while((c=next_char(f)) && c!='\n' && c!=EOF) +		; +} + +int read_config_line(FILE *f, char *line, const char **value, int bufsize) +{ +	int i = 0, isname = 0; + +	*value = NULL; +	while(i<bufsize-1) { +		int c = next_char(f); +		if (!isname && (c=='#' || c==';')) { +			skip_line(f); +			continue; +		} +		if (!isname && isspace(c)) +			continue; + +		if (c=='=' && !*value) { +			line[i] = 0; +			*value = &line[i+1]; +		} else if (c=='\n' && !isname) { +			i = 0; +			continue; +		} else if (c=='\n' || c==EOF) { +			line[i] = 0; +			break; +		} else { +			line[i]=c; +		} +		isname = 1; +		i++; +	} +	line[i+1] = 0; +	return i; +} + +int parse_configfile(const char *filename, configfile_value_fn fn) +{ +	static int nesting; +	int len; +	char line[256]; +	const char *value; +	FILE *f; + +	/* cancel deeply nested include-commands */ +	if (nesting > 8) +		return -1; +	if (!(f = fopen(filename, "r"))) +		return -1; +	nesting++; +	while((len = read_config_line(f, line, &value, sizeof(line))) > 0) +		fn(line, value); +	nesting--; +	fclose(f); +	return 0; +} + | 
