blob: 54ab3325ca6b3dd6e7584d9884f3299ee57ff95f [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 Xuc4447322017-03-06 14:44:59 -080043bool Evaluate(State* state, const std::unique_ptr<Expr>& expr, std::string* result) {
Tianjie Xuaced5d92016-10-12 10:55:04 -070044 if (result == nullptr) {
45 return false;
46 }
47
Tianjie Xuc4447322017-03-06 14:44:59 -080048 std::unique_ptr<Value> v(expr->fn(expr->name.c_str(), state, expr->argv));
Tianjie Xuaced5d92016-10-12 10:55:04 -070049 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
Tianjie Xuc4447322017-03-06 14:44:59 -080061Value* EvaluateValue(State* state, const std::unique_ptr<Expr>& expr) {
62 return expr->fn(expr->name.c_str(), state, 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
Tianjie Xuc4447322017-03-06 14:44:59 -080076Value* ConcatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
77 if (argv.empty()) {
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;
Tianjie Xuc4447322017-03-06 14:44:59 -080081 for (size_t i = 0; i < argv.size(); ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -070082 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
Tianjie Xuc4447322017-03-06 14:44:59 -080092Value* IfElseFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
93 if (argv.size() != 2 && argv.size() != 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]);
Tianjie Xuc4447322017-03-06 14:44:59 -0800105 } else if (argv.size() == 3) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700106 return EvaluateValue(state, argv[2]);
107 }
108
109 return StringValue("");
Doug Zongker37bee622009-06-08 17:35:39 -0700110}
111
Tianjie Xuc4447322017-03-06 14:44:59 -0800112Value* AbortFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700113 std::string msg;
Tianjie Xuc4447322017-03-06 14:44:59 -0800114 if (!argv.empty() && 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
Tianjie Xuc4447322017-03-06 14:44:59 -0800122Value* AssertFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
123 for (size_t i = 0; i < argv.size(); ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700124 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
Tianjie Xuc4447322017-03-06 14:44:59 -0800137Value* SleepFn(const char* name, State* state, const std::vector<std::unique_ptr<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
Tianjie Xuc4447322017-03-06 14:44:59 -0800152Value* StdoutFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
153 for (size_t i = 0; i < argv.size(); ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700154 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,
Tianjie Xuc4447322017-03-06 14:44:59 -0800164 const std::vector<std::unique_ptr<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,
Tianjie Xuc4447322017-03-06 14:44:59 -0800177 const std::vector<std::unique_ptr<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,
Tianjie Xuc4447322017-03-06 14:44:59 -0800190 const std::vector<std::unique_ptr<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,
Tianjie Xuc4447322017-03-06 14:44:59 -0800200 const std::vector<std::unique_ptr<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
Tianjie Xuc4447322017-03-06 14:44:59 -0800215Value* EqualityFn(const char* name, State* state, const std::vector<std::unique_ptr<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
Tianjie Xuc4447322017-03-06 14:44:59 -0800229Value* InequalityFn(const char* name, State* state,
230 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700231 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;
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700238 }
239
Tianjie Xuaced5d92016-10-12 10:55:04 -0700240 const char* result = (left != right) ? "t" : "";
Doug Zongker512536a2010-02-17 16:11:44 -0800241 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700242}
243
Tianjie Xuc4447322017-03-06 14:44:59 -0800244Value* SequenceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700245 std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
246 if (!left) {
247 return nullptr;
248 }
Doug Zongker512536a2010-02-17 16:11:44 -0800249 return EvaluateValue(state, argv[1]);
Doug Zongker37bee622009-06-08 17:35:39 -0700250}
251
Tianjie Xuc4447322017-03-06 14:44:59 -0800252Value* LessThanIntFn(const char* name, State* state,
253 const std::vector<std::unique_ptr<Expr>>& argv) {
254 if (argv.size() != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700255 state->errmsg = "less_than_int expects 2 arguments";
Tianjie Xuaced5d92016-10-12 10:55:04 -0700256 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700257 }
258
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700259 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800260 if (!ReadArgs(state, argv, &args)) {
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700261 return nullptr;
262 }
Doug Zongkere3da02e2009-06-12 16:13:52 -0700263
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700264 // Parse up to at least long long or 64-bit integers.
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700265 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;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700269 }
270
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700271 int64_t r_int;
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700272 if (!android::base::ParseInt(args[1].c_str(), &r_int)) {
273 state->errmsg = "failed to parse int in " + args[1];
274 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700275 }
276
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700277 return StringValue(l_int < r_int ? "t" : "");
Doug Zongkere3da02e2009-06-12 16:13:52 -0700278}
279
Doug Zongker512536a2010-02-17 16:11:44 -0800280Value* GreaterThanIntFn(const char* name, State* state,
Tianjie Xuc4447322017-03-06 14:44:59 -0800281 const std::vector<std::unique_ptr<Expr>>& argv) {
282 if (argv.size() != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700283 state->errmsg = "greater_than_int expects 2 arguments";
Tianjie Xuaced5d92016-10-12 10:55:04 -0700284 return nullptr;
Doug Zongkere3da02e2009-06-12 16:13:52 -0700285 }
286
Tianjie Xuc4447322017-03-06 14:44:59 -0800287 std::vector<std::string> args;
288 if (!ReadArgs(state, argv, &args)) {
289 return nullptr;
290 }
Doug Zongkere3da02e2009-06-12 16:13:52 -0700291
Tianjie Xuc4447322017-03-06 14:44:59 -0800292 // 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" : "");
Doug Zongkere3da02e2009-06-12 16:13:52 -0700306}
307
Tianjie Xuc4447322017-03-06 14:44:59 -0800308Value* Literal(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700309 return StringValue(name);
Doug Zongker37bee622009-06-08 17:35:39 -0700310}
311
Doug Zongker9931f7f2009-06-10 14:11:53 -0700312// -----------------------------------------------------------------
313// the function table
314// -----------------------------------------------------------------
315
Tao Bao39119ad2016-10-10 22:52:18 -0700316static std::unordered_map<std::string, Function> fn_table;
Doug Zongker37bee622009-06-08 17:35:39 -0700317
Tao Bao39119ad2016-10-10 22:52:18 -0700318void RegisterFunction(const std::string& name, Function fn) {
319 fn_table[name] = fn;
320}
321
322Function FindFunction(const std::string& name) {
323 if (fn_table.find(name) == fn_table.end()) {
324 return nullptr;
325 } else {
326 return fn_table[name];
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700327 }
Doug Zongker37bee622009-06-08 17:35:39 -0700328}
329
330void RegisterBuiltins() {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700331 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);
Doug Zongkere3da02e2009-06-12 16:13:52 -0700338
339 RegisterFunction("less_than_int", LessThanIntFn);
340 RegisterFunction("greater_than_int", GreaterThanIntFn);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700341}
342
343
344// -----------------------------------------------------------------
345// convenience methods for functions
346// -----------------------------------------------------------------
347
Tianjie Xuc4447322017-03-06 14:44:59 -0800348// 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.
350bool 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
355bool ReadArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
356 std::vector<std::string>* args, size_t start, size_t len) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700357 if (args == nullptr) {
358 return false;
359 }
Tianjie Xubf607c42017-03-23 15:12:22 -0700360 if (start + len > argv.size()) {
Tianjie Xuc4447322017-03-06 14:44:59 -0800361 return false;
362 }
363 for (size_t i = start; i < start + len; ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700364 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
Tianjie Xuc4447322017-03-06 14:44:59 -0800374// 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.
376bool ReadValueArgs(State* state, const std::vector<std::unique_ptr<Expr>>& argv,
Tianjie Xuaced5d92016-10-12 10:55:04 -0700377 std::vector<std::unique_ptr<Value>>* args) {
Tianjie Xuc4447322017-03-06 14:44:59 -0800378 return ReadValueArgs(state, argv, args, 0, argv.size());
379}
380
381bool 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) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700383 if (args == nullptr) {
384 return false;
385 }
Tianjie Xuc4447322017-03-06 14:44:59 -0800386 if (len == 0 || start + len > argv.size()) {
387 return false;
388 }
389 for (size_t i = start; i < start + len; ++i) {
Tianjie Xuaced5d92016-10-12 10:55:04 -0700390 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
Tianjie Xu16255832016-04-30 11:49:59 -0700400// Use printf-style arguments to compose an error message to put into
401// *state. Returns nullptr.
402Value* ErrorAbort(State* state, const char* format, ...) {
403 va_list ap;
404 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700405 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700406 va_end(ap);
407 return nullptr;
408}
409
410Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
411 va_list ap;
412 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700413 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700414 va_end(ap);
415 state->cause_code = cause_code;
416 return nullptr;
Doug Zongker47cace92009-06-18 10:11:50 -0700417}
Tao Bao59dcb9c2016-10-03 18:06:46 -0700418
419State::State(const std::string& script, void* cookie) :
420 script(script),
421 cookie(cookie) {
422}
423