aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2016-07-16 12:21:27 +0300
committerSergey Poznyakoff <gray@gnu.org>2016-07-16 12:21:27 +0300
commit529fed25f92e04d694c30b3fc6bc8645e2703f4e (patch)
treec575001b35a43ba8f325bf7af60d7b9fb8b8b32a
parent6201e61fb932dbe6153f92ede836e07247d04b7c (diff)
downloadgrecs-529fed25f92e04d694c30b3fc6bc8645e2703f4e.tar.gz
grecs-529fed25f92e04d694c30b3fc6bc8645e2703f4e.tar.bz2
Disable adjacent string concatenation.
The adjacent string concatenation feature doesn't work well with multiple-argument statements. The common example (found in GNU pies) is the "env" statement: env "PATH=/sbin:$PATH" "PRELOAD=true" The intent was to pass it two arguments, but in fact they get concatenated into one. To control this, the grecs_parser_options variable is introduced. If it has the GRECS_OPTION_QUOTED_STRING_CONCAT bit set, adjacent string concatenation is enabled. By default it is disabled. The GRECS_OPTION_ADJUST_STRING_LOCATIONS bit controls the way the quoted sring locations are computed. If it is set, the beginning of the string is counted at the first character after the opening double quote, and its end at the character immediately preceding the closing double quote. Otherwise, both double-quote characters are included in the location (the default). The change is backward incompatible. * doc/grecs-syntax.texi: Update. * include/grecs/parser.h (grecs_adjust_string_locations): Remove. (grecs_parser_options): New extern. * src/grecs-lex.l: QSTRING is returned only if GRECS_OPTION_QUOTED_STRING_CONCAT option is set. The GRECS_OPTION_ADJUST_STRING_LOCATIONS option controls string locus adjustment. * src/parser.c (grecs_adjust_string_locations): Remove. (grecs_parser_options): New variable. * tests/Makefile.am: Add strcat.at, stradj.at * tests/testsuite.at: Likewise. * tests/gcffmt.c: New options -strcat and -stradj * tests/stradj.at: New test case. * tests/strcat.at: New test case.
-rw-r--r--doc/grecs-syntax.texi15
-rw-r--r--include/grecs/parser.h5
-rw-r--r--src/grecs-lex.l10
-rw-r--r--src/parser.c2
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/gcffmt.c7
-rw-r--r--tests/stradj.at39
-rw-r--r--tests/strcat.at31
-rw-r--r--tests/testsuite.at4
9 files changed, 106 insertions, 9 deletions
diff --git a/doc/grecs-syntax.texi b/doc/grecs-syntax.texi
index a7738d6..2ddedea 100644
--- a/doc/grecs-syntax.texi
+++ b/doc/grecs-syntax.texi
@@ -111,9 +111,12 @@ The default include search path is:
111where @var{prefix} is the installation prefix. 111where @var{prefix} is the installation prefix.
112 112
113@c FIXME: Uncomment this, if necessary: 113@c FIXME: Uncomment this, if necessary:
114@c FIXME: New directories can be appended in front of it using @option{-I} 114@ignore
115@c FIXME: (@option{--include-directory}) command line option 115New directories can be appended in front of it using @option{-I}
116@c FIXME: (@pxref{Preprocessor, include-directory}). 116(@option{--include-directory}) command line option
117(@pxref{Preprocessor, include-directory}).
118}
119@end ignore
117 120
118@kwindex #include_once 121@kwindex #include_once
119@item #include_once <@var{file}> 122@item #include_once <@var{file}>
@@ -216,6 +219,11 @@ physical lines, e.g.:
216 If the character following a backslash is not one of those specified 219 If the character following a backslash is not one of those specified
217above, the backslash is ignored and a warning is issued. 220above, the backslash is ignored and a warning is issued.
218 221
222@c FIXME: If grecs_parser_options variable has
223@c FIXME: GRECS_OPTION_QUOTED_STRING_CONCAT bit set, then the
224@c FIXME: following holds:
225
226@ignore
219 Two or more adjacent quoted strings are concatenated, which gives 227 Two or more adjacent quoted strings are concatenated, which gives
220another way to split long strings over several lines to improve 228another way to split long strings over several lines to improve
221readability. The following fragment produces the same result as the 229readability. The following fragment produces the same result as the
@@ -227,6 +235,7 @@ example above:
227" split over several lines" 235" split over several lines"
228@end group 236@end group
229@end smallexample 237@end smallexample
238@end ignore
230 239
231@anchor{here-document} 240@anchor{here-document}
232@item Here-document 241@item Here-document
diff --git a/include/grecs/parser.h b/include/grecs/parser.h
index 00878f4..41b3ae4 100644
--- a/include/grecs/parser.h
+++ b/include/grecs/parser.h
@@ -28,9 +28,12 @@ extern int grecs_default_port;
28 28
29extern struct grecs_locus_point grecs_current_locus_point; 29extern struct grecs_locus_point grecs_current_locus_point;
30extern grecs_locus_t grecs_locus; 30extern grecs_locus_t grecs_locus;
31extern int grecs_adjust_string_locations;
32extern int grecs_error_count; 31extern int grecs_error_count;
33 32
33#define GRECS_OPTION_ADJUST_STRING_LOCATIONS 0x01
34#define GRECS_OPTION_QUOTED_STRING_CONCAT 0x02
35extern int grecs_parser_options;
36
34/* Main entry point */ 37/* Main entry point */
35struct grecs_node *grecs_parse(const char *name); 38struct grecs_node *grecs_parse(const char *name);
36void grecs_gram_trace(int n); 39void grecs_gram_trace(int n);
diff --git a/src/grecs-lex.l b/src/grecs-lex.l
index 113ee88..f7be62f 100644
--- a/src/grecs-lex.l
+++ b/src/grecs-lex.l
@@ -56,6 +56,10 @@ static int ident(void);
56static int isemptystr(int off); 56static int isemptystr(int off);
57static void qstring_locus_fixup(void); 57static void qstring_locus_fixup(void);
58 58
59#define qstring() \
60 ((grecs_parser_options & GRECS_OPTION_QUOTED_STRING_CONCAT) \
61 ? QSTRING : STRING)
62
59#undef YY_INPUT 63#undef YY_INPUT
60#define YY_INPUT(buf,result,max_size) \ 64#define YY_INPUT(buf,result,max_size) \
61 do { \ 65 do { \
@@ -116,7 +120,7 @@ P [1-9][0-9]*
116 grecs_line_add(yytext + 1, yyleng - 2); 120 grecs_line_add(yytext + 1, yyleng - 2);
117 yylval.string = grecs_line_finish(); 121 yylval.string = grecs_line_finish();
118 qstring_locus_fixup(); 122 qstring_locus_fixup();
119 return QSTRING; } 123 return qstring(); }
120\"[^\\"\n]*\\\n { BEGIN(STR); 124\"[^\\"\n]*\\\n { BEGIN(STR);
121 grecs_line_begin(); 125 grecs_line_begin();
122 grecs_line_acc_grow_unescape_last(yytext + 1, 126 grecs_line_acc_grow_unescape_last(yytext + 1,
@@ -138,7 +142,7 @@ P [1-9][0-9]*
138 grecs_line_add(yytext, yyleng - 1); 142 grecs_line_add(yytext, yyleng - 1);
139 yylval.string = grecs_line_finish(); 143 yylval.string = grecs_line_finish();
140 qstring_locus_fixup(); 144 qstring_locus_fixup();
141 return QSTRING; } 145 return qstring(); }
142 /* Multiline strings */ 146 /* Multiline strings */
143"<<"(-" "?)?\\?{ID}[ \t]*#.*\n | 147"<<"(-" "?)?\\?{ID}[ \t]*#.*\n |
144"<<"(-" "?)?\\?{ID}[ \t]*"//".*\n | 148"<<"(-" "?)?\\?{ID}[ \t]*"//".*\n |
@@ -348,7 +352,7 @@ ident()
348static void 352static void
349qstring_locus_fixup() 353qstring_locus_fixup()
350{ 354{
351 if (grecs_adjust_string_locations) { 355 if (grecs_parser_options & GRECS_OPTION_ADJUST_STRING_LOCATIONS) {
352 yylloc.beg.col++; 356 yylloc.beg.col++;
353 yylloc.end.col--; 357 yylloc.end.col--;
354 } 358 }
diff --git a/src/parser.c b/src/parser.c
index 1ad43c1..ed99a7a 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -26,7 +26,7 @@ int grecs_error_count = 0;
26int grecs_default_port = 0; 26int grecs_default_port = 0;
27 27
28int grecs_trace_flags = 0; 28int grecs_trace_flags = 0;
29int grecs_adjust_string_locations = 0; 29int grecs_parser_options = 0;
30 30
31#ifndef GRECS_DEFAULT_PARSER 31#ifndef GRECS_DEFAULT_PARSER
32# define GRECS_DEFAULT_PARSER grecs_grecs_parser 32# define GRECS_DEFAULT_PARSER grecs_grecs_parser
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9bf28da..65f590a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -121,6 +121,8 @@ TESTSUITE_AT = \
121 set.at\ 121 set.at\
122 sort00.at\ 122 sort00.at\
123 sort01.at\ 123 sort01.at\
124 stradj.at\
125 strcat.at\
124 testsuite.at\ 126 testsuite.at\
125 vercmp.at\ 127 vercmp.at\
126 wordsplit.at\ 128 wordsplit.at\
diff --git a/tests/gcffmt.c b/tests/gcffmt.c
index 8e378f9..170f788 100644
--- a/tests/gcffmt.c
+++ b/tests/gcffmt.c
@@ -94,7 +94,8 @@ main(int argc, char **argv)
94 int flags = GRECS_NODE_FLAG_DEFAULT; 94 int flags = GRECS_NODE_FLAG_DEFAULT;
95 int reduce = 0; 95 int reduce = 0;
96 int sort = 0; 96 int sort = 0;
97 97
98 grecs_parser_options = 0;
98 while (--argc) { 99 while (--argc) {
99 char *arg = *++argv; 100 char *arg = *++argv;
100 if (strcmp(arg, "-locus") == 0) 101 if (strcmp(arg, "-locus") == 0)
@@ -128,6 +129,10 @@ main(int argc, char **argv)
128 grecs_gram_trace(1); 129 grecs_gram_trace(1);
129 else if (strcmp(arg, "-X") == 0) 130 else if (strcmp(arg, "-X") == 0)
130 grecs_lex_trace(1); 131 grecs_lex_trace(1);
132 else if (strcmp(arg, "-strcat") == 0)
133 grecs_parser_options |= GRECS_OPTION_QUOTED_STRING_CONCAT;
134 else if (strcmp(arg, "-stradj") == 0)
135 grecs_parser_options |= GRECS_OPTION_ADJUST_STRING_LOCATIONS;
131 else if (arg[0] == '-') 136 else if (arg[0] == '-')
132 usage(progname, stderr, 1); 137 usage(progname, stderr, 1);
133 else { 138 else {
diff --git a/tests/stradj.at b/tests/stradj.at
new file mode 100644
index 0000000..186078a
--- /dev/null
+++ b/tests/stradj.at
@@ -0,0 +1,39 @@
1# This file is part of grecs -*- Autotest -*-
2# Copyright (C) 2016 Sergey Poznyakoff
3#
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
6# the Free Software Foundation; either version 3, or (at your option)
7# any later version.
8#
9# Grecs is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
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/>.
16
17AT_SETUP([String location adjustment])
18AT_KEYWORDS([format option stradj])
19
20AT_DATA([input.conf],
21[ident name;
22option "string";
23])
24
25AT_CHECK([echo "Default"
26gcffmt -nopath -locus input.conf
27echo "Adjustment"
28gcffmt -nopath -locus -stradj input.conf
29],
30[0],
31[Default
32input.conf:1.7-10: "name"
33input.conf:2.8-15: "string"
34Adjustment
35input.conf:1.7-10: "name"
36input.conf:2.9-14: "string"
37])
38
39AT_CLEANUP
diff --git a/tests/strcat.at b/tests/strcat.at
new file mode 100644
index 0000000..b5f703a
--- /dev/null
+++ b/tests/strcat.at
@@ -0,0 +1,31 @@
1# This file is part of grecs -*- Autotest -*-
2# Copyright (C) 2016 Sergey Poznyakoff
3#
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
6# the Free Software Foundation; either version 3, or (at your option)
7# any later version.
8#