all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Paul Eggert <eggert@cs.ucla.edu>
To: Dmitry Antipov <dmantipov@yandex.ru>,
	 Emacs development discussions <emacs-devel@gnu.org>
Subject: Re: Using stpcpy
Date: Mon, 22 Dec 2014 22:47:34 -0800	[thread overview]
Message-ID: <54991006.8030208@cs.ucla.edu> (raw)
In-Reply-To: <549849A7.3070208@yandex.ru>

[-- Attachment #1: Type: text/plain, Size: 528 bytes --]

Dmitry Antipov wrote:
> Can we assume that stpcpy(3) is mature enough to be used in Emacs?
> It can help to simplify strcpy/strlen/strcat mess here and there.
> (IIUC there is a gnulib module as well).

Yes, stpcpy is mature enough; it's been around for ages in the GNU C library and 
is not likely to change.  That being said, stpcpy isn't universal, so for Emacs 
to be portable we should add gnulib's stpcpy module.

Something like the attached patch, perhaps?  Tested on both GNU/Linux and 
Solaris 10 (which lacks stpcpy).

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Prefer-stpcpy-to-strcat.patch --]
[-- Type: text/x-diff; name="0001-Prefer-stpcpy-to-strcat.patch", Size: 20849 bytes --]

From 1a89819dcbe51883cb63c411179af1db77ffb32d Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 22 Dec 2014 22:13:02 -0800
Subject: [PATCH] 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.
* 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.
strcat tends to be part of O(N**2) algorithms.
---
 ChangeLog          | 17 +++++++++++++++++
 admin/merge-gnulib |  2 +-
 lib/gnulib.mk      | 11 ++++++++++-
 lib/stpcpy.c       | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 m4/gnulib-comp.m4  |  9 +++++++++
 m4/stpcpy.m4       | 25 +++++++++++++++++++++++++
 src/callproc.c     |  7 ++-----
 src/dbusbind.c     |  2 +-
 src/doc.c          |  6 ++----
 src/editfns.c      |  5 ++---
 src/frame.c        | 20 ++++++++++----------
 src/gtkutil.c      |  6 +++---
 src/tparam.c       |  4 ++--
 src/xfns.c         | 34 +++++++++++++++++-----------------
 src/xrdb.c         | 45 +++++++++++++++++++++------------------------
 src/xsmfns.c       |  6 ++----
 16 files changed, 173 insertions(+), 75 deletions(-)
 create mode 100644 lib/stpcpy.c
 create mode 100644 m4/stpcpy.m4

diff --git a/ChangeLog b/ChangeLog
index 7e68314..acafad6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
 2014-12-23  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.
+	* 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.
+	strcat tends to be part of O(N**2) algorithms.
+
 	Merge from gnulib
 	2014-12-20 utimens: remove unnecessary assert
 	2014-12-16 stdalign: port better to HP compilers
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/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 --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
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 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
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..7705ab0 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));
+	strcpy (stpcpy (vdata, "DISPLAY="), SSDATA (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..c6c3251 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -137,8 +137,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));
+	  strcpy (stpcpy (name, "../etc/"), SSDATA (file));
 
 	  fd = emacs_open (name, O_RDONLY, 0);
 	}
@@ -594,8 +593,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 ***/
+  strcpy (stpcpy (name, dirname), SSDATA (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..955e962 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 = stpcpy (&r[q - p], SSDATA (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..d71a26c 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 = stpcpy (cz, SSDATA (class));
 
   if (!NILP (component))
     {
-      strcat (class_key, ".");
-      strcat (class_key, SSDATA (subclass));
+      *cz++ = '.';
+      strcpy (cz, SSDATA (subclass));
 
-      strcat (name_key, ".");
-      strcat (name_key, SSDATA (component));
+      *nz++ = '.';
+      nz = stpcpy (nz, SSDATA (component));
     }
 
-  strcat (name_key, ".");
-  strcat (name_key, SSDATA (attribute));
+  *nz++ = '.';
+  strcpy (nz, SSDATA (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;
 }
 \f
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..c653373 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,23 @@ 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);
+      char *host = SSDATA (Vsystem_name);
+      ptrdiff_t filenamesize = (homelen + sizeof xdefaults
+				+ SBYTES (Vsystem_name));
+      p = filename = xrealloc (home, filenamesize);
+      strcpy (stpcpy (filename + homelen, xdefaults), host);
     }
 
   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;
-- 
1.9.3


  reply	other threads:[~2014-12-23  6:47 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-22 16:41 Using stpcpy Dmitry Antipov
2014-12-23  6:47 ` Paul Eggert [this message]
2014-12-23 10:39   ` Dmitry Antipov
2014-12-25 12:25     ` Paul Eggert
2014-12-25 17:42       ` Dmitry Antipov
2014-12-25 23:44         ` Paul Eggert
2014-12-26 17:06           ` Dani Moncayo
2014-12-26 21:24             ` Eli Zaretskii
2014-12-26 22:01               ` Dani Moncayo
2014-12-27  5:56                 ` cg
2014-12-27  7:45                   ` Eli Zaretskii
2014-12-27 10:26                     ` Dani Moncayo
2014-12-27 10:39                       ` Eli Zaretskii
2014-12-27 10:54                         ` Dani Moncayo
2014-12-27 11:57                     ` cg
2014-12-27 19:52                       ` Eli Zaretskii
2014-12-27 20:03                         ` David Engster
2014-12-27 20:17                           ` Eli Zaretskii
2014-12-27 20:25                             ` Eli Zaretskii
2014-12-27 20:49                               ` David Engster
2014-12-28  3:36                                 ` Eli Zaretskii
2014-12-28 23:57                               ` Richard Stallman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54991006.8030208@cs.ucla.edu \
    --to=eggert@cs.ucla.edu \
    --cc=dmantipov@yandex.ru \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.