aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2014-12-25 20:15:22 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2014-12-26 01:17:52 +0200
commitadd57c075c6f747a81c142ab48d59106de822664 (patch)
treec15f94acdf135954e2f63ac7657c57cdd134ed75
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.
-rw-r--r--doc/grecs-syntax.texi25
-rw-r--r--doc/grecs_config.527
-rw-r--r--src/preproc.c63
-rw-r--r--tests/Makefile.am6
-rw-r--r--tests/incl00.at39
-rw-r--r--tests/incl01.at41
-rw-r--r--tests/incl02.at51
-rw-r--r--tests/incl03.at45
-rw-r--r--tests/testsuite.at8
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 @@
1@c This file is part of grecs - Gray's Extensible Configuration System 1@c This file is part of grecs - Gray's Extensible Configuration System
2@c Copyright (C) 2007, 2009-2012 Sergey Poznyakoff 2@c Copyright (C) 2007, 2009-2014 Sergey Poznyakoff
3@c 3@c
4@c Grecs is free software; you can redistribute it and/or modify 4@c Grecs is free software; you can redistribute it and/or modify
5@c it under the terms of the GNU General Public License as published by 5@c it under the terms of the GNU General Public License as published by
@@ -82,12 +82,23 @@ next physical newline character.
82@kwindex #include 82@kwindex #include
83@item #include <@var{file}> 83@item #include <@var{file}>
84@itemx #include @var{file} 84@itemx #include @var{file}
85Include the contents of the file @var{file}. If @var{file} is an 85Include the contents of the file @var{file}. There are three possible
86absolute file name, both forms are equivalent. Otherwise, the form 86use cases.
87with angle brackets searches for the file in the @dfn{include 87
88search path}, while the second one looks for it in the current working 88If @var{file} is an absolute file name, the named file is included.
89directory first, and, if not found there, in the include search 89An error message will be issued if it does not exist.
90path. 90
91If @var{file} contains wildcard characters (@samp{*}, @samp{[},
92@samp{]} or @samp{?}), it is interpreted as shell globbing pattern and
93all files matching that pattern are included, in lexicographical
94order. If no files match the pattern, the statement is silently
95ignored.
96
97Otherwise, the form with angle brackets searches for file in the
98@dfn{include search path}, while the second one looks for it in the
99current working directory first, and, if not found there, in the
100include search path. If the file is not found, an error message will
101be issued.
91 102
92The default include search path is: 103The default include search path is:
93 104
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 @@
1.\" This file is part of grecs -*- nroff -*- 1.\" This file is part of grecs -*- nroff -*-
2.\" Copyright (C) 2007, 2009-2012 Sergey Poznyakoff 2.\" Copyright (C) 2007, 2009-2014 Sergey Poznyakoff
3.\" 3.\"
4.\" Grecs is free software; you can redistribute it and/or modify 4.\" Grecs is free software; you can redistribute it and/or modify
5.\" it under the terms of the GNU General Public License as published by 5.\" it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
14.\" You should have received a copy of the GNU General Public License 14.\" You should have received a copy of the GNU General Public License
15.\" along with Grecs. If not, see <http://www.gnu.org/licenses/>. 15.\" along with Grecs. If not, see <http://www.gnu.org/licenses/>.
16.\" 16.\"
17.TH GRECS_CONFIG 3 "May 4, 2011" "GRECS" "Grecs User Reference" 17.TH GRECS_CONFIG 3 "December 25, 2014" "GRECS" "Grecs User Reference"
18.SH NAME 18.SH NAME
19\fBGrecs\fR configuration file syntax 19\fBGrecs\fR configuration file syntax
20.SH DESCRIPTION 20.SH DESCRIPTION
@@ -64,12 +64,23 @@ sign and end with the next physical newline character.
64.TP 64.TP
65.BR "#include " "file" 65.BR "#include " "file"
66.PD 66.PD
67Include the contents of the file \fIfile\fR. If it is an 67Include the contents of the file \fIfile\fR. There are three possible
68absolute file name, both forms are equivalent. Otherwise, the form 68use cases.
69with angle brackets searches for the file in the \fIinclude 69
70search path\fR, while the second one looks for it in the current working 70If \fIfile\fR is an absolute file name, the named file is included.
71directory first, and, if not found there, in the include search 71An error message will be issued if it does not exist.
72path. 72
73If \fIfile\fR contains wildcard characters (\fB*\fR, \fB[\fR,
74\fB]\fR or \fB?\fR), it is interpreted as shell globbing pattern and
75all files matching that pattern are included, in lexicographical
76order. If no files match the pattern, the statement is silently
77ignored.
78
79Otherwise, the form with angle brackets searches for file in the
80\fIinclude search path\fR, while the second one looks for it in the
81current working directory first, and, if not found there, in the
82include search path. If the file is not found, an error message will
83be issued.
73.sp 84.sp
74The default include search path is: 85The default include search path is:
75.sp 86.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 @@
1/* grecs - Gray's Extensible Configuration System 1/* grecs - Gray's Extensible Configuration System
2 Copyright (C) 2007-2012 Sergey Poznyakoff 2 Copyright (C) 2007-2014 Sergey Poznyakoff
3 3
4 Grecs is free software; you can redistribute it and/or modify it 4 Grecs is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the 5 under the terms of the GNU General Public License as published by the
@@ -28,6 +28,7 @@
28#include <string.h> 28#include <string.h>
29#include <errno.h> 29#include <errno.h>
30#include <signal.h> 30#include <signal.h>
31#include <glob.h>
31 32
32#include <wordsplit.h> 33#include <wordsplit.h>
33 34
@@ -62,6 +63,9 @@ static size_t bufsize;
62static char *putback_buffer; 63static char *putback_buffer;
63static size_t putback_size; 64static size_t putback_size;
64static size_t putback_max; 65static size_t putback_max;
66static glob_t include_glob;
67static size_t include_pos;
68static int include_once;
65 69
66static int push_source (const char *name, int once); 70static int push_source (const char *name, int once);
67static int pop_source (void); 71static int pop_source (void);
@@ -287,7 +291,9 @@ static int
287pp_list_find(struct grecs_list *list, struct file_data *dptr) 291pp_list_find(struct grecs_list *list, struct file_data *dptr)
288{ 292{
289 struct grecs_list_entry *ep; 293 struct grecs_list_entry *ep;
290 294
295 if (!list)
296 return 0;
291 for (ep = list->head; !dptr->found && ep; ep = ep->next) { 297 for (ep = list->head; !dptr->found && ep; ep = ep->next) {
292 const char *dir = ep->data; 298 const char *dir = ep->data;
293 size_t size = strlen (dir) + 1 + dptr->namelen + 1; 299 size_t size = strlen (dir) + 1 + dptr->namelen + 1;
@@ -395,6 +401,13 @@ incl_compare(void const *data1, void const *data2)
395} 401}
396 402
397static int 403static int
404incl_copy(void *dst, void *src)
405{
406 memcpy(dst, src, sizeof(struct input_file_ident));
407 return 0;
408}
409
410static int
398source_lookup(struct stat *st) 411source_lookup(struct stat *st)
399{ 412{
400 struct input_file_ident key; 413 struct input_file_ident key;
@@ -405,7 +418,7 @@ source_lookup(struct stat *st)
405 sizeof(struct input_file_ident), 418 sizeof(struct input_file_ident),
406 incl_hasher, 419 incl_hasher,
407 incl_compare, 420 incl_compare,
408 NULL, 421 incl_copy,
409 NULL,/*FIXME: alloc*/ 422 NULL,/*FIXME: alloc*/
410 NULL); 423 NULL);
411 if (!incl_sources) 424 if (!incl_sources)
@@ -505,6 +518,14 @@ pop_source()
505 grecs_free(context_stack); 518 grecs_free(context_stack);
506 context_stack = ctx; 519 context_stack = ctx;
507 520
521 if (include_pos < include_glob.gl_pathc) {
522 push_source(include_glob.gl_pathv[include_pos++], include_once);
523 return 0;
524 } else if (include_glob.gl_pathc) {
525 globfree(&include_glob);
526 include_pos = include_glob.gl_pathc = 0;
527 }
528
508 if (!context_stack) { 529 if (!context_stack) {
509 if (grecs_grecs__flex_debug) 530 if (grecs_grecs__flex_debug)
510 fprintf(stderr, "End of input\n"); 531 fprintf(stderr, "End of input\n");
@@ -552,6 +573,16 @@ grecs_find_include_file(const char *name, int allow_cwd)
552} 573}
553 574
554static int 575static int
576isglob(const char *s)
577{
578 for (; *s; s++) {
579 if (strchr("*?[", *s))
580 return 1;
581 }
582 return 0;
583}
584
585static int
555parse_include(const char *text, int once) 586parse_include(const char *text, int once)
556{ 587{
557 struct wordsplit ws; 588 struct wordsplit ws;
@@ -579,17 +610,35 @@ parse_include(const char *text, int once)
579 else 610 else
580 allow_cwd = 1; 611 allow_cwd = 1;
581 612
582 if (p[0] != '/') { 613 if (isglob(p)) {
583 p = grecs_find_include_file(p, allow_cwd); 614 switch (glob(p, 0, NULL, &include_glob)) {
615 case 0:
616 include_pos = 0;
617 include_once = once;
618 break;
619 case GLOB_NOSPACE:
620 grecs_alloc_die();
621 case GLOB_NOMATCH:
622 break;
623 default:
624 grecs_error(&LOCUS, 0, _("read error"));
625 }
626