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 <string.h>
18 #include <stdbool.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <unistd.h>
23 
24 #include "expr.h"
25 
26 // Functions should:
27 //
28 //    - return a malloc()'d string
29 //    - if Evaluate() on any argument returns NULL, return NULL.
30 
BooleanString(const char * s)31 int BooleanString(const char* s) {
32     return s[0] != '\0';
33 }
34 
Evaluate(State * state,Expr * expr)35 char* Evaluate(State* state, Expr* expr) {
36     Value* v = expr->fn(expr->name, state, expr->argc, expr->argv);
37     if (v == NULL) return NULL;
38     if (v->type != VAL_STRING) {
39         ErrorAbort(state, "expecting string, got value type %d", v->type);
40         FreeValue(v);
41         return NULL;
42     }
43     char* result = v->data;
44     free(v);
45     return result;
46 }
47 
EvaluateValue(State * state,Expr * expr)48 Value* EvaluateValue(State* state, Expr* expr) {
49     return expr->fn(expr->name, state, expr->argc, expr->argv);
50 }
51 
StringValue(char * str)52 Value* StringValue(char* str) {
53     if (str == NULL) return NULL;
54     Value* v = malloc(sizeof(Value));
55     v->type = VAL_STRING;
56     v->size = strlen(str);
57     v->data = str;
58     return v;
59 }
60 
FreeValue(Value * v)61 void FreeValue(Value* v) {
62     if (v == NULL) return;
63     free(v->data);
64     free(v);
65 }
66 
ConcatFn(const char * name,State * state,int argc,Expr * argv[])67 Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
68     if (argc == 0) {
69         return StringValue(strdup(""));
70     }
71     char** strings = malloc(argc * sizeof(char*));
72     int i;
73     for (i = 0; i < argc; ++i) {
74         strings[i] = NULL;
75     }
76     char* result = NULL;
77     int length = 0;
78     for (i = 0; i < argc; ++i) {
79         strings[i] = Evaluate(state, argv[i]);
80         if (strings[i] == NULL) {
81             goto done;
82         }
83         length += strlen(strings[i]);
84     }
85 
86     result = malloc(length+1);
87     int p = 0;
88     for (i = 0; i < argc; ++i) {
89         strcpy(result+p, strings[i]);
90         p += strlen(strings[i]);
91     }
92     result[p] = '\0';
93 
94   done:
95     for (i = 0; i < argc; ++i) {
96         free(strings[i]);
97     }
98     free(strings);
99     return StringValue(result);
100 }
101 
IfElseFn(const char * name,State * state,int argc,Expr * argv[])102 Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
103     if (argc != 2 && argc != 3) {
104         free(state->errmsg);
105         state->errmsg = strdup("ifelse expects 2 or 3 arguments");
106         return NULL;
107     }
108     char* cond = Evaluate(state, argv[0]);
109     if (cond == NULL) {
110         return NULL;
111     }
112 
113     if (BooleanString(cond) == true) {
114         free(cond);
115         return EvaluateValue(state, argv[1]);
116     } else {
117         if (argc == 3) {
118             free(cond);
119             return EvaluateValue(state, argv[2]);
120         } else {
121             return StringValue(cond);
122         }
123     }
124 }
125 
AbortFn(const char * name,State * state,int argc,Expr * argv[])126 Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
127     char* msg = NULL;
128     if (argc > 0) {
129         msg = Evaluate(state, argv[0]);
130     }
131     free(state->errmsg);
132     if (msg) {
133         state->errmsg = msg;
134     } else {
135         state->errmsg = strdup("called abort()");
136     }
137     return NULL;
138 }
139 
AssertFn(const char * name,State * state,int argc,Expr * argv[])140 Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
141     int i;
142     for (i = 0; i < argc; ++i) {
143         char* v = Evaluate(state, argv[i]);
144         if (v == NULL) {
145             return NULL;
146         }
147         int b = BooleanString(v);
148         free(v);
149         if (!b) {
150             int prefix_len;
151             int len = argv[i]->end - argv[i]->start;
152             char* err_src = malloc(len + 20);
153             strcpy(err_src, "assert failed: ");
154             prefix_len = strlen(err_src);
155             memcpy(err_src + prefix_len, state->script + argv[i]->start, len);
156             err_src[prefix_len + len] = '\0';
157             free(state->errmsg);
158             state->errmsg = err_src;
159             return NULL;
160         }
161     }
162     return StringValue(strdup(""));
163 }
164 
SleepFn(const char * name,State * state,int argc,Expr * argv[])165 Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
166     char* val = Evaluate(state, argv[0]);
167     if (val == NULL) {
168         return NULL;
169     }
170     int v = strtol(val, NULL, 10);
171     sleep(v);
172     return StringValue(val);
173 }
174 
StdoutFn(const char * name,State * state,int argc,Expr * argv[])175 Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
176     int i;
177     for (i = 0; i < argc; ++i) {
178         char* v = Evaluate(state, argv[i]);
179         if (v == NULL) {
180             return NULL;
181         }
182         fputs(v, stdout);
183         free(v);
184     }
185     return StringValue(strdup(""));
186 }
187 
LogicalAndFn(const char * name,State * state,int argc,Expr * argv[])188 Value* LogicalAndFn(const char* name, State* state,
189                    int argc, Expr* argv[]) {
190     char* left = Evaluate(state, argv[0]);
191     if (left == NULL) return NULL;
192     if (BooleanString(left) == true) {
193         free(left);
194         return EvaluateValue(state, argv[1]);
195     } else {
196         return StringValue(left);
197     }
198 }
199 
LogicalOrFn(const char * name,State * state,int argc,Expr * argv[])200 Value* LogicalOrFn(const char* name, State* state,
201                    int argc, Expr* argv[]) {
202     char* left = Evaluate(state, argv[0]);
203     if (left == NULL) return NULL;
204     if (BooleanString(left) == false) {
205         free(left);
206         return EvaluateValue(state, argv[1]);
207     } else {
208         return StringValue(left);
209     }
210 }
211 
LogicalNotFn(const char * name,State * state,int argc,Expr * argv[])212 Value* LogicalNotFn(const char* name, State* state,
213                     int argc, Expr* argv[]) {
214     char* val = Evaluate(state, argv[0]);
215     if (val == NULL) return NULL;
216     bool bv = BooleanString(val);
217     free(val);
218     return StringValue(strdup(bv ? "" : "t"));
219 }
220 
SubstringFn(const char * name,State * state,int argc,Expr * argv[])221 Value* SubstringFn(const char* name, State* state,
222                    int argc, Expr* argv[]) {
223     char* needle = Evaluate(state, argv[0]);
224     if (needle == NULL) return NULL;
225     char* haystack = Evaluate(state, argv[1]);
226     if (haystack == NULL) {
227         free(needle);
228         return NULL;
229     }
230 
231     char* result = strdup(strstr(haystack, needle) ? "t" : "");
232     free(needle);
233     free(haystack);
234     return StringValue(result);
235 }
236 
EqualityFn(const char * name,State * state,int argc,Expr * argv[])237 Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
238     char* left = Evaluate(state, argv[0]);
239     if (left == NULL) return NULL;
240     char* right = Evaluate(state, argv[1]);
241     if (right == NULL) {
242         free(left);
243         return NULL;
244     }
245 
246     char* result = strdup(strcmp(left, right) == 0 ? "t" : "");
247     free(left);
248     free(right);
249     return StringValue(result);
250 }
251 
InequalityFn(const char * name,State * state,int argc,Expr * argv[])252 Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
253     char* left = Evaluate(state, argv[0]);
254     if (left == NULL) return NULL;
255     char* right = Evaluate(state, argv[1]);
256     if (right == NULL) {
257         free(left);
258         return NULL;
259     }
260 
261     char* result = strdup(strcmp(left, right) != 0 ? "t" : "");
262     free(left);
263     free(right);
264     return StringValue(result);
265 }
266 
SequenceFn(const char * name,State * state,int argc,Expr * argv[])267 Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
268     Value* left = EvaluateValue(state, argv[0]);
269     if (left == NULL) return NULL;
270     FreeValue(left);
271     return EvaluateValue(state, argv[1]);
272 }
273 
LessThanIntFn(const char * name,State * state,int argc,Expr * argv[])274 Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
275     if (argc != 2) {
276         free(state->errmsg);
277         state->errmsg = strdup("less_than_int expects 2 arguments");
278         return NULL;
279     }
280 
281     char* left;
282     char* right;
283     if (ReadArgs(state, argv, 2, &left, &right) < 0) return NULL;
284 
285     bool result = false;
286     char* end;
287 
288     long l_int = strtol(left, &end, 10);
289     if (left[0] == '\0' || *end != '\0') {
290         goto done;
291     }
292 
293     long r_int = strtol(right, &end, 10);
294     if (right[0] == '\0' || *end != '\0') {
295         goto done;
296     }
297 
298     result = l_int < r_int;
299 
300   done:
301     free(left);
302     free(right);
303     return StringValue(strdup(result ? "t" : ""));
304 }
305 
GreaterThanIntFn(const char * name,State * state,int argc,Expr * argv[])306 Value* GreaterThanIntFn(const char* name, State* state,
307                         int argc, Expr* argv[]) {
308     if (argc != 2) {
309         free(state->errmsg);
310         state->errmsg = strdup("greater_than_int expects 2 arguments");
311         return NULL;
312     }
313 
314     Expr* temp[2];
315     temp[0] = argv[1];
316     temp[1] = argv[0];
317 
318     return LessThanIntFn(name, state, 2, temp);
319 }
320 
Literal(const char * name,State * state,int argc,Expr * argv[])321 Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
322     return StringValue(strdup(name));
323 }
324 
Build(Function fn,YYLTYPE loc,int count,...)325 Expr* Build(Function fn, YYLTYPE loc, int count, ...) {
326     va_list v;
327     va_start(v, count);
328     Expr* e = malloc(sizeof(Expr));
329     e->fn = fn;
330     e->name = "(operator)";
331     e->argc = count;
332     e->argv = malloc(count * sizeof(Expr*));
333     int i;
334     for (i = 0; i < count; ++i) {
335         e->argv[i] = va_arg(v, Expr*);
336     }
337     va_end(v);
338     e->start = loc.start;
339     e->end = loc.end;
340     return e;
341 }
342 
343 // -----------------------------------------------------------------
344 //   the function table
345 // -----------------------------------------------------------------
346 
347 static int fn_entries = 0;
348 static int fn_size = 0;
349 NamedFunction* fn_table = NULL;
350 
RegisterFunction(const char * name,Function fn)351 void RegisterFunction(const char* name, Function fn) {
352     if (fn_entries >= fn_size) {
353         fn_size = fn_size*2 + 1;
354         fn_table = realloc(fn_table, fn_size * sizeof(NamedFunction));
355     }
356     fn_table[fn_entries].name = name;
357     fn_table[fn_entries].fn = fn;
358     ++fn_entries;
359 }
360 
fn_entry_compare(const void * a,const void * b)361 static int fn_entry_compare(const void* a, const void* b) {
362     const char* na = ((const NamedFunction*)a)->name;
363     const char* nb = ((const NamedFunction*)b)->name;
364     return strcmp(na, nb);
365 }
366 
FinishRegistration()367 void FinishRegistration() {
368     qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
369 }
370 
FindFunction(const char * name)371 Function FindFunction(const char* name) {
372     NamedFunction key;
373     key.name = name;
374     NamedFunction* nf = bsearch(&key, fn_table, fn_entries,
375                                 sizeof(NamedFunction), fn_entry_compare);
376     if (nf == NULL) {
377         return NULL;
378     }
379     return nf->fn;
380 }
381 
RegisterBuiltins()382 void RegisterBuiltins() {
383     RegisterFunction("ifelse", IfElseFn);
384     RegisterFunction("abort", AbortFn);
385     RegisterFunction("assert", AssertFn);
386     RegisterFunction("concat", ConcatFn);
387     RegisterFunction("is_substring", SubstringFn);
388     RegisterFunction("stdout", StdoutFn);
389     RegisterFunction("sleep", SleepFn);
390 
391     RegisterFunction("less_than_int", LessThanIntFn);
392     RegisterFunction("greater_than_int", GreaterThanIntFn);
393 }
394 
395 
396 // -----------------------------------------------------------------
397 //   convenience methods for functions
398 // -----------------------------------------------------------------
399 
400 // Evaluate the expressions in argv, giving 'count' char* (the ... is
401 // zero or more char** to put them in).  If any expression evaluates
402 // to NULL, free the rest and return -1.  Return 0 on success.
ReadArgs(State * state,Expr * argv[],int count,...)403 int ReadArgs(State* state, Expr* argv[], int count, ...) {
404     char** args = malloc(count * sizeof(char*));
405     va_list v;
406     va_start(v, count);
407     int i;
408     for (i = 0; i < count; ++i) {
409         args[i] = Evaluate(state, argv[i]);
410         if (args[i] == NULL) {
411             va_end(v);
412             int j;
413             for (j = 0; j < i; ++j) {
414                 free(args[j]);
415             }
416             free(args);
417             return -1;
418         }
419         *(va_arg(v, char**)) = args[i];
420     }
421     va_end(v);
422     free(args);
423     return 0;
424 }
425 
426 // Evaluate the expressions in argv, giving 'count' Value* (the ... is
427 // zero or more Value** to put them in).  If any expression evaluates
428 // to NULL, free the rest and return -1.  Return 0 on success.
ReadValueArgs(State * state,Expr * argv[],int count,...)429 int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
430     Value** args = malloc(count * sizeof(Value*));
431     va_list v;
432     va_start(v, count);
433     int i;
434     for (i = 0; i < count; ++i) {
435         args[i] = EvaluateValue(state, argv[i]);
436         if (args[i] == NULL) {
437             va_end(v);
438             int j;
439             for (j = 0; j < i; ++j) {
440                 FreeValue(args[j]);
441             }
442             free(args);
443             return -1;
444         }
445         *(va_arg(v, Value**)) = args[i];
446     }
447     va_end(v);
448     free(args);
449     return 0;
450 }
451 
452 // Evaluate the expressions in argv, returning an array of char*
453 // results.  If any evaluate to NULL, free the rest and return NULL.
454 // The caller is responsible for freeing the returned array and the
455 // strings it contains.
ReadVarArgs(State * state,int argc,Expr * argv[])456 char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
457     char** args = (char**)malloc(argc * sizeof(char*));
458     int i = 0;
459     for (i = 0; i < argc; ++i) {
460         args[i] = Evaluate(state, argv[i]);
461         if (args[i] == NULL) {
462             int j;
463             for (j = 0; j < i; ++j) {
464                 free(args[j]);
465             }
466             free(args);
467             return NULL;
468         }
469     }
470     return args;
471 }
472 
473 // Evaluate the expressions in argv, returning an array of Value*
474 // results.  If any evaluate to NULL, free the rest and return NULL.
475 // The caller is responsible for freeing the returned array and the
476 // Values it contains.
ReadValueVarArgs(State * state,int argc,Expr * argv[])477 Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
478     Value** args = (Value**)malloc(argc * sizeof(Value*));
479     int i = 0;
480     for (i = 0; i < argc; ++i) {
481         args[i] = EvaluateValue(state, argv[i]);
482         if (args[i] == NULL) {
483             int j;
484             for (j = 0; j < i; ++j) {
485                 FreeValue(args[j]);
486             }
487             free(args);
488             return NULL;
489         }
490     }
491     return args;
492 }
493 
494 // Use printf-style arguments to compose an error message to put into
495 // *state.  Returns NULL.
ErrorAbort(State * state,const char * format,...)496 Value* ErrorAbort(State* state, const char* format, ...) {
497     char* buffer = malloc(4096);
498     va_list v;
499     va_start(v, format);
500     vsnprintf(buffer, 4096, format, v);
501     va_end(v);
502     free(state->errmsg);
503     state->errmsg = buffer;
504     return NULL;
505 }
506