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 | |
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.
-rw-r--r-- | doc/grecs-syntax.texi | 25 | ||||
-rw-r--r-- | doc/grecs_config.5 | 27 | ||||
-rw-r--r-- | src/preproc.c | 63 | ||||
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/incl00.at | 39 | ||||
-rw-r--r-- | tests/incl01.at | 41 | ||||
-rw-r--r-- | tests/incl02.at | 51 | ||||
-rw-r--r-- | tests/incl03.at | 45 | ||||
-rw-r--r-- | tests/testsuite.at | 8 |
9 files changed, 281 insertions, 24 deletions
diff --git a/doc/grecs-syntax.texi b/doc/grecs-syntax.texi index c10cab6..da59d03 100644 --- a/doc/grecs-syntax.texi +++ b/doc/grecs-syntax.texi @@ -1,5 +1,5 @@ @c This file is part of grecs - Gray's Extensible Configuration System -@c Copyright (C) 2007, 2009-2012 Sergey Poznyakoff +@c Copyright (C) 2007, 2009-2014 Sergey Poznyakoff @c @c Grecs is free software; you can redistribute it and/or modify @c it under the terms of the GNU General Public License as published by @@ -82,12 +82,23 @@ next physical newline character. @kwindex #include @item #include <@var{file}> @itemx #include @var{file} -Include the contents of the file @var{file}. If @var{file} is an -absolute file name, both forms are equivalent. Otherwise, the form -with angle brackets searches for the file in the @dfn{include -search path}, while the second one looks for it in the current working -directory first, and, if not found there, in the include search -path. +Include the contents of the file @var{file}. There are three possible +use cases. + +If @var{file} is an absolute file name, the named file is included. +An error message will be issued if it does not exist. + +If @var{file} contains wildcard characters (@samp{*}, @samp{[}, +@samp{]} or @samp{?}), it is interpreted as shell globbing pattern and +all files matching that pattern are included, in lexicographical +order. If no files match the pattern, the statement is silently +ignored. + +Otherwise, the form with angle brackets searches for file in the +@dfn{include search path}, while the second one looks for it in the +current working directory first, and, if not found there, in the +include search path. If the file is not found, an error message will +be issued. The default include search path is: diff --git a/doc/grecs_config.5 b/doc/grecs_config.5 index 80f7bcc..82633d5 100644 --- a/doc/grecs_config.5 +++ b/doc/grecs_config.5 @@ -1,5 +1,5 @@ .\" This file is part of grecs -*- nroff -*- -.\" Copyright (C) 2007, 2009-2012 Sergey Poznyakoff +.\" Copyright (C) 2007, 2009-2014 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 @@ -14,7 +14,7 @@ .\" You should have received a copy of the GNU General Public License .\" along with Grecs. If not, see <http://www.gnu.org/licenses/>. .\" -.TH GRECS_CONFIG 3 "May 4, 2011" "GRECS" "Grecs User Reference" +.TH GRECS_CONFIG 3 "December 25, 2014" "GRECS" "Grecs User Reference" .SH NAME \fBGrecs\fR configuration file syntax .SH DESCRIPTION @@ -64,12 +64,23 @@ sign and end with the next physical newline character. .TP .BR "#include " "file" .PD -Include the contents of the file \fIfile\fR. If it is an -absolute file name, both forms are equivalent. Otherwise, the form -with angle brackets searches for the file in the \fIinclude -search path\fR, while the second one looks for it in the current working -directory first, and, if not found there, in the include search -path. +Include the contents of the file \fIfile\fR. There are three possible +use cases. + +If \fIfile\fR is an absolute file name, the named file is included. +An error message will be issued if it does not exist. + +If \fIfile\fR contains wildcard characters (\fB*\fR, \fB[\fR, +\fB]\fR or \fB?\fR), it is interpreted as shell globbing pattern and +all files matching that pattern are included, in lexicographical +order. If no files match the pattern, the statement is silently +ignored. + +Otherwise, the form with angle brackets searches for file in the +\fIinclude search path\fR, while the second one looks for it in the +current working directory first, and, if not found there, in the +include search path. If the file is not found, an error message will +be issued. .sp The default include search path is: .sp diff --git a/src/preproc.c b/src/preproc.c index ce32a29..56dcc22 100644 --- a/src/preproc.c +++ b/src/preproc.c @@ -1,5 +1,5 @@ /* 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 under the terms of the GNU General Public License as published by the @@ -28,6 +28,7 @@ #include <string.h> #include <errno.h> #include <signal.h> +#include <glob.h> #include <wordsplit.h> @@ -62,6 +63,9 @@ static size_t bufsize; 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); static int pop_source (void); @@ -287,7 +291,9 @@ static int 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; size_t size = strlen (dir) + 1 + dptr->namelen + 1; @@ -395,6 +401,13 @@ 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) { struct input_file_ident key; @@ -405,7 +418,7 @@ source_lookup(struct stat *st) sizeof(struct input_file_ident), incl_hasher, incl_compare, - NULL, + incl_copy, NULL,/*FIXME: alloc*/ NULL); if (!incl_sources) @@ -505,6 +518,14 @@ pop_source() grecs_free(context_stack); 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) fprintf(stderr, "End of input\n"); @@ -552,6 +573,16 @@ 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) { struct wordsplit ws; @@ -579,17 +610,35 @@ parse_include(const char *text, int once) else 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); return rc; diff --git a/tests/Makefile.am b/tests/Makefile.am index 76cfbfe..d6b9d3e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,5 +1,5 @@ # This file is part of grecs - Gray's Extensible Configuration System -# Copyright (C) 2007, 2009-2012 Sergey Poznyakoff +# Copyright (C) 2007, 2009-2014 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 @@ -83,6 +83,10 @@ TESTSUITE_AT = \ glob05.at\ grecs00.at\ enum.at\ + incl00.at\ + incl01.at\ + incl02.at\ + incl03.at\ join.at\ locus00.at\ locus01.at\ diff --git a/tests/incl00.at b/tests/incl00.at new file mode 100644 index 0000000..bb99fd2 --- /dev/null +++ b/tests/incl00.at @@ -0,0 +1,39 @@ +# This file is part of grecs -*- Autotest -*- +# Copyright (C) 2014 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, 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/>. + +AT_SETUP([Include path]) +AT_KEYWORDS([include incl00]) + +AT_CHECK([ +mkdir include +AT_DATA([include/1.inc],[this true; +]) + +AT_DATA([test.cf],[ +before 1; +#include <1.inc> +after 1; +]) + +gcffmt -I`pwd`/include ./test.cf +], +[0], +[.before: "1" +.this: "true" +.after: "1" +]) + +AT_CLEANUP diff --git a/tests/incl01.at b/tests/incl01.at new file mode 100644 index 0000000..0be469b --- /dev/null +++ b/tests/incl01.at @@ -0,0 +1,41 @@ +# This file is part of grecs -*- Autotest -*- +# Copyright (C) 2014 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, 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/>. + +AT_SETUP([Recursive inclusion]) +AT_KEYWORDS([include incl01]) + +AT_CHECK([ +AT_DATA([a.inc],[this true; +#include "b.inc" +]) + +AT_DATA([b.inc],[#include "a.inc" +]) + +AT_DATA([test.cf],[before 1; +#include "a.inc" +after 1; +]) + +gcffmt ./test.cf +], +[1], +[], +[./b.inc:1: Recursive inclusion +./test.cf:2: `./a.inc' already included here +]) + +AT_CLEANUP diff --git a/tests/incl02.at b/tests/incl02.at new file mode 100644 index 0000000..edf83c3 --- /dev/null +++ b/tests/incl02.at @@ -0,0 +1,51 @@ +# This file is part of grecs -*- Autotest -*- +# Copyright (C) 2014 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, 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/>. + +AT_SETUP([Include once]) +AT_KEYWORDS([include incl02]) + +AT_CHECK([ +AT_DATA([a.inc],[a true; +]) + +AT_DATA([test1.cf],[before 1; +#include "a.inc" +#include "a.inc" +after 1; +]) + +AT_DATA([test2.cf],[before 1; +#include_once "a.inc" +#include_once "a.inc" +after 1; +]) + +gcffmt ./test1.cf +echo == +gcffmt ./test2.cf +], +[0], +[.before: "1" +.a: "true" +.a: "true" +.after: "1" +== +.before: "1" +.a: "true" +.after: "1" +]) + +AT_CLEANUP diff --git a/tests/incl03.at b/tests/incl03.at new file mode 100644 index 0000000..201222f --- /dev/null +++ b/tests/incl03.at @@ -0,0 +1,45 @@ +# This file is part of grecs -*- Autotest -*- +# Copyright (C) 2014 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, 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/>. + +AT_SETUP([Wildcard inclusion]) +AT_KEYWORDS([include incl03]) + +AT_CHECK([ +AT_DATA([i1.inc],[i1 included; +]) + +AT_DATA([i2.inc],[i2 included; +]) + +AT_DATA([i3.inc],[i3 included; +]) + +AT_DATA([test.cf],[before 1; +#include "i*.inc" +after 1; +]) + +gcffmt ./test.cf +], +[0], +[.before: "1" +.i1: "included" +.i2: "included" +.i3: "included" +.after: "1" +]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 2d42d4d..eaad2f1 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,5 +1,5 @@ # This file is part of grecs - Gray's Extensible Configuration System -*- Autotest -*- -# Copyright (C) 2007, 2009-2012 Sergey Poznyakoff +# Copyright (C) 2007, 2009-2014 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 @@ -79,6 +79,12 @@ AT_BANNER([Sort]) m4_include([sort00.at]) m4_include([sort01.at]) +AT_BANNER([Include]) +m4_include([incl00.at]) +m4_include([incl01.at]) +m4_include([incl02.at]) +m4_include([incl03.at]) + m4_ifdef([ENABLE_BIND_PARSER],[ AT_BANNER([BIND Parser]) m4_include([parser-bind.at]) |