On Monday 07 July 2008 22:29:38 Vladimir Dronnikov wrote:
> Sure :)
> But some help is needed. I am trying to convert inotifyd. mdev is
> "saint animal". Natanael mentioned ifup/down. There is crond that uses
> plain config. There gotta be savings en gros if we cope this together.
> 
> --
> Vladimir
> 
> 
> 2008/7/7, Bernhard Fischer <[EMAIL PROTECTED]>:
> > On Mon, Jul 07, 2008 at 12:31:29PM -0700, [EMAIL PROTECTED] wrote:
> >>A helper function for parsing vanilla config files is added.
> >>I see mdev, crond and others can use it to uniformly process their configs.
> >
> > It would be better if you would convert a few users to this new
> > parse_config() and show the size-savings. The more you save, the more we
> > all will like it :)
> >
> > Please don't forget to check that you don't accidentally introduce bugs
> > in the course.
> >
> > cheers,
> >

Hi,
just for fun I've done my own version of parse_config(),
it returns a linked list of all the options found.
The list is then evaluated and freed by the caller.
At the moment there is just an indipendent executable
to compile in test.c and a config file i used for testing.
Usage is: ./test PATH_TO_CONFIG_FILE
and all the options should be printed to the screen:

 ./test config.cfg
option=1
option=2
option=corner-case1
option=corner-case3
option=corner-case2
option=after_new_lines
option 3
option 3        3       3       3
option abracadabra
option=multiline-option

Just my 0,2 cents....in the hope it could be somehow useful.... :-)

Ciao,
Tito

/* Lines starting with "#" are ignored. Note that end-of-line
*  comments are supported.
*  Blank lines are ignored. 
*  Lines may be indented freely.
*  A "\" character at the very end of the line indicates the next line
*  should be treated as a continuation of the current one.
*/

llist_t *parse_config(const char *filename)
{
        char *line;
        char *next_line;
        char *p;
        char *t;
        llist_t *option_list = NULL;
        FILE *file = fopen(filename, "r");
        
        if (file) {
                while ((line = xmalloc_fgetline(file))) {
                        while ((p = last_char_is(line, '\\'))){
                                        /* Multi-line object */
                                        *p = '\0'; /* Remove '\' */
                                        next_line = xmalloc_fgetline(file);
                                        line = xasprintf("%s%s", line, 
(next_line) ? next_line : "");
                                        free(next_line);
                        }
                        p = skip_whitespace(line); /* Remove leading whitespace 
*/
                        if (*p && *p != '#') { /* Not a comment or indented 
comment */
                                if ((t = strchr(p, '#'))) /* End of line 
comment - cut it */
                                        *t = '\0';
                                /* What remains is an option so add it to the 
linked list */
                                llist_add_to_end(&option_list, xstrdup(p));
                                continue;
                        } /* else empty line */
                        free(line);
                } /*EOF */      
                fclose(file);
        }  /* else cannot read  - return NULL */
        return option_list;
}

# comment
        #indented comment
#multiline-\
comment
option=1
option=2#end of line comment
\
option=corner-case1
  \
option=corner-case3
 \
option=corner-case2




option=after_new_lines
option 3
option 3        3       3       3
                                                                
option abracadabra
option=multiline-\
option
\
#define _GNU_SOURCE
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
/* Try to pull in PATH_MAX */
#include <limits.h>
#include <sys/param.h>

typedef struct llist_t {
	char *data;
	struct llist_t *link;
} llist_t;


char* last_char_is(const char *s, int c)
{
	if (s && *s) {
		size_t sz = strlen(s) - 1;
		s += sz;
		//printf("last_char_is: %s\n", s);
		if ((unsigned char)*s == c)
			return (char*)s;
	}
	return NULL;
}


char* skip_whitespace(const char *s)
{
	/* NB: isspace('\0') returns 0 */
	while (isspace(*s)) ++s;

	return (char *) s;
}

void* xrealloc(void *ptr, size_t size)
{
	ptr = realloc(ptr, size);
	if (ptr == NULL && size != 0)
		exit(1);
	return ptr;
}

char* bb_get_chunk_from_file(FILE *file, int *end)
{
	int ch;
	int idx = 0;
	char *linebuf = NULL;
	int linebufsz = 0;

	while ((ch = getc(file)) != EOF) {
		/* grow the line buffer as necessary */
		if (idx >= linebufsz) {
			linebufsz += 80;
			linebuf = xrealloc(linebuf, linebufsz);
		}
		linebuf[idx++] = (char) ch;
		if (!ch || (end && ch == '\n'))
			break;
	}
	if (end)
		*end = idx;
	if (linebuf) {
		// huh, does fgets discard prior data on error like this?
		// I don't think so....
		//if (ferror(file)) {
		//	free(linebuf);
		//	return NULL;
		//}
		linebuf = xrealloc(linebuf, idx + 1);
		linebuf[idx] = '\0';
	}
	return linebuf;
}

/* Get line.  Remove trailing \n */
char* xmalloc_fgetline(FILE *file)
{
	int i;
	char *c = bb_get_chunk_from_file(file, &i);

	if (i && c[--i] == '\n')
		c[i] = '\0';

	return c;
}

void* xmalloc(size_t size)
{
	void *ptr = malloc(size);
	if (ptr == NULL && size != 0)
		exit(1);
	return ptr;
}


char* xasprintf(const char *format, ...)
{
	va_list p;
	int r;
	char *string_ptr;

	// GNU extension
	va_start(p, format);
	r = vasprintf(&string_ptr, format, p);
	va_end(p);

	if (r < 0)
		exit(1);
	return string_ptr;
}

/* Add data to the end of the linked list.  */
void llist_add_to_end(llist_t **list_head, void *data)
{
	llist_t *new_item = xmalloc(sizeof(llist_t));

	new_item->data = data;
	new_item->link = NULL;

	if (!*list_head)
		*list_head = new_item;
	else {
		llist_t *tail = *list_head;

		while (tail->link)
			tail = tail->link;
		tail->link = new_item;
	}
}

/* Remove first element from the list and return it */
void* llist_pop(llist_t **head)
{
	void *data, *next;

	if (!*head)
		return NULL;

	data = (*head)->data;
	next = (*head)->link;
	free(*head);
	*head = next;

	return data;
}

char* xstrdup(const char *s)
{
	char *t;

	if (s == NULL)
		return NULL;

	t = strdup(s);

	if (t == NULL)
		exit(1);

	return t;
}

/* Copyright (C) 2008 by Tito Ragusa <[EMAIL PROTECTED]>
*  Lines starting with "#" are ignored. Note that end-of-line
*  comments are supported.
*  Blank lines are ignored. 
*  Lines may be indented freely.
*  A "\" character at the very end of the line indicates the next line
*  should be treated as a continuation of the current one.
*/

llist_t *parse_config(const char *filename)
{
	char *line;
	char *next_line;
	char *p;
	char *t;
	llist_t *option_list = NULL;
	FILE *file = fopen(filename, "r");
	
	if (file) {
		while ((line = xmalloc_fgetline(file))) {
			while ((p = last_char_is(line, '\\'))){
					/* Multi-line object */
					*p = '\0'; /* Remove '\' */
					next_line = xmalloc_fgetline(file);
					line = xasprintf("%s%s", line, (next_line) ? next_line : "");
					free(next_line);
			}
			p = skip_whitespace(line); /* Remove leading whitespace */
			if (*p && *p != '#') { /* Not a comment or indented comment */
				if ((t = strchr(p, '#'))) /* End of line comment - cut it */
					*t = '\0';
				/* What remains is an option so add it to the linked list */
				llist_add_to_end(&option_list, xstrdup(p));
				continue;
			} /* else empty line */
			free(line);
		} /*EOF */	
		fclose(file);
	}  /* else cannot read  - return NULL */
	return option_list;
}


int main(int argc, char **argv)
{
	llist_t *config_options = NULL;
	void *data;

	if (argv[1])
		config_options = parse_config(argv[1]);

	if (config_options) {
		while ((data = llist_pop(&config_options))) {
			puts(data);
			free(data);
		}
		free(config_options);
	}
	return 0;
}
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to