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 | |
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')
-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,4 +1,4 @@ /* grecs - Gray's Extensible Configuration System - Copyright (C) 2007-2012 Sergey Poznyakoff + Copyright (C) 2007-2014 Sergey Poznyakoff Grecs is free software; you can redistribute it and/or modify it @@ -29,4 +29,5 @@ #include <errno.h> #include <signal.h> +#include <glob.h> #include <wordsplit.h> @@ -63,4 +64,7 @@ static char *putback_buffer; static size_t putback_size; static size_t putback_max; +static glob_t include_glob; +static size_t include_pos; +static int include_once; static int push_source (const char *name, int once); @@ -288,5 +292,7 @@ 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) { const char *dir = ep->data; @@ -396,4 +402,11 @@ 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) { @@ -406,5 +419,5 @@ source_lookup(struct stat *st) incl_hasher, incl_compare, - NULL, + incl_copy, NULL,/*FIXME: alloc*/ NULL); @@ -506,4 +519,12 @@ pop_source() context_stack = ctx; + 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) { if (grecs_grecs__flex_debug) @@ -553,4 +574,14 @@ 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) { @@ -580,15 +611,33 @@ parse_include(const char *text, int once) allow_cwd = 1; - 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) grecs_error(&LOCUS, 0, _("%s: No such file or directory"), - p); + q); } - } + } if (p) 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); wordsplit_free(&ws); |