112 lines · 2.1 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0#include <stdbool.h>#include <assert.h>#include "expr.h"#include "expr-bison.h"#define YY_EXTRA_TYPE int#include "expr-flex.h" #ifdef PARSER_DEBUGextern int expr_debug;#endif /* Caller must make sure id is allocated */void expr__add_id(struct parse_ctx *ctx, const char *name, double val){	int idx; 	assert(ctx->num_ids < MAX_PARSE_ID);	idx = ctx->num_ids++;	ctx->ids[idx].name = name;	ctx->ids[idx].val = val;} void expr__ctx_init(struct parse_ctx *ctx){	ctx->num_ids = 0;} static int__expr__parse(double *val, struct parse_ctx *ctx, const char *expr,	      int start){	YY_BUFFER_STATE buffer;	void *scanner;	int ret; 	ret = expr_lex_init_extra(start, &scanner);	if (ret)		return ret; 	buffer = expr__scan_string(expr, scanner); #ifdef PARSER_DEBUG	expr_debug = 1;#endif 	ret = expr_parse(val, ctx, scanner); 	expr__flush_buffer(buffer, scanner);	expr__delete_buffer(buffer, scanner);	expr_lex_destroy(scanner);	return ret;} int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr){	return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0;} static boolalready_seen(const char *val, const char *one, const char **other,	     int num_other){	int i; 	if (one && !strcasecmp(one, val))		return true;	for (i = 0; i < num_other; i++)		if (!strcasecmp(other[i], val))			return true;	return false;} int expr__find_other(const char *expr, const char *one, const char ***other,		     int *num_other){	int err, i = 0, j = 0;	struct parse_ctx ctx; 	expr__ctx_init(&ctx);	err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER);	if (err)		return -1; 	*other = malloc((ctx.num_ids + 1) * sizeof(char *));	if (!*other)		return -ENOMEM; 	for (i = 0, j = 0; i < ctx.num_ids; i++) {		const char *str = ctx.ids[i].name; 		if (already_seen(str, one, *other, j))			continue; 		str = strdup(str);		if (!str)			goto out;		(*other)[j++] = str;	}	(*other)[j] = NULL; out:	if (i != ctx.num_ids) {		while (--j)			free((char *) (*other)[i]);		free(*other);		err = -1;	} 	*num_other = j;	return err;}