⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcfg_static.c

📁 The configuration file reading samples for ARM project development. Including the sample .conf files
💻 C
📖 第 1 页 / 共 2 页
字号:
				{					state = multiline_end;				}				break;			case multiline_end:				if( c == '/' )				{					state = start;				}				else if( c != '*' )				{					state = in_multiline;				}				break;			case in_identifier:				if( isalnum(c) || c == '-' || c == '_' )				{					lcfg_string_cat_char(s->prepared_token.string, c);				}				else				{					s->prepared_token.type = lcfg_identifier;					consume = 0;					state = start;				}				break;			case in_str:				if( c == '"' )				{					s->prepared_token.type = lcfg_string;					state = start;				}				else if( c == '\\' )				{					state = in_esc;				}				else				{					lcfg_string_cat_char(s->prepared_token.string, c);				}				break;			case in_esc:				state = in_str;				switch( c )				{					case '"':						lcfg_string_cat_char(s->prepared_token.string, '"');						break;					case 'n':						lcfg_string_cat_char(s->prepared_token.string, '\n');						break;					case 't':						lcfg_string_cat_char(s->prepared_token.string, '\t');						break;					case 'r':						lcfg_string_cat_char(s->prepared_token.string, '\r');						break;					case '0':						lcfg_string_cat_char(s->prepared_token.string, '\0');						break;					case 'x':						state = esc_hex_exp_first;						break;					default:						lcfg_error_set(s->lcfg, "invalid string escape sequence `%c' near line %d, col %d", c, s->line, s->col);						state = invalid;				}				break;			case esc_hex_exp_first:				if( !isxdigit(c) )				{					lcfg_error_set(s->lcfg, "invalid hex escape sequence `%c' on line %d column %d", c, s->line, s->col);					state = invalid;				}				hex[0] = c;				state = esc_hex_exp_second;				break;			case esc_hex_exp_second:				if( !isxdigit(c) )				{					lcfg_error_set(s->lcfg, "invalid hex escape sequence `%c' on line %d column %d", c, s->line, s->col);					state = invalid;				}				hex[1] = c;				hex[2] = '\0';				lcfg_string_cat_char(s->prepared_token.string, strtoul(hex, NULL, 16));				state = in_str;				break;			case invalid:				break;		}		/*#include <stdio.h>		printf("read %c at line %d column %d, new state is %d\n", isprint(c) ? c : '.', s->line, s->col, state);*/				/* this is technically not optimal (token position identified by last char), but it will suffice for now */		s->prepared_token.line = s->line;		s->prepared_token.col = s->col;			if( consume )		{			lcfg_scanner_char_read(s, &c);			if( c == '\n' )			{				s->line++;				s->col = 1;			}			else			{				s->col++;			}		}				if( s->prepared_token.type != lcfg_null_token || state == invalid )		{			break;		}	}		if( state != start )	{		if( state != invalid )		{			lcfg_error_set(s->lcfg, "parse error: premature end of file near line %d, col %d", s->line, s->col);		}				return lcfg_status_error;	}		return lcfg_status_ok;}enum lcfg_status lcfg_scanner_init(struct lcfg_scanner *s){	/* prepare the first token */	return lcfg_scanner_token_read(s); }int lcfg_scanner_has_next(struct lcfg_scanner *s){	return s->prepared_token.type != lcfg_null_token;}enum lcfg_status lcfg_scanner_next_token(struct lcfg_scanner *s, struct lcfg_token *t){	if( !lcfg_scanner_has_next(s) )	{		lcfg_error_set(s->lcfg, "%s", "cannot access tokenstream beyond eof");		return lcfg_status_error;	}		memcpy(t, &s->prepared_token, sizeof(struct lcfg_token));	t->string = lcfg_string_new_copy(s->prepared_token.string);		/* prepare the next token */	return lcfg_scanner_token_read(s); }struct lcfg_scanner *lcfg_scanner_new(struct lcfg *c, int fd){	struct lcfg_scanner *s = malloc(sizeof(struct lcfg_scanner));	assert(s);		memset(s, 0, sizeof(struct lcfg_scanner));		s->lcfg = c;	s->fd = fd;		s->line = s->col = 1;		s->prepared_token.string = lcfg_string_new();		return s;}void lcfg_scanner_delete(struct lcfg_scanner *s){	lcfg_string_delete(s->prepared_token.string);	free(s);}/*** end file src/lcfg_scanner.c ***//*** begin file src/lcfg_parser.c ***//* * liblcfg - lightweight configuration file library * Copyright (C) 2007  Paul Baecher *  *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License along *  with this program; if not, write to the Free Software Foundation, Inc., *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *    $Id: lcfg_parser.c 995 2007-05-07 01:49:42Z dp $ *  */#ifndef strdupchar *strdup(const char *s){	char *sdup;		size_t len = strlen(s) + 1;	sdup = malloc(len);	if( sdup != NULL )	{		memcpy(sdup, s, len);	}		return sdup;}#endifstruct lcfg_parser_value_pair{	char *key;	struct lcfg_string *value;};struct lcfg_parser{	struct lcfg *lcfg;	char *filename;	struct lcfg_scanner *scanner;		struct lcfg_parser_value_pair *values;	unsigned int value_length;	unsigned int value_capacity;};static int lcfg_parser_add_value(struct lcfg_parser *p, const char *key, struct lcfg_string *value){	if( p->value_length == p->value_capacity )	{		p->value_capacity *= 2;		p->values = realloc(p->values, sizeof(struct lcfg_parser_value_pair) * p->value_capacity);		assert(p->values);	}		p->values[p->value_length].key = strdup(key);	p->values[p->value_length].value = lcfg_string_new_copy(value);		return ++p->value_length;}struct lcfg_parser *lcfg_parser_new(struct lcfg *c, const char *filename){	struct lcfg_parser *p = malloc(sizeof(struct lcfg_parser));	assert(p);		memset(p, 0, sizeof(struct lcfg_parser));		p->filename = strdup(filename);	p->lcfg = c;		p->value_length = 0;	p->value_capacity = 8;	p->values = malloc(sizeof(struct lcfg_parser_value_pair) * p->value_capacity);	assert(p->values);		return p;}/* this is a basic push down automata */static enum lcfg_status lcfg_parser_parse(struct lcfg_parser *p){	enum state { top_level = 0, exp_equals, exp_value, in_list, in_map, invalid };	/*const char *state_map[] = { "top_level", "exp_equals", "exp_value", "in_list", "in_map", "invalid" };*/	struct state_element	{		enum state s;		int list_counter;	};	/* start of ugly preproc stuff */	#define STATE_STACK_PUSH(t) \	if( ssi + 1 == state_stack_size ) \	{ \		state_stack_size *= 2; \		state_stack = realloc(state_stack, state_stack_size * sizeof(struct state_element)); \	} \	state_stack[++ssi].s = t; \	state_stack[ssi].list_counter = 0	#define STATE_STACK_POP() ssi--	#define PATH_PUSH_STR(s) \	if( lcfg_string_len(current_path) != 0 ) \	{ \		lcfg_string_cat_char(current_path, '.'); \	} \	lcfg_string_cat_cstr(current_path, s);	#define PATH_PUSH_INT(i) \	if( lcfg_string_len(current_path) != 0 ) \	{ \		lcfg_string_cat_char(current_path, '.'); \	} \	lcfg_string_cat_uint(current_path, i);	#define PATH_POP() \	if( lcfg_string_rfind(current_path, '.') != -1 ) \	{ \		lcfg_string_trunc(current_path, lcfg_string_rfind(current_path, '.')); \	} \	else \	{ \		lcfg_string_trunc(current_path, 0); \	}	/* end of ugly preproc stuff */	if( lcfg_scanner_init(p->scanner) != lcfg_status_ok )	{		return lcfg_status_error;	}		int state_stack_size = 8;	int ssi = 0; /* ssi = state stack index */	struct state_element *state_stack = malloc(sizeof(struct state_element) * state_stack_size);		state_stack[ssi].s = top_level;	state_stack[ssi].list_counter = 0;		struct lcfg_token t;	struct lcfg_string *current_path = lcfg_string_new();		while( lcfg_scanner_has_next(p->scanner) && state_stack[ssi].s != invalid )	{		if( lcfg_scanner_next_token(p->scanner, &t) != lcfg_status_ok )		{			free(state_stack);			lcfg_string_delete(t.string);			lcfg_string_delete(current_path);			return lcfg_status_error;		}				switch( state_stack[ssi].s )		{			case top_level:			case in_map:				if( t.type == lcfg_identifier )				{					PATH_PUSH_STR(lcfg_string_cstr(t.string));					STATE_STACK_PUSH(exp_equals);				}				else if( state_stack[ssi].s == in_map && t.type == lcfg_brace_close )				{					STATE_STACK_POP();					PATH_POP();				}				else				{					lcfg_error_set(p->lcfg, "invalid token (%s) near line %d column %d: expected identifier%s", lcfg_token_map[t.type], t.line, t.col, state_stack[ssi].s == in_map ? " or `}'" : ""); 					state_stack[ssi].s = invalid;				}				break;			case exp_equals:				if( t.type == lcfg_equals )					state_stack[ssi].s = exp_value;				else				{					lcfg_error_set(p->lcfg, "invalid token (%s) near line %d column %d: expected `='", lcfg_token_map[t.type], t.line, t.col); 					state_stack[ssi].s = invalid;				}				break;			case exp_value:				if( t.type == lcfg_string )				{					lcfg_parser_add_value(p, lcfg_string_cstr(current_path), t.string);					/*printf("adding string value for single statement\n");*/					STATE_STACK_POP();					PATH_POP();				}				else if( t.type == lcfg_sbracket_open )				{					state_stack[ssi].s = in_list;				}				else if( t.type == lcfg_brace_open )				{					state_stack[ssi].s = in_map;				}				else				{					lcfg_error_set(p->lcfg, "invalid token (%s) near line %d column %d: expected string, `[' or `{'", lcfg_token_map[t.type], t.line, t.col); 					state_stack[ssi].s = invalid;				}				break;			case in_list:				if( t.type == lcfg_comma ); /* ignore comma */				else if( t.type == lcfg_string )				{					PATH_PUSH_INT(state_stack[ssi].list_counter);					lcfg_parser_add_value(p, lcfg_string_cstr(current_path), t.string);					PATH_POP();					/*printf("adding string to list pos %d\n", state_stack[ssi].list_counter);*/					state_stack[ssi].list_counter++;				}				else if( t.type == lcfg_sbracket_open )				{					PATH_PUSH_INT(state_stack[ssi].list_counter);					/*printf("adding list to list pos %d\n", state_stack[ssi].list_counter);*/					state_stack[ssi].list_counter++;					STATE_STACK_PUSH(in_list);				}				else if( t.type == lcfg_brace_open )				{					PATH_PUSH_INT(state_stack[ssi].list_counter);					/*printf("adding map to list pos %d\n", state_stack[ssi].list_counter);*/					state_stack[ssi].list_counter++;					STATE_STACK_PUSH(in_map);				}				else if( t.type == lcfg_sbracket_close )				{					PATH_POP();					STATE_STACK_POP();				}				else				{					lcfg_error_set(p->lcfg, "invalid token (%s) near line %d column %d: expected string, `[', `{', `,' or `]'", lcfg_token_map[t.type], t.line, t.col); 					state_stack[ssi].s = invalid;				}				break;			case invalid: /* unreachable */				assert(0);				break;		}				lcfg_string_delete(t.string);				/*printf(" *** pda: read %s, state is now %s\n", lcfg_token_map[t.type], state_map[state_stack[ssi].s]);*/	}	lcfg_string_delete(current_path);			if( state_stack[ssi].s == top_level && ssi == 0 )	{		free(state_stack);		return lcfg_status_ok;	}	else	{		free(state_stack);		return lcfg_status_error;	}}enum lcfg_status lcfg_parser_run(struct lcfg_parser *p){		int fd = open(p->filename, 0);	enum lcfg_status status;		if( fd < 0 )	{		lcfg_error_set(p->lcfg, "open(): %s", strerror(errno));		return lcfg_status_error;	}		p->scanner = lcfg_scanner_new(p->lcfg, fd);		status = lcfg_parser_parse(p);			close(fd);		return status;}enum lcfg_status lcfg_parser_accept(struct lcfg_parser *p, lcfg_visitor_function fn, void *user_data){	int i;		for( i = 0; i < p->value_length; i++ )	{		if( fn(p->values[i].key, (void *)lcfg_string_cstr(p->values[i].value), lcfg_string_len(p->values[i].value), user_data) != lcfg_status_ok )		{			lcfg_error_set(p->lcfg, "%s", "configuration value traversal aborted upon user request");			return lcfg_status_error;		}	}		return lcfg_status_ok;}enum lcfg_status lcfg_parser_get(struct lcfg_parser *p, const char *key, void **data, size_t *len){	int i;	for( i = 0; i < p->value_length; i++ )	{		if( !strcmp(p->values[i].key, key) )		{			*data = (void *)lcfg_string_cstr(p->values[i].value);			*len = lcfg_string_len(p->values[i].value);			return lcfg_status_ok;		}	}		return lcfg_status_error;}void lcfg_parser_delete(struct lcfg_parser *p){	if( p->scanner != NULL )	{		lcfg_scanner_delete(p->scanner);	}		int i;		for( i = 0; i < p->value_length; i++ )	{		free(p->values[i].key);		lcfg_string_delete(p->values[i].value);	}	free(p->values);	free(p->filename);	free(p);}/*** end file src/lcfg_parser.c ***//*** begin file src/lcfg.c ***//* * liblcfg - lightweight configuration file library * Copyright (C) 2007  Paul Baecher *  *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. *   *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License along *  with this program; if not, write to the Free Software Foundation, Inc., *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *    $Id: lcfg.c 995 2007-05-07 01:49:42Z dp $ *  */struct lcfg{	char error[0xff];	struct lcfg_parser *parser;};struct lcfg *lcfg_new(const char *filename){	struct lcfg *c = malloc(sizeof(struct lcfg));	assert(c);	memset(c, 0, sizeof(struct lcfg));		c->parser = lcfg_parser_new(c, filename);	assert(c->parser);		return c;}void lcfg_delete(struct lcfg *c){	lcfg_parser_delete(c->parser);	free(c);}const char *lcfg_error_get(struct lcfg *c){	return c->error;}enum lcfg_status lcfg_parse(struct lcfg *c){	return lcfg_parser_run(c->parser);}enum lcfg_status lcfg_accept(struct lcfg *c, lcfg_visitor_function fn, void *user_data){	return lcfg_parser_accept(c->parser, fn, user_data);}enum lcfg_status lcfg_value_get(struct lcfg *c, const char *key, void **data, size_t *len){	return lcfg_parser_get(c->parser, key, data, len);}void lcfg_error_set(struct lcfg *c, const char *fmt, ...){		va_list ap;	va_start(ap, fmt);	vsnprintf(c->error, sizeof(c->error), fmt, ap);	va_end(ap);}/*** end file src/lcfg.c ***/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -