• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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