aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-19 22:00:50 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-19 22:17:45 +0300
commitbcab0df28d7e87f99da29a32327787c25261273e (patch)
tree1dd18f5394afdd0584947cc502c5d2050ba721ba /src
parent304935a296997c9781688f08693ef70180dd24e4 (diff)
downloadgrecs-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.am1
-rw-r--r--src/format.c3
-rw-r--r--src/grecs.h4
-rw-r--r--src/lookup.c13
-rw-r--r--src/path-parser.c124
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;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.