]> git.sesse.net Git - vlc/blobdiff - include/vlc_fixups.h
win32: fix %zu fixups - dont use mingw's vsnprintf
[vlc] / include / vlc_fixups.h
index b88a900b2383c353067fc814ccbae9b1554f8ab7..02cf88c804e6bfcf306970e0a6ed6f1f1871032f 100644 (file)
@@ -38,6 +38,155 @@ static inline char *strdup (const char *str)
 }
 #endif
 
+#ifdef WIN32
+/* Windows' printf doesn't support %z modifiers, thus we need to rewrite
+ * the format string in a wrapper. */
+# include <string.h>
+# include <stdlib.h>
+static inline char *vlc_fix_format_string (const char *format)
+{
+    char *fmt;
+# ifdef WIN64
+    const char *src = format, *tmp;
+    char *dst;
+    size_t n = 0;
+    while ((tmp = strstr (src, "%z")) != NULL)
+    {
+        n++;
+        src = tmp + 2;
+    }
+    if (n == 0)
+        return NULL;
+
+    fmt = (char*)malloc (strlen (format) + n + 1);
+    if (fmt == NULL)
+        return NULL;
+
+    src = format;
+    dst = fmt;
+    while ((tmp = strstr (src, "%z")) != NULL)
+    {
+        size_t d = tmp - src;
+        memcpy (dst, src, d);
+        dst += d;
+        memcpy (dst, "%ll", 3);
+        dst += 3;
+        src = tmp + 2;
+    }
+    strcpy (dst, src);
+# else
+    char *f;
+    if (strstr (format, "%z") == NULL)
+        return NULL;
+
+    fmt = strdup (format);
+    if (fmt == NULL)
+        return NULL;
+
+    while ((f = strstr (fmt, "%z")) != NULL)
+    {
+       f[1] = 'l';
+    }
+# endif
+    return fmt;
+}
+
+# include <stdio.h>
+# include <stdarg.h>
+
+static inline int vlc_vprintf (const char *format, va_list ap)
+{
+    char *fmt = vlc_fix_format_string (format);
+    int ret = vprintf (fmt ? fmt : format, ap);
+    free (fmt);
+    return ret;
+}
+# define vprintf vlc_vprintf
+
+static inline int vlc_vfprintf (FILE *stream, const char *format, va_list ap)
+{
+    char *fmt = vlc_fix_format_string (format);
+    int ret = vfprintf (stream, fmt ? fmt : format, ap);
+    free (fmt);
+    return ret;
+}
+# define vfprintf vlc_vfprintf
+
+static inline int vlc_vsprintf (char *str, const char *format, va_list ap)
+{
+    char *fmt = vlc_fix_format_string (format);
+    int ret = vsprintf (str, fmt ? fmt : format, ap);
+    free (fmt);
+    return ret;
+}
+# define vsprintf vlc_vsprintf
+
+static inline int vlc_vsnprintf (char *str, size_t size, const char *format, va_list ap)
+{
+    char *fmt = vlc_fix_format_string (format);
+    /* traditionally, MSVCRT has provided vsnprintf as _vsnprintf;
+     * to 'aid' portability/standards compliance, mingw provides a
+     * static version of vsnprintf that is buggy.  Be sure to use
+     * MSVCRT version, at least it behaves as expected */
+    int ret = _vsnprintf (str, size, fmt ? fmt : format, ap);
+    free (fmt);
+    return ret;
+}
+# define vsnprintf vlc_vsnprintf
+
+static inline int vlc_printf (const char *format, ...)
+{
+    va_list ap;
+    int ret;
+    va_start (ap, format);
+    ret = vlc_vprintf (format, ap);
+    va_end (ap);
+    return ret;
+}
+# define printf(...) vlc_printf(__VA_ARGS__)
+
+static inline int vlc_fprintf (FILE *stream, const char *format, ...)
+{
+    va_list ap;
+    int ret;
+    va_start (ap, format);
+    ret = vlc_vfprintf (stream, format, ap);
+    va_end (ap);
+    return ret;
+}
+# define fprintf vlc_fprintf
+
+#if 0
+static inline int vlc_sprintf (char *str, const char *format, ...)
+{
+    va_list ap;
+    int ret;
+    va_start (ap, format);
+    ret = vlc_vsprintf (str, format, ap);
+    va_end (ap);
+    return ret;
+}
+# define sprintf vlc_sprintf
+#endif
+
+static inline int vlc_snprintf (char *str, size_t size, const char *format, ...)
+{
+    va_list ap;
+    int ret;
+    va_start (ap, format);
+    ret = vlc_vsnprintf (str, size, format, ap);
+    va_end (ap);
+    return ret;
+}
+/* win32: snprintf must always be vlc_snprintf or _snprintf,
+ * see comment in vlc_vsnprintf */
+# define snprintf vlc_snprintf
+
+/* Make sure we don't use flawed vasprintf or asprintf either */
+# undef HAVE_VASPRINTF
+# undef HAVE_ASPRINTF
+#endif
+
 #ifndef HAVE_VASPRINTF
 # include <stdio.h>
 # include <stdlib.h>
@@ -50,7 +199,7 @@ static inline int vasprintf (char **strp, const char *fmt, va_list ap)
     if (res == NULL)
         return -1;
     *strp = res;
-    return vsprintf (res, fmt, ap);
+    return vsnprintf (res, len, fmt, ap);
 #else
     /* HACK: vsnprintf in the WinCE API behaves like
      * the one in glibc 2.0 and doesn't return the number of characters
@@ -77,8 +226,7 @@ static inline int vasprintf (char **strp, const char *fmt, va_list ap)
         }
 
         /* Else try again with more space. */
-        if (n == -1)
-            size *= 2;  /* twice the old size */
+        size *= 2;  /* twice the old size */
 
         if ((np = (char *) realloc (res, size)) == NULL)
         {