diff options
author | Chris Liddell <chris.liddell@artifex.com> | 2015-06-29 11:58:04 +0100 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2015-06-29 16:03:06 +0100 |
commit | 9ac4a688337c356f94bf49c8ebf345f5dd370d14 (patch) | |
tree | 288ab1368dd6e9ef6c1d692d12dc156a7f8079fb | |
parent | b0c457a915a016d0ba1764c561621877857f67cc (diff) | |
download | ghostpdl-gs_sprintf-apache_sprintf.tar.gz |
Tweak to work outside of Apachegs_sprintf-apache_sprintf
-rw-r--r-- | gs/base/gssprintf.c | 214 |
1 files changed, 168 insertions, 46 deletions
diff --git a/gs/base/gssprintf.c b/gs/base/gssprintf.c index 9ede49e2a..fa0e62675 100644 --- a/gs/base/gssprintf.c +++ b/gs/base/gssprintf.c @@ -13,34 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* From: https://svn.apache.org/repos/asf/apr/apr/trunk/strings/apr_snprintf.c */ +/* Additional modifications to work outside Apache for use with Ghostscript */ + +#include "stdio_.h" +#include "stdint_.h" +#include "string_.h" +#include <stdarg.h> +#include "math_.h" +#include <ctype.h> -#include "apr.h" -#include "apr_private.h" +#define APR_HAVE_IPV6 0 +#define APR_HAS_THREADS 0 + +#define FOR_GS 1 + +#define apr_isalpha(c) isalpha(c) +#define apr_islower(c) islower(c) +#define apr_isdigit(c) isdigit(c) -#include "apr_lib.h" -#include "apr_strings.h" -#include "apr_network_io.h" -#include "apr_portable.h" -#include "apr_errno.h" -#include <math.h> -#if APR_HAVE_CTYPE_H -#include <ctype.h> -#endif -#if APR_HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#if APR_HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#if APR_HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#if APR_HAVE_LIMITS_H -#include <limits.h> -#endif -#if APR_HAVE_STRING_H -#include <string.h> -#endif + +typedef uint32_t apr_uint32_t; +typedef int32_t apr_int32_t; +typedef uint64_t apr_uint64_t; +typedef int64_t apr_int64_t; +typedef size_t apr_size_t; +typedef int64_t apr_off_t; + + +typedef struct apr_vformatter_buff_t apr_vformatter_buff_t; + +/** + * Structure used by the variable-formatter routines. + */ +struct apr_vformatter_buff_t { + /** The current position */ + char *curpos; + /** The end position of the format string */ + char *endpos; +}; typedef enum { NO = 0, YES = 1 @@ -54,7 +65,29 @@ typedef enum { #endif #define NUL '\0' -#define S_NULL "(null)" +#define APR_INT64_C(x) ((int64_t)x) +#define APR_UINT64_C(x) ((uint64_t)x) + +#define APR_INT16_MIN (-0x7fff - 1) +#define APR_INT16_MAX (0x7fff) +#define APR_UINT16_MAX (0xffff) +#define APR_INT32_MIN (-0x7fffffff - 1) +#define APR_INT32_MAX 0x7fffffff +#define APR_UINT32_MAX (0xffffffffU) +#define APR_INT64_MIN (APR_INT64_C(-0x7fffffffffffffff) - 1) +#define APR_INT64_MAX APR_INT64_C(0x7fffffffffffffff) +#define APR_UINT64_MAX APR_UINT64_C(0xffffffffffffffff) +#define APR_SIZE_MAX (~((apr_size_t)0)) + +#define APR_SIZEOF_VOIDP ARCH_SIZEOF_PTR + +#define APR_INT64_T_FMT PRId64 +#define APR_UINT64_T_FMT PRIu64 +#define APR_UINT64_T_HEX_FMT PRIx64 +#define APR_OFF_T_FMT PRId64 + +static const char null_string[] = "(null)"; +#define S_NULL ((char *)null_string) #define S_NULL_LEN 6 #define FLOAT_DIGITS 6 @@ -68,8 +101,8 @@ typedef enum { #define NUM_BUF_SIZE 512 /* - * cvt.c - IEEE floating point formatting routines for FreeBSD - * from GNU libc-4.6.27. Modified to be thread safe. + * cvt - IEEE floating point formatting routines. + * Derived from UNIX V7, Copyright(C) Caldera International Inc. */ /* @@ -178,6 +211,8 @@ static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform) register char *p1, *p2; register int i; char buf1[NDIG]; + int nd = ndigit; + double magn = number < 0 ? -number : number; p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1); p2 = buf; @@ -185,11 +220,18 @@ static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform) *p2++ = '-'; for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) ndigit--; +#if !FOR_GS if ((decpt >= 0 && decpt - ndigit > 4) || (decpt < 0 && decpt < -3)) { /* use E-style */ +#else + if (magn != 0 && ((magn < (double)9.9999989999999991e-05) + || (magn >= pow(10, nd)))) { /* use E-style */ +#endif decpt--; *p2++ = *p1++; - *p2++ = '.'; + + if (ndigit >= 2) + *p2++ = '.'; for (i = 1; i < ndigit; i++) *p2++ = *p1++; *p2++ = 'e'; @@ -201,14 +243,19 @@ static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform) *p2++ = '+'; if (decpt / 100 > 0) *p2++ = decpt / 100 + '0'; + +#if !FOR_GS /* We want the extra zero here so we get, for example, 2e+08 instead of 2e+8 */ if (decpt / 10 > 0) +#endif *p2++ = (decpt % 100) / 10 + '0'; *p2++ = decpt % 10 + '0'; } else { if (decpt <= 0) { - if (*p1 != '0') + if (*p1 != '0') { + *p2++ = '0'; *p2++ = '.'; + } while (decpt < 0) { decpt++; *p2++ = '0'; @@ -421,6 +468,7 @@ static char *conv_10_quad(apr_int64_t num, register int is_unsigned, return (p); } +#if !FOR_GS static char *conv_in_addr(struct in_addr *ia, char *buf_end, apr_size_t *len) { unsigned addr = ntohl(ia->s_addr); @@ -440,7 +488,6 @@ static char *conv_in_addr(struct in_addr *ia, char *buf_end, apr_size_t *len) return (p); } - /* Must be passed a buffer of size NUM_BUF_SIZE where buf_end points * to 1 byte past the end of the buffer. */ static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *len) @@ -479,6 +526,7 @@ static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *le *len = buf_end - p; return (p); } +#endif @@ -679,7 +727,7 @@ static char *conv_os_thread_t_hex(apr_os_thread_t *tid, char *buf_end, apr_size_ /* * Do format conversion placing the output in buffer */ -APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), +static int apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap) { register char *sp; @@ -689,7 +737,7 @@ APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), register char *s = NULL; char *q; - apr_size_t s_len; + apr_size_t s_len = 0; register apr_size_t min_width = 0; apr_size_t precision = 0; @@ -703,7 +751,7 @@ APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), apr_int64_t i_quad = 0; apr_uint64_t ui_quad; apr_int32_t i_num = 0; - apr_uint32_t ui_num; + apr_uint32_t ui_num = 0; char num_buf[NUM_BUF_SIZE]; char char_buf[2]; /* for printing %% and %<unknown> */ @@ -809,10 +857,27 @@ APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), adjust_precision = adjust_width = NO; /* - * Modifier check. Note that if APR_INT64_T_FMT is "d", - * the first if condition is never true. + * Modifier check. In same cases, APR_OFF_T_FMT can be + * "lld" and APR_INT64_T_FMT can be "ld" (that is, off_t is + * "larger" than int64). Check that case 1st. + * Note that if APR_OFF_T_FMT is "d", + * the first if condition is never true. If APR_INT64_T_FMT + * is "d' then the second if condition is never true. */ - if ((sizeof(APR_INT64_T_FMT) == 4 && + if ((sizeof(APR_OFF_T_FMT) > sizeof(APR_INT64_T_FMT)) && + ((sizeof(APR_OFF_T_FMT) == 4 && + fmt[0] == APR_OFF_T_FMT[0] && + fmt[1] == APR_OFF_T_FMT[1]) || + (sizeof(APR_OFF_T_FMT) == 3 && + fmt[0] == APR_OFF_T_FMT[0]) || + (sizeof(APR_OFF_T_FMT) > 4 && + strncmp(fmt, APR_OFF_T_FMT, + sizeof(APR_OFF_T_FMT) - 2) == 0))) { + /* Need to account for trailing 'd' and null in sizeof() */ + var_type = IS_QUAD; + fmt += (sizeof(APR_OFF_T_FMT) - 2); + } + else if ((sizeof(APR_INT64_T_FMT) == 4 && fmt[0] == APR_INT64_T_FMT[0] && fmt[1] == APR_INT64_T_FMT[1]) || (sizeof(APR_INT64_T_FMT) == 3 && @@ -941,7 +1006,7 @@ APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), &num_buf[NUM_BUF_SIZE], &s_len); } FIX_PRECISION(adjust_precision, precision, s, s_len); - if (alternate_form && i_num != 0) { + if (alternate_form && ui_num != 0) { *--s = *fmt; /* 'x' or 'X' */ *--s = '0'; s_len += 2; @@ -1111,13 +1176,14 @@ APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), } #endif else { - s = "%p"; + s = (char *)"%p"; s_len = 2; prefix_char = NUL; } pad_char = ' '; break; +#if !FOR_GS /* print an apr_sockaddr_t as a.b.c.d:port */ case 'I': { @@ -1173,6 +1239,7 @@ APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), pad_char = ' '; } break; +#endif case 'T': #if APR_HAS_THREADS @@ -1224,6 +1291,7 @@ APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), #endif break; +#if !FOR_GS case 'B': case 'F': case 'S': @@ -1249,13 +1317,34 @@ APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), pad_char = ' '; } break; +#endif case NUL: - /* if %p ends the string, oh well ignore it */ - continue; + /* if %p ends the string, treat it as pointer */ +#if APR_SIZEOF_VOIDP == 8 + if (sizeof(void *) <= sizeof(apr_uint64_t)) { + ui_quad = (apr_uint64_t) va_arg(ap, void *); + s = conv_p2_quad(ui_quad, 4, 'x', + &num_buf[NUM_BUF_SIZE], &s_len); + } +#else + if (sizeof(void *) <= sizeof(apr_uint32_t)) { + ui_num = (apr_uint32_t) va_arg(ap, void *); + s = conv_p2(ui_num, 4, 'x', + &num_buf[NUM_BUF_SIZE], &s_len); + } +#endif + else { + s = (char *)"%p"; + s_len = 2; + prefix_char = NUL; + } + pad_char = ' '; + fmt--; + break; default: - s = "bogus %p"; + s = (char *)"bogus %p"; s_len = 8; prefix_char = NUL; (void)va_arg(ap, void *); /* skip the bogus argument on the stack */ @@ -1334,8 +1423,7 @@ static int snprintf_flush(apr_vformatter_buff_t *vbuff) return -1; } - -APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, +int gs_snprintf(char *buf, int32_t len, const char *format, ...) { int cc; @@ -1366,8 +1454,26 @@ APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, return (cc == -1) ? (int)len - 1 : cc; } +int gs_sprintf(char *buf, const char *format, ...) +{ + int cc; + va_list ap; + apr_vformatter_buff_t vbuff; -APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, + /* save one byte for nul terminator */ + vbuff.curpos = buf; + vbuff.endpos = buf + NUM_BUF_SIZE - 1; + + va_start(ap, format); + cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); + va_end(ap); + *vbuff.curpos = '\0'; + + return cc; +} + + +int gs_vsnprintf(char *buf, int32_t len, const char *format, va_list ap) { int cc; @@ -1386,5 +1492,21 @@ APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, if (len != 0) { *vbuff.curpos = '\0'; } + return (cc == -1) ? (int)len - 1 : cc; } + +int gs_vsprintf(char *buf, const char *format, va_list ap) +{ + int cc; + apr_vformatter_buff_t vbuff; + + /* save one byte for nul terminator */ + vbuff.curpos = buf; + vbuff.endpos = buf + NUM_BUF_SIZE - 1; + + cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); + *vbuff.curpos = '\0'; + + return cc; +} |