• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         printf("[%s] is not an int\n", left);
291         goto done;
292     }
293 
294     long r_int = strtol(right, &end, 10);
295     if (right[0] == '\0' || *end != '\0') {
296         printf("[%s] is not an int\n", right);
297         goto done;
298     }
299 
300     result = l_int < r_int;
301 
302   done:
303     free(left);
304     free(right);
305     return StringValue(strdup(result ? "t" : ""));
306 }
307 
GreaterThanIntFn(const char * name,State * state,int argc,Expr * argv[])308 Value* GreaterThanIntFn(const char* name, State* state,
309                         int argc, Expr* argv[]) {
310     if (argc != 2) {
311         free(state->errmsg);
312         state->errmsg = strdup("greater_than_int expects 2 arguments");
313         return NULL;
314     }
315 
316     Expr* temp[2];
317     temp[0] = argv[1];
318     temp[1] = argv[0];
319 
320     return LessThanIntFn(name, state, 2, temp);
321 }
322 
Literal(const char * name,State * state,int argc,Expr * argv[])323 Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
324     return StringValue(strdup(name));
325 }
326 
Build(Function fn,YYLTYPE loc,int count,...)327 Expr* Build(Function fn, YYLTYPE loc, int count, ...) {
328     va_list v;
329     va_start(v, count);
330     Expr* e = malloc(sizeof(Expr));
331     e->fn = fn;
332     e->name = "(operator)";
333     e->argc = count;
334     e->argv = malloc(count * sizeof(Expr*));
335     int i;
336     for (i = 0; i < count; ++i) {
337         e->argv[i] = va_arg(v, Expr*);
338     }
339     va_end(v);
340     e->start = loc.start;
341     e->end = loc.end;
342     return e;
343 }
344 
345 // -----------------------------------------------------------------
346 //   the function table
347 // -----------------------------------------------------------------
348 
349 static int fn_entries = 0;
350 static int fn_size = 0;
351 NamedFunction* fn_table = NULL;
352 
RegisterFunction(const char * name,Function fn)353 void RegisterFunction(const char* name, Function fn) {
354     if (fn_entries >= fn_size) {
355         fn_size = fn_size*2 + 1;
356         fn_table = realloc(fn_table, fn_size * sizeof(NamedFunction));
357     }
358     fn_table[fn_entries].name = name;
359     fn_table[fn_entries].fn = fn;
360     ++fn_entries;
361 }
362 
fn_entry_compare(const void * a,const void * b)363 static int fn_entry_compare(const void* a, const void* b) {
364     const char* na = ((const NamedFunction*)a)->name;
365     const char* nb = ((const NamedFunction*)b)->name;
366     return strcmp(na, nb);
367 }
368 
FinishRegistration()369 void FinishRegistration() {
370     qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
371 }
372 
FindFunction(const char * name)373 Function FindFunction(const char* name) {
374     NamedFunction key;
375     key.name = name;
376     NamedFunction* nf = bsearch(&key, fn_table, fn_entries,
377                                 sizeof(NamedFunction), fn_entry_compare);
378     if (nf == NULL) {
379         return NULL;
380     }
381     return nf->fn;
382 }
383 
RegisterBuiltins()384 void RegisterBuiltins() {
385     RegisterFunction("ifelse", IfElseFn);
386     RegisterFunction("abort", AbortFn);
387     RegisterFunction("assert", AssertFn);
388     RegisterFunction("concat", ConcatFn);
389     RegisterFunction("is_substring", SubstringFn);
390     RegisterFunction("stdout", StdoutFn);
391     RegisterFunction("sleep", SleepFn);
392 
393     RegisterFunction("less_than_int", LessThanIntFn);
394     RegisterFunction("greater_than_int", GreaterThanIntFn);
395 }
396 
397 
398 // -----------------------------------------------------------------
399 //   convenience methods for functions
400 // -----------------------------------------------------------------
401 
402 // Evaluate the expressions in argv, giving 'count' char* (the ... is
403 // zero or more char** to put them in).  If any expression evaluates
404 // to NULL, free the rest and return -1.  Return 0 on success.
ReadArgs(State * state,Expr * argv[],int count,...)405 int ReadArgs(State* state, Expr* argv[], int count, ...) {
406     char** args = malloc(count * sizeof(char*));
407     va_list v;
408     va_start(v, count);
409     int i;
410     for (i = 0; i < count; ++i) {
411         args[i] = Evaluate(state, argv[i]);
412         if (args[i] == NULL) {
413             va_end(v);
414             int j;
415             for (j = 0; j < i; ++j) {
416                 free(args[j]);
417             }
418             free(args);
419             return -1;
420         }
421         *(va_arg(v, char**)) = args[i];
422     }
423     va_end(v);
424     free(args);
425     return 0;
426 }
427 
428 // Evaluate the expressions in argv, giving 'count' Value* (the ... is
429 // zero or more Value** to put them in).  If any expression evaluates
430 // to NULL, free the rest and return -1.  Return 0 on success.
ReadValueArgs(State * state,Expr * argv[],int count,...)431 int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
432     Value** args = malloc(count * sizeof(Value*));
433     va_list v;
434     va_start(v, count);
435     int i;
436     for (i = 0; i < count; ++i) {
437         args[i] = EvaluateValue(state, argv[i]);
438         if (args[i] == NULL) {
439             va_end(v);
440             int j;
441             for (j = 0; j < i; ++j) {
442                 FreeValue(args[j]);
443             }
444             free(args);
445             return -1;
446         }
447         *(va_arg(v, Value**)) = args[i];
448     }
449     va_end(v);
450     free(args);
451     return 0;
452 }
453 
454 // Evaluate the expressions in argv, returning an array of char*
455 // results.  If any evaluate to NULL, free the rest and return NULL.
456 // The caller is responsible for freeing the returned array and the
457 // strings it contains.
ReadVarArgs(State * state,int argc,Expr * argv[])458 char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
459     char** args = (char**)malloc(argc * sizeof(char*));
460     int i = 0;
461     for (i = 0; i < argc; ++i) {
462         args[i] = Evaluate(state, argv[i]);
463         if (args[i] == NULL) {
464             int j;
465             for (j = 0; j < i; ++j) {
466                 free(args[j]);
467             }
468             free(args);
469             return NULL;
470         }
471     }
472     return args;
473 }
474 
475 // Evaluate the expressions in argv, returning an array of Value*
476 // results.  If any evaluate to NULL, free the rest and return NULL.
477 // The caller is responsible for freeing the returned array and the
478 // Values it contains.
ReadValueVarArgs(State * state,int argc,Expr * argv[])479 Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
480     Value** args = (Value**)malloc(argc * sizeof(Value*));
481     int i = 0;
482     for (i = 0; i < argc; ++i) {
483         args[i] = EvaluateValue(state, argv[i]);
484         if (args[i] == NULL) {
485             int j;
486             for (j = 0; j < i; ++j) {
487                 FreeValue(args[j]);
488             }
489             free(args);
490             return NULL;
491         }
492     }
493     return args;
494 }
495 
496 // Use printf-style arguments to compose an error message to put into
497 // *state.  Returns NULL.
ErrorAbort(State * state,const char * format,...)498 Value* ErrorAbort(State* state, const char* format, ...) {
499     char* buffer = malloc(4096);
500     va_list v;
501     va_start(v, format);
502     vsnprintf(buffer, 4096, format, v);
503     va_end(v);
504     free(state->errmsg);
505     state->errmsg = buffer;
506     return NULL;
507 }
508