aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-03 21:06:47 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-03 21:23:25 +0300
commited838ca0467f7cc9745b042099b568cdf0f2b835 (patch)
tree1ffa754e73507d31ece0151e68db25a4ecb81592 /src
parent3d679b3df641f59fb81ca1651799f4e2965ed67e (diff)
downloadgrecs-ed838ca0467f7cc9745b042099b568cdf0f2b835.tar.gz
grecs-ed838ca0467f7cc9745b042099b568cdf0f2b835.tar.bz2
Various impovements.
* am/grecs.m4 (GRECS_SETUP): New flags: getopt and git2chg. * src/format.c (grecs_format_locus): Ignore NULL loci. (grecs_format_node_ident): Rename to grecs_format_node_path. Change semantics of the second argument. (grecs_format_value): Change signature (take flags). Correctly quote string values. * src/grecs.h: Protect the contents with #ifndef _GRECS_H. (GRECS_AGGR): New flag (for future use). (grecs_node) <prev>: New member. (grecs_format_value): Change signature. (grecs_format_node_ident): Rename to grecs_format_node_path. (GRECS_NODE_FLAG_PATH,GRECS_NODE_FLAG_VALUE) (GRECS_NODE_FLAG_QUOTE,GRECS_NODE_FLAG_QUOTE_HEX) (GRECS_NODE_FLAG_DEFAULT): New flags. (grecs_node_from_path): New proto. * src/lookup.c (grecs_node_from_path): New function. * src/tree.c (grecs_node_bind): Keep track of node->prev.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/format.c53
-rw-r--r--src/grecs.h21
-rw-r--r--src/lookup.c59
-rw-r--r--src/tree.c13
-rw-r--r--src/wordsplit.h2
6 files changed, 124 insertions, 30 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 0c2c444..76ae21a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,18 +1,18 @@
# This file is part of grecs - Gray's Extensible Configuration System
# Copyright (C) 2007, 2009-2011 Sergey Poznyakoff
#
-# Grex is free software; you can redistribute it and/or modify
+# Grecs 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 3, or (at your option)
# any later version.
#
-# Grex is distributed in the hope that it will be useful,
+# Grecs 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 Grex. If not, see <http://www.gnu.org/licenses/>.
+# along with Grecs. If not, see <http://www.gnu.org/licenses/>.
noinst_LIBRARIES=libgrecs.a
libgrecs_a_SOURCES = \
diff --git a/src/format.c b/src/format.c
index 11b405a..96cdb0e 100644
--- a/src/format.c
+++ b/src/format.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
+#include "wordsplit.h"
const char *
grecs_data_type_string(enum grecs_data_type type)
@@ -186,38 +187,55 @@ grecs_format_statement_array(struct grecs_keyword *kwp,
void
grecs_format_locus(grecs_locus_t *locus, FILE *fp)
{
- fprintf(fp, "%s:%d:", locus->file, locus->line);
+ if (locus)
+ fprintf(fp, "%s:%d:", locus->file, locus->line);
}
void
-grecs_format_node_ident(struct grecs_node *node, int delim, FILE *fp)
+grecs_format_node_path(struct grecs_node *node, int flags, FILE *fp)
{
+ int delim = flags & 0xff;
if (node->up)
- grecs_format_node_ident(node->up, delim, fp);
- fputc(delim, fp);
+ grecs_format_node_path(node->up, flags, fp);
+ fputc(delim ? delim : '.', fp);
fprintf(fp, "%s", node->ident);
if (node->type == grecs_node_block &&
!GRECS_VALUE_EMPTY_P(&node->value)) {
fputc('=', fp);
- grecs_format_value(&node->value, fp);
+ grecs_format_value(&node->value, flags|GRECS_NODE_FLAG_QUOTE,
+ fp);
}
}
void
-grecs_format_value(struct grecs_value *val, FILE *fp)
+grecs_format_value(struct grecs_value *val, int flags, FILE *fp)
{
int i;
struct grecs_list_entry *ep;
+ size_t clen;
+ int need_quote;
switch (val->type) {
case GRECS_TYPE_STRING:
- fprintf(fp, "\"%s\"", val->v.string); /*FIXME: Quoting*/
+ clen = wordsplit_c_quoted_length(val->v.string,
+ flags & GRECS_NODE_FLAG_QUOTE_HEX,
+ &need_quote);
+ if (flags & GRECS_NODE_FLAG_QUOTE)
+ need_quote = 1;
+ if (need_quote) {
+ char *cbuf = grecs_malloc(clen + 1);
+ wordsplit_c_quote_copy(cbuf, val->v.string,
+ flags & GRECS_NODE_FLAG_QUOTE_HEX);
+ fprintf(fp, "\"%s\"", cbuf);
+ free(cbuf);
+ } else
+ fprintf(fp, "%s", val->v.string);
break;
case GRECS_TYPE_LIST:
fputc('(', fp);
for (ep = val->v.list->head; ep; ep = ep->next) {
- grecs_format_value(ep->data, fp);
+ grecs_format_value(ep->data, flags, fp);
if (ep->next) {
fputc(',', fp);
fputc(' ', fp);
@@ -230,7 +248,7 @@ grecs_format_value(struct grecs_value *val, FILE *fp)
for (i = 0; i < val->v.arg.c; i++) {
if (i)
fputc(' ', fp);
- grecs_format_value(&val->v.arg.v[i], fp);
+ grecs_format_value(&val->v.arg.v[i], flags, fp);
}
}
}
@@ -238,10 +256,8 @@ grecs_format_value(struct grecs_value *val, FILE *fp)
void
grecs_format_node(struct grecs_node *node, int flags, FILE *fp)
{
- int delim = flags & 0xff;
-
- if (!delim)
- delim = '.';
+ if (!flags)
+ flags = GRECS_NODE_FLAG_DEFAULT;
switch (node->type) {
case grecs_node_block:
for (node = node->down; node; node = node->next) {
@@ -256,10 +272,13 @@ grecs_format_node(struct grecs_node *node, int flags, FILE *fp)
grecs_format_locus(&node->locus, fp);
fputc(' ', fp);
}
- grecs_format_node_ident(node, delim, fp);
- fputc(':', fp);
- fputc(' ', fp);
- grecs_format_value(&node->value, fp);
+ if (flags & GRECS_NODE_FLAG_PATH) {
+ grecs_format_node_path(node, flags, fp);
+ fputc(':', fp);
+ fputc(' ', fp);
+ }
+ if (flags & GRECS_NODE_FLAG_VALUE)
+ grecs_format_value(&node->value, flags, fp);
}
}
diff --git a/src/grecs.h b/src/grecs.h
index e0f0fa5..c408aa0 100644
--- a/src/grecs.h
+++ b/src/grecs.h
@@ -14,6 +14,9 @@
You should have received a copy of the GNU General Public License along
with Grecs. If not, see <http://www.gnu.org/licenses/>. */
+#ifndef _GRECS_H
+#define _GRECS_H
+
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
@@ -61,6 +64,7 @@ enum grecs_data_type {
grecs_type_section
};
+#define GRECS_AGGR 0x1000
#define GRECS_LIST 0x8000
#define GRECS_TYPE_MASK 0x00ff
#define GRECS_TYPE(c) ((c) & GRECS_TYPE_MASK)
@@ -115,6 +119,7 @@ typedef struct grecs_node {
struct grecs_node *up;
struct grecs_node *down;
struct grecs_node *next;
+ struct grecs_node *prev;
char *ident;
struct grecs_value value;
} grecs_node_t;
@@ -224,10 +229,16 @@ void grecs_format_statement_array(struct grecs_keyword *kwp,
unsigned level, FILE *stream);
void grecs_format_locus(grecs_locus_t *locus, FILE *fp);
-void grecs_format_node_ident(struct grecs_node *node, int delim, FILE *fp);
-void grecs_format_value(struct grecs_value *val, FILE *fp);
-
-#define GRECS_NODE_FLAG_LOCUS 0x0100
+void grecs_format_node_path(struct grecs_node *node, int flag, FILE *fp);
+void grecs_format_value(struct grecs_value *val, int flags, FILE *fp);
+
+#define GRECS_NODE_FLAG_LOCUS 0x0100
+#define GRECS_NODE_FLAG_PATH 0x0200
+#define GRECS_NODE_FLAG_VALUE 0x0400
+#define GRECS_NODE_FLAG_QUOTE 0x0800
+#define GRECS_NODE_FLAG_QUOTE_HEX 0x1000
+#define GRECS_NODE_FLAG_DEFAULT \
+ (GRECS_NODE_FLAG_PATH|GRECS_NODE_FLAG_VALUE|GRECS_NODE_FLAG_QUOTE)
void grecs_format_node(struct grecs_node *node, int flags, FILE *fp);
struct grecs_list *grecs_list_create(void);
@@ -301,4 +312,6 @@ int grecs_tree_process(struct grecs_node *node, struct grecs_keyword *kwd);
int grecs_value_eq(struct grecs_value *a, struct grecs_value *b);
struct grecs_node *grecs_find_node(struct grecs_node *node, const char *path);
+struct grecs_node *grecs_node_from_path(const char *path, const char *value);
+#endif
diff --git a/src/lookup.c b/src/lookup.c
index fdf1ae1..7795274 100644
--- a/src/lookup.c
+++ b/src/lookup.c
@@ -256,7 +256,7 @@ grecs_find_node(struct grecs_node *node, const char *path)
struct find_closure clos;
rc = split_cfg_path(path, &clos.argc, &clos.argv);
- if (!clos.argc)
+ if (rc || !clos.argc)
return NULL;
clos.tag = 0;
clos.label = NULL;
@@ -270,3 +270,60 @@ grecs_find_node(struct grecs_node *node, const char *path)
return clos.node;
}
+
+struct grecs_node *
+grecs_node_from_path(const char *path, const char *value)
+{
+ int rc;
+ int i;
+ int argc;
+ char **argv;
+ struct grecs_node *dn = NULL;
+
+ rc = split_cfg_path(path, &argc, &argv);
+ if (rc)
+ return NULL;
+ dn = grecs_node_create(grecs_node_stmt, NULL);
+ dn->ident = argv[argc - 1];
+ if (value) {
+ struct grecs_value *gval = parse_label(value);
+ dn->value = *gval;
+ free(gval); //FIXME
+ } else {
+ dn->value.type = GRECS_TYPE_STRING;
+ dn->value.v.string = NULL;
+ }
+
+ for (i = argc - 2; i >= 0; i--) {
+ struct grecs_value *label = NULL;
+ struct grecs_node *node;
+ char *p, *q = argv[i];
+
+ do {
+ p = strchr(q, '=');
+ if (p && p > argv[i] && p[-1] != '\\') {
+ *p++ = 0;
+ label = parse_label(p);
+ break;
+ } else if (p)
+ q = p + 1;
+ else
+ break;
+ } while (*q);
+
+ node = grecs_node_create(grecs_node_block, NULL);
+ node->ident = argv[i];
+ if (label) {
+ node->value = *label;
+ free(label); //FIXME
+ }
+ node->down = dn;
+ if (dn)
+ dn->up = node;
+ dn = node;
+ }
+
+ free(argv);
+ return dn;
+}
+
diff --git a/src/tree.c b/src/tree.c
index 52d38c0..1a2bba5 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -43,22 +43,26 @@ grecs_node_bind(struct grecs_node *master, struct grecs_node *node, int dn)
struct grecs_node *np;
if (dn) {
- if (!master->down)
+ if (!master->down) {
master->down = node;
- else {
+ node->prev = NULL;
+ } else {
for (np = master->down; np->next; np = np->next)
;
np->next = node;
+ node->prev = np;
}
for (; node; node = node->next)
node->up = master;
} else {
- if (!master->next)
+ if (!master->next) {
master->next = node;
- else {
+ node->prev = NULL;
+ } else {
for (np = master->next; np->next; np = np->next)
;
np->next = node;
+ node->prev = np;
}
node->up = master->up;
}
@@ -771,3 +775,4 @@ grecs_tree_process(struct grecs_node *node, struct grecs_keyword *kwd)
grecs_list_free(clos.sections);
return rc;
}
+
diff --git a/src/wordsplit.h b/src/wordsplit.h
index 5da725a..0ddb02b 100644
--- a/src/wordsplit.h
+++ b/src/wordsplit.h
@@ -131,7 +131,7 @@ void wordsplit_free_words (struct wordsplit *ws);
int wordsplit_c_unquote_char (int c);
int wordsplit_c_quote_char (int c);
size_t wordsplit_c_quoted_length (const char *str, int quote_hex,
- int *quote);
+ int *quote);
void wordsplit_sh_unquote_copy (char *dst, const char *src, size_t n);
void wordsplit_c_unquote_copy (char *dst, const char *src, size_t n);
void wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex);

Return to:

Send suggestions and report system problems to the System administrator.