unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Using stpcpy
@ 2014-12-22 16:41 Dmitry Antipov
  2014-12-23  6:47 ` Paul Eggert
  0 siblings, 1 reply; 22+ messages in thread
From: Dmitry Antipov @ 2014-12-22 16:41 UTC (permalink / raw)
  To: Emacs development discussions; +Cc: Paul Eggert

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

Dmitry



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-22 16:41 Using stpcpy Dmitry Antipov
@ 2014-12-23  6:47 ` Paul Eggert
  2014-12-23 10:39   ` Dmitry Antipov
  0 siblings, 1 reply; 22+ messages in thread
From: Paul Eggert @ 2014-12-23  6:47 UTC (permalink / raw)
  To: Dmitry Antipov, Emacs development discussions

[-- 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


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-23  6:47 ` Paul Eggert
@ 2014-12-23 10:39   ` Dmitry Antipov
  2014-12-25 12:25     ` Paul Eggert
  0 siblings, 1 reply; 22+ messages in thread
From: Dmitry Antipov @ 2014-12-23 10:39 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Emacs development discussions

On 12/23/2014 09:47 AM, Paul Eggert wrote:

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

Not quite; in particular, I would prefer (for example, in doc.c):

@@ -137,8 +136,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, "../etc/"), file);

rather than:

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

(because lispstpcpy can use known length of a Lisp_String and so call memcpy,
which should be faster than strcpy).

Dmitry




^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-23 10:39   ` Dmitry Antipov
@ 2014-12-25 12:25     ` Paul Eggert
  2014-12-25 17:42       ` Dmitry Antipov
  0 siblings, 1 reply; 22+ messages in thread
From: Paul Eggert @ 2014-12-25 12:25 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Emacs development discussions

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

Dmitry Antipov wrote:
> (because lispstpcpy can use known length of a Lisp_String and so call memcpy,
> which should be faster than strcpy).

Thanks for reviewing.  Also, we should fix the strcat uses in lib-src and lwlib. 
  Attached is a revised patch that should address all this.


[-- 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: 34414 bytes --]

From 5609af083525dae86339be5c8548679363b1ed90 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 25 Dec 2014 04:19:17 -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.
* 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 liststpcpy.  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(-)
 create mode 100644 lib/stpcpy.c
 create mode 100644 m4/stpcpy.m4

diff --git a/ChangeLog b/ChangeLog
index 425984a..6ec465d 100644
--- 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 liststpcpy.  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.
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 --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/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;
 }
 \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..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;
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-25 12:25     ` Paul Eggert
@ 2014-12-25 17:42       ` Dmitry Antipov
  2014-12-25 23:44         ` Paul Eggert
  0 siblings, 1 reply; 22+ messages in thread
From: Dmitry Antipov @ 2014-12-25 17:42 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Emacs development discussions

On 12/25/2014 03:25 PM, Paul Eggert wrote:

> Thanks for reviewing.  Also, we should fix the strcat uses in lib-src and lwlib.
> Attached is a revised patch that should address all this.

s/liststpcpy/lispstpcpy, otherwise looks good for me.

Dmitry





^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-25 17:42       ` Dmitry Antipov
@ 2014-12-25 23:44         ` Paul Eggert
  2014-12-26 17:06           ` Dani Moncayo
  0 siblings, 1 reply; 22+ messages in thread
From: Paul Eggert @ 2014-12-25 23:44 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: Emacs development discussions

Dmitry Antipov wrote:
> s/liststpcpy/lispstpcpy, otherwise looks good for me.

Thanks, I pushed it into the master.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-25 23:44         ` Paul Eggert
@ 2014-12-26 17:06           ` Dani Moncayo
  2014-12-26 21:24             ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: Dani Moncayo @ 2014-12-26 17:06 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Dmitry Antipov, Emacs development discussions

On Fri, Dec 26, 2014 at 12:44 AM, Paul Eggert <eggert@cs.ucla.edu> wrote:
> Dmitry Antipov wrote:
>>
>> s/liststpcpy/lispstpcpy, otherwise looks good for me.
>
>
> Thanks, I pushed it into the master.

I've got the following build-time error (current trunk, on
MS-Windows), which is probably related to the above commit:

-------------------------------------------
[...]
make -C lib-src all
make[1]: Entering directory
`/home/Dani/devel/emacs/build-master-20141226T123627-i686-mingw32/lib-src'
gcc -std=gnu99  -mtune=pentium4      -I. -I../src -I../lib
-I/c/cygwin64/home/Dani/devel/emacs/repo/lib-src -I/c/cygwin
64/home/Dani/devel/emacs/repo/lib-src/../src
-I/c/cygwin64/home/Dani/devel/emacs/repo/lib-src/../lib
-mtune=pentium4
-DGLYPH_DEBUG=1 -DUSE_CRT_DLL=1 -I
/c/cygwin64/home/Dani/devel/emacs/repo/nt/inc -g3 -O2 -gdwarf-2
-DEMACS_NAME="\"GNU E
macs\"" -DVERSION="\"25.0.50\"" -o etags.exe
/c/cygwin64/home/Dani/devel/emacs/repo/lib-src/etags.c regex.o
../lib/libgn
u.a  ntlib.o
ntlib.o: In function `stat':
c:/cygwin64/home/Dani/devel/emacs/repo/lib-src/ntlib.c:350: undefined
reference to `stpcpy'
collect2.exe: error: ld returned 1 exit status
Makefile:327: recipe for target `etags.exe' failed
make[1]: *** [etags.exe] Error 1
make[1]: Leaving directory
`/home/Dani/devel/emacs/build-master-20141226T123627-i686-mingw32/lib-src'
Makefile:372: recipe for target `lib-src' failed
make: *** [lib-src] Error 2
$
-------------------------------------------

-- 
Dani Moncayo



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-26 17:06           ` Dani Moncayo
@ 2014-12-26 21:24             ` Eli Zaretskii
  2014-12-26 22:01               ` Dani Moncayo
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2014-12-26 21:24 UTC (permalink / raw)
  To: Dani Moncayo; +Cc: eggert, dmantipov, emacs-devel

> Date: Fri, 26 Dec 2014 18:06:57 +0100
> From: Dani Moncayo <dmoncayo@gmail.com>
> Cc: Dmitry Antipov <dmantipov@yandex.ru>,
> 	Emacs development discussions <emacs-devel@gnu.org>
> 
> On Fri, Dec 26, 2014 at 12:44 AM, Paul Eggert <eggert@cs.ucla.edu> wrote:
> > Dmitry Antipov wrote:
> >>
> >> s/liststpcpy/lispstpcpy, otherwise looks good for me.
> >
> >
> > Thanks, I pushed it into the master.
> 
> I've got the following build-time error (current trunk, on
> MS-Windows), which is probably related to the above commit:
> 
> -------------------------------------------
> [...]
> make -C lib-src all
> make[1]: Entering directory
> `/home/Dani/devel/emacs/build-master-20141226T123627-i686-mingw32/lib-src'
> gcc -std=gnu99  -mtune=pentium4      -I. -I../src -I../lib
> -I/c/cygwin64/home/Dani/devel/emacs/repo/lib-src -I/c/cygwin
> 64/home/Dani/devel/emacs/repo/lib-src/../src
> -I/c/cygwin64/home/Dani/devel/emacs/repo/lib-src/../lib
> -mtune=pentium4
> -DGLYPH_DEBUG=1 -DUSE_CRT_DLL=1 -I
> /c/cygwin64/home/Dani/devel/emacs/repo/nt/inc -g3 -O2 -gdwarf-2
> -DEMACS_NAME="\"GNU E
> macs\"" -DVERSION="\"25.0.50\"" -o etags.exe
> /c/cygwin64/home/Dani/devel/emacs/repo/lib-src/etags.c regex.o
> ../lib/libgn
> u.a  ntlib.o
> ntlib.o: In function `stat':
> c:/cygwin64/home/Dani/devel/emacs/repo/lib-src/ntlib.c:350: undefined
> reference to `stpcpy'
> collect2.exe: error: ld returned 1 exit status
> Makefile:327: recipe for target `etags.exe' failed
> make[1]: *** [etags.exe] Error 1
> make[1]: Leaving directory
> `/home/Dani/devel/emacs/build-master-20141226T123627-i686-mingw32/lib-src'
> Makefile:372: recipe for target `lib-src' failed
> make: *** [lib-src] Error 2

Make sure you have the latest trunk, and then make sure to re-run the
configure script.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-26 21:24             ` Eli Zaretskii
@ 2014-12-26 22:01               ` Dani Moncayo
  2014-12-27  5:56                 ` cg
  0 siblings, 1 reply; 22+ messages in thread
From: Dani Moncayo @ 2014-12-26 22:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Paul Eggert, Dmitry Antipov, Emacs development discussions

> Make sure you have the latest trunk, and then make sure to re-run the
> configure script.

Yes, I already made sure of that.   Anyway, I've just tried again:
1. git pull (now at commit 7284a174abc03c9ccf45aa43c939585beea351b7)
2. autogen.sh
3. make a new build directory.
4. CPPFLAGS='-DGLYPH_DEBUG=1' <sourcepath>/configure
--enable-checking='yes,glyphs'
5. make

Same error:

gcc -std=gnu99  -mtune=pentium4      -I. -I../src -I../lib
-I/c/cygwin64/home/Dani/devel/emacs/repo/lib-src
-I/c/cygwin64/home/Dani/devel/emacs/repo/lib-src/../src
-I/c/cygwin64/home/Dani/devel/emacs/repo/lib-src/../lib
-mtune=pentium4 -DGLYPH_DEBUG=1 -DUSE_CRT_DLL=1 -I
/c/cygwin64/home/Dani/devel/emacs/repo/nt/inc -g3 -O2 -gdwarf-2
-DEMACS_NAME="\"GNU Emacs\"" -DVERSION="\"25.0.50\"" -o etags.exe
/c/cygwin64/home/Dani/devel/emacs/repo/lib-src/etags.c regex.o
../lib/libgnu.a  ntlib.o
ntlib.o: In function `stat':
c:/cygwin64/home/Dani/devel/emacs/repo/lib-src/ntlib.c:350: undefined
reference to `stpcpy'
collect2.exe: error: ld returned 1 exit status
Makefile:327: recipe for target `etags.exe' failed
make[1]: *** [etags.exe] Error 1
make[1]: Leaving directory
`/home/Dani/devel/emacs/build-master-20141226T205933-i686-mingw32/lib-src'
Makefile:372: recipe for target `lib-src' failed
make: *** [lib-src] Error 2


-- 
Dani Moncayo



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-26 22:01               ` Dani Moncayo
@ 2014-12-27  5:56                 ` cg
  2014-12-27  7:45                   ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: cg @ 2014-12-27  5:56 UTC (permalink / raw)
  To: emacs-devel

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

On 12/27/2014 6:01 AM, Dani Moncayo wrote:
> Same error:
>
> c:/cygwin64/home/Dani/devel/emacs/repo/lib-src/ntlib.c:350: undefined
> reference to `stpcpy'
>

I got the same error. It seems caused by linking order of files, I fixed it
by swapping $(NTLIB) and $(LOADLIBES) in lib-src/Makefile.in.

Patch attached.


[-- Attachment #2: fix-stpcpy-link-error.patch --]
[-- Type: text/x-patch, Size: 2060 bytes --]

diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index cae0898..13a7a05 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -321,7 +321,7 @@ regex.o: $(srcdir)/../src/regex.c $(srcdir)/../src/regex.h $(config_h)
 
 etags_deps = ${srcdir}/etags.c regex.o $(NTLIB) $(config_h)
 etags_cflags = -DEMACS_NAME="\"GNU Emacs\"" -DVERSION="\"${version}\"" -o $@
-etags_libs = regex.o $(LOADLIBES) $(NTLIB)
+etags_libs = regex.o $(NTLIB) $(LOADLIBES)
 
 etags${EXEEXT}: ${etags_deps}
 	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $(etags_cflags) $< $(etags_libs)
@@ -336,18 +336,18 @@ ctags${EXEEXT}: ${srcdir}/ctags.c ${etags_deps}
 ebrowse${EXEEXT}: ${srcdir}/ebrowse.c ${srcdir}/../lib/min-max.h $(NTLIB) \
                    $(config_h)
 	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} -DVERSION="\"${version}\"" \
-	  $< $(LOADLIBES) $(NTLIB) -o $@
+	  $< $(NTLIB) $(LOADLIBES) -o $@
 
 profile${EXEEXT}: ${srcdir}/profile.c $(NTLIB) $(config_h)
 	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $< \
-	  $(LOADLIBES) $(NTLIB) $(LIB_CLOCK_GETTIME) -o $@
+	  $(NTLIB) $(LOADLIBES) $(LIB_CLOCK_GETTIME) -o $@
 
 make-docfile${EXEEXT}: ${srcdir}/make-docfile.c $(NTLIB) $(config_h)
-	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $< $(LOADLIBES) $(NTLIB) -o $@
+	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $< $(NTLIB) $(LOADLIBES) -o $@
 
 movemail${EXEEXT}: ${srcdir}/movemail.c pop.o $(NTLIB) $(config_h)
 	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} ${MOVE_FLAGS} $< pop.o \
-	  $(LOADLIBES) $(NTLIB) $(LIBS_MOVE) -o $@
+	  $(NTLIB) $(LOADLIBES) $(LIBS_MOVE) -o $@
 
 pop.o: ${srcdir}/pop.c ${srcdir}/pop.h ${srcdir}/../lib/min-max.h $(config_h)
 	$(AM_V_CC)$(CC) -c ${CPP_CFLAGS} ${MOVE_FLAGS} $<
@@ -378,7 +378,7 @@ hexl${EXEEXT}: ${srcdir}/hexl.c $(NTLIB) $(config_h)
 update-game-score${EXEEXT}: ${srcdir}/update-game-score.c $(NTLIB) $(config_h)
 	$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} \
 	  -DHAVE_SHARED_GAME_DIR="\"$(gamedir)\"" \
-	  $< $(LOADLIBES) $(NTLIB) -o $@
+	  $< $(NTLIB) $(LOADLIBES) -o $@
 
 emacsclient.res: ../nt/emacsclient.rc $(NTINC)/../icons/emacs.ico
 	$(WINDRES) -O coff --include-dir=$(NTINC)/.. -o $@ $<

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27  5:56                 ` cg
@ 2014-12-27  7:45                   ` Eli Zaretskii
  2014-12-27 10:26                     ` Dani Moncayo
  2014-12-27 11:57                     ` cg
  0 siblings, 2 replies; 22+ messages in thread
From: Eli Zaretskii @ 2014-12-27  7:45 UTC (permalink / raw)
  To: cg, Dani Moncayo; +Cc: emacs-devel

> From: cg <chengang31@gmail.com>
> Date: Sat, 27 Dec 2014 13:56:14 +0800
> 
> On 12/27/2014 6:01 AM, Dani Moncayo wrote:
> > Same error:
> >
> > c:/cygwin64/home/Dani/devel/emacs/repo/lib-src/ntlib.c:350: undefined
> > reference to `stpcpy'
> >
> 
> I got the same error. It seems caused by linking order of files, I fixed it
> by swapping $(NTLIB) and $(LOADLIBES) in lib-src/Makefile.in.
> 
> Patch attached.

Sorry, I don't understand this: there's no call to stpcpy on line 350
of ntlib.c, or anywhere else in ntlib.c, actually.  That line calls
strcpy, not stpcpy.  Can you try to find out why do you get this
error?  If nothing else helps, please look in a preprocessed version
of ntlib.c for any header files that "#define strcpy stpcpy" or some
such.

Thanks.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27  7:45                   ` Eli Zaretskii
@ 2014-12-27 10:26                     ` Dani Moncayo
  2014-12-27 10:39                       ` Eli Zaretskii
  2014-12-27 11:57                     ` cg
  1 sibling, 1 reply; 22+ messages in thread
From: Dani Moncayo @ 2014-12-27 10:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: cg, Emacs development discussions

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

> Sorry, I don't understand this: there's no call to stpcpy on line 350
> of ntlib.c, or anywhere else in ntlib.c, actually.  That line calls
> strcpy, not stpcpy.

True.

>  Can you try to find out why do you get this
> error?  If nothing else helps, please look in a preprocessed version
> of ntlib.c for any header files that "#define strcpy stpcpy" or some
> such.

I've generated the preprocessed version of ntlib.c with the same
command run by 'make', but adding a "-E" switch as first argument to
'gcc':

  $ gcc -E -std=gnu99  -mtune=pentium4 \
  -I. \
  -I../src -I../lib \
  -I<srcdir>/lib-src \
  -I<srcdir>/lib-src/../src \
  -I<srcdir>/lib-src/../lib \
  -mtune=pentium4  -DGLYPH_DEBUG=1 -DUSE_CRT_DLL=1 \
  -I <srcdir>/nt/inc -g3 -O2 -gdwarf-2 \
  -DEMACS_NAME="\"GNU Emacs\"" -DVERSION="\"25.0.50\"" \
  -o etags.exe \
  <srcdir>/lib-src/etags.c regex.o \
  ../lib/libgnu.a  ntlib.o

But I don't find anything like "#define strcpy stpcpy" in the
preprocessed file, which I'm attaching to this message.

-- 
Dani Moncayo

[-- Attachment #2: etags.prep.c.zip --]
[-- Type: application/zip, Size: 48973 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27 10:26                     ` Dani Moncayo
@ 2014-12-27 10:39                       ` Eli Zaretskii
  2014-12-27 10:54                         ` Dani Moncayo
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2014-12-27 10:39 UTC (permalink / raw)
  To: Dani Moncayo; +Cc: chengang31, emacs-devel

> Date: Sat, 27 Dec 2014 11:26:47 +0100
> From: Dani Moncayo <dmoncayo@gmail.com>
> Cc: cg <chengang31@gmail.com>, 
> 	Emacs development discussions <emacs-devel@gnu.org>
> 
> >  Can you try to find out why do you get this
> > error?  If nothing else helps, please look in a preprocessed version
> > of ntlib.c for any header files that "#define strcpy stpcpy" or some
> > such.
> 
> I've generated the preprocessed version of ntlib.c with the same
> command run by 'make', but adding a "-E" switch as first argument to
> 'gcc':
> 
>   $ gcc -E -std=gnu99  -mtune=pentium4 \
>   -I. \
>   -I../src -I../lib \
>   -I<srcdir>/lib-src \
>   -I<srcdir>/lib-src/../src \
>   -I<srcdir>/lib-src/../lib \
>   -mtune=pentium4  -DGLYPH_DEBUG=1 -DUSE_CRT_DLL=1 \
>   -I <srcdir>/nt/inc -g3 -O2 -gdwarf-2 \
>   -DEMACS_NAME="\"GNU Emacs\"" -DVERSION="\"25.0.50\"" \
>   -o etags.exe \
>   <srcdir>/lib-src/etags.c regex.o \
>   ../lib/libgnu.a  ntlib.o
> 
> But I don't find anything like "#define strcpy stpcpy" in the
> preprocessed file, which I'm attaching to this message.

Thanks, but this is a wrong command, so it produced the preprocessed
source of etags.c, not of ntlib.c.

To get the latter, say "make -W ntlib.c ntlib.o" in the lib-src
directory, then use the command to compile ntlib.c into ntlib.o with
"-c" replaced by "-E" and "-o ntlib.o" replaced with "-o ntlib.ii".
Then send ntlib.ii you get.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27 10:39                       ` Eli Zaretskii
@ 2014-12-27 10:54                         ` Dani Moncayo
  0 siblings, 0 replies; 22+ messages in thread
From: Dani Moncayo @ 2014-12-27 10:54 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: cg, Emacs development discussions

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

> Thanks, but this is a wrong command, so it produced the preprocessed
> source of etags.c, not of ntlib.c.

Ooops, sorry.

> To get the latter, say "make -W ntlib.c ntlib.o" in the lib-src
> directory

It produces this command (prettified a bit):

  gcc -std=gnu99  -c -mtune=pentium4      \
  -I. \
  -I../src \
  -I../lib  \
  -I<srcdir>/lib-src \
  -I<srcdir>/lib-src/../src \
  -I<srcdir>/lib-src/../lib  \
  -mtune=pentium4  -DGLYPH_DEBUG=1 -DUSE_CRT_DLL=1 \
  -I <srcdir>/nt/inc \
  -g3 -O2 -gdwarf-2 <srcdir>/lib-src/ntlib.c

>, then use the command to compile ntlib.c into ntlib.o with
> "-c" replaced by "-E" and "-o ntlib.o" replaced with "-o ntlib.ii".

As you can see above, there is no "-o ntlib.o"; anyway I've added "-o ntlib.ii":

  gcc -std=gnu99  -E -o ntlib.ii -mtune=pentium4      \
  -I. \
  -I../src \
  -I../lib  \
  -I<srcdir>/lib-src \
  -I<srcdir>/lib-src/../src \
  -I<srcdir>/lib-src/../lib  \
  -mtune=pentium4  -DGLYPH_DEBUG=1 -DUSE_CRT_DLL=1 \
  -I <srcdir>/nt/inc \
  -g3 -O2 -gdwarf-2 <srcdir>/lib-src/ntlib.c


> Then send ntlib.ii you get.

See attached.

-- 
Dani Moncayo

[-- Attachment #2: ntlib.ii.zip --]
[-- Type: application/zip, Size: 216281 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27  7:45                   ` Eli Zaretskii
  2014-12-27 10:26                     ` Dani Moncayo
@ 2014-12-27 11:57                     ` cg
  2014-12-27 19:52                       ` Eli Zaretskii
  1 sibling, 1 reply; 22+ messages in thread
From: cg @ 2014-12-27 11:57 UTC (permalink / raw)
  To: emacs-devel

On 12/27/2014 3:45 PM, Eli Zaretskii wrote:
>
> Sorry, I don't understand this: there's no call to stpcpy on line 350
> of ntlib.c, or anywhere else in ntlib.c, actually.  That line calls
>

Yes, I was confused by the error message too, and found ntlib.c
didin't use stpcpy at all. It looks like it has something to do with
compiler optimization.

So I tried to use different optimization flags, and this error only
happens when -O2 or -Ofast is used as CFLAGS:

./autogen.sh
export CFLASG=-O0 # no error
#export CFLASG=-O1 # no error
#export CFLASG=-O2 # error!
#export CFLASG=-Ofast # error!
./confgure
make

I am using msys2.







^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27 11:57                     ` cg
@ 2014-12-27 19:52                       ` Eli Zaretskii
  2014-12-27 20:03                         ` David Engster
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2014-12-27 19:52 UTC (permalink / raw)
  To: chengang31; +Cc: emacs-devel

> From: cg <chengang31@gmail.com>
> Date: Sat, 27 Dec 2014 19:57:07 +0800
> 
> On 12/27/2014 3:45 PM, Eli Zaretskii wrote:
> >
> > Sorry, I don't understand this: there's no call to stpcpy on line 350
> > of ntlib.c, or anywhere else in ntlib.c, actually.  That line calls
> >
> 
> Yes, I was confused by the error message too, and found ntlib.c
> didin't use stpcpy at all. It looks like it has something to do with
> compiler optimization.
> 
> So I tried to use different optimization flags, and this error only
> happens when -O2 or -Ofast is used as CFLAGS:
> 
> ./autogen.sh
> export CFLASG=-O0 # no error
> #export CFLASG=-O1 # no error
> #export CFLASG=-O2 # error!
> #export CFLASG=-Ofast # error!
> ./confgure
> make
> 
> I am using msys2.

Incredible as it sounds, in an optimized build, GCC (sometimes?) calls
stpcpy even though the source calls strcpy, provided that the
prototype of stpcpy is in scope.  In this case, ntlib.c includes
windows.h, which includes string.h, which comes from lib/string.h,
which declares the prototype of stpcpy, and that is enough to trigger
this misfeature.

I fixed this by switching the order of the libraries, as suggested,
but only because doing so is TRT in general.

Thanks.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27 19:52                       ` Eli Zaretskii
@ 2014-12-27 20:03                         ` David Engster
  2014-12-27 20:17                           ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: David Engster @ 2014-12-27 20:03 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: chengang31, emacs-devel

Eli Zaretskii writes:
>> From: cg <chengang31@gmail.com>
>> Date: Sat, 27 Dec 2014 19:57:07 +0800
>> 
>
>> On 12/27/2014 3:45 PM, Eli Zaretskii wrote:
>> >
>> > Sorry, I don't understand this: there's no call to stpcpy on line 350
>> > of ntlib.c, or anywhere else in ntlib.c, actually.  That line calls
>> >
>> 
>> Yes, I was confused by the error message too, and found ntlib.c
>> didin't use stpcpy at all. It looks like it has something to do with
>> compiler optimization.
>> 
>> So I tried to use different optimization flags, and this error only
>> happens when -O2 or -Ofast is used as CFLAGS:
>> 
>> ./autogen.sh
>> export CFLASG=-O0 # no error
>> #export CFLASG=-O1 # no error
>> #export CFLASG=-O2 # error!
>> #export CFLASG=-Ofast # error!
>> ./confgure
>> make
>> 
>> I am using msys2.
>
> Incredible as it sounds, in an optimized build, GCC (sometimes?) calls
> stpcpy even though the source calls strcpy, provided that the
> prototype of stpcpy is in scope.  In this case, ntlib.c includes
> windows.h, which includes string.h, which comes from lib/string.h,
> which declares the prototype of stpcpy, and that is enough to trigger
> this misfeature.
>
> I fixed this by switching the order of the libraries, as suggested,
> but only because doing so is TRT in general.

Yes, it seems gcc optimizes this because of the following strlen
call. You can disable this optimization with -fno-optimize-strlen.

-David



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27 20:03                         ` David Engster
@ 2014-12-27 20:17                           ` Eli Zaretskii
  2014-12-27 20:25                             ` Eli Zaretskii
  0 siblings, 1 reply; 22+ messages in thread
From: Eli Zaretskii @ 2014-12-27 20:17 UTC (permalink / raw)
  To: David Engster; +Cc: chengang31, emacs-devel

> From: David Engster <deng@randomsample.de>
> Cc: chengang31@gmail.com,  emacs-devel@gnu.org
> Date: Sat, 27 Dec 2014 21:03:10 +0100
> 
> > Incredible as it sounds, in an optimized build, GCC (sometimes?) calls
> > stpcpy even though the source calls strcpy, provided that the
> > prototype of stpcpy is in scope.  In this case, ntlib.c includes
> > windows.h, which includes string.h, which comes from lib/string.h,
> > which declares the prototype of stpcpy, and that is enough to trigger
> > this misfeature.
> >
> > I fixed this by switching the order of the libraries, as suggested,
> > but only because doing so is TRT in general.
> 
> Yes, it seems gcc optimizes this because of the following strlen
> call. You can disable this optimization with -fno-optimize-strlen.

GCC shouldn't have done that by default.  It's nasty.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27 20:17                           ` Eli Zaretskii
@ 2014-12-27 20:25                             ` Eli Zaretskii
  2014-12-27 20:49                               ` David Engster
  2014-12-28 23:57                               ` Richard Stallman
  0 siblings, 2 replies; 22+ messages in thread
From: Eli Zaretskii @ 2014-12-27 20:25 UTC (permalink / raw)
  To: deng; +Cc: chengang31, emacs-devel

> Date: Sat, 27 Dec 2014 22:17:45 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: chengang31@gmail.com, emacs-devel@gnu.org
> 
> > Yes, it seems gcc optimizes this because of the following strlen
> > call. You can disable this optimization with -fno-optimize-strlen.
> 
> GCC shouldn't have done that by default.  It's nasty.

To say nothing of the fact that this switch is not documented in the
GCC manual, not even in the manual that comes with GCC 4.8.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  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
  1 sibling, 1 reply; 22+ messages in thread
From: David Engster @ 2014-12-27 20:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: chengang31, emacs-devel

Eli Zaretskii writes:
>> Date: Sat, 27 Dec 2014 22:17:45 +0200
>> From: Eli Zaretskii <eliz@gnu.org>
>> Cc: chengang31@gmail.com, emacs-devel@gnu.org
>> 
>> > Yes, it seems gcc optimizes this because of the following strlen
>> > call. You can disable this optimization with -fno-optimize-strlen.
>> 
>> GCC shouldn't have done that by default.  It's nasty.
>
> To say nothing of the fact that this switch is not documented in the
> GCC manual, not even in the manual that comes with GCC 4.8.

It was documented in the GCC 4.7 release notes

https://gcc.gnu.org/gcc-4.7/changes.html

but was apparently forgotten for the regular docs. It's not even in
4.9.2, but it seems they just fixed it, since at least -foptimize-strlen
is now documented:

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options

However, the above release notes also say that it will only switch
functions "for hosted compilations where stpcpy is available in the
runtime and headers provide its prototype", so the prototype alone
should not be enough. Why does GCC think that your runtime provides
stpcpy when it does not?

-David



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27 20:49                               ` David Engster
@ 2014-12-28  3:36                                 ` Eli Zaretskii
  0 siblings, 0 replies; 22+ messages in thread
From: Eli Zaretskii @ 2014-12-28  3:36 UTC (permalink / raw)
  To: David Engster; +Cc: chengang31, emacs-devel

> From: David Engster <deng@randomsample.de>
> Cc: chengang31@gmail.com,  emacs-devel@gnu.org
> Date: Sat, 27 Dec 2014 21:49:50 +0100
> 
> However, the above release notes also say that it will only switch
> functions "for hosted compilations where stpcpy is available in the
> runtime and headers provide its prototype", so the prototype alone
> should not be enough. Why does GCC think that your runtime provides
> stpcpy when it does not?

It probably assumes that if a system header provides a prototype,
it's a sign that the runtime has it.  And gnulib headers announce
themselves as system headers.



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Using stpcpy
  2014-12-27 20:25                             ` Eli Zaretskii
  2014-12-27 20:49                               ` David Engster
@ 2014-12-28 23:57                               ` Richard Stallman
  1 sibling, 0 replies; 22+ messages in thread
From: Richard Stallman @ 2014-12-28 23:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: chengang31, deng, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > GCC shouldn't have done that by default.  It's nasty.

  > To say nothing of the fact that this switch is not documented in the
  > GCC manual, not even in the manual that comes with GCC 4.8.

Please file a bug report to GCC.

-- 
Dr Richard Stallman
President, Free Software Foundation
51 Franklin St
Boston MA 02110
USA
www.fsf.org  www.gnu.org
Skype: No way! That's nonfree (freedom-denying) software.
  Use Ekiga or an ordinary phone call.




^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2014-12-28 23:57 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-22 16:41 Using stpcpy Dmitry Antipov
2014-12-23  6:47 ` Paul Eggert
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

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).