Home | History | Annotate | Download | only in edify
      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 
     31 int BooleanString(const char* s) {
     32     return s[0] != '\0';
     33 }
     34 
     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 
     48 Value* EvaluateValue(State* state, Expr* expr) {
     49     return expr->fn(expr->name, state, expr->argc, expr->argv);
     50 }
     51 
     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 
     61 void FreeValue(Value* v) {
     62     if (v == NULL) return;
     63     free(v->data);
     64     free(v);
     65 }
     66 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    321 Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
    322     return StringValue(strdup(name));
    323 }
    324 
    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 
    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 
    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 
    367 void FinishRegistration() {
    368     qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);
    369 }
    370 
    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 
    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.
    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.
    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.
    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.
    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.
    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