From b6c964fb5a00c8b8ab26a4678cdde24c3e9b1d9c Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Tue, 28 Mar 2023 16:48:58 +0200 Subject: Rename cooker and eater with seitan prefix --- cooker/parse.c | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 cooker/parse.c (limited to 'cooker/parse.c') diff --git a/cooker/parse.c b/cooker/parse.c new file mode 100644 index 0000000..9d8a7be --- /dev/null +++ b/cooker/parse.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/* seitan - Syscall Expressive Interpreter, Transformer and Notifier + * + * cooker/parse.c - JSON recipe parsing + * + * Copyright 2023 Red Hat GmbH + * Author: Stefano Brivio + */ + +#include "parson.h" +#include "calls.h" +#include "cooker.h" +#include "gluten.h" +#include "emit.h" +#include "util.h" + +#include "calls/net.h" + +struct rule_parser { + const char *type; + int (*fn)(struct gluten_ctx *g, JSON_Value *value); +}; + +static int parse_match_load(struct gluten_ctx *g, struct arg *a) +{ + if (!a->size || g->match_dst[a->pos].len) + return 0; + + g->match_dst[a->pos].offset = gluten_alloc(g, a->size); + g->match_dst[a->pos].len = a->size; + + emit_load(g, g->match_dst[a->pos].offset, a->pos, a->size); + + return 0; +} + +static long long parse_match_expr_num(struct arg_num *desc, JSON_Value *value) +{ + const char *s = NULL; + long long n; + + if (desc) { + s = json_value_get_string(value); + for (; desc->name && s && strcmp(s, desc->name); desc++); + if (s && !desc->name) + die(" Invalid value %s", s); + + n = desc->value; + } + + if (!s) { + if (json_value_get_type(value) != JSONNumber) + die(" Invalid value type"); + + n = json_value_get_number(value); + } + + return n; +} + +static int parse_match_key(struct gluten_ctx *g, int index, enum arg_type type, + union arg_value desc, JSON_Value *value) +{ + JSON_Object *tmp; + const char *ref; + + (void)index; + + if (json_value_get_type(value) == JSONObject && + (tmp = json_value_get_object(value)) && + (ref = json_object_get_string(tmp, "ref"))) { + debug(" setting reference '%s'", ref); + gluten_alloc_type(g, type); + value = json_object_get_value(tmp, "value"); + } + + if (!value) + return 0; + + switch (type) { + case ARG_INTFLAGS: + case ARG_LONGFLAGS: + case ARG_U32FLAGS: + /* fetch/combine expr algebra loop */ + case ARG_INTMASK: + /* calculate mask first */ + case ARG_INT: + case ARG_LONG: + case ARG_U32: + parse_match_expr_num(desc.d_num, value); + //emit_cmp(...); + default: + ; + } + + return 0; +} + +static int parse_match_arg(struct gluten_ctx *g, const char *name, + JSON_Value *value, struct arg *a) +{ + debug(" Parsing match argument %s", name); + + parse_match_load(g, a); + parse_match_key(g, a->pos, a->type, a->desc, value); + + return 0; +} + +static int parse_match(struct gluten_ctx *g, JSON_Object *obj, struct arg *args) +{ + unsigned count = 0; + struct arg *a; + + for (a = args; a->name; a++) { + JSON_Value *value; + + if ((value = json_object_get_value(obj, a->name))) { + count++; + parse_match_arg(g, a->name, value, a); + } + } + + if (count != json_object_get_count(obj)) + die(" Stray elements in match"); + + return 0; +} + +static int parse_matches(struct gluten_ctx *g, JSON_Value *value) +{ + JSON_Array *matches = json_value_get_array(value); + unsigned i; + + for (i = 0; i < json_array_get_count(matches); i++) { + JSON_Object *match, *args; + struct call **set, *call; + const char *name; + + g->lr = g->ip; + g->sp = 0; + + match = json_array_get_object(matches, i); + name = json_object_get_name(match, 0); + args = json_object_get_object(match, name); + debug(" Parsing match %i: %s", i, name); + + for (set = call_sets, call = set[0]; *set; call++) { + if (!call->name) { + set++; + continue; + } + + if (!strcmp(name, call->name)) { + debug(" Found handler for %s", name); + emit_nr(g, call->number); + + parse_match(g, args, call->args); + break; + } + } + + if (!*set) + die(" Unknown system call: %s", name); + } + + return 0; +} + +static int parse_call(struct gluten_ctx *g, JSON_Value *value) +{ + (void)g; + (void)value; + return 0; +} + +static int parse_inject(struct gluten_ctx *g, JSON_Value *value) +{ + (void)g; + (void)value; + return 0; +} + +struct rule_parser parsers[] = { + { "match", parse_matches }, + { "call", parse_call }, + { "inject", parse_inject }, + { NULL, NULL }, +}; + +static int parse_block(struct gluten_ctx *g, JSON_Object *block) +{ + unsigned i; + + for (i = 0; i < json_object_get_count(block); i++) { + struct rule_parser *parser; + JSON_Value *rule; + const char *type; + + type = json_object_get_name(block, i); + rule = json_object_get_value(block, type); + + for (parser = parsers; parser->type; parser++) { + if (!strcmp(type, parser->type)) { + parser->fn(g, rule); + break; + } + } + + if (!parser->type) + die(" Invalid rule type: \"%s\"", type); + } + + return 0; +} + +int parse_file(struct gluten_ctx *g, const char *path) +{ + JSON_Array *blocks; + JSON_Value *root; + JSON_Object *obj; + unsigned i; + + root = json_parse_file_with_comments(path); + if (json_value_get_type(root) != JSONArray) + die("Invalid input file %s", path); + + blocks = json_value_get_array(root); + for (i = 0; i < json_array_get_count(blocks); i++) { + obj = json_array_get_object(blocks, i); + debug("Parsing block %i", i); + parse_block(g, obj); + } + + return 0; +} -- cgit v1.2.3