diff --git a/samples/pet/src/pet_decode.c b/samples/pet/src/pet_decode.c index bfb53ad0..7e26bb80 100644 --- a/samples/pet/src/pet_decode.c +++ b/samples/pet/src/pet_decode.c @@ -37,13 +37,19 @@ static bool decode_Pet( { zcbor_log("%s\r\n", __func__); - bool res = (((zcbor_list_start_decode(state) && ((((zcbor_list_start_decode(state) && ((zcbor_multi_decode(1, 3, &(*result).names_count, (zcbor_decoder_t *)zcbor_tstr_decode, state, (&(*result).names), sizeof(struct zcbor_string))) || (zcbor_list_map_end_force_decode(state), false)) && zcbor_list_end_decode(state))) + bool res = (((zcbor_list_start_decode(state) && ((((zcbor_list_start_decode(state) && ((zcbor_multi_decode(1, 3, &(*result).names_count, (zcbor_decoder_t *)zcbor_tstr_decode, state, (*&(*result).names), sizeof(struct zcbor_string))) || (zcbor_list_map_end_force_decode(state), false)) && zcbor_list_end_decode(state))) && ((zcbor_bstr_decode(state, (&(*result).birthday))) && ((((((*result).birthday.len == 8)) || (zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false))) || (zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false))) && ((((zcbor_uint_decode(state, &(*result).species_choice, sizeof((*result).species_choice)))) && ((((((*result).species_choice == Pet_species_cat_c) && ((1))) || (((*result).species_choice == Pet_species_dog_c) && ((1))) || (((*result).species_choice == Pet_species_other_c) && ((1)))) || (zcbor_error(state, ZCBOR_ERR_WRONG_VALUE), false)))))) || (zcbor_list_map_end_force_decode(state), false)) && zcbor_list_end_decode(state)))); + if (false) { + /* For testing that the types of the arguments are correct. + A compiler error here means a bug in zcbor. */ + zcbor_tstr_decode(state, (*&(*result).names)); + } + log_result(state, res, __func__); return res; } diff --git a/samples/pet/src/pet_encode.c b/samples/pet/src/pet_encode.c index 70e509e2..894ab883 100644 --- a/samples/pet/src/pet_encode.c +++ b/samples/pet/src/pet_encode.c @@ -37,7 +37,7 @@ static bool encode_Pet( { zcbor_log("%s\r\n", __func__); - bool res = (((zcbor_list_start_encode(state, 3) && ((((zcbor_list_start_encode(state, 3) && ((zcbor_multi_encode_minmax(1, 3, &(*input).names_count, (zcbor_encoder_t *)zcbor_tstr_encode, state, (&(*input).names), sizeof(struct zcbor_string))) || (zcbor_list_map_end_force_encode(state), false)) && zcbor_list_end_encode(state, 3))) + bool res = (((zcbor_list_start_encode(state, 3) && ((((zcbor_list_start_encode(state, 3) && ((zcbor_multi_encode_minmax(1, 3, &(*input).names_count, (zcbor_encoder_t *)zcbor_tstr_encode, state, (*&(*input).names), sizeof(struct zcbor_string))) || (zcbor_list_map_end_force_encode(state), false)) && zcbor_list_end_encode(state, 3))) && (((((((*input).birthday.len == 8)) || (zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false))) || (zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false)) && (zcbor_bstr_encode(state, (&(*input).birthday)))) && ((((*input).species_choice == Pet_species_cat_c) ? ((zcbor_uint32_put(state, (1)))) diff --git a/zcbor/zcbor.py b/zcbor/zcbor.py index 05c17c65..8e2a16a1 100755 --- a/zcbor/zcbor.py +++ b/zcbor/zcbor.py @@ -14,7 +14,7 @@ from argparse import ArgumentParser, ArgumentTypeError, RawDescriptionHelpFormatter, FileType from datetime import datetime from copy import copy -from itertools import tee +from itertools import tee, chain from cbor2 import (loads, dumps, CBORTag, load, CBORDecodeValueError, CBORDecodeEOF, undefined, CBORSimpleValue) from yaml import safe_load as yaml_load, dump as yaml_dump @@ -2599,7 +2599,8 @@ def full_xcode(self, union_int=None): f"zcbor_present_decode(&(%s), (zcbor_decoder_t *)%s, %s)" % (self.present_var_access(), func, xcode_args(*arguments),)) elif self.count_var_condition(): - func, *arguments = self.repeated_single_func(ptr_result=True) + func, arg = self.repeated_single_func(ptr_result=True) + minmax = "_minmax" if self.mode == "encode" else "" mode = self.mode return ( @@ -2608,7 +2609,7 @@ def full_xcode(self, union_int=None): self.max_qty, self.count_var_access(), func, - xcode_args(*arguments), + xcode_args("*" + arg if arg != "NULL" and self.result_len() != "0" else arg), self.result_len())) else: return self.repeated_xcode(union_int) @@ -2755,6 +2756,32 @@ def render_forward_declaration(self, xcoder, mode): def render_function(self, xcoder, mode): body = xcoder.body + + # Define the subroutine "paren" that matches parenthesised expressions. + paren_re = r'(?(DEFINE)(?P\(((?>[^\(\)]+|(?&paren))*)\)))' + # This uses "paren" to match a single argument to a function. + arg_re = rf'([^,\(\)]|(?&paren))+' + # Match a function pointer argument to a function. + func_re = rf'\(zcbor_(en|de)coder_t \*\)(?P{arg_re})' + # Match a triplet of function pointer, state arg, and result arg. + call_re = rf'{func_re}, (?P{arg_re}), (?P{arg_re})' + multi_re = rf'{paren_re}zcbor_multi_(en|de)code\(({arg_re},){{3}} {call_re}' + present_re = rf'{paren_re}zcbor_present_(en|de)code\({arg_re}, {call_re}\)' + map_re = rf'{paren_re}zcbor_unordered_map_search\({call_re}\)' + all_funcs = chain(getrp(multi_re).finditer(body), + getrp(present_re).finditer(body), + getrp(map_re).finditer(body)) + arg_test = "" + calls = ("\n ".join( + (f"{m.group('func')}({m.group('state')}, {m.group('arg')});" for m in (all_funcs)))) + if calls != "": + arg_test = f""" + if (false) {{ + /* For testing that the types of the arguments are correct. + A compiler error here means a bug in zcbor. */ + {calls} + }} +""" return f""" static bool {xcoder.func_name}( zcbor_state_t *state, {"" if mode == "decode" else "const "}{ @@ -2766,7 +2793,7 @@ def render_function(self, xcoder, mode): {"bool int_res;" if "int_res" in body else ""} bool res = ({body}); - +{arg_test} log_result(state, res, __func__); return res; }}""".replace(" \n", "") # call replace() to remove empty lines.