diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-19 22:00:50 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-19 22:17:45 +0300 |
commit | bcab0df28d7e87f99da29a32327787c25261273e (patch) | |
tree | 1dd18f5394afdd0584947cc502c5d2050ba721ba /src | |
parent | 304935a296997c9781688f08693ef70180dd24e4 (diff) | |
download | grecs-bcab0df28d7e87f99da29a32327787c25261273e.tar.gz grecs-bcab0df28d7e87f99da29a32327787c25261273e.tar.bz2 |
Implement "path-style" (Xres-style) config parser.
* src/path-parser.c: New file.
* src/format.c (grecs_format_node): Attempt to print value only
if the node is grecs_node_stmt.
* src/grecs.h (grecs_path_parser): New proto.
(grecs_node_from_path_locus): New proto.
* src/lookup.c (grecs_node_from_path_locus): New function.
* src/Make.am (GRECS_SRC): Add path-parser.c.
* build-aux/getopt.m4: Implement print_help_hook.
Diffstat (limited to 'src')
-rw-r--r-- | src/Make.am | 1 | ||||
-rw-r--r-- | src/format.c | 3 | ||||
-rw-r--r-- | src/grecs.h | 4 | ||||
-rw-r--r-- | src/lookup.c | 13 | ||||
-rw-r--r-- | src/path-parser.c | 124 |
5 files changed, 141 insertions, 4 deletions
diff --git a/src/Make.am b/src/Make.am index 312c734..ae6af64 100644 --- a/src/Make.am +++ b/src/Make.am @@ -40,6 +40,7 @@ GRECS_SRC = \ lookup.c\ mem.c\ parser.c\ + path-parser.c\ preproc.c\ sort.c\ symtab.c\ diff --git a/src/format.c b/src/format.c index 9e88412..6d87aed 100644 --- a/src/format.c +++ b/src/format.c @@ -302,7 +302,8 @@ grecs_format_node(struct grecs_node *node, int flags, grecs_format_node_path(node, flags, clos); delim_str = ": "; } - if (flags & GRECS_NODE_FLAG_VALUE) { + if (node->type == grecs_node_stmt && + (flags & GRECS_NODE_FLAG_VALUE)) { if (delim_str) clos->fmtfun(delim_str, clos->data); grecs_format_value(node->v.value, flags, clos); diff --git a/src/grecs.h b/src/grecs.h index fd44e40..c254439 100644 --- a/src/grecs.h +++ b/src/grecs.h @@ -219,6 +219,7 @@ struct grecs_node *grecs_grecs_parser(const char *name, int traceflags); struct grecs_node *grecs_meta1_parser(const char *name, int traceflags); struct grecs_node *grecs_bind_parser(const char *name, int traceflags); struct grecs_node *grecs_git_parser(const char *name, int traceflags); +struct grecs_node *grecs_path_parser(const char *name, int traceflags); struct grecs_list *_grecs_simple_list_create(int dispose); @@ -428,6 +429,9 @@ int grecs_value_match(struct grecs_value *pat, 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); +struct grecs_node *grecs_node_from_path_locus(const char *path, + const char *value, + grecs_locus_t *locus); int grecs_tree_reduce(struct grecs_node *node, struct grecs_keyword *kwd, int flags); diff --git a/src/lookup.c b/src/lookup.c index e7f380e..95b7aac 100644 --- a/src/lookup.c +++ b/src/lookup.c @@ -332,7 +332,8 @@ grecs_find_node(struct grecs_node *node, const char *path) struct grecs_node * -grecs_node_from_path(const char *path, const char *value) +grecs_node_from_path_locus(const char *path, const char *value, + grecs_locus_t *locus) { int rc; int i; @@ -343,7 +344,7 @@ grecs_node_from_path(const char *path, const char *value) rc = split_cfg_path(path, &argc, &argv, NULL); if (rc) return NULL; - dn = grecs_node_create(grecs_node_stmt, NULL); + dn = grecs_node_create(grecs_node_stmt, locus); dn->ident = argv[argc - 1]; if (value) { struct grecs_value *gval = parse_label(value); @@ -368,7 +369,7 @@ grecs_node_from_path(const char *path, const char *value) break; } while (*q); - node = grecs_node_create(grecs_node_block, NULL); + node = grecs_node_create(grecs_node_block, locus); node->ident = argv[i]; if (label) node->v.value = label; @@ -383,6 +384,12 @@ grecs_node_from_path(const char *path, const char *value) return dn; } +struct grecs_node * +grecs_node_from_path(const char *path, const char *value) +{ + return grecs_node_from_path_locus(path, value, NULL); +} + #define ISWC(c,w) ((c)[0] == (w) && (c)[1] == 0) diff --git a/src/path-parser.c b/src/path-parser.c new file mode 100644 index 0000000..c66f8ca --- /dev/null +++ b/src/path-parser.c @@ -0,0 +1,124 @@ +/* Path-style configuration file parser for Grecs. + Copyright (C) 2011 Sergey Poznyakoff + + 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 of the License, or (at your + option) any later version. + + 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 Grecs. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <grecs.h> + +static size_t +trimnl(char *buf) +{ + size_t len = strlen(buf); + + if (len && buf[len-1] == '\n') { + buf[--len] = 0; + if (len && buf[len-1] == '\r') + buf[--len] = 0; + } + return len; +} + +struct grecs_node * +grecs_path_parser(const char *name, int traceflags) +{ + struct grecs_node *root, *subtree = NULL, *node; + FILE *infile; + char *buf = NULL; + size_t size = 0; + struct grecs_txtacc *acc = NULL; + char *prevptr = NULL; + char *ptr, *p; + int inquote, cont = 0; + + infile = fopen(name, "r"); + if (!infile) { + grecs_error(NULL, errno, _("cannot open `%s'"), name); + return NULL; + } + grecs_current_locus.file = grecs_install_text(name); + grecs_current_locus.line = 0; + + while (grecs_getline(&buf, &size, infile) >= 0) { + size_t len; + + ++grecs_current_locus.line; + len = trimnl(buf); + if (len && buf[len-1] == '\\') { + if (!acc) + acc = grecs_txtacc_create(); + else if (prevptr) { + grecs_txtacc_free_string(acc, prevptr); + prevptr = NULL; + } + grecs_txtacc_grow(acc, buf, len - 1); + cont = 1; + continue; + } else { + if (cont) + ptr = prevptr = grecs_txtacc_finish(acc, 0); + else + ptr = buf; + cont = 0; + } + + while (*ptr && (*ptr == ' ' || *ptr == '\t')) + ptr++; + if (!*ptr || *ptr == '#') + continue; + inquote = 0; + for (p = ptr; *p && *p != ':'; p++) { + if (inquote) { + if (inquote == '"' && *p == '\\') + p++; + else if (*p == inquote) + inquote = 0; + } else if (*p == '\'' || *p == '"') + inquote = *p; + } + if (!*p) { + grecs_error(&grecs_current_locus, 0, + _("syntax error")); + continue; + } + *p++ = 0; + while (*p && (*p == ' ' || *p == '\t')) + p++; + + node = grecs_node_from_path_locus(ptr, p, + &grecs_current_locus); + if (!subtree) + subtree = node; + else + grecs_node_bind(subtree, node, 0); + } + + fclose(infile); + free(buf); + grecs_txtacc_free(acc); + + root = grecs_node_create(grecs_node_root, &grecs_current_locus); + root->v.texttab = grecs_text_table(); + grecs_node_bind(root, subtree, 1); + grecs_tree_reduce(root, NULL, 0); + + return root; +} + |