]> code.delx.au - gnu-emacs/commitdiff
Prefer stpcpy to strcat
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 25 Dec 2014 12:19:17 +0000 (04:19 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 25 Dec 2014 23:44:23 +0000 (15:44 -0800)
* 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.

22 files changed:
ChangeLog
admin/merge-gnulib
lib-src/ebrowse.c
lib-src/emacsclient.c
lib-src/etags.c
lib-src/pop.c
lib-src/update-game-score.c
lib/gnulib.mk
lib/stpcpy.c [new file with mode: 0644]
lwlib/xlwmenu.c
m4/gnulib-comp.m4
m4/stpcpy.m4 [new file with mode: 0644]
src/callproc.c
src/dbusbind.c
src/doc.c
src/editfns.c
src/frame.c
src/gtkutil.c
src/tparam.c
src/xfns.c
src/xrdb.c
src/xsmfns.c

index 425984ae2343943bf1a30f24d7ac91c140af9ff6..90d7c0bb613e20cc61d9c4378718a0d81f4b1934 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2014-12-25  Paul Eggert  <eggert@cs.ucla.edu>
+
+       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  <stephen_leake@stephe-leake.org>
 
        * CONTRIBUTE: Move user-level information to doc/emacs/trouble.texi.
index 64514f79bddcb1b7906cc676a1af17e925f5d40d..84c6ebf3e27ac925f666770c02bc319b472a1620 100755 (executable)
@@ -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
index 29a88e85f021ac7135f8c65292d3b4c943a0eb51..b7431593c3e96fb944f2a1d7dc81b0ff4e1b124b 100644 (file)
@@ -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");
     }
 
index ddc1b6de5e3a4a13d0e59bdc2255b97e0bcfe200..cfc321a183020629b59216ecd824e5edccb28a1f 100644 (file)
@@ -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);
index 6639ac4f235450a4eaf735e6c22397e6e9542280..78b3fed1128584bfa3c2d17eac0a894951c77991 100644 (file)
@@ -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;
index ffe16c5f91123f6c766b7e97a9325ba95a726572..70011504a34a1dda2f609edbeddf017e6ca099b7 100644 (file)
@@ -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)
index 7a64cd04f479da1f23ab807cb298266b69b2037d..b311001bd62e670f3a2b9d9b7c3351d2fb4b8520 100644 (file)
@@ -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)
index 740ebb1e96c2e61dbe404d1b1a4183854bc966b1..27a5964cd7cc2d772b284345b92f5af03fa0ed34 100644 (file)
@@ -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 --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat 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 sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
+# 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 --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
 
 
 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 (file)
index 0000000..880a706
--- /dev/null
@@ -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 bug-glibc@prep.ai.mit.edu.
+
+   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
index 6f4db562e0ba6833737b81a557b97574844c3ae7..2d2d40938086f734a7fbbdff9cf9a33788729bca 100644 (file)
@@ -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;
index 39ec8ae00e694de3285a1d4a3d3e1055e2d4c86e..49fdf5ef199fe8105806f99ab2162b03136d33af 100644 (file)
@@ -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 (file)
index 0000000..966ba95
--- /dev/null
@@ -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], [
+  :
+])
index a677334b3b7710136d7ec763b2609b6a0f49eef1..f40ed3244a5b8ca7b60817f200373d461fd22d3d 100644 (file)
@@ -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);
       }
 
index 4852739d8e4405339b860e4deeb68ec8ea708ecb..983b05c420670079304874d642db7390efdfc52b 100644 (file)
@@ -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
index 1b87c23e9498088976b69b1792cdd145f35e759c..1d9c330d12caa547cc6449f23b06f89684273cd5 100644 (file)
--- 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))
index 0a07886934c71c0a8f2fbe6f030d2245b71ff48b..430c4c91fb3b175841afbe101217619e028e1d62 100644 (file)
@@ -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 ();
     }
index 31273665e887ca0e121ed841a0f888921e339859..2ad1c1b52b706333636889f96526eb13de00718e 100644 (file)
@@ -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();
index 9465d5479dfe9e21b8e2e43899b56a7e4ccaf1b0..f61cbc2c85cd1e2da7c40c88e92ddfebe315417a 100644 (file)
@@ -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.");
 
index e02cea3689e537491a138e28b9b1c7ac3f6313c9..b0cd0047ba2ebcd819b1fa7a58a5e8b930f927b7 100644 (file)
@@ -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;
 }
 \f
index 1b17311f99ce7b979d83711bd1a67897f9ceb574..ba2601daca40bde25c90826d857e32f143217734 100644 (file)
@@ -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 */
index 32ad3c7f01e65caaca4376dcc358565b4d10d684..e21206d0800044fd7e7d862cd01294a12bb1e276 100644 (file)
@@ -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;
 }
index cd4f9ce57fa9d5aa008cf492399b73b3d10ac5bc..8a835cf95f1edf70156897968507cbc39e929927 100644 (file)
@@ -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;