diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-12-16 12:22:52 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-12-16 12:27:02 +0200 |
commit | 74d73e0936d8ff28167e1f5045e3661ab9384a38 (patch) | |
tree | 8fbd707298c690fdaade7ff9cd6b7acfc84434cf | |
parent | 27ac5a32a7ca4cddacce307c586830fbb877b4ce (diff) | |
parent | 9e978b089268e6bfc4b8fcdf9ef721f6fa92c11f (diff) | |
download | grecs-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.m4 | 110 | ||||
-rw-r--r-- | src/format.c | 14 | ||||
-rw-r--r-- | src/grecs-lex.l | 6 | ||||
-rw-r--r-- | src/grecs.hin | 1 | ||||
-rw-r--r-- | src/preproc.c | 3 |
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; |