aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-12-16 12:22:52 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-12-16 12:27:02 +0200
commit74d73e0936d8ff28167e1f5045e3661ab9384a38 (patch)
tree8fbd707298c690fdaade7ff9cd6b7acfc84434cf
parent27ac5a32a7ca4cddacce307c586830fbb877b4ce (diff)
parent9e978b089268e6bfc4b8fcdf9ef721f6fa92c11f (diff)
downloadgrecs-74d73e0936d8ff28167e1f5045e3661ab9384a38.tar.gz
grecs-74d73e0936d8ff28167e1f5045e3661ab9384a38.tar.bz2
Merge branch 'master' into clparse
* build-aux/getopt.m4: Use separate namespace for internal symbols * src/format.c (grecs_format_node_path) (grecs_format_node_path): don't coredump on NULL values. * src/grecs-lex.l: Improve error reporting.
-rw-r--r--build-aux/getopt.m4110
-rw-r--r--src/format.c14
-rw-r--r--src/grecs-lex.l6
-rw-r--r--src/grecs.hin1
-rw-r--r--src/preproc.c3
5 files changed, 75 insertions, 59 deletions
diff --git a/build-aux/getopt.m4 b/build-aux/getopt.m4
index c7357d1..97a2cd5 100644
--- a/build-aux/getopt.m4
+++ b/build-aux/getopt.m4
@@ -79,185 +79,187 @@ define([<_getopt_switch_option_val>],
[<pushdef([<val>],[<_getopt_get_option($1)>])dnl
__getopt_switch_option_val(val, shift($@))[<>]dnl
popdef([<val>])>])
dnl _getopt_set_options(OPTION[,OPTION...])
dnl ---------------------------------------
dnl Set options given as arguments.
define([<_getopt_set_options>],
[<ifelse([<$1>],,,
[<_getopt_set_option([<$1>])
_getopt_set_options(shift($@))>])>])
-dnl format_authors(name[,name...])
+dnl __getopt_format_authors(name[,name...])
dnl ------------------------------
-define([<format_authors>],dnl
+define([<__getopt_format_authors>],dnl
[<ifelse([<$1>],,NULL,[<"$1",
-format_authors(shift($@))>])>])
+__getopt_format_authors(shift($@))>])>])
-dnl upcase(ARGS...)
+dnl __getopt_upcase(ARGS...)
dnl Concatenate and convert ARGS to upper case.
dnl
-define([<upcase>], [<translit([<$*>], [<a-z>], [<A-Z>])>])
+define([<__getopt_upcase>], [<translit([<$*>], [<a-z>], [<A-Z>])>])
-dnl concat(ARGS...)
+dnl __getopt_concat(ARGS...)
dnl Concatenate arguments, inserting ", " between each pair of them.
dnl
-define([<concat>],[<ifelse([<$#>],1,[<$1>],[<$1, concat(shift($@))>])>])
+define([<__getopt_concat>],[<ifelse([<$#>],1,[<$1>],[<$1, __getopt_concat(shift($@))>])>])
-dnl flushleft(ARGS...)
+dnl __getopt_flushleft(ARGS...)
dnl Concatenate ARGS and remove any leading whitespace
dnl
-define([<flushleft>],
- [<patsubst([<concat($*)>], [<^[ ]+>])>])
+define([<__getopt_flushleft>],
+ [<patsubst([<__getopt_concat($*)>], [<^[ ]+>])>])
-dnl chop(ARGS...)
+dnl __getopt_chop(ARGS...)
dnl Concatenate ARGS and remove any trailing whitespace
dnl
-define([<chop>],
+define([<__getopt_chop>],
[<patsubst([<$*>], [<[ ]+$>])>])
-dnl escape(ARGS...)
+dnl __getopt_escape(ARGS...)
dnl Concatenate ARGS and escape any occurrences of double-quotes with
dnl backslashes.
dnl
-define([<escape>],
-[<patsubst([<concat($*)>],[<[\"]>],[<\\\&>])>])
+define([<__getopt_escape>],
+[<patsubst([<__getopt_concat($*)>],[<[\"]>],[<\\\&>])>])
-dnl prep(ARG)
+dnl __getopt_prep(ARG)
dnl Prepare ARG for including in C strings: replace newlines and any
dnl preceding and following whitespace by a single space character, remove
dnl leading whitespace, and escape double-quotes.
dnl
-define([<prep>],
- [<escape(flushleft(patsubst([<$1>],[<[ ]*
+define([<__getopt_prep>],
+ [<__getopt_escape(__getopt_flushleft(patsubst([<$1>],[<[ ]*
+[ ]*>],[< >])))>])
-dnl SHORT_OPTS
+dnl __GETOPT_SHORT_OPTS
dnl Accumulator for the 3rd argument of getopt_long
dnl
-define([<SHORT_OPTS>],[<_getopt_if_option_set([<nopermute>],+)>])
+define([<__GETOPT_SHORT_OPTS>],[<_getopt_if_option_set([<nopermute>],+)>])
dnl GROUP(STRING)
dnl Begin a named group of options
dnl
define([<GROUP>],[<dnl
divert(3)
- { NULL, NULL, 0, N_("prep([<$1>])") },
+ { NULL, NULL, 0, N_("__getopt_prep([<$1>])") },
divert(-1)>])
-# quote(args) - convert args to single-quoted string
-define([<quote>], [<ifelse([<$#>], [<0>], [<>], [<[<$*>]>])>])
-define([<dquote>], [<[<$@>]>])
+# __getopt_quote(args) - convert args to single-quoted string
+define([<__getopt_quote>], [<ifelse([<$#>], [<0>], [<>], [<[<$*>]>])>])
+define([<__getopt_dquote>], [<[<$@>]>])
define([<__GATHER_OPTIONS>],[<
-define([<KEY>],ifelse([<$2>],,[<OPTION_>]upcase(patsubst($1,-,_)),'$2'))
+pushdef([<__GETOPT_KEY>],ifelse([<$2>],,[<OPTION_>]__getopt_upcase(patsubst($1,-,_)),'$2'))
ifelse([<$2>],,[<
divert(1)
- KEY,
+ __GETOPT_KEY,
divert(-1)
>])
-define([<SELECTOR>],ifdef([<SELECTOR>],SELECTOR) case KEY:)
+define([<__GETOPT_SELECTOR>],ifdef([<__GETOPT_SELECTOR>],__GETOPT_SELECTOR) case __GETOPT_KEY:)
ifelse([<$1>],,,[<
divert(2)
- { "$1", ARGTYPE, 0, KEY },
+ { "$1", __GETOPT_ARGTYPE, 0, __GETOPT_KEY },
divert(-1)>])
dnl
-define([<SHORT_OPTS>],dquote(SHORT_OPTS[<>]dnl
-ifelse([<$2>],,,[<$2>]ifelse(ARGTYPE,[<no_argument>],,ARGTYPE,[<required_argument>],:,ARGTYPE,[<optional_argument>],::))))
+define([<__GETOPT_SHORT_OPTS>],__getopt_dquote(__GETOPT_SHORT_OPTS[<>]dnl
+ifelse([<$2>],,,[<$2>]ifelse(__GETOPT_ARGTYPE,[<no_argument>],,__GETOPT_ARGTYPE,[<required_argument>],:,__GETOPT_ARGTYPE,[<optional_argument>],::))))
dnl
ifelse([<$1>],,,dnl
-[<define([<LONG_TAG>],ifelse(LONG_TAG,,[<--$1>],[<LONG_TAG; --$1>]))>])
+[<define([<__GETOPT_LONG_TAG>],ifelse(__GETOPT_LONG_TAG,,[<--$1>],[<__GETOPT_LONG_TAG; --$1>]))>])
ifelse([<$2>],,,dnl
-[<define([<SHORT_TAG>],ifelse(SHORT_TAG,,[<-$2>],[<SHORT_TAG; -$2>]))>])
+[<define([<__GETOPT_SHORT_TAG>],ifelse(__GETOPT_SHORT_TAG,,[<-$2>],[<__GETOPT_SHORT_TAG; -$2>]))>])
+popdef([<__GETOPT_KEY>])
>])
dnl OPTION(long-opt, short-opt, [arg], [descr])
dnl Introduce a command line option. Arguments:
dnl long-opt Long option.
dnl short-opt Short option (a single char)
dnl (At least one of long-opt or short-opt must be present)
dnl
dnl Optional arguments:
dnl arg Option argument.
dnl descr Option description
dnl
dnl If arg is absent, the option does not take any arguments. If arg is
dnl enclosed in square brackets, the option takes an optional argument.
dnl Otherwise, the argument is required.
dnl
dnl If descr is not given the option will not appear in the --help and
dnl --usage outputs.
dnl
define([<OPTION>],[<
-pushdef([<LONG_TAG>])
-pushdef([<SHORT_TAG>])
-pushdef([<ARGNAME>],[<$3>])
-pushdef([<HIDDEN>],ifelse([<$4>],,1,0))
-pushdef([<DOCSTRING>],[<prep([<$4>])>])
-pushdef([<ARGTYPE>],[<ifelse([<$3>],,[<no_argument>],dnl
+pushdef([<__GETOPT_LONG_TAG>])
+pushdef([<__GETOPT_SHORT_TAG>])
+pushdef([<__GETOPT_SELECTOR>])
+pushdef([<__GETOPT_ARGNAME>],[<$3>])
+pushdef([<__GETOPT_HIDDEN>],ifelse([<$4>],,1,0))
+pushdef([<__GETOPT_DOCSTRING>],[<__getopt_prep([<$4>])>])
+pushdef([<__GETOPT_ARGTYPE>],[<ifelse([<$3>],,[<no_argument>],dnl
patsubst([<$3>],[<\[.*\]>]),,[<optional_argument>],dnl
[<required_argument>])>])
__GATHER_OPTIONS($@)
>])
dnl ALIAS(long-opt, short-opt)
dnl Declare aliases for the previous OPTION statement.
dnl long-opt Long option.
dnl short-opt Short option (a single char)
dnl (At least one of long-opt or short-opt must be present)
dnl An OPTION statement may be followed by any number of ALIAS statements.
dnl
define([<ALIAS>],[<
__GATHER_OPTIONS($1,$2)
>])
dnl BEGIN
dnl Start an action associated with the declared option. Must follow OPTION
dnl statement, with optional ALIAS statements in between.
dnl
define([<BEGIN>],[<
-ifelse(HIDDEN,1,,[<
+ifelse(__GETOPT_HIDDEN,1,,[<
divert(3)
{
#ifdef HAVE_GETOPT_LONG
"translit(dnl
-ifelse(SHORT_TAG,,LONG_TAG,[<SHORT_TAG[<>]ifelse(LONG_TAG,,,; LONG_TAG)>]),
+ifelse(__GETOPT_SHORT_TAG,,__GETOPT_LONG_TAG,[<__GETOPT_SHORT_TAG[<>]ifelse(__GETOPT_LONG_TAG,,,; __GETOPT_LONG_TAG)>]),
[<;>],[<,>])",
#else
- "translit(SHORT_TAG, [<;>],[<,>])",
+ "translit(__GETOPT_SHORT_TAG, [<;>],[<,>])",
#endif
- ifelse(ARGNAME,,[<NULL, 0>],
-[<ifelse(ARGTYPE,[<optional_argument>],
-[<N_(>]"[<patsubst(ARGNAME,[<\[\(.*\)\]>],[<\1>])>][<"), 1>],[<N_("ARGNAME"), 0>])>]), N_("DOCSTRING") },
+ ifelse(__GETOPT_ARGNAME,,[<NULL, 0>],
+[<ifelse(__GETOPT_ARGTYPE,[<optional_argument>],
+[<N_(>]"[<patsubst(__GETOPT_ARGNAME,[<\[\(.*\)\]>],[<\1>])>][<"), 1>],[<N_("__GETOPT_ARGNAME"), 0>])>]), N_("__GETOPT_DOCSTRING") },
divert(-1)>])
-popdef([<ARGTYPE>])
-popdef([<ARGNAME>])
-popdef([<DOCSTRING>])
-popdef([<HIDDEN>])
+popdef([<__GETOPT_ARGTYPE>])
+popdef([<__GETOPT_ARGNAME>])
+popdef([<__GETOPT_DOCSTRING>])
+popdef([<__GETOPT_HIDDEN>])
divert(4)dnl
-popdef([<LONG_TAG>])dnl
-popdef([<SHORT_TAG>])dnl
- SELECTOR
+popdef([<__GETOPT_LONG_TAG>])dnl
+popdef([<__GETOPT_SHORT_TAG>])dnl
+ __GETOPT_SELECTOR
{
>])
dnl END
dnl Finish the associated action
dnl
define([<END>],[<
break;
}
divert(-1)
-undefine([<SELECTOR>])>])
+popdef([<__GETOPT_SELECTOR>])>])
dnl OPTNODE(name, value)
define([<OPTNODE>],[<do {
struct grecs_node *node = grecs_node_from_path($1, $2);
if (!cmdline_tree)
cmdline_tree = node;
else
grecs_node_bind(cmdline_tree, node, 0);
} while(0)
>])
dnl GETOPT(argc, argv, [long_index], [onerr])
@@ -266,28 +268,28 @@ dnl
dnl argc Name of the 1st argument to getopt_long.
dnl argv Name of the 2nd argument to getopt_long.
dnl long_index 5th argument to getopt_long. If not given,
dnl NULL will be passed.
dnl onerr Action to take if parsing fails.
dnl
define([<GETOPT>],[<
{
int c;
optind = 0;
#ifdef HAVE_GETOPT_LONG
- while ((c = getopt_long($1, $2, "SHORT_OPTS",
+ while ((c = getopt_long($1, $2, "__GETOPT_SHORT_OPTS",
long_options, NULL)) != EOF)
#else
- while ((c = getopt($1, $2, "SHORT_OPTS")) != EOF)
+ while ((c = getopt($1, $2, "__GETOPT_SHORT_OPTS")) != EOF)
#endif
{
switch (c)
{
default:
ifelse([<$4>],,,[<$4;>])dnl
exit(EX_USAGE);
undivert(4)
}
}
ifelse([<$3>],,[<
if (optind < argc) {
diff --git a/src/format.c b/src/format.c
index 6c13ac4..aaad65a 100644
--- a/src/format.c
+++ b/src/format.c
@@ -1,14 +1,14 @@
/* grecs - Gray's Extensible Configuration System
- Copyright (C) 2007-2012, 2015 Sergey Poznyakoff
+ Copyright (C) 2007-2015 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 of the License, 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
@@ -179,24 +179,26 @@ grecs_print_block_statement(struct grecs_keyword *kwp, unsigned level,
}
void
grecs_print_statement_array(struct grecs_keyword *kwp,
unsigned n,
unsigned level,
FILE *stream)
{
if (!kwp) {
return;
}
for (; kwp->ident; kwp++, n++) {
+ if (kwp->flags & GRECS_HIDDEN)
+ continue;
if (n)
fputc('\n', stream);
if (kwp->type == grecs_type_section)
grecs_print_block_statement(kwp, level, stream);
else
grecs_print_simple_statement(kwp, level, stream);
}
}
void
grecs_format_locus(grecs_locus_t *locus, struct grecs_format_closure *clos)
@@ -233,24 +235,29 @@ grecs_format_locus(grecs_locus_t *locus, struct grecs_format_closure *clos)
clos->fmtfun(str, clos->data);
free(str);
}
}
void
grecs_format_node_path(struct grecs_node *node, int flags,
struct grecs_format_closure *clos)
{
char delim[2] = ".";
+ if (!node) {
+ clos->fmtfun("NULL", clos->data);
+ return;
+ }
+
if (node->up)
grecs_format_node_path(node->up, flags, clos);
if (node->type == grecs_node_root)
return;
if (flags & _GRECS_NODE_MASK_DELIM)
delim[0] = flags & _GRECS_NODE_MASK_DELIM;
clos->fmtfun(delim, clos->data);
clos->fmtfun(node->ident, clos->data);
if (node->type == grecs_node_block &&
!GRECS_VALUE_EMPTY_P(node->v.value)) {
clos->fmtfun("=", clos->data);
grecs_format_value(node->v.value, flags|GRECS_NODE_FLAG_QUOTE,
@@ -312,24 +319,29 @@ grecs_format_value(struct grecs_value *val, int flags,
int
grecs_format_node(struct grecs_node *node, int flags,
struct grecs_format_closure *clos)
{
const char *delim_str = NULL;
if (!(flags & _GRECS_NODE_MASK_OUTPUT)) {
errno = EINVAL;
return 1;
}
+ if (!node) {
+ clos->fmtfun("NULL", clos->data);
+ return 0;
+ }
+
switch (node->type) {
case grecs_node_root:
case grecs_node_block:
if (flags & GRECS_NODE_FLAG_DESCEND) {
for (node = node->down; node; node = node->next) {
grecs_format_node(node, flags, clos);
if (node->next)
clos->fmtfun("\n", clos->data);
}
break;
}
diff --git a/src/grecs-lex.l b/src/grecs-lex.l
index 15d5e9b..29a511e 100644
--- a/src/grecs-lex.l
+++ b/src/grecs-lex.l
@@ -374,25 +374,26 @@ assign_locus(struct grecs_locus_point *ploc,
ploc->col = 0;
return *p != 0;
}
void
grecs_parse_line_directive(char *text, grecs_locus_t *ploc,
struct grecs_locus_point *ppoint, size_t *pxlines)
{
int rc = 1;
struct wordsplit ws;
if (wordsplit(text, &ws, WRDSF_DEFFLAGS))
- grecs_error(ploc, 0, _("cannot parse #line line"));
+ grecs_error(ploc, 0, _("cannot parse #line line: %s"),
+ wordsplit_strerror(&ws));
else {
if (ws.ws_wordc == 2)
rc = assign_locus(ppoint, NULL,
ws.ws_wordv[1], pxlines);
else if (ws.ws_wordc == 3)
rc = assign_locus(ppoint, ws.ws_wordv[2],
ws.ws_wordv[1], pxlines);
else if (ws.ws_wordc == 4) {
rc = assign_locus(ppoint, ws.ws_wordv[2],
ws.ws_wordv[1], 0);
if (pxlines && rc == 0) {
char *p;
@@ -410,24 +411,25 @@ grecs_parse_line_directive(char *text, grecs_locus_t *ploc,
wordsplit_free(&ws);
}
}
void
grecs_parse_line_directive_cpp(char *text, grecs_locus_t *ploc,
struct grecs_locus_point *ppoint,
size_t *pxlines)
{
struct wordsplit ws;
if (wordsplit(text, &ws, WRDSF_DEFFLAGS)) {
- grecs_error(ploc, 0, _("cannot parse #line line"));
+ grecs_error(ploc, 0, _("cannot parse #line line: %s"),
+ wordsplit_strerror(&ws));
return;
} else if (ws.ws_wordc < 3)
grecs_error(ploc, 0, _("invalid #line statement"));
else {
if (assign_locus(ppoint, ws.ws_wordv[2],
ws.ws_wordv[1], pxlines))
grecs_error(ploc, 0, _("malformed #line statement"));
}
wordsplit_free(&ws);
}
diff --git a/src/grecs.hin b/src/grecs.hin
index 6e3f54c..c01c175 100644
--- a/src/grecs.hin
+++ b/src/grecs.hin
@@ -93,24 +93,25 @@ enum grecs_data_type {
grecs_type_cidr,
grecs_type_host,
grecs_type_sockaddr,
grecs_type_section,
grecs_type_null
};
#define GRECS_DFLT 0x00
#define GRECS_AGGR 0x01
#define GRECS_MULT 0x02
#define GRECS_INAC 0x04
#define GRECS_LIST 0x08
+#define GRECS_HIDDEN 0x10
enum grecs_callback_command {
grecs_callback_section_begin,
grecs_callback_section_end,
grecs_callback_set_value
};
#define GRECS_TYPE_STRING 0
#define GRECS_TYPE_LIST 1
#define GRECS_TYPE_ARRAY 2
struct grecs_list_entry {
diff --git a/src/preproc.c b/src/preproc.c
index 2753b40..bdf4d40 100644
--- a/src/preproc.c
+++ b/src/preproc.c
@@ -597,26 +597,25 @@ parse_include(const char *text, int once)
grecs_error(&LOCUS, 0, _("invalid include statement"));
} else {
size_t len;
int allow_cwd;
p = ws.ws_wordv[1];
len = strlen (p);
if (p[0] == '<' && p[len - 1] == '>') {
allow_cwd = 0;
p[len - 1] = 0;
p++;
- }
- else
+ } else
allow_cwd = 1;
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;

Return to:

Send suggestions and report system problems to the System administrator.