From: Adam Tkac Date: Wed, 3 Dec 2008 14:13:36 +0000 (+0000) Subject: [Portability] Reimplement vsnprintf to be C89 compatible X-Git-Tag: v0.0.90~347 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=241e9009710f205fb95273a9bed9684285a2ef0d;p=tigervnc.git [Portability] Reimplement vsnprintf to be C89 compatible 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 --- diff --git a/common/os/print.c b/common/os/print.c index a38ea2fe..f24717fb 100644 --- a/common/os/print.c +++ b/common/os/print.c @@ -21,38 +21,71 @@ #endif #include + #include +#include +#include #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 */ diff --git a/common/os/print.h b/common/os/print.h index ea550411..47893adf 100644 --- a/common/os/print.h +++ b/common/os/print.h @@ -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