Gentoo Archives: gentoo-commits

From: "Petteri Räty" <betelgeuse@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/libbash:master commit in: /, src/builtins/tests/, src/core/, src/, src/builtins/
Date: Sun, 03 Jul 2011 20:22:33
Message-Id: 2bd9927e275728d55698592cc7534b636d34f797.betelgeuse@gentoo
1 commit: 2bd9927e275728d55698592cc7534b636d34f797
2 Author: Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
3 AuthorDate: Thu Jun 23 09:46:16 2011 +0000
4 Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
5 CommitDate: Sun Jul 3 20:09:19 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=2bd9927e
7
8 Builtin: support shift built-in
9
10 ---
11 Makefile.am | 3 ++
12 src/builtins/shift_builtin.cpp | 44 +++++++++++++++++++++++
13 src/builtins/shift_builtin.h | 35 ++++++++++++++++++
14 src/builtins/tests/shift_tests.cpp | 69 ++++++++++++++++++++++++++++++++++++
15 src/core/interpreter.cpp | 9 +++++
16 src/core/interpreter.h | 5 +++
17 src/core/symbols.hpp | 29 +++++++++++++++
18 src/cppbash_builtin.cpp | 2 +
19 8 files changed, 196 insertions(+), 0 deletions(-)
20
21 diff --git a/Makefile.am b/Makefile.am
22 index fb36438..81ad4e1 100644
23 --- a/Makefile.am
24 +++ b/Makefile.am
25 @@ -109,6 +109,7 @@ cppunittests_SOURCES = test/run_tests.cpp \
26 src/builtins/tests/declare_tests.cpp \
27 src/builtins/tests/boolean_tests.cpp \
28 src/builtins/tests/source_tests.cpp \
29 + src/builtins/tests/shift_tests.cpp \
30 src/builtins/tests/shopt_tests.cpp \
31 src/builtins/tests/return_tests.cpp \
32 src/builtins/tests/printf_tests.cpp \
33 @@ -204,6 +205,8 @@ libcppbash_la_SOURCES = src/common.h \
34 src/builtins/boolean_builtins.h \
35 src/builtins/source_builtin.h \
36 src/builtins/source_builtin.cpp \
37 + src/builtins/shift_builtin.h \
38 + src/builtins/shift_builtin.cpp \
39 src/builtins/shopt_builtin.h \
40 src/builtins/shopt_builtin.cpp \
41 src/builtins/return_builtin.h \
42
43 diff --git a/src/builtins/shift_builtin.cpp b/src/builtins/shift_builtin.cpp
44 new file mode 100644
45 index 0000000..c78c6ae
46 --- /dev/null
47 +++ b/src/builtins/shift_builtin.cpp
48 @@ -0,0 +1,44 @@
49 +/*
50 + Please use git log for copyright holder and year information
51 +
52 + This file is part of libbash.
53 +
54 + libbash is free software: you can redistribute it and/or modify
55 + it under the terms of the GNU General Public License as published by
56 + the Free Software Foundation, either version 2 of the License, or
57 + (at your option) any later version.
58 +
59 + libbash is distributed in the hope that it will be useful,
60 + but WITHOUT ANY WARRANTY; without even the implied warranty of
61 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62 + GNU General Public License for more details.
63 +
64 + You should have received a copy of the GNU General Public License
65 + along with libbash. If not, see <http://www.gnu.org/licenses/>.
66 +*/
67 +///
68 +/// \file shift_builtin.h
69 +/// \brief implementation for the shift builtin
70 +///
71 +#include "builtins/shift_builtin.h"
72 +
73 +#include <boost/lexical_cast.hpp>
74 +
75 +#include "builtins/builtin_exceptions.h"
76 +#include "core/exceptions.h"
77 +#include "core/interpreter.h"
78 +
79 +int shift_builtin::exec(const std::vector<std::string>& bash_args)
80 +{
81 + int shift_number = 1;
82 +
83 + if(!bash_args.empty())
84 + {
85 + if(bash_args.size() != 1)
86 + throw libbash::illegal_argument_exception("shift: the number of arguments should be 1");
87 +
88 + shift_number = boost::lexical_cast<int>(bash_args[0]);
89 + }
90 +
91 + return _walker.shift(shift_number);
92 +}
93
94 diff --git a/src/builtins/shift_builtin.h b/src/builtins/shift_builtin.h
95 new file mode 100644
96 index 0000000..c413380
97 --- /dev/null
98 +++ b/src/builtins/shift_builtin.h
99 @@ -0,0 +1,35 @@
100 +/*
101 + Please use git log for copyright holder and year information
102 +
103 + This file is part of libbash.
104 +
105 + libbash is free software: you can redistribute it and/or modify
106 + it under the terms of the GNU General Public License as published by
107 + the Free Software Foundation, either version 2 of the License, or
108 + (at your option) any later version.
109 +
110 + libbash is distributed in the hope that it will be useful,
111 + but WITHOUT ANY WARRANTY; without even the implied warranty of
112 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
113 + GNU General Public License for more details.
114 +
115 + You should have received a copy of the GNU General Public License
116 + along with libbash. If not, see <http://www.gnu.org/licenses/>.
117 +*/
118 +///
119 +/// \file shift_builtin.h
120 +/// \brief implementation for the shift builtin
121 +///
122 +#ifndef LIBBASH_BUILTINS_SHIFT_BUILTIN_H_
123 +#define LIBBASH_BUILTINS_SHIFT_BUILTIN_H_
124 +
125 +#include "cppbash_builtin.h"
126 +
127 +class shift_builtin : public virtual cppbash_builtin
128 +{
129 +public:
130 + BUILTIN_CONSTRUCTOR(shift)
131 + virtual int exec(const std::vector<std::string>& );
132 +};
133 +
134 +#endif
135
136 diff --git a/src/builtins/tests/shift_tests.cpp b/src/builtins/tests/shift_tests.cpp
137 new file mode 100644
138 index 0000000..8625a6c
139 --- /dev/null
140 +++ b/src/builtins/tests/shift_tests.cpp
141 @@ -0,0 +1,69 @@
142 +/*
143 + Please use git log for copyright holder and year information
144 +
145 + This file is part of libbash.
146 +
147 + libbash is free software: you can redistribute it and/or modify
148 + it under the terms of the GNU General Public License as published by
149 + the Free Software Foundation, either version 2 of the License, or
150 + (at your option) any later version.
151 +
152 + libbash is distributed in the hope that it will be useful,
153 + but WITHOUT ANY WARRANTY; without even the implied warranty of
154 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155 + GNU General Public License for more details.
156 +
157 + You should have received a copy of the GNU General Public License
158 + along with libbash. If not, see <http://www.gnu.org/licenses/>.
159 +*/
160 +///
161 +/// \file shift_tests.cpp
162 +/// \brief series of unit tests for shift builtin
163 +///
164 +#include <boost/lexical_cast.hpp>
165 +#include <gtest/gtest.h>
166 +
167 +#include "core/exceptions.h"
168 +#include "core/interpreter.h"
169 +#include "cppbash_builtin.h"
170 +
171 +TEST(shift_builtin_test, bad_argument)
172 +{
173 + interpreter walker;
174 + std::map<unsigned, std::string> values = {{1, "1"}, {2, "2"}, {3, "3"}};
175 + walker.define("*", values);
176 +
177 + EXPECT_NE(0, cppbash_builtin::exec("shift", {"-1"}, std::cout, std::cerr, std::cin, walker));
178 + EXPECT_NE(0, cppbash_builtin::exec("shift", {"4"}, std::cout, std::cerr, std::cin, walker));
179 + EXPECT_THROW(cppbash_builtin::exec("shift", {"1", "2"}, std::cout, std::cerr, std::cin, walker),
180 + libbash::illegal_argument_exception);
181 + EXPECT_THROW(cppbash_builtin::exec("shift", {"abc"}, std::cout, std::cerr, std::cin, walker),
182 + boost::bad_lexical_cast);
183 +}
184 +
185 +TEST(shift_builtin_test, shift_all)
186 +{
187 + interpreter walker;
188 + std::map<unsigned, std::string> values = {{1, "1"}, {2, "2"}, {3, "3"}};
189 + walker.define("*", values);
190 +
191 + EXPECT_EQ(0, cppbash_builtin::exec("shift", {"3"}, std::cout, std::cerr, std::cin, walker));
192 + EXPECT_EQ(0, walker.get_array_length("*"));
193 +}
194 +
195 +TEST(shift_builtin_test, normal)
196 +{
197 + interpreter walker;
198 + std::map<unsigned, std::string> values = {{1, "1"}, {2, "2"}, {3, "3"}};
199 + walker.define("*", values);
200 +
201 + EXPECT_EQ(0, cppbash_builtin::exec("shift", {"2"}, std::cout, std::cerr, std::cin, walker));
202 + EXPECT_EQ(1, walker.get_array_length("*"));
203 + EXPECT_STREQ("3", walker.resolve<std::string>("*", 1).c_str());
204 +
205 + walker.define("*", values);
206 + EXPECT_EQ(0, cppbash_builtin::exec("shift", {"1"}, std::cout, std::cerr, std::cin, walker));
207 + EXPECT_EQ(2, walker.get_array_length("*"));
208 + EXPECT_STREQ("2", walker.resolve<std::string>("*", 1).c_str());
209 + EXPECT_STREQ("3", walker.resolve<std::string>("*", 2).c_str());
210 +}
211
212 diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
213 index ed9f626..bd19925 100644
214 --- a/src/core/interpreter.cpp
215 +++ b/src/core/interpreter.cpp
216 @@ -435,3 +435,12 @@ long interpreter::eval_arithmetic(const std::string& expression)
217 bash_ast ast(std::stringstream(expression), &bash_ast::parser_arithmetics);
218 return ast.interpret_with(*this, &bash_ast::walker_arithmetics);
219 }
220 +
221 +int interpreter::shift(int shift_number)
222 +{
223 + auto parameters = resolve_variable("*");
224 + if(shift_number < 0)
225 + return 1;
226 +
227 + return parameters->shift(static_cast<unsigned>(shift_number));
228 +}
229
230 diff --git a/src/core/interpreter.h b/src/core/interpreter.h
231 index c623e86..3363ae7 100644
232 --- a/src/core/interpreter.h
233 +++ b/src/core/interpreter.h
234 @@ -508,6 +508,11 @@ public:
235 /// \return the evaluated result
236 long eval_arithmetic(const std::string& expression);
237
238 + /// \brief shift the positional parameters to the left by n.
239 + /// \param the number to be shifted
240 + /// \return zero unless n is greater than $# or less than zero, non-zero otherwise.
241 + int shift(int shift_number);
242 +
243 /// \brief perform expansion like ${var//foo/bar}
244 /// \param value the value to be expanded
245 /// \param pattern the pattern used to match the value
246
247 diff --git a/src/core/symbols.hpp b/src/core/symbols.hpp
248 index c535f8f..5114df1 100644
249 --- a/src/core/symbols.hpp
250 +++ b/src/core/symbols.hpp
251 @@ -33,6 +33,7 @@
252
253 #include <boost/variant.hpp>
254 #include <boost/lexical_cast.hpp>
255 +#include <boost/numeric/conversion/cast.hpp>
256
257 #include "core/exceptions.h"
258
259 @@ -234,6 +235,34 @@ public:
260 {
261 return readonly;
262 }
263 +
264 + int shift(unsigned shift_number)
265 + {
266 + assert(!readonly&&"readonly variables shouldn't be shifted");
267 + // Remove this cast after making arithmetic expansion follow POSIX
268 + unsigned size = boost::numeric_cast<unsigned>(value.size());
269 +
270 + if(shift_number > size)
271 + {
272 + return 1;
273 + }
274 + else if(shift_number == size)
275 + {
276 + value.clear();
277 + }
278 + else
279 + {
280 + // copy elements
281 + for(unsigned i = shift_number + 1; i <= size; ++i)
282 + value[i - shift_number] = value[i];
283 +
284 + // remove tail elements
285 + for(unsigned i = size - shift_number + 1; i <= size; ++i)
286 + value.erase(i);
287 + }
288 +
289 + return 0;
290 + }
291 };
292
293 /// \brief the specialized constructor for arrays
294
295 diff --git a/src/cppbash_builtin.cpp b/src/cppbash_builtin.cpp
296 index 52c5c9b..3cf4d18 100644
297 --- a/src/cppbash_builtin.cpp
298 +++ b/src/cppbash_builtin.cpp
299 @@ -38,6 +38,7 @@
300 #include "builtins/let_builtin.h"
301 #include "builtins/return_builtin.h"
302 #include "builtins/printf_builtin.h"
303 +#include "builtins/shift_builtin.h"
304 #include "builtins/shopt_builtin.h"
305 #include "builtins/source_builtin.h"
306 #include "builtins/unset_builtin.h"
307 @@ -58,6 +59,7 @@ cppbash_builtin::builtins_type& cppbash_builtin::builtins() {
308 {"eval", boost::factory<eval_builtin*>()},
309 {"declare", boost::factory<declare_builtin*>()},
310 {"source", boost::factory<source_builtin*>()},
311 + {"shift", boost::factory<shift_builtin*>()},
312 {"shopt", boost::factory<shopt_builtin*>()},
313 {"inherit", boost::factory<inherit_builtin*>()},
314 {":", boost::factory<true_builtin*>()},