1 |
commit: 2a029a4cb1c33939a7ec3fe697431a72237231cd |
2 |
Author: Mu Qiao <qiaomuf <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri Apr 22 07:35:03 2011 +0000 |
4 |
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org> |
5 |
CommitDate: Mon Apr 25 10:08:02 2011 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=2a029a4c |
7 |
|
8 |
Walker: support for each loop |
9 |
|
10 |
Syntax like "for x in blah" is supported now. Empty value used as |
11 |
$@ is not supported for now. Add support for $? variable. |
12 |
|
13 |
--- |
14 |
Makefile.am | 2 + |
15 |
bashast/libbashWalker.g | 58 +++++++++++++++++++++++++-------- |
16 |
scripts/compound_command.bash | 9 +++++ |
17 |
scripts/compound_command.bash.result | 6 +++ |
18 |
src/core/interpreter.cpp | 4 ++- |
19 |
src/core/interpreter.h | 9 +++++- |
20 |
utils/variable_printer.cpp | 8 ++++- |
21 |
7 files changed, 79 insertions(+), 17 deletions(-) |
22 |
|
23 |
diff --git a/Makefile.am b/Makefile.am |
24 |
index 03848ed..0d21393 100644 |
25 |
--- a/Makefile.am |
26 |
+++ b/Makefile.am |
27 |
@@ -52,12 +52,14 @@ BASH_TESTS = scripts/var_def.bash \ |
28 |
scripts/command_execution.bash \ |
29 |
scripts/function_def.bash \ |
30 |
scripts/arithmetic_assignment.bash \ |
31 |
+ scripts/compound_command.bash \ |
32 |
scripts/binary_arithmetic.bash |
33 |
BASH_RESULT = scripts/var_def.bash.result \ |
34 |
scripts/var_expansion.bash.result \ |
35 |
scripts/command_execution.bash.result \ |
36 |
scripts/function_def.bash.result \ |
37 |
scripts/arithmetic_assignment.bash.result \ |
38 |
+ scripts/compound_command.bash.result \ |
39 |
scripts/binary_arithmetic.bash.result |
40 |
|
41 |
TESTS = $(GUNIT_TESTS) $(BASH_TESTS) |
42 |
|
43 |
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g |
44 |
index a3bf40d..90cf04f 100644 |
45 |
--- a/bashast/libbashWalker.g |
46 |
+++ b/bashast/libbashWalker.g |
47 |
@@ -272,7 +272,8 @@ var_ref [bool double_quoted] returns[std::string libbash_value] |
48 |
|
49 |
command |
50 |
:variable_definitions |
51 |
- |simple_command; |
52 |
+ |simple_command |
53 |
+ |compound_command; |
54 |
|
55 |
simple_command |
56 |
@declarations { |
57 |
@@ -280,28 +281,29 @@ simple_command |
58 |
} |
59 |
:^(COMMAND string_expr (argument[libbash_args])* var_def*) { |
60 |
if(walker->has_function($string_expr.libbash_value)) |
61 |
- walker->call($string_expr.libbash_value, |
62 |
- libbash_args, |
63 |
- ctx, |
64 |
- compound_command); |
65 |
+ { |
66 |
+ walker->set_status(walker->call($string_expr.libbash_value, |
67 |
+ libbash_args, |
68 |
+ ctx, |
69 |
+ compound_command)); |
70 |
+ } |
71 |
else if(cppbash_builtin::is_builtin($string_expr.libbash_value)) |
72 |
- walker->execute_builtin($string_expr.libbash_value, libbash_args); |
73 |
+ { |
74 |
+ walker->set_status(walker->execute_builtin($string_expr.libbash_value, libbash_args)); |
75 |
+ } |
76 |
else |
77 |
+ { |
78 |
std::cerr << $string_expr.libbash_value << " is not supported yet" << std::endl; |
79 |
+ walker->set_status(1); |
80 |
+ } |
81 |
}; |
82 |
|
83 |
argument[std::vector<std::string>& args] |
84 |
: string_expr { |
85 |
if($string_expr.quoted) |
86 |
- { |
87 |
args.push_back($string_expr.libbash_value); |
88 |
- } |
89 |
else |
90 |
- { |
91 |
- std::vector<std::string> arguments; |
92 |
- walker->split_word($string_expr.libbash_value, arguments); |
93 |
- args.insert(args.end(), arguments.begin(), arguments.end()); |
94 |
- } |
95 |
+ walker->split_word($string_expr.libbash_value, args); |
96 |
}; |
97 |
|
98 |
logic_command_list |
99 |
@@ -311,7 +313,35 @@ logic_command_list |
100 |
|
101 |
command_list: ^(LIST logic_command_list+); |
102 |
|
103 |
-compound_command: ^(CURRENT_SHELL command_list); |
104 |
+compound_command |
105 |
+ : ^(CURRENT_SHELL command_list) |
106 |
+ | for_expr; |
107 |
+ |
108 |
+for_expr |
109 |
+@declarations { |
110 |
+ ANTLR3_MARKER commands_index; |
111 |
+ std::vector<std::string> splitted_values; |
112 |
+} |
113 |
+ :^(FOR libbash_string=name_base |
114 |
+ // Empty value as $@ is not supported currently |
115 |
+ (string_expr |
116 |
+ { |
117 |
+ // Word splitting happens here |
118 |
+ if($string_expr.quoted) |
119 |
+ splitted_values.push_back($string_expr.libbash_value); |
120 |
+ else |
121 |
+ walker->split_word($string_expr.libbash_value, splitted_values); |
122 |
+ } |
123 |
+ )+ |
124 |
+ { |
125 |
+ commands_index = INDEX(); |
126 |
+ for(auto iter = splitted_values.begin(); iter != splitted_values.end(); ++iter) |
127 |
+ { |
128 |
+ SEEK(commands_index); |
129 |
+ walker->set_value(libbash_string, *iter); |
130 |
+ command_list(ctx); |
131 |
+ } |
132 |
+ }); |
133 |
|
134 |
command_substitution returns[std::string libbash_value] |
135 |
@declarations { |
136 |
|
137 |
diff --git a/scripts/compound_command.bash b/scripts/compound_command.bash |
138 |
new file mode 100644 |
139 |
index 0000000..46d965d |
140 |
--- /dev/null |
141 |
+++ b/scripts/compound_command.bash |
142 |
@@ -0,0 +1,9 @@ |
143 |
+for file in " foo bar " |
144 |
+do |
145 |
+ echo $file |
146 |
+done |
147 |
+ |
148 |
+for foo in abc def ghi |
149 |
+do |
150 |
+ echo $foo |
151 |
+done |
152 |
|
153 |
diff --git a/scripts/compound_command.bash.result b/scripts/compound_command.bash.result |
154 |
new file mode 100644 |
155 |
index 0000000..cfdaac2 |
156 |
--- /dev/null |
157 |
+++ b/scripts/compound_command.bash.result |
158 |
@@ -0,0 +1,6 @@ |
159 |
+foo bar |
160 |
+abc |
161 |
+def |
162 |
+ghi |
163 |
+file= foo bar |
164 |
+foo=ghi |
165 |
|
166 |
diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp |
167 |
index 58b1495..2656e68 100644 |
168 |
--- a/src/core/interpreter.cpp |
169 |
+++ b/src/core/interpreter.cpp |
170 |
@@ -75,7 +75,9 @@ void interpreter::split_word(const std::string& word, std::vector<std::string>& |
171 |
if(trimmed == "") |
172 |
return; |
173 |
|
174 |
- boost::split(output, trimmed, boost::is_any_of(delimeter), boost::token_compress_on); |
175 |
+ std::vector<std::string> splitted_values; |
176 |
+ boost::split(splitted_values, trimmed, boost::is_any_of(delimeter), boost::token_compress_on); |
177 |
+ output.insert(output.end(), splitted_values.begin(), splitted_values.end()); |
178 |
} |
179 |
|
180 |
inline void define_function_arguments(std::unique_ptr<scope>& current_stack, |
181 |
|
182 |
diff --git a/src/core/interpreter.h b/src/core/interpreter.h |
183 |
index af81c49..9d14f7d 100644 |
184 |
--- a/src/core/interpreter.h |
185 |
+++ b/src/core/interpreter.h |
186 |
@@ -478,6 +478,13 @@ public: |
187 |
return new_value; |
188 |
} |
189 |
|
190 |
+ /// \brief set the return status of the last command |
191 |
+ /// \param the value of the return status |
192 |
+ void set_status(int status) |
193 |
+ { |
194 |
+ set_value("?", status); |
195 |
+ } |
196 |
+ |
197 |
/// \brief define a new global variable |
198 |
/// \param the name of the variable |
199 |
/// \param the value of the variable |
200 |
@@ -647,7 +654,7 @@ public: |
201 |
|
202 |
/// \brief implementation of word splitting |
203 |
/// \param the value of the word |
204 |
- //. \param[out] the splitted result |
205 |
+ //. \param[out] the splitted result will be appended to output |
206 |
void split_word(const std::string& word, std::vector<std::string>& output); |
207 |
|
208 |
/// \brief perform expansion like ${var//foo/bar} |
209 |
|
210 |
diff --git a/utils/variable_printer.cpp b/utils/variable_printer.cpp |
211 |
index ed4aa69..3e31a34 100644 |
212 |
--- a/utils/variable_printer.cpp |
213 |
+++ b/utils/variable_printer.cpp |
214 |
@@ -32,6 +32,11 @@ |
215 |
|
216 |
#include "libbash.h" |
217 |
|
218 |
+static const std::vector<std::string> special_variables |
219 |
+{ |
220 |
+ "IFS", "?" |
221 |
+}; |
222 |
+ |
223 |
int main(int argc, char** argv) |
224 |
{ |
225 |
if(argc != 2) |
226 |
@@ -45,7 +50,8 @@ int main(int argc, char** argv) |
227 |
|
228 |
std::map<std::string, std::vector<std::string>> sorted(variables.begin(), variables.end()); |
229 |
// Currently we don't need internal variables |
230 |
- sorted.erase("IFS"); |
231 |
+ for(auto iter = special_variables.begin(); iter != special_variables.end(); ++iter) |
232 |
+ sorted.erase(*iter); |
233 |
|
234 |
using namespace boost::spirit::karma; |
235 |
std::cout << format((string << '=' << -(string % ' ')) % eol, sorted) << std::endl; |