Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Tom Lane wrote:
> >> First line of thought: we surely must not insert a snprintf into
> >> libpq.so unless it is 100% up to spec *and* has no performance issues
> >> ... neither of which can be claimed of the CVS-tip version.
> 
> > Agreed, and we have to support all the 64-bit specifications a port
> > might support like %qd and %I64d as well as %lld.  I have added that to
> > our current CVS version.
> 
> I really dislike that idea and request that you revert it.
> 
> > Is there any way we can have just gettext() call our snprintf under a
> > special name?
> 
> The issue only comes up in libpq --- in the backend there is no reason
> that snprintf can't be our snprintf, and likewise in self-contained
> programs like psql.  It might be worth the pain-in-the-neck quality to
> have libpq refer to the functions as pq_snprintf etc.  Perhaps we could
> do this via macros
> 
> #define snprintf      pq_snprintf
> 
> and not have to uglify the source code.

OK, here is a patch that changes snprintf() to pg_snprintf() for
platforms that need our snprintf.  We do the same thing with
pgrename/pgunlink.  

It manages to preserve printf-like argument checking in gcc.

I considered using a macro just in libpq but realized it was going to be
too ugly and too easy to break without us detecting it.  

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: configure
===================================================================
RCS file: /cvsroot/pgsql/configure,v
retrieving revision 1.432
diff -c -c -r1.432 configure
*** configure   2 Mar 2005 15:42:35 -0000       1.432
--- configure   10 Mar 2005 21:05:27 -0000
***************
*** 14973,14978 ****
--- 14973,14983 ----
  
  # Now we have checked all the reasons to replace snprintf
  if test $pgac_need_repl_snprintf = yes; then
+ 
+ cat >>confdefs.h <<\_ACEOF
+ #define USE_SNPRINTF 1
+ _ACEOF
+ 
    LIBOBJS="$LIBOBJS snprintf.$ac_objext"
  fi
  
Index: configure.in
===================================================================
RCS file: /cvsroot/pgsql/configure.in,v
retrieving revision 1.405
diff -c -c -r1.405 configure.in
*** configure.in        2 Mar 2005 15:42:35 -0000       1.405
--- configure.in        10 Mar 2005 21:05:28 -0000
***************
*** 1143,1148 ****
--- 1143,1149 ----
  
  # Now we have checked all the reasons to replace snprintf
  if test $pgac_need_repl_snprintf = yes; then
+   AC_DEFINE(USE_SNPRINTF, 1, [Use replacement snprintf() functions.])
    AC_LIBOBJ(snprintf)
  fi
  
Index: src/bin/pg_ctl/pg_ctl.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_ctl/pg_ctl.c,v
retrieving revision 1.54
diff -c -c -r1.54 pg_ctl.c
*** src/bin/pg_ctl/pg_ctl.c     22 Feb 2005 04:39:22 -0000      1.54
--- src/bin/pg_ctl/pg_ctl.c     10 Mar 2005 21:05:30 -0000
***************
*** 337,355 ****
        if (log_file != NULL)
  #ifndef WIN32 /* Cygwin doesn't have START */
                snprintf(cmd, MAXPGPATH, "%s\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 
&%s",
  #else
                snprintf(cmd, MAXPGPATH, "%sSTART /B \"\" \"%s\" %s%s < \"%s\" 
>> \"%s\" 2>&1%s",
- #endif
                                 SYSTEMQUOTE, postgres_path, pgdata_opt, 
post_opts,
                                 DEVNULL, log_file, SYSTEMQUOTE);
        else
  #ifndef WIN32 /* Cygwin doesn't have START */
                snprintf(cmd, MAXPGPATH, "%s\"%s\" %s%s < \"%s\" 2>&1 &%s",
  #else
                snprintf(cmd, MAXPGPATH, "%sSTART /B \"\" \"%s\" %s%s < \"%s\" 
2>&1%s",
- #endif
                                 SYSTEMQUOTE, postgres_path, pgdata_opt, 
post_opts,
                                 DEVNULL, SYSTEMQUOTE);
  
        return system(cmd);
  }
--- 337,359 ----
        if (log_file != NULL)
  #ifndef WIN32 /* Cygwin doesn't have START */
                snprintf(cmd, MAXPGPATH, "%s\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 
&%s",
+                                SYSTEMQUOTE, postgres_path, pgdata_opt, 
post_opts,
+                                DEVNULL, log_file, SYSTEMQUOTE);
  #else
                snprintf(cmd, MAXPGPATH, "%sSTART /B \"\" \"%s\" %s%s < \"%s\" 
>> \"%s\" 2>&1%s",
                                 SYSTEMQUOTE, postgres_path, pgdata_opt, 
post_opts,
                                 DEVNULL, log_file, SYSTEMQUOTE);
+ #endif
        else
  #ifndef WIN32 /* Cygwin doesn't have START */
                snprintf(cmd, MAXPGPATH, "%s\"%s\" %s%s < \"%s\" 2>&1 &%s",
+                                SYSTEMQUOTE, postgres_path, pgdata_opt, 
post_opts,
+                                DEVNULL, SYSTEMQUOTE);
  #else
                snprintf(cmd, MAXPGPATH, "%sSTART /B \"\" \"%s\" %s%s < \"%s\" 
2>&1%s",
                                 SYSTEMQUOTE, postgres_path, pgdata_opt, 
post_opts,
                                 DEVNULL, SYSTEMQUOTE);
+ #endif
  
        return system(cmd);
  }
Index: src/bin/psql/command.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.140
diff -c -c -r1.140 command.c
*** src/bin/psql/command.c      22 Feb 2005 04:40:51 -0000      1.140
--- src/bin/psql/command.c      10 Mar 2005 21:05:31 -0000
***************
*** 1175,1187 ****
                 *      supplied path unless we use only backslashes, so we do 
that.
                 */
  #endif
-               snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
  #ifndef WIN32
!                               "/",
  #else
!                               "",     /* trailing separator already present */
  #endif
-                               (int)getpid());
  
                fname = (const char *) fnametmp;
  
--- 1175,1187 ----
                 *      supplied path unless we use only backslashes, so we do 
that.
                 */
  #endif
  #ifndef WIN32
!               snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
!                               "/", (int)getpid());
  #else
!               snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
!                               "" /* trailing separator already present */, 
(int)getpid());
  #endif
  
                fname = (const char *) fnametmp;
  
Index: src/include/pg_config.h.in
===================================================================
RCS file: /cvsroot/pgsql/src/include/pg_config.h.in,v
retrieving revision 1.81
diff -c -c -r1.81 pg_config.h.in
*** src/include/pg_config.h.in  6 Nov 2004 23:06:25 -0000       1.81
--- src/include/pg_config.h.in  10 Mar 2005 21:05:31 -0000
***************
*** 648,653 ****
--- 648,656 ----
  /* Define to 1 to build with Rendezvous support. (--with-rendezvous) */
  #undef USE_RENDEZVOUS
  
+ /* Use replacement snprintf() functions. */
+ #undef USE_SNPRINTF
+ 
  /* Define to build with (Open)SSL support. (--with-openssl) */
  #undef USE_SSL
  
Index: src/include/port.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/port.h,v
retrieving revision 1.70
diff -c -c -r1.70 port.h
*** src/include/port.h  27 Feb 2005 00:53:29 -0000      1.70
--- src/include/port.h  10 Mar 2005 21:05:31 -0000
***************
*** 107,112 ****
--- 107,132 ----
  extern unsigned char pg_toupper(unsigned char ch);
  extern unsigned char pg_tolower(unsigned char ch);
  
+ #ifdef USE_SNPRINTF
+ extern int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list 
args);
+ extern int pg_snprintf(char *str, size_t count, const char *fmt,...)
+ /* This extension allows gcc to check the format string */
+ __attribute__((format(printf, 3, 4)));
+ extern int pg_printf(const char *fmt,...)
+ /* This extension allows gcc to check the format string */
+ __attribute__((format(printf, 1, 2)));
+ 
+ #ifdef __GNUC__
+ #define vsnprintf(...)        pg_vsnprintf(__VA_ARGS__)
+ #define snprintf(...) pg_snprintf(__VA_ARGS__)
+ #define printf(...)           pg_printf(__VA_ARGS__)
+ #else
+ #define vsnprintf             pg_vsnprintf
+ #define snprintf              pg_snprintf
+ #define printf                        pg_printf
+ #endif
+ #endif
+ 
  /* Portable prompt handling */
  extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
  
Index: src/port/snprintf.c
===================================================================
RCS file: /cvsroot/pgsql/src/port/snprintf.c,v
retrieving revision 1.16
diff -c -c -r1.16 snprintf.c
*** src/port/snprintf.c 2 Mar 2005 23:56:53 -0000       1.16
--- src/port/snprintf.c 10 Mar 2005 21:05:32 -0000
***************
*** 67,83 ****
  
  /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.16 
2005/03/02 23:56:53 momjian Exp $";*/
  
! int                   snprintf(char *str, size_t count, const char *fmt,...);
! int                   vsnprintf(char *str, size_t count, const char *fmt, 
va_list args);
! int                   printf(const char *format, ...);
  static void dopr(char *buffer, const char *format, va_list args, char *end);
  
- /*
-  *    If vsnprintf() is not before snprintf() in this file, snprintf()
-  *    will call the system vsnprintf() on MinGW.
-  */
  int
! vsnprintf(char *str, size_t count, const char *fmt, va_list args)
  {
        char *end;
        str[0] = '\0';
--- 67,79 ----
  
  /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.16 
2005/03/02 23:56:53 momjian Exp $";*/
  
! int                   pg_snprintf(char *str, size_t count, const char 
*fmt,...);
! int                   pg_vsnprintf(char *str, size_t count, const char *fmt, 
va_list args);
! int                   pg_printf(const char *format, ...);
  static void dopr(char *buffer, const char *format, va_list args, char *end);
  
  int
! pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
  {
        char *end;
        str[0] = '\0';
***************
*** 89,107 ****
  }
  
  int
! snprintf(char *str, size_t count, const char *fmt,...)
  {
        int                     len;
        va_list         args;
  
        va_start(args, fmt);
!       len = vsnprintf(str, count, fmt, args);
        va_end(args);
        return len;
  }
  
  int
! printf(const char *fmt,...)
  {
        int                     len;
        va_list                 args;
--- 85,103 ----
  }
  
  int
! pg_snprintf(char *str, size_t count, const char *fmt,...)
  {
        int                     len;
        va_list         args;
  
        va_start(args, fmt);
!       len = pg_vsnprintf(str, count, fmt, args);
        va_end(args);
        return len;
  }
  
  int
! pg_printf(const char *fmt,...)
  {
        int                     len;
        va_list                 args;
***************
*** 109,115 ****
        char*                   p;
  
        va_start(args, fmt);
!       len = vsnprintf((char*)buffer, (size_t)4096, fmt, args);
        va_end(args);
        p = (char*)buffer;
        for(;*p;p++)
--- 105,111 ----
        char*                   p;
  
        va_start(args, fmt);
!       len = pg_vsnprintf((char*)buffer, (size_t)4096, fmt, args);
        va_end(args);
        p = (char*)buffer;
        for(;*p;p++)
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to