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