]> granicus.if.org Git - postgresql/commitdiff
Get rid of use of asprintf() in favor of a more portable implementation.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 22 Oct 2013 22:42:13 +0000 (18:42 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 22 Oct 2013 22:42:13 +0000 (18:42 -0400)
asprintf(), aside from not being particularly portable, has a fundamentally
badly-designed API; the psprintf() function that was added in passing in
the previous patch has a much better API choice.  Moreover, the NetBSD
implementation that was borrowed for the previous patch doesn't work with
non-C99-compliant vsnprintf, which is something we still have to cope with
on some platforms; and it depends on va_copy which isn't all that portable
either.  Get rid of that code in favor of an implementation similar to what
we've used for many years in stringinfo.c.  Also, move it into libpgcommon
since it's not really libpgport material.

I think this patch will be enough to turn the buildfarm green again, but
there's still cosmetic work left to do, namely get rid of pg_asprintf()
in favor of using psprintf().  That will come in a followon patch.

18 files changed:
configure
configure.in
src/backend/libpq/auth.c
src/backend/utils/init/miscinit.c
src/backend/utils/mmgr/mcxt.c
src/bin/psql/large_obj.c
src/common/Makefile
src/common/fe_memutils.c
src/common/psprintf.c [new file with mode: 0644]
src/include/pg_config.h.in
src/include/port.h
src/include/port/win32.h
src/include/utils/palloc.h
src/interfaces/ecpg/test/expected/pgtypeslib-dt_test2.c
src/interfaces/ecpg/test/pgtypeslib/dt_test2.pgc
src/interfaces/libpq/fe-auth.c
src/port/asprintf.c [deleted file]
src/tools/msvc/Mkvcbuild.pm

index c20afde8db140a2e1b234b4b87d626d52edca6e4..74e34ebae7a7d2ba97287debd7bd155b7059b6ca 100755 (executable)
--- a/configure
+++ b/configure
@@ -21500,8 +21500,7 @@ fi
 
 
 
-
-for ac_func in asprintf crypt fls getopt getrusage inet_aton random rint srandom strerror strlcat strlcpy
+for ac_func in crypt fls getopt getrusage inet_aton random rint srandom strerror strlcat strlcpy
 do
 as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
index d2bab32589ac3a21fde35f799f8153e98e3b96c0..a4baeaf4c9c4cc505086281a185e5dd9748f90b6 100644 (file)
@@ -1344,7 +1344,7 @@ else
   AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break])
 fi
 
-AC_REPLACE_FUNCS([asprintf crypt fls getopt getrusage inet_aton random rint srandom strerror strlcat strlcpy])
+AC_REPLACE_FUNCS([crypt fls getopt getrusage inet_aton random rint srandom strerror strlcat strlcpy])
 
 case $host_os in
 
index 7e65d2814c512fa92202c37e6349ede55c2bc95b..2dbf7e53a1294ec2a5f7c16bbc899bf5472b53ba 100644 (file)
@@ -1015,15 +1015,17 @@ pg_GSS_recvauth(Port *port)
                 */
                if (getenv("KRB5_KTNAME") == NULL)
                {
-                       char       *kt_path;
+                       size_t          kt_len = strlen(pg_krb_server_keyfile) + 14;
+                       char       *kt_path = malloc(kt_len);
 
-                       if (asprintf(&kt_path, "KRB5_KTNAME=%s", pg_krb_server_keyfile) < 0)
+                       if (!kt_path)
                        {
                                ereport(LOG,
                                                (errcode(ERRCODE_OUT_OF_MEMORY),
                                                 errmsg("out of memory")));
                                return STATUS_ERROR;
                        }
+                       snprintf(kt_path, kt_len, "KRB5_KTNAME=%s", pg_krb_server_keyfile);
                        putenv(kt_path);
                }
        }
index 381a629334b9e656bece6e92093de562136156ee..a3c82398ddea861b3a45ca0fe7eb0a0c5bb14d20 100644 (file)
@@ -165,10 +165,12 @@ make_absolute_path(const char *path)
                        }
                }
 
-               if (asprintf(&new, "%s/%s", buf, path) < 0)
+               new = malloc(strlen(buf) + strlen(path) + 2);
+               if (!new)
                        ereport(FATAL,
                                        (errcode(ERRCODE_OUT_OF_MEMORY),
                                         errmsg("out of memory")));
+               sprintf(new, "%s/%s", buf, path);
                free(buf);
        }
        else
index b7beb130ea32f794d93a029e0fde2fbdd750205c..9574fd3c7a3886fc6900d599fa64ca2eaffce71f 100644 (file)
@@ -852,52 +852,3 @@ pnstrdup(const char *in, Size len)
        out[len] = '\0';
        return out;
 }
-
-/*
- * asprintf()-like functions around palloc, adapted from
- * http://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/pkgtools/libnbcompat/files/asprintf.c
- */
-
-char *
-psprintf(const char *format, ...)
-{
-       va_list ap;
-       char   *retval;
-
-       va_start(ap, format);
-       retval = pvsprintf(format, ap);
-       va_end(ap);
-
-       return retval;
-}
-
-char *
-pvsprintf(const char *format, va_list ap)
-{
-       char *buf, *new_buf;
-       size_t len;
-       int retval;
-       va_list ap2;
-
-       len = 128;
-       buf = palloc(len);
-
-       va_copy(ap2, ap);
-       retval = vsnprintf(buf, len, format, ap);
-       Assert(retval >= 0);
-
-       if (retval < len)
-       {
-               new_buf = repalloc(buf, retval + 1);
-               va_end(ap2);
-               return new_buf;
-       }
-
-       len = (size_t)retval + 1;
-       pfree(buf);
-       buf = palloc(len);
-       retval = vsnprintf(buf, len, format, ap2);
-       va_end(ap2);
-       Assert(retval == len - 1);
-       return buf;
-}
index 065e0c1cb24d2721573bb605fd6acbe85841774a..faaecce61448b9481b3d7c946019caa3488212cb 100644 (file)
@@ -200,12 +200,12 @@ do_lo_import(const char *filename_arg, const char *comment_arg)
                char       *cmdbuf;
                char       *bufptr;
                size_t          slen = strlen(comment_arg);
-               int                     rv;
 
-               rv = asprintf(&cmdbuf, "COMMENT ON LARGE OBJECT %u IS '", loid);
-               if (rv < 0)
+               cmdbuf = malloc(slen * 2 + 256);
+               if (!cmdbuf)
                        return fail_lo_xact("\\lo_import", own_transaction);
-               bufptr = cmdbuf + rv;
+               sprintf(cmdbuf, "COMMENT ON LARGE OBJECT %u IS '", loid);
+               bufptr = cmdbuf + strlen(cmdbuf);
                bufptr += PQescapeStringConn(pset.db, bufptr, comment_arg, slen, NULL);
                strcpy(bufptr, "'");
 
index d4ef2f1a30785aa69841ae96aa28f3004c254098..62ca8ab0c353986c491934aed9eb1d01429ba2b4 100644 (file)
@@ -23,7 +23,7 @@ include $(top_builddir)/src/Makefile.global
 override CPPFLAGS := -DFRONTEND $(CPPFLAGS)
 LIBS += $(PTHREAD_LIBS)
 
-OBJS_COMMON = exec.o pgfnames.o relpath.o rmtree.o wait_error.o
+OBJS_COMMON = exec.o pgfnames.o psprintf.o relpath.o rmtree.o wait_error.o
 
 OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o
 
index 7b96a4b6ba7aaf48304bfbd7c95e1b485154bf7e..bfe79f8e4371068edd1334bab88614b4617e89fb 100644 (file)
@@ -93,25 +93,6 @@ pg_free(void *ptr)
                free(ptr);
 }
 
-int
-pg_asprintf(char **ret, const char *format, ...)
-{
-       va_list         ap;
-       int                     rc;
-
-       va_start(ap, format);
-       rc = vasprintf(ret, format, ap);
-       va_end(ap);
-
-       if (rc < 0)
-       {
-               fprintf(stderr, _("out of memory\n"));
-               exit(EXIT_FAILURE);
-       }
-
-       return rc;
-}
-
 /*
  * Frontend emulation of backend memory management functions.  Useful for
  * programs that compile backend files.
@@ -145,23 +126,3 @@ repalloc(void *pointer, Size size)
 {
        return pg_realloc(pointer, size);
 }
-
-char *
-psprintf(const char *format, ...)
-{
-       va_list     ap;
-       int         rc;
-       char       *ret;
-
-       va_start(ap, format);
-       rc = vasprintf(&ret, format, ap);
-       va_end(ap);
-
-       if (rc < 0)
-       {
-               fprintf(stderr, _("out of memory\n"));
-               exit(EXIT_FAILURE);
-       }
-
-       return ret;
-}
diff --git a/src/common/psprintf.c b/src/common/psprintf.c
new file mode 100644 (file)
index 0000000..87fd013
--- /dev/null
@@ -0,0 +1,207 @@
+/*-------------------------------------------------------------------------
+ *
+ * psprintf.c
+ *             sprintf into an allocated-on-demand buffer
+ *
+ *
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       src/common/psprintf.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "utils/memutils.h"
+
+
+static size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
+
+
+/*
+ * psprintf
+ *
+ * Format text data under the control of fmt (an sprintf-style format string)
+ * and return it in an allocated-on-demand buffer.     The buffer is allocated
+ * with palloc in the backend, or malloc in frontend builds.  Caller is
+ * responsible to free the buffer when no longer needed, if appropriate.
+ *
+ * Errors are not returned to the caller, but are reported via elog(ERROR)
+ * in the backend, or printf-to-stderr-and-exit() in frontend builds.
+ * One should therefore think twice about using this in libpq.
+ */
+char *
+psprintf(const char *fmt,...)
+{
+       size_t          len = 128;              /* initial assumption about buffer size */
+
+       for (;;)
+       {
+               char       *result;
+               va_list         args;
+
+               /*
+                * Allocate result buffer.      Note that in frontend this maps to malloc
+                * with exit-on-error.
+                */
+               result = (char *) palloc(len);
+
+               /* Try to format the data. */
+               va_start(args, fmt);
+               len = pvsnprintf(result, len, fmt, args);
+               va_end(args);
+
+               if (len == 0)
+                       return result;          /* success */
+
+               /* Release buffer and loop around to try again with larger len. */
+               pfree(result);
+       }
+}
+
+/*
+ * pvsnprintf
+ *
+ * Attempt to format text data under the control of fmt (an sprintf-style
+ * format string) and insert it into buf (which has length len).
+ *
+ * If successful, return zero. If there's not enough space in buf, return
+ * an estimate of the buffer size needed to succeed (this *must* be more
+ * than "len", else psprintf might loop infinitely).
+ * Other error cases do not return.
+ *
+ * XXX This API is ugly, but there seems no alternative given the C spec's
+ * restrictions on what can portably be done with va_list arguments: you have
+ * to redo va_start before you can rescan the argument list, and we can't do
+ * that from here.
+ */
+static size_t
+pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
+{
+       int                     nprinted;
+
+       Assert(len > 0);
+
+       errno = 0;
+
+       /*
+        * Assert check here is to catch buggy vsnprintf that overruns the
+        * specified buffer length.  Solaris 7 in 64-bit mode is an example of a
+        * platform with such a bug.
+        */
+#ifdef USE_ASSERT_CHECKING
+       buf[len - 1] = '\0';
+#endif
+
+       nprinted = vsnprintf(buf, len, fmt, args);
+
+       Assert(buf[len - 1] == '\0');
+
+       /*
+        * If vsnprintf reports an error other than ENOMEM, fail.  The possible
+        * causes of this are not user-facing errors, so elog should be enough.
+        */
+       if (nprinted < 0 && errno != 0 && errno != ENOMEM)
+       {
+#ifndef FRONTEND
+               elog(ERROR, "vsnprintf failed: %m");
+#else
+               fprintf(stderr, "vsnprintf failed: %s\n", strerror(errno));
+               exit(EXIT_FAILURE);
+#endif
+       }
+
+       /*
+        * Note: some versions of vsnprintf return the number of chars actually
+        * stored, not the total space needed as C99 specifies.  And at least one
+        * returns -1 on failure.  Be conservative about believing whether the
+        * print worked.
+        */
+       if (nprinted >= 0 && (size_t) nprinted < len - 1)
+       {
+               /* Success.  Note nprinted does not include trailing null. */
+               return 0;
+       }
+
+       if (nprinted >= 0 && (size_t) nprinted > len)
+       {
+               /*
+                * This appears to be a C99-compliant vsnprintf, so believe its
+                * estimate of the required space.      (If it's wrong, this code will
+                * still work, but may loop multiple times.)  Note that the space
+                * needed should be only nprinted+1 bytes, but we'd better allocate
+                * one more than that so that the test above will succeed next time.
+                *
+                * In the corner case where the required space just barely overflows,
+                * fall through so that we'll error out below (possibly after looping).
+                */
+               if ((size_t) nprinted <= MaxAllocSize - 2)
+                       return nprinted + 2;
+       }
+
+       /*
+        * Buffer overrun, and we don't know how much space is needed.  Estimate
+        * twice the previous buffer size.      If this would overflow, choke.  We use
+        * a palloc-oriented overflow limit even when in frontend.
+        */
+       if (len > MaxAllocSize / 2)
+       {
+#ifndef FRONTEND
+               ereport(ERROR,
+                               (errcode(ERRCODE_OUT_OF_MEMORY),
+                                errmsg("out of memory")));
+#else
+               fprintf(stderr, _("out of memory\n"));
+               exit(EXIT_FAILURE);
+#endif
+       }
+
+       return len * 2;
+}
+
+
+/*
+ * XXX this is going away shortly.
+ */
+#ifdef FRONTEND
+int
+pg_asprintf(char **ret, const char *fmt, ...)
+{
+       size_t          len = 128;              /* initial assumption about buffer size */
+
+       for (;;)
+       {
+               char       *result;
+               va_list         args;
+
+               /*
+                * Allocate result buffer.      Note that in frontend this maps to malloc
+                * with exit-on-error.
+                */
+               result = (char *) palloc(len);
+
+               /* Try to format the data. */
+               va_start(args, fmt);
+               len = pvsnprintf(result, len, fmt, args);
+               va_end(args);
+
+               if (len == 0)
+               {
+                       *ret = result;
+                       return 0;
+               }
+
+               /* Release buffer and loop around to try again with larger len. */
+               pfree(result);
+       }
+}
+#endif
index 0250e39dbbbb6883f120aec92b786ecaffb475c6..5eac52d93a9c24f78f7324c45d87ffee0da9cb7c 100644 (file)
@@ -87,9 +87,6 @@
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
-/* Define to 1 if you have the `asprintf' function. */
-#undef HAVE_ASPRINTF
-
 /* Define to 1 if you have the `cbrt' function. */
 #undef HAVE_CBRT
 
index 0b9dfc81e2a3d23176f90a1b52bda74a5dfea01a..5ef4b0a0b11863d96213e4379ee958109691cb98 100644 (file)
@@ -404,11 +404,6 @@ extern double rint(double x);
 extern int     inet_aton(const char *cp, struct in_addr * addr);
 #endif
 
-#ifndef HAVE_ASPRINTF
-extern int asprintf(char **ret, const char *fmt, ...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
-extern int vasprintf(char **ret, const char *fmt, va_list ap) __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
-#endif
-
 #if !HAVE_DECL_STRLCAT
 extern size_t strlcat(char *dst, const char *src, size_t siz);
 #endif
index 70175d14a57ab8a0bd994cc41eb3e9d8150627e2..2c2d93765ee3bffdc7d5e3527be29e1c4a882fd1 100644 (file)
@@ -237,15 +237,6 @@ int                        setitimer(int which, const struct itimerval * value, struct itimerval * ov
 #endif
 #endif
 
-/*
- * Supplement to <stdarg.h>
- */
-
-/* Visual Studios 2012 and earlier don't have va_copy() */
-#if defined(_MSC_VER) && _MSC_VER <= 1700
-#define va_copy(dest, src) ((dest) = (src))
-#endif
-
 /*
  * Supplement to <sys/types.h>.
  *
index 03ef87e2d7f591ff1ac58ca85b59c189ecedf5f2..676333fd6d87ee8864d813801dcd354a81aef834 100644 (file)
@@ -97,11 +97,15 @@ extern char *MemoryContextStrdup(MemoryContext context, const char *string);
 
 extern char *pstrdup(const char *in);
 extern char *pnstrdup(const char *in, Size len);
+
+/* sprintf into a palloc'd buffer */
+extern char *psprintf(const char *fmt,...)
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
+
+/* basic memory allocation functions */
 extern void *palloc(Size size);
 extern void *palloc0(Size size);
 extern void pfree(void *pointer);
 extern void *repalloc(void *pointer, Size size);
-extern char *psprintf(const char *format, ...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
-extern char *pvsprintf(const char *format, va_list ap) __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 0)));
 
 #endif   /* PALLOC_H */
index 8d716e58a22fd909f5da9615b49ca215eea6967c..d3ebb0e106c35f6f353f4e17feb539b4f776022b 100644 (file)
@@ -127,9 +127,12 @@ main(void)
                {
                        for (j = 0; times[j]; j++)
                        {
-                               char* t;
-                               if (asprintf(&t, "%s %s", dates[i], times[j]) < 0)
-                                       abort();
+                               int length = strlen(dates[i])
+                                               + 1
+                                               + strlen(times[j])
+                                               + 1;
+                               char* t = malloc(length);
+                               sprintf(t, "%s %s", dates[i], times[j]);
                                ts1 = PGTYPEStimestamp_from_asc(t, NULL);
                                text = PGTYPEStimestamp_to_asc(ts1);
                                if (i != 19 || j != 3) /* timestamp as integer or double differ for this case */
index 2a1c4a61dd9873db3410657049ff33e9a190a99e..0edf012fd11253da11ddbae50f8b08bd7d5fa81b 100644 (file)
@@ -92,9 +92,12 @@ main(void)
                {
                        for (j = 0; times[j]; j++)
                        {
-                               char* t;
-                               if (asprintf(&t, "%s %s", dates[i], times[j]) < 0)
-                                       abort();
+                               int length = strlen(dates[i])
+                                               + 1
+                                               + strlen(times[j])
+                                               + 1;
+                               char* t = malloc(length);
+                               sprintf(t, "%s %s", dates[i], times[j]);
                                ts1 = PGTYPEStimestamp_from_asc(t, NULL);
                                text = PGTYPEStimestamp_to_asc(ts1);
                                if (i != 19 || j != 3) /* timestamp as integer or double differ for this case */
index dfc9cfb1fbe88a62c111768793891eb0cee2877e..975f7958d11567ce93e8b7a384e3b2578c4884bb 100644 (file)
@@ -420,6 +420,7 @@ pg_GSS_startup(PGconn *conn)
 {
        OM_uint32       maj_stat,
                                min_stat;
+       int                     maxlen;
        gss_buffer_desc temp_gbuf;
 
        if (!(conn->pghost && conn->pghost[0] != '\0'))
@@ -440,14 +441,16 @@ pg_GSS_startup(PGconn *conn)
         * Import service principal name so the proper ticket can be acquired by
         * the GSSAPI system.
         */
-       if (asprintf((char **)&temp_gbuf.value, "%s@%s",
-                                conn->krbsrvname, conn->pghost) < 0)
+       maxlen = NI_MAXHOST + strlen(conn->krbsrvname) + 2;
+       temp_gbuf.value = (char *) malloc(maxlen);
+       if (!temp_gbuf.value)
        {
                printfPQExpBuffer(&conn->errorMessage,
-                                                 libpq_gettext("out of memory"));
+                                                 libpq_gettext("out of memory\n"));
                return STATUS_ERROR;
        }
-
+       snprintf(temp_gbuf.value, maxlen, "%s@%s",
+                        conn->krbsrvname, conn->pghost);
        temp_gbuf.length = strlen(temp_gbuf.value);
 
        maj_stat = gss_import_name(&min_stat, &temp_gbuf,
@@ -659,11 +662,13 @@ pg_SSPI_startup(PGconn *conn, int use_negotiate)
                                                  libpq_gettext("host name must be specified\n"));
                return STATUS_ERROR;
        }
-       if (asprintf(&conn->sspitarget, "%s/%s", conn->krbsrvname, conn->pghost) < 0)
+       conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(conn->pghost) + 2);
+       if (!conn->sspitarget)
        {
                printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
                return STATUS_ERROR;
        }
+       sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, conn->pghost);
 
        /*
         * Indicate that we're in SSPI authentication mode to make sure that
diff --git a/src/port/asprintf.c b/src/port/asprintf.c
deleted file mode 100644 (file)
index fafc03a..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* src/port/asprintf.c */
-
-/* $NetBSD: asprintf.c,v 1.3 2012/07/02 16:02:53 joerg Exp $ */
-
-/*-
- * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "c.h"
-
-#define HAVE_VA_COPY 1
-
-int
-asprintf(char **ret, const char *fmt, ...)
-{
-       va_list ap;
-       int retval;
-
-       va_start(ap, fmt);
-       retval = vasprintf(ret, fmt, ap);
-       va_end(ap);
-
-       return retval;
-}
-
-int
-vasprintf(char **ret, const char *fmt, va_list ap)
-{
-       char *buf, *new_buf;
-       size_t len;
-       int retval;
-       va_list ap2;
-
-       len = 128;
-       buf = malloc(len);
-       if (buf == NULL) {
-               *ret = NULL;
-               return -1;
-       }
-
-#if defined(HAVE_VA_COPY)
-       va_copy(ap2, ap);
-#define        my_va_end(ap2)  va_end(ap2)
-#elif defined(HAVE___BUILTIN_VA_COPY)
-       __builtin_va_copy(ap2, ap);
-#define        my_va_end(ap2)  __builtin_va_end(ap2)
-#else
-       ap2 = ap;
-#define        my_va_end(ap2)  do {} while (0)
-#endif
-       retval = vsnprintf(buf, len, fmt, ap);
-       if (retval < 0) {
-               free(buf);
-               *ret = NULL;
-               va_end(ap2);
-               return -1;
-       }
-
-       if (retval < len) {
-               new_buf = realloc(buf, retval + 1);
-               if (new_buf == NULL)
-                       *ret = buf;
-               else
-                       *ret = new_buf;
-               my_va_end(ap2);
-               return retval;
-       }
-
-       len = (size_t)retval + 1;
-       free(buf);
-       buf = malloc(len);
-       if (buf == NULL) {
-               *ret = NULL;
-               my_va_end(ap2);
-               return -1;
-       }
-       retval = vsnprintf(buf, len, fmt, ap2);
-       my_va_end(ap2);
-       if (retval != len - 1) {
-               free(buf);
-               *ret = NULL;
-               return -1;
-       }
-       *ret = buf;
-       return retval;
-}
index 0e84348e4d2d0b0771744980ddbeb50f6c55f2f8..bc7f4496e01e90345f241fe49f776a86e213adf9 100644 (file)
@@ -65,7 +65,7 @@ sub mkvcbuild
        $solution = CreateSolution($vsVersion, $config);
 
        our @pgportfiles = qw(
-         asprintf.c chklocale.c crypt.c fls.c fseeko.c getrusage.c inet_aton.c random.c
+         chklocale.c crypt.c fls.c fseeko.c getrusage.c inet_aton.c random.c
          srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
          erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
          pgcheckdir.c pg_crc.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
@@ -74,7 +74,7 @@ sub mkvcbuild
          win32error.c win32setlocale.c);
 
        our @pgcommonallfiles = qw(
-         exec.c pgfnames.c relpath.c rmtree.c wait_error.c);
+         exec.c pgfnames.c psprintf.c relpath.c rmtree.c wait_error.c);
 
        our @pgcommonfrontendfiles = (@pgcommonallfiles, qw(fe_memutils.c));