linux/tools/perf/util/expr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <stdbool.h>
   3#include <assert.h>
   4#include "expr.h"
   5#include "expr-bison.h"
   6#define YY_EXTRA_TYPE int
   7#include "expr-flex.h"
   8
   9#ifdef PARSER_DEBUG
  10extern int expr_debug;
  11#endif
  12
  13/* Caller must make sure id is allocated */
  14void expr__add_id(struct parse_ctx *ctx, const char *name, double val)
  15{
  16        int idx;
  17
  18        assert(ctx->num_ids < MAX_PARSE_ID);
  19        idx = ctx->num_ids++;
  20        ctx->ids[idx].name = name;
  21        ctx->ids[idx].val = val;
  22}
  23
  24void expr__ctx_init(struct parse_ctx *ctx)
  25{
  26        ctx->num_ids = 0;
  27}
  28
  29static int
  30__expr__parse(double *val, struct parse_ctx *ctx, const char *expr,
  31              int start)
  32{
  33        YY_BUFFER_STATE buffer;
  34        void *scanner;
  35        int ret;
  36
  37        ret = expr_lex_init_extra(start, &scanner);
  38        if (ret)
  39                return ret;
  40
  41        buffer = expr__scan_string(expr, scanner);
  42
  43#ifdef PARSER_DEBUG
  44        expr_debug = 1;
  45#endif
  46
  47        ret = expr_parse(val, ctx, scanner);
  48
  49        expr__flush_buffer(buffer, scanner);
  50        expr__delete_buffer(buffer, scanner);
  51        expr_lex_destroy(scanner);
  52        return ret;
  53}
  54
  55int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr)
  56{
  57        return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0;
  58}
  59
  60static bool
  61already_seen(const char *val, const char *one, const char **other,
  62             int num_other)
  63{
  64        int i;
  65
  66        if (one && !strcasecmp(one, val))
  67                return true;
  68        for (i = 0; i < num_other; i++)
  69                if (!strcasecmp(other[i], val))
  70                        return true;
  71        return false;
  72}
  73
  74int expr__find_other(const char *expr, const char *one, const char ***other,
  75                     int *num_other)
  76{
  77        int err, i = 0, j = 0;
  78        struct parse_ctx ctx;
  79
  80        expr__ctx_init(&ctx);
  81        err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER);
  82        if (err)
  83                return -1;
  84
  85        *other = malloc((ctx.num_ids + 1) * sizeof(char *));
  86        if (!*other)
  87                return -ENOMEM;
  88
  89        for (i = 0, j = 0; i < ctx.num_ids; i++) {
  90                const char *str = ctx.ids[i].name;
  91
  92                if (already_seen(str, one, *other, j))
  93                        continue;
  94
  95                str = strdup(str);
  96                if (!str)
  97                        goto out;
  98                (*other)[j++] = str;
  99        }
 100        (*other)[j] = NULL;
 101
 102out:
 103        if (i != ctx.num_ids) {
 104                while (--j)
 105                        free((char *) (*other)[i]);
 106                free(*other);
 107                err = -1;
 108        }
 109
 110        *num_other = j;
 111        return err;
 112}
 113