From e011b04c6b2e31bdc46320e5d8a4f48715681f15 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 12 Jan 2022 02:58:02 +0100 Subject: libosmo-gtlv: add C code generator for IE structs and arrays Defining a protocol of message types with lists of IEs bears a lot of repetitive, copy-paste-error-prone writing out of data structures. Add a third layer to libosmo-gtlv, which allows helpful code generation. By non-repetitive data structures that briefly describe the protocol's messages and IEs, generate possibly repetitive IE list arrays and decoded-struct definitions automatically, avoiding grunt work errors. I tried C macros for this at first, but it became too convoluted. Generating C code that can be read and grepped makes things easier. A usage example is found in tests/libosmo-gtlv/test_gtlv_gen/. Related: SYS#5599 Change-Id: Ifb3ea54d2797ce060b95834aa117725ec2d6c4cf --- .../test_gtlv_gen/gen__myproto_ies_auto.c | 114 +++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c (limited to 'tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c') diff --git a/tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c b/tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c new file mode 100644 index 0000000..75d657d --- /dev/null +++ b/tests/libosmo-gtlv/test_gtlv_gen/gen__myproto_ies_auto.c @@ -0,0 +1,114 @@ +/* + * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH + * All Rights Reserved. + * + * Author: Neels Janosch Hofmeyr + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include + +#define O OSMO_GTLV_GEN_O +#define M OSMO_GTLV_GEN_M +#define O_MULTI OSMO_GTLV_GEN_O_MULTI +#define M_MULTI OSMO_GTLV_GEN_M_MULTI + +#define ALL_FROM_NAME osmo_gtlv_gen_ie_auto + +/* An IE where the type is not a 'struct myproto_ie_${name}'. */ +static const struct osmo_gtlv_gen_ie number = { + .decoded_type = "int", /* add 'int foo;' to the struct */ + .dec_enc = "u16", /* use myproto_dec_u16() and myproto_enc_u16() for the TLV value part */ + .spec_ref = "an int coded as uint16_t", +}; + +static const struct osmo_gtlv_gen_ie_o ies_in_moo_nest[] = { + /* Mandatory member xxx.foo of the type defined in 'number' above. */ + M(number, "foo"), + /* Mandatory member xxx.bar of type 'struct myproto_ie_bar', using myproto_ie_dec_bar(), myproto_ie_enc_bar(), + * myproto_ie_enc_to_str_bar(), all defined in myproto_ies_custom.h/c. */ + M(ALL_FROM_NAME, "bar"), + M(ALL_FROM_NAME, "baz"), + {} +}; + +static const struct osmo_gtlv_gen_ie huge_number = { + .decoded_type = "uint64_t", + .dec_enc = "u64", +}; + +static const struct osmo_gtlv_gen_ie moo_nest = { + .tag_name = "moo_nest", + .nested_ies = ies_in_moo_nest, +}; + +static const struct osmo_gtlv_gen_ie_o ies_in_goo_nest[] = { + O(huge_number, "val"), + M(moo_nest, "nest"), + {} +}; + +static const struct osmo_gtlv_gen_ie goo_nest = { + .tag_name = "goo_nest", + .nested_ies = ies_in_goo_nest, +}; + +static const struct osmo_gtlv_gen_ie_o ies_in_moo_msg[] = { + M(number, "foo"), + M(ALL_FROM_NAME, "bar"), + O(ALL_FROM_NAME, "baz"), + O_MULTI(32, number, "repeat_int"), + O_MULTI(32, ALL_FROM_NAME, "repeat_struct"), + O(moo_nest, "nest"), + {} +}; + +static const struct osmo_gtlv_gen_ie_o ies_in_goo_msg[] = { + M(number, "foo"), + O(ALL_FROM_NAME, "bar"), + O_MULTI(8, goo_nest, "nest"), + {} +}; + +static const struct osmo_gtlv_gen_msg msg_defs[] = { + { "moo", ies_in_moo_msg }, + { "goo", ies_in_goo_msg }, + {} +}; + +int main(int argc, const char **argv) +{ + struct osmo_gtlv_gen_cfg cfg = { + .proto_name = "myproto", + .message_type_enum = "enum myproto_msg_type", + .message_type_prefix = "MYPROTO_MSGT_", + .tag_enum = "enum myproto_iei", + .tag_prefix = "MYPROTO_IEI_", + .decoded_type_prefix = "struct myproto_ie_", + .h_header = "#include \"myproto_ies_custom.h\"", + .c_header = "#include ", + .msg_defs = msg_defs, + .add_enc_to_str = true, + }; + return osmo_gtlv_gen_main(&cfg, argc, argv); +} -- cgit v1.2.3