aboutsummaryrefslogtreecommitdiff
path: root/src/path-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/path-parser.c')
-rw-r--r--src/path-parser.c124
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 @@
+/* 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.