]> source.dussan.org Git - tigervnc.git/commitdiff
[Portability] Reimplement vsnprintf to be C89 compatible
authorAdam Tkac <atkac@redhat.com>
Wed, 3 Dec 2008 14:13:36 +0000 (14:13 +0000)
committerAdam Tkac <atkac@redhat.com>
Wed, 3 Dec 2008 14:13:36 +0000 (14:13 +0000)
Main problem is that C89 doesn't have va_copy macro thus you can't parse va_list
twice.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3289 3789f03b-4d11-0410-bbf8-ca57d06f2519

common/os/print.c
common/os/print.h

index a38ea2fef8b4ccfb5544cc4f950bbeb65881c99e..f24717fbb6ad84427ebc8cc52ff9fb4006a362f1 100644 (file)
 #endif
 
 #include <os/print.h>
+
 #include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
 
 #ifndef HAVE_VSNPRINTF
-int vsnprintf(char *str, size_t n, const char *format, va_list ap) {
-       static FILE *fp = NULL;
-       va_list ap_new;
-       int len, written;
+size_t internal_memcpy(char *dest, const char *src, size_t destsize,
+                      size_t srcsize) {
+       size_t copied;
 
-       if (n < 1)
-               return 0;
+       copied = ((destsize) < (srcsize)) ? (destsize) : (srcsize);
+       memcpy(dest, src, copied);
 
-       str[0] = '\0';
-       if (fp == NULL) {
-               fp = fopen("/dev/null","w");
-               if (fp == NULL)
-                       return 0;
-       }
+       return copied;
+}
 
-       va_copy(ap_new, ap);
-       len = vfprintf(fp, format, ap_new);
-       va_end(ap_new);
+int tight_vsnprintf(char *str, size_t n, const char *format, va_list ap) {
+       int written = 0;
+       int tmpint, len;
+       char buf[64]; /* Is it enough? */
+       char *tmpstr;
 
-       if (len <= 0)
+       if (format == NULL || n < 1)
                return 0;
 
-       CharArray s(len+1);
-       vsprintf(s.buf, format, ap);
+       while (*format != '\0' && written < n - 1) {
+               if (*format != '%') {
+                       if (written < n) {
+                               str[written++] = *format++;
+                               continue;
+                       } else
+                               break;
+               }
+
+               format++;
+               switch (*format) {
+                       case '\0':
+                               str[written++] = '%';
+                               continue;
+                       case 'd':
+                               tmpint = va_arg(ap, int);
+                               sprintf(buf, "%d", tmpint);
+                               len = strlen(buf);
+                               written += internal_memcpy (&str[written], buf,
+                                                           len, n - written);
+                               break;
+                       case 's':
+                               tmpstr = va_arg(ap, char *);
+                               len = strlen(tmpstr);
+                               written += internal_memcpy (&str[written],
+                                                           tmpstr, len,
+                                                           n - written);
+                               break;
+                       /* Catch unimplemented stuff */
+                       default:
+                               fprintf(stderr, "Unimplemented format: %c\n",
+                                       *format);
+                               abort();
+               }
+               format++;
+       }
 
-       written = (len < (n - 1)) ? len : (n - 1);
-       memcpy(str, s.buf, written);
        str[written] = '\0';
-       return len;
+
+       return written;
 }
 #endif /* HAVE_VSNPRINTF */
 
index ea5504113987ed8736d349bd57ba640ff4a2d0c7..47893adf21dfd58786448b712bab10ff593775ab 100644 (file)
@@ -36,7 +36,16 @@ extern "C" {
 #endif
 
 #ifndef HAVE_VSNPRINTF
-int vsnprintf(char *str, size_t n, const char *format, va_list ap);
+/* NOTE:
+ *
+ * This is only very limited implementation for our internal purposes. It
+ * doesn't conform to C99/POSIX
+ * - limited conversion specifiers
+ * - returns written number of characters instead of number what would be
+ *   written
+ */
+int tight_vsnprintf(char *str, size_t n, const char *format, va_list ap);
+#define vsnprintf tight_vsnprintf
 #endif
 
 #ifdef __cplusplus