mirror of
https://github.com/fltk/fltk.git
synced 2026-06-04 15:32:12 +08:00
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:
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user