blob: 329cf3acdba0d4f28899bd10f44c484468c82492 [file] [log] [blame]
Doug Zongker37bee622009-06-08 17:35:39 -07001/*
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
Tao Bao39119ad2016-10-10 22:52:18 -070017#include "expr.h"
18
19#include <stdarg.h>
Doug Zongker37bee622009-06-08 17:35:39 -070020#include <stdio.h>
21#include <stdlib.h>
Tao Bao39119ad2016-10-10 22:52:18 -070022#include <string.h>
Doug Zongker9931f7f2009-06-10 14:11:53 -070023#include <unistd.h>
Doug Zongker37bee622009-06-08 17:35:39 -070024
Tianjie Xuaced5d92016-10-12 10:55:04 -070025#include <memory>
Tianjie Xu16255832016-04-30 11:49:59 -070026#include <string>
Tao Bao39119ad2016-10-10 22:52:18 -070027#include <unordered_map>
Tianjie Xuaced5d92016-10-12 10:55:04 -070028#include <vector>
Tianjie Xu16255832016-04-30 11:49:59 -070029
Tianjie Xuaced5d92016-10-12 10:55:04 -070030#include <android-base/parseint.h>
Tianjie Xu16255832016-04-30 11:49:59 -070031#include <android-base/stringprintf.h>
32#include <android-base/strings.h>
33
Doug Zongker37bee622009-06-08 17:35:39 -070034// Functions should:
35//
36// - return a malloc()'d string
Tianjie Xuaced5d92016-10-12 10:55:04 -070037// - if Evaluate() on any argument returns nullptr, return nullptr.
Doug Zongker37bee622009-06-08 17:35:39 -070038
Tianjie Xuaced5d92016-10-12 10:55:04 -070039static bool BooleanString(const std::string& s) {
40 return !s.empty();
Doug Zongker37bee622009-06-08 17:35:39 -070041}
42
Tianjie Xuaced5d92016-10-12 10:55:04 -070043bool Evaluate(State* state, Expr* expr, std::string* result) {
44 if (result == nullptr) {
45 return false;
46 }
47
48 std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv));
49 if (!v) {
50 return false;
51 }
Doug Zongker512536a2010-02-17 16:11:44 -080052 if (v->type != VAL_STRING) {
Tianjie Xu16255832016-04-30 11:49:59 -070053 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
Tianjie Xuaced5d92016-10-12 10:55:04 -070054 return false;
Doug Zongker512536a2010-02-17 16:11:44 -080055 }
Tianjie Xuaced5d92016-10-12 10:55:04 -070056
57 *result = v->data;
58 return true;
Doug Zongker512536a2010-02-17 16:11:44 -080059}
60
61Value* EvaluateValue(State* state, Expr* expr) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070062 return expr->fn(expr->name, state, expr->argc, expr->argv);
Doug Zongker37bee622009-06-08 17:35:39 -070063}
64
Tianjie Xuaced5d92016-10-12 10:55:04 -070065Value* StringValue(const char* str) {
66 if (str == nullptr) {
67 return nullptr;
68 }
69 return new Value(VAL_STRING, str);
Doug Zongker512536a2010-02-17 16:11:44 -080070}
71
Tianjie Xuaced5d92016-10-12 10:55:04 -070072Value* StringValue(const std::string& str) {
73 return StringValue(str.c_str());
Doug Zongker512536a2010-02-17 16:11:44 -080074}
75
76Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070077 if (argc == 0) {
Tianjie Xuaced5d92016-10-12 10:55:04 -070078 return StringValue("");
Doug Zongker37bee622009-06-08 17:35:39 -070079 }
Tianjie Xuaced5d92016-10-12 10:55:04 -070080 std::string result;
81 for (int i = 0; i < argc; ++i) {
82 std::string str;
83 if (!Evaluate(state, argv[i], &str)) {
84 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070085 }
Tianjie Xuaced5d92016-10-12 10:55:04 -070086 result += str;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070087 }
Doug Zongker37bee622009-06-08 17:35:39 -070088
Doug Zongker512536a2010-02-17 16:11:44 -080089 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -070090}
91
Doug Zongker512536a2010-02-17 16:11:44 -080092Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070093 if (argc != 2 && argc != 3) {
Tao Bao59dcb9c2016-10-03 18:06:46 -070094 state->errmsg = "ifelse expects 2 or 3 arguments";
Tianjie Xuaced5d92016-10-12 10:55:04 -070095 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070096 }
Doug Zongker37bee622009-06-08 17:35:39 -070097
Tianjie Xuaced5d92016-10-12 10:55:04 -070098 std::string cond;
99 if (!Evaluate(state, argv[0], &cond)) {
100 return nullptr;
Doug Zongker37bee622009-06-08 17:35:39 -0700101 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700102
103 if (!cond.empty()) {
104 return EvaluateValue(state, argv[1]);
105 } else if (argc == 3) {
106 return EvaluateValue(state, argv[2]);
107 }
108
109 return StringValue("");
Doug Zongker37bee622009-06-08 17:35:39 -0700110}
111
Doug Zongker512536a2010-02-17 16:11:44 -0800112Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700113 std::string msg;
114 if (argc > 0 && Evaluate(state, argv[0], &msg)) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700115 state->errmsg = msg;
116 } else {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700117 state->errmsg = "called abort()";
Doug Zongker37bee622009-06-08 17:35:39 -0700118 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700119 return nullptr;
Doug Zongker9931f7f2009-06-10 14:11:53 -0700120}
121
Doug Zongker512536a2010-02-17 16:11:44 -0800122Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700123 for (int i = 0; i < argc; ++i) {
124 std::string result;
125 if (!Evaluate(state, argv[i], &result)) {
126 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700127 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700128 if (result.empty()) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700129 int len = argv[i]->end - argv[i]->start;
Tao Bao59dcb9c2016-10-03 18:06:46 -0700130 state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
Tianjie Xuaced5d92016-10-12 10:55:04 -0700131 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700132 }
Doug Zongker37bee622009-06-08 17:35:39 -0700133 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700134 return StringValue("");
Doug Zongker37bee622009-06-08 17:35:39 -0700135}
136
Doug Zongker512536a2010-02-17 16:11:44 -0800137Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700138 std::string val;
139 if (!Evaluate(state, argv[0], &val)) {
140 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700141 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700142
143 int v;
144 if (!android::base::ParseInt(val.c_str(), &v, 0)) {
145 return nullptr;
146 }
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700147 sleep(v);
Tianjie Xuaced5d92016-10-12 10:55:04 -0700148
Doug Zongker512536a2010-02-17 16:11:44 -0800149 return StringValue(val);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700150}
151
Doug Zongker512536a2010-02-17 16:11:44 -0800152Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700153 for (int i = 0; i < argc; ++i) {
154 std::string v;
155 if (!Evaluate(state, argv[i], &v)) {
156 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700157 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700158 fputs(v.c_str(), stdout);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700159 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700160 return StringValue("");
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700161}
162
Doug Zongker512536a2010-02-17 16:11:44 -0800163Value* LogicalAndFn(const char* name, State* state,
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700164 int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700165 std::string left;
166 if (!Evaluate(state, argv[0], &left)) {
167 return nullptr;
168 }
169 if (BooleanString(left)) {
Doug Zongker512536a2010-02-17 16:11:44 -0800170 return EvaluateValue(state, argv[1]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700171 } else {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700172 return StringValue("");
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700173 }
174}
175
Doug Zongker512536a2010-02-17 16:11:44 -0800176Value* LogicalOrFn(const char* name, State* state,
177 int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700178 std::string left;
179 if (!Evaluate(state, argv[0], &left)) {
180 return nullptr;
181 }
182 if (!BooleanString(left)) {
Doug Zongker512536a2010-02-17 16:11:44 -0800183 return EvaluateValue(state, argv[1]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700184 } else {
Doug Zongker512536a2010-02-17 16:11:44 -0800185 return StringValue(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700186 }
187}
188
Doug Zongker512536a2010-02-17 16:11:44 -0800189Value* LogicalNotFn(const char* name, State* state,
190 int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700191 std::string val;
192 if (!Evaluate(state, argv[0], &val)) {
193 return nullptr;
194 }
195
196 return StringValue(BooleanString(val) ? "" : "t");
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700197}
198
Doug Zongker512536a2010-02-17 16:11:44 -0800199Value* SubstringFn(const char* name, State* state,
200 int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700201 std::string needle;
202 if (!Evaluate(state, argv[0], &needle)) {
203 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700204 }
205
Tianjie Xuaced5d92016-10-12 10:55:04 -0700206 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" : "";
Doug Zongker512536a2010-02-17 16:11:44 -0800212 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700213}
214
Doug Zongker512536a2010-02-17 16:11:44 -0800215Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700216 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;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700223 }
224
Tianjie Xuaced5d92016-10-12 10:55:04 -0700225 const char* result = (left == right) ? "t" : "";
Doug Zongker512536a2010-02-17 16:11:44 -0800226 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700227}
228
Doug Zongker512536a2010-02-17 16:11:44 -0800229Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700230 std::string left;
231 if (!Evaluate(state, argv[0], &left)) {
232 return nullptr;
233 }
234 std::string right;
235 if (!Evaluate(state, argv[1], &right)) {
236 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700237 }
238
Tianjie Xuaced5d92016-10-12 10:55:04 -0700239 const char* result = (left != right) ? "t" : "";
Doug Zongker512536a2010-02-17 16:11:44 -0800240 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700241}
242
Doug Zongker512536a2010-02-17 16:11:44 -0800243Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700244 std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
245 if (!left) {
246 return nullptr;
247 }
Doug Zongker512536a2010-02-17 16:11:44 -0800248 return EvaluateValue(state, argv[1]);
Doug Zongker37bee622009-06-08 17:35:39 -0700249}
250
Doug Zongker512536a2010-02-17 16:11:44 -0800251Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700252 if (argc != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700253 state->errmsg = "less_than_int expects 2 arguments";
Tianjie Xuaced5d92016-10-12 10:55:04 -0700254 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700255 }
256
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700257 std::vector<std::string> args;
258 if (!ReadArgs(state, 2, argv, &args)) {
259 return nullptr;
260 }
Doug Zongkere3da02e2009-06-12 16:13:52 -0700261
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700262 // Parse up to at least long long or 64-bit integers.
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700263 int64_t l_int;
264 if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
265 state->errmsg = "failed to parse int in " + args[0];
266 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700267 }
268
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700269 int64_t r_int;
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700270 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
271 state->errmsg = "failed to parse int in " + args[1];
272 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700273 }
274
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700275 return StringValue(l_int < r_int ? "t" : "");
Doug Zongkere3da02e2009-06-12 16:13:52 -0700276}
277
Doug Zongker512536a2010-02-17 16:11:44 -0800278Value* GreaterThanIntFn(const char* name, State* state,
279 int argc, Expr* argv[]) {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700280 if (argc != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700281 state->errmsg = "greater_than_int expects 2 arguments";
Tianjie Xuaced5d92016-10-12 10:55:04 -0700282 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700283 }
284
285 Expr* temp[2];
286 temp[0] = argv[1];
287 temp[1] = argv[0];
288
289 return LessThanIntFn(name, state, 2, temp);
290}
291
Doug Zongker512536a2010-02-17 16:11:44 -0800292Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700293 return StringValue(name);
Doug Zongker37bee622009-06-08 17:35:39 -0700294}
295
Doug Zongker9931f7f2009-06-10 14:11:53 -0700296// -----------------------------------------------------------------
297// the function table
298// -----------------------------------------------------------------
299
Tao Bao39119ad2016-10-10 22:52:18 -0700300static std::unordered_map<std::string, Function> fn_table;
Doug Zongker37bee622009-06-08 17:35:39 -0700301
Tao Bao39119ad2016-10-10 22:52:18 -0700302void RegisterFunction(const std::string& name, Function fn) {
303 fn_table[name] = fn;
304}
305
306Function FindFunction(const std::string& name) {
307 if (fn_table.find(name) == fn_table.end()) {
308 return nullptr;
309 } else {
310 return fn_table[name];
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700311 }
Doug Zongker37bee622009-06-08 17:35:39 -0700312}
313
314void RegisterBuiltins() {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700315 RegisterFunction("ifelse", IfElseFn);
316 RegisterFunction("abort", AbortFn);
317 RegisterFunction("assert", AssertFn);
318 RegisterFunction("concat", ConcatFn);
319 RegisterFunction("is_substring", SubstringFn);
320 RegisterFunction("stdout", StdoutFn);
321 RegisterFunction("sleep", SleepFn);
Doug Zongkere3da02e2009-06-12 16:13:52 -0700322
323 RegisterFunction("less_than_int", LessThanIntFn);
324 RegisterFunction("greater_than_int", GreaterThanIntFn);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700325}
326
327
328// -----------------------------------------------------------------
329// convenience methods for functions
330// -----------------------------------------------------------------
331
Tianjie Xuaced5d92016-10-12 10:55:04 -0700332// Evaluate the expressions in argv, and put the results of strings in
333// args. If any expression evaluates to nullptr, free the rest and return
334// false. Return true on success.
335bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) {
336 if (args == nullptr) {
337 return false;
338 }
339 for (int i = 0; i < argc; ++i) {
340 std::string var;
341 if (!Evaluate(state, argv[i], &var)) {
342 args->clear();
343 return false;
344 }
345 args->push_back(var);
346 }
347 return true;
348}
349
350// Evaluate the expressions in argv, and put the results of Value* in
351// args. If any expression evaluate to nullptr, free the rest and return
352// false. Return true on success.
353bool ReadValueArgs(State* state, int argc, Expr* argv[],
354 std::vector<std::unique_ptr<Value>>* args) {
355 if (args == nullptr) {
356 return false;
357 }
358 for (int i = 0; i < argc; ++i) {
359 std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
360 if (!v) {
361 args->clear();
362 return false;
363 }
364 args->push_back(std::move(v));
365 }
366 return true;
367}
368
Tianjie Xu16255832016-04-30 11:49:59 -0700369// Use printf-style arguments to compose an error message to put into
370// *state. Returns nullptr.
371Value* ErrorAbort(State* state, const char* format, ...) {
372 va_list ap;
373 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700374 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700375 va_end(ap);
376 return nullptr;
377}
378
379Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
380 va_list ap;
381 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700382 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700383 va_end(ap);
384 state->cause_code = cause_code;
385 return nullptr;
Doug Zongker47cace92009-06-18 10:11:50 -0700386}
Tao Bao59dcb9c2016-10-03 18:06:46 -0700387
388State::State(const std::string& script, void* cookie) :
389 script(script),
390 cookie(cookie) {
391}
392