diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-03 21:06:47 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-03 21:23:25 +0300 |
commit | ed838ca0467f7cc9745b042099b568cdf0f2b835 (patch) | |
tree | 1ffa754e73507d31ece0151e68db25a4ecb81592 /src | |
parent | 3d679b3df641f59fb81ca1651799f4e2965ed67e (diff) | |
download | grecs-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.am | 6 | ||||
-rw-r--r-- | src/format.c | 53 | ||||
-rw-r--r-- | src/grecs.h | 21 | ||||
-rw-r--r-- | src/lookup.c | 59 | ||||
-rw-r--r-- | src/tree.c | 13 | ||||
-rw-r--r-- | src/wordsplit.h | 2 |
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; +} + @@ -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); |