15d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 25d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang * Use of this source code is governed by a BSD-style license that can be 35d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang * found in the LICENSE file. 45d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang */ 55d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 65d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang#include <ctype.h> 75d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang#include <stdlib.h> 85d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang#include <syslog.h> 95d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 105d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang#include "array.h" 115d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang#include "cras_expr.h" 125d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 135d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic const char *copy_str(const char *begin, const char *end) 145d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 155d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang char *s = malloc(end - begin + 1); 165d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang memcpy(s, begin, end - begin); 175d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang s[end - begin] = '\0'; 185d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return s; 195d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 205d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 215d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void value_set_boolean(struct cras_expr_value *value, char boolean) 225d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 235d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(value); 245d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->type = CRAS_EXPR_VALUE_TYPE_BOOLEAN; 255d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.boolean = !!boolean; 265d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 275d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 285d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void value_set_integer(struct cras_expr_value *value, int integer) 295d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 305d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(value); 315d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->type = CRAS_EXPR_VALUE_TYPE_INT; 325d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.integer = integer; 335d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 345d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 355d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void value_set_string2(struct cras_expr_value *value, const char *begin, 365d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *end) 375d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 385d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(value); 395d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->type = CRAS_EXPR_VALUE_TYPE_STRING; 405d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.string = copy_str(begin, end); 415d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 425d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 435d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void value_set_string(struct cras_expr_value *value, const char *str) 445d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 455d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_string2(value, str, str + strlen(str)); 465d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 475d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 485d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void cras_expr_value_set_function(struct cras_expr_value *value, 495d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_function_type function) 505d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 515d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(value); 525d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->type = CRAS_EXPR_VALUE_TYPE_FUNCTION; 535d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.function = function; 545d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 555d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 565d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void copy_value(struct cras_expr_value *value, 575d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *original) 585d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 595d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(value); /* free the original value first */ 605d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->type = original->type; 615d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang switch (value->type) { 625d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_NONE: 635d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 645d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_BOOLEAN: 655d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.boolean = original->u.boolean; 665d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 675d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_INT: 685d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.integer = original->u.integer; 695d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 705d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_STRING: 715d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.string = strdup(original->u.string); 725d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 735d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_FUNCTION: 745d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.function = original->u.function; 755d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 765d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 775d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 785d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 795d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_value_free(struct cras_expr_value *value) 805d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 815d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang switch (value->type) { 825d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_STRING: 835d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang free((char *)value->u.string); 845d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.string = NULL; 855d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 865d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_NONE: 875d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_BOOLEAN: 885d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_INT: 895d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_FUNCTION: 905d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 915d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 925d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->type = CRAS_EXPR_VALUE_TYPE_NONE; 935d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 945d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 955d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_value_dump(struct dumper *d, const struct cras_expr_value *value) 965d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 975d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang switch (value->type) { 985d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_NONE: 995d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "none"); 1005d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 1015d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_BOOLEAN: 1025d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "boolean(%s)", 1035d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.boolean ? "true" : "false"); 1045d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 1055d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_INT: 1065d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "integer(%d)", value->u.integer); 1075d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 1085d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_STRING: 1095d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "string(%s)", value->u.string); 1105d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 1115d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_FUNCTION: 1125d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "function(%p)", value->u.function); 1135d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 1145d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 1155d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 1165d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1175d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_value *find_value(struct cras_expr_env *env, 1185d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *name) 1195d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 1205d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 1215d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char **key; 1225d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1235d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(&env->keys, i, key) { 1245d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (strcmp(*key, name) == 0) 1255d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return ARRAY_ELEMENT(&env->values, i); 1265d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 1275d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return NULL; 1285d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 1295d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1305d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang/* Insert a (key, value) pair to the environment. The value is 1315d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang * initialized to zero. Return the pointer to value so it can be set 1325d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang * to the proper value. */ 1335d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_value *insert_value(struct cras_expr_env *env, 1345d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *key) 1355d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 1365d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang *ARRAY_APPEND_ZERO(&env->keys) = strdup(key); 1375d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return ARRAY_APPEND_ZERO(&env->values); 1385d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 1395d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1405d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_value *find_or_insert_value(struct cras_expr_env *env, 1415d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *key) 1425d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 1435d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value = find_value(env, key); 1445d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (!value) 1455d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value = insert_value(env, key); 1465d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return value; 1475d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 1485d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1495d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void function_not(cras_expr_value_array *operands, 1505d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *result) 1515d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 1525d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value; 1535d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int is_false; 1545d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1555d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (ARRAY_COUNT(operands) != 2) { 1565d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(result); 1575d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, "not takes one argument"); 1585d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return; 1595d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 1605d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1615d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value = ARRAY_ELEMENT(operands, 1); 1625d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang is_false = (value->type == CRAS_EXPR_VALUE_TYPE_BOOLEAN && 1635d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang !value->u.boolean); 1645d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_boolean(result, is_false); 1655d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 1665d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1675d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void function_and(cras_expr_value_array *operands, 1685d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *result) 1695d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 1705d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 1715d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value; 1725d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int n = ARRAY_COUNT(operands); 1735d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1745d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* no operands -- return #t */ 1755d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (n <= 1) { 1765d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_boolean(result, 1); 1775d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return; 1785d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 1795d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1805d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* if there is any #f, return it */ 1815d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(operands, i, value) { 1825d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (i == 0) 1835d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang continue; /* ignore "and" itself */ 184903b1c1c5eeb2ffc1bb8c6c000abf8af0b0d086eChih-Chung Chang if (value->type == CRAS_EXPR_VALUE_TYPE_BOOLEAN && 1855d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang !value->u.boolean) { 1865d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_boolean(result, 0); 1875d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return; 1885d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 1895d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 1905d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1915d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* otherwise return the last element */ 1925d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang copy_value(result, ARRAY_ELEMENT(operands, n - 1)); 1935d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 1945d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 1955d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void function_or(cras_expr_value_array *operands, 1965d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *result) 1975d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 1985d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 1995d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value; 2005d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2015d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(operands, i, value) { 2025d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (i == 0) 2035d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang continue; /* ignore "or" itself */ 2045d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (value->type != CRAS_EXPR_VALUE_TYPE_BOOLEAN || 2055d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.boolean) { 2065d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang copy_value(result, value); 2075d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return; 2085d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 2095d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 2105d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2115d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_boolean(result, 0); 2125d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 2135d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2145d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic char function_equal_real(cras_expr_value_array *operands) 2155d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 2165d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 2175d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value, *prev; 2185d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2195d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(operands, i, value) { 2205d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (i <= 1) 2215d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang continue; /* ignore equal? and first operand */ 2225d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* compare with the previous operand */ 2235d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2245d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang prev = ARRAY_ELEMENT(operands, i - 1); 2255d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2265d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (prev->type != value->type) 2275d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 0; 2285d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2295d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang switch (prev->type) { 2305d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_NONE: 2315d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 2325d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_BOOLEAN: 2335d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (prev->u.boolean != value->u.boolean) 2345d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 0; 2355d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 2365d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_INT: 2375d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (prev->u.integer != value->u.integer) 2385d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 0; 2395d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 2405d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_STRING: 2415d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (strcmp(prev->u.string, value->u.string) != 0) 2425d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 0; 2435d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 2445d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_FUNCTION: 2455d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (prev->u.function != value->u.function) 2465d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 0; 2475d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 2485d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 2495d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 2505d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2515d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 1; 2525d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 2535d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2545d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void function_equal(cras_expr_value_array *operands, 2555d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *result) 2565d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 2575d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_boolean(result, function_equal_real(operands)); 2585d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 2595d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2605d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void env_set_variable(struct cras_expr_env *env, const char *name, 2615d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *new_value) 2625d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 2635d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value = find_or_insert_value(env, name); 2645d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang copy_value(value, new_value); 2655d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 2665d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2675d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_env_install_builtins(struct cras_expr_env *env) 2685d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 2695d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value value = CRAS_EXPR_VALUE_INIT; 2705d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2715d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* initialize env with builtin functions */ 2725d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_set_function(&value, &function_not); 2735d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang env_set_variable(env, "not", &value); 2745d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2755d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_set_function(&value, &function_and); 2765d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang env_set_variable(env, "and", &value); 2775d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2785d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_set_function(&value, &function_or); 2795d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang env_set_variable(env, "or", &value); 2805d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2815d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_set_function(&value, &function_equal); 2825d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang env_set_variable(env, "equal?", &value); 2835d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2845d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(&value); 2855d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 2865d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2875d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_env_set_variable_boolean(struct cras_expr_env *env, 2885d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *name, char boolean) 2895d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 2905d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value = find_or_insert_value(env, name); 2915d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_boolean(value, boolean); 2925d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 2935d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 2945d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_env_set_variable_integer(struct cras_expr_env *env, 2955d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *name, int integer) 2965d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 2975d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value = find_or_insert_value(env, name); 2985d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_integer(value, integer); 2995d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3005d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3015d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_env_set_variable_string(struct cras_expr_env *env, 3025d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *name, const char *str) 3035d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3045d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value = find_or_insert_value(env, name); 3055d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_string(value, str); 3065d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3075d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3085d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_env_free(struct cras_expr_env *env) 3095d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3105d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 3115d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char **key; 3125d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value; 3135d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3145d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(&env->keys, i, key) { 3155d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang free((char *)*key); 3165d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 3175d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3185d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(&env->values, i, value) { 3195d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(value); 3205d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 3215d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3225d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang ARRAY_FREE(&env->keys); 3235d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang ARRAY_FREE(&env->values); 3245d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3255d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3265d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_env_dump(struct dumper *d, const struct cras_expr_env *env) 3275d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3285d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 3295d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char **key; 3305d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value; 3315d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3325d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "--- environment ---\n"); 3335d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(&env->keys, i, key) { 3345d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, " key=%s,", *key); 3355d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, " value="); 3365d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value = ARRAY_ELEMENT(&env->values, i); 3375d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_dump(d, value); 3385d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "\n"); 3395d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 3405d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3415d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3425d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_expression *new_boolean_literal(char boolean) 3435d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3445d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression *expr; 3455d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr = calloc(1, sizeof(struct cras_expr_expression)); 3465d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->type = EXPR_TYPE_LITERAL; 3475d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_boolean(&expr->u.literal, boolean); 3485d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return expr; 3495d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3505d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3515d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_expression *new_integer_literal(int integer) 3525d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3535d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression *expr; 3545d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr = calloc(1, sizeof(struct cras_expr_expression)); 3555d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->type = EXPR_TYPE_LITERAL; 3565d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_integer(&expr->u.literal, integer); 3575d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return expr; 3585d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3595d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3605d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_expression *new_string_literal(const char *begin, 3615d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *end) 3625d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3635d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression *expr; 3645d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr = calloc(1, sizeof(struct cras_expr_expression)); 3655d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->type = EXPR_TYPE_LITERAL; 3665d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value_set_string2(&expr->u.literal, begin, end); 3675d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return expr; 3685d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3695d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3705d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_expression *new_variable(const char *begin, 3715d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *end) 3725d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3735d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression *expr; 3745d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr = calloc(1, sizeof(struct cras_expr_expression)); 3755d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->type = EXPR_TYPE_VARIABLE; 3765d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->u.variable = copy_str(begin, end); 3775d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return expr; 3785d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3795d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3805d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_expression *new_compound_expression() 3815d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3825d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression *expr; 3835d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr = calloc(1, sizeof(struct cras_expr_expression)); 3845d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->type = EXPR_TYPE_COMPOUND; 3855d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return expr; 3865d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3875d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3885d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void add_sub_expression(struct cras_expr_expression *expr, 3895d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression *sub) 3905d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3915d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang ARRAY_APPEND(&expr->u.children, sub); 3925d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 3935d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 3945d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic int is_identifier_char(char c) 3955d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 3965d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (isspace(c)) 3975d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 0; 3985d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (c == '\0') 3995d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 0; 4005d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (isalpha(c)) 4015d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 1; 4025d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (c == '_' || c == '-' || c == '?') 4035d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 1; 4045d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return 0; 4055d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 4065d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4075d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic struct cras_expr_expression *parse_one_expr(const char **str) 4085d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 4095d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* skip whitespace */ 4105d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang while (isspace(**str)) 4115d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang (*str)++; 4125d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4135d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (**str == '\0') 4145d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return NULL; 4155d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4165d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* boolean literal: #t, #f */ 4175d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (**str == '#') { 4185d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang (*str)++; 4195d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang char c = **str; 4205d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (c == 't' || c == 'f') { 4215d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang (*str)++; 4225d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return new_boolean_literal(c == 't'); 4235d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } else { 4245d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, "unexpected char after #: '%c'", 4255d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang c); 4265d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 4275d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return NULL; 4285d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 4295d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4305d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* integer literal: (-)[0-9]+ */ 4315d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (isdigit(**str) || (**str == '-' && isdigit((*str)[1]))) 4325d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return new_integer_literal(strtol(*str, (char **)str, 10)); 4335d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4345d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* string literal: "..." */ 4355d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (**str == '"') { 4365d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *begin = *str + 1; 4375d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *end = strchr(begin, '"'); 4385d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (end == NULL) { 4395d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, "no matching \""); 4405d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang end = begin; 4415d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang *str = begin; 4425d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } else { 4435d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang *str = end + 1; 4445d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 4455d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return new_string_literal(begin, end); 4465d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 4475d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4485d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* compound expression: (expr1 expr2 ...) */ 4495d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (**str == '(') { 4505d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang (*str)++; 4515d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression *expr = new_compound_expression(); 4525d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang while (1) { 4535d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression *next = parse_one_expr(str); 4545d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (next == NULL) 4555d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 4565d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang add_sub_expression(expr, next); 4575d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 4585d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (**str != ')') { 4595d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, "no matching ): found '%c'", **str); 4605d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_expression_free(expr); 4615d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return NULL; 4625d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } else { 4635d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang (*str)++; 4645d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 4655d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return expr; 4665d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 4675d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4685d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang /* variable name */ 4695d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (is_identifier_char(**str)) { 4705d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const char *begin = *str; 4715d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang while (is_identifier_char(**str)) 4725d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang (*str)++; 4735d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return new_variable(begin, *str); 4745d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 4755d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4765d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return NULL; 4775d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 4785d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4795d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstruct cras_expr_expression *cras_expr_expression_parse(const char *str) 4805d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 4815d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (!str) 4825d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return NULL; 4835d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return parse_one_expr(&str); 4845d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 4855d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 4865d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void dump_value(struct dumper *d, const struct cras_expr_value *value, 4875d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int indent) 4885d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 4895d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang switch (value->type) { 4905d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_NONE: 4915d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*s(none)", indent, ""); 4925d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 4935d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_BOOLEAN: 4945d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*s%s", indent, "", 4955d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value->u.boolean ? "#t" : "#f"); 4965d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 4975d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_INT: 4985d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*s%d", indent, "", value->u.integer); 4995d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5005d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_STRING: 5015d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*s%s", indent, "", value->u.string); 5025d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5035d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case CRAS_EXPR_VALUE_TYPE_FUNCTION: 5045d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*s%p", indent, "", value->u.function); 5055d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5065d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 5075d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 5085d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 5095d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changstatic void dump_one_expression(struct dumper *d, 5105d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const struct cras_expr_expression *expr, 5115d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int indent) 5125d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 5135d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 5145d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression **sub; 5155d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 5165d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang switch (expr->type) { 5175d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_NONE: 5185d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*snone", indent, ""); 5195d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5205d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_LITERAL: 5215d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*sliteral", indent, ""); 5225d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dump_value(d, &expr->u.literal, indent + 2); 5235d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5245d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_VARIABLE: 5255d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*svariable (%s)", indent, "", 5265d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->u.variable); 5275d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5285d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_COMPOUND: 5295d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dumpf(d, "%*scompound", indent, ""); 5305d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(&expr->u.children, i, sub) { 5315d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dump_one_expression(d, *sub, indent + 2); 5325d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 5335d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5345d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 5355d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 5365d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 5375d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_expression_dump(struct dumper *d, 5385d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang const struct cras_expr_expression *expr) 5395d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 5405d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang dump_one_expression(d, expr, 0); 5415d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 5425d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 5435d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_expression_free(struct cras_expr_expression *expr) 5445d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 5455d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (!expr) 5465d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return; 5475d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 5485d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang switch (expr->type) { 5495d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_NONE: 5505d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5515d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_LITERAL: 5525d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(&expr->u.literal); 5535d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5545d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_VARIABLE: 5555d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang free((char *)expr->u.variable); 5565d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5575d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_COMPOUND: 5585d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang { 5595d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 5605d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression **psub; 5615d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(&expr->u.children, i, psub) { 5625d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_expression_free(*psub); 5635d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 5645d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang ARRAY_FREE(&expr->u.children); 5655d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5665d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 5675d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 5685d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang free(expr); 5695d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 5705d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 5715d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changvoid cras_expr_expression_eval(struct cras_expr_expression *expr, 5725d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_env *env, 5735d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *result) 5745d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 5755d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(result); 5765d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 5775d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang switch (expr->type) { 5785d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_NONE: 5795d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5805d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_LITERAL: 5815d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang copy_value(result, &expr->u.literal); 5825d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5835d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_VARIABLE: 5845d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang { 5855d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value = find_value(env, 5865d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->u.variable); 5875d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (value == NULL) { 5885d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, "cannot find value for %s", 5895d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang expr->u.variable); 5905d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } else { 5915d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang copy_value(result, value); 5925d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 5935d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 5945d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 5955d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang case EXPR_TYPE_COMPOUND: 5965d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang { 5975d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int i; 5985d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_expression **psub; 5995d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_array values = ARRAY_INIT; 6005d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *value; 6015d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 6025d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(&expr->u.children, i, psub) { 6035d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang value = ARRAY_APPEND_ZERO(&values); 6045d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_expression_eval(*psub, env, value); 6055d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 6065d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 6075d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (ARRAY_COUNT(&values) > 0) { 6085d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value *f = ARRAY_ELEMENT(&values, 0); 6095d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (f->type == CRAS_EXPR_VALUE_TYPE_FUNCTION) 6105d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang f->u.function(&values, result); 6115d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang else 6125d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, 6135d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang "first element is not a function"); 6145d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } else { 6155d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, "empty compound expression?"); 6165d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 6175d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 6185d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang FOR_ARRAY_ELEMENT(&values, i, value) { 6195d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(value); 6205d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 6215d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 6225d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang ARRAY_FREE(&values); 6235d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang break; 6245d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 6255d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 6265d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 6275d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 6285d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changint cras_expr_expression_eval_int(struct cras_expr_expression *expr, 6295d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_env *env, 6305d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int *integer) 6315d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 6325d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int rc = 0; 6335d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value value = CRAS_EXPR_VALUE_INIT; 6345d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 6355d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_expression_eval(expr, env, &value); 6365d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (value.type == CRAS_EXPR_VALUE_TYPE_INT) { 6375d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang *integer = value.u.integer; 6385d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } else { 6395d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, "value type is not integer (%d)", value.type); 6405d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang rc = -1; 6415d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 6425d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(&value); 6435d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return rc; 6445d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 6455d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 6465d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Changint cras_expr_expression_eval_boolean(struct cras_expr_expression *expr, 6475d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_env *env, 6485d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang char *boolean) 6495d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang{ 6505d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang int rc = 0; 6515d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang struct cras_expr_value value = CRAS_EXPR_VALUE_INIT; 6525d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang 6535d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_expression_eval(expr, env, &value); 6545d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang if (value.type == CRAS_EXPR_VALUE_TYPE_BOOLEAN) { 6555d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang *boolean = value.u.boolean; 6565d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } else { 6575d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang syslog(LOG_ERR, "value type is not boolean (%d)", value.type); 6585d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang rc = -1; 6595d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang } 6605d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang cras_expr_value_free(&value); 6615d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang return rc; 6625d3c38538845869fb38cde16ec12e96245bc996fChih-Chung Chang} 663