From 58033b86f03f010d73c1080760950414b9c5ca0f Mon Sep 17 00:00:00 2001 From: Oliver Kellogg Date: Tue, 5 Nov 2024 23:18:14 +0100 Subject: [PATCH] https://github.com/eclipse-cyclonedds/cyclonedds/issues/2123 - Create branch issue-2123-add-deepcopy-func from master @ d8cef89 - Work in progress, build currently fails on compiling CdrStreamOptimize.c generated for src/core/ddsc/tests/ CdrStreamOptimize.idl. src/idl/include/idl/tree.h src/idl/src/tree.c - Add function idl_is_scalar_type. src/core/ddsc/include/dds/ddsc/dds_public_alloc.h - Add defines for __alloc functions of primitive types. src/tools/idlc/src/libidlc/libidlc__generator.c - In function print_includes add generation of #include for strcat() / strcpy() required by libidlc__types.c emit_struct() added generation of _copy function. src/tools/idlc/src/libidlc/libidlc__types.c - In various emit() functions remove superfluous ending semicolon in generated __alloc() macros. - In function emit_implicit_sequence add generation of _copy function. - In function emit_struct start adding generation of _copy function. Generation for @optional and @external members is work in progress and struct supertypes have not yet been considered. Also, have not started adding _copy generation in emit_union(). --- .../ddsc/include/dds/ddsc/dds_public_alloc.h | 14 ++ src/idl/include/idl/tree.h | 3 +- src/idl/src/tree.c | 17 ++ .../idlc/src/libidlc/libidlc__generator.c | 2 + src/tools/idlc/src/libidlc/libidlc__types.c | 204 ++++++++++++++++-- 5 files changed, 216 insertions(+), 24 deletions(-) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_alloc.h b/src/core/ddsc/include/dds/ddsc/dds_public_alloc.h index 68ba6302a5..c1549d58dc 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_alloc.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_alloc.h @@ -159,6 +159,20 @@ DDS_EXPORT void dds_string_free (char * str); */ DDS_EXPORT void dds_sample_free (void * sample, const struct dds_topic_descriptor * desc, dds_free_op_t op); +#define bool__alloc() (bool *)dds_alloc(sizeof(bool)) +#define char__alloc() (char *)dds_alloc(sizeof(char)) +#define octet__alloc() (octet *)dds_alloc(sizeof(octet)) +#define int8_t__alloc() (int8_t *)dds_alloc(sizeof(int8_t)) +#define uint8_t__alloc() (uint8_t *)dds_alloc(sizeof(uint8_t)) +#define int16_t__alloc() (int16_t *)dds_alloc(sizeof(int16_t)) +#define uint16_t__alloc() (uint16_t *)dds_alloc(sizeof(uint16_t)) +#define int32_t__alloc() (int32_t *)dds_alloc(sizeof(int32_t)) +#define uint32_t__alloc() (uint32_t *)dds_alloc(sizeof(uint32_t)) +#define int64_t__alloc() (int64_t *)dds_alloc(sizeof(int64_t)) +#define uint64_t__alloc() (uint64_t *)dds_alloc(sizeof(uint64_t)) +#define float__alloc() (float *)dds_alloc(sizeof(float)) +#define double__alloc() (double *)dds_alloc(sizeof(double)) + #if defined (__cplusplus) } #endif diff --git a/src/idl/include/idl/tree.h b/src/idl/include/idl/tree.h index 3bc125c384..053b66430b 100644 --- a/src/idl/include/idl/tree.h +++ b/src/idl/include/idl/tree.h @@ -25,7 +25,7 @@ contain the result from an expression, pragmas contain compiler-specific instructions that apply to a specific declaration, much like annotations. the exact type of a node is stored in the mask property of the base node - and is an constructed by combining preprocessor defines. unique bits are + and is constructed by combining preprocessor defines. unique bits are reserved for categories and properties that generators are likely to filter on when applying a visitor pattern. */ @@ -522,6 +522,7 @@ IDL_EXPORT bool idl_is_type_spec(const void *node); IDL_EXPORT bool idl_is_base_type(const void *node); IDL_EXPORT bool idl_is_floating_pt_type(const void *node); IDL_EXPORT bool idl_is_integer_type(const void *node); +IDL_EXPORT bool idl_is_scalar_type(const void *node); IDL_EXPORT bool idl_is_templ_type(const void *node); IDL_EXPORT bool idl_is_bounded(const void *node); IDL_EXPORT bool idl_is_sequence(const void *node); diff --git a/src/idl/src/tree.c b/src/idl/src/tree.c index b060576be7..76dee37c73 100644 --- a/src/idl/src/tree.c +++ b/src/idl/src/tree.c @@ -760,6 +760,23 @@ bool idl_is_integer_type(const void *node) return (idl_mask(node) & IDL_INTEGER_TYPE) != 0; } +bool idl_is_scalar_type(const void *node) +{ + idl_mask_t mask; + if (idl_mask(node) & IDL_DECLARATOR) + node = idl_parent(node); + mask = idl_mask(node); + if (mask & (IDL_BASE_TYPE|IDL_ENUM|IDL_ENUMERATOR|IDL_BITMASK)) + return (mask != IDL_ANY); + if (!(mask & IDL_TYPEDEF)) + return false; + { + idl_typedef_t *_typedef = (idl_typedef_t*) node; + void *type_spec = idl_unalias(_typedef->type_spec); + return idl_is_scalar_type(type_spec); + } +} + static void delete_base_type(void *ptr) { idl_free(ptr); diff --git a/src/tools/idlc/src/libidlc/libidlc__generator.c b/src/tools/idlc/src/libidlc/libidlc__generator.c index 9da6699467..4e239fa391 100644 --- a/src/tools/idlc/src/libidlc/libidlc__generator.c +++ b/src/tools/idlc/src/libidlc/libidlc__generator.c @@ -115,6 +115,8 @@ static idl_retcode_t print_includes(FILE *fh, const idl_source_t *source) return IDL_RETCODE_NO_MEMORY; } + if (fputs("#include \n\n", fh) < 0) + return IDL_RETCODE_NO_MEMORY; return IDL_RETCODE_OK; } diff --git a/src/tools/idlc/src/libidlc/libidlc__types.c b/src/tools/idlc/src/libidlc/libidlc__types.c index 3a20eda23a..b0c907aa5f 100644 --- a/src/tools/idlc/src/libidlc/libidlc__types.c +++ b/src/tools/idlc/src/libidlc/libidlc__types.c @@ -95,13 +95,47 @@ emit_implicit_sequence( " bool _release;\n" "} %2$s;\n\n" "#define %2$s__alloc() \\\n" - "((%2$s*) dds_alloc (sizeof (%2$s)));\n\n" + "((%2$s*) dds_alloc (sizeof (%2$s)))\n\n" "#define %2$s_allocbuf(l) \\\n" - "((%3$s%4$s %5$s%6$s*%7$s%8$s) dds_alloc ((l) * sizeof (%3$s%4$s%5$s%8$s)))\n" - "#endif /* %1$s_DEFINED */\n\n"; + "((%3$s%4$s %5$s%6$s*%7$s%8$s) dds_alloc ((l) * sizeof (%3$s%4$s%5$s%8$s)))\n"; if (idl_fprintf(gen->header.handle, fmt, macro, name, type_prefix, type, star, lpar, rpar, dims) < 0) return IDL_RETCODE_NO_MEMORY; + /* generate function _copy() */ + if (gen->config.export_macro && idl_fprintf(gen->header.handle, "%1$s ", gen->config.export_macro) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = "extern void %1$s_copy(%1$s *d, const %1$s *s);\n\n"; + if (idl_fprintf(gen->header.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = "void %1$s_copy(%1$s *d, const %1$s *s) {\n"; + if (idl_fprintf(gen->source.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = /* " size_t elemsize = sizeof (%1$s%2$s);\n" */ + " %1$s%2$s *dptr = %3$s_allocbuf(s->_maximum);\n" + " const %1$s%2$s *sptr = (const %1$s%2$s *)s->_buffer;\n" + " d->_maximum = s->_maximum;\n" + " d->_length = s->_length;\n" + " d->_release = true;\n" + " d->_buffer = dptr;\n" + " for (unsigned i = 0; i < s->_length; i++) {\n"; + if (idl_fprintf(gen->source.handle, fmt, type_prefix, type, name) < 0) + return IDL_RETCODE_NO_MEMORY; + if (idl_is_scalar_type(type_spec)) { + if (idl_fprintf(gen->source.handle, " *(dptr + i) = *(sptr + i);\n") < 0) + return IDL_RETCODE_NO_MEMORY; + } else { + fmt = " %1$s_copy(dptr + i, sptr + i);\n"; + if (idl_fprintf(gen->source.handle, fmt, type) < 0) + return IDL_RETCODE_NO_MEMORY; + } + if (idl_fprintf(gen->source.handle, " }\n") < 0) + return IDL_RETCODE_NO_MEMORY; + if (idl_fprintf(gen->source.handle, "}\n\n") < 0) + return IDL_RETCODE_NO_MEMORY; + + if (idl_fprintf(gen->header.handle, "#endif /* %1$s_DEFINED */\n\n", macro) < 0) + return IDL_RETCODE_NO_MEMORY; + return IDL_VISIT_DONT_RECURSE; } @@ -221,6 +255,8 @@ emit_struct( char *name = NULL; const char *fmt; bool empty = idl_is_empty(node); + const idl_struct_t *_struct = (const idl_struct_t *)node; + idl_member_t *members = _struct->members; if (IDL_PRINTA(&name, print_type, node) < 0) return IDL_RETCODE_NO_MEMORY; @@ -231,36 +267,158 @@ emit_struct( return IDL_RETCODE_NO_MEMORY; if (!empty && idl_fprintf(gen->header.handle, "\n") < 0) return IDL_RETCODE_NO_MEMORY; - if (!empty && idl_is_topic(node, (pstate->config.flags & IDL_FLAG_KEYLIST) != 0)) { - if (gen->config.export_macro && idl_fprintf(gen->header.handle, "%1$s ", gen->config.export_macro) < 0) - return IDL_RETCODE_NO_MEMORY; - fmt = "extern const dds_topic_descriptor_t %1$s_desc;\n" - "\n" - "#define %1$s__alloc() \\\n" - "((%1$s*) dds_alloc (sizeof (%1$s)));\n" - "\n" - "#define %1$s_free(d,o) \\\n" - "dds_sample_free ((d), &%1$s_desc, (o))\n" + if (!empty) { + fmt = "#define %1$s__alloc() \\\n" + "((%1$s*) dds_alloc (sizeof (%1$s)))\n" "\n"; if (idl_fprintf(gen->header.handle, fmt, name) < 0) return IDL_RETCODE_NO_MEMORY; - if (gen->config.generate_cdrstream_desc) + if (idl_is_topic(node, (pstate->config.flags & IDL_FLAG_KEYLIST) != 0)) { + if (gen->config.export_macro && idl_fprintf(gen->header.handle, "%1$s ", gen->config.export_macro) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = "extern const dds_topic_descriptor_t %1$s_desc;\n\n"; + if (idl_fprintf(gen->header.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + if (gen->config.export_macro && idl_fprintf(gen->header.handle, "%1$s ", gen->config.export_macro) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = "extern void %1$s_free(void *d, dds_free_op_t o);\n\n"; + if (idl_fprintf(gen->header.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = "void %1$s_free(void *d, dds_free_op_t o) {\n" + " dds_sample_free ((d), &%1$s_desc, (o));\n" + "}\n\n"; + if (idl_fprintf(gen->source.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + if (gen->config.generate_cdrstream_desc) + { + if (gen->config.export_macro && idl_fprintf(gen->header.handle, "%1$s ", gen->config.export_macro) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = "extern const struct dds_cdrstream_desc %1$s_cdrstream_desc;\n\n"; + if (idl_fprintf(gen->header.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + } + if ((ret = generate_descriptor(pstate, gen, node))) + return ret; + } else { + /* generate _free() */ + if (gen->config.export_macro && idl_fprintf(gen->header.handle, "%1$s ", gen->config.export_macro) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = "extern void %1$s_free(void *d);\n\n"; + if (idl_fprintf(gen->header.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = "void %1$s_free(void *d) {\n"; + if (idl_fprintf(gen->source.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + if (idl_fprintf(gen->source.handle, " dds_free(d);\n") < 0) + return IDL_RETCODE_NO_MEMORY; + if (idl_fprintf(gen->source.handle, "}\n\n") < 0) + return IDL_RETCODE_NO_MEMORY; + } { + /* generate _copy() */ + idl_member_t *member; if (gen->config.export_macro && idl_fprintf(gen->header.handle, "%1$s ", gen->config.export_macro) < 0) return IDL_RETCODE_NO_MEMORY; - fmt = "extern const struct dds_cdrstream_desc %1$s_cdrstream_desc;\n\n"; + fmt = "extern void %1$s_copy(%1$s *d, const %1$s *s);\n\n"; if (idl_fprintf(gen->header.handle, fmt, name) < 0) return IDL_RETCODE_NO_MEMORY; + fmt = "void %1$s_copy(%1$s *d, const %1$s *s) {\n"; + if (idl_fprintf(gen->source.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + IDL_FOREACH(member, members) { + bool is_scalar = idl_is_scalar_type(member->type_spec); + bool is_string = idl_is_string(member->type_spec); + bool is_bounded = idl_is_bounded(member->type_spec); + bool is_external = idl_is_external((idl_node_t*)member); + bool is_optional = idl_is_optional((idl_node_t*)member); + bool is_pointer = is_external || is_optional; + idl_declarator_t *decl; + IDL_FOREACH(decl, member->declarators) { + const char *declname = decl->name->identifier; + unsigned dimindex = 0; + char dimbuf[64]; /* buffer for array index syntax */ + dimbuf[0] = '\0'; + if (is_pointer) { + char *membertype; + if (IDL_PRINTA(&membertype, print_type, member->type_spec) < 0) + return IDL_RETCODE_NO_MEMORY; + fmt = " if (s->%1$s == NULL) {\n" + " d->%1$s = NULL;\n" + " } else {\n" + " d->%1$s = %2$s__alloc();\n" + " }\n" + " if (d->%1$s) {\n"; + if (idl_fprintf(gen->source.handle, fmt, declname, membertype) < 0) + return IDL_RETCODE_NO_MEMORY; + } + if (decl->const_expr) { + for (idl_const_expr_t *ce = decl->const_expr; ce; ce = idl_next(ce)) { + idl_literal_t const * const lit = ce; + char ndxbuf[16]; + int res; + fmt = " for (unsigned i%1$u = 0; i%1$u < %2$u; i%1$u++) {\n"; + if (idl_fprintf(gen->source.handle, fmt, dimindex, lit->value.uint32) < 0) + return IDL_RETCODE_NO_MEMORY; + res = snprintf(ndxbuf, sizeof(ndxbuf), "[i%u]", dimindex); + if (res < 0 || (size_t)res >= sizeof(ndxbuf)) + return IDL_RETCODE_NO_MEMORY; + if (strlen(dimbuf) + strlen(ndxbuf) >= sizeof(dimbuf)) + return IDL_RETCODE_NO_MEMORY; + strcat(dimbuf, ndxbuf); + ++dimindex; + } + } + if (is_scalar) { + if (is_pointer) { + fmt = " *(d->%1$s%2$s) = *(s->%1$s%2$s);\n"; + } else { + fmt = " d->%1$s%2$s = s->%1$s%2$s;\n"; + } + if (idl_fprintf(gen->source.handle, fmt, declname, dimbuf) < 0) + return IDL_RETCODE_NO_MEMORY; + } else if (is_string) { + if (is_pointer) { + fmt = " *(d->%1$s%2$s = dds_string_dup(*(s->%1$s%2$s));\n"; + } else if (is_bounded) { + fmt = " strcpy(d->%1$s%2$s, s->%1$s%2$s);\n"; + } else { + fmt = " d->%1$s%2$s = dds_string_dup(s->%1$s%2$s);\n"; + } + if (idl_fprintf(gen->source.handle, fmt, declname, dimbuf) < 0) + return IDL_RETCODE_NO_MEMORY; + } else { + char *membertype; + if (IDL_PRINTA(&membertype, print_type, member->type_spec) < 0) + return IDL_RETCODE_NO_MEMORY; + if (is_pointer) { + fmt = " %s_copy(&((*d)->%2$s%3$s), &((*s)->%2$s%3$s));\n"; + } else { + fmt = " %s_copy(&(d->%2$s%3$s), &(s->%2$s%3$s));\n"; + } + if (idl_fprintf(gen->source.handle, fmt, membertype, declname, dimbuf) < 0) + return IDL_RETCODE_NO_MEMORY; + } + for (unsigned i = 0; i < dimindex; i++) { + if (idl_fprintf(gen->source.handle, " }\n") < 0) + return IDL_RETCODE_NO_MEMORY; + } + if (is_optional) { + if (idl_fprintf(gen->source.handle, " } /* optional is non NULL */\n") < 0) + return IDL_RETCODE_NO_MEMORY; + } else if (is_external) { + if (idl_fprintf(gen->source.handle, " } /* external is non NULL */\n") < 0) + return IDL_RETCODE_NO_MEMORY; + } + } + } + if (idl_fprintf(gen->source.handle, "}\n\n") < 0) + return IDL_RETCODE_NO_MEMORY; } - if ((ret = generate_descriptor(pstate, gen, node))) - return ret; } if (empty) if (idl_fprintf(gen->header.handle, "#endif /* empty struct */\n\n") < 0) return IDL_RETCODE_NO_MEMORY; } else { - const idl_struct_t *_struct = (const idl_struct_t *)node; - const idl_member_t *members = _struct->members; /* ensure typedefs for unnamed sequences exist beforehand */ if (members && (ret = generate_implicit_sequences(pstate, revisit, path, members, user_data))) return ret; @@ -324,7 +482,7 @@ emit_union( fmt = "extern const dds_topic_descriptor_t %1$s_desc;\n" "\n" "#define %1$s__alloc() \\\n" - "((%1$s*) dds_alloc (sizeof (%1$s)));\n" + "((%1$s*) dds_alloc (sizeof (%1$s)))\n" "\n" "#define %1$s_free(d,o) \\\n" "dds_sample_free ((d), &%1$s_desc, (o))\n" @@ -443,7 +601,7 @@ emit_sequence_typedef( } fmt = ";\n\n" "#define %1$s__alloc() \\\n" - "((%1$s*) dds_alloc (sizeof (%1$s)));\n\n" + "((%1$s*) dds_alloc (sizeof (%1$s)))\n\n" "#define %1$s_allocbuf(l) \\\n" "((%2$s%3$s %4$s%5$s*%6$s%7$s) dds_alloc ((l) * sizeof (%2$s%3$s%4$s%7$s)))\n"; if (idl_fprintf(gen->header.handle, fmt, name, type_prefix, type, star, lpar, rpar, dims) < 0) @@ -497,7 +655,7 @@ emit_typedef( } fmt = ";\n\n" "#define %1$s__alloc() \\\n" - "((%1$s*) dds_alloc (sizeof (%1$s)));\n\n"; + "((%1$s*) dds_alloc (sizeof (%1$s)))\n\n"; if (idl_fprintf(gen->header.handle, fmt, name) < 0) return IDL_RETCODE_NO_MEMORY; } @@ -545,7 +703,7 @@ emit_enum( fmt = "\n} %1$s;\n\n" "#define %1$s__alloc() \\\n" - "((%1$s*) dds_alloc (sizeof (%1$s)));\n\n"; + "((%1$s*) dds_alloc (sizeof (%1$s)))\n\n"; if (idl_fprintf(gen->header.handle, fmt, type) < 0) return IDL_RETCODE_NO_MEMORY;