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/path-parser.c | |
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/path-parser.c')
-rw-r--r-- | src/path-parser.c | 124 |
1 files changed, 124 insertions, 0 deletions
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 @@ | |||
1 | /* Path-style configuration file parser for Grecs. | ||
2 | Copyright (C) 2011 Sergey Poznyakoff | ||
3 | |||
4 | Grecs is free software; you can redistribute it and/or modify it | ||
5 | under the terms of the GNU General Public License as published by the | ||
6 | Free Software Foundation; either version 3 of the License, or (at your | ||
7 | option) any later version. | ||
8 | |||
9 | Grecs is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License along | ||
15 | with Grecs. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <ctype.h> | ||
23 | #include <errno.h> | ||
24 | #include <grecs.h> | ||
25 | |||
26 | static size_t | ||
27 | trimnl(char *buf) | ||
28 | { | ||
29 | size_t len = strlen(buf); | ||
30 | |||
31 | if (len && buf[len-1] == '\n') { | ||
32 | buf[--len] = 0; | ||
33 | if (len && buf[len-1] == '\r') | ||
34 | buf[--len] = 0; | ||
35 | } | ||
36 | return len; | ||
37 | } | ||
38 | |||
39 | struct grecs_node * | ||
40 | grecs_path_parser(const char *name, int traceflags) | ||
41 | { | ||
42 | struct grecs_node *root, *subtree = NULL, *node; | ||
43 | FILE *infile; | ||
44 | char *buf = NULL; | ||
45 | size_t size = 0; | ||
46 | struct grecs_txtacc *acc = NULL; | ||
47 | char *prevptr = NULL; | ||
48 | char *ptr, *p; | ||
49 | int inquote, cont = 0; | ||
50 | |||
51 | infile = fopen(name, "r"); | ||
52 | if (!infile) { | ||
53 | grecs_error(NULL, errno, _("cannot open `%s'"), name); | ||
54 | return NULL; | ||
55 | } | ||
56 | grecs_current_locus.file = grecs_install_text(name); | ||
57 | grecs_current_locus.line = 0; | ||
58 | |||
59 | while (grecs_getline(&buf, &size, infile) >= 0) { | ||
60 | size_t len; | ||
61 | |||
62 | ++grecs_current_locus.line; | ||
63 | len = trimnl(buf); | ||
64 | if (len && buf[len-1] == '\\') { | ||
65 | if (!acc) | ||
66 | acc = grecs_txtacc_create(); | ||
67 | else if (prevptr) { | ||
68 | grecs_txtacc_free_string(acc, prevptr); | ||
69 | prevptr = NULL; | ||
70 | } | ||
71 | grecs_txtacc_grow(acc, buf, len - 1); | ||
72 | cont = 1; | ||
73 | continue; | ||
74 | } else { | ||
75 | if (cont) | ||
76 | ptr = prevptr = grecs_txtacc_finish(acc, 0); | ||
77 | else | ||
78 | ptr = buf; | ||
79 | cont = 0; | ||
80 | } | ||
81 | |||
82 | while (*ptr && (*ptr == ' ' || *ptr == '\t')) | ||
83 | ptr++; | ||
84 | if (!*ptr || *ptr == '#') | ||
85 | continue; | ||
86 | inquote = 0; | ||
87 | for (p = ptr; *p && *p != ':'; p++) { | ||
88 | if (inquote) { | ||
89 | if (inquote == '"' && *p == '\\') | ||
90 | p++; | ||
91 | else if (*p == inquote) | ||
92 | inquote = 0; | ||
93 | } else if (*p == '\'' || *p == '"') | ||
94 | inquote = *p; | ||
95 | } | ||
96 | if (!*p) { | ||
97 | grecs_error(&grecs_current_locus, 0, | ||
98 | _("syntax error")); | ||
99 | continue; | ||
100 | } | ||
101 | *p++ = 0; | ||
102 | while (*p && (*p == ' ' || *p == '\t')) | ||
103 | p++; | ||
104 | |||
105 | node = grecs_node_from_path_locus(ptr, p, | ||
106 | &grecs_current_locus); | ||
107 | if (!subtree) | ||
108 | subtree = node; | ||
109 | else | ||
110 | grecs_node_bind(subtree, node, 0); | ||
111 | } | ||
112 | |||
113 | fclose(infile); | ||
114 | free(buf); | ||
115 | grecs_txtacc_free(acc); | ||
116 | |||
117 | root = grecs_node_create(grecs_node_root, &grecs_current_locus); | ||
118 | root->v.texttab = grecs_text_table(); | ||
119 | grecs_node_bind(root, subtree, 1); | ||
120 | grecs_tree_reduce(root, NULL, 0); | ||
121 | |||
122 | return root; | ||
123 | } | ||
124 | |||