diff --git a/src/clang_convert/ast_object/ast_parser.py b/src/clang_convert/ast_object/ast_parser.py index 8cf09f8cf..4baa76c31 100755 --- a/src/clang_convert/ast_object/ast_parser.py +++ b/src/clang_convert/ast_object/ast_parser.py @@ -329,12 +329,13 @@ class AstParser: if_expression = self.parse_ast_node(children[0]) if_action = self.parse_ast_node(children[1]) - if_stmt = if_statement.IfStatement(if_expression, if_action) if child_count == 3: else_statement = self.parse_ast_node(children[2]) - if_stmt.add_else(else_statement) + else: + else_statement = None + if_stmt = if_statement.IfStatement(if_expression, if_action, else_statement) return if_stmt def parse_SWITCH_STMT(self, node): diff --git a/src/clang_convert/code_object/if_statement.py b/src/clang_convert/code_object/if_statement.py index 8577c4781..d4d8c852e 100755 --- a/src/clang_convert/code_object/if_statement.py +++ b/src/clang_convert/code_object/if_statement.py @@ -10,14 +10,15 @@ from utils.string_funcs import strip_semicolon # # expression & action can be a string or a code_interface subclass (or None) class IfStatement(code_interface.CodeInterface): - def __init__(self, expression, action) -> None: + def __init__(self, expression, action, else_statement) -> None: self._expression = expression assert isinstance(self._expression, code_interface.CodeInterface), f"Expression must be a CodeInterface class" self._action = action assert isinstance(self._action, code_interface.CodeInterface), f"Action must be a CodeInterface class" - self._else = None + self._else_statement = else_statement + assert self._else_statement is None or isinstance(self._else_statement, code_interface.CodeInterface), f"Else statement must be a CodeInterface class" @property def expression(self): @@ -29,11 +30,7 @@ class IfStatement(code_interface.CodeInterface): @property def else_statement(self): - return self._else - - def add_else(self, else_statement): - self._else = else_statement - assert isinstance(self._else, code_interface.CodeInterface), f"Else statement must be a CodeInterface class" + return self._else_statement def as_lines(self): if_lines = [] @@ -48,8 +45,8 @@ class IfStatement(code_interface.CodeInterface): action_lines.extend(self._action.as_lines()) else_lines = [] - if self._else: - else_lines.extend(self._else.as_lines()) + if self._else_statement: + else_lines.extend(self._else_statement.as_lines()) else_lines[0] = "else " + else_lines[0] return if_lines + action_lines + else_lines \ No newline at end of file diff --git a/src/clang_convert/code_object_converter/if_statement_converter.py b/src/clang_convert/code_object_converter/if_statement_converter.py index 501ae8f73..de4a35c2b 100755 --- a/src/clang_convert/code_object_converter/if_statement_converter.py +++ b/src/clang_convert/code_object_converter/if_statement_converter.py @@ -19,10 +19,8 @@ class IfStatementConverter(code_interface_converter.CodeInterfaceConverter): debug.line("create_cpp_code_object", f"C expression=[{debug.as_debug_string(self._ccode_object.expression)}] converted to NONE_VALUE: setting to false") cpp_expression = literal.Literal("false") - cpp_if = if_statement.IfStatement(cpp_expression, cpp_action) + cpp_else = conversion_funcs.convert_ccode_object(self._ccode_object.else_statement, conversion_pack) - if self._ccode_object.else_statement: - cpp_else = conversion_funcs.convert_ccode_object(self._ccode_object.else_statement, conversion_pack) - cpp_if.add_else(cpp_else) + cpp_if = if_statement.IfStatement(cpp_expression, cpp_action, cpp_else) return conversion_pack.conversion_validation.validate_if_statement(self._ccode_object, cpp_if) diff --git a/src/clang_convert/default/default_conversion_pack/default_conversion_validation.py b/src/clang_convert/default/default_conversion_pack/default_conversion_validation.py index b4cf8ad4b..7b6363417 100755 --- a/src/clang_convert/default/default_conversion_pack/default_conversion_validation.py +++ b/src/clang_convert/default/default_conversion_pack/default_conversion_validation.py @@ -13,6 +13,7 @@ import code_object.variable_declaration as variable_declaration import code_object.paren_expression as paren_expression import code_object.array_access as array_access import code_object.if_statement as if_statement +import code_object.struct_member_access as struct_member_access from code_object_converter.conversion_utils import as_commented_out_code from utils.string_funcs import is_number import code_object.cast_expression as cast_expression @@ -205,10 +206,15 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): # We are assigning a container value to a pointer arg, so need to call .data() cppright = literal.Literal(f"{right_cpparg.name}.data()") return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) + if not left_cpparg.decl_spec.pointer: - # We are assigning a container value to a basic variable, so use index 0 - cppright = array_access.ArrayAccess(literal.Literal(right_cpparg.name), literal.Literal("0")) - return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) + if isinstance(cppright, array_access.ArrayAccess) or \ + isinstance(cppright, struct_member_access.StructMemberAccess): + debug.line("validate_binary_operation", f"Container assignment check OK, using cppbinary_operation=[{debug.as_debug_string(cppbinary_operation)}]") + else: + # We are assigning a container value to a basic variable, so use index 0 + cppright = array_access.ArrayAccess(literal.Literal(right_cpparg.name), literal.Literal("0")) + return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright) elif cppbinary_op.is_comparison(): cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data) @@ -271,7 +277,7 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): value_cpparg = arg_utils.to_cpparg(cppvariable_declaration.value, self._conversion_data) if variable_cpparg and value_cpparg: - debug.line("validate_variable_declaration", f"Container assignment check: variable_cpparg=[{debug.as_debug_string(variable_cpparg)}] value_cpparg=[{debug.as_debug_string(value_cpparg)}] ") + debug.line("validate_variable_declaration", f"Container assignment check [1]: variable_cpparg=[{debug.as_debug_string(variable_cpparg)}] value_cpparg=[{debug.as_debug_string(value_cpparg)}]") if self._conversion_data.is_container_type(value_cpparg.decl_spec.type) and \ not self._conversion_data.is_container_type(variable_cpparg.decl_spec.type): if variable_cpparg.decl_spec.is_raw_pointer(): @@ -279,9 +285,14 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): updated_value = literal.Literal(f"{value_cpparg.name}.data()") return variable_declaration.VariableDeclaration(cppvariable, updated_value) if not variable_cpparg.decl_spec.pointer: - # We are assigning a container value to a basic variable, so use index 0 - updated_value = array_access.ArrayAccess(literal.Literal(value_cpparg.name), literal.Literal("0")) - return variable_declaration.VariableDeclaration(cppvariable, updated_value) + if isinstance(cppvariable_declaration.value, array_access.ArrayAccess) or \ + isinstance(cppvariable_declaration.value, struct_member_access.StructMemberAccess): + pass + else: + # We are assigning a container value to a basic variable, so use index 0 + updated_value = array_access.ArrayAccess(literal.Literal(value_cpparg.name), literal.Literal("0")) + debug.line("validate_variable_declaration", f"Container assignment check [2]: updated_value=[{debug.as_debug_string(updated_value)}] because cppvariable_declaration.value type=[{cppvariable_declaration.value}]") + return variable_declaration.VariableDeclaration(cppvariable, updated_value) return cppvariable_declaration @@ -289,7 +300,7 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation): cppexpression = self.try_to_make_boolean(cppif_statement.expression) - return if_statement.IfStatement(cppexpression, cppif_statement.action) + return if_statement.IfStatement(cppexpression, cppif_statement.action, cppif_statement.else_statement) # Helper to determine how a container should receive the value returned by the function diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_conversion_validation.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_conversion_validation.py index e906c14cf..eeed428d6 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_conversion_validation.py +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_conversion_validation.py @@ -168,7 +168,15 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv updated_cppfunction_call = function_call.FunctionCall("copyBuffer", updated_args) debug.line("apply_special_function_call_conversions", f"Updated memcpy: [{debug.as_debug_string(cppfunction_call)}]->[{debug.as_debug_string(updated_cppfunction_call)}]") return updated_cppfunction_call - + + # Convert from: snprintf(result, 1024, "+proj=longlat +datum=WGS84 +no_defs +type=crs", ...); + # to : result = fmtString("+proj=longlat +datum=WGS84 +no_defs +type=crs", ...); + if cppfunction_call.name == "snprintf": + fmtString_call = function_call.FunctionCall("fmtString", cppfunction_call.args[2:]) + snprintf_call = binary_operation.BinaryOperation(cppfunction_call.args[0], "=", fmtString_call) + + debug.line("apply_special_function_call_conversions", f"Updated snprintf: [{debug.as_debug_string(cppfunction_call)}]->[{debug.as_debug_string(snprintf_call)}]") + return snprintf_call return None @@ -215,8 +223,8 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv expression_value = cppif_statement.expression.as_string() cpparg = self._conversion_data.funcbody_cpparg_for_carg_name(expression_value) if cpparg and cpparg != NONE_VALUE and cpparg.decl_spec.type == "GribStatus": - updated_expression = literal.Literal(f"GribStatusSuccess({cpparg.name})") - updated_cppif_statement = if_statement.IfStatement(updated_expression, cppif_statement.action) + updated_expression = literal.Literal(f"GribStatusError({cpparg.name})") + updated_cppif_statement = if_statement.IfStatement(updated_expression, cppif_statement.action, cppif_statement.else_statement) debug.line("validate_if_statement", f"updated_cppif_statement=[{debug.as_debug_string(updated_cppif_statement)}]") return updated_cppif_statement @@ -306,7 +314,7 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv if cppcode_object.unary_op.value == "!": updated_expression = literal.Literal(f"GribStatusSuccess({cpparg.name})") else: - updated_expression = literal.Literal(f"!GribStatusSuccess({cpparg.name})") + updated_expression = literal.Literal(f"GribStatusError({cpparg.name})") debug.line("apply_special_unary_operation_conversion", f"Updating GribStatus error: [{debug.as_debug_string(cppcode_object)}]->[{debug.as_debug_string(updated_expression)}]") return updated_expression @@ -315,7 +323,7 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv cppfuncsig = self._conversion_data.cppfuncsig_for_cppfuncname(cppcode_object.name) if cppfuncsig: if cppfuncsig.return_type.type == "GribStatus": - updated_cppcode_object = literal.Literal(f"GribStatusSuccess({cppcode_object.as_string()})") + updated_cppcode_object = literal.Literal(f"GribStatusError({cppcode_object.as_string()})") return updated_cppcode_object return super().try_to_make_boolean(cppcode_object) \ No newline at end of file diff --git a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_special_function_call_conversion.py b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_special_function_call_conversion.py index 23ac7eb33..cce398186 100755 --- a/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_special_function_call_conversion.py +++ b/src/clang_convert/grib_accessor/grib_accessor_conversion_pack/grib_accessor_special_function_call_conversion.py @@ -1,6 +1,5 @@ special_function_name_mapping = { - "snprintf" : "fmtString", "strtol" : "strToLong", "strtod" : "strToDouble", "atol" : "strAtoL", diff --git a/src/cpp/eccodes/accessor/AccessorUtils/ConversionHelper.h b/src/cpp/eccodes/accessor/AccessorUtils/ConversionHelper.h index db0814fb7..23808fc14 100644 --- a/src/cpp/eccodes/accessor/AccessorUtils/ConversionHelper.h +++ b/src/cpp/eccodes/accessor/AccessorUtils/ConversionHelper.h @@ -22,8 +22,8 @@ std::string fmtString(std::string format, Args... args) { // Determine buffer size size_t formatSize = snprintf(nullptr, 0, format.c_str(), args...); - char buf[formatSize]; - snprintf(buf, formatSize, format.c_str(), args...); + char buf[formatSize+1]; + snprintf(buf, sizeof(buf), format.c_str(), args...); return std::string(buf); } diff --git a/src/cpp/eccodes/accessor/GribCpp/GribStatus.cc b/src/cpp/eccodes/accessor/GribCpp/GribStatus.cc index 2e3593825..01be8744a 100644 --- a/src/cpp/eccodes/accessor/GribCpp/GribStatus.cc +++ b/src/cpp/eccodes/accessor/GribCpp/GribStatus.cc @@ -8,4 +8,9 @@ bool GribStatusSuccess(GribStatus stat) return stat == GribStatus::SUCCESS; } +bool GribStatusError(GribStatus stat) +{ + return stat != GribStatus::SUCCESS; +} + } diff --git a/src/cpp/eccodes/accessor/GribCpp/GribStatus.h b/src/cpp/eccodes/accessor/GribCpp/GribStatus.h index 2475b74de..7b480e5f7 100644 --- a/src/cpp/eccodes/accessor/GribCpp/GribStatus.h +++ b/src/cpp/eccodes/accessor/GribCpp/GribStatus.h @@ -87,5 +87,6 @@ enum class GribStatus{ // Helper for the conversion process bool GribStatusSuccess(GribStatus stat); +bool GribStatusError(GribStatus stat); } diff --git a/src/grib_accessor.cc b/src/grib_accessor.cc index de64cc4e4..56b7b4066 100644 --- a/src/grib_accessor.cc +++ b/src/grib_accessor.cc @@ -315,8 +315,9 @@ int grib_unpack_string(grib_accessor* a, char* v, size_t* len) int ret = c->unpack_string(a, v, len); if(auto accessorPtr = eccodes::accessor::get(eccodes::accessor::AccessorName(a->name)); accessorPtr) { - std::string value = accessorPtr->unpack(); - if(value != std::string(v, *len)) { Assert(false); } + std::string cvalue = std::string(v, *len); + std::string cppvalue = accessorPtr->unpack(); + if(cvalue != cppvalue) { Assert(false); } } return ret; #else