Update parser
This commit is contained in:
parent
3902489af5
commit
6b75a8cc02
@ -172,17 +172,20 @@ void
|
|||||||
layout_rotate(struct tag *t, bool left)
|
layout_rotate(struct tag *t, bool left)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct geo g;
|
struct geo g, ug = t->screen->ugeo;
|
||||||
|
|
||||||
SLIST_FOREACH(c, &t->clients, tnext)
|
SLIST_FOREACH(c, &t->clients, tnext)
|
||||||
{
|
{
|
||||||
/* g = c->geo;
|
/*
|
||||||
c->geo.x = g.y;
|
g = c->geo;
|
||||||
c->geo.y = g.x;
|
c->geo.x = (g.y * ug.h) / ug.w;
|
||||||
c->geo.w = g.h;
|
c->geo.y = (g.x * ug.w) / ug.h;
|
||||||
c->geo.h = g.w;*/
|
|
||||||
|
c->geo.w = (g.h * ug.w) / ug.h;
|
||||||
|
c->geo.h = (g.w * ug.h) / ug.w;
|
||||||
|
|
||||||
client_moveresize(c, c->geo);
|
client_moveresize(c, c->geo);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
||||||
|
* Copyright (c) 2011 Martin Duquesnoy <xorg62@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -41,10 +42,12 @@ extern char *__progname;
|
|||||||
enum keyword_t { SEC_START, SEC_END, INCLUDE, WORD, EQUAL, LIST_START, LIST_END, NONE };
|
enum keyword_t { SEC_START, SEC_END, INCLUDE, WORD, EQUAL, LIST_START, LIST_END, NONE };
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static struct {
|
static const struct
|
||||||
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
enum keyword_t type;
|
enum keyword_t type;
|
||||||
} kw_t_name[] = {
|
} kw_t_name[] =
|
||||||
|
{
|
||||||
{"SEC_START", SEC_START},
|
{"SEC_START", SEC_START},
|
||||||
{"SEC_END", SEC_END},
|
{"SEC_END", SEC_END},
|
||||||
{"INCLUDE", INCLUDE},
|
{"INCLUDE", INCLUDE},
|
||||||
@ -56,12 +59,14 @@ static struct {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct files {
|
struct files
|
||||||
|
{
|
||||||
char *name;
|
char *name;
|
||||||
struct files *parent;
|
struct files *parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct keyword {
|
struct keyword
|
||||||
|
{
|
||||||
enum keyword_t type;
|
enum keyword_t type;
|
||||||
/* if WORD */
|
/* if WORD */
|
||||||
int line;
|
int line;
|
||||||
@ -70,7 +75,8 @@ struct keyword {
|
|||||||
struct keyword *next;
|
struct keyword *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct state {
|
struct state
|
||||||
|
{
|
||||||
bool quote;
|
bool quote;
|
||||||
bool comment;
|
bool comment;
|
||||||
char quote_char;
|
char quote_char;
|
||||||
@ -88,7 +94,7 @@ push_keyword(struct keyword *tail, enum keyword_t type, char *buf, size_t *offse
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (type == WORD && *offset == 0)
|
if(type == WORD && *offset == 0)
|
||||||
return tail;
|
return tail;
|
||||||
|
|
||||||
kw = xcalloc(1, sizeof(*kw));
|
kw = xcalloc(1, sizeof(*kw));
|
||||||
@ -97,28 +103,29 @@ push_keyword(struct keyword *tail, enum keyword_t type, char *buf, size_t *offse
|
|||||||
kw->file = file;
|
kw->file = file;
|
||||||
kw->next = NULL;
|
kw->next = NULL;
|
||||||
|
|
||||||
if (*offset != 0) {
|
if(*offset)
|
||||||
|
{
|
||||||
buf[*offset] = '\0';
|
buf[*offset] = '\0';
|
||||||
if (!strcmp(buf, INCLUDE_CMD))
|
|
||||||
|
if(!strcmp(buf, INCLUDE_CMD))
|
||||||
kw->type = INCLUDE;
|
kw->type = INCLUDE;
|
||||||
else
|
else
|
||||||
kw->name = strdup(buf);
|
kw->name = strdup(buf);
|
||||||
|
|
||||||
*offset = 0;
|
*offset = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
kw->name = NULL;
|
kw->name = NULL;
|
||||||
|
|
||||||
if (tail)
|
if(tail)
|
||||||
tail->next = kw;
|
tail->next = kw;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (i = 0; kw_t_name[i].type != NONE; i++) {
|
for(i = 0; kw_t_name[i].type != NONE; ++i)
|
||||||
if (kw_t_name[i].type == kw->type) {
|
if(kw_t_name[i].type == kw->type)
|
||||||
warnx("%s %s %s:%d\n", kw_t_name[i].name,
|
warnx("%s %s %s:%d\n", kw_t_name[i].name,
|
||||||
(kw->name) ? kw->name : "",
|
(kw->name) ? kw->name : "",
|
||||||
kw->file->name, kw->line);
|
kw->file->name, kw->line);
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return kw;
|
return kw;
|
||||||
@ -131,10 +138,10 @@ syntax(struct keyword *kw, const char *fmt, ...)
|
|||||||
|
|
||||||
fprintf(stderr, "%s:", __progname);
|
fprintf(stderr, "%s:", __progname);
|
||||||
|
|
||||||
if (kw && kw->file && kw->file->name)
|
if(kw && kw->file && kw->file->name)
|
||||||
fprintf(stderr, "%s:%d", kw->file->name, kw->line);
|
fprintf(stderr, "%s:%d", kw->file->name, kw->line);
|
||||||
|
|
||||||
if (kw && kw->name)
|
if(kw && kw->name)
|
||||||
fprintf(stderr, ", near '%s'", kw->name);
|
fprintf(stderr, ", near '%s'", kw->name);
|
||||||
fprintf(stderr, ": ");
|
fprintf(stderr, ": ");
|
||||||
|
|
||||||
@ -153,39 +160,42 @@ parse_keywords(const char *filename)
|
|||||||
int fd;
|
int fd;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
struct keyword *head = NULL;
|
struct keyword *head = NULL;
|
||||||
struct keyword *tail = NULL;
|
struct keyword *tail = NULL;
|
||||||
struct files *file;
|
struct files *file;
|
||||||
enum keyword_t type; /* keyword type to push */
|
enum keyword_t type; /* keyword type to push */
|
||||||
struct state s = { False, False, '\0'};
|
struct state s = { false, false, '\0'};
|
||||||
char *bufname;
|
char *bufname;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
int line;
|
int line;
|
||||||
bool error = False;
|
bool error = false;
|
||||||
|
|
||||||
|
|
||||||
if ((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1) {
|
if((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1)
|
||||||
|
{
|
||||||
warn("%s", filename);
|
warn("%s", filename);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st.st_size == 0) {
|
if(!st.st_size)
|
||||||
|
{
|
||||||
warnx("%s: empty file", filename);
|
warnx("%s: empty file", filename);
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!realpath(filename, path)) {
|
if(!realpath(filename, path))
|
||||||
|
{
|
||||||
warn("%s", filename);
|
warn("%s", filename);
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = xmalloc(1, st.st_size+1);
|
buf = xmalloc(1, st.st_size + 1);
|
||||||
|
|
||||||
if (read(fd, buf, st.st_size) == -1) {
|
if(read(fd, buf, st.st_size) == -1)
|
||||||
|
{
|
||||||
warn("%s", filename);
|
warn("%s", filename);
|
||||||
free(buf);
|
free(buf);
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -199,107 +209,122 @@ parse_keywords(const char *filename)
|
|||||||
file->name = strdup(path);
|
file->name = strdup(path);
|
||||||
file->parent = NULL;
|
file->parent = NULL;
|
||||||
|
|
||||||
for(i = 0, j = 0, line = 1; i < (size_t)st.st_size; i++) {
|
for(i = j = 0, line = 1; i < (size_t)st.st_size; ++i)
|
||||||
|
{
|
||||||
if (!head && tail)
|
if(!head && tail)
|
||||||
head = tail;
|
head = tail;
|
||||||
|
|
||||||
if (buf[i] == '\n' && s.comment == True) {
|
if(buf[i] == '\n' && s.comment)
|
||||||
|
{
|
||||||
line++;
|
line++;
|
||||||
s.comment = False;
|
s.comment = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[i] == '#' && s.quote == False) {
|
if(buf[i] == '#' && !s.quote)
|
||||||
s.comment = True;
|
{
|
||||||
|
s.comment = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.comment == True)
|
if(s.comment)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (s.quote == True && buf[i] == s.quote_char) {
|
|
||||||
/* end of quotted string */
|
/* end of quotted string */
|
||||||
|
if(s.quote && buf[i] == s.quote_char)
|
||||||
|
{
|
||||||
PUSH_KEYWORD(WORD);
|
PUSH_KEYWORD(WORD);
|
||||||
s.quote = False;
|
s.quote = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.quote == False) {
|
if(!s.quote)
|
||||||
if ((buf[i] == '"' || buf[i] == '\'')) {
|
{
|
||||||
|
if((buf[i] == '"' || buf[i] == '\''))
|
||||||
|
{
|
||||||
PUSH_KEYWORD(WORD);
|
PUSH_KEYWORD(WORD);
|
||||||
/* begin quotted string */
|
/* begin quotted string */
|
||||||
s.quote_char = buf[i];
|
s.quote_char = buf[i];
|
||||||
s.quote = True;
|
s.quote = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[i] == '[') {
|
if(buf[i] == '[')
|
||||||
|
{
|
||||||
PUSH_KEYWORD(WORD);
|
PUSH_KEYWORD(WORD);
|
||||||
if (buf[i+1] == '/') {
|
|
||||||
i +=2;
|
if(buf[i + 1] == '/')
|
||||||
|
{
|
||||||
|
i += 2;
|
||||||
type = SEC_END;
|
type = SEC_END;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
i++;
|
{
|
||||||
|
++i;
|
||||||
type = SEC_START;
|
type = SEC_START;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get section name */
|
/* get section name */
|
||||||
while (buf[i] != ']') {
|
while(buf[i] != ']')
|
||||||
|
{
|
||||||
if (i >= ((size_t)st.st_size-1) || j >= (BUFSIZ-1)) {
|
if(i >= ((size_t)st.st_size-1) || j >= (BUFSIZ-1))
|
||||||
|
{
|
||||||
bufname[j] = '\0';
|
bufname[j] = '\0';
|
||||||
syntax(NULL, "word too long in %s:%d near '%s'",
|
syntax(NULL, "word too long in %s:%d near '%s'",
|
||||||
file->name, line, bufname);
|
file->name, line, bufname);
|
||||||
error = True;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufname[j++] = buf[i++];
|
bufname[j++] = buf[i++];
|
||||||
}
|
}
|
||||||
PUSH_KEYWORD(type);
|
PUSH_KEYWORD(type);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[i] == '{') {
|
if(buf[i] == '{')
|
||||||
|
{
|
||||||
PUSH_KEYWORD(WORD);
|
PUSH_KEYWORD(WORD);
|
||||||
PUSH_KEYWORD(LIST_START);
|
PUSH_KEYWORD(LIST_START);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[i] == '}') {
|
if(buf[i] == '}')
|
||||||
|
{
|
||||||
PUSH_KEYWORD(WORD);
|
PUSH_KEYWORD(WORD);
|
||||||
PUSH_KEYWORD(LIST_END);
|
PUSH_KEYWORD(LIST_END);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[i] == ',') {
|
if(buf[i] == ',')
|
||||||
|
{
|
||||||
PUSH_KEYWORD(WORD);
|
PUSH_KEYWORD(WORD);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[i] == '=') {
|
if(buf[i] == '=')
|
||||||
|
{
|
||||||
PUSH_KEYWORD(WORD);
|
PUSH_KEYWORD(WORD);
|
||||||
PUSH_KEYWORD(EQUAL);
|
PUSH_KEYWORD(EQUAL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strchr("\t\n ", buf[i])) {
|
if(strchr("\t\n ", buf[i]))
|
||||||
|
{
|
||||||
PUSH_KEYWORD(WORD);
|
PUSH_KEYWORD(WORD);
|
||||||
|
|
||||||
if (buf[i] == '\n')
|
if(buf[i] == '\n')
|
||||||
line++;
|
++line;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} /* s.quote == False */
|
}
|
||||||
|
|
||||||
if (j >= (BUFSIZ - 1)) {
|
if(j >= (BUFSIZ - 1))
|
||||||
|
{
|
||||||
bufname[j] = '\0';
|
bufname[j] = '\0';
|
||||||
syntax(NULL, "word too long in %s:%d near '%s'",
|
syntax(NULL, "word too long in %s:%d near '%s'",
|
||||||
file->name, line, bufname);
|
file->name, line, bufname);
|
||||||
error = True;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,22 +356,26 @@ include(struct keyword *head)
|
|||||||
|
|
||||||
head = head->next;
|
head = head->next;
|
||||||
|
|
||||||
if (!head || head->type != WORD) {
|
if(!head || head->type != WORD)
|
||||||
|
{
|
||||||
syntax(head, "missing filename to include");
|
syntax(head, "missing filename to include");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* replace ~ by user directory */
|
/* replace ~ by user directory */
|
||||||
if (head->name && head->name[0] == '~') {
|
if(head->name && head->name[0] == '~')
|
||||||
if ( (user = getpwuid(getuid())) && user->pw_dir)
|
{
|
||||||
xasprintf(&filename, "%s%s", user->pw_dir, head->name+1);
|
if((user = getpwuid(getuid())) && user->pw_dir)
|
||||||
else if (getenv("HOME"))
|
xasprintf(&filename, "%s%s", user->pw_dir, head->name + 1);
|
||||||
xasprintf(&filename, "%s%s", getenv("HOME"), head->name+1);
|
else if(getenv("HOME"))
|
||||||
|
xasprintf(&filename, "%s%s", getenv("HOME"), head->name + 1);
|
||||||
else /* to warning ? */
|
else /* to warning ? */
|
||||||
filename = head->name;
|
filename = head->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* relative path from parent file */
|
/* relative path from parent file */
|
||||||
else if (head->name && head->name[0] != '/') {
|
else if(head->name && head->name[0] != '/')
|
||||||
|
{
|
||||||
base = strdup(head->file->name);
|
base = strdup(head->file->name);
|
||||||
xasprintf(&filename, "%s/%s", dirname(base), head->name);
|
xasprintf(&filename, "%s/%s", dirname(base), head->name);
|
||||||
free(base);
|
free(base);
|
||||||
@ -354,10 +383,11 @@ include(struct keyword *head)
|
|||||||
else
|
else
|
||||||
filename = head->name;
|
filename = head->name;
|
||||||
|
|
||||||
if (!(kw = parse_keywords(filename))) {
|
if(!(kw = parse_keywords(filename)))
|
||||||
|
{
|
||||||
warnx("no config found in include file %s", head->name);
|
warnx("no config found in include file %s", head->name);
|
||||||
|
|
||||||
if (filename != head->name)
|
if(filename != head->name)
|
||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -366,24 +396,25 @@ include(struct keyword *head)
|
|||||||
kw->file->parent = head->file;
|
kw->file->parent = head->file;
|
||||||
|
|
||||||
/* detect circular include */
|
/* detect circular include */
|
||||||
for (file = kw->file->parent; file != NULL; file = file->parent) {
|
for(file = kw->file->parent; file != NULL; file = file->parent)
|
||||||
if (!strcmp(file->name, kw->file->name)) {
|
if(!strcmp(file->name, kw->file->name))
|
||||||
|
{
|
||||||
syntax(kw, "circular include of %s", kw->file->name);
|
syntax(kw, "circular include of %s", kw->file->name);
|
||||||
|
|
||||||
if (filename != head->name)
|
if(filename != head->name)
|
||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (filename != head->name)
|
if(filename != head->name)
|
||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
head = head->next;
|
head = head->next;
|
||||||
|
|
||||||
if (kw) {
|
if(kw)
|
||||||
for (tail = kw; tail->next; tail = tail->next);
|
{
|
||||||
|
for(tail = kw; tail->next; tail = tail->next);
|
||||||
tail->next = head;
|
tail->next = head;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,51 +437,60 @@ get_option(struct keyword **head)
|
|||||||
|
|
||||||
o = xcalloc(1, sizeof(*o));
|
o = xcalloc(1, sizeof(*o));
|
||||||
o->name = kw->name;
|
o->name = kw->name;
|
||||||
o->used = False;
|
o->used = false;
|
||||||
o->line = kw->line;
|
o->line = kw->line;
|
||||||
o->filename = kw->file->name;
|
o->filename = kw->file->name;
|
||||||
|
|
||||||
kw = kw->next;
|
kw = kw->next;
|
||||||
|
|
||||||
if (kw->type != EQUAL) {
|
if(kw->type != EQUAL)
|
||||||
|
{
|
||||||
syntax(kw, "missing '=' here");
|
syntax(kw, "missing '=' here");
|
||||||
return free_opt(o);
|
return free_opt(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
kw = kw->next;
|
if(!(kw = kw->next))
|
||||||
|
{
|
||||||
if (!kw) {
|
|
||||||
syntax(kw, "missing value");
|
syntax(kw, "missing value");
|
||||||
return free_opt(o);
|
return free_opt(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(kw->type)
|
||||||
switch (kw->type) {
|
{
|
||||||
case INCLUDE:
|
case INCLUDE:
|
||||||
if (!(kw = include(kw)))
|
if(!(kw = include(kw)))
|
||||||
return free_opt(o);
|
return free_opt(o);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WORD:
|
case WORD:
|
||||||
o->val[0] = kw->name;
|
o->val[0] = kw->name;
|
||||||
o->val[1] = NULL;
|
o->val[1] = NULL;
|
||||||
kw = kw->next;
|
kw = kw->next;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LIST_START:
|
case LIST_START:
|
||||||
kw = kw->next;
|
kw = kw->next;
|
||||||
while (kw && kw->type != LIST_END) {
|
|
||||||
switch (kw->type) {
|
while(kw && kw->type != LIST_END)
|
||||||
|
{
|
||||||
|
switch(kw->type)
|
||||||
|
{
|
||||||
case WORD:
|
case WORD:
|
||||||
if (j >= (PARSE_MAX_LIST - 1)) {
|
if(j >= (PARSE_MAX_LIST - 1))
|
||||||
|
{
|
||||||
syntax(kw, "too much values in list");
|
syntax(kw, "too much values in list");
|
||||||
return free_opt(o);
|
return free_opt(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
o->val[j++] = kw->name;
|
o->val[j++] = kw->name;
|
||||||
kw = kw->next;
|
kw = kw->next;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INCLUDE:
|
case INCLUDE:
|
||||||
if (!(kw = include(kw)))
|
if(!(kw = include(kw)))
|
||||||
return free_opt(o);
|
return free_opt(o);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
syntax(kw, "declaration into a list");
|
syntax(kw, "declaration into a list");
|
||||||
return free_opt(o);
|
return free_opt(o);
|
||||||
@ -458,13 +498,15 @@ get_option(struct keyword **head)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!kw) {
|
if(!kw)
|
||||||
|
{
|
||||||
syntax(kw, "list unclosed");
|
syntax(kw, "list unclosed");
|
||||||
return free_opt(o);
|
return free_opt(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
kw = kw->next;
|
kw = kw->next;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
syntax(kw, "missing value");
|
syntax(kw, "missing value");
|
||||||
return free_opt(o);
|
return free_opt(o);
|
||||||
@ -481,19 +523,25 @@ free_sec(struct conf_sec *sec)
|
|||||||
struct conf_opt *o;
|
struct conf_opt *o;
|
||||||
struct conf_sec *s;
|
struct conf_sec *s;
|
||||||
|
|
||||||
if (sec) {
|
if(sec)
|
||||||
while (!SLIST_EMPTY(&sec->optlist)) {
|
{
|
||||||
|
while(!SLIST_EMPTY(&sec->optlist))
|
||||||
|
{
|
||||||
o = SLIST_FIRST(&sec->optlist);
|
o = SLIST_FIRST(&sec->optlist);
|
||||||
SLIST_REMOVE_HEAD(&sec->optlist, entry);
|
SLIST_REMOVE_HEAD(&sec->optlist, entry);
|
||||||
free_opt(o);
|
free_opt(o);
|
||||||
}
|
}
|
||||||
while (!TAILQ_EMPTY(&sec->sub)) {
|
|
||||||
|
while(!TAILQ_EMPTY(&sec->sub))
|
||||||
|
{
|
||||||
s = TAILQ_FIRST(&sec->sub);
|
s = TAILQ_FIRST(&sec->sub);
|
||||||
TAILQ_REMOVE(&sec->sub, s, entry);
|
TAILQ_REMOVE(&sec->sub, s, entry);
|
||||||
free_sec(s);
|
free_sec(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(sec);
|
free(sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,29 +555,35 @@ get_section(struct keyword **head)
|
|||||||
|
|
||||||
s = xcalloc(1, sizeof(*s));
|
s = xcalloc(1, sizeof(*s));
|
||||||
s->name = kw->name;
|
s->name = kw->name;
|
||||||
|
|
||||||
TAILQ_INIT(&s->sub);
|
TAILQ_INIT(&s->sub);
|
||||||
SLIST_INIT(&s->optlist);
|
SLIST_INIT(&s->optlist);
|
||||||
|
|
||||||
kw = kw->next;
|
kw = kw->next;
|
||||||
|
|
||||||
while (kw && kw->type != SEC_END) {
|
while(kw && kw->type != SEC_END)
|
||||||
switch (kw->type) {
|
{
|
||||||
|
switch(kw->type)
|
||||||
|
{
|
||||||
case INCLUDE:
|
case INCLUDE:
|
||||||
if (!(kw = include(kw)))
|
if(!(kw = include(kw)))
|
||||||
return free_sec(s);
|
return free_sec(s);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEC_START:
|
case SEC_START:
|
||||||
if (!(sub = get_section(&kw)))
|
if(!(sub = get_section(&kw)))
|
||||||
return free_sec(s);
|
return free_sec(s);
|
||||||
TAILQ_INSERT_TAIL(&s->sub, sub, entry);
|
TAILQ_INSERT_TAIL(&s->sub, sub, entry);
|
||||||
s->nsub++;
|
++s->nsub;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WORD:
|
case WORD:
|
||||||
if (!(o = get_option(&kw)))
|
if(!(o = get_option(&kw)))
|
||||||
return free_sec(s);
|
return free_sec(s);
|
||||||
SLIST_INSERT_HEAD(&s->optlist, o, entry);
|
SLIST_INSERT_HEAD(&s->optlist, o, entry);
|
||||||
s->nopt++;
|
++s->nopt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
syntax(kw, "syntax error");
|
syntax(kw, "syntax error");
|
||||||
return free_sec(s);
|
return free_sec(s);
|
||||||
@ -537,7 +591,8 @@ get_section(struct keyword **head)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!kw || strcmp(kw->name, s->name)) {
|
if(!kw || strcmp(kw->name, s->name))
|
||||||
|
{
|
||||||
syntax(kw, "missing end section %s", s->name);
|
syntax(kw, "missing end section %s", s->name);
|
||||||
return free_sec(s);
|
return free_sec(s);
|
||||||
}
|
}
|
||||||
@ -556,7 +611,8 @@ free_conf(void)
|
|||||||
struct files **f = NULL;
|
struct files **f = NULL;
|
||||||
int i, nf = 0;
|
int i, nf = 0;
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&config)) {
|
while(!TAILQ_EMPTY(&config))
|
||||||
|
{
|
||||||
s = TAILQ_FIRST(&config);
|
s = TAILQ_FIRST(&config);
|
||||||
TAILQ_REMOVE(&config, s, entry);
|
TAILQ_REMOVE(&config, s, entry);
|
||||||
free_sec(s);
|
free_sec(s);
|
||||||
@ -564,29 +620,34 @@ free_conf(void)
|
|||||||
|
|
||||||
kw = keywords;
|
kw = keywords;
|
||||||
|
|
||||||
while (kw) {
|
while(kw)
|
||||||
|
{
|
||||||
nkw = kw->next;
|
nkw = kw->next;
|
||||||
|
|
||||||
free(kw->name);
|
free(kw->name);
|
||||||
|
|
||||||
for (i = 0; i < nf; i++) {
|
for(i = 0; i < nf; ++i)
|
||||||
if (f[i] == kw->file) {
|
if(f[i] == kw->file)
|
||||||
if (!(f = realloc(f, sizeof(*f) * (++i))))
|
{
|
||||||
|
if(!(f = realloc(f, sizeof(*f) * (++i))))
|
||||||
err(EXIT_FAILURE, "realloc");
|
err(EXIT_FAILURE, "realloc");
|
||||||
f[i-1] = kw->file;
|
|
||||||
}
|
f[i - 1] = kw->file;
|
||||||
}
|
}
|
||||||
|
|
||||||
kw = nkw;
|
kw = nkw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nf > 0) {
|
if(nf > 0)
|
||||||
for (i = 0; i < nf; i++) {
|
{
|
||||||
|
for(i = 0; i < nf; ++i)
|
||||||
|
{
|
||||||
free(f[i]->name);
|
free(f[i]->name);
|
||||||
free(f[i]);
|
free(f[i]);
|
||||||
}
|
}
|
||||||
free(f);
|
free(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,34 +655,38 @@ int
|
|||||||
get_conf(const char *filename)
|
get_conf(const char *filename)
|
||||||
{
|
{
|
||||||
struct conf_sec *s;
|
struct conf_sec *s;
|
||||||
struct keyword *head, *kw;
|
struct keyword *head = parse_keywords(filename);
|
||||||
|
struct keyword *kw = parse_keywords(filename);
|
||||||
|
|
||||||
kw = head = parse_keywords(filename);
|
if(!head)
|
||||||
|
|
||||||
if (!head)
|
|
||||||
return -1; /* TODO ERREUR */
|
return -1; /* TODO ERREUR */
|
||||||
|
|
||||||
keywords = head;
|
keywords = head;
|
||||||
|
|
||||||
TAILQ_INIT(&config);
|
TAILQ_INIT(&config);
|
||||||
|
|
||||||
while (kw) {
|
while(kw)
|
||||||
switch (kw->type) {
|
{
|
||||||
|
switch(kw->type)
|
||||||
|
{
|
||||||
case INCLUDE:
|
case INCLUDE:
|
||||||
if (!(kw = include(kw)))
|
if(!(kw = include(kw)))
|
||||||
return free_conf();
|
return free_conf();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEC_START:
|
case SEC_START:
|
||||||
if (!(s = get_section(&kw)))
|
if(!(s = get_section(&kw)))
|
||||||
return free_conf();
|
return free_conf();
|
||||||
TAILQ_INSERT_TAIL(&config, s, entry);
|
TAILQ_INSERT_TAIL(&config, s, entry);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
syntax(kw, "out of any section");
|
syntax(kw, "out of any section");
|
||||||
return free_conf();
|
return free_conf();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
||||||
|
* Copyright (c) 2011 Martin Duquesnoy <xorg62@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -22,7 +23,8 @@
|
|||||||
#define INCLUDE_CMD "@include"
|
#define INCLUDE_CMD "@include"
|
||||||
#define PARSE_MAX_LIST 32
|
#define PARSE_MAX_LIST 32
|
||||||
|
|
||||||
struct conf_opt {
|
struct conf_opt
|
||||||
|
{
|
||||||
char *name;
|
char *name;
|
||||||
char *val[PARSE_MAX_LIST];
|
char *val[PARSE_MAX_LIST];
|
||||||
size_t nval;
|
size_t nval;
|
||||||
@ -32,16 +34,18 @@ struct conf_opt {
|
|||||||
SLIST_ENTRY(conf_opt) entry;
|
SLIST_ENTRY(conf_opt) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct conf_sec {
|
struct conf_sec
|
||||||
|
{
|
||||||
char *name;
|
char *name;
|
||||||
SLIST_HEAD(, conf_opt) optlist;
|
SLIST_HEAD(, conf_opt) optlist;
|
||||||
TAILQ_HEAD(, conf_sec) sub;
|
TAILQ_HEAD(cshead, conf_sec) sub;
|
||||||
size_t nopt;
|
size_t nopt;
|
||||||
size_t nsub;
|
size_t nsub;
|
||||||
TAILQ_ENTRY(conf_sec) entry;
|
TAILQ_ENTRY(conf_sec) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct opt_type {
|
struct opt_type
|
||||||
|
{
|
||||||
long int num;
|
long int num;
|
||||||
float fnum;
|
float fnum;
|
||||||
bool boolean;
|
bool boolean;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
||||||
|
* Copyright (c) 2011 Martin Duquesnoy <xorg62@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -27,24 +28,23 @@
|
|||||||
|
|
||||||
extern TAILQ_HEAD(, conf_sec) config;
|
extern TAILQ_HEAD(, conf_sec) config;
|
||||||
|
|
||||||
static const struct opt_type opt_type_null = { 0, 0, False, NULL };
|
static const struct opt_type opt_type_null = { 0, 0, false, NULL };
|
||||||
|
|
||||||
static struct opt_type
|
static struct opt_type
|
||||||
string_to_opt(char *s)
|
string_to_opt(char *s)
|
||||||
{
|
{
|
||||||
struct opt_type ret = opt_type_null;
|
struct opt_type ret = opt_type_null;
|
||||||
|
|
||||||
if (!s || !strlen(s))
|
if(!s || !strlen(s))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret.num = strtol(s, (char**)NULL, 10);
|
ret.num = strtol(s, (char**)NULL, 10);
|
||||||
ret.fnum = strtod(s, NULL);
|
ret.fnum = strtod(s, NULL);
|
||||||
|
|
||||||
if (!strcmp(s, "true") || !strcmp(s, "True") ||
|
ret.boolean = (!strcmp(s, "true")
|
||||||
!strcmp(s, "TRUE") || !strcmp(s, "1"))
|
|| !strcmp(s, "true")
|
||||||
ret.boolean = True;
|
|| !strcmp(s, "TRUE")
|
||||||
else
|
|| !strcmp(s, "1"));
|
||||||
ret.boolean = False;
|
|
||||||
|
|
||||||
ret.str = s;
|
ret.str = s;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ print_unused(struct conf_sec *sec)
|
|||||||
struct conf_sec *s;
|
struct conf_sec *s;
|
||||||
struct conf_opt *o;
|
struct conf_opt *o;
|
||||||
|
|
||||||
if (!sec)
|
if(!sec)
|
||||||
{
|
{
|
||||||
TAILQ_FOREACH(s, &config, entry)
|
TAILQ_FOREACH(s, &config, entry)
|
||||||
print_unused(s);
|
print_unused(s);
|
||||||
@ -66,12 +66,11 @@ print_unused(struct conf_sec *sec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SLIST_FOREACH(o, &sec->optlist, entry)
|
SLIST_FOREACH(o, &sec->optlist, entry)
|
||||||
if (o->used == False)
|
if(!o->used)
|
||||||
warnx("%s:%d, unused param %s",
|
warnx("%s:%d, unused param %s", o->filename, o->line, o->name);
|
||||||
o->filename, o->line, o->name);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(s, &sec->sub, entry)
|
TAILQ_FOREACH(s, &sec->sub, entry)
|
||||||
if (!TAILQ_EMPTY(&s->sub))
|
if(!TAILQ_EMPTY(&s->sub))
|
||||||
print_unused(s);
|
print_unused(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,26 +81,32 @@ fetch_section(struct conf_sec *s, char *name)
|
|||||||
struct conf_sec *sec;
|
struct conf_sec *sec;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
if (!name)
|
if(!name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!s) {
|
if(!s)
|
||||||
|
{
|
||||||
ret = xcalloc(2, sizeof(struct conf_sec *));
|
ret = xcalloc(2, sizeof(struct conf_sec *));
|
||||||
|
|
||||||
TAILQ_FOREACH(sec, &config, entry)
|
TAILQ_FOREACH(sec, &config, entry)
|
||||||
if (!strcmp(sec->name, name)) {
|
if(!strcmp(sec->name, name))
|
||||||
|
{
|
||||||
ret[0] = sec;
|
ret[0] = sec;
|
||||||
ret[1] = NULL;
|
ret[1] = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
ret = xcalloc(s->nsub+1, sizeof(struct conf_sec *));
|
{
|
||||||
TAILQ_FOREACH(sec, &s->sub, entry) {
|
ret = xcalloc(s->nsub + 1, sizeof(struct conf_sec *));
|
||||||
if (!strcmp(sec->name, name) && i < s->nsub)
|
|
||||||
|
TAILQ_FOREACH(sec, &s->sub, entry)
|
||||||
|
if(!strcmp(sec->name, name) && i < s->nsub)
|
||||||
ret[i++] = sec;
|
ret[i++] = sec;
|
||||||
}
|
|
||||||
ret[i] = NULL;
|
ret[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,26 +114,20 @@ struct conf_sec *
|
|||||||
fetch_section_first(struct conf_sec *s, char *name)
|
fetch_section_first(struct conf_sec *s, char *name)
|
||||||
{
|
{
|
||||||
struct conf_sec *sec, *ret = NULL;
|
struct conf_sec *sec, *ret = NULL;
|
||||||
|
TAILQ_HEAD(cshead, conf_sec) *head =
|
||||||
|
(s
|
||||||
|
? (struct cshead*)&s->sub
|
||||||
|
: (struct cshead*)&config);
|
||||||
|
|
||||||
if (!name)
|
if(!name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!s)
|
TAILQ_FOREACH(sec, head, entry)
|
||||||
|
if(sec->name && !strcmp(sec->name, name))
|
||||||
{
|
{
|
||||||
TAILQ_FOREACH(sec, &config, entry)
|
|
||||||
if(sec->name && !strcmp(sec->name, name)) {
|
|
||||||
ret = sec;
|
ret = sec;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TAILQ_FOREACH(sec, &s->sub, entry)
|
|
||||||
if (sec->name && !strcmp(sec->name, name)) {
|
|
||||||
ret = sec;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -136,8 +135,11 @@ fetch_section_first(struct conf_sec *s, char *name)
|
|||||||
size_t
|
size_t
|
||||||
fetch_section_count(struct conf_sec **s)
|
fetch_section_count(struct conf_sec **s)
|
||||||
{
|
{
|
||||||
size_t ret;
|
size_t ret = 0;
|
||||||
for (ret = 0; s[ret]; ret++);
|
|
||||||
|
while(s[ret])
|
||||||
|
++ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,20 +150,25 @@ fetch_opt(struct conf_sec *s, char *dfl, char *name)
|
|||||||
struct opt_type *ret;
|
struct opt_type *ret;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
if (!name)
|
if(!name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = xcalloc(10, sizeof(struct opt_type));
|
ret = xcalloc(10, sizeof(struct opt_type));
|
||||||
|
|
||||||
if (s) {
|
if(s)
|
||||||
|
{
|
||||||
SLIST_FOREACH(o, &s->optlist, entry)
|
SLIST_FOREACH(o, &s->optlist, entry)
|
||||||
if (!strcmp(o->name, name)) {
|
if(!strcmp(o->name, name))
|
||||||
while (o->val[i]) {
|
{
|
||||||
o->used = True;
|
while(o->val[i])
|
||||||
|
{
|
||||||
|
o->used = true;
|
||||||
ret[i] = string_to_opt(o->val[i]);
|
ret[i] = string_to_opt(o->val[i]);
|
||||||
i++;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret[i] = opt_type_null;
|
ret[i] = opt_type_null;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,22 +184,30 @@ fetch_opt_first(struct conf_sec *s, char *dfl, char *name)
|
|||||||
{
|
{
|
||||||
struct conf_opt *o;
|
struct conf_opt *o;
|
||||||
|
|
||||||
if (!name)
|
if(!name)
|
||||||
return opt_type_null;
|
return opt_type_null;
|
||||||
else if (s)
|
else if(s)
|
||||||
|
{
|
||||||
SLIST_FOREACH(o, &s->optlist, entry)
|
SLIST_FOREACH(o, &s->optlist, entry)
|
||||||
if (!strcmp(o->name, name)) {
|
if(!strcmp(o->name, name))
|
||||||
o->used = True;
|
{
|
||||||
|
o->used = true;
|
||||||
|
|
||||||
return string_to_opt(o->val[0]);
|
return string_to_opt(o->val[0]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return string_to_opt(dfl);
|
return string_to_opt(dfl);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
fetch_opt_count(struct opt_type *o)
|
fetch_opt_count(struct opt_type *o)
|
||||||
{
|
{
|
||||||
size_t ret;
|
size_t ret = 0;
|
||||||
for(ret = 0; o[ret].str; ret++);
|
|
||||||
|
while(o[ret].str)
|
||||||
|
++ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user