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 
find_value(struct cras_expr_env * env,const char * name)95 static struct cras_expr_value *find_value(struct cras_expr_env *env,
96 					  const char *name)
97 {
98 	int i;
99 	const char **key;
100 
101 	FOR_ARRAY_ELEMENT(&env->keys, i, key) {
102 		if (strcmp(*key, name) == 0)
103 			return ARRAY_ELEMENT(&env->values, i);
104 	}
105 	return NULL;
106 }
107 
108 /* Insert a (key, value) pair to the environment. The value is
109  * initialized to zero. Return the pointer to value so it can be set
110  * to the proper value. */
insert_value(struct cras_expr_env * env,const char * key)111 static struct cras_expr_value *insert_value(struct cras_expr_env *env,
112 					    const char *key)
113 {
114 	*ARRAY_APPEND_ZERO(&env->keys) = strdup(key);
115 	return ARRAY_APPEND_ZERO(&env->values);
116 }
117 
find_or_insert_value(struct cras_expr_env * env,const char * key)118 static struct cras_expr_value *find_or_insert_value(struct cras_expr_env *env,
119 						    const char *key)
120 {
121 	struct cras_expr_value *value = find_value(env, key);
122 	if (!value)
123 		value = insert_value(env, key);
124 	return value;
125 }
126 
function_not(cras_expr_value_array * operands,struct cras_expr_value * result)127 static void function_not(cras_expr_value_array *operands,
128 			 struct cras_expr_value *result)
129 {
130 	struct cras_expr_value *value;
131 	int is_false;
132 
133 	if (ARRAY_COUNT(operands) != 2) {
134 		cras_expr_value_free(result);
135 		syslog(LOG_ERR, "not takes one argument");
136 		return;
137 	}
138 
139 	value = ARRAY_ELEMENT(operands, 1);
140 	is_false = (value->type == CRAS_EXPR_VALUE_TYPE_BOOLEAN &&
141 		    !value->u.boolean);
142 	value_set_boolean(result, is_false);
143 }
144 
function_and(cras_expr_value_array * operands,struct cras_expr_value * result)145 static void function_and(cras_expr_value_array *operands,
146 			 struct cras_expr_value *result)
147 {
148 	int i;
149 	struct cras_expr_value *value;
150 	int n = ARRAY_COUNT(operands);
151 
152 	/* no operands -- return #t */
153 	if (n <= 1) {
154 		value_set_boolean(result, 1);
155 		return;
156 	}
157 
158 	/* if there is any #f, return it */
159 	FOR_ARRAY_ELEMENT(operands, i, value) {
160 		if (i == 0)
161 			continue;  /* ignore "and" itself */
162 		if (value->type == CRAS_EXPR_VALUE_TYPE_BOOLEAN &&
163 		    !value->u.boolean) {
164 			value_set_boolean(result, 0);
165 			return;
166 		}
167 	}
168 
169 	/* otherwise return the last element */
170 	copy_value(result, ARRAY_ELEMENT(operands, n - 1));
171 }
172 
function_or(cras_expr_value_array * operands,struct cras_expr_value * result)173 static void function_or(cras_expr_value_array *operands,
174 			struct cras_expr_value *result)
175 {
176 	int i;
177 	struct cras_expr_value *value;
178 
179 	FOR_ARRAY_ELEMENT(operands, i, value) {
180 		if (i == 0)
181 			continue;  /* ignore "or" itself */
182 		if (value->type != CRAS_EXPR_VALUE_TYPE_BOOLEAN ||
183 		    value->u.boolean) {
184 			copy_value(result, value);
185 			return;
186 		}
187 	}
188 
189 	value_set_boolean(result, 0);
190 }
191 
function_equal_real(cras_expr_value_array * operands)192 static char function_equal_real(cras_expr_value_array *operands)
193 {
194 	int i;
195 	struct cras_expr_value *value, *prev;
196 
197 	FOR_ARRAY_ELEMENT(operands, i, value) {
198 		if (i <= 1)
199 			continue;  /* ignore equal? and first operand */
200 		/* compare with the previous operand */
201 
202 		prev = ARRAY_ELEMENT(operands, i - 1);
203 
204 		if (prev->type != value->type)
205 			return 0;
206 
207 		switch (prev->type) {
208 		case CRAS_EXPR_VALUE_TYPE_NONE:
209 			break;
210 		case CRAS_EXPR_VALUE_TYPE_BOOLEAN:
211 			if (prev->u.boolean != value->u.boolean)
212 				return 0;
213 			break;
214 		case CRAS_EXPR_VALUE_TYPE_INT:
215 			if (prev->u.integer != value->u.integer)
216 				return 0;
217 			break;
218 		case CRAS_EXPR_VALUE_TYPE_STRING:
219 			if (strcmp(prev->u.string, value->u.string) != 0)
220 				return 0;
221 			break;
222 		case CRAS_EXPR_VALUE_TYPE_FUNCTION:
223 			if (prev->u.function != value->u.function)
224 				return 0;
225 			break;
226 		}
227 	}
228 
229 	return 1;
230 }
231 
function_equal(cras_expr_value_array * operands,struct cras_expr_value * result)232 static void function_equal(cras_expr_value_array *operands,
233 			   struct cras_expr_value *result)
234 {
235 	value_set_boolean(result, function_equal_real(operands));
236 }
237 
env_set_variable(struct cras_expr_env * env,const char * name,struct cras_expr_value * new_value)238 static void env_set_variable(struct cras_expr_env *env, const char *name,
239 			     struct cras_expr_value *new_value)
240 {
241 	struct cras_expr_value *value = find_or_insert_value(env, name);
242 	copy_value(value, new_value);
243 }
244 
cras_expr_env_install_builtins(struct cras_expr_env * env)245 void cras_expr_env_install_builtins(struct cras_expr_env *env)
246 {
247 	struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
248 
249 	/* initialize env with builtin functions */
250 	cras_expr_value_set_function(&value, &function_not);
251 	env_set_variable(env, "not", &value);
252 
253 	cras_expr_value_set_function(&value, &function_and);
254 	env_set_variable(env, "and", &value);
255 
256 	cras_expr_value_set_function(&value, &function_or);
257 	env_set_variable(env, "or", &value);
258 
259 	cras_expr_value_set_function(&value, &function_equal);
260 	env_set_variable(env, "equal?", &value);
261 
262 	cras_expr_value_free(&value);
263 }
264 
cras_expr_env_set_variable_boolean(struct cras_expr_env * env,const char * name,char boolean)265 void cras_expr_env_set_variable_boolean(struct cras_expr_env *env,
266 					const char *name, char boolean)
267 {
268 	struct cras_expr_value *value = find_or_insert_value(env, name);
269 	value_set_boolean(value, boolean);
270 }
271 
cras_expr_env_set_variable_integer(struct cras_expr_env * env,const char * name,int integer)272 void cras_expr_env_set_variable_integer(struct cras_expr_env *env,
273 					const char *name, int integer)
274 {
275 	struct cras_expr_value *value = find_or_insert_value(env, name);
276 	value_set_integer(value, integer);
277 }
278 
cras_expr_env_set_variable_string(struct cras_expr_env * env,const char * name,const char * str)279 void cras_expr_env_set_variable_string(struct cras_expr_env *env,
280 				       const char *name, const char *str)
281 {
282 	struct cras_expr_value *value = find_or_insert_value(env, name);
283 	value_set_string(value, str);
284 }
285 
cras_expr_env_free(struct cras_expr_env * env)286 void cras_expr_env_free(struct cras_expr_env *env)
287 {
288 	int i;
289 	const char **key;
290 	struct cras_expr_value *value;
291 
292 	FOR_ARRAY_ELEMENT(&env->keys, i, key) {
293 		free((char *)*key);
294 	}
295 
296 	FOR_ARRAY_ELEMENT(&env->values, i, value) {
297 		cras_expr_value_free(value);
298 	}
299 
300 	ARRAY_FREE(&env->keys);
301 	ARRAY_FREE(&env->values);
302 }
303 
new_boolean_literal(char boolean)304 static struct cras_expr_expression *new_boolean_literal(char boolean)
305 {
306 	struct cras_expr_expression *expr;
307 	expr = calloc(1, sizeof(struct cras_expr_expression));
308 	expr->type = EXPR_TYPE_LITERAL;
309 	value_set_boolean(&expr->u.literal, boolean);
310 	return expr;
311 }
312 
new_integer_literal(int integer)313 static struct cras_expr_expression *new_integer_literal(int integer)
314 {
315 	struct cras_expr_expression *expr;
316 	expr = calloc(1, sizeof(struct cras_expr_expression));
317 	expr->type = EXPR_TYPE_LITERAL;
318 	value_set_integer(&expr->u.literal, integer);
319 	return expr;
320 }
321 
new_string_literal(const char * begin,const char * end)322 static struct cras_expr_expression *new_string_literal(const char *begin,
323 						       const char *end)
324 {
325 	struct cras_expr_expression *expr;
326 	expr = calloc(1, sizeof(struct cras_expr_expression));
327 	expr->type = EXPR_TYPE_LITERAL;
328 	value_set_string2(&expr->u.literal, begin, end);
329 	return expr;
330 }
331 
new_variable(const char * begin,const char * end)332 static struct cras_expr_expression *new_variable(const char *begin,
333 						 const char *end)
334 {
335 	struct cras_expr_expression *expr;
336 	expr = calloc(1, sizeof(struct cras_expr_expression));
337 	expr->type = EXPR_TYPE_VARIABLE;
338 	expr->u.variable = copy_str(begin, end);
339 	return expr;
340 }
341 
new_compound_expression()342 static struct cras_expr_expression *new_compound_expression()
343 {
344 	struct cras_expr_expression *expr;
345 	expr = calloc(1, sizeof(struct cras_expr_expression));
346 	expr->type = EXPR_TYPE_COMPOUND;
347 	return expr;
348 }
349 
add_sub_expression(struct cras_expr_expression * expr,struct cras_expr_expression * sub)350 static void add_sub_expression(struct cras_expr_expression *expr,
351 			       struct cras_expr_expression *sub)
352 {
353 	ARRAY_APPEND(&expr->u.children, sub);
354 }
355 
is_identifier_char(char c)356 static int is_identifier_char(char c)
357 {
358 	if (isspace(c))
359 		return 0;
360 	if (c == '\0')
361 		return 0;
362 	if (isalpha(c))
363 		return 1;
364 	if (c == '_' || c == '-' || c == '?')
365 		return 1;
366 	return 0;
367 }
368 
parse_one_expr(const char ** str)369 static struct cras_expr_expression *parse_one_expr(const char **str)
370 {
371 	/* skip whitespace */
372 	while (isspace(**str))
373 		(*str)++;
374 
375 	if (**str == '\0')
376 		return NULL;
377 
378 	/* boolean literal: #t, #f */
379 	if (**str == '#') {
380 		(*str)++;
381 		char c = **str;
382 		if (c == 't' || c == 'f') {
383 			(*str)++;
384 			return new_boolean_literal(c == 't');
385 		} else {
386 			syslog(LOG_ERR, "unexpected char after #: '%c'",
387 			       c);
388 		}
389 		return NULL;
390 	}
391 
392 	/* integer literal: (-)[0-9]+ */
393 	if (isdigit(**str) || (**str == '-' && isdigit((*str)[1])))
394 		return new_integer_literal(strtol(*str, (char **)str, 10));
395 
396 	/* string literal: "..." */
397 	if (**str == '"') {
398 		const char *begin = *str + 1;
399 		const char *end = strchr(begin, '"');
400 		if (end == NULL) {
401 			syslog(LOG_ERR, "no matching \"");
402 			end = begin;
403 			*str = begin;
404 		} else {
405 			*str = end + 1;
406 		}
407 		return new_string_literal(begin, end);
408 	}
409 
410 	/* compound expression: (expr1 expr2 ...) */
411 	if (**str == '(') {
412 		(*str)++;
413 		struct cras_expr_expression *expr = new_compound_expression();
414 		while (1) {
415 			struct cras_expr_expression *next = parse_one_expr(str);
416 			if (next == NULL)
417 				break;
418 			add_sub_expression(expr, next);
419 		}
420 		if (**str != ')') {
421 			syslog(LOG_ERR, "no matching ): found '%c'", **str);
422 			cras_expr_expression_free(expr);
423 			return NULL;
424 		} else {
425 			(*str)++;
426 		}
427 		return expr;
428 	}
429 
430 	/* variable name */
431 	if (is_identifier_char(**str)) {
432 		const char *begin = *str;
433 		while (is_identifier_char(**str))
434 			(*str)++;
435 		return new_variable(begin, *str);
436 	}
437 
438 	return NULL;
439 }
440 
cras_expr_expression_parse(const char * str)441 struct cras_expr_expression *cras_expr_expression_parse(const char *str)
442 {
443 	if (!str)
444 		return NULL;
445 	return parse_one_expr(&str);
446 }
447 
cras_expr_expression_free(struct cras_expr_expression * expr)448 void cras_expr_expression_free(struct cras_expr_expression *expr)
449 {
450 	if (!expr)
451 		return;
452 
453 	switch (expr->type) {
454 	case EXPR_TYPE_NONE:
455 		break;
456 	case EXPR_TYPE_LITERAL:
457 		cras_expr_value_free(&expr->u.literal);
458 		break;
459 	case EXPR_TYPE_VARIABLE:
460 		free((char *)expr->u.variable);
461 		break;
462 	case EXPR_TYPE_COMPOUND:
463 	{
464 		int i;
465 		struct cras_expr_expression **psub;
466 		FOR_ARRAY_ELEMENT(&expr->u.children, i, psub) {
467 			cras_expr_expression_free(*psub);
468 		}
469 		ARRAY_FREE(&expr->u.children);
470 		break;
471 	}
472 	}
473 	free(expr);
474 }
475 
cras_expr_expression_eval(struct cras_expr_expression * expr,struct cras_expr_env * env,struct cras_expr_value * result)476 void cras_expr_expression_eval(struct cras_expr_expression *expr,
477 			       struct cras_expr_env *env,
478 			       struct cras_expr_value *result)
479 {
480 	cras_expr_value_free(result);
481 
482 	switch (expr->type) {
483 	case EXPR_TYPE_NONE:
484 		break;
485 	case EXPR_TYPE_LITERAL:
486 		copy_value(result, &expr->u.literal);
487 		break;
488 	case EXPR_TYPE_VARIABLE:
489 	{
490 		struct cras_expr_value *value = find_value(env,
491 							   expr->u.variable);
492 		if (value == NULL) {
493 			syslog(LOG_ERR, "cannot find value for %s",
494 			       expr->u.variable);
495 		} else {
496 			copy_value(result, value);
497 		}
498 		break;
499 	}
500 	case EXPR_TYPE_COMPOUND:
501 	{
502 		int i;
503 		struct cras_expr_expression **psub;
504 		cras_expr_value_array values = ARRAY_INIT;
505 		struct cras_expr_value *value;
506 
507 		FOR_ARRAY_ELEMENT(&expr->u.children, i, psub) {
508 			value = ARRAY_APPEND_ZERO(&values);
509 			cras_expr_expression_eval(*psub, env, value);
510 		}
511 
512 		if (ARRAY_COUNT(&values) > 0) {
513 			struct cras_expr_value *f = ARRAY_ELEMENT(&values, 0);
514 			if (f->type == CRAS_EXPR_VALUE_TYPE_FUNCTION)
515 				f->u.function(&values, result);
516 			else
517 				syslog(LOG_ERR,
518 				       "first element is not a function");
519 		} else {
520 			syslog(LOG_ERR, "empty compound expression?");
521 		}
522 
523 		FOR_ARRAY_ELEMENT(&values, i, value) {
524 			cras_expr_value_free(value);
525 		}
526 
527 		ARRAY_FREE(&values);
528 		break;
529 	}
530 	}
531 }
532 
cras_expr_expression_eval_int(struct cras_expr_expression * expr,struct cras_expr_env * env,int * integer)533 int cras_expr_expression_eval_int(struct cras_expr_expression *expr,
534 				  struct cras_expr_env *env,
535 				  int *integer)
536 {
537 	int rc = 0;
538 	struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
539 
540 	cras_expr_expression_eval(expr, env, &value);
541 	if (value.type == CRAS_EXPR_VALUE_TYPE_INT) {
542 		*integer = value.u.integer;
543 	} else {
544 		syslog(LOG_ERR, "value type is not integer (%d)", value.type);
545 		rc = -1;
546 	}
547 	cras_expr_value_free(&value);
548 	return rc;
549 }
550 
cras_expr_expression_eval_boolean(struct cras_expr_expression * expr,struct cras_expr_env * env,char * boolean)551 int cras_expr_expression_eval_boolean(struct cras_expr_expression *expr,
552 				      struct cras_expr_env *env,
553 				      char *boolean)
554 {
555 	int rc = 0;
556 	struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
557 
558 	cras_expr_expression_eval(expr, env, &value);
559 	if (value.type == CRAS_EXPR_VALUE_TYPE_BOOLEAN) {
560 		*boolean = value.u.boolean;
561 	} else {
562 		syslog(LOG_ERR, "value type is not boolean (%d)", value.type);
563 		rc = -1;
564 	}
565 	cras_expr_value_free(&value);
566 	return rc;
567 }
568