diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-12-25 20:15:22 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-12-26 01:17:52 +0200 |
commit | add57c075c6f747a81c142ab48d59106de822664 (patch) | |
tree | c15f94acdf135954e2f63ac7657c57cdd134ed75 /src/preproc.c | |
parent | d51e1365118ce87016a39bd94437e31b35b8d307 (diff) | |
download | grecs-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')
-rw-r--r-- | src/preproc.c | 63 |
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); |