aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
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')
-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,8 +1,8 @@
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
6 Free Software Foundation; either version 3 of the License, or (at your 6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version. 7 option) any later version.
8 8
@@ -25,12 +25,13 @@
25#include <stdio.h> 25#include <stdio.h>
26#include <stdlib.h> 26#include <stdlib.h>
27#include <stdarg.h> 27#include <stdarg.h>
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
34int grecs_log_to_stderr = 1; 35int grecs_log_to_stderr = 1;
35void (*grecs_log_setup_hook) () = NULL; 36void (*grecs_log_setup_hook) () = NULL;
36 37
@@ -59,12 +60,15 @@ static size_t linebufsize = 0;
59 60
60static char *linebuf; 61static char *linebuf;
61static size_t bufsize; 62static 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);
68static int parse_include (const char *text, int once); 72static int parse_include (const char *text, int once);
69 73
70ssize_t 74ssize_t
@@ -284,13 +288,15 @@ struct file_data {
284}; 288};
285 289
286static int 290static 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;
294 if (size > dptr->buflen) { 300 if (size > dptr->buflen) {
295 dptr->buflen = size; 301 dptr->buflen = size;
296 dptr->buf = grecs_realloc(dptr->buf, dptr->buflen); 302 dptr->buf = grecs_realloc(dptr->buf, dptr->buflen);
@@ -392,23 +398,30 @@ incl_compare(void const *data1, void const *data2)
392 const struct input_file_ident *id1 = data1; 398 const struct input_file_ident *id1 = data1;
393 const struct input_file_ident *id2 = data2; 399 const struct input_file_ident *id2 = data2;
394 return !(id1->device == id2->device && id1->i_node == id2->i_node); 400 return !(id1->device == id2->device && id1->i_node == id2->i_node);
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;
401 int install = 1; 414 int install = 1;
402 415
403 if (!incl_sources) { 416 if (!incl_sources) {
404 incl_sources = grecs_symtab_create( 417 incl_sources = grecs_symtab_create(
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)
412 grecs_alloc_die(); 425 grecs_alloc_die();
413 } 426 }
414 427
@@ -502,12 +515,20 @@ pop_source()
502 515
503 /* Restore previous context */ 516 /* Restore previous context */
504 ctx = context_stack->prev; 517 ctx = context_stack->prev;
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");
511 return 1; 532 return 1;
512 } 533 }
513 534
@@ -549,12 +570,22 @@ grecs_find_include_file(const char *name, int allow_cwd)
549 return NULL; 570 return NULL;
550 } 571 }
551 return fd.buf; 572 return fd.buf;
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;
558 char *tmp = NULL; 589 char *tmp = NULL;
559 char *p = NULL; 590 char *p = NULL;
560 int rc = 1; 591 int rc = 1;
@@ -576,23 +607,41 @@ parse_include(const char *text, int once)
576 p[len - 1] = 0; 607 p[len - 1] = 0;
577 p++; 608 p++;
578 } 609 }
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 p = NULL;
627 } else if (p[0] != '/') {
628 char *q = p;
629 p = grecs_find_include_file(q, allow_cwd);
584 if (!p) 630 if (!p)
585 grecs_error(&LOCUS, 0, 631 grecs_error(&LOCUS, 0,
586 _("%s: No such file or directory"), 632 _("%s: No such file or directory"),
587 p); 633 q);
588 } 634 }
589 } 635 }
590 636
591 if (p) 637 if (p)
592 rc = push_source(p, once); 638 rc = push_source(p, once);
639 else if (include_pos < include_glob.gl_pathc)
640 rc = push_source(include_glob.gl_pathv[include_pos++], once);
641
593 grecs_free(tmp); 642 grecs_free(tmp);
594 wordsplit_free(&ws); 643 wordsplit_free(&ws);
595 return rc; 644 return rc;
596} 645}
597 646
598int 647int

Return to:

Send suggestions and report system problems to the System administrator.