diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-07-16 12:21:27 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-07-16 12:21:27 +0300 |
commit | 529fed25f92e04d694c30b3fc6bc8645e2703f4e (patch) | |
tree | c575001b35a43ba8f325bf7af60d7b9fb8b8b32a | |
parent | 6201e61fb932dbe6153f92ede836e07247d04b7c (diff) | |
download | grecs-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.texi | 15 | ||||
-rw-r--r-- | include/grecs/parser.h | 5 | ||||
-rw-r--r-- | src/grecs-lex.l | 10 | ||||
-rw-r--r-- | src/parser.c | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/gcffmt.c | 7 | ||||
-rw-r--r-- | tests/stradj.at | 39 | ||||
-rw-r--r-- | tests/strcat.at | 31 | ||||
-rw-r--r-- | tests/testsuite.at | 4 |
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: | |||
111 | where @var{prefix} is the installation prefix. | 111 | where @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 | 115 | New 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 |
217 | above, the backslash is ignored and a warning is issued. | 220 | above, 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 |
220 | another way to split long strings over several lines to improve | 228 | another way to split long strings over several lines to improve |
221 | readability. The following fragment produces the same result as the | 229 | readability. 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 | ||
29 | extern struct grecs_locus_point grecs_current_locus_point; | 29 | extern struct grecs_locus_point grecs_current_locus_point; |
30 | extern grecs_locus_t grecs_locus; | 30 | extern grecs_locus_t grecs_locus; |
31 | extern int grecs_adjust_string_locations; | ||
32 | extern int grecs_error_count; | 31 | extern int grecs_error_count; |
33 | 32 | ||
33 | #define GRECS_OPTION_ADJUST_STRING_LOCATIONS 0x01 | ||
34 | #define GRECS_OPTION_QUOTED_STRING_CONCAT 0x02 | ||
35 | extern int grecs_parser_options; | ||
36 | |||
34 | /* Main entry point */ | 37 | /* Main entry point */ |
35 | struct grecs_node *grecs_parse(const char *name); | 38 | struct grecs_node *grecs_parse(const char *name); |
36 | void grecs_gram_trace(int n); | 39 | void 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); | |||
56 | static int isemptystr(int off); | 56 | static int isemptystr(int off); |
57 | static void qstring_locus_fixup(void); | 57 | static 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() | |||
348 | static void | 352 | static void |
349 | qstring_locus_fixup() | 353 | qstring_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; | |||
26 | int grecs_default_port = 0; | 26 | int grecs_default_port = 0; |
27 | 27 | ||
28 | int grecs_trace_flags = 0; | 28 | int grecs_trace_flags = 0; |
29 | int grecs_adjust_string_locations = 0; | 29 | int 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 | |||
17 | AT_SETUP([String location adjustment]) | ||
18 | AT_KEYWORDS([format option stradj]) | ||
19 | |||
20 | AT_DATA([input.conf], | ||
21 | [ident name; | ||
22 | option "string"; | ||
23 | ]) | ||
24 | |||
25 | AT_CHECK([echo "Default" | ||
26 | gcffmt -nopath -locus input.conf | ||
27 | echo "Adjustment" | ||
28 | gcffmt -nopath -locus -stradj input.conf | ||
29 | ], | ||
30 | [0], | ||
31 | [Default | ||
32 | input.conf:1.7-10: "name" | ||
33 | input.conf:2.8-15: "string" | ||
34 | Adjustment | ||
35 | input.conf:1.7-10: "name" | ||
36 | input.conf:2.9-14: "string" | ||
37 | ]) | ||
38 | |||
39 | AT_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 | # | ||