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);