blob: 4000bc4db4d723ce85c3a247844de347975be952 [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 Xu16255832016-04-30 11:49:59 -070025#include <string>
Tao Bao39119ad2016-10-10 22:52:18 -070026#include <unordered_map>
Tianjie Xu16255832016-04-30 11:49:59 -070027
28#include <android-base/stringprintf.h>
29#include <android-base/strings.h>
30
Doug Zongker37bee622009-06-08 17:35:39 -070031// Functions should:
32//
33// - return a malloc()'d string
34// - if Evaluate() on any argument returns NULL, return NULL.
35
36int BooleanString(const char* s) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070037 return s[0] != '\0';
Doug Zongker37bee622009-06-08 17:35:39 -070038}
39
Doug Zongkerd9c9d102009-06-12 12:24:39 -070040char* Evaluate(State* state, Expr* expr) {
Doug Zongker512536a2010-02-17 16:11:44 -080041 Value* v = expr->fn(expr->name, state, expr->argc, expr->argv);
42 if (v == NULL) return NULL;
43 if (v->type != VAL_STRING) {
Tianjie Xu16255832016-04-30 11:49:59 -070044 ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
Doug Zongker512536a2010-02-17 16:11:44 -080045 FreeValue(v);
46 return NULL;
47 }
48 char* result = v->data;
49 free(v);
50 return result;
51}
52
53Value* EvaluateValue(State* state, Expr* expr) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070054 return expr->fn(expr->name, state, expr->argc, expr->argv);
Doug Zongker37bee622009-06-08 17:35:39 -070055}
56
Doug Zongker512536a2010-02-17 16:11:44 -080057Value* StringValue(char* str) {
Doug Zongker5b695f32010-02-24 15:03:47 -080058 if (str == NULL) return NULL;
Tao Bao2a5a49d2015-08-20 12:10:46 -070059 Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value)));
Doug Zongker512536a2010-02-17 16:11:44 -080060 v->type = VAL_STRING;
61 v->size = strlen(str);
62 v->data = str;
63 return v;
64}
65
66void FreeValue(Value* v) {
67 if (v == NULL) return;
68 free(v->data);
69 free(v);
70}
71
72Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -070073 if (argc == 0) {
Doug Zongker512536a2010-02-17 16:11:44 -080074 return StringValue(strdup(""));
Doug Zongker37bee622009-06-08 17:35:39 -070075 }
Tao Bao2a5a49d2015-08-20 12:10:46 -070076 char** strings = reinterpret_cast<char**>(malloc(argc * sizeof(char*)));
Doug Zongkerd9c9d102009-06-12 12:24:39 -070077 int i;
78 for (i = 0; i < argc; ++i) {
79 strings[i] = NULL;
80 }
81 char* result = NULL;
82 int length = 0;
83 for (i = 0; i < argc; ++i) {
84 strings[i] = Evaluate(state, argv[i]);
85 if (strings[i] == NULL) {
86 goto done;
87 }
88 length += strlen(strings[i]);
89 }
Doug Zongker37bee622009-06-08 17:35:39 -070090
Tao Bao2a5a49d2015-08-20 12:10:46 -070091 result = reinterpret_cast<char*>(malloc(length+1));
92 int p;
93 p = 0;
Doug Zongkerd9c9d102009-06-12 12:24:39 -070094 for (i = 0; i < argc; ++i) {
95 strcpy(result+p, strings[i]);
96 p += strlen(strings[i]);
97 }
98 result[p] = '\0';
Doug Zongker37bee622009-06-08 17:35:39 -070099
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700100 done:
101 for (i = 0; i < argc; ++i) {
102 free(strings[i]);
103 }
Kenny Root21854cc2010-02-17 18:31:48 -0800104 free(strings);
Doug Zongker512536a2010-02-17 16:11:44 -0800105 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700106}
107
Doug Zongker512536a2010-02-17 16:11:44 -0800108Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700109 if (argc != 2 && argc != 3) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700110 state->errmsg = "ifelse expects 2 or 3 arguments";
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700111 return NULL;
112 }
113 char* cond = Evaluate(state, argv[0]);
114 if (cond == NULL) {
115 return NULL;
116 }
Doug Zongker37bee622009-06-08 17:35:39 -0700117
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700118 if (BooleanString(cond) == true) {
119 free(cond);
Doug Zongker512536a2010-02-17 16:11:44 -0800120 return EvaluateValue(state, argv[1]);
Doug Zongker37bee622009-06-08 17:35:39 -0700121 } else {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700122 if (argc == 3) {
123 free(cond);
Doug Zongker512536a2010-02-17 16:11:44 -0800124 return EvaluateValue(state, argv[2]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700125 } else {
Doug Zongker512536a2010-02-17 16:11:44 -0800126 return StringValue(cond);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700127 }
Doug Zongker37bee622009-06-08 17:35:39 -0700128 }
Doug Zongker37bee622009-06-08 17:35:39 -0700129}
130
Doug Zongker512536a2010-02-17 16:11:44 -0800131Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700132 char* msg = NULL;
133 if (argc > 0) {
134 msg = Evaluate(state, argv[0]);
Doug Zongker37bee622009-06-08 17:35:39 -0700135 }
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700136 if (msg) {
137 state->errmsg = msg;
138 } else {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700139 state->errmsg = "called abort()";
Doug Zongker37bee622009-06-08 17:35:39 -0700140 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700141 return NULL;
Doug Zongker9931f7f2009-06-10 14:11:53 -0700142}
143
Doug Zongker512536a2010-02-17 16:11:44 -0800144Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700145 int i;
146 for (i = 0; i < argc; ++i) {
147 char* v = Evaluate(state, argv[i]);
148 if (v == NULL) {
149 return NULL;
150 }
151 int b = BooleanString(v);
152 free(v);
153 if (!b) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700154 int len = argv[i]->end - argv[i]->start;
Tao Bao59dcb9c2016-10-03 18:06:46 -0700155 state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700156 return NULL;
157 }
Doug Zongker37bee622009-06-08 17:35:39 -0700158 }
Doug Zongker512536a2010-02-17 16:11:44 -0800159 return StringValue(strdup(""));
Doug Zongker37bee622009-06-08 17:35:39 -0700160}
161
Doug Zongker512536a2010-02-17 16:11:44 -0800162Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700163 char* val = Evaluate(state, argv[0]);
164 if (val == NULL) {
165 return NULL;
166 }
167 int v = strtol(val, NULL, 10);
168 sleep(v);
Doug Zongker512536a2010-02-17 16:11:44 -0800169 return StringValue(val);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700170}
171
Doug Zongker512536a2010-02-17 16:11:44 -0800172Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700173 int i;
174 for (i = 0; i < argc; ++i) {
175 char* v = Evaluate(state, argv[i]);
176 if (v == NULL) {
177 return NULL;
178 }
179 fputs(v, stdout);
180 free(v);
181 }
Doug Zongker512536a2010-02-17 16:11:44 -0800182 return StringValue(strdup(""));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700183}
184
Doug Zongker512536a2010-02-17 16:11:44 -0800185Value* LogicalAndFn(const char* name, State* state,
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700186 int argc, Expr* argv[]) {
187 char* left = Evaluate(state, argv[0]);
188 if (left == NULL) return NULL;
189 if (BooleanString(left) == true) {
190 free(left);
Doug Zongker512536a2010-02-17 16:11:44 -0800191 return EvaluateValue(state, argv[1]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700192 } else {
Doug Zongker512536a2010-02-17 16:11:44 -0800193 return StringValue(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700194 }
195}
196
Doug Zongker512536a2010-02-17 16:11:44 -0800197Value* LogicalOrFn(const char* name, State* state,
198 int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700199 char* left = Evaluate(state, argv[0]);
200 if (left == NULL) return NULL;
201 if (BooleanString(left) == false) {
202 free(left);
Doug Zongker512536a2010-02-17 16:11:44 -0800203 return EvaluateValue(state, argv[1]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700204 } else {
Doug Zongker512536a2010-02-17 16:11:44 -0800205 return StringValue(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700206 }
207}
208
Doug Zongker512536a2010-02-17 16:11:44 -0800209Value* LogicalNotFn(const char* name, State* state,
210 int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700211 char* val = Evaluate(state, argv[0]);
212 if (val == NULL) return NULL;
213 bool bv = BooleanString(val);
214 free(val);
Doug Zongker512536a2010-02-17 16:11:44 -0800215 return StringValue(strdup(bv ? "" : "t"));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700216}
217
Doug Zongker512536a2010-02-17 16:11:44 -0800218Value* SubstringFn(const char* name, State* state,
219 int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700220 char* needle = Evaluate(state, argv[0]);
221 if (needle == NULL) return NULL;
222 char* haystack = Evaluate(state, argv[1]);
223 if (haystack == NULL) {
224 free(needle);
225 return NULL;
226 }
227
228 char* result = strdup(strstr(haystack, needle) ? "t" : "");
Doug Zongker37bee622009-06-08 17:35:39 -0700229 free(needle);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700230 free(haystack);
Doug Zongker512536a2010-02-17 16:11:44 -0800231 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700232}
233
Doug Zongker512536a2010-02-17 16:11:44 -0800234Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700235 char* left = Evaluate(state, argv[0]);
236 if (left == NULL) return NULL;
237 char* right = Evaluate(state, argv[1]);
238 if (right == NULL) {
239 free(left);
240 return NULL;
241 }
242
243 char* result = strdup(strcmp(left, right) == 0 ? "t" : "");
Doug Zongker37bee622009-06-08 17:35:39 -0700244 free(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700245 free(right);
Doug Zongker512536a2010-02-17 16:11:44 -0800246 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700247}
248
Doug Zongker512536a2010-02-17 16:11:44 -0800249Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700250 char* left = Evaluate(state, argv[0]);
251 if (left == NULL) return NULL;
252 char* right = Evaluate(state, argv[1]);
253 if (right == NULL) {
254 free(left);
255 return NULL;
256 }
257
258 char* result = strdup(strcmp(left, right) != 0 ? "t" : "");
Doug Zongker37bee622009-06-08 17:35:39 -0700259 free(left);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700260 free(right);
Doug Zongker512536a2010-02-17 16:11:44 -0800261 return StringValue(result);
Doug Zongker37bee622009-06-08 17:35:39 -0700262}
263
Doug Zongker512536a2010-02-17 16:11:44 -0800264Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
265 Value* left = EvaluateValue(state, argv[0]);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700266 if (left == NULL) return NULL;
Doug Zongker512536a2010-02-17 16:11:44 -0800267 FreeValue(left);
268 return EvaluateValue(state, argv[1]);
Doug Zongker37bee622009-06-08 17:35:39 -0700269}
270
Doug Zongker512536a2010-02-17 16:11:44 -0800271Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700272 if (argc != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700273 state->errmsg = "less_than_int expects 2 arguments";
Doug Zongkere3da02e2009-06-12 16:13:52 -0700274 return NULL;
275 }
276
277 char* left;
278 char* right;
279 if (ReadArgs(state, argv, 2, &left, &right) < 0) return NULL;
280
281 bool result = false;
282 char* end;
283
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700284 // Parse up to at least long long or 64-bit integers.
285 int64_t l_int = static_cast<int64_t>(strtoll(left, &end, 10));
Doug Zongkere3da02e2009-06-12 16:13:52 -0700286 if (left[0] == '\0' || *end != '\0') {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700287 goto done;
288 }
289
Chih-Hung Hsieh54a27472016-04-18 11:30:55 -0700290 int64_t r_int;
291 r_int = static_cast<int64_t>(strtoll(right, &end, 10));
Doug Zongkere3da02e2009-06-12 16:13:52 -0700292 if (right[0] == '\0' || *end != '\0') {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700293 goto done;
294 }
295
296 result = l_int < r_int;
297
298 done:
299 free(left);
300 free(right);
Doug Zongker512536a2010-02-17 16:11:44 -0800301 return StringValue(strdup(result ? "t" : ""));
Doug Zongkere3da02e2009-06-12 16:13:52 -0700302}
303
Doug Zongker512536a2010-02-17 16:11:44 -0800304Value* GreaterThanIntFn(const char* name, State* state,
305 int argc, Expr* argv[]) {
Doug Zongkere3da02e2009-06-12 16:13:52 -0700306 if (argc != 2) {
Tao Bao59dcb9c2016-10-03 18:06:46 -0700307 state->errmsg = "greater_than_int expects 2 arguments";
Doug Zongkere3da02e2009-06-12 16:13:52 -0700308 return NULL;
309 }
310
311 Expr* temp[2];
312 temp[0] = argv[1];
313 temp[1] = argv[0];
314
315 return LessThanIntFn(name, state, 2, temp);
316}
317
Doug Zongker512536a2010-02-17 16:11:44 -0800318Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
319 return StringValue(strdup(name));
Doug Zongker37bee622009-06-08 17:35:39 -0700320}
321
Doug Zongker9931f7f2009-06-10 14:11:53 -0700322// -----------------------------------------------------------------
323// the function table
324// -----------------------------------------------------------------
325
Tao Bao39119ad2016-10-10 22:52:18 -0700326static std::unordered_map<std::string, Function> fn_table;
Doug Zongker37bee622009-06-08 17:35:39 -0700327
Tao Bao39119ad2016-10-10 22:52:18 -0700328void RegisterFunction(const std::string& name, Function fn) {
329 fn_table[name] = fn;
330}
331
332Function FindFunction(const std::string& name) {
333 if (fn_table.find(name) == fn_table.end()) {
334 return nullptr;
335 } else {
336 return fn_table[name];
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700337 }
Doug Zongker37bee622009-06-08 17:35:39 -0700338}
339
340void RegisterBuiltins() {
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700341 RegisterFunction("ifelse", IfElseFn);
342 RegisterFunction("abort", AbortFn);
343 RegisterFunction("assert", AssertFn);
344 RegisterFunction("concat", ConcatFn);
345 RegisterFunction("is_substring", SubstringFn);
346 RegisterFunction("stdout", StdoutFn);
347 RegisterFunction("sleep", SleepFn);
Doug Zongkere3da02e2009-06-12 16:13:52 -0700348
349 RegisterFunction("less_than_int", LessThanIntFn);
350 RegisterFunction("greater_than_int", GreaterThanIntFn);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700351}
352
353
354// -----------------------------------------------------------------
355// convenience methods for functions
356// -----------------------------------------------------------------
357
358// Evaluate the expressions in argv, giving 'count' char* (the ... is
359// zero or more char** to put them in). If any expression evaluates
360// to NULL, free the rest and return -1. Return 0 on success.
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700361int ReadArgs(State* state, Expr* argv[], int count, ...) {
Tao Bao2a5a49d2015-08-20 12:10:46 -0700362 char** args = reinterpret_cast<char**>(malloc(count * sizeof(char*)));
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700363 va_list v;
364 va_start(v, count);
365 int i;
366 for (i = 0; i < count; ++i) {
367 args[i] = Evaluate(state, argv[i]);
368 if (args[i] == NULL) {
369 va_end(v);
370 int j;
371 for (j = 0; j < i; ++j) {
372 free(args[j]);
373 }
Kenny Root21854cc2010-02-17 18:31:48 -0800374 free(args);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700375 return -1;
376 }
377 *(va_arg(v, char**)) = args[i];
Doug Zongker9931f7f2009-06-10 14:11:53 -0700378 }
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700379 va_end(v);
Kenny Root21854cc2010-02-17 18:31:48 -0800380 free(args);
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700381 return 0;
Doug Zongker9931f7f2009-06-10 14:11:53 -0700382}
383
Doug Zongker512536a2010-02-17 16:11:44 -0800384// Evaluate the expressions in argv, giving 'count' Value* (the ... is
385// zero or more Value** to put them in). If any expression evaluates
386// to NULL, free the rest and return -1. Return 0 on success.
387int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
Tao Bao2a5a49d2015-08-20 12:10:46 -0700388 Value** args = reinterpret_cast<Value**>(malloc(count * sizeof(Value*)));
Doug Zongker512536a2010-02-17 16:11:44 -0800389 va_list v;
390 va_start(v, count);
391 int i;
392 for (i = 0; i < count; ++i) {
393 args[i] = EvaluateValue(state, argv[i]);
394 if (args[i] == NULL) {
395 va_end(v);
396 int j;
397 for (j = 0; j < i; ++j) {
398 FreeValue(args[j]);
399 }
400 free(args);
401 return -1;
402 }
403 *(va_arg(v, Value**)) = args[i];
404 }
405 va_end(v);
406 free(args);
407 return 0;
408}
409
Doug Zongker9931f7f2009-06-10 14:11:53 -0700410// Evaluate the expressions in argv, returning an array of char*
411// results. If any evaluate to NULL, free the rest and return NULL.
412// The caller is responsible for freeing the returned array and the
413// strings it contains.
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700414char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
415 char** args = (char**)malloc(argc * sizeof(char*));
416 int i = 0;
417 for (i = 0; i < argc; ++i) {
418 args[i] = Evaluate(state, argv[i]);
419 if (args[i] == NULL) {
420 int j;
421 for (j = 0; j < i; ++j) {
422 free(args[j]);
423 }
424 free(args);
425 return NULL;
426 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700427 }
Doug Zongkerd9c9d102009-06-12 12:24:39 -0700428 return args;
Doug Zongker37bee622009-06-08 17:35:39 -0700429}
Doug Zongker47cace92009-06-18 10:11:50 -0700430
Doug Zongker512536a2010-02-17 16:11:44 -0800431// Evaluate the expressions in argv, returning an array of Value*
432// results. If any evaluate to NULL, free the rest and return NULL.
433// The caller is responsible for freeing the returned array and the
434// Values it contains.
435Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
436 Value** args = (Value**)malloc(argc * sizeof(Value*));
437 int i = 0;
438 for (i = 0; i < argc; ++i) {
439 args[i] = EvaluateValue(state, argv[i]);
440 if (args[i] == NULL) {
441 int j;
442 for (j = 0; j < i; ++j) {
443 FreeValue(args[j]);
444 }
445 free(args);
446 return NULL;
447 }
448 }
449 return args;
450}
451
Tianjie Xu16255832016-04-30 11:49:59 -0700452// Use printf-style arguments to compose an error message to put into
453// *state. Returns nullptr.
454Value* ErrorAbort(State* state, const char* format, ...) {
455 va_list ap;
456 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700457 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700458 va_end(ap);
459 return nullptr;
460}
461
462Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
463 va_list ap;
464 va_start(ap, format);
Tao Bao59dcb9c2016-10-03 18:06:46 -0700465 android::base::StringAppendV(&state->errmsg, format, ap);
Tianjie Xu16255832016-04-30 11:49:59 -0700466 va_end(ap);
467 state->cause_code = cause_code;
468 return nullptr;
Doug Zongker47cace92009-06-18 10:11:50 -0700469}
Tao Bao59dcb9c2016-10-03 18:06:46 -0700470
471State::State(const std::string& script, void* cookie) :
472 script(script),
473 cookie(cookie) {
474}
475