1 |
commit: 081100747d776b2e596508b3af3c74718ac4aa49 |
2 |
Author: Mu Qiao <qiaomuf <AT> gentoo <DOT> org> |
3 |
AuthorDate: Wed Jun 22 12:31:21 2011 +0000 |
4 |
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Jul 3 20:16:03 2011 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=08110074 |
7 |
|
8 |
Walker: support ANSI-C Quoting |
9 |
|
10 |
--- |
11 |
bashast/libbashWalker.g | 17 ++++++++++++++--- |
12 |
scripts/command_execution.bash | 2 ++ |
13 |
scripts/command_execution.bash.result | 4 ++++ |
14 |
src/builtins/echo_builtin.cpp | 2 +- |
15 |
src/builtins/printf_builtin.cpp | 2 +- |
16 |
src/builtins/tests/echo_tests.cpp | 9 +++++++++ |
17 |
src/core/interpreter.cpp | 3 +++ |
18 |
src/cppbash_builtin.cpp | 6 +++++- |
19 |
src/cppbash_builtin.h | 11 ++++++----- |
20 |
9 files changed, 45 insertions(+), 11 deletions(-) |
21 |
|
22 |
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g |
23 |
index f379183..a16d501 100644 |
24 |
--- a/bashast/libbashWalker.g |
25 |
+++ b/bashast/libbashWalker.g |
26 |
@@ -153,6 +153,13 @@ options |
27 |
boost::numeric_cast<unsigned>(token->stop - token->start + 1)); |
28 |
} |
29 |
|
30 |
+ std::string get_single_quoted_string(pANTLR3_BASE_TREE node) |
31 |
+ { |
32 |
+ pANTLR3_COMMON_TOKEN token = node->getToken(node); |
33 |
+ return std::string(reinterpret_cast<const char *>(token->start + 1), |
34 |
+ boost::numeric_cast<unsigned>(token->stop - token->start - 1)); |
35 |
+ } |
36 |
+ |
37 |
char get_char(pANTLR3_BASE_TREE node) |
38 |
{ |
39 |
return *reinterpret_cast<const char *>(node->getToken(node)->start); |
40 |
@@ -267,9 +274,7 @@ string_part returns[std::string libbash_value, bool quoted, bool is_raw_string] |
41 |
$quoted = true; |
42 |
})*) |
43 |
|(SINGLE_QUOTED_STRING) => ^(SINGLE_QUOTED_STRING node=SINGLE_QUOTED_STRING_TOKEN) { |
44 |
- pANTLR3_COMMON_TOKEN token = node->getToken(node); |
45 |
- $libbash_value = std::string(reinterpret_cast<const char *>(token->start + 1), |
46 |
- boost::numeric_cast<unsigned>(token->stop - token->start - 1)); |
47 |
+ $libbash_value = get_single_quoted_string(node); |
48 |
} |
49 |
|(ARITHMETIC_EXPRESSION) => |
50 |
^(ARITHMETIC_EXPRESSION value=arithmetics { |
51 |
@@ -284,6 +289,12 @@ string_part returns[std::string libbash_value, bool quoted, bool is_raw_string] |
52 |
$libbash_value = libbash_string; |
53 |
$is_raw_string = false; |
54 |
} |
55 |
+ |(ANSI_C_QUOTING) => ^(ANSI_C_QUOTING node=SINGLE_QUOTED_STRING_TOKEN) { |
56 |
+ std::stringstream transformed; |
57 |
+ cppbash_builtin::transform_escapes(get_single_quoted_string(node), transformed, true); |
58 |
+ $libbash_value = transformed.str(); |
59 |
+ $quoted = true; |
60 |
+ } |
61 |
|(libbash_string=any_string { |
62 |
$libbash_value = libbash_string; |
63 |
}); |
64 |
|
65 |
diff --git a/scripts/command_execution.bash b/scripts/command_execution.bash |
66 |
index 76e9c4c..dff9984 100644 |
67 |
--- a/scripts/command_execution.bash |
68 |
+++ b/scripts/command_execution.bash |
69 |
@@ -57,3 +57,5 @@ printf "%s %s\n" abc def |
70 |
printf "%s %s\n" $FOO001, def |
71 |
((FOO010=1)) |
72 |
echo "abc #av### ##" # for comment |
73 |
+echo $'abc\tdef\nxyz' |
74 |
+echo -e "\'\"\t\n" |
75 |
|
76 |
diff --git a/scripts/command_execution.bash.result b/scripts/command_execution.bash.result |
77 |
index 5f9bede..0e2e1d6 100644 |
78 |
--- a/scripts/command_execution.bash.result |
79 |
+++ b/scripts/command_execution.bash.result |
80 |
@@ -56,6 +56,10 @@ shopt -u xpg_echo |
81 |
abc def |
82 |
hello, def |
83 |
abc #av### ## |
84 |
+abc def |
85 |
+xyz |
86 |
+\'" |
87 |
+ |
88 |
DEFAULTED=yes |
89 |
FOO001=hello |
90 |
FOO002=Hello World |
91 |
|
92 |
diff --git a/src/builtins/echo_builtin.cpp b/src/builtins/echo_builtin.cpp |
93 |
index 8caecef..9440232 100644 |
94 |
--- a/src/builtins/echo_builtin.cpp |
95 |
+++ b/src/builtins/echo_builtin.cpp |
96 |
@@ -61,7 +61,7 @@ int echo_builtin::exec(const std::vector<std::string>& bash_args) |
97 |
{ |
98 |
try |
99 |
{ |
100 |
- transform_escapes(*i, out_buffer()); |
101 |
+ cppbash_builtin::transform_escapes(*i, out_buffer(), false); |
102 |
} |
103 |
catch(suppress_output) |
104 |
{ |
105 |
|
106 |
diff --git a/src/builtins/printf_builtin.cpp b/src/builtins/printf_builtin.cpp |
107 |
index 9b5fd41..db40fff 100644 |
108 |
--- a/src/builtins/printf_builtin.cpp |
109 |
+++ b/src/builtins/printf_builtin.cpp |
110 |
@@ -39,7 +39,7 @@ int printf_builtin::exec(const std::vector<std::string>& bash_args) |
111 |
begin = bash_args.begin() + 2; |
112 |
|
113 |
std::stringstream format_string; |
114 |
- transform_escapes(*begin, format_string); |
115 |
+ cppbash_builtin::transform_escapes(*begin, format_string, false); |
116 |
boost::format formatter(format_string.str()); |
117 |
for(auto iter = begin + 1; iter != bash_args.end(); ++iter) |
118 |
formatter = formatter % *iter; |
119 |
|
120 |
diff --git a/src/builtins/tests/echo_tests.cpp b/src/builtins/tests/echo_tests.cpp |
121 |
index 7b38422..bd7e2d1 100644 |
122 |
--- a/src/builtins/tests/echo_tests.cpp |
123 |
+++ b/src/builtins/tests/echo_tests.cpp |
124 |
@@ -31,6 +31,15 @@ |
125 |
|
126 |
using namespace std; |
127 |
|
128 |
+TEST(echo_builtin_test, escaped_characters) |
129 |
+{ |
130 |
+ stringstream test_output1, test_output2; |
131 |
+ interpreter walker; |
132 |
+ cppbash_builtin::exec("echo",{"-e", "\\e"},test_output1,cerr,cin,walker); |
133 |
+ cppbash_builtin::exec("echo",{"-e", "\\E"},test_output2,cerr,cin,walker); |
134 |
+ ASSERT_STREQ(test_output1.str().c_str(), test_output2.str().c_str()); |
135 |
+} |
136 |
+ |
137 |
static void test_echo(const string& expected, std::initializer_list<string> args) |
138 |
{ |
139 |
stringstream test_output; |
140 |
|
141 |
diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp |
142 |
index bd19925..ba69143 100644 |
143 |
--- a/src/core/interpreter.cpp |
144 |
+++ b/src/core/interpreter.cpp |
145 |
@@ -36,6 +36,9 @@ |
146 |
#include <boost/range/adaptor/filtered.hpp> |
147 |
#include <boost/range/adaptor/map.hpp> |
148 |
#include <boost/range/algorithm/copy.hpp> |
149 |
+#include <boost/spirit/include/karma.hpp> |
150 |
+#include <boost/spirit/include/phoenix.hpp> |
151 |
+#include <boost/spirit/include/qi.hpp> |
152 |
|
153 |
#include "core/bash_ast.h" |
154 |
|
155 |
|
156 |
diff --git a/src/cppbash_builtin.cpp b/src/cppbash_builtin.cpp |
157 |
index 3cf4d18..c8eb5b9 100644 |
158 |
--- a/src/cppbash_builtin.cpp |
159 |
+++ b/src/cppbash_builtin.cpp |
160 |
@@ -74,7 +74,8 @@ cppbash_builtin::builtins_type& cppbash_builtin::builtins() { |
161 |
} |
162 |
|
163 |
void cppbash_builtin::transform_escapes(const std::string &string, |
164 |
- std::ostream& output) const |
165 |
+ std::ostream& output, |
166 |
+ bool ansi_c) |
167 |
{ |
168 |
using phoenix::val; |
169 |
using qi::lit; |
170 |
@@ -87,11 +88,14 @@ void cppbash_builtin::transform_escapes(const std::string &string, |
171 |
lit('b')[output << val("\b")] | |
172 |
// \e is a GNU extension |
173 |
lit('e')[output << val("\033")] | |
174 |
+ lit('E')[output << val("\033")] | |
175 |
lit('f')[output << val("\f")] | |
176 |
lit('n')[output << val("\n")] | |
177 |
lit('r')[output << val("\r")] | |
178 |
lit('t')[output << val("\t")] | |
179 |
lit('v')[output << val("\v")] | |
180 |
+ lit('\'')[output << val(ansi_c ? "'" : "\\'")] | |
181 |
+ lit('"')[output << val(ansi_c ? "\"" : "\\\"")] | |
182 |
lit('c')[phoenix::throw_(suppress_output())] | |
183 |
lit('\\')[output << val('\\')] | |
184 |
lit("0") >> qi::uint_parser<unsigned, 8, 1, 3>()[ output << phoenix::static_cast_<char>(qi::_1)] | |
185 |
|
186 |
diff --git a/src/cppbash_builtin.h b/src/cppbash_builtin.h |
187 |
index 04ff387..5b27fad 100644 |
188 |
--- a/src/cppbash_builtin.h |
189 |
+++ b/src/cppbash_builtin.h |
190 |
@@ -104,6 +104,12 @@ class cppbash_builtin: public boost::noncopyable |
191 |
return builtin_map.find(builtin) != builtin_map.end(); |
192 |
} |
193 |
|
194 |
+ /// \brief transforms escapes in quoted string |
195 |
+ /// \param string the target string |
196 |
+ /// \param output the place to write |
197 |
+ /// \param ansi_c whether to follow ANSI C standard |
198 |
+ static void transform_escapes(const std::string &string, std::ostream& output, bool ansi_c); |
199 |
+ |
200 |
protected: |
201 |
/// |
202 |
/// \var *_out_stream |
203 |
@@ -129,11 +135,6 @@ class cppbash_builtin: public boost::noncopyable |
204 |
/// holds factories for creating instances of child classes |
205 |
typedef std::map<std::string, boost::function< cppbash_builtin*(BUILTIN_ARGS) >> builtins_type; |
206 |
static builtins_type& builtins(); |
207 |
- |
208 |
- /// \brief transforms escapes in echo input |
209 |
- /// \param string the target string |
210 |
- /// \param output the place to write |
211 |
- void transform_escapes(const std::string &string, std::ostream& output) const; |
212 |
}; |
213 |
|
214 |
/// shortcut for builtin constructor |