1 /*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "expr.h"
18
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include <memory>
26 #include <string>
27 #include <unordered_map>
28 #include <vector>
29
30 #include <android-base/parseint.h>
31 #include <android-base/stringprintf.h>
32 #include <android-base/strings.h>
33
34 // Functions should:
35 //
36 // - return a malloc()'d string
37 // - if Evaluate() on any argument returns nullptr, return nullptr.
38
BooleanString(const std::string & s)39 static bool BooleanString(const std::string& s) {
40 return !s.empty();
41 }
42
Evaluate(State * state,const std::unique_ptr<Expr> & expr,std::string * result)43 bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) {
44 if (result == nullptr) {
45 return false;
46 }
47
48 std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv));
49 if (!v) {
50 return false;
51 }
52 if (v->type != VAL_STRING) {
53 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
54 return false;
55 }
56
57 *result = v->data;
58 return true;
59 }
60
EvaluateValue(State * state,const std::unique_ptr<Expr> & expr)61 Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) {
62 return expr->fn(expr->name.c_str(), state, expr->argv);
63 }
64
StringValue(const char * str)65 Value* StringValue(const char* str) {
66 if (str == nullptr) {
67 return nullptr;
68 }
69 return new Value(VAL_STRING, str);
70 }
71
StringValue(const std::string & str)72 Value* StringValue(const std::string& str) {
73 return StringValue(str.c_str());
74 }
75
ConcatFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)76 Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
77 if (argv.empty()) {
78 return StringValue("");
79 }
80 std::string result;
81 for (size_t i = 0; i < argv.size(); ++i) {
82 std::string str;
83 if (!Evaluate(state, argv[i], &str)) {
84 return nullptr;
85 }
86 result += str;
87 }
88
89 return StringValue(result);
90 }
91
IfElseFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)92 Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
93 if (argv.size() != 2 && argv.size() != 3) {
94 state->errmsg = "ifelse expects 2 or 3 arguments";
95 return nullptr;
96 }
97
98 std::string cond;
99 if (!Evaluate(state, argv[0], &cond)) {
100 return nullptr;
101 }
102
103 if (!cond.empty()) {
104 return EvaluateValue(state, argv[1]);
105 } else if (argv.size() == 3) {
106 return EvaluateValue(state, argv[2]);
107 }
108
109 return StringValue("");
110 }
111
AbortFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)112 Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
113 std::string msg;
114 if (!argv.empty() && Evaluate(state, argv[0], &msg)) {
115 state->errmsg = msg;
116 } else {
117 state->errmsg = "called abort()";
118 }
119 return nullptr;
120 }
121
AssertFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)122 Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
123 for (size_t i = 0; i < argv.size(); ++i) {
124 std::string result;
125 if (!Evaluate(state, argv[i], &result)) {
126 return nullptr;
127 }
128 if (result.empty()) {
129 int len = argv[i]->end - argv[i]->start;
130 state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
131 return nullptr;
132 }
133 }
134 return StringValue("");
135 }
136
SleepFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)137 Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
138 std::string val;
139 if (!Evaluate(state, argv[0], &val)) {
140 return nullptr;
141 }
142
143 int v;
144 if (!android::base::ParseInt(val.c_str(), &v, 0)) {
145 return nullptr;
146 }
147 sleep(v);
148
149 return StringValue(val);
150 }
151
StdoutFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)152 Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
153 for (size_t i = 0; i < argv.size(); ++i) {
154 std::string v;
155 if (!Evaluate(state, argv[i], &v)) {
156 return nullptr;
157 }
158 fputs(v.c_str(), stdout);
159 }
160 return StringValue("");
161 }
162
LogicalAndFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)163 Value* LogicalAndFn(const char* name, State* state,
164 const std::vector<std::unique_ptr<Expr>>& argv) {
165 std::string left;
166 if (!Evaluate(state, argv[0], &left)) {
167 return nullptr;
168 }
169 if (BooleanString(left)) {
170 return EvaluateValue(state, argv[1]);
171 } else {
172 return StringValue("");
173 }
174 }
175
LogicalOrFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)176 Value* LogicalOrFn(const char* name, State* state,
177 const std::vector<std::unique_ptr<Expr>>& argv) {
178 std::string left;
179 if (!Evaluate(state, argv[0], &left)) {
180 return nullptr;
181 }
182 if (!BooleanString(left)) {
183 return EvaluateValue(state, argv[1]);
184 } else {
185 return StringValue(left);
186 }
187 }
188
LogicalNotFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)189 Value* LogicalNotFn(const char* name, State* state,
190 const std::vector<std::unique_ptr<Expr>>& argv) {
191 std::string val;
192 if (!Evaluate(state, argv[0], &val)) {
193 return nullptr;
194 }
195
196 return StringValue(BooleanString(val) ? "" : "t");
197 }
198
SubstringFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)199 Value* SubstringFn(const char* name, State* state,
200 const std::vector<std::unique_ptr<Expr>>& argv) {
201 std::string needle;
202 if (!Evaluate(state, argv[0], &needle)) {
203 return nullptr;
204 }
205
206 std::string haystack;
207 if (!Evaluate(state, argv[1], &haystack)) {
208 return nullptr;
209 }
210
211 std::string result = (haystack.find(needle) != std::string::npos) ? "t" : "";
212 return StringValue(result);
213 }
214
EqualityFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)215 Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
216 std::string left;
217 if (!Evaluate(state, argv[0], &left)) {
218 return nullptr;
219 }
220 std::string right;
221 if (!Evaluate(state, argv[1], &right)) {
222 return nullptr;
223 }
224
225 const char* result = (left == right) ? "t" : "";
226 return StringValue(result);
227 }
228
InequalityFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)229 Value* InequalityFn(const char* name, State* state,
230 const std::vector<std::unique_ptr<Expr>>& argv) {
231 std::string left;
232 if (!Evaluate(state, argv[0], &left)) {
233 return nullptr;
234 }
235 std::string right;
236 if (!Evaluate(state, argv[1], &right)) {
237 return nullptr;
238 }
239
240 const char* result = (left != right) ? "t" : "";
241 return StringValue(result);
242 }
243
SequenceFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)244 Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
245 std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
246 if (!left) {
247 return nullptr;
248 }
249 return EvaluateValue(state, argv[1]);
250 }
251
LessThanIntFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)252 Value* LessThanIntFn(const char* name, State* state,
253 const std::vector<std::unique_ptr<Expr>>& argv) {
254 if (argv.size() != 2) {
255 state->errmsg = "less_than_int expects 2 arguments";
256 return nullptr;
257 }
258
259 std::vector<std::string> args;
260 if (!ReadArgs(state, argv, &args)) {
261 return nullptr;
262 }
263
264 // Parse up to at least long long or 64-bit integers.
265 int64_t l_int;
266 if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
267 state->errmsg = "failed to parse int in " + args[0];
268 return nullptr;
269 }
270
271 int64_t r_int;
272 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
273 state->errmsg = "failed to parse int in " + args[1];
274 return nullptr;
275 }
276
277 return StringValue(l_int < r_int ? "t" : "");
278 }
279
GreaterThanIntFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)280 Value* GreaterThanIntFn(const char* name, State* state,
281 const std::vector<std::unique_ptr<Expr>>& argv) {
282 if (argv.size() != 2) {
283 state->errmsg = "greater_than_int expects 2 arguments";
284 return nullptr;
285 }
286
287 std::vector<std::string> args;
288 if (!ReadArgs(state, argv, &args)) {
289 return nullptr;
290 }
291
292 // Parse up to at least long long or 64-bit integers.
293 int64_t l_int;
294 if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
295 state->errmsg = "failed to parse int in " + args[0];
296 return nullptr;
297 }
298
299 int64_t r_int;
300 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
301 state->errmsg = "failed to parse int in " + args[1];
302 return nullptr;
303 }
304
305 return StringValue(l_int > r_int ? "t" : "");
306 }
307
Literal(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)308 Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
309 return StringValue(name);
310 }
311
312 // -----------------------------------------------------------------
313 // the function table
314 // -----------------------------------------------------------------
315
316 static std::unordered_map<std::string, Function> fn_table;
317
RegisterFunction(const std::string & name,Function fn)318 void RegisterFunction(const std::string& name, Function fn) {
319 fn_table[name] = fn;
320 }
321
FindFunction(const std::string & name)322 Function FindFunction(const std::string& name) {
323 if (fn_table.find(name) == fn_table.end()) {
324 return nullptr;
325 } else {
326 return fn_table[name];
327 }
328 }
329
RegisterBuiltins()330 void RegisterBuiltins() {
331 RegisterFunction("ifelse", IfElseFn);
332 RegisterFunction("abort", AbortFn);
333 RegisterFunction("assert", AssertFn);
334 RegisterFunction("concat", ConcatFn);
335 RegisterFunction("is_substring", SubstringFn);
336 RegisterFunction("stdout", StdoutFn);
337 RegisterFunction("sleep", SleepFn);
338
339 RegisterFunction("less_than_int", LessThanIntFn);
340 RegisterFunction("greater_than_int", GreaterThanIntFn);
341 }
342
343
344 // -----------------------------------------------------------------
345 // convenience methods for functions
346 // -----------------------------------------------------------------
347
348 // Evaluate the expressions in argv, and put the results of strings in args. If any expression
349 // evaluates to nullptr, return false. Return true on success.
ReadArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::string> * args)350 bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
351 std::vector<std::string>* args) {
352 return ReadArgs(state, argv, args, 0, argv.size());
353 }
354
ReadArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::string> * args,size_t start,size_t len)355 bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
356 std::vector<std::string>* args, size_t start, size_t len) {
357 if (args == nullptr) {
358 return false;
359 }
360 if (start + len > argv.size()) {
361 return false;
362 }
363 for (size_t i = start; i < start + len; ++i) {
364 std::string var;
365 if (!Evaluate(state, argv[i], &var)) {
366 args->clear();
367 return false;
368 }
369 args->push_back(var);
370 }
371 return true;
372 }
373
374 // Evaluate the expressions in argv, and put the results of Value* in args. If any expression
375 // evaluate to nullptr, return false. Return true on success.
ReadValueArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::unique_ptr<Value>> * args)376 bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
377 std::vector<std::unique_ptr<Value>>* args) {
378 return ReadValueArgs(state, argv, args, 0, argv.size());
379 }
380
ReadValueArgs(State * state,const std::vector<std::unique_ptr<Expr>> & argv,std::vector<std::unique_ptr<Value>> * args,size_t start,size_t len)381 bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
382 std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) {
383 if (args == nullptr) {
384 return false;
385 }
386 if (len == 0 || start + len > argv.size()) {
387 return false;
388 }
389 for (size_t i = start; i < start + len; ++i) {
390 std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
391 if (!v) {
392 args->clear();
393 return false;
394 }
395 args->push_back(std::move(v));
396 }
397 return true;
398 }
399
400 // Use printf-style arguments to compose an error message to put into
401 // *state. Returns nullptr.
ErrorAbort(State * state,const char * format,...)402 Value* ErrorAbort(State* state, const char* format, ...) {
403 va_list ap;
404 va_start(ap, format);
405 android::base::StringAppendV(&state->errmsg, format, ap);
406 va_end(ap);
407 return nullptr;
408 }
409
ErrorAbort(State * state,CauseCode cause_code,const char * format,...)410 Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
411 va_list ap;
412 va_start(ap, format);
413 android::base::StringAppendV(&state->errmsg, format, ap);
414 va_end(ap);
415 state->cause_code = cause_code;
416 return nullptr;
417 }
418
State(const std::string & script,void * cookie)419 State::State(const std::string& script, void* cookie) :
420 script(script),
421 cookie(cookie) {
422 }
423
424