diff options
Diffstat (limited to 'cras/src/server/cras_expr.c')
-rw-r--r-- | cras/src/server/cras_expr.c | 653 |
1 files changed, 0 insertions, 653 deletions
diff --git a/cras/src/server/cras_expr.c b/cras/src/server/cras_expr.c deleted file mode 100644 index f7fab0d2..00000000 --- a/cras/src/server/cras_expr.c +++ /dev/null @@ -1,653 +0,0 @@ -/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <ctype.h> -#include <stdlib.h> -#include <syslog.h> - -#include "array.h" -#include "cras_expr.h" - -static const char *copy_str(const char *begin, const char *end) -{ - char *s = malloc(end - begin + 1); - memcpy(s, begin, end - begin); - s[end - begin] = '\0'; - return s; -} - -static void value_set_boolean(struct cras_expr_value *value, char boolean) -{ - cras_expr_value_free(value); - value->type = CRAS_EXPR_VALUE_TYPE_BOOLEAN; - value->u.boolean = !!boolean; -} - -static void value_set_integer(struct cras_expr_value *value, int integer) -{ - cras_expr_value_free(value); - value->type = CRAS_EXPR_VALUE_TYPE_INT; - value->u.integer = integer; -} - -static void value_set_string2(struct cras_expr_value *value, const char *begin, - const char *end) -{ - cras_expr_value_free(value); - value->type = CRAS_EXPR_VALUE_TYPE_STRING; - value->u.string = copy_str(begin, end); -} - -static void value_set_string(struct cras_expr_value *value, const char *str) -{ - value_set_string2(value, str, str + strlen(str)); -} - -static void cras_expr_value_set_function(struct cras_expr_value *value, - cras_expr_function_type function) -{ - cras_expr_value_free(value); - value->type = CRAS_EXPR_VALUE_TYPE_FUNCTION; - value->u.function = function; -} - -static void copy_value(struct cras_expr_value *value, - struct cras_expr_value *original) -{ - cras_expr_value_free(value); /* free the original value first */ - value->type = original->type; - switch (value->type) { - case CRAS_EXPR_VALUE_TYPE_NONE: - break; - case CRAS_EXPR_VALUE_TYPE_BOOLEAN: - value->u.boolean = original->u.boolean; - break; - case CRAS_EXPR_VALUE_TYPE_INT: - value->u.integer = original->u.integer; - break; - case CRAS_EXPR_VALUE_TYPE_STRING: - value->u.string = strdup(original->u.string); - break; - case CRAS_EXPR_VALUE_TYPE_FUNCTION: - value->u.function = original->u.function; - break; - } -} - -void cras_expr_value_free(struct cras_expr_value *value) -{ - switch (value->type) { - case CRAS_EXPR_VALUE_TYPE_STRING: - free((char *)value->u.string); - value->u.string = NULL; - break; - case CRAS_EXPR_VALUE_TYPE_NONE: - case CRAS_EXPR_VALUE_TYPE_BOOLEAN: - case CRAS_EXPR_VALUE_TYPE_INT: - case CRAS_EXPR_VALUE_TYPE_FUNCTION: - break; - } - value->type = CRAS_EXPR_VALUE_TYPE_NONE; -} - -void cras_expr_value_dump(struct dumper *d, const struct cras_expr_value *value) -{ - switch (value->type) { - case CRAS_EXPR_VALUE_TYPE_NONE: - dumpf(d, "none"); - break; - case CRAS_EXPR_VALUE_TYPE_BOOLEAN: - dumpf(d, "boolean(%s)", value->u.boolean ? "true" : "false"); - break; - case CRAS_EXPR_VALUE_TYPE_INT: - dumpf(d, "integer(%d)", value->u.integer); - break; - case CRAS_EXPR_VALUE_TYPE_STRING: - dumpf(d, "string(%s)", value->u.string); - break; - case CRAS_EXPR_VALUE_TYPE_FUNCTION: - dumpf(d, "function(%p)", value->u.function); - break; - } -} - -static struct cras_expr_value *find_value(struct cras_expr_env *env, - const char *name) -{ - int i; - const char **key; - - ARRAY_ELEMENT_FOREACH (&env->keys, i, key) { - if (strcmp(*key, name) == 0) - return ARRAY_ELEMENT(&env->values, i); - } - return NULL; -} - -/* Insert a (key, value) pair to the environment. The value is - * initialized to zero. Return the pointer to value so it can be set - * to the proper value. */ -static struct cras_expr_value *insert_value(struct cras_expr_env *env, - const char *key) -{ - *ARRAY_APPEND_ZERO(&env->keys) = strdup(key); - return ARRAY_APPEND_ZERO(&env->values); -} - -static struct cras_expr_value *find_or_insert_value(struct cras_expr_env *env, - const char *key) -{ - struct cras_expr_value *value = find_value(env, key); - if (!value) - value = insert_value(env, key); - return value; -} - -static void function_not(cras_expr_value_array *operands, - struct cras_expr_value *result) -{ - struct cras_expr_value *value; - int is_false; - - if (ARRAY_COUNT(operands) != 2) { - cras_expr_value_free(result); - syslog(LOG_ERR, "not takes one argument"); - return; - } - - value = ARRAY_ELEMENT(operands, 1); - is_false = (value->type == CRAS_EXPR_VALUE_TYPE_BOOLEAN && - !value->u.boolean); - value_set_boolean(result, is_false); -} - -static void function_and(cras_expr_value_array *operands, - struct cras_expr_value *result) -{ - int i; - struct cras_expr_value *value; - int n = ARRAY_COUNT(operands); - - /* no operands -- return #t */ - if (n <= 1) { - value_set_boolean(result, 1); - return; - } - - /* if there is any #f, return it */ - ARRAY_ELEMENT_FOREACH (operands, i, value) { - if (i == 0) - continue; /* ignore "and" itself */ - if (value->type == CRAS_EXPR_VALUE_TYPE_BOOLEAN && - !value->u.boolean) { - value_set_boolean(result, 0); - return; - } - } - - /* otherwise return the last element */ - copy_value(result, ARRAY_ELEMENT(operands, n - 1)); -} - -static void function_or(cras_expr_value_array *operands, - struct cras_expr_value *result) -{ - int i; - struct cras_expr_value *value; - - ARRAY_ELEMENT_FOREACH (operands, i, value) { - if (i == 0) - continue; /* ignore "or" itself */ - if (value->type != CRAS_EXPR_VALUE_TYPE_BOOLEAN || - value->u.boolean) { - copy_value(result, value); - return; - } - } - - value_set_boolean(result, 0); -} - -static char function_equal_real(cras_expr_value_array *operands) -{ - int i; - struct cras_expr_value *value, *prev; - - ARRAY_ELEMENT_FOREACH (operands, i, value) { - if (i <= 1) - continue; /* ignore equal? and first operand */ - /* compare with the previous operand */ - - prev = ARRAY_ELEMENT(operands, i - 1); - - if (prev->type != value->type) - return 0; - - switch (prev->type) { - case CRAS_EXPR_VALUE_TYPE_NONE: - break; - case CRAS_EXPR_VALUE_TYPE_BOOLEAN: - if (prev->u.boolean != value->u.boolean) - return 0; - break; - case CRAS_EXPR_VALUE_TYPE_INT: - if (prev->u.integer != value->u.integer) - return 0; - break; - case CRAS_EXPR_VALUE_TYPE_STRING: - if (strcmp(prev->u.string, value->u.string) != 0) - return 0; - break; - case CRAS_EXPR_VALUE_TYPE_FUNCTION: - if (prev->u.function != value->u.function) - return 0; - break; - } - } - - return 1; -} - -static void function_equal(cras_expr_value_array *operands, - struct cras_expr_value *result) -{ - value_set_boolean(result, function_equal_real(operands)); -} - -static void env_set_variable(struct cras_expr_env *env, const char *name, - struct cras_expr_value *new_value) -{ - struct cras_expr_value *value = find_or_insert_value(env, name); - copy_value(value, new_value); -} - -void cras_expr_env_install_builtins(struct cras_expr_env *env) -{ - struct cras_expr_value value = CRAS_EXPR_VALUE_INIT; - - /* initialize env with builtin functions */ - cras_expr_value_set_function(&value, &function_not); - env_set_variable(env, "not", &value); - - cras_expr_value_set_function(&value, &function_and); - env_set_variable(env, "and", &value); - - cras_expr_value_set_function(&value, &function_or); - env_set_variable(env, "or", &value); - - cras_expr_value_set_function(&value, &function_equal); - env_set_variable(env, "equal?", &value); - - cras_expr_value_free(&value); -} - -void cras_expr_env_set_variable_boolean(struct cras_expr_env *env, - const char *name, char boolean) -{ - struct cras_expr_value *value = find_or_insert_value(env, name); - value_set_boolean(value, boolean); -} - -void cras_expr_env_set_variable_integer(struct cras_expr_env *env, - const char *name, int integer) -{ - struct cras_expr_value *value = find_or_insert_value(env, name); - value_set_integer(value, integer); -} - -void cras_expr_env_set_variable_string(struct cras_expr_env *env, - const char *name, const char *str) -{ - struct cras_expr_value *value = find_or_insert_value(env, name); - value_set_string(value, str); -} - -void cras_expr_env_free(struct cras_expr_env *env) -{ - int i; - const char **key; - struct cras_expr_value *value; - - ARRAY_ELEMENT_FOREACH (&env->keys, i, key) { - free((char *)*key); - } - - ARRAY_ELEMENT_FOREACH (&env->values, i, value) { - cras_expr_value_free(value); - } - - ARRAY_FREE(&env->keys); - ARRAY_FREE(&env->values); -} - -void cras_expr_env_dump(struct dumper *d, const struct cras_expr_env *env) -{ - int i; - const char **key; - struct cras_expr_value *value; - - dumpf(d, "--- environment ---\n"); - ARRAY_ELEMENT_FOREACH (&env->keys, i, key) { - dumpf(d, " key=%s,", *key); - dumpf(d, " value="); - value = ARRAY_ELEMENT(&env->values, i); - cras_expr_value_dump(d, value); - dumpf(d, "\n"); - } -} - -static struct cras_expr_expression *new_boolean_literal(char boolean) -{ - struct cras_expr_expression *expr; - expr = calloc(1, sizeof(struct cras_expr_expression)); - expr->type = EXPR_TYPE_LITERAL; - value_set_boolean(&expr->u.literal, boolean); - return expr; -} - -static struct cras_expr_expression *new_integer_literal(int integer) -{ - struct cras_expr_expression *expr; - expr = calloc(1, sizeof(struct cras_expr_expression)); - expr->type = EXPR_TYPE_LITERAL; - value_set_integer(&expr->u.literal, integer); - return expr; -} - -static struct cras_expr_expression *new_string_literal(const char *begin, - const char *end) -{ - struct cras_expr_expression *expr; - expr = calloc(1, sizeof(struct cras_expr_expression)); - expr->type = EXPR_TYPE_LITERAL; - value_set_string2(&expr->u.literal, begin, end); - return expr; -} - -static struct cras_expr_expression *new_variable(const char *begin, - const char *end) -{ - struct cras_expr_expression *expr; - expr = calloc(1, sizeof(struct cras_expr_expression)); - expr->type = EXPR_TYPE_VARIABLE; - expr->u.variable = copy_str(begin, end); - return expr; -} - -static struct cras_expr_expression *new_compound_expression() -{ - struct cras_expr_expression *expr; - expr = calloc(1, sizeof(struct cras_expr_expression)); - expr->type = EXPR_TYPE_COMPOUND; - return expr; -} - -static void add_sub_expression(struct cras_expr_expression *expr, - struct cras_expr_expression *sub) -{ - ARRAY_APPEND(&expr->u.children, sub); -} - -static int is_identifier_char(char c) -{ - if (isspace(c)) - return 0; - if (c == '\0') - return 0; - if (isalpha(c)) - return 1; - if (c == '_' || c == '-' || c == '?') - return 1; - return 0; -} - -static struct cras_expr_expression *parse_one_expr(const char **str) -{ - /* skip whitespace */ - while (isspace(**str)) - (*str)++; - - if (**str == '\0') - return NULL; - - /* boolean literal: #t, #f */ - if (**str == '#') { - (*str)++; - char c = **str; - if (c == 't' || c == 'f') { - (*str)++; - return new_boolean_literal(c == 't'); - } else { - syslog(LOG_ERR, "unexpected char after #: '%c'", c); - } - return NULL; - } - - /* integer literal: (-)[0-9]+ */ - if (isdigit(**str) || (**str == '-' && isdigit((*str)[1]))) - return new_integer_literal(strtol(*str, (char **)str, 10)); - - /* string literal: "..." */ - if (**str == '"') { - const char *begin = *str + 1; - const char *end = strchr(begin, '"'); - if (end == NULL) { - syslog(LOG_ERR, "no matching \""); - end = begin; - *str = begin; - } else { - *str = end + 1; - } - return new_string_literal(begin, end); - } - - /* compound expression: (expr1 expr2 ...) */ - if (**str == '(') { - (*str)++; - struct cras_expr_expression *expr = new_compound_expression(); - while (1) { - struct cras_expr_expression *next = parse_one_expr(str); - if (next == NULL) - break; - add_sub_expression(expr, next); - } - if (**str != ')') { - syslog(LOG_ERR, "no matching ): found '%c'", **str); - cras_expr_expression_free(expr); - return NULL; - } else { - (*str)++; - } - return expr; - } - - /* variable name */ - if (is_identifier_char(**str)) { - const char *begin = *str; - while (is_identifier_char(**str)) - (*str)++; - return new_variable(begin, *str); - } - - return NULL; -} - -struct cras_expr_expression *cras_expr_expression_parse(const char *str) -{ - if (!str) - return NULL; - return parse_one_expr(&str); -} - -static void dump_value(struct dumper *d, const struct cras_expr_value *value, - int indent) -{ - switch (value->type) { - case CRAS_EXPR_VALUE_TYPE_NONE: - dumpf(d, "%*s(none)", indent, ""); - break; - case CRAS_EXPR_VALUE_TYPE_BOOLEAN: - dumpf(d, "%*s%s", indent, "", value->u.boolean ? "#t" : "#f"); - break; - case CRAS_EXPR_VALUE_TYPE_INT: - dumpf(d, "%*s%d", indent, "", value->u.integer); - break; - case CRAS_EXPR_VALUE_TYPE_STRING: - dumpf(d, "%*s%s", indent, "", value->u.string); - break; - case CRAS_EXPR_VALUE_TYPE_FUNCTION: - dumpf(d, "%*s%p", indent, "", value->u.function); - break; - } -} - -static void dump_one_expression(struct dumper *d, - const struct cras_expr_expression *expr, - int indent) -{ - int i; - struct cras_expr_expression **sub; - - switch (expr->type) { - case EXPR_TYPE_NONE: - dumpf(d, "%*snone", indent, ""); - break; - case EXPR_TYPE_LITERAL: - dumpf(d, "%*sliteral", indent, ""); - dump_value(d, &expr->u.literal, indent + 2); - break; - case EXPR_TYPE_VARIABLE: - dumpf(d, "%*svariable (%s)", indent, "", expr->u.variable); - break; - case EXPR_TYPE_COMPOUND: - dumpf(d, "%*scompound", indent, ""); - ARRAY_ELEMENT_FOREACH (&expr->u.children, i, sub) { - dump_one_expression(d, *sub, indent + 2); - } - break; - } -} - -void cras_expr_expression_dump(struct dumper *d, - const struct cras_expr_expression *expr) -{ - dump_one_expression(d, expr, 0); -} - -void cras_expr_expression_free(struct cras_expr_expression *expr) -{ - if (!expr) - return; - - switch (expr->type) { - case EXPR_TYPE_NONE: - break; - case EXPR_TYPE_LITERAL: - cras_expr_value_free(&expr->u.literal); - break; - case EXPR_TYPE_VARIABLE: - free((char *)expr->u.variable); - break; - case EXPR_TYPE_COMPOUND: { - int i; - struct cras_expr_expression **psub; - ARRAY_ELEMENT_FOREACH (&expr->u.children, i, psub) { - cras_expr_expression_free(*psub); - } - ARRAY_FREE(&expr->u.children); - break; - } - } - free(expr); -} - -void cras_expr_expression_eval(struct cras_expr_expression *expr, - struct cras_expr_env *env, - struct cras_expr_value *result) -{ - cras_expr_value_free(result); - - switch (expr->type) { - case EXPR_TYPE_NONE: - break; - case EXPR_TYPE_LITERAL: - copy_value(result, &expr->u.literal); - break; - case EXPR_TYPE_VARIABLE: { - struct cras_expr_value *value = - find_value(env, expr->u.variable); - if (value == NULL) { - syslog(LOG_ERR, "cannot find value for %s", - expr->u.variable); - } else { - copy_value(result, value); - } - break; - } - case EXPR_TYPE_COMPOUND: { - int i; - struct cras_expr_expression **psub; - cras_expr_value_array values = ARRAY_INIT; - struct cras_expr_value *value; - - ARRAY_ELEMENT_FOREACH (&expr->u.children, i, psub) { - value = ARRAY_APPEND_ZERO(&values); - cras_expr_expression_eval(*psub, env, value); - } - - if (ARRAY_COUNT(&values) > 0) { - struct cras_expr_value *f = ARRAY_ELEMENT(&values, 0); - if (f->type == CRAS_EXPR_VALUE_TYPE_FUNCTION) - f->u.function(&values, result); - else - syslog(LOG_ERR, - "first element is not a function"); - } else { - syslog(LOG_ERR, "empty compound expression?"); - } - - ARRAY_ELEMENT_FOREACH (&values, i, value) { - cras_expr_value_free(value); - } - - ARRAY_FREE(&values); - break; - } - } -} - -int cras_expr_expression_eval_int(struct cras_expr_expression *expr, - struct cras_expr_env *env, int *integer) -{ - int rc = 0; - struct cras_expr_value value = CRAS_EXPR_VALUE_INIT; - - cras_expr_expression_eval(expr, env, &value); - if (value.type == CRAS_EXPR_VALUE_TYPE_INT) { - *integer = value.u.integer; - } else { - syslog(LOG_ERR, "value type is not integer (%d)", value.type); - rc = -1; - } - cras_expr_value_free(&value); - return rc; -} - -int cras_expr_expression_eval_boolean(struct cras_expr_expression *expr, - struct cras_expr_env *env, char *boolean) -{ - int rc = 0; - struct cras_expr_value value = CRAS_EXPR_VALUE_INIT; - - cras_expr_expression_eval(expr, env, &value); - if (value.type == CRAS_EXPR_VALUE_TYPE_BOOLEAN) { - *boolean = value.u.boolean; - } else { - syslog(LOG_ERR, "value type is not boolean (%d)", value.type); - rc = -1; - } - cras_expr_value_free(&value); - return rc; -} |