summaryrefslogtreecommitdiffabout
path: root/src/preproc.c
authorSergey Poznyakoff <gray@gnu.org.ua>2014-12-25 18:15:22 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2014-12-25 23:17:52 (GMT)
commitadd57c075c6f747a81c142ab48d59106de822664 (patch) (side-by-side diff)
treec15f94acdf135954e2f63ac7657c57cdd134ed75 /src/preproc.c
parentd51e1365118ce87016a39bd94437e31b35b8d307 (diff)
downloadgrecs-add57c075c6f747a81c142ab48d59106de822664.tar.gz
grecs-add57c075c6f747a81c142ab48d59106de822664.tar.bz2
Add globbing pattern support to #include and #include_once
* doc/grecs-syntax.texi: Document changes to the #include statement. * doc/grecs_config.5: Likewise. * src/preproc.c (include_glob, include_pos) (include_once): New statics. (pp_list_find): Return 0 if list is NULL. (incl_copy): New statics. (source_lookup): Use incl_copy as the copy function. (pop_source): If more glob expansions are available, push next one onto input stack. (isglob): New static. (parse_include): Support globbing patterns. * tests/Makefile.am: Add new testes. * tests/testsuite.at: Likewise. * tests/incl00.at: New test case. * tests/incl01.at: New test case. * tests/incl02.at: New test case. * tests/incl03.at: New test case.
Diffstat (limited to 'src/preproc.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/preproc.c63
1 files changed, 56 insertions, 7 deletions
diff --git a/src/preproc.c b/src/preproc.c
index ce32a29..56dcc22 100644
--- a/src/preproc.c
+++ b/src/preproc.c
@@ -1,3 +1,3 @@
/* grecs - Gray's Extensible Configuration System
- Copyright (C) 2007-2012 Sergey Poznyakoff
+ Copyright (C) 2007-2014 Sergey Poznyakoff
@@ -30,2 +30,3 @@
#include <signal.h>
+#include <glob.h>
@@ -64,2 +65,5 @@ static size_t putback_size;
static size_t putback_max;
+static glob_t include_glob;
+static size_t include_pos;
+static int include_once;
@@ -289,3 +293,5 @@ pp_list_find(struct grecs_list *list, struct file_data *dptr)
struct grecs_list_entry *ep;
-
+
+ if (!list)
+ return 0;
for (ep = list->head; !dptr->found && ep; ep = ep->next) {
@@ -397,2 +403,9 @@ incl_compare(void const *data1, void const *data2)
static int
+incl_copy(void *dst, void *src)
+{
+ memcpy(dst, src, sizeof(struct input_file_ident));
+ return 0;
+}
+
+static int
source_lookup(struct stat *st)
@@ -407,3 +420,3 @@ source_lookup(struct stat *st)
incl_compare,
- NULL,
+ incl_copy,
NULL,/*FIXME: alloc*/
@@ -507,2 +520,10 @@ pop_source()
+ if (include_pos < include_glob.gl_pathc) {
+ push_source(include_glob.gl_pathv[include_pos++], include_once);
+ return 0;
+ } else if (include_glob.gl_pathc) {
+ globfree(&include_glob);
+ include_pos = include_glob.gl_pathc = 0;
+ }
+
if (!context_stack) {
@@ -554,2 +575,12 @@ grecs_find_include_file(const char *name, int allow_cwd)
static int
+isglob(const char *s)
+{
+ for (; *s; s++) {
+ if (strchr("*?[", *s))
+ return 1;
+ }
+ return 0;
+}
+
+static int
parse_include(const char *text, int once)
@@ -581,4 +612,19 @@ parse_include(const char *text, int once)
- if (p[0] != '/') {
- p = grecs_find_include_file(p, allow_cwd);
+ if (isglob(p)) {
+ switch (glob(p, 0, NULL, &include_glob)) {
+ case 0:
+ include_pos = 0;
+ include_once = once;
+ break;
+ case GLOB_NOSPACE:
+ grecs_alloc_die();
+ case GLOB_NOMATCH:
+ break;
+ default:
+ grecs_error(&LOCUS, 0, _("read error"));
+ }
+ p = NULL;
+ } else if (p[0] != '/') {
+ char *q = p;
+ p = grecs_find_include_file(q, allow_cwd);
if (!p)
@@ -586,5 +632,5 @@ parse_include(const char *text, int once)
_("%s: No such file or directory"),
- p);
+ q);
}
- }
+ }
@@ -592,2 +638,5 @@ parse_include(const char *text, int once)
rc = push_source(p, once);
+ else if (include_pos < include_glob.gl_pathc)
+ rc = push_source(include_glob.gl_pathv[include_pos++], once);
+
grecs_free(tmp);

Return to:

Send suggestions and report system problems to the System administrator.