Rémi Bernon : widl: Introduce new strappend helper.

Alexandre Julliard julliard at winehq.org
Fri Feb 12 14:37:37 CST 2021


Module: wine
Branch: master
Commit: 6341546fde9c17c41fbc40302e47c9fcb28e01e4
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6341546fde9c17c41fbc40302e47c9fcb28e01e4

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Thu Feb 11 17:37:28 2021 +0100

widl: Introduce new strappend helper.

And use it for format_namespace to grow buffer as needed.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 tools/widl/typetree.c | 46 +++++++++++++++-------------------------------
 tools/widl/utils.c    | 37 +++++++++++++++++++++++++++++++++++++
 tools/widl/utils.h    |  1 +
 3 files changed, 53 insertions(+), 31 deletions(-)

diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index f696d30a5f5..203fffcdee6 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -89,41 +89,25 @@ const char *type_get_name(const type_t *type, enum name_type name_type)
     return NULL;
 }
 
-static char *append_namespace(char *ptr, struct namespace *namespace, const char *separator, const char *abi_prefix)
+static size_t append_namespace(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *separator, const char *abi_prefix)
 {
-    if(is_global_namespace(namespace)) {
-        if(!abi_prefix) return ptr;
-        strcpy(ptr, abi_prefix);
-        strcat(ptr, separator);
-        return ptr + strlen(ptr);
-    }
-
-    ptr = append_namespace(ptr, namespace->parent, separator, abi_prefix);
-    strcpy(ptr, namespace->name);
-    strcat(ptr, separator);
-    return ptr + strlen(ptr);
+    int nested = namespace && !is_global_namespace(namespace);
+    const char *name = nested ? namespace->name : abi_prefix;
+    size_t n = 0;
+    if (!name) return 0;
+    if (nested) n += append_namespace(buf, len, pos + n, namespace->parent, separator, abi_prefix);
+    n += strappend(buf, len, pos + n, "%s%s", name, separator);
+    return n;
 }
 
-char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix,
-                       const char *abi_prefix)
+char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix)
 {
-    unsigned len = strlen(prefix) + strlen(suffix);
-    unsigned sep_len = strlen(separator);
-    struct namespace *iter;
-    char *ret, *ptr;
-
-    if(abi_prefix)
-        len += strlen(abi_prefix) + sep_len;
-
-    for(iter = namespace; !is_global_namespace(iter); iter = iter->parent)
-        len += strlen(iter->name) + sep_len;
-
-    ret = xmalloc(len+1);
-    strcpy(ret, prefix);
-    ptr = append_namespace(ret + strlen(ret), namespace, separator, abi_prefix);
-    strcpy(ptr, suffix);
-
-    return ret;
+    size_t len = 0, pos = 0;
+    char *buf = NULL;
+    pos += strappend(&buf, &len, pos, "%s", prefix);
+    pos += append_namespace(&buf, &len, pos, namespace, separator, abi_prefix);
+    pos += strappend(&buf, &len, pos, "%s", suffix);
+    return buf;
 }
 
 type_t *type_new_function(var_list_t *args)
diff --git a/tools/widl/utils.c b/tools/widl/utils.c
index ea92372c8c7..634bd12a0ba 100644
--- a/tools/widl/utils.c
+++ b/tools/widl/utils.c
@@ -245,6 +245,43 @@ char *strmake( const char* fmt, ... )
     }
 }
 
+size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...)
+{
+    size_t size;
+    va_list ap;
+    char *ptr;
+    int n;
+
+    assert( buf && len );
+    assert( (*len == 0 && *buf == NULL) || (*len != 0 && *buf != NULL) );
+
+    if (*buf)
+    {
+        size = *len;
+        ptr = *buf;
+    }
+    else
+    {
+        size = 100;
+        ptr = xmalloc( size );
+    }
+
+    for (;;)
+    {
+        va_start( ap, fmt );
+        n = vsnprintf( ptr + pos, size - pos, fmt, ap );
+        va_end( ap );
+        if (n == -1) size *= 2;
+        else if (pos + (size_t)n >= size) size = pos + n + 1;
+        else break;
+        ptr = xrealloc( ptr, size );
+    }
+
+    *len = size;
+    *buf = ptr;
+    return n;
+}
+
 char *xstrdup(const char *str)
 {
 	char *s;
diff --git a/tools/widl/utils.h b/tools/widl/utils.h
index 37406656504..82e0a6ae489 100644
--- a/tools/widl/utils.h
+++ b/tools/widl/utils.h
@@ -45,6 +45,7 @@ void warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
 void warning_loc_info(const loc_info_t *, const char *s, ...) __attribute__((format (printf, 2, 3)));
 void chat(const char *s, ...) __attribute__((format (printf, 1, 2)));
 char *strmake(const char* fmt, ...) __attribute__((__format__ (__printf__, 1, 2 )));
+size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...) __attribute__((__format__ (__printf__, 4, 5 )));
 
 char *dup_basename(const char *name, const char *ext);
 size_t widl_getline(char **linep, size_t *lenp, FILE *fp);




More information about the wine-cvs mailing list