The FLTK string functions are now compiled in on all systems (STR

#774)

src/vsnprintf.c:
    - Replaced fl_vsnprintf() implementation with one that
      properly emulates the vsnprintf() function.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@4262 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Michael R Sweet
2005-04-10 22:14:08 +00:00
parent 5b20fbdce4
commit 558958ad23
4 changed files with 215 additions and 88 deletions
+2
View File
@@ -2,6 +2,8 @@ CHANGES IN FLTK 1.1.7
- Documentation fixes (STR #648, STR #692, STR #730, STR - Documentation fixes (STR #648, STR #692, STR #730, STR
#744, STR #745) #744, STR #745)
- The FLTK string functions are now compiled in on all
systems (STR #774)
- Fixed symbol demo label bug (STR #777) - Fixed symbol demo label bug (STR #777)
- Fixed position of menu titles (STR #795) - Fixed position of menu titles (STR #795)
- Added missing Fl_Window::copy_label() method. - Added missing Fl_Window::copy_label() method.
+2 -4
View File
@@ -25,7 +25,7 @@
#include "flstring.h" #include "flstring.h"
# if !HAVE_STRLCAT
/* /*
* 'fl_strlcat()' - Safely concatenate two strings. * 'fl_strlcat()' - Safely concatenate two strings.
*/ */
@@ -64,9 +64,8 @@ fl_strlcat(char *dst, /* O - Destination string */
return (dstlen + srclen); return (dstlen + srclen);
} }
# endif /* !HAVE_STRLCAT */
# if !HAVE_STRLCPY
/* /*
* 'fl_strlcpy()' - Safely copy two strings. * 'fl_strlcpy()' - Safely copy two strings.
*/ */
@@ -97,7 +96,6 @@ fl_strlcpy(char *dst, /* O - Destination string */
return (srclen); return (srclen);
} }
# endif /* !HAVE_STRLCPY */
/* /*
+4 -4
View File
@@ -69,13 +69,13 @@ int strncasecmp(const char*,const char*,int);
char *strdup(const char*); char *strdup(const char*);
# endif # endif
# if !HAVE_SNPRINTF
FL_EXPORT extern int fl_snprintf(char *, size_t, const char *, ...); FL_EXPORT extern int fl_snprintf(char *, size_t, const char *, ...);
# if !HAVE_SNPRINTF
# define snprintf fl_snprintf # define snprintf fl_snprintf
# endif /* !HAVE_SNPRINTF */ # endif /* !HAVE_SNPRINTF */
# if !HAVE_VSNPRINTF
FL_EXPORT extern int fl_vsnprintf(char *, size_t, const char *, va_list ap); FL_EXPORT extern int fl_vsnprintf(char *, size_t, const char *, va_list ap);
# if !HAVE_VSNPRINTF
# define vsnprintf fl_vsnprintf # define vsnprintf fl_vsnprintf
# endif /* !HAVE_VSNPRINTF */ # endif /* !HAVE_VSNPRINTF */
@@ -84,13 +84,13 @@ FL_EXPORT extern int fl_vsnprintf(char *, size_t, const char *, va_list ap);
* that work the way strncpy() and strncat() *should* have worked. * that work the way strncpy() and strncat() *should* have worked.
*/ */
# if !HAVE_STRLCAT
FL_EXPORT extern size_t fl_strlcat(char *, const char *, size_t); FL_EXPORT extern size_t fl_strlcat(char *, const char *, size_t);
# if !HAVE_STRLCAT
# define strlcat fl_strlcat # define strlcat fl_strlcat
# endif /* !HAVE_STRLCAT */ # endif /* !HAVE_STRLCAT */
# if !HAVE_STRLCPY
FL_EXPORT extern size_t fl_strlcpy(char *, const char *, size_t); FL_EXPORT extern size_t fl_strlcpy(char *, const char *, size_t);
# if !HAVE_STRLCPY
# define strlcpy fl_strlcpy # define strlcpy fl_strlcpy
# endif /* !HAVE_STRLCPY */ # endif /* !HAVE_STRLCPY */
+207 -80
View File
@@ -1,21 +1,7 @@
/* /*
* "$Id$" * "$Id$"
* *
* vsnprintf() function for the Fast Light Tool Kit (FLTK). * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK).
*
* Emulates this call on systems that lack it (pretty much everything
* except glibc systems).
*
* KNOWN BUGS:
*
* Field width & Precision is ignored for %%, %c, and %s.
*
* A malicious user who manages to create a %-fmt string that prints
* more than 99 characters can still overflow the temporary buffer.
* For instance %110f will overflow.
*
* Only handles formats that are both documented in the glibc man page
* for printf and also handled by your system's sprintf().
* *
* Copyright 1998-2005 by Bill Spitzak and others. * Copyright 1998-2005 by Bill Spitzak and others.
* *
@@ -48,76 +34,219 @@
extern "C" { extern "C" {
#endif #endif
#if !HAVE_VSNPRINTF int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) {
char *bufptr, /* Pointer to position in buffer */
*bufend, /* Pointer to end of buffer */
sign, /* Sign of format width */
size, /* Size character (h, l, L) */
type; /* Format type character */
const char *bufformat; /* Start of format */
int width, /* Width of field */
prec; /* Number of characters of precision */
char tformat[100], /* Temporary format string for sprintf() */
temp[1024]; /* Buffer for formatted numbers */
char *s; /* Pointer to string */
int slen; /* Length of string */
int bytes; /* Total number of bytes needed */
int fl_vsnprintf(char* str, size_t size, const char* fmt, va_list ap) {
const char* e = str+size-1;
char* p = str;
char copy[20];
char* copy_p;
char sprintf_out[100];
while (*fmt && p < e) { /*
if (*fmt != '%') { * Loop through the format string, formatting as needed...
*p++ = *fmt++; */
} else {
fmt++; bufptr = buffer;
copy[0] = '%'; bufend = buffer + bufsize - 1;
for (copy_p = copy+1; copy_p < copy+19;) { bytes = 0;
switch ((*copy_p++ = *fmt++)) {
case 0: while (*format) {
fmt--; goto CONTINUE; if (*format == '%') {
case '%': bufformat = format;
*p++ = '%'; goto CONTINUE; format ++;
case 'c':
*p++ = va_arg(ap, int); if (*format == '%') {
goto CONTINUE; *bufptr++ = *format++;
case 'd': continue;
case 'i': } else if (strchr(" -+#\'", *format)) sign = *format++;
case 'o': else sign = 0;
case 'u':
case 'x': width = 0;
case 'X': while (isdigit(*format)) width = width * 10 + *format++ - '0';
*copy_p = 0;
sprintf(sprintf_out, copy, va_arg(ap, int)); if (*format == '.') {
copy_p = sprintf_out; format ++;
goto DUP; prec = 0;
case 'e':
case 'E': while (isdigit(*format)) prec = prec * 10 + *format++ - '0';
case 'f': } else prec = -1;
case 'g':
*copy_p = 0; if (*format == 'l' && format[1] == 'l') {
sprintf(sprintf_out, copy, va_arg(ap, double)); size = 'L';
copy_p = sprintf_out; format += 2;
goto DUP; } else if (*format == 'h' || *format == 'l' || *format == 'L') size = *format++;
case 'p':
*copy_p = 0; if (!*format) break;
sprintf(sprintf_out, copy, va_arg(ap, void*));
copy_p = sprintf_out; type = *format++;
goto DUP;
case 'n': switch (type) {
*(va_arg(ap, int*)) = p-str; case 'E' : /* Floating point formats */
goto CONTINUE; case 'G' :
case 's': case 'e' :
copy_p = va_arg(ap, char*); case 'f' :
if (!copy_p) copy_p = "NULL"; case 'g' :
DUP: if ((format - bufformat + 1) > sizeof(tformat) ||
while (*copy_p && p < e) *p++ = *copy_p++; (width + 2) > sizeof(temp)) break;
goto CONTINUE;
} strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, double));
bytes += strlen(temp);
if (bufptr) {
if ((bufptr + strlen(temp)) > bufend) {
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
} else {
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
break;
case 'B' : /* Integer formats */
case 'X' :
case 'b' :
case 'd' :
case 'i' :
case 'o' :
case 'u' :
case 'x' :
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp)) break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, int));
bytes += strlen(temp);
if (bufptr) {
if ((bufptr + strlen(temp)) > bufend) {
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
} else {
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
break;
case 'p' : /* Pointer value */
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp)) break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, void *));
bytes += strlen(temp);
if (bufptr) {
if ((bufptr + strlen(temp)) > bufend) {
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
} else {
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
break;
case 'c' : /* Character or character array */
bytes += width;
if (bufptr) {
if (width <= 1) *bufptr++ = va_arg(ap, int);
else {
if ((bufptr + width) > bufend) width = bufend - bufptr;
memcpy(bufptr, va_arg(ap, char *), width);
bufptr += width;
}
}
break;
case 's' : /* String */
if ((s = va_arg(ap, char *)) == NULL) s = "(null)";
slen = strlen(s);
if (slen > width && prec != width) width = slen;
bytes += width;
if (bufptr) {
if ((bufptr + width) > bufend) width = bufend - bufptr;
if (slen > width) slen = width;
if (sign == '-') {
strncpy(bufptr, s, slen);
memset(bufptr + slen, ' ', width - slen);
} else {
memset(bufptr, ' ', width - slen);
strncpy(bufptr + width - slen, s, slen);
}
bufptr += width;
}
break;
case 'n' : /* Output number of chars so far */
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp)) break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, int));
bytes += strlen(temp);
if (bufptr) {
if ((bufptr + strlen(temp)) > bufend) {
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
} else {
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
break;
} }
} else {
bytes ++;
if (bufptr && bufptr < bufend) *bufptr++ = *format++;
} }
CONTINUE:;
} }
*p = 0;
if (*fmt) return -1; /*
return p-str; * Nul-terminate the string and return the number of characters needed.
*/
if (bufptr) *bufptr = '\0';
return (bytes);
} }
#endif
#if !HAVE_SNPRINTF
int fl_snprintf(char* str, size_t size, const char* fmt, ...) { int fl_snprintf(char* str, size_t size, const char* fmt, ...) {
int ret; int ret;
va_list ap; va_list ap;
@@ -127,8 +256,6 @@ int fl_snprintf(char* str, size_t size, const char* fmt, ...) {
return ret; return ret;
} }
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif