blob: 1b8623f03c2b0b7b3af18aad71fe5fd4c1b08558 [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 Baoe6f7f952017-10-04 09:33:01 -070017#include "edify/expr.h"
Tao Bao39119ad2016-10-10 22:52:18 -070018
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
Tao Bao1fc5bf32017-10-06 07:43:41 -070034#include "otautil/error_code.h"
Tao Bao0bf20d52017-10-05 12:06:49 -070035
Doug Zongker37bee622009-06-08 17:35:39 -070036// Functions should:
37//
38// - return a malloc()'d string
Tianjie Xuaced5d92016-10-12 10:55:04 -070039// - if Evaluate() on any argument returns nullptr, return nullptr.
Doug Zongker37bee622009-06-08 17:35:39 -070040
Tianjie Xuaced5d92016-10-12 10:55:04 -070041static bool BooleanString(const std::string& s) {
42 return !s.empty();
Doug Zongker37bee622009-06-08 17:35:39 -070043}
44
Tianjie Xuc4447322017-03-06 14:44:59 -080045bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) {
Tianjie Xuaced5d92016-10-12 10:55:04 -070046 if (result == nullptr) {
47 return false;
48 }
49
Tianjie Xuc4447322017-03-06 14:44:59 -080050 std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv));
Tianjie Xuaced5d92016-10-12 10:55:04 -070051 if (!v) {
52 return false;
53 }
Doug Zongker512536a2010-02-17 16:11:44 -080054 if (v->type != VAL_STRING) {
Tianjie Xu16255832016-04-30 11:49:59 -070055 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
Tianjie Xuaced5d92016-10-12 10:55:04 -070056 return false;
Doug Zongker512536a2010-02-17 16:11:44 -080057 }
Tianjie Xuaced5d92016-10-12 10:55:04 -070058
59 *result = v->data;
60 return true;
Doug Zongker512536a2010-02-17 16:11:44 -080061}
62
Tianjie Xuc4447322017-03-06 14:44:59 -080063Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) {
64 return expr->fn(expr->name.c_str(), state, expr->argv);
Doug Zongker37bee622009-06-08 17:35:39 -070065}
66
Tianjie Xuaced5d92016-10-12 10:55:04 -070067Value* StringValue(const char* str) {
68 if (str == nullptr) {
69 return nullptr;
70 }
71 return new Value(VAL_STRING, str);
Doug Zongker512536a2010-02-17 16:11:44 -080072}
73
Tianjie Xuaced5d92016-10-12 10:55:04 -070074Value* StringValue(const std::string& str) {
75 return StringValue(str.c_str());
Doug Zongker512536a2010-02-17 16:11:44 -080076}
77
Tianjie Xuc4447322017-03-06 14:44:59 -080078Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
79 if (argv.empty()) {
Tianjie Xuaced5d92016-10-12 10:55:04 -070080 return StringValue("");
Doug Zongker37bee622009-06-08 17:35:39 -070081 }
Tianjie Xuaced5d92016-10-12 10:55:04 -070082 std::string result;
Tianjie Xuc4447322017-03-06 14:44:59 -080083 for (size_t i = 0; i < argv.size(); ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -070084 std::string str;
85 if (!Evaluate(state, argv[i], &str)) {
86 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070087 }
Tianjie Xuaced5d92016-10-12 10:55:04 -070088 result += str;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070089 }
Doug Zongker37bee622009-06-08 17:35:39 -070090
Doug Zongker512536a2010-02-17 16:11:44 -080091 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -070092}
93
Tianjie Xuc4447322017-03-06 14:44:59 -080094Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
95 if (argv.size() != 2 && argv.size() != 3) {
Tao Bao59dcb9c2016-10-03 18:06:46 -070096 state->errmsg = "ifelse expects 2 or 3 arguments";
Tianjie Xuaced5d92016-10-12 10:55:04 -070097 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070098 }
Doug Zongker37bee622009-06-08 17:35:39 -070099
Tianjie Xuaced5d92016-10-12 10:55:04 -0700100 std::string cond;
101 if (!Evaluate(state, argv[0], &cond)) {
102 return nullptr;
Doug Zongker37bee622009-06-08 17:35:39 -0700103 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700104
105 if (!cond.empty()) {
106 return EvaluateValue(state, argv[1]);
Tianjie Xuc4447322017-03-06 14:44:59 -0800107 } else if (argv.size() == 3) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700108 return EvaluateValue(state, argv[2]);
109 }
110
111 return StringValue("");
Doug Zongker37bee622009-06-08 17:35:39 -0700112}
113
Tianjie Xuc4447322017-03-06 14:44:59 -0800114Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700115 std::string msg;
Tianjie Xuc4447322017-03-06 14:44:59 -0800116 if (!argv.empty() && Evaluate(state, argv[0], &msg)) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700117 state->errmsg = msg;
118 } else {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700119 state->errmsg = "called abort()";
Doug Zongker37bee622009-06-08 17:35:39 -0700120 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700121 return nullptr;
Doug Zongker9931f7f2009-06-10 14:11:53 -0700122}
123
Tianjie Xuc4447322017-03-06 14:44:59 -0800124Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
125 for (size_t i = 0; i < argv.size(); ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700126 std::string result;
127 if (!Evaluate(state, argv[i], &result)) {
128 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700129 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700130 if (result.empty()) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700131 int len = argv[i]->end - argv[i]->start;
Tao Bao59dcb9c2016-10-03 18:06:46 -0700132 state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
Tianjie Xuaced5d92016-10-12 10:55:04 -0700133 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700134 }
Doug Zongker37bee622009-06-08 17:35:39 -0700135 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700136 return StringValue("");
Doug Zongker37bee622009-06-08 17:35:39 -0700137}
138
Tianjie Xuc4447322017-03-06 14:44:59 -0800139Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700140 std::string val;
141 if (!Evaluate(state, argv[0], &val)) {
142 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700143 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700144
145 int v;
146 if (!android::base::ParseInt(val.c_str(), &v, 0)) {
147 return nullptr;
148 }
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700149 sleep(v);
Tianjie Xuaced5d92016-10-12 10:55:04 -0700150
Doug Zongker512536a2010-02-17 16:11:44 -0800151 return StringValue(val);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700152}
153
Tianjie Xuc4447322017-03-06 14:44:59 -0800154Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
155 for (size_t i = 0; i < argv.size(); ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700156 std::string v;
157 if (!Evaluate(state, argv[i], &v)) {
158 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700159 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700160 fputs(v.c_str(), stdout);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700161 }
Tianjie Xuaced5d92016-10-12 10:55:04 -0700162 return StringValue("");
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700163}
164
Doug Zongker512536a2010-02-17 16:11:44 -0800165Value* LogicalAndFn(const char* name, State* state,
Tianjie Xuc4447322017-03-06 14:44:59 -0800166 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700167 std::string left;
168 if (!Evaluate(state, argv[0], &left)) {
169 return nullptr;
170 }
171 if (BooleanString(left)) {
Doug Zongker512536a2010-02-17 16:11:44 -0800172 return EvaluateValue(state, argv[1]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700173 } else {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700174 return StringValue("");
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700175 }
176}
177
Doug Zongker512536a2010-02-17 16:11:44 -0800178Value* LogicalOrFn(const char* name, State* state,
Tianjie Xuc4447322017-03-06 14:44:59 -0800179 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700180 std::string left;
181 if (!Evaluate(state, argv[0], &left)) {
182 return nullptr;
183 }
184 if (!BooleanString(left)) {
Doug Zongker512536a2010-02-17 16:11:44 -0800185 return EvaluateValue(state, argv[1]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700186 } else {
Doug Zongker512536a2010-02-17 16:11:44 -0800187 return StringValue(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700188 }
189}
190
Doug Zongker512536a2010-02-17 16:11:44 -0800191Value* LogicalNotFn(const char* name, State* state,
Tianjie Xuc4447322017-03-06 14:44:59 -0800192 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700193 std::string val;
194 if (!Evaluate(state, argv[0], &val)) {
195 return nullptr;
196 }
197
198 return StringValue(BooleanString(val) ? "" : "t");
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700199}
200
Doug Zongker512536a2010-02-17 16:11:44 -0800201Value* SubstringFn(const char* name, State* state,
Tianjie Xuc4447322017-03-06 14:44:59 -0800202 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700203 std::string needle;
204 if (!Evaluate(state, argv[0], &needle)) {
205 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700206 }
207
Tianjie Xuaced5d92016-10-12 10:55:04 -0700208 std::string haystack;
209 if (!Evaluate(state, argv[1], &haystack)) {
210 return nullptr;
211 }
212
213 std::string result = (haystack.find(needle) != std::string::npos) ? "t" : "";
Doug Zongker512536a2010-02-17 16:11:44 -0800214 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700215}
216
Tianjie Xuc4447322017-03-06 14:44:59 -0800217Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700218 std::string left;
219 if (!Evaluate(state, argv[0], &left)) {
220 return nullptr;
221 }
222 std::string right;
223 if (!Evaluate(state, argv[1], &right)) {
224 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700225 }
226
Tianjie Xuaced5d92016-10-12 10:55:04 -0700227 const char* result = (left == right) ? "t" : "";
Doug Zongker512536a2010-02-17 16:11:44 -0800228 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700229}
230
Tianjie Xuc4447322017-03-06 14:44:59 -0800231Value* InequalityFn(const char* name, State* state,
232 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700233 std::string left;
234 if (!Evaluate(state, argv[0], &left)) {
235 return nullptr;
236 }
237 std::string right;
238 if (!Evaluate(state, argv[1], &right)) {
239 return nullptr;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700240 }
241
Tianjie Xuaced5d92016-10-12 10:55:04 -0700242 const char* result = (left != right) ? "t" : "";
Doug Zongker512536a2010-02-17 16:11:44 -0800243 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700244}
245
Tianjie Xuc4447322017-03-06 14:44:59 -0800246Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700247 std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
248 if (!left) {
249 return nullptr;
250 }
Doug Zongker512536a2010-02-17 16:11:44 -0800251 return EvaluateValue(state, argv[1]);
Doug Zongker37bee622009-06-08 17:35:39 -0700252}
253
Tianjie Xuc4447322017-03-06 14:44:59 -0800254Value* LessThanIntFn(const char* name, State* state,
255 const std::vector<std::unique_ptr<Expr>>& argv) {
256 if (argv.size() != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700257 state->errmsg = "less_than_int expects 2 arguments";
Tianjie Xuaced5d92016-10-12 10:55:04 -0700258 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700259 }
260
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700261 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800262 if (!ReadArgs(state, argv, &args)) {
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700263 return nullptr;
264 }
Doug Zongkere3da02e2009-06-12 16:13:52 -0700265
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700266 // Parse up to at least long long or 64-bit integers.
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700267 int64_t l_int;
268 if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
269 state->errmsg = "failed to parse int in " + args[0];
270 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700271 }
272
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700273 int64_t r_int;
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700274 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
275 state->errmsg = "failed to parse int in " + args[1];
276 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700277 }
278
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700279 return StringValue(l_int < r_int ? "t" : "");
Doug Zongkere3da02e2009-06-12 16:13:52 -0700280}
281
Doug Zongker512536a2010-02-17 16:11:44 -0800282Value* GreaterThanIntFn(const char* name, State* state,
Tianjie Xuc4447322017-03-06 14:44:59 -0800283 const std::vector<std::unique_ptr<Expr>>& argv) {
284 if (argv.size() != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700285 state->errmsg = "greater_than_int expects 2 arguments";
Tianjie Xuaced5d92016-10-12 10:55:04 -0700286 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700287 }
288
Tianjie Xuc4447322017-03-06 14:44:59 -0800289 std::vector<std::string> args;
290 if (!ReadArgs(state, argv, &args)) {
291 return nullptr;
292 }
Doug Zongkere3da02e2009-06-12 16:13:52 -0700293
Tianjie Xuc4447322017-03-06 14:44:59 -0800294 // Parse up to at least long long or 64-bit integers.
295 int64_t l_int;
296 if (!android::base::ParseInt(args[0].c_str(), &l_int)) {
297 state->errmsg = "failed to parse int in " + args[0];
298 return nullptr;
299 }
300
301 int64_t r_int;
302 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
303 state->errmsg = "failed to parse int in " + args[1];
304 return nullptr;
305 }
306
307 return StringValue(l_int > r_int ? "t" : "");
Doug Zongkere3da02e2009-06-12 16:13:52 -0700308}
309
Tianjie Xuc4447322017-03-06 14:44:59 -0800310Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700311 return StringValue(name);
Doug Zongker37bee622009-06-08 17:35:39 -0700312}
313
Doug Zongker9931f7f2009-06-10 14:11:53 -0700314// -----------------------------------------------------------------
315// the function table
316// -----------------------------------------------------------------
317
Tao Bao39119ad2016-10-10 22:52:18 -0700318static std::unordered_map<std::string, Function> fn_table;
Doug Zongker37bee622009-06-08 17:35:39 -0700319
Tao Bao39119ad2016-10-10 22:52:18 -0700320void RegisterFunction(const std::string& name, Function fn) {
321 fn_table[name] = fn;
322}
323
324Function FindFunction(const std::string& name) {
325 if (fn_table.find(name) == fn_table.end()) {
326 return nullptr;
327 } else {
328 return fn_table[name];
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700329 }
Doug Zongker37bee622009-06-08 17:35:39 -0700330}
331
332void RegisterBuiltins() {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700333 RegisterFunction("ifelse", IfElseFn);
334 RegisterFunction("abort", AbortFn);
335 RegisterFunction("assert", AssertFn);
336 RegisterFunction("concat", ConcatFn);
337 RegisterFunction("is_substring", SubstringFn);
338 RegisterFunction("stdout", StdoutFn);
339 RegisterFunction("sleep", SleepFn);
Doug Zongkere3da02e2009-06-12 16:13:52 -0700340
341 RegisterFunction("less_than_int", LessThanIntFn);
342 RegisterFunction("greater_than_int", GreaterThanIntFn);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700343}
344
345
346// -----------------------------------------------------------------
347// convenience methods for functions
348// -----------------------------------------------------------------
349
Tianjie Xuc4447322017-03-06 14:44:59 -0800350// Evaluate the expressions in argv, and put the results of strings in args. If any expression
351// evaluates to nullptr, return false. Return true on success.
352bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
353 std::vector<std::string>* args) {
354 return ReadArgs(state, argv, args, 0, argv.size());
355}
356
357bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
358 std::vector<std::string>* args, size_t start, size_t len) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700359 if (args == nullptr) {
360 return false;
361 }
Tianjie Xubf607c42017-03-23 15:12:22 -0700362 if (start + len > argv.size()) {
Tianjie Xuc4447322017-03-06 14:44:59 -0800363 return false;
364 }
365 for (size_t i = start; i < start + len; ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700366 std::string var;
367 if (!Evaluate(state, argv[i], &var)) {
368 args->clear();
369 return false;
370 }
371 args->push_back(var);
372 }
373 return true;
374}
375
Tianjie Xuc4447322017-03-06 14:44:59 -0800376// Evaluate the expressions in argv, and put the results of Value* in args. If any expression
377// evaluate to nullptr, return false. Return true on success.
378bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
Tianjie Xuaced5d92016-10-12 10:55:04 -0700379 std::vector<std::unique_ptr<Value>>* args) {
Tianjie Xuc4447322017-03-06 14:44:59 -0800380 return ReadValueArgs(state, argv, args, 0, argv.size());
381}
382
383bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
384 std::vector<std::unique_ptr<Value>>* args, size_t start, size_t len) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700385 if (args == nullptr) {
386 return false;
387 }
Tianjie Xuc4447322017-03-06 14:44:59 -0800388 if (len == 0 || start + len > argv.size()) {
389 return false;
390 }
391 for (size_t i = start; i < start + len; ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700392 std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
393 if (!v) {
394 args->clear();
395 return false;
396 }
397 args->push_back(std::move(v));
398 }
399 return true;
400}
401
Tianjie Xu16255832016-04-30 11:49:59 -0700402// Use printf-style arguments to compose an error message to put into
403// *state. Returns nullptr.
404Value* ErrorAbort(State* state, const char* format, ...) {
405 va_list ap;
406 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700407 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700408 va_end(ap);
409 return nullptr;
410}
411
412Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
413 va_list ap;
414 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700415 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700416 va_end(ap);
417 state->cause_code = cause_code;
418 return nullptr;
Doug Zongker47cace92009-06-18 10:11:50 -0700419}
Tao Bao59dcb9c2016-10-03 18:06:46 -0700420
Tao Bao0bf20d52017-10-05 12:06:49 -0700421State::State(const std::string& script, void* cookie)
422 : script(script), cookie(cookie), error_code(kNoError), cause_code(kNoCause) {}