patch 9.1.2044: Inefficient use of ga_concat()

Commit: 
https://github.com/vim/vim/commit/a7e671fbb9fa2af9ad6c4ba9a7a881df431cd02b
Author: John Marriott <[email protected]>
Date:   Fri Jan 2 14:11:58 2026 +0000

    patch 9.1.2044: Inefficient use of ga_concat()
    
    Problem:  Inefficient use of ga_concat()
    Solution: Use ga_concat_len() when the length is already known to avoid
              use of strlen() (John Marriott).
    
    Additionally the following changes are done:
    os_unix.c:
    - in function `socket_server_list_sockets()` use a `string_T` for the
      strings `buf` and `path` for use in `ga_concat_len()`
      and drop un-needed variable `dir`.
    
    quickfix.c:
    - in function `qf_jump_print_msg()` use a `string_T` for the string
      `IObuff` for use in `ga_concat_len()`.
    - in function `qf_range_text()` use a `string_T` for the string `buf`
      for use in `ga_concat_len()`.
    
    register.c:
    - simplify function `execreg_line_continuation()`.
    
    terminal.c:
    - in function `read_dump_file()` use a `string_T` for the
      string `prev_char` for use in `ga_concat_len()`.
    
    tuple.c:
    - in function `tuple_join_inner()` use a `string_T` for the
      string `s` for use in `ga_concat_len()`. Also, change local struct
      `join_T` to use `string_T`.
    
    vim9type.c:
    - in functions `type_name_tuple()` and `type_name_func()`
      use a `string_T` for the string `arg_type` for use in
      `ga_concat_len()`.
    
    closes: #19038
    
    Signed-off-by: John Marriott <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/blob.c b/src/blob.c
index 9dfda36fb..e72b5d00a 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -276,13 +276,16 @@ blob2string(blob_T *blob, char_u **tofree, char_u *numbuf)
 
     // Store bytes in the growarray.
     ga_init2(&ga, 1, 4000);
-    ga_concat(&ga, (char_u *)"0z");
+    ga_concat_len(&ga, (char_u *)"0z", 2);
     for (i = 0; i < blob_len(blob); i++)
     {
+       size_t  numbuflen;
+
        if (i > 0 && (i & 3) == 0)
-           ga_concat(&ga, (char_u *)".");
-       vim_snprintf((char *)numbuf, NUMBUFLEN, "%02X", blob_get(blob, i));
-       ga_concat(&ga, numbuf);
+           ga_concat_len(&ga, (char_u *)".", 1);
+       numbuflen = vim_snprintf_safelen((char *)numbuf, NUMBUFLEN,
+           "%02X", blob_get(blob, i));
+       ga_concat_len(&ga, numbuf, numbuflen);
     }
     ga_append(&ga, NUL);               // append a NUL at the end
     *tofree = ga.ga_data;
diff --git a/src/eval.c b/src/eval.c
index 75418c449..15ee3fe11 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -6270,14 +6270,14 @@ partial_tv2string(
     fname = string_quote(pt == NULL ? NULL : partial_name(pt), FALSE);
 
     ga_init2(&ga, 1, 100);
-    ga_concat(&ga, (char_u *)"function(");
+    ga_concat_len(&ga, (char_u *)"function(", 9);
     if (fname != NULL)
     {
        // When using uf_name prepend "g:" for a global function.
        if (pt != NULL && pt->pt_name == NULL && fname[0] == '\''
                                                && vim_isupper(fname[1]))
        {
-           ga_concat(&ga, (char_u *)"'g:");
+           ga_concat_len(&ga, (char_u *)"'g:", 3);
            ga_concat(&ga, fname + 1);
        }
        else
@@ -6286,21 +6286,21 @@ partial_tv2string(
     }
     if (pt != NULL && pt->pt_argc > 0)
     {
-       ga_concat(&ga, (char_u *)", [");
+       ga_concat_len(&ga, (char_u *)", [", 3);
        for (i = 0; i < pt->pt_argc; ++i)
        {
            if (i > 0)
-               ga_concat(&ga, (char_u *)", ");
+               ga_concat_len(&ga, (char_u *)", ", 2);
            ga_concat(&ga, tv2string(&pt->pt_argv[i], &tf, numbuf, copyID));
            vim_free(tf);
        }
-       ga_concat(&ga, (char_u *)"]");
+       ga_concat_len(&ga, (char_u *)"]", 1);
     }
     if (pt != NULL && pt->pt_dict != NULL)
     {
        typval_T dtv;
 
-       ga_concat(&ga, (char_u *)", ");
+       ga_concat_len(&ga, (char_u *)", ", 2);
        dtv.v_type = VAR_DICT;
        dtv.vval.v_dict = pt->pt_dict;
        ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID));
diff --git a/src/evalwindow.c b/src/evalwindow.c
index 9a4efaa8c..57620b61b 100644
--- a/src/evalwindow.c
+++ b/src/evalwindow.c
@@ -1200,10 +1200,14 @@ f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv)
        winnr = 1;
        FOR_ALL_WINDOWS(wp)
        {
-           sprintf((char *)buf, ":%dresize %d|", winnr, wp->w_height);
-           ga_concat(&ga, buf);
-           sprintf((char *)buf, "vert :%dresize %d|", winnr, wp->w_width);
-           ga_concat(&ga, buf);
+           size_t  buflen;
+
+           buflen = vim_snprintf_safelen((char *)buf, sizeof(buf),
+               ":%dresize %d|", winnr, wp->w_height);
+           ga_concat_len(&ga, buf, buflen);
+           buflen = vim_snprintf_safelen((char *)buf, sizeof(buf),
+               "vert :%dresize %d|", winnr, wp->w_width);
+           ga_concat_len(&ga, buf, buflen);
            ++winnr;
        }
     }
diff --git a/src/gui.c b/src/gui.c
index 1470facf9..aeb46c5af 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -5308,26 +5308,26 @@ gui_do_findrepl(
 
     ga_init2(&ga, 1, 100);
     if (type == FRD_REPLACEALL)
-       ga_concat(&ga, (char_u *)"%s/");
+       ga_concat_len(&ga, (char_u *)"%s/", 3);
 
-    ga_concat(&ga, (char_u *)"\V");
+    ga_concat_len(&ga, (char_u *)"\V", 2);
     if (flags & FRD_MATCH_CASE)
-       ga_concat(&ga, (char_u *)"\C");
+       ga_concat_len(&ga, (char_u *)"\C", 2);
     else
-       ga_concat(&ga, (char_u *)"\c");
+       ga_concat_len(&ga, (char_u *)"\c", 2);
     if (flags & FRD_WHOLE_WORD)
-       ga_concat(&ga, (char_u *)"\<");
+       ga_concat_len(&ga, (char_u *)"\<", 2);
     // escape slash and backslash
     p = vim_strsave_escaped(find_text, (char_u *)"/\");
     if (p != NULL)
        ga_concat(&ga, p);
     vim_free(p);
     if (flags & FRD_WHOLE_WORD)
-       ga_concat(&ga, (char_u *)"\>");
+       ga_concat_len(&ga, (char_u *)"\>", 2);
 
     if (type == FRD_REPLACEALL)
     {
-       ga_concat(&ga, (char_u *)"/");
+       ga_concat_len(&ga, (char_u *)"/", 1);
        // Escape slash and backslash.
        // Also escape tilde and ampersand if 'magic' is set.
        p = vim_strsave_escaped(repl_text,
@@ -5335,7 +5335,7 @@ gui_do_findrepl(
        if (p != NULL)
            ga_concat(&ga, p);
        vim_free(p);
-       ga_concat(&ga, (char_u *)"/g");
+       ga_concat_len(&ga, (char_u *)"/g", 2);
     }
     ga_append(&ga, NUL);
 
diff --git a/src/os_unix.c b/src/os_unix.c
index fdae5d67f..490be1f25 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -9363,8 +9363,8 @@ socket_server_uninit(void)
 socket_server_list_sockets(void)
 {
     garray_T           str;
-    char_u             *buf;
-    char_u             *path;
+    string_T           buf;
+    string_T           path;
     DIR                        *dirp;
     struct dirent      *dp;
     struct sockaddr_un addr;
@@ -9374,13 +9374,15 @@ socket_server_list_sockets(void)
        (char_u *)"/tmp"
     };
 
-    if ((buf = alloc(sizeof(addr.sun_path))) == NULL)
+    if ((buf.string = alloc(sizeof(addr.sun_path))) == NULL)
        return NULL;
-    if ((path = alloc(sizeof(addr.sun_path))) == NULL)
+    if ((path.string = alloc(sizeof(addr.sun_path))) == NULL)
     {
-       vim_free(buf);
+       vim_free(buf.string);
        return NULL;
     }
+    buf.length = 0;
+    path.length = 0;
 
     ga_init2(&str, 1, 100);
 
@@ -9393,15 +9395,13 @@ socket_server_list_sockets(void)
 
        if (STRCMP(dir, "/tmp") == 0 ||
                (known_dirs[1] != NULL && STRCMP(dir, known_dirs[1]) == 0))
-           vim_snprintf((char *)path, sizeof(addr.sun_path), "%s/vim-%lu",
-                   dir, (unsigned long int)getuid());
+           path.length = vim_snprintf_safelen((char *)path.string, 
sizeof(addr.sun_path),
+               "%s/vim-%lu", dir, (unsigned long int)getuid());
        else
-           vim_snprintf((char *)path, sizeof(addr.sun_path), "%s/vim", dir);
-
-       dir = path;
-
-       dirp = opendir((char *)dir);
+           path.length = vim_snprintf_safelen((char *)path.string, 
sizeof(addr.sun_path),
+               "%s/vim", dir);
 
+       dirp = opendir((char *)path.string);
        if (dirp == NULL)
            continue;
 
@@ -9411,15 +9411,15 @@ socket_server_list_sockets(void)
            if (STRCMP(dp->d_name, ".") == 0 || STRCMP(dp->d_name, "..") == 0)
                continue;
 
-           vim_snprintf((char *)buf, sizeof(addr.sun_path), "%s/%s",
-                   dir, dp->d_name);
+           buf.length = vim_snprintf_safelen((char *)buf.string, 
sizeof(addr.sun_path),
+               "%s/%s", path.string, dp->d_name);
 
            // Try sending an ALIVE command. This is more assuring than a
            // simple connect, and *also seems to make tests less flaky*.
-           if (!socket_server_check_alive(buf))
+           if (!socket_server_check_alive(buf.string))
                continue;
 
-           ga_concat(&str, (char_u *)dp->d_name);
+           ga_concat_len(&str, (char_u *)dp->d_name, buf.length - (path.length 
+ 1));
            ga_append(&str, '
');
        }
 
@@ -9428,8 +9428,8 @@ socket_server_list_sockets(void)
        break;
     }
 
-    vim_free(path);
-    vim_free(buf);
+    vim_free(path.string);
+    vim_free(buf.string);
 
     ga_append(&str, NUL);
 
diff --git a/src/quickfix.c b/src/quickfix.c
index c3c1ea84f..07e0b7aa1 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -3646,6 +3646,7 @@ qf_jump_print_msg(
 {
     linenr_T           i;
     garray_T           *gap;
+    size_t             IObufflen;
 
     gap = qfga_get();
 
@@ -3653,12 +3654,13 @@ qf_jump_print_msg(
     // scrolled up.
     if (!msg_scrolled)
        update_topline_redraw();
-    vim_snprintf((char *)IObuff, IOSIZE, _("(%d of %d)%s%s: "), qf_index,
+    IObufflen = vim_snprintf_safelen((char *)IObuff, IOSIZE,
+           _("(%d of %d)%s%s: "), qf_index,
            qf_get_curlist(qi)->qf_count,
            qf_ptr->qf_cleared ? _(" (line deleted)") : "",
            (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr));
     // Add the message, skipping leading whitespace and newlines.
-    ga_concat(gap, IObuff);
+    ga_concat_len(gap, IObuff, IObufflen);
     qf_fmt_text(gap, skipwhite(qf_ptr->qf_text));
     ga_append(gap, NUL);
 
@@ -4126,32 +4128,25 @@ qf_fmt_text(garray_T *gap, char_u *text)
     static void
 qf_range_text(garray_T *gap, qfline_T *qfp)
 {
-    char_u     *buf = IObuff;
-    int                bufsize = IOSIZE;
-    int len;
+    string_T   buf = {IObuff, 0};
 
-    vim_snprintf((char *)buf, bufsize, "%ld", qfp->qf_lnum);
-    len = (int)STRLEN(buf);
+    buf.length = vim_snprintf_safelen((char *)buf.string, IOSIZE, "%ld", 
qfp->qf_lnum);
 
     if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum)
     {
-       vim_snprintf((char *)buf + len, bufsize - len, "-%ld",
-                                                            qfp->qf_end_lnum);
-       len += (int)STRLEN(buf + len);
+       buf.length += vim_snprintf_safelen((char *)buf.string + buf.length,
+           IOSIZE - buf.length, "-%ld", qfp->qf_end_lnum);
     }
     if (qfp->qf_col > 0)
     {
-       vim_snprintf((char *)buf + len, bufsize - len, " col %d", qfp->qf_col);
-       len += (int)STRLEN(buf + len);
+       buf.length += vim_snprintf_safelen((char *)buf.string + buf.length,
+           IOSIZE - buf.length, " col %d", qfp->qf_col);
        if (qfp->qf_end_col > 0 && qfp->qf_col != qfp->qf_end_col)
-       {
-           vim_snprintf((char *)buf + len, bufsize - len, "-%d",
-                                                             qfp->qf_end_col);
-           len += (int)STRLEN(buf + len);
-       }
+           buf.length += vim_snprintf_safelen((char *)buf.string + buf.length,
+               IOSIZE - buf.length, "-%d", qfp->qf_end_col);
     }
 
-    ga_concat_len(gap, buf, len);
+    ga_concat_len(gap, buf.string, buf.length);
 }
 
 /*
diff --git a/src/register.c b/src/register.c
index 90abbcc54..a92dd2282 100644
--- a/src/register.c
+++ b/src/register.c
@@ -565,10 +565,9 @@ set_execreg_lastc(int lastc)
 execreg_line_continuation(string_T *lines, long *idx)
 {
     garray_T   ga;
-    long       i = *idx;
-    char_u     *p;
-    int                cmd_start;
-    int                cmd_end = i;
+    long       cmd_start = *idx;
+    long       cmd_end = *idx;
+    string_T   *tmp;
     int                j;
     char_u     *str;
 
@@ -577,19 +576,24 @@ execreg_line_continuation(string_T *lines, long *idx)
     // search backwards to find the first line of this command.
     // Any line not starting with \ or "\ is the start of the
     // command.
-    while (--i > 0)
+    while (--cmd_start > 0)
     {
-       p = skipwhite(lines[i].string);
+       char_u  *p;
+
+       p = skipwhite(lines[cmd_start].string);
        if (*p != '\' && (p[0] != '"' || p[1] != '\' || p[2] != ' '))
            break;
     }
-    cmd_start = i;
 
     // join all the lines
-    ga_concat(&ga, lines[cmd_start].string);
+    tmp = &lines[cmd_start];
+    ga_concat_len(&ga, tmp->string, tmp->length);
     for (j = cmd_start + 1; j <= cmd_end; j++)
     {
-       p = skipwhite(lines[j].string);
+       char_u  *p;
+
+       tmp = &lines[j];
+       p = skipwhite(tmp->string);
        if (*p == '\')
        {
            // Adjust the growsize to the current length to
@@ -601,14 +605,15 @@ execreg_line_continuation(string_T *lines, long *idx)
                else
                    ga.ga_growsize = ga.ga_len;
            }
-           ga_concat(&ga, p + 1);
+           p++;
+           ga_concat_len(&ga, p, (tmp->string + tmp->length) - p);
        }
     }
     ga_append(&ga, NUL);
     str = vim_strnsave(ga.ga_data, ga.ga_len);
     ga_clear(&ga);
 
-    *idx = i;
+    *idx = cmd_start;
     return str;
 }
 
diff --git a/src/terminal.c b/src/terminal.c
index 234807e90..d2e20e251 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -5378,7 +5378,7 @@ f_term_dumpwrite(typval_T *argvars, typval_T *rettv 
UNUSED)
     static void
 dump_is_corrupt(garray_T *gap)
 {
-    ga_concat(gap, (char_u *)"CORRUPT");
+    ga_concat_len(gap, (char_u *)"CORRUPT", 7);
 }
 
     static void
@@ -5409,7 +5409,7 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
     int                    c;
     garray_T       ga_text;
     garray_T       ga_cell;
-    char_u         *prev_char = NULL;
+    string_T       prev_char = {NULL, 0};
     int                    attr = 0;
     cellattr_T     cell;
     cellattr_T     empty_cell;
@@ -5488,10 +5488,16 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
            }
 
            // save the character for repeating it
-           vim_free(prev_char);
+           VIM_CLEAR_STRING(prev_char);
            if (ga_text.ga_data != NULL)
-               prev_char = vim_strnsave(((char_u *)ga_text.ga_data) + prev_len,
-                                                   ga_text.ga_len - prev_len);
+           {
+               prev_char.length = (size_t)(ga_text.ga_len - prev_len);
+               prev_char.string = vim_strnsave(
+                   ((char_u *)ga_text.ga_data) + prev_len,
+                   prev_char.length);
+               if (prev_char.string == NULL)
+                   prev_char.length = 0;
+           }
 
            if (c == '@' || c == '|' || c == '>' || c == '
')
            {
@@ -5601,7 +5607,7 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
        }
        else if (c == '@')
        {
-           if (prev_char == NULL)
+           if (prev_char.string == NULL)
                dump_is_corrupt(&ga_text);
            else
            {
@@ -5618,7 +5624,7 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
 
                while (count-- > 0)
                {
-                   ga_concat(&ga_text, prev_char);
+                   ga_concat_len(&ga_text, prev_char.string, prev_char.length);
                    append_cell(&ga_cell, &cell);
                }
            }
@@ -5641,7 +5647,7 @@ read_dump_file(FILE *fd, VTermPos *cursor_pos)
 
     ga_clear(&ga_text);
     ga_clear(&ga_cell);
-    vim_free(prev_char);
+    vim_free(prev_char.string);
 
     return max_cells;
 }
diff --git a/src/tuple.c b/src/tuple.c
index c58d11d7a..28fb59888 100644
--- a/src/tuple.c
+++ b/src/tuple.c
@@ -633,7 +633,7 @@ tuple_lock(tuple_T *tuple, int deep, int lock, int 
check_refcount)
 }
 
 typedef struct join_S {
-    char_u     *s;
+    string_T   s;
     char_u     *tofree;
 } join_T;
 
@@ -649,37 +649,39 @@ tuple_join_inner(
 {
     int                i;
     join_T     *p;
-    int                len;
     int                sumlen = 0;
     int                first = TRUE;
     char_u     *tofree;
     char_u     numbuf[NUMBUFLEN];
-    char_u     *s;
+    string_T   s;
     typval_T   *tv;
+    size_t     seplen = 0;
 
     // Stringify each item in the tuple.
     for (i = 0; i < TUPLE_LEN(tuple) && !got_int; i++)
     {
        tv = TUPLE_ITEM(tuple, i);
-       s = echo_string_core(tv, &tofree, numbuf, copyID,
+       s.string = echo_string_core(tv, &tofree, numbuf, copyID,
                                      echo_style, restore_copyID, !echo_style);
-       if (s == NULL)
+       if (s.string == NULL)
            return FAIL;
 
-       len = (int)STRLEN(s);
-       sumlen += len;
+       s.length = STRLEN(s.string);
+       sumlen += (int)s.length;
 
        (void)ga_grow(join_gap, 1);
        p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++);
-       if (tofree != NULL || s != numbuf)
+       if (tofree != NULL || s.string != numbuf)
        {
-           p->s = s;
+           p->s.string = s.string;
+           p->s.length = s.length;
            p->tofree = tofree;
        }
        else
        {
-           p->s = vim_strnsave(s, len);
-           p->tofree = p->s;
+           p->s.string = vim_strnsave(s.string, s.length);
+           p->s.length = s.length;
+           p->tofree = p->s.string;
        }
 
        line_breakcheck();
@@ -689,8 +691,12 @@ tuple_join_inner(
 
     // Allocate result buffer with its total size, avoid re-allocation and
     // multiple copy operations.  Add 2 for a tailing ')' and NUL.
-    if (join_gap->ga_len >= 2)
-       sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1);
+    if (join_gap->ga_len > 0)
+    {
+       seplen = STRLEN(sep);
+       if (join_gap->ga_len >= 2)
+           sumlen += (int)seplen * (join_gap->ga_len - 1);
+    }
     if (ga_grow(gap, sumlen + 2) == FAIL)
        return FAIL;
 
@@ -699,18 +705,18 @@ tuple_join_inner(
        if (first)
            first = FALSE;
        else
-           ga_concat(gap, sep);
+           ga_concat_len(gap, sep, seplen);
        p = ((join_T *)join_gap->ga_data) + i;
 
-       if (p->s != NULL)
-           ga_concat(gap, p->s);
+       if (p->s.string != NULL)
+           ga_concat_len(gap, p->s.string, p->s.length);
        line_breakcheck();
     }
 
     // If there is only one item in the tuple, then add the separator after
     // that.
     if (join_gap->ga_len == 1)
-       ga_concat(gap, sep);
+       ga_concat_len(gap, sep, seplen);
 
     return OK;
 }
diff --git a/src/version.c b/src/version.c
index 84a08d2be..ca2125168 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2044,
 /**/
     2043,
 /**/
diff --git a/src/vim9type.c b/src/vim9type.c
index 6d1b28afd..393b85251 100644
--- a/src/vim9type.c
+++ b/src/vim9type.c
@@ -2580,30 +2580,29 @@ type_name_tuple(type_T *type, char **tofree)
 
     if (type->tt_argcount <= 0)
        // empty tuple
-       ga_concat(&ga, (char_u *)"any");
+       ga_concat_len(&ga, (char_u *)"any", 3);
     else
     {
        if (type->tt_args == NULL)
-           ga_concat(&ga, (char_u *)"[unknown]");
+           ga_concat_len(&ga, (char_u *)"[unknown]", 9);
        else
        {
            for (i = 0; i < type->tt_argcount; ++i)
            {
-               char    *arg_type;
-               int     len;
+               string_T    arg_type;
 
-               arg_type = type_name(type->tt_args[i], &arg_free);
+               arg_type.string = (char_u *)type_name(type->tt_args[i], 
&arg_free);
                if (i > 0)
                {
                    STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
                    ga.ga_len += 2;
                }
-               len = (int)STRLEN(arg_type);
-               if (ga_grow(&ga, len + 8) == FAIL)
+               arg_type.length = STRLEN(arg_type.string);
+               if (ga_grow(&ga, (int)arg_type.length + 8) == FAIL)
                    goto failed;
                if (varargs && i == type->tt_argcount - 1)
-                   ga_concat(&ga, (char_u *)"...");
-               ga_concat(&ga, (char_u *)arg_type);
+                   ga_concat_len(&ga, (char_u *)"...", 3);
+               ga_concat_len(&ga, arg_type.string, arg_type.length);
                VIM_CLEAR(arg_free);
            }
        }
@@ -2670,31 +2669,35 @@ type_name_func(type_T *type, char **tofree)
 
     for (i = 0; i < type->tt_argcount; ++i)
     {
-       char *arg_type;
-       int  len;
+       string_T    arg_type;
 
        if (type->tt_args == NULL)
-           arg_type = "[unknown]";
+       {
+           arg_type.string = (char_u *)"[unknown]";
+           arg_type.length = 9;
+       }
        else
-           arg_type = type_name(type->tt_args[i], &arg_free);
+       {
+           arg_type.string = (char_u *)type_name(type->tt_args[i], &arg_free);
+           arg_type.length = STRLEN(arg_type.string);
+       }
        if (i > 0)
        {
            STRCPY((char *)ga.ga_data + ga.ga_len, ", ");
            ga.ga_len += 2;
        }
-       len = (int)STRLEN(arg_type);
-       if (ga_grow(&ga, len + 8) == FAIL)
+       if (ga_grow(&ga, (int)arg_type.length + 8) == FAIL)
            goto failed;
        if (varargs && i == type->tt_argcount - 1)
-           ga_concat(&ga, (char_u *)"...");
+           ga_concat_len(&ga, (char_u *)"...", 3);
        else if (i >= type->tt_min_argcount)
            *((char *)ga.ga_data + ga.ga_len++) = '?';
-       ga_concat(&ga, (char_u *)arg_type);
+       ga_concat_len(&ga, arg_type.string, arg_type.length);
        VIM_CLEAR(arg_free);
     }
     if (type->tt_argcount < 0)
        // any number of arguments
-       ga_concat(&ga, (char_u *)"...");
+       ga_concat_len(&ga, (char_u *)"...", 3);
 
     if (type->tt_member == &t_void)
        STRCPY((char *)ga.ga_data + ga.ga_len, ")");

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1vbgAG-00AVDc-MH%40256bit.org.

Raspunde prin e-mail lui