emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 1e6879d: Prefer stpcpy to strcat


From: Paul Eggert
Subject: [Emacs-diffs] master 1e6879d: Prefer stpcpy to strcat
Date: Thu, 25 Dec 2014 23:44:29 +0000

branch: master
commit 1e6879dbdb0832427f5c588c89a53a8a80768a00
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Prefer stpcpy to strcat
    
    * admin/merge-gnulib (GNULIB_MODULES): Add stpcpy.
    * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
    * lib/stpcpy.c, m4/stpcpy.m4: New files, from gnulib.
    * lib-src/ebrowse.c (sym_scope_1, operator_name, open_file):
    * lib-src/emacsclient.c (get_server_config, set_local_socket)
    (start_daemon_and_retry_set_socket):
    * lib-src/etags.c (main, C_entries, relative_filename):
    * lib-src/pop.c (sendline):
    * lib-src/update-game-score.c (main):
    * lwlib/xlwmenu.c (resource_widget_value):
    * src/callproc.c (child_setup):
    * src/dbusbind.c (xd_signature_cat):
    * src/doc.c (get_doc_string, Fsnarf_documentation):
    * src/editfns.c (Fuser_full_name):
    * src/frame.c (xrdb_get_resource):
    * src/gtkutil.c (xg_get_file_with_chooser):
    * src/tparam.c (tparam1):
    * src/xfns.c (xic_create_fontsetname):
    * src/xrdb.c (gethomedir, get_user_db, get_environ_db):
    * src/xsmfns.c (smc_save_yourself_CB):
    Rewrite to avoid the need for strcat, typically by using stpcpy
    and/or lispstpcpy.  strcat tends to be part of O(N**2) algorithms.
    * src/doc.c (sibling_etc):
    * src/xrdb.c (xdefaults):
    Now a top-level static constant.
---
 ChangeLog                   |   29 +++++++++++++++++++++++++
 admin/merge-gnulib          |    2 +-
 lib-src/ebrowse.c           |   29 ++++++++++++++-----------
 lib-src/emacsclient.c       |   35 ++++++++++++++----------------
 lib-src/etags.c             |   33 +++++++++++++++--------------
 lib-src/pop.c               |    3 +-
 lib-src/update-game-score.c |   12 ++++------
 lib/gnulib.mk               |   11 ++++++++-
 lib/stpcpy.c                |   49 +++++++++++++++++++++++++++++++++++++++++++
 lwlib/xlwmenu.c             |    7 ++---
 m4/gnulib-comp.m4           |    9 ++++++++
 m4/stpcpy.m4                |   25 ++++++++++++++++++++++
 src/callproc.c              |    7 +----
 src/dbusbind.c              |    2 +-
 src/doc.c                   |   33 ++++++++++------------------
 src/editfns.c               |    5 +--
 src/frame.c                 |   20 ++++++++--------
 src/gtkutil.c               |    6 ++--
 src/tparam.c                |    4 +-
 src/xfns.c                  |   34 +++++++++++++++---------------
 src/xrdb.c                  |   44 +++++++++++++++++---------------------
 src/xsmfns.c                |    6 +---
 22 files changed, 252 insertions(+), 153 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 425984a..90d7c0b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2014-12-25  Paul Eggert  <address@hidden>
+
+       Prefer stpcpy to strcat
+       * admin/merge-gnulib (GNULIB_MODULES): Add stpcpy.
+       * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
+       * lib/stpcpy.c, m4/stpcpy.m4: New files, from gnulib.
+       * lib-src/ebrowse.c (sym_scope_1, operator_name, open_file):
+       * lib-src/emacsclient.c (get_server_config, set_local_socket)
+       (start_daemon_and_retry_set_socket):
+       * lib-src/etags.c (main, C_entries, relative_filename):
+       * lib-src/pop.c (sendline):
+       * lib-src/update-game-score.c (main):
+       * lwlib/xlwmenu.c (resource_widget_value):
+       * src/callproc.c (child_setup):
+       * src/dbusbind.c (xd_signature_cat):
+       * src/doc.c (get_doc_string, Fsnarf_documentation):
+       * src/editfns.c (Fuser_full_name):
+       * src/frame.c (xrdb_get_resource):
+       * src/gtkutil.c (xg_get_file_with_chooser):
+       * src/tparam.c (tparam1):
+       * src/xfns.c (xic_create_fontsetname):
+       * src/xrdb.c (gethomedir, get_user_db, get_environ_db):
+       * src/xsmfns.c (smc_save_yourself_CB):
+       Rewrite to avoid the need for strcat, typically by using stpcpy
+       and/or lispstpcpy.  strcat tends to be part of O(N**2) algorithms.
+       * src/doc.c (sibling_etc):
+       * src/xrdb.c (xdefaults):
+       Now a top-level static constant.
+
 2014-12-24  Stephen Leake  <address@hidden>
 
        * CONTRIBUTE: Move user-level information to doc/emacs/trouble.texi.
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 64514f7..84c6ebf 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -36,7 +36,7 @@ GNULIB_MODULES='
   manywarnings memrchr mkostemp mktime
   pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat
   sig2str socklen stat-time stdalign stddef stdio
-  strftime strtoimax strtoumax symlink sys_stat
+  stpcpy strftime strtoimax strtoumax symlink sys_stat
   sys_time time time_r timer-time timespec-add timespec-sub
   unsetenv update-copyright utimens
   vla warnings
diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c
index 29a88e8..b743159 100644
--- a/lib-src/ebrowse.c
+++ b/lib-src/ebrowse.c
@@ -1150,19 +1150,19 @@ sym_scope_1 (struct sym *p)
   if (*scope_buffer)
     {
       ensure_scope_buffer_room (3);
-      strcat (scope_buffer, "::");
+      strcpy (scope_buffer + scope_buffer_len, "::");
       scope_buffer_len += 2;
     }
 
   len = strlen (p->name);
   ensure_scope_buffer_room (len + 1);
-  strcat (scope_buffer, p->name);
+  strcpy (scope_buffer + scope_buffer_len, p->name);
   scope_buffer_len += len;
 
   if (HAS_FLAG (p->flags, F_TEMPLATE))
     {
       ensure_scope_buffer_room (3);
-      strcat (scope_buffer, "<>");
+      strcpy (scope_buffer + scope_buffer_len, "<>");
       scope_buffer_len += 2;
     }
 
@@ -2797,24 +2797,25 @@ operator_name (int *sc)
       s = token_string (LA1);
       MATCH ();
 
-      len = strlen (s) + 10;
+      ptrdiff_t slen = strlen (s);
+      len = slen + 10;
       if (len > id_size)
        {
          size_t new_size = max (len, 2 * id_size);
          id = (char *) xrealloc (id, new_size);
          id_size = new_size;
        }
-      strcpy (id, s);
+      char *z = stpcpy (id, s);
 
       /* Vector new or delete?  */
       if (LOOKING_AT ('['))
        {
-         strcat (id, "[");
+         z = stpcpy (z, "[");
          MATCH ();
 
          if (LOOKING_AT (']'))
            {
-             strcat (id, "]");
+             strcpy (z, "]");
              MATCH ();
            }
        }
@@ -2830,7 +2831,7 @@ operator_name (int *sc)
          id = (char *) xrealloc (id, new_size);
          id_size = new_size;
        }
-      strcpy (id, "operator");
+      char *z = stpcpy (id, "operator");
 
       /* Beware access declarations of the form "X::f;" Beware of
         `operator () ()'.  Yet another difficulty is found in
@@ -2842,14 +2843,16 @@ operator_name (int *sc)
          len += strlen (s) + 2;
          if (len > id_size)
            {
+             ptrdiff_t idlen = z - id;
              size_t new_size = max (len, 2 * id_size);
              id = (char *) xrealloc (id, new_size);
              id_size = new_size;
+             z = id + idlen;
            }
 
          if (*s != ')' && *s != ']')
-           strcat (id, " ");
-          strcat (id, s);
+           *z++ = ' ';
+          z = stpcpy (z, s);
           MATCH ();
 
          /* If this is a simple operator like `+', stop now.  */
@@ -3462,9 +3465,9 @@ open_file (char *file)
          buffer = (char *) xrealloc (buffer, buffer_size);
        }
 
-      strcpy (buffer, path->path);
-      strcat (buffer, "/");
-      strcat (buffer, file);
+      char *z = stpcpy (buffer, path->path);
+      *z++ = '/';
+      strcpy (z, file);
       fp = fopen (buffer, "r");
     }
 
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index ddc1b6d..cfc321a 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -905,9 +905,9 @@ get_server_config (const char *config_file, struct 
sockaddr_in *server,
         {
          char *path = xmalloc (strlen (home) + strlen (config_file)
                                + EXTRA_SPACE);
-         strcpy (path, home);
-         strcat (path, "/.emacs.d/server/");
-         strcat (path, config_file);
+         char *z = stpcpy (path, home);
+         z = stpcpy (z, "/.emacs.d/server/");
+         strcpy (z, config_file);
           config = fopen (path, "rb");
          free (path);
         }
@@ -916,9 +916,9 @@ get_server_config (const char *config_file, struct 
sockaddr_in *server,
         {
          char *path = xmalloc (strlen (home) + strlen (config_file)
                                + EXTRA_SPACE);
-         strcpy (path, home);
-         strcat (path, "/.emacs.d/server/");
-         strcat (path, config_file);
+         char *z = stpcpy (path, home);
+         z = stpcpy (z, "/.emacs.d/server/");
+         strcpy (z, config_file);
           config = fopen (path, "rb");
          free (path);
         }
@@ -1193,7 +1193,6 @@ set_local_socket (const char *local_socket_name)
       {
        /* socket_name is a file name component.  */
        long uid = geteuid ();
-       ptrdiff_t tmpdirlen;
        use_tmpdir = 1;
        tmpdir = egetenv ("TMPDIR");
        if (!tmpdir)
@@ -1212,12 +1211,11 @@ set_local_socket (const char *local_socket_name)
 #endif
               tmpdir = "/tmp";
           }
-       tmpdirlen = strlen (tmpdir);
        socket_name_storage =
-         xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE);
-       strcpy (socket_name_storage, tmpdir);
-       sprintf (socket_name_storage + tmpdirlen, "/emacs%ld/", uid);
-       strcat (socket_name_storage + tmpdirlen, server_name);
+         xmalloc (strlen (tmpdir) + strlen (server_name) + EXTRA_SPACE);
+       char *z = stpcpy (socket_name_storage, tmpdir);
+       z += sprintf (z, "/emacs%ld/", uid);
+       strcpy (z, server_name);
        local_socket_name = socket_name_storage;
       }
 
@@ -1253,12 +1251,12 @@ set_local_socket (const char *local_socket_name)
              {
                /* We're running under su, apparently. */
                long uid = pw->pw_uid;
-               ptrdiff_t tmpdirlen = strlen (tmpdir);
                char *user_socket_name
-                 = xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE);
-               strcpy (user_socket_name, tmpdir);
-               sprintf (user_socket_name + tmpdirlen, "/emacs%ld/", uid);
-               strcat (user_socket_name + tmpdirlen, server_name);
+                 = xmalloc (strlen (tmpdir) + strlen (server_name)
+                            + EXTRA_SPACE);
+               char *z = stpcpy (user_socket_name, tmpdir);
+               z += sprintf (z, "/emacs%ld/", uid);
+               strcpy (z, server_name);
 
                if (strlen (user_socket_name) < sizeof (server.sun_path))
                  strcpy (server.sun_path, user_socket_name);
@@ -1507,8 +1505,7 @@ start_daemon_and_retry_set_socket (void)
          const char *deq = "--daemon=";
          char *daemon_arg = xmalloc (strlen (deq)
                                      + strlen (socket_name) + 1);
-         strcpy (daemon_arg, deq);
-         strcat (daemon_arg, socket_name);
+         strcpy (stpcpy (daemon_arg, deq), socket_name);
          d_argv[1] = daemon_arg;
        }
       execvp ("emacs", d_argv);
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 6639ac4..78b3fed 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -1277,13 +1277,13 @@ main (int argc, char **argv)
            default:
              continue;         /* the for loop */
            }
-         strcpy (cmd, "mv ");
-         strcat (cmd, tagfile);
-         strcat (cmd, " OTAGS;fgrep -v '\t");
-         strcat (cmd, argbuffer[i].what);
-         strcat (cmd, "\t' OTAGS >");
-         strcat (cmd, tagfile);
-         strcat (cmd, ";rm OTAGS");
+         char *z = stpcpy (cmd, "mv ");
+         z = stpcpy (z, tagfile);
+         z = stpcpy (z, " OTAGS;fgrep -v '\t");
+         z = stpcpy (z, argbuffer[i].what);
+         z = stpcpy (z, "\t' OTAGS >");
+         z = stpcpy (z, tagfile);
+         strcpy (z, ";rm OTAGS");
          if (system (cmd) != EXIT_SUCCESS)
            fatal ("failed to execute shell command", (char *)NULL);
        }
@@ -1307,10 +1307,10 @@ main (int argc, char **argv)
        /* Maybe these should be used:
           setenv ("LC_COLLATE", "C", 1);
           setenv ("LC_ALL", "C", 1); */
-       strcpy (cmd, "sort -u -o ");
-       strcat (cmd, tagfile);
-       strcat (cmd, " ");
-       strcat (cmd, tagfile);
+       char *z = stpcpy (cmd, "sort -u -o ");
+       z = stpcpy (z, tagfile);
+       *z++ = ' ';
+       strcpy (z, tagfile);
        exit (system (cmd));
       }
   return EXIT_SUCCESS;
@@ -3427,8 +3427,9 @@ C_entries (int c_ext, FILE *inf)
            case omethodtag:
            case omethodparm:
              objdef = omethodcolon;
-             linebuffer_setlen (&token_name, token_name.len + 1);
-             strcat (token_name.buffer, ":");
+             int toklen = token_name.len;
+             linebuffer_setlen (&token_name, toklen + 1);
+             strcpy (token_name.buffer + toklen, ":");
              break;
            }
          if (structdef == stagseen)
@@ -6362,12 +6363,12 @@ relative_filename (char *file, char *dir)
   while ((dp = strchr (dp + 1, '/')) != NULL)
     i += 1;
   res = xnew (3*i + strlen (fp + 1) + 1, char);
-  res[0] = '\0';
+  char *z = res;
   while (i-- > 0)
-    strcat (res, "../");
+    z = stpcpy (z, "../");
 
   /* Add the file name relative to the common root of file and dir. */
-  strcat (res, fp + 1);
+  strcpy (z, fp + 1);
   free (afn);
 
   return res;
diff --git a/lib-src/pop.c b/lib-src/pop.c
index ffe16c5..7001150 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -1397,8 +1397,7 @@ sendline (popserver server, const char *line)
      over a few dozen messages, and is a big chunk of the time we
      spend fetching mail from a server close by.  */
   buf = alloca (strlen (line) + 3);
-  strcpy (buf, line);
-  strcat (buf, "\r\n");
+  strcpy (stpcpy (buf, line), "\r\n");
   ret = fullwrite (server->file, buf, strlen (buf));
 
   if (ret < 0)
diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c
index 7a64cd0..b311001 100644
--- a/lib-src/update-game-score.c
+++ b/lib-src/update-game-score.c
@@ -221,9 +221,9 @@ main (int argc, char **argv)
   if (!scorefile)
     lose_syserr ("Couldn't allocate score file");
 
-  strcpy (scorefile, prefix);
-  strcat (scorefile, "/");
-  strcat (scorefile, argv[optind]);
+  char *z = stpcpy (scorefile, prefix);
+  *z++ = '/';
+  strcpy (z, argv[optind]);
 
   newscore.score = normalize_integer (argv[optind + 1]);
   if (! newscore.score)
@@ -430,8 +430,7 @@ write_scores (const char *filename, const struct 
score_entry *scores,
   char *tempfile = malloc (strlen (filename) + strlen (".tempXXXXXX") + 1);
   if (!tempfile)
     return -1;
-  strcpy (tempfile, filename);
-  strcat (tempfile, ".tempXXXXXX");
+  strcpy (stpcpy (tempfile, filename), ".tempXXXXXX");
   fd = mkostemp (tempfile, 0);
   if (fd < 0)
     return -1;
@@ -462,8 +461,7 @@ lock_file (const char *filename, void **state)
   char *lockpath = malloc (strlen (filename) + strlen (lockext) + 60);
   if (!lockpath)
     return -1;
-  strcpy (lockpath, filename);
-  strcat (lockpath, lockext);
+  strcpy (stpcpy (lockpath, filename), lockext);
   *state = lockpath;
 
   while ((fd = open (lockpath, O_CREAT | O_EXCL, 0600)) < 0)
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index 740ebb1..27a5964 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -21,7 +21,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib 
--m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux 
--avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix 
--avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die 
--avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select 
--avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib 
--makefile-name=gnulib.mk --conditional-dependencies --no-libtool --ma [...]
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib 
--m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux 
--avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix 
--avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die 
--avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select 
--avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib 
--makefile-name=gnulib.mk --conditional-dependencies --no-libtool --ma [...]
 
 
 MOSTLYCLEANFILES += core *.stackdump
@@ -1214,6 +1214,15 @@ EXTRA_DIST += stdlib.in.h
 
 ## end   gnulib module stdlib
 
+## begin gnulib module stpcpy
+
+
+EXTRA_DIST += stpcpy.c
+
+EXTRA_libgnu_a_SOURCES += stpcpy.c
+
+## end   gnulib module stpcpy
+
 ## begin gnulib module strftime
 
 libgnu_a_SOURCES += strftime.c
diff --git a/lib/stpcpy.c b/lib/stpcpy.c
new file mode 100644
index 0000000..880a706
--- /dev/null
+++ b/lib/stpcpy.c
@@ -0,0 +1,49 @@
+/* stpcpy.c -- copy a string and return pointer to end of new string
+   Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2014 Free Software
+   Foundation, Inc.
+
+   NOTE: The canonical source of this file is maintained with the GNU C 
Library.
+   Bugs can be reported to address@hidden
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 3 of the License, or any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <string.h>
+
+#undef __stpcpy
+#ifdef _LIBC
+# undef stpcpy
+#endif
+
+#ifndef weak_alias
+# define __stpcpy stpcpy
+#endif
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST.  */
+char *
+__stpcpy (char *dest, const char *src)
+{
+  register char *d = dest;
+  register const char *s = src;
+
+  do
+    *d++ = *s;
+  while (*s++ != '\0');
+
+  return d - 1;
+}
+#ifdef weak_alias
+weak_alias (__stpcpy, stpcpy)
+#endif
diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c
index 6f4db56..2d2d409 100644
--- a/lwlib/xlwmenu.c
+++ b/lwlib/xlwmenu.c
@@ -439,10 +439,9 @@ resource_widget_value (XlwMenuWidget mw, widget_value *val)
          int complete_length =
            strlen (resourced_name) + strlen (val->value) + 2;
          complete_name = XtMalloc (complete_length);
-         *complete_name = 0;
-         strcat (complete_name, resourced_name);
-         strcat (complete_name, " ");
-         strcat (complete_name, val->value);
+         char *z = stpcpy (complete_name, resourced_name);
+         *z++ = ' ';
+         strcpy (z, val->value);
        }
 
       val->toolkit_data = complete_name;
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 39ec8ae..49fdf5e 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -123,6 +123,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module stdint:
   # Code from module stdio:
   # Code from module stdlib:
+  # Code from module stpcpy:
   # Code from module strftime:
   # Code from module string:
   # Code from module strtoimax:
@@ -341,6 +342,12 @@ AC_DEFUN([gl_INIT],
   gl_STDINT_H
   gl_STDIO_H
   gl_STDLIB_H
+  gl_FUNC_STPCPY
+  if test $HAVE_STPCPY = 0; then
+    AC_LIBOBJ([stpcpy])
+    gl_PREREQ_STPCPY
+  fi
+  gl_STRING_MODULE_INDICATOR([stpcpy])
   gl_FUNC_GNU_STRFTIME
   gl_HEADER_STRING_H
   gl_FUNC_STRTOIMAX
@@ -889,6 +896,7 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/stdint.in.h
   lib/stdio.in.h
   lib/stdlib.in.h
+  lib/stpcpy.c
   lib/strftime.c
   lib/strftime.h
   lib/string.in.h
@@ -995,6 +1003,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/stdint.m4
   m4/stdio_h.m4
   m4/stdlib_h.m4
+  m4/stpcpy.m4
   m4/strftime.m4
   m4/string_h.m4
   m4/strtoimax.m4
diff --git a/m4/stpcpy.m4 b/m4/stpcpy.m4
new file mode 100644
index 0000000..966ba95
--- /dev/null
+++ b/m4/stpcpy.m4
@@ -0,0 +1,25 @@
+# stpcpy.m4 serial 8
+dnl Copyright (C) 2002, 2007, 2009-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_STPCPY],
+[
+  dnl Persuade glibc <string.h> to declare stpcpy().
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+  dnl The stpcpy() declaration in lib/string.in.h uses 'restrict'.
+  AC_REQUIRE([AC_C_RESTRICT])
+
+  AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
+  AC_CHECK_FUNCS([stpcpy])
+  if test $ac_cv_func_stpcpy = no; then
+    HAVE_STPCPY=0
+  fi
+])
+
+# Prerequisites of lib/stpcpy.c.
+AC_DEFUN([gl_PREREQ_STPCPY], [
+  :
+])
diff --git a/src/callproc.c b/src/callproc.c
index a677334..f40ed32 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1315,13 +1315,10 @@ child_setup (int in, int out, int err, char **new_argv, 
bool set_pgrp,
 
     if (STRINGP (display))
       {
-       char *vdata;
-
        if (MAX_ALLOCA - sizeof "DISPLAY=" < SBYTES (display))
          exec_failed (new_argv[0], ENOMEM);
-       vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
-       strcpy (vdata, "DISPLAY=");
-       strcat (vdata, SSDATA (display));
+       char *vdata = alloca (sizeof "DISPLAY=" + SBYTES (display));
+       lispstpcpy (stpcpy (vdata, "DISPLAY="), display);
        new_env = add_env (env, new_env, vdata);
       }
 
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 4852739..983b05c 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -357,7 +357,7 @@ xd_signature_cat (char *signature, char const *x)
   ptrdiff_t xlen = strlen (x);
   if (DBUS_MAXIMUM_SIGNATURE_LENGTH - xlen <= siglen)
     string_overflow ();
-  strcat (signature, x);
+  strcpy (signature + siglen, x);
 }
 
 /* Compute SIGNATURE of OBJECT.  It must have a form that it can be
diff --git a/src/doc.c b/src/doc.c
index 1b87c23..1d9c330 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -42,6 +42,8 @@ static ptrdiff_t get_doc_string_buffer_size;
 
 static unsigned char *read_bytecode_pointer;
 
+static char const sibling_etc[] = "../etc/";
+
 /* `readchar' in lread.c calls back here to fetch the next byte.
    If UNREADFLAG is 1, we unread a byte.  */
 
@@ -80,7 +82,6 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool 
definition)
 {
   char *from, *to, *name, *p, *p1;
   int fd;
-  ptrdiff_t minsize;
   int offset;
   EMACS_INT position;
   Lisp_Object file, tem, pos;
@@ -113,21 +114,14 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool 
definition)
 
   tem = Ffile_name_absolute_p (file);
   file = ENCODE_FILE (file);
-  if (NILP (tem))
-    {
-      Lisp_Object docdir = ENCODE_FILE (Vdoc_directory);
-      minsize = SCHARS (docdir);
-      /* sizeof ("../etc/") == 8 */
-      if (minsize < 8)
-       minsize = 8;
-      name = SAFE_ALLOCA (minsize + SCHARS (file) + 8);
-      char *z = lispstpcpy (name, docdir);
-      strcpy (z, SSDATA (file));
-    }
-  else
-    {
-      name = SSDATA (file);
-    }
+  Lisp_Object docdir
+    = NILP (tem) ? ENCODE_FILE (Vdoc_directory) : empty_unibyte_string;
+  ptrdiff_t docdir_sizemax = SBYTES (docdir) + 1;
+#ifndef CANNOT_DUMP
+  docdir_sizemax = max (docdir_sizemax, sizeof sibling_etc);
+#endif
+  name = SAFE_ALLOCA (docdir_sizemax + SBYTES (file));
+  lispstpcpy (lispstpcpy (name, docdir), file);
 
   fd = emacs_open (name, O_RDONLY, 0);
   if (fd < 0)
@@ -137,8 +131,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool 
definition)
        {
          /* Preparing to dump; DOC file is probably not installed.
             So check in ../etc.  */
-         strcpy (name, "../etc/");
-         strcat (name, SSDATA (file));
+         lispstpcpy (stpcpy (name, sibling_etc), file);
 
          fd = emacs_open (name, O_RDONLY, 0);
        }
@@ -580,7 +573,6 @@ the same file name is found in the `doc-directory'.  */)
       (0)
 #endif /* CANNOT_DUMP */
     {
-      static char const sibling_etc[] = "../etc/";
       dirname = sibling_etc;
       dirlen = sizeof sibling_etc - 1;
     }
@@ -594,8 +586,7 @@ the same file name is found in the `doc-directory'.  */)
   count = SPECPDL_INDEX ();
   USE_SAFE_ALLOCA;
   name = SAFE_ALLOCA (dirlen + SBYTES (filename) + 1);
-  strcpy (name, dirname);
-  strcat (name, SSDATA (filename));    /*** Add this line ***/
+  lispstpcpy (stpcpy (name, dirname), filename);       /*** Add this line ***/
 
   /* Vbuild_files is nil when temacs is run, and non-nil after that.  */
   if (NILP (Vbuild_files))
diff --git a/src/editfns.c b/src/editfns.c
index 0a07886..430c4c9 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1350,10 +1350,9 @@ name, or nil if there is no such user.  */)
       USE_SAFE_ALLOCA;
       char *r = SAFE_ALLOCA (strlen (p) + SBYTES (login) + 1);
       memcpy (r, p, q - p);
-      r[q - p] = 0;
-      strcat (r, SSDATA (login));
+      char *s = lispstpcpy (&r[q - p], login);
       r[q - p] = upcase ((unsigned char) r[q - p]);
-      strcat (r, q + 1);
+      strcpy (s, q + 1);
       full = build_string (r);
       SAFE_FREE ();
     }
diff --git a/src/frame.c b/src/frame.c
index 3127366..2ad1c1b5 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -4076,23 +4076,23 @@ xrdb_get_resource (XrmDatabase rdb, Lisp_Object 
attribute, Lisp_Object class, Li
 
   /* Start with emacs.FRAMENAME for the name (the specific one)
      and with `Emacs' for the class key (the general one).  */
-  lispstpcpy (name_key, Vx_resource_name);
-  lispstpcpy (class_key, Vx_resource_class);
+  char *nz = lispstpcpy (name_key, Vx_resource_name);
+  char *cz = lispstpcpy (class_key, Vx_resource_class);
 
-  strcat (class_key, ".");
-  strcat (class_key, SSDATA (class));
+  *cz++ = '.';
+  cz = lispstpcpy (cz, class);
 
   if (!NILP (component))
     {
-      strcat (class_key, ".");
-      strcat (class_key, SSDATA (subclass));
+      *cz++ = '.';
+      lispstpcpy (cz, subclass);
 
-      strcat (name_key, ".");
-      strcat (name_key, SSDATA (component));
+      *nz++ = '.';
+      nz = lispstpcpy (nz, component);
     }
 
-  strcat (name_key, ".");
-  strcat (name_key, SSDATA (attribute));
+  *nz++ = '.';
+  lispstpcpy (nz, attribute);
 
   char *value = x_get_string_resource (rdb, name_key, class_key);
   SAFE_FREE();
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 9465d54..f61cbc2 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1839,12 +1839,12 @@ xg_get_file_with_chooser (struct frame *f,
 
   if (x_gtk_file_dialog_help_text)
     {
-      msgbuf[0] = '\0';
+      char *z = msgbuf;
       /* Gtk+ 2.10 has the file name text entry box integrated in the dialog.
          Show the C-l help text only for versions < 2.10.  */
       if (gtk_check_version (2, 10, 0) && action != 
GTK_FILE_CHOOSER_ACTION_SAVE)
-        strcat (msgbuf, "\nType C-l to display a file name text entry box.\n");
-      strcat (msgbuf, "\nIf you don't like this file selector, use the "
+        z = stpcpy (z, "\nType C-l to display a file name text entry box.\n");
+      strcpy (z, "\nIf you don't like this file selector, use the "
               "corresponding\nkey binding or customize "
               "use-file-dialog to turn it off.");
 
diff --git a/src/tparam.c b/src/tparam.c
index e02cea3..b0cd004 100644
--- a/src/tparam.c
+++ b/src/tparam.c
@@ -255,9 +255,9 @@ tparam1 (const char *string, char *outstring, int len,
     }
   *op = 0;
   while (doup-- > 0)
-    strcat (op, up);
+    op = stpcpy (op, up);
   while (doleft-- > 0)
-    strcat (op, left);
+    op = stpcpy (op, left);
   return outstring;
 }
 
diff --git a/src/xfns.c b/src/xfns.c
index 1b17311..ba2601d 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -1710,13 +1710,14 @@ xic_create_fontsetname (const char *base_fontname, int 
motif)
 {
   const char *sep = motif ? ";" : ",";
   char *fontsetname;
+  char *z;
 
   /* Make a fontset name from the base font name.  */
   if (xic_default_fontset == base_fontname)
     {
       /* There is no base font name, use the default.  */
       fontsetname = xmalloc (strlen (base_fontname) + 2);
-      strcpy (fontsetname, base_fontname);
+      z = stpcpy (fontsetname, base_fontname);
     }
   else
     {
@@ -1737,9 +1738,9 @@ xic_create_fontsetname (const char *base_fontname, int 
motif)
             Use the specified font plus the default.  */
          fontsetname = xmalloc (strlen (base_fontname)
                                 + strlen (xic_default_fontset) + 3);
-         strcpy (fontsetname, base_fontname);
-         strcat (fontsetname, sep);
-         strcat (fontsetname, xic_default_fontset);
+         z = stpcpy (fontsetname, base_fontname);
+         z = stpcpy (z, sep);
+         z = stpcpy (z, xic_default_fontset);
        }
       else
        {
@@ -1800,27 +1801,26 @@ xic_create_fontsetname (const char *base_fontname, int 
motif)
          /* Build the font spec that matches all.  */
          len = p - p2 + strlen (allcs) + strlen (all) + strlen (allfamilies) + 
1;
          font_all = alloca (len);
-         strcpy (font_all, allfamilies);
-         strcat (font_all, all);
-         memcpy (font_all + strlen (all) + strlen (allfamilies), p2, p - p2);
-         strcpy (font_all + strlen (all) + strlen (allfamilies) + (p - p2),
-                 allcs);
+         z = stpcpy (font_all, allfamilies);
+         z = stpcpy (z, all);
+         memcpy (z, p2, p - p2);
+         strcpy (z + (p - p2), allcs);
 
          /* Build the actual font set name.  */
          len = strlen (base_fontname) + strlen (font_allcs)
            + strlen (font_allfamilies) + strlen (font_all) + 5;
          fontsetname = xmalloc (len);
-         strcpy (fontsetname, base_fontname);
-         strcat (fontsetname, sep);
-         strcat (fontsetname, font_allcs);
-         strcat (fontsetname, sep);
-         strcat (fontsetname, font_allfamilies);
-         strcat (fontsetname, sep);
-         strcat (fontsetname, font_all);
+         z = stpcpy (fontsetname, base_fontname);
+         z = stpcpy (z, sep);
+         z = stpcpy (z, font_allcs);
+         z = stpcpy (z, sep);
+         z = stpcpy (z, font_allfamilies);
+         z = stpcpy (z, sep);
+         z = stpcpy (z, font_all);
        }
     }
   if (motif)
-    return strcat (fontsetname, ":");
+    strcpy (z, ":");
   return fontsetname;
 }
 #endif /* HAVE_X_WINDOWS && USE_X_TOOLKIT */
diff --git a/src/xrdb.c b/src/xrdb.c
index 32ad3c7..e21206d 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -232,9 +232,10 @@ gethomedir (void)
   if (ptr == NULL)
     return xstrdup ("/");
 
-  copy = xmalloc (strlen (ptr) + 2);
-  strcpy (copy, ptr);
-  return strcat (copy, "/");
+  ptrdiff_t len = strlen (ptr);
+  copy = xmalloc (len + 2);
+  strcpy (copy + len, "/");
+  return memcpy (copy, ptr, len);
 }
 
 
@@ -334,6 +335,7 @@ get_user_app (const char *class)
   return db;
 }
 
+static char const xdefaults[] = ".Xdefaults";
 
 static XrmDatabase
 get_user_db (Display *display)
@@ -351,16 +353,12 @@ get_user_db (Display *display)
     db = XrmGetStringDatabase (xdefs);
   else
     {
-      char *home;
-      char *xdefault;
-
-      home = gethomedir ();
-      xdefault = xmalloc (strlen (home) + sizeof ".Xdefaults");
-      strcpy (xdefault, home);
-      strcat (xdefault, ".Xdefaults");
-      db = XrmGetFileDatabase (xdefault);
-      xfree (home);
-      xfree (xdefault);
+      char *home = gethomedir ();
+      ptrdiff_t homelen = strlen (home);
+      char *filename = xrealloc (home, homelen + sizeof xdefaults);
+      strcpy (filename + homelen, xdefaults);
+      db = XrmGetFileDatabase (filename);
+      xfree (filename);
     }
 
 #ifdef HAVE_XSCREENRESOURCESTRING
@@ -380,24 +378,22 @@ static XrmDatabase
 get_environ_db (void)
 {
   XrmDatabase db;
-  char *p;
-  char *path = 0;
+  char *p = getenv ("XENVIRONMENT");
+  char *filename = 0;
 
-  if ((p = getenv ("XENVIRONMENT")) == NULL)
+  if (!p)
     {
-      static char const xdefaults[] = ".Xdefaults-";
       char *home = gethomedir ();
-      char const *host = SSDATA (Vsystem_name);
-      ptrdiff_t pathsize = (strlen (home) + sizeof xdefaults
-                           + SBYTES (Vsystem_name));
-      path = xrealloc (home, pathsize);
-      strcat (strcat (path, xdefaults), host);
-      p = path;
+      ptrdiff_t homelen = strlen (home);
+      ptrdiff_t filenamesize = (homelen + sizeof xdefaults
+                               + SBYTES (Vsystem_name));
+      p = filename = xrealloc (home, filenamesize);
+      lispstpcpy (stpcpy (filename + homelen, xdefaults), Vsystem_name);
     }
 
   db = XrmGetFileDatabase (p);
 
-  xfree (path);
+  xfree (filename);
 
   return db;
 }
diff --git a/src/xsmfns.c b/src/xsmfns.c
index cd4f9ce..8a835cf 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -230,8 +230,7 @@ smc_save_yourself_CB (SmcConn smcConn,
   props[props_idx]->vals[vp_idx++].value = emacs_program;
 
   smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1);
-  strcpy (smid_opt, SMID_OPT);
-  strcat (smid_opt, client_id);
+  strcpy (stpcpy (smid_opt, SMID_OPT), client_id);
 
   props[props_idx]->vals[vp_idx].length = strlen (smid_opt);
   props[props_idx]->vals[vp_idx++].value = smid_opt;
@@ -242,8 +241,7 @@ smc_save_yourself_CB (SmcConn smcConn,
   if (cwd)
     {
       chdir_opt = xmalloc (strlen (CHDIR_OPT) + strlen (cwd) + 1);
-      strcpy (chdir_opt, CHDIR_OPT);
-      strcat (chdir_opt, cwd);
+      strcpy (stpcpy (chdir_opt, CHDIR_OPT), cwd);
 
       props[props_idx]->vals[vp_idx].length = strlen (chdir_opt);
       props[props_idx]->vals[vp_idx++].value = chdir_opt;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]