• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <syslog.h>
9 
10 #include "array.h"
11 #include "cras_expr.h"
12 
copy_str(const char * begin,const char * end)13 static const char *copy_str(const char *begin, const char *end)
14 {
15 	char *s = malloc(end - begin + 1);
16 	memcpy(s, begin, end - begin);
17 	s[end - begin] = '\0';
18 	return s;
19 }
20 
value_set_boolean(struct cras_expr_value * value,char boolean)21 static void value_set_boolean(struct cras_expr_value *value, char boolean)
22 {
23 	cras_expr_value_free(value);
24 	value->type = CRAS_EXPR_VALUE_TYPE_BOOLEAN;
25 	value->u.boolean = !!boolean;
26 }
27 
value_set_integer(struct cras_expr_value * value,int integer)28 static void value_set_integer(struct cras_expr_value *value, int integer)
29 {
30 	cras_expr_value_free(value);
31 	value->type = CRAS_EXPR_VALUE_TYPE_INT;
32 	value->u.integer = integer;
33 }
34 
value_set_string2(struct cras_expr_value * value,const char * begin,const char * end)35 static void value_set_string2(struct cras_expr_value *value, const char *begin,
36 			      const char *end)
37 {
38 	cras_expr_value_free(value);
39 	value->type = CRAS_EXPR_VALUE_TYPE_STRING;
40 	value->u.string = copy_str(begin, end);
41 }
42 
value_set_string(struct cras_expr_value * value,const char * str)43 static void value_set_string(struct cras_expr_value *value, const char *str)
44 {
45 	value_set_string2(value, str, str + strlen(str));
46 }
47 
cras_expr_value_set_function(struct cras_expr_value * value,cras_expr_function_type function)48 static void cras_expr_value_set_function(struct cras_expr_value *value,
49 					 cras_expr_function_type function)
50 {
51 	cras_expr_value_free(value);
52 	value->type = CRAS_EXPR_VALUE_TYPE_FUNCTION;
53 	value->u.function = function;
54 }
55 
copy_value(struct cras_expr_value * value,struct cras_expr_value * original)56 static void copy_value(struct cras_expr_value *value,
57 		       struct cras_expr_value *original)
58 {
59 	cras_expr_value_free(value); /* free the original value first */
60 	value->type = original->type;
61 	switch (value->type) {
62 	case CRAS_EXPR_VALUE_TYPE_NONE:
63 		break;
64 	case CRAS_EXPR_VALUE_TYPE_BOOLEAN:
65 		value->u.boolean = original->u.boolean;
66 		break;
67 	case CRAS_EXPR_VALUE_TYPE_INT:
68 		value->u.integer = original->u.integer;
69 		break;
70 	case CRAS_EXPR_VALUE_TYPE_STRING:
71 		value->u.string = strdup(original->u.string);
72 		break;
73 	case CRAS_EXPR_VALUE_TYPE_FUNCTION:
74 		value->u.function = original->u.function;
75 		break;
76 	}
77 }
78 
cras_expr_value_free(struct cras_expr_value * value)79 void cras_expr_value_free(struct cras_expr_value *value)
80 {
81 	switch (value->type) {
82 	case CRAS_EXPR_VALUE_TYPE_STRING:
83 		free((char *)value->u.string);
84 		value->u.string = NULL;
85 		break;
86 	case CRAS_EXPR_VALUE_TYPE_NONE:
87 	case CRAS_EXPR_VALUE_TYPE_BOOLEAN:
88 	case CRAS_EXPR_VALUE_TYPE_INT:
89 	case CRAS_EXPR_VALUE_TYPE_FUNCTION:
90 		break;
91 	}
92 	value->type = CRAS_EXPR_VALUE_TYPE_NONE;
93 }
94 
cras_expr_value_dump(struct dumper * d,const struct cras_expr_value * value)95 void cras_expr_value_dump(struct dumper *d, const struct cras_expr_value *value)
96 {
97 	switch (value->type) {
98 	case CRAS_EXPR_VALUE_TYPE_NONE:
99 		dumpf(d, "none");
100 		break;
101 	case CRAS_EXPR_VALUE_TYPE_BOOLEAN:
102 		dumpf(d, "boolean(%s)", value->u.boolean ? "true" : "false");
103 		break;
104 	case CRAS_EXPR_VALUE_TYPE_INT:
105 		dumpf(d, "integer(%d)", value->u.integer);
106 		break;
107 	case CRAS_EXPR_VALUE_TYPE_STRING:
108 		dumpf(d, "string(%s)", value->u.string);
109 		break;
110 	case CRAS_EXPR_VALUE_TYPE_FUNCTION:
111 		dumpf(d, "function(%p)", value->u.function);
112 		break;
113 	}
114 }
115 
find_value(struct cras_expr_env * env,const char * name)116 static struct cras_expr_value *find_value(struct cras_expr_env *env,
117 					  const char *name)
118 {
119 	int i;
120 	const char **key;
121 
122 	ARRAY_ELEMENT_FOREACH (&env->keys, i, key) {
123 		if (strcmp(*key, name) == 0)
124 			return ARRAY_ELEMENT(&env->values, i);
125 	}
126 	return NULL;
127 }
128 
129 /* Insert a (key, value) pair to the environment. The value is
130  * initialized to zero. Return the pointer to value so it can be set
131  * to the proper value. */
insert_value(struct cras_expr_env * env,const char * key)132 static struct cras_expr_value *insert_value(struct cras_expr_env *env,
133 					    const char *key)
134 {
135 	*ARRAY_APPEND_ZERO(&env->keys) = strdup(key);
136 	return ARRAY_APPEND_ZERO(&env->values);
137 }
138 
find_or_insert_value(struct cras_expr_env * env,const char * key)139 static struct cras_expr_value *find_or_insert_value(struct cras_expr_env *env,
140 						    const char *key)
141 {
142 	struct cras_expr_value *value = find_value(env, key);
143 	if (!value)
144 		value = insert_value(env, key);
145 	return value;
146 }
147 
function_not(cras_expr_value_array * operands,struct cras_expr_value * result)148 static void function_not(cras_expr_value_array *operands,
149 			 struct cras_expr_value *result)
150 {
151 	struct cras_expr_value *value;
152 	int is_false;
153 
154 	if (ARRAY_COUNT(operands) != 2) {
155 		cras_expr_value_free(result);
156 		syslog(LOG_ERR, "not takes one argument");
157 		return;
158 	}
159 
160 	value = ARRAY_ELEMENT(operands, 1);
161 	is_false = (value->type == CRAS_EXPR_VALUE_TYPE_BOOLEAN &&
162 		    !value->u.boolean);
163 	value_set_boolean(result, is_false);
164 }
165 
function_and(cras_expr_value_array * operands,struct cras_expr_value * result)166 static void function_and(cras_expr_value_array *operands,
167 			 struct cras_expr_value *result)
168 {
169 	int i;
170 	struct cras_expr_value *value;
171 	int n = ARRAY_COUNT(operands);
172 
173 	/* no operands -- return #t */
174 	if (n <= 1) {
175 		value_set_boolean(result, 1);
176 		return;
177 	}
178 
179 	/* if there is any #f, return it */
180 	ARRAY_ELEMENT_FOREACH (operands, i, value) {
181 		if (i == 0)
182 			continue; /* ignore "and" itself */
183 		if (value->type == CRAS_EXPR_VALUE_TYPE_BOOLEAN &&
184 		    !value->u.boolean) {
185 			value_set_boolean(result, 0);
186 			return;
187 		}
188 	}
189 
190 	/* otherwise return the last element */
191 	copy_value(result, ARRAY_ELEMENT(operands, n - 1));
192 }
193 
function_or(cras_expr_value_array * operands,struct cras_expr_value * result)194 static void function_or(cras_expr_value_array *operands,
195 			struct cras_expr_value *result)
196 {
197 	int i;
198 	struct cras_expr_value *value;
199 
200 	ARRAY_ELEMENT_FOREACH (operands, i, value) {
201 		if (i == 0)
202 			continue; /* ignore "or" itself */
203 		if (value->type != CRAS_EXPR_VALUE_TYPE_BOOLEAN ||
204 		    value->u.boolean) {
205 			copy_value(result, value);
206 			return;
207 		}
208 	}
209 
210 	value_set_boolean(result, 0);
211 }
212 
function_equal_real(cras_expr_value_array * operands)213 static char function_equal_real(cras_expr_value_array *operands)
214 {
215 	int i;
216 	struct cras_expr_value *value, *prev;
217 
218 	ARRAY_ELEMENT_FOREACH (operands, i, value) {
219 		if (i <= 1)
220 			continue; /* ignore equal? and first operand */
221 		/* compare with the previous operand */
222 
223 		prev = ARRAY_ELEMENT(operands, i - 1);
224 
225 		if (prev->type != value->type)
226 			return 0;
227 
228 		switch (prev->type) {
229 		case CRAS_EXPR_VALUE_TYPE_NONE:
230 			break;
231 		case CRAS_EXPR_VALUE_TYPE_BOOLEAN:
232 			if (prev->u.boolean != value->u.boolean)
233 				return 0;
234 			break;
235 		case CRAS_EXPR_VALUE_TYPE_INT:
236 			if (prev->u.integer != value->u.integer)
237 				return 0;
238 			break;
239 		case CRAS_EXPR_VALUE_TYPE_STRING:
240 			if (strcmp(prev->u.string, value->u.string) != 0)
241 				return 0;
242 			break;
243 		case CRAS_EXPR_VALUE_TYPE_FUNCTION:
244 			if (prev->u.function != value->u.function)
245 				return 0;
246 			break;
247 		}
248 	}
249 
250 	return 1;
251 }
252 
function_equal(cras_expr_value_array * operands,struct cras_expr_value * result)253 static void function_equal(cras_expr_value_array *operands,
254 			   struct cras_expr_value *result)
255 {
256 	value_set_boolean(result, function_equal_real(operands));
257 }
258 
env_set_variable(struct cras_expr_env * env,const char * name,struct cras_expr_value * new_value)259 static void env_set_variable(struct cras_expr_env *env, const char *name,
260 			     struct cras_expr_value *new_value)
261 {
262 	struct cras_expr_value *value = find_or_insert_value(env, name);
263 	copy_value(value, new_value);
264 }
265 
cras_expr_env_install_builtins(struct cras_expr_env * env)266 void cras_expr_env_install_builtins(struct cras_expr_env *env)
267 {
268 	struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
269 
270 	/* initialize env with builtin functions */
271 	cras_expr_value_set_function(&value, &function_not);
272 	env_set_variable(env, "not", &value);
273 
274 	cras_expr_value_set_function(&value, &function_and);
275 	env_set_variable(env, "and", &value);
276 
277 	cras_expr_value_set_function(&value, &function_or);
278 	env_set_variable(env, "or", &value);
279 
280 	cras_expr_value_set_function(&value, &function_equal);
281 	env_set_variable(env, "equal?", &value);
282 
283 	cras_expr_value_free(&value);
284 }
285 
cras_expr_env_set_variable_boolean(struct cras_expr_env * env,const char * name,char boolean)286 void cras_expr_env_set_variable_boolean(struct cras_expr_env *env,
287 					const char *name, char boolean)
288 {
289 	struct cras_expr_value *value = find_or_insert_value(env, name);
290 	value_set_boolean(value, boolean);
291 }
292 
cras_expr_env_set_variable_integer(struct cras_expr_env * env,const char * name,int integer)293 void cras_expr_env_set_variable_integer(struct cras_expr_env *env,
294 					const char *name, int integer)
295 {
296 	struct cras_expr_value *value = find_or_insert_value(env, name);
297 	value_set_integer(value, integer);
298 }
299 
cras_expr_env_set_variable_string(struct cras_expr_env * env,const char * name,const char * str)300 void cras_expr_env_set_variable_string(struct cras_expr_env *env,
301 				       const char *name, const char *str)
302 {
303 	struct cras_expr_value *value = find_or_insert_value(env, name);
304 	value_set_string(value, str);
305 }
306 
cras_expr_env_free(struct cras_expr_env * env)307 void cras_expr_env_free(struct cras_expr_env *env)
308 {
309 	int i;
310 	const char **key;
311 	struct cras_expr_value *value;
312 
313 	ARRAY_ELEMENT_FOREACH (&env->keys, i, key) {
314 		free((char *)*key);
315 	}
316 
317 	ARRAY_ELEMENT_FOREACH (&env->values, i, value) {
318 		cras_expr_value_free(value);
319 	}
320 
321 	ARRAY_FREE(&env->keys);
322 	ARRAY_FREE(&env->values);
323 }
324 
cras_expr_env_dump(struct dumper * d,const struct cras_expr_env * env)325 void cras_expr_env_dump(struct dumper *d, const struct cras_expr_env *env)
326 {
327 	int i;
328 	const char **key;
329 	struct cras_expr_value *value;
330 
331 	dumpf(d, "--- environment ---\n");
332 	ARRAY_ELEMENT_FOREACH (&env->keys, i, key) {
333 		dumpf(d, " key=%s,", *key);
334 		dumpf(d, " value=");
335 		value = ARRAY_ELEMENT(&env->values, i);
336 		cras_expr_value_dump(d, value);
337 		dumpf(d, "\n");
338 	}
339 }
340 
new_boolean_literal(char boolean)341 static struct cras_expr_expression *new_boolean_literal(char boolean)
342 {
343 	struct cras_expr_expression *expr;
344 	expr = calloc(1, sizeof(struct cras_expr_expression));
345 	expr->type = EXPR_TYPE_LITERAL;
346 	value_set_boolean(&expr->u.literal, boolean);
347 	return expr;
348 }
349 
new_integer_literal(int integer)350 static struct cras_expr_expression *new_integer_literal(int integer)
351 {
352 	struct cras_expr_expression *expr;
353 	expr = calloc(1, sizeof(struct cras_expr_expression));
354 	expr->type = EXPR_TYPE_LITERAL;
355 	value_set_integer(&expr->u.literal, integer);
356 	return expr;
357 }
358 
new_string_literal(const char * begin,const char * end)359 static struct cras_expr_expression *new_string_literal(const char *begin,
360 						       const char *end)
361 {
362 	struct cras_expr_expression *expr;
363 	expr = calloc(1, sizeof(struct cras_expr_expression));
364 	expr->type = EXPR_TYPE_LITERAL;
365 	value_set_string2(&expr->u.literal, begin, end);
366 	return expr;
367 }
368 
new_variable(const char * begin,const char * end)369 static struct cras_expr_expression *new_variable(const char *begin,
370 						 const char *end)
371 {
372 	struct cras_expr_expression *expr;
373 	expr = calloc(1, sizeof(struct cras_expr_expression));
374 	expr->type = EXPR_TYPE_VARIABLE;
375 	expr->u.variable = copy_str(begin, end);
376 	return expr;
377 }
378 
new_compound_expression()379 static struct cras_expr_expression *new_compound_expression()
380 {
381 	struct cras_expr_expression *expr;
382 	expr = calloc(1, sizeof(struct cras_expr_expression));
383 	expr->type = EXPR_TYPE_COMPOUND;
384 	return expr;
385 }
386 
add_sub_expression(struct cras_expr_expression * expr,struct cras_expr_expression * sub)387 static void add_sub_expression(struct cras_expr_expression *expr,
388 			       struct cras_expr_expression *sub)
389 {
390 	ARRAY_APPEND(&expr->u.children, sub);
391 }
392 
is_identifier_char(char c)393 static int is_identifier_char(char c)
394 {
395 	if (isspace(c))
396 		return 0;
397 	if (c == '\0')
398 		return 0;
399 	if (isalpha(c))
400 		return 1;
401 	if (c == '_' || c == '-' || c == '?')
402 		return 1;
403 	return 0;
404 }
405 
parse_one_expr(const char ** str)406 static struct cras_expr_expression *parse_one_expr(const char **str)
407 {
408 	/* skip whitespace */
409 	while (isspace(**str))
410 		(*str)++;
411 
412 	if (**str == '\0')
413 		return NULL;
414 
415 	/* boolean literal: #t, #f */
416 	if (**str == '#') {
417 		(*str)++;
418 		char c = **str;
419 		if (c == 't' || c == 'f') {
420 			(*str)++;
421 			return new_boolean_literal(c == 't');
422 		} else {
423 			syslog(LOG_ERR, "unexpected char after #: '%c'", c);
424 		}
425 		return NULL;
426 	}
427 
428 	/* integer literal: (-)[0-9]+ */
429 	if (isdigit(**str) || (**str == '-' && isdigit((*str)[1])))
430 		return new_integer_literal(strtol(*str, (char **)str, 10));
431 
432 	/* string literal: "..." */
433 	if (**str == '"') {
434 		const char *begin = *str + 1;
435 		const char *end = strchr(begin, '"');
436 		if (end == NULL) {
437 			syslog(LOG_ERR, "no matching \"");
438 			end = begin;
439 			*str = begin;
440 		} else {
441 			*str = end + 1;
442 		}
443 		return new_string_literal(begin, end);
444 	}
445 
446 	/* compound expression: (expr1 expr2 ...) */
447 	if (**str == '(') {
448 		(*str)++;
449 		struct cras_expr_expression *expr = new_compound_expression();
450 		while (1) {
451 			struct cras_expr_expression *next = parse_one_expr(str);
452 			if (next == NULL)
453 				break;
454 			add_sub_expression(expr, next);
455 		}
456 		if (**str != ')') {
457 			syslog(LOG_ERR, "no matching ): found '%c'", **str);
458 			cras_expr_expression_free(expr);
459 			return NULL;
460 		} else {
461 			(*str)++;
462 		}
463 		return expr;
464 	}
465 
466 	/* variable name */
467 	if (is_identifier_char(**str)) {
468 		const char *begin = *str;
469 		while (is_identifier_char(**str))
470 			(*str)++;
471 		return new_variable(begin, *str);
472 	}
473 
474 	return NULL;
475 }
476 
cras_expr_expression_parse(const char * str)477 struct cras_expr_expression *cras_expr_expression_parse(const char *str)
478 {
479 	if (!str)
480 		return NULL;
481 	return parse_one_expr(&str);
482 }
483 
dump_value(struct dumper * d,const struct cras_expr_value * value,int indent)484 static void dump_value(struct dumper *d, const struct cras_expr_value *value,
485 		       int indent)
486 {
487 	switch (value->type) {
488 	case CRAS_EXPR_VALUE_TYPE_NONE:
489 		dumpf(d, "%*s(none)", indent, "");
490 		break;
491 	case CRAS_EXPR_VALUE_TYPE_BOOLEAN:
492 		dumpf(d, "%*s%s", indent, "", value->u.boolean ? "#t" : "#f");
493 		break;
494 	case CRAS_EXPR_VALUE_TYPE_INT:
495 		dumpf(d, "%*s%d", indent, "", value->u.integer);
496 		break;
497 	case CRAS_EXPR_VALUE_TYPE_STRING:
498 		dumpf(d, "%*s%s", indent, "", value->u.string);
499 		break;
500 	case CRAS_EXPR_VALUE_TYPE_FUNCTION:
501 		dumpf(d, "%*s%p", indent, "", value->u.function);
502 		break;
503 	}
504 }
505 
dump_one_expression(struct dumper * d,const struct cras_expr_expression * expr,int indent)506 static void dump_one_expression(struct dumper *d,
507 				const struct cras_expr_expression *expr,
508 				int indent)
509 {
510 	int i;
511 	struct cras_expr_expression **sub;
512 
513 	switch (expr->type) {
514 	case EXPR_TYPE_NONE:
515 		dumpf(d, "%*snone", indent, "");
516 		break;
517 	case EXPR_TYPE_LITERAL:
518 		dumpf(d, "%*sliteral", indent, "");
519 		dump_value(d, &expr->u.literal, indent + 2);
520 		break;
521 	case EXPR_TYPE_VARIABLE:
522 		dumpf(d, "%*svariable (%s)", indent, "", expr->u.variable);
523 		break;
524 	case EXPR_TYPE_COMPOUND:
525 		dumpf(d, "%*scompound", indent, "");
526 		ARRAY_ELEMENT_FOREACH (&expr->u.children, i, sub) {
527 			dump_one_expression(d, *sub, indent + 2);
528 		}
529 		break;
530 	}
531 }
532 
cras_expr_expression_dump(struct dumper * d,const struct cras_expr_expression * expr)533 void cras_expr_expression_dump(struct dumper *d,
534 			       const struct cras_expr_expression *expr)
535 {
536 	dump_one_expression(d, expr, 0);
537 }
538 
cras_expr_expression_free(struct cras_expr_expression * expr)539 void cras_expr_expression_free(struct cras_expr_expression *expr)
540 {
541 	if (!expr)
542 		return;
543 
544 	switch (expr->type) {
545 	case EXPR_TYPE_NONE:
546 		break;
547 	case EXPR_TYPE_LITERAL:
548 		cras_expr_value_free(&expr->u.literal);
549 		break;
550 	case EXPR_TYPE_VARIABLE:
551 		free((char *)expr->u.variable);
552 		break;
553 	case EXPR_TYPE_COMPOUND: {
554 		int i;
555 		struct cras_expr_expression **psub;
556 		ARRAY_ELEMENT_FOREACH (&expr->u.children, i, psub) {
557 			cras_expr_expression_free(*psub);
558 		}
559 		ARRAY_FREE(&expr->u.children);
560 		break;
561 	}
562 	}
563 	free(expr);
564 }
565 
cras_expr_expression_eval(struct cras_expr_expression * expr,struct cras_expr_env * env,struct cras_expr_value * result)566 void cras_expr_expression_eval(struct cras_expr_expression *expr,
567 			       struct cras_expr_env *env,
568 			       struct cras_expr_value *result)
569 {
570 	cras_expr_value_free(result);
571 
572 	switch (expr->type) {
573 	case EXPR_TYPE_NONE:
574 		break;
575 	case EXPR_TYPE_LITERAL:
576 		copy_value(result, &expr->u.literal);
577 		break;
578 	case EXPR_TYPE_VARIABLE: {
579 		struct cras_expr_value *value =
580 			find_value(env, expr->u.variable);
581 		if (value == NULL) {
582 			syslog(LOG_ERR, "cannot find value for %s",
583 			       expr->u.variable);
584 		} else {
585 			copy_value(result, value);
586 		}
587 		break;
588 	}
589 	case EXPR_TYPE_COMPOUND: {
590 		int i;
591 		struct cras_expr_expression **psub;
592 		cras_expr_value_array values = ARRAY_INIT;
593 		struct cras_expr_value *value;
594 
595 		ARRAY_ELEMENT_FOREACH (&expr->u.children, i, psub) {
596 			value = ARRAY_APPEND_ZERO(&values);
597 			cras_expr_expression_eval(*psub, env, value);
598 		}
599 
600 		if (ARRAY_COUNT(&values) > 0) {
601 			struct cras_expr_value *f = ARRAY_ELEMENT(&values, 0);
602 			if (f->type == CRAS_EXPR_VALUE_TYPE_FUNCTION)
603 				f->u.function(&values, result);
604 			else
605 				syslog(LOG_ERR,
606 				       "first element is not a function");
607 		} else {
608 			syslog(LOG_ERR, "empty compound expression?");
609 		}
610 
611 		ARRAY_ELEMENT_FOREACH (&values, i, value) {
612 			cras_expr_value_free(value);
613 		}
614 
615 		ARRAY_FREE(&values);
616 		break;
617 	}
618 	}
619 }
620 
cras_expr_expression_eval_int(struct cras_expr_expression * expr,struct cras_expr_env * env,int * integer)621 int cras_expr_expression_eval_int(struct cras_expr_expression *expr,
622 				  struct cras_expr_env *env, int *integer)
623 {
624 	int rc = 0;
625 	struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
626 
627 	cras_expr_expression_eval(expr, env, &value);
628 	if (value.type == CRAS_EXPR_VALUE_TYPE_INT) {
629 		*integer = value.u.integer;
630 	} else {
631 		syslog(LOG_ERR, "value type is not integer (%d)", value.type);
632 		rc = -1;
633 	}
634 	cras_expr_value_free(&value);
635 	return rc;
636 }
637 
cras_expr_expression_eval_boolean(struct cras_expr_expression * expr,struct cras_expr_env * env,char * boolean)638 int cras_expr_expression_eval_boolean(struct cras_expr_expression *expr,
639 				      struct cras_expr_env *env, char *boolean)
640 {
641 	int rc = 0;
642 	struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
643 
644 	cras_expr_expression_eval(expr, env, &value);
645 	if (value.type == CRAS_EXPR_VALUE_TYPE_BOOLEAN) {
646 		*boolean = value.u.boolean;
647 	} else {
648 		syslog(LOG_ERR, "value type is not boolean (%d)", value.type);
649 		rc = -1;
650 	}
651 	cras_expr_value_free(&value);
652 	return rc;
653 }
654