summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--configure.ac70
-rw-r--r--openbsd-compat/Makefile.in4
-rw-r--r--openbsd-compat/bsd-asprintf.c95
-rw-r--r--openbsd-compat/bsd-snprintf.c610
-rw-r--r--openbsd-compat/openbsd-compat.h10
6 files changed, 562 insertions, 236 deletions
diff --git a/ChangeLog b/ChangeLog
index 1164b770d..c869db7d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,11 @@
120051122 120051122
2 - (djm) [configure.ac openbsd-compat/Makefile.in openbsd-compat/bsd-asprintf.c
3 openbsd-compat/bsd-snprintf.c openbsd-compat/openbsd-compat.h] Add an
4 asprintf() implementation, after syncing our {v,}snprintf() implementation
5 with some extra fixes from Samba's version. With help and debugging from
6 dtucker and tim; ok dtucker@
7
820051122
2 - (dtucker) OpenBSD CVS Sync 9 - (dtucker) OpenBSD CVS Sync
3 - deraadt@cvs.openbsd.org 2005/11/12 18:37:59 10 - deraadt@cvs.openbsd.org 2005/11/12 18:37:59
4 [ssh-add.c] 11 [ssh-add.c]
@@ -3333,4 +3340,4 @@
3333 - (djm) Trim deprecated options from INSTALL. Mention UsePAM 3340 - (djm) Trim deprecated options from INSTALL. Mention UsePAM
3334 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu 3341 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
3335 3342
3336$Id: ChangeLog,v 1.4002 2005/11/22 08:55:13 dtucker Exp $ 3343$Id: ChangeLog,v 1.4003 2005/11/24 08:58:19 djm Exp $
diff --git a/configure.ac b/configure.ac
index 2885a69fb..396552888 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
1# $Id: configure.ac,v 1.307 2005/11/12 07:42:37 dtucker Exp $ 1# $Id: configure.ac,v 1.308 2005/11/24 08:58:20 djm Exp $
2# 2#
3# Copyright (c) 1999-2004 Damien Miller 3# Copyright (c) 1999-2004 Damien Miller
4# 4#
@@ -426,6 +426,7 @@ mips-sony-bsd|mips-sony-newsos4)
426 ;; 426 ;;
427# UnixWare 1.x, UnixWare 2.x, and others based on code from Univel. 427# UnixWare 1.x, UnixWare 2.x, and others based on code from Univel.
428*-*-sysv4.2*) 428*-*-sysv4.2*)
429 CFLAGS="$CFLAGS -Dva_list=_VA_LIST"
429 AC_DEFINE(USE_PIPES) 430 AC_DEFINE(USE_PIPES)
430 AC_DEFINE(SETEUID_BREAKS_SETUID) 431 AC_DEFINE(SETEUID_BREAKS_SETUID)
431 AC_DEFINE(BROKEN_SETREUID) 432 AC_DEFINE(BROKEN_SETREUID)
@@ -1106,6 +1107,7 @@ AC_ARG_WITH(audit,
1106dnl Checks for library functions. Please keep in alphabetical order 1107dnl Checks for library functions. Please keep in alphabetical order
1107AC_CHECK_FUNCS( \ 1108AC_CHECK_FUNCS( \
1108 arc4random \ 1109 arc4random \
1110 asprintf \
1109 b64_ntop \ 1111 b64_ntop \
1110 __b64_ntop \ 1112 __b64_ntop \
1111 b64_pton \ 1113 b64_pton \
@@ -1181,6 +1183,7 @@ AC_CHECK_FUNCS( \
1181 truncate \ 1183 truncate \
1182 unsetenv \ 1184 unsetenv \
1183 updwtmpx \ 1185 updwtmpx \
1186 vasprintf \
1184 vhangup \ 1187 vhangup \
1185 vsnprintf \ 1188 vsnprintf \
1186 waitpid \ 1189 waitpid \
@@ -1299,6 +1302,40 @@ int main(void){char b[5];snprintf(b,5,"123456789");exit(b[4]!='\0');}
1299 ) 1302 )
1300fi 1303fi
1301 1304
1305# If we don't have a working asprintf, then we strongly depend on vsnprintf
1306# returning the right thing on overflow: the number of characters it tried to
1307# create (as per SUSv3)
1308if test "x$ac_cv_func_asprintf" != "xyes" && \
1309 test "x$ac_cv_func_vsnprintf" = "xyes" ; then
1310 AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow])
1311 AC_RUN_IFELSE(
1312 [AC_LANG_SOURCE([[
1313#include <sys/types.h>
1314#include <stdio.h>
1315#include <stdarg.h>
1316
1317int x_snprintf(char *str,size_t count,const char *fmt,...)
1318{
1319 size_t ret; va_list ap;
1320 va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap);
1321 return ret;
1322}
1323int main(void)
1324{
1325 char x[1];
1326 exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1);
1327} ]])],
1328 [AC_MSG_RESULT(yes)],
1329 [
1330 AC_MSG_RESULT(no)
1331 AC_DEFINE(BROKEN_SNPRINTF, 1,
1332 [Define if your snprintf is busted])
1333 AC_MSG_WARN([****** Your vsnprintf() function is broken, complain to your vendor])
1334 ],
1335 [ AC_MSG_WARN([cross compiling: Assuming working vsnprintf()]) ]
1336 )
1337fi
1338
1302# Check for missing getpeereid (or equiv) support 1339# Check for missing getpeereid (or equiv) support
1303NO_PEERCHECK="" 1340NO_PEERCHECK=""
1304if test "x$ac_cv_func_getpeereid" != "xyes" ; then 1341if test "x$ac_cv_func_getpeereid" != "xyes" ; then
@@ -1978,7 +2015,10 @@ if test ! -z "$SONY" ; then
1978 LIBS="$LIBS -liberty"; 2015 LIBS="$LIBS -liberty";
1979fi 2016fi
1980 2017
1981# Checks for data types 2018# Check for long long datatypes
2019AC_CHECK_TYPES([long long, unsigned long long, long double])
2020
2021# Check datatype sizes
1982AC_CHECK_SIZEOF(char, 1) 2022AC_CHECK_SIZEOF(char, 1)
1983AC_CHECK_SIZEOF(short int, 2) 2023AC_CHECK_SIZEOF(short int, 2)
1984AC_CHECK_SIZEOF(int, 4) 2024AC_CHECK_SIZEOF(int, 4)
@@ -2669,6 +2709,32 @@ if test "x$ac_cv_cc_implements___func__" = "xyes" ; then
2669 AC_DEFINE(HAVE___func__, 1, [Define if compiler implements __func__]) 2709 AC_DEFINE(HAVE___func__, 1, [Define if compiler implements __func__])
2670fi 2710fi
2671 2711
2712AC_CACHE_CHECK([whether va_copy exists], ac_cv_have_va_copy, [
2713 AC_TRY_LINK(
2714 [#include <stdarg.h>
2715 va_list x,y;],
2716 [va_copy(x,y);],
2717 [ ac_cv_have_va_copy="yes" ],
2718 [ ac_cv_have_va_copy="no" ]
2719 )
2720])
2721if test "x$ac_cv_have_va_copy" = "xyes" ; then
2722 AC_DEFINE(HAVE_VA_COPY, 1, [Define if va_copy exists])
2723fi
2724
2725AC_CACHE_CHECK([whether __va_copy exists], ac_cv_have___va_copy, [
2726 AC_TRY_LINK(
2727 [#include <stdarg.h>
2728 va_list x,y;],
2729 [__va_copy(x,y);],
2730 [ ac_cv_have___va_copy="yes" ],
2731 [ ac_cv_have___va_copy="no" ]
2732 )
2733])
2734if test "x$ac_cv_have___va_copy" = "xyes" ; then
2735 AC_DEFINE(HAVE___VA_COPY, 1, [Define if __va_copy exists])
2736fi
2737
2672AC_CACHE_CHECK([whether getopt has optreset support], 2738AC_CACHE_CHECK([whether getopt has optreset support],
2673 ac_cv_have_getopt_optreset, [ 2739 ac_cv_have_getopt_optreset, [
2674 AC_TRY_LINK( 2740 AC_TRY_LINK(
diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in
index 6f5ee2845..89ac6cdaf 100644
--- a/openbsd-compat/Makefile.in
+++ b/openbsd-compat/Makefile.in
@@ -1,4 +1,4 @@
1# $Id: Makefile.in,v 1.35 2005/08/26 20:15:20 tim Exp $ 1# $Id: Makefile.in,v 1.36 2005/11/24 08:58:21 djm Exp $
2 2
3sysconfdir=@sysconfdir@ 3sysconfdir=@sysconfdir@
4piddir=@piddir@ 4piddir=@piddir@
@@ -18,7 +18,7 @@ LDFLAGS=-L. @LDFLAGS@
18 18
19OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o 19OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o
20 20
21COMPAT=bsd-arc4random.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-snprintf.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o 21COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-snprintf.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
22 22
23PORTS=port-irix.o port-aix.o port-uw.o 23PORTS=port-irix.o port-aix.o port-uw.o
24 24
diff --git a/openbsd-compat/bsd-asprintf.c b/openbsd-compat/bsd-asprintf.c
new file mode 100644
index 000000000..5ca01f80f
--- /dev/null
+++ b/openbsd-compat/bsd-asprintf.c
@@ -0,0 +1,95 @@
1/*
2 * Copyright (c) 2004 Darren Tucker.
3 *
4 * Based originally on asprintf.c from OpenBSD:
5 * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "includes.h"
21
22#ifndef HAVE_VASPRINTF
23
24#ifndef VA_COPY
25# ifdef HAVE_VA_COPY
26# define VA_COPY(dest, src) va_copy(dest, src)
27# else
28# ifdef HAVE___VA_COPY
29# define VA_COPY(dest, src) __va_copy(dest, src)
30# else
31# define VA_COPY(dest, src) (dest) = (src)
32# endif
33# endif
34#endif
35
36#define INIT_SZ 128
37
38int vasprintf(char **str, const char *fmt, va_list ap)
39{
40 int ret = -1;
41 va_list ap2;
42 char *string, *newstr;
43 size_t len;
44
45 VA_COPY(ap2, ap);
46 if ((string = malloc(INIT_SZ)) == NULL)
47 goto fail;
48
49 ret = vsnprintf(string, INIT_SZ, fmt, ap2);
50 if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
51 *str = string;
52 } else if (ret == INT_MAX) { /* shouldn't happen */
53 goto fail;
54 } else { /* bigger than initial, realloc allowing for nul */
55 len = (size_t)ret + 1;
56 if ((newstr = realloc(string, len)) == NULL) {
57 free(string);
58 goto fail;
59 } else {
60 va_end(ap2);
61 VA_COPY(ap2, ap);
62 ret = vsnprintf(newstr, len, fmt, ap2);
63 if (ret >= 0 && (size_t)ret < len) {
64 *str = newstr;
65 } else { /* failed with realloc'ed string, give up */
66 free(newstr);
67 goto fail;
68 }
69 }
70 }
71 va_end(ap2);
72 return (ret);
73
74fail:
75 *str = NULL;
76 errno = ENOMEM;
77 va_end(ap2);
78 return (-1);
79}
80#endif
81
82#ifndef HAVE_ASPRINTF
83int asprintf(char **str, const char *fmt, ...)
84{
85 va_list ap;
86 int ret;
87
88 *str = NULL;
89 va_start(ap, fmt);
90 ret = vasprintf(str, fmt, ap);
91 va_end(ap);
92
93 return ret;
94}
95#endif
diff --git a/openbsd-compat/bsd-snprintf.c b/openbsd-compat/bsd-snprintf.c
index b5a7ef7a0..ca275abdf 100644
--- a/openbsd-compat/bsd-snprintf.c
+++ b/openbsd-compat/bsd-snprintf.c
@@ -45,45 +45,82 @@
45 * missing. Some systems only have snprintf() but not vsnprintf(), so 45 * missing. Some systems only have snprintf() but not vsnprintf(), so
46 * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. 46 * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
47 * 47 *
48 * Ben Lindstrom <mouring@eviladmin.org> 09/27/00 for OpenSSH 48 * Andrew Tridgell (tridge@samba.org) Oct 1998
49 * Welcome to the world of %lld and %qd support. With other 49 * fixed handling of %.0f
50 * long long support. This is needed for sftp-server to work 50 * added test for HAVE_LONG_DOUBLE
51 * right.
52 * 51 *
53 * Ben Lindstrom <mouring@eviladmin.org> 02/12/01 for OpenSSH 52 * tridge@samba.org, idra@samba.org, April 2001
54 * Removed all hint of VARARGS stuff and banished it to the void, 53 * got rid of fcvt code (twas buggy and made testing harder)
55 * and did a bit of KNF style work to make things a bit more 54 * added C99 semantics
56 * acceptable. Consider stealing from mutt or enlightenment. 55 *
56 * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0
57 * actually print args for %g and %e
58 *
59 * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0
60 * Since includes.h isn't included here, VA_COPY has to be defined here. I don't
61 * see any include file that is guaranteed to be here, so I'm defining it
62 * locally. Fixes AIX and Solaris builds.
63 *
64 * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13
65 * put the ifdef for HAVE_VA_COPY in one place rather than in lots of
66 * functions
67 *
68 * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4
69 * Fix usage of va_list passed as an arg. Use __va_copy before using it
70 * when it exists.
71 *
72 * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14
73 * Fix incorrect zpadlen handling in fmtfp.
74 * Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
75 * few mods to make it easier to compile the tests.
76 * addedd the "Ollie" test to the floating point ones.
77 *
78 * Martin Pool (mbp@samba.org) April 2003
79 * Remove NO_CONFIG_H so that the test case can be built within a source
80 * tree with less trouble.
81 * Remove unnecessary SAFE_FREE() definition.
82 *
83 * Martin Pool (mbp@samba.org) May 2003
84 * Put in a prototype for dummy_snprintf() to quiet compiler warnings.
85 *
86 * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
87 * if the C library has some snprintf functions already.
57 **************************************************************/ 88 **************************************************************/
58 89
59#include "includes.h" 90#include "includes.h"
60 91
61RCSID("$Id: bsd-snprintf.c,v 1.9 2004/09/23 11:35:09 dtucker Exp $"); 92RCSID("$Id: bsd-snprintf.c,v 1.10 2005/11/24 08:58:21 djm Exp $");
62 93
63#if defined(BROKEN_SNPRINTF) /* For those with broken snprintf() */ 94#if defined(BROKEN_SNPRINTF) /* For those with broken snprintf() */
64# undef HAVE_SNPRINTF 95# undef HAVE_SNPRINTF
65# undef HAVE_VSNPRINTF 96# undef HAVE_VSNPRINTF
66#endif 97#endif
67 98
68#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) 99#ifndef VA_COPY
69 100# ifdef HAVE_VA_COPY
70static void 101# define VA_COPY(dest, src) va_copy(dest, src)
71dopr(char *buffer, size_t maxlen, const char *format, va_list args); 102# else
72 103# ifdef HAVE___VA_COPY
73static void 104# define VA_COPY(dest, src) __va_copy(dest, src)
74fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, 105# else
75 int min, int max); 106# define VA_COPY(dest, src) (dest) = (src)
107# endif
108# endif
109#endif
76 110
77static void 111#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
78fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
79 int min, int max, int flags);
80 112
81static void 113#ifdef HAVE_LONG_DOUBLE
82fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, 114# define LDOUBLE long double
83 int min, int max, int flags); 115#else
116# define LDOUBLE double
117#endif
84 118
85static void 119#ifdef HAVE_LONG_LONG
86dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); 120# define LLONG long long
121#else
122# define LLONG long
123#endif
87 124
88/* 125/*
89 * dopr(): poor man's version of doprintf 126 * dopr(): poor man's version of doprintf
@@ -109,28 +146,49 @@ dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
109#define DP_F_UNSIGNED (1 << 6) 146#define DP_F_UNSIGNED (1 << 6)
110 147
111/* Conversion Flags */ 148/* Conversion Flags */
112#define DP_C_SHORT 1 149#define DP_C_SHORT 1
113#define DP_C_LONG 2 150#define DP_C_LONG 2
114#define DP_C_LDOUBLE 3 151#define DP_C_LDOUBLE 3
115#define DP_C_LONG_LONG 4 152#define DP_C_LLONG 4
116 153
117#define char_to_int(p) (p - '0') 154#define char_to_int(p) ((p)- '0')
118#define abs_val(p) (p < 0 ? -p : p) 155#ifndef MAX
119 156# define MAX(p,q) (((p) >= (q)) ? (p) : (q))
157#endif
120 158
121static void 159static size_t dopr(char *buffer, size_t maxlen, const char *format,
122dopr(char *buffer, size_t maxlen, const char *format, va_list args) 160 va_list args_in);
161static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
162 char *value, int flags, int min, int max);
163static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
164 long value, int base, int min, int max, int flags);
165static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
166 LDOUBLE fvalue, int min, int max, int flags);
167static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
168
169static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
123{ 170{
124 char *strvalue, ch; 171 char ch;
125 long value; 172 LLONG value;
126 long double fvalue; 173 LDOUBLE fvalue;
127 int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0; 174 char *strvalue;
128 size_t currlen = 0; 175 int min;
129 176 int max;
177 int state;
178 int flags;
179 int cflags;
180 size_t currlen;
181 va_list args;
182
183 VA_COPY(args, args_in);
184
185 state = DP_S_DEFAULT;
186 currlen = flags = cflags = min = 0;
187 max = -1;
130 ch = *format++; 188 ch = *format++;
131 189
132 while (state != DP_S_DONE) { 190 while (state != DP_S_DONE) {
133 if ((ch == '\0') || (currlen >= maxlen)) 191 if (ch == '\0')
134 state = DP_S_DONE; 192 state = DP_S_DONE;
135 193
136 switch(state) { 194 switch(state) {
@@ -138,7 +196,7 @@ dopr(char *buffer, size_t maxlen, const char *format, va_list args)
138 if (ch == '%') 196 if (ch == '%')
139 state = DP_S_FLAGS; 197 state = DP_S_FLAGS;
140 else 198 else
141 dopr_outch(buffer, &currlen, maxlen, ch); 199 dopr_outch (buffer, &currlen, maxlen, ch);
142 ch = *format++; 200 ch = *format++;
143 break; 201 break;
144 case DP_S_FLAGS: 202 case DP_S_FLAGS:
@@ -170,34 +228,37 @@ dopr(char *buffer, size_t maxlen, const char *format, va_list args)
170 break; 228 break;
171 case DP_S_MIN: 229 case DP_S_MIN:
172 if (isdigit((unsigned char)ch)) { 230 if (isdigit((unsigned char)ch)) {
173 min = 10 * min + char_to_int (ch); 231 min = 10*min + char_to_int (ch);
174 ch = *format++; 232 ch = *format++;
175 } else if (ch == '*') { 233 } else if (ch == '*') {
176 min = va_arg (args, int); 234 min = va_arg (args, int);
177 ch = *format++; 235 ch = *format++;
178 state = DP_S_DOT; 236 state = DP_S_DOT;
179 } else 237 } else {
180 state = DP_S_DOT; 238 state = DP_S_DOT;
239 }
181 break; 240 break;
182 case DP_S_DOT: 241 case DP_S_DOT:
183 if (ch == '.') { 242 if (ch == '.') {
184 state = DP_S_MAX; 243 state = DP_S_MAX;
185 ch = *format++; 244 ch = *format++;
186 } else 245 } else {
187 state = DP_S_MOD; 246 state = DP_S_MOD;
247 }
188 break; 248 break;
189 case DP_S_MAX: 249 case DP_S_MAX:
190 if (isdigit((unsigned char)ch)) { 250 if (isdigit((unsigned char)ch)) {
191 if (max < 0) 251 if (max < 0)
192 max = 0; 252 max = 0;
193 max = 10 * max + char_to_int(ch); 253 max = 10*max + char_to_int (ch);
194 ch = *format++; 254 ch = *format++;
195 } else if (ch == '*') { 255 } else if (ch == '*') {
196 max = va_arg (args, int); 256 max = va_arg (args, int);
197 ch = *format++; 257 ch = *format++;
198 state = DP_S_MOD; 258 state = DP_S_MOD;
199 } else 259 } else {
200 state = DP_S_MOD; 260 state = DP_S_MOD;
261 }
201 break; 262 break;
202 case DP_S_MOD: 263 case DP_S_MOD:
203 switch (ch) { 264 switch (ch) {
@@ -208,15 +269,11 @@ dopr(char *buffer, size_t maxlen, const char *format, va_list args)
208 case 'l': 269 case 'l':
209 cflags = DP_C_LONG; 270 cflags = DP_C_LONG;
210 ch = *format++; 271 ch = *format++;
211 if (ch == 'l') { 272 if (ch == 'l') { /* It's a long long */
212 cflags = DP_C_LONG_LONG; 273 cflags = DP_C_LLONG;
213 ch = *format++; 274 ch = *format++;
214 } 275 }
215 break; 276 break;
216 case 'q':
217 cflags = DP_C_LONG_LONG;
218 ch = *format++;
219 break;
220 case 'L': 277 case 'L':
221 cflags = DP_C_LDOUBLE; 278 cflags = DP_C_LDOUBLE;
222 ch = *format++; 279 ch = *format++;
@@ -231,37 +288,37 @@ dopr(char *buffer, size_t maxlen, const char *format, va_list args)
231 case 'd': 288 case 'd':
232 case 'i': 289 case 'i':
233 if (cflags == DP_C_SHORT) 290 if (cflags == DP_C_SHORT)
234 value = va_arg(args, int); 291 value = va_arg (args, int);
235 else if (cflags == DP_C_LONG) 292 else if (cflags == DP_C_LONG)
236 value = va_arg(args, long int); 293 value = va_arg (args, long int);
237 else if (cflags == DP_C_LONG_LONG) 294 else if (cflags == DP_C_LLONG)
238 value = va_arg (args, long long); 295 value = va_arg (args, LLONG);
239 else 296 else
240 value = va_arg (args, int); 297 value = va_arg (args, int);
241 fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags); 298 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
242 break; 299 break;
243 case 'o': 300 case 'o':
244 flags |= DP_F_UNSIGNED; 301 flags |= DP_F_UNSIGNED;
245 if (cflags == DP_C_SHORT) 302 if (cflags == DP_C_SHORT)
246 value = va_arg(args, unsigned int); 303 value = va_arg (args, unsigned int);
247 else if (cflags == DP_C_LONG) 304 else if (cflags == DP_C_LONG)
248 value = va_arg(args, unsigned long int); 305 value = (long)va_arg (args, unsigned long int);
249 else if (cflags == DP_C_LONG_LONG) 306 else if (cflags == DP_C_LLONG)
250 value = va_arg(args, unsigned long long); 307 value = (long)va_arg (args, unsigned LLONG);
251 else 308 else
252 value = va_arg(args, unsigned int); 309 value = (long)va_arg (args, unsigned int);
253 fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags); 310 fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
254 break; 311 break;
255 case 'u': 312 case 'u':
256 flags |= DP_F_UNSIGNED; 313 flags |= DP_F_UNSIGNED;
257 if (cflags == DP_C_SHORT) 314 if (cflags == DP_C_SHORT)
258 value = va_arg(args, unsigned int); 315 value = va_arg (args, unsigned int);
259 else if (cflags == DP_C_LONG) 316 else if (cflags == DP_C_LONG)
260 value = va_arg(args, unsigned long int); 317 value = (long)va_arg (args, unsigned long int);
261 else if (cflags == DP_C_LONG_LONG) 318 else if (cflags == DP_C_LLONG)
262 value = va_arg(args, unsigned long long); 319 value = (LLONG)va_arg (args, unsigned LLONG);
263 else 320 else
264 value = va_arg(args, unsigned int); 321 value = (long)va_arg (args, unsigned int);
265 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); 322 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
266 break; 323 break;
267 case 'X': 324 case 'X':
@@ -269,79 +326,86 @@ dopr(char *buffer, size_t maxlen, const char *format, va_list args)
269 case 'x': 326 case 'x':
270 flags |= DP_F_UNSIGNED; 327 flags |= DP_F_UNSIGNED;
271 if (cflags == DP_C_SHORT) 328 if (cflags == DP_C_SHORT)
272 value = va_arg(args, unsigned int); 329 value = va_arg (args, unsigned int);
273 else if (cflags == DP_C_LONG) 330 else if (cflags == DP_C_LONG)
274 value = va_arg(args, unsigned long int); 331 value = (long)va_arg (args, unsigned long int);
275 else if (cflags == DP_C_LONG_LONG) 332 else if (cflags == DP_C_LLONG)
276 value = va_arg(args, unsigned long long); 333 value = (LLONG)va_arg (args, unsigned LLONG);
277 else 334 else
278 value = va_arg(args, unsigned int); 335 value = (long)va_arg (args, unsigned int);
279 fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags); 336 fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
280 break; 337 break;
281 case 'f': 338 case 'f':
282 if (cflags == DP_C_LDOUBLE) 339 if (cflags == DP_C_LDOUBLE)
283 fvalue = va_arg(args, long double); 340 fvalue = va_arg (args, LDOUBLE);
284 else 341 else
285 fvalue = va_arg(args, double); 342 fvalue = va_arg (args, double);
286 /* um, floating point? */ 343 /* um, floating point? */
287 fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags); 344 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
288 break; 345 break;
289 case 'E': 346 case 'E':
290 flags |= DP_F_UP; 347 flags |= DP_F_UP;
291 case 'e': 348 case 'e':
292 if (cflags == DP_C_LDOUBLE) 349 if (cflags == DP_C_LDOUBLE)
293 fvalue = va_arg(args, long double); 350 fvalue = va_arg (args, LDOUBLE);
294 else 351 else
295 fvalue = va_arg(args, double); 352 fvalue = va_arg (args, double);
353 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
296 break; 354 break;
297 case 'G': 355 case 'G':
298 flags |= DP_F_UP; 356 flags |= DP_F_UP;
299 case 'g': 357 case 'g':
300 if (cflags == DP_C_LDOUBLE) 358 if (cflags == DP_C_LDOUBLE)
301 fvalue = va_arg(args, long double); 359 fvalue = va_arg (args, LDOUBLE);
302 else 360 else
303 fvalue = va_arg(args, double); 361 fvalue = va_arg (args, double);
362 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
304 break; 363 break;
305 case 'c': 364 case 'c':
306 dopr_outch(buffer, &currlen, maxlen, va_arg(args, int)); 365 dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
307 break; 366 break;
308 case 's': 367 case 's':
309 strvalue = va_arg(args, char *); 368 strvalue = va_arg (args, char *);
310 if (max < 0) 369 if (!strvalue) strvalue = "(NULL)";
311 max = maxlen; /* ie, no max */ 370 if (max == -1) {
312 fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max); 371 max = strlen(strvalue);
372 }
373 if (min > 0 && max >= 0 && min > max) max = min;
374 fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
313 break; 375 break;
314 case 'p': 376 case 'p':
315 strvalue = va_arg(args, void *); 377 strvalue = va_arg (args, void *);
316 fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); 378 fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
317 break; 379 break;
318 case 'n': 380 case 'n':
319 if (cflags == DP_C_SHORT) { 381 if (cflags == DP_C_SHORT) {
320 short int *num; 382 short int *num;
321 num = va_arg(args, short int *); 383 num = va_arg (args, short int *);
322 *num = currlen; 384 *num = currlen;
323 } else if (cflags == DP_C_LONG) { 385 } else if (cflags == DP_C_LONG) {
324 long int *num; 386 long int *num;
325 num = va_arg(args, long int *); 387 num = va_arg (args, long int *);
326 *num = currlen; 388 *num = (long int)currlen;
327 } else if (cflags == DP_C_LONG_LONG) { 389 } else if (cflags == DP_C_LLONG) {
328 long long *num; 390 LLONG *num;
329 num = va_arg(args, long long *); 391 num = va_arg (args, LLONG *);
330 *num = currlen; 392 *num = (LLONG)currlen;
331 } else { 393 } else {
332 int *num; 394 int *num;
333 num = va_arg(args, int *); 395 num = va_arg (args, int *);
334 *num = currlen; 396 *num = currlen;
335 } 397 }
336 break; 398 break;
337 case '%': 399 case '%':
338 dopr_outch(buffer, &currlen, maxlen, ch); 400 dopr_outch (buffer, &currlen, maxlen, ch);
339 break; 401 break;
340 case 'w': /* not supported yet, treat as next char */ 402 case 'w':
403 /* not supported yet, treat as next char */
341 ch = *format++; 404 ch = *format++;
342 break; 405 break;
343 default: /* Unknown, skip */ 406 default:
344 break; 407 /* Unknown, skip */
408 break;
345 } 409 }
346 ch = *format++; 410 ch = *format++;
347 state = DP_S_DEFAULT; 411 state = DP_S_DEFAULT;
@@ -350,24 +414,33 @@ dopr(char *buffer, size_t maxlen, const char *format, va_list args)
350 break; 414 break;
351 case DP_S_DONE: 415 case DP_S_DONE:
352 break; 416 break;
353 default: /* hmm? */ 417 default:
418 /* hmm? */
354 break; /* some picky compilers need this */ 419 break; /* some picky compilers need this */
355 } 420 }
356 } 421 }
357 if (currlen < maxlen - 1) 422 if (maxlen != 0) {
358 buffer[currlen] = '\0'; 423 if (currlen < maxlen - 1)
359 else 424 buffer[currlen] = '\0';
360 buffer[maxlen - 1] = '\0'; 425 else if (maxlen > 0)
426 buffer[maxlen - 1] = '\0';
427 }
428
429 return currlen;
361} 430}
362 431
363static void 432static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
364fmtstr(char *buffer, size_t *currlen, size_t maxlen, 433 char *value, int flags, int min, int max)
365 char *value, int flags, int min, int max)
366{ 434{
367 int cnt = 0, padlen, strln; /* amount to pad */ 435 int padlen, strln; /* amount to pad */
368 436 int cnt = 0;
369 if (value == 0) 437
438#ifdef DEBUG_SNPRINTF
439 printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
440#endif
441 if (value == 0) {
370 value = "<NULL>"; 442 value = "<NULL>";
443 }
371 444
372 for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */ 445 for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */
373 padlen = min - strln; 446 padlen = min - strln;
@@ -375,18 +448,18 @@ fmtstr(char *buffer, size_t *currlen, size_t maxlen,
375 padlen = 0; 448 padlen = 0;
376 if (flags & DP_F_MINUS) 449 if (flags & DP_F_MINUS)
377 padlen = -padlen; /* Left Justify */ 450 padlen = -padlen; /* Left Justify */
378 451
379 while ((padlen > 0) && (cnt < max)) { 452 while ((padlen > 0) && (cnt < max)) {
380 dopr_outch(buffer, currlen, maxlen, ' '); 453 dopr_outch (buffer, currlen, maxlen, ' ');
381 --padlen; 454 --padlen;
382 ++cnt; 455 ++cnt;
383 } 456 }
384 while (*value && (cnt < max)) { 457 while (*value && (cnt < max)) {
385 dopr_outch(buffer, currlen, maxlen, *value++); 458 dopr_outch (buffer, currlen, maxlen, *value++);
386 ++cnt; 459 ++cnt;
387 } 460 }
388 while ((padlen < 0) && (cnt < max)) { 461 while ((padlen < 0) && (cnt < max)) {
389 dopr_outch(buffer, currlen, maxlen, ' '); 462 dopr_outch (buffer, currlen, maxlen, ' ');
390 ++padlen; 463 ++padlen;
391 ++cnt; 464 ++cnt;
392 } 465 }
@@ -394,49 +467,49 @@ fmtstr(char *buffer, size_t *currlen, size_t maxlen,
394 467
395/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ 468/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
396 469
397static void 470static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
398fmtint(char *buffer, size_t *currlen, size_t maxlen, 471 long value, int base, int min, int max, int flags)
399 long value, int base, int min, int max, int flags)
400{ 472{
473 int signvalue = 0;
401 unsigned long uvalue; 474 unsigned long uvalue;
402 char convert[20]; 475 char convert[20];
403 int signvalue = 0, place = 0, caps = 0; 476 int place = 0;
404 int spadlen = 0; /* amount to space pad */ 477 int spadlen = 0; /* amount to space pad */
405 int zpadlen = 0; /* amount to zero pad */ 478 int zpadlen = 0; /* amount to zero pad */
406 479 int caps = 0;
480
407 if (max < 0) 481 if (max < 0)
408 max = 0; 482 max = 0;
409 483
410 uvalue = value; 484 uvalue = value;
411 485
412 if (!(flags & DP_F_UNSIGNED)) { 486 if(!(flags & DP_F_UNSIGNED)) {
413 if (value < 0) { 487 if( value < 0 ) {
414 signvalue = '-'; 488 signvalue = '-';
415 uvalue = -value; 489 uvalue = -value;
416 } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 490 } else {
417 signvalue = '+'; 491 if (flags & DP_F_PLUS) /* Do a sign (+/i) */
418 else if (flags & DP_F_SPACE) 492 signvalue = '+';
419 signvalue = ' '; 493 else if (flags & DP_F_SPACE)
494 signvalue = ' ';
495 }
420 } 496 }
421 497
422 if (flags & DP_F_UP) 498 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
423 caps = 1; /* Should characters be upper case? */ 499
424 do { 500 do {
425 convert[place++] = 501 convert[place++] =
426 (caps ? "0123456789ABCDEF" : "0123456789abcdef") 502 (caps? "0123456789ABCDEF":"0123456789abcdef")
427 [uvalue % (unsigned)base]; 503 [uvalue % (unsigned)base ];
428 uvalue = (uvalue / (unsigned)base ); 504 uvalue = (uvalue / (unsigned)base );
429 } while (uvalue && (place < 20)); 505 } while(uvalue && (place < 20));
430 if (place == 20) 506 if (place == 20) place--;
431 place--;
432 convert[place] = 0; 507 convert[place] = 0;
433 508
434 zpadlen = max - place; 509 zpadlen = max - place;
435 spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); 510 spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
436 if (zpadlen < 0) 511 if (zpadlen < 0) zpadlen = 0;
437 zpadlen = 0; 512 if (spadlen < 0) spadlen = 0;
438 if (spadlen < 0)
439 spadlen = 0;
440 if (flags & DP_F_ZERO) { 513 if (flags & DP_F_ZERO) {
441 zpadlen = MAX(zpadlen, spadlen); 514 zpadlen = MAX(zpadlen, spadlen);
442 spadlen = 0; 515 spadlen = 0;
@@ -444,27 +517,32 @@ fmtint(char *buffer, size_t *currlen, size_t maxlen,
444 if (flags & DP_F_MINUS) 517 if (flags & DP_F_MINUS)
445 spadlen = -spadlen; /* Left Justifty */ 518 spadlen = -spadlen; /* Left Justifty */
446 519
520#ifdef DEBUG_SNPRINTF
521 printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
522 zpadlen, spadlen, min, max, place);
523#endif
524
447 /* Spaces */ 525 /* Spaces */
448 while (spadlen > 0) { 526 while (spadlen > 0) {
449 dopr_outch(buffer, currlen, maxlen, ' '); 527 dopr_outch (buffer, currlen, maxlen, ' ');
450 --spadlen; 528 --spadlen;
451 } 529 }
452 530
453 /* Sign */ 531 /* Sign */
454 if (signvalue) 532 if (signvalue)
455 dopr_outch(buffer, currlen, maxlen, signvalue); 533 dopr_outch (buffer, currlen, maxlen, signvalue);
456 534
457 /* Zeros */ 535 /* Zeros */
458 if (zpadlen > 0) { 536 if (zpadlen > 0) {
459 while (zpadlen > 0) { 537 while (zpadlen > 0) {
460 dopr_outch(buffer, currlen, maxlen, '0'); 538 dopr_outch (buffer, currlen, maxlen, '0');
461 --zpadlen; 539 --zpadlen;
462 } 540 }
463 } 541 }
464 542
465 /* Digits */ 543 /* Digits */
466 while (place > 0) 544 while (place > 0)
467 dopr_outch(buffer, currlen, maxlen, convert[--place]); 545 dopr_outch (buffer, currlen, maxlen, convert[--place]);
468 546
469 /* Left Justified spaces */ 547 /* Left Justified spaces */
470 while (spadlen < 0) { 548 while (spadlen < 0) {
@@ -473,11 +551,20 @@ fmtint(char *buffer, size_t *currlen, size_t maxlen,
473 } 551 }
474} 552}
475 553
476static long double 554static LDOUBLE abs_val(LDOUBLE value)
477pow10(int exp)
478{ 555{
479 long double result = 1; 556 LDOUBLE result = value;
557
558 if (value < 0)
559 result = -value;
560
561 return result;
562}
480 563
564static LDOUBLE POW10(int exp)
565{
566 LDOUBLE result = 1;
567
481 while (exp) { 568 while (exp) {
482 result *= 10; 569 result *= 10;
483 exp--; 570 exp--;
@@ -486,28 +573,69 @@ pow10(int exp)
486 return result; 573 return result;
487} 574}
488 575
489static long 576static LLONG ROUND(LDOUBLE value)
490round(long double value)
491{ 577{
492 long intpart = value; 578 LLONG intpart;
493
494 value -= intpart;
495 if (value >= 0.5)
496 intpart++;
497 579
580 intpart = (LLONG)value;
581 value = value - intpart;
582 if (value >= 0.5) intpart++;
583
498 return intpart; 584 return intpart;
499} 585}
500 586
501static void 587/* a replacement for modf that doesn't need the math library. Should
502fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, 588 be portable, but slow */
503 int min, int max, int flags) 589static double my_modf(double x0, double *iptr)
504{ 590{
505 char iconvert[20], fconvert[20]; 591 int i;
506 int signvalue = 0, iplace = 0, fplace = 0; 592 long l;
593 double x = x0;
594 double f = 1.0;
595
596 for (i=0;i<100;i++) {
597 l = (long)x;
598 if (l <= (x+1) && l >= (x-1)) break;
599 x *= 0.1;
600 f *= 10.0;
601 }
602
603 if (i == 100) {
604 /* yikes! the number is beyond what we can handle. What do we do? */
605 (*iptr) = 0;
606 return 0;
607 }
608
609 if (i != 0) {
610 double i2;
611 double ret;
612
613 ret = my_modf(x0-l*f, &i2);
614 (*iptr) = l*f + i2;
615 return ret;
616 }
617
618 (*iptr) = l;
619 return x - (*iptr);
620}
621
622
623static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
624 LDOUBLE fvalue, int min, int max, int flags)
625{
626 int signvalue = 0;
627 double ufvalue;
628 char iconvert[311];
629 char fconvert[311];
630 int iplace = 0;
631 int fplace = 0;
507 int padlen = 0; /* amount to pad */ 632 int padlen = 0; /* amount to pad */
508 int zpadlen = 0, caps = 0; 633 int zpadlen = 0;
509 long intpart, fracpart; 634 int caps = 0;
510 long double ufvalue; 635 int idx;
636 double intpart;
637 double fracpart;
638 double temp;
511 639
512 /* 640 /*
513 * AIX manpage says the default is 0, but Solaris says the default 641 * AIX manpage says the default is 0, but Solaris says the default
@@ -516,137 +644,159 @@ fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
516 if (max < 0) 644 if (max < 0)
517 max = 6; 645 max = 6;
518 646
519 ufvalue = abs_val(fvalue); 647 ufvalue = abs_val (fvalue);
520 648
521 if (fvalue < 0) 649 if (fvalue < 0) {
522 signvalue = '-'; 650 signvalue = '-';
523 else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 651 } else {
524 signvalue = '+'; 652 if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
525 else if (flags & DP_F_SPACE) 653 signvalue = '+';
526 signvalue = ' '; 654 } else {
655 if (flags & DP_F_SPACE)
656 signvalue = ' ';
657 }
658 }
527 659
528 intpart = ufvalue; 660#if 0
661 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
662#endif
663
664#if 0
665 if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
666#endif
529 667
530 /* 668 /*
531 * Sorry, we only support 9 digits past the decimal because of our 669 * Sorry, we only support 16 digits past the decimal because of our
532 * conversion method 670 * conversion method
533 */ 671 */
534 if (max > 9) 672 if (max > 16)
535 max = 9; 673 max = 16;
536 674
537 /* We "cheat" by converting the fractional part to integer by 675 /* We "cheat" by converting the fractional part to integer by
538 * multiplying by a factor of 10 676 * multiplying by a factor of 10
539 */ 677 */
540 fracpart = round((pow10 (max)) * (ufvalue - intpart));
541 678
542 if (fracpart >= pow10 (max)) { 679 temp = ufvalue;
680 my_modf(temp, &intpart);
681
682 fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
683
684 if (fracpart >= POW10(max)) {
543 intpart++; 685 intpart++;
544 fracpart -= pow10 (max); 686 fracpart -= POW10(max);
545 } 687 }
546 688
547 /* Convert integer part */ 689 /* Convert integer part */
548 do { 690 do {
691 temp = intpart*0.1;
692 my_modf(temp, &intpart);
693 idx = (int) ((temp -intpart +0.05)* 10.0);
694 /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
695 /* printf ("%llf, %f, %x\n", temp, intpart, idx); */
549 iconvert[iplace++] = 696 iconvert[iplace++] =
550 (caps ? "0123456789ABCDEF" : "0123456789abcdef") 697 (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
551 [intpart % 10]; 698 } while (intpart && (iplace < 311));
552 intpart = (intpart / 10); 699 if (iplace == 311) iplace--;
553 } while(intpart && (iplace < 20));
554 if (iplace == 20)
555 iplace--;
556 iconvert[iplace] = 0; 700 iconvert[iplace] = 0;
557 701
558 /* Convert fractional part */ 702 /* Convert fractional part */
559 do { 703 if (fracpart)
560 fconvert[fplace++] = 704 {
561 (caps ? "0123456789ABCDEF" : "0123456789abcdef") 705 do {
562 [fracpart % 10]; 706 temp = fracpart*0.1;
563 fracpart = (fracpart / 10); 707 my_modf(temp, &fracpart);
564 } while(fracpart && (fplace < 20)); 708 idx = (int) ((temp -fracpart +0.05)* 10.0);
565 if (fplace == 20) 709 /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
566 fplace--; 710 /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
711 fconvert[fplace++] =
712 (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
713 } while(fracpart && (fplace < 311));
714 if (fplace == 311) fplace--;
715 }
567 fconvert[fplace] = 0; 716 fconvert[fplace] = 0;
568 717
569 /* -1 for decimal point, another -1 if we are printing a sign */ 718 /* -1 for decimal point, another -1 if we are printing a sign */
570 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 719 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
571 zpadlen = max - fplace; 720 zpadlen = max - fplace;
572 if (zpadlen < 0) 721 if (zpadlen < 0) zpadlen = 0;
573 zpadlen = 0;
574 if (padlen < 0) 722 if (padlen < 0)
575 padlen = 0; 723 padlen = 0;
576 if (flags & DP_F_MINUS) 724 if (flags & DP_F_MINUS)
577 padlen = -padlen; /* Left Justifty */ 725 padlen = -padlen; /* Left Justifty */
578 726
579 if ((flags & DP_F_ZERO) && (padlen > 0)) { 727 if ((flags & DP_F_ZERO) && (padlen > 0)) {
580 if (signvalue) { 728 if (signvalue) {
581 dopr_outch(buffer, currlen, maxlen, signvalue); 729 dopr_outch (buffer, currlen, maxlen, signvalue);
582 --padlen; 730 --padlen;
583 signvalue = 0; 731 signvalue = 0;
584 } 732 }
585 while (padlen > 0) { 733 while (padlen > 0) {
586 dopr_outch(buffer, currlen, maxlen, '0'); 734 dopr_outch (buffer, currlen, maxlen, '0');
587 --padlen; 735 --padlen;
588 } 736 }
589 } 737 }
590 while (padlen > 0) { 738 while (padlen > 0) {
591 dopr_outch(buffer, currlen, maxlen, ' '); 739 dopr_outch (buffer, currlen, maxlen, ' ');
592 --padlen; 740 --padlen;
593 } 741 }
594 if (signvalue) 742 if (signvalue)
595 dopr_outch(buffer, currlen, maxlen, signvalue); 743 dopr_outch (buffer, currlen, maxlen, signvalue);
596 744
597 while (iplace > 0) 745 while (iplace > 0)
598 dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]); 746 dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
747
748#ifdef DEBUG_SNPRINTF
749 printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
750#endif
599 751
600 /* 752 /*
601 * Decimal point. This should probably use locale to find the 753 * Decimal point. This should probably use locale to find the correct
602 * correct char to print out. 754 * char to print out.
603 */ 755 */
604 dopr_outch(buffer, currlen, maxlen, '.'); 756 if (max > 0) {
605 757 dopr_outch (buffer, currlen, maxlen, '.');
606 while (fplace > 0) 758
607 dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]); 759 while (zpadlen > 0) {
760 dopr_outch (buffer, currlen, maxlen, '0');
761 --zpadlen;
762 }
608 763
609 while (zpadlen > 0) { 764 while (fplace > 0)
610 dopr_outch(buffer, currlen, maxlen, '0'); 765 dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
611 --zpadlen;
612 } 766 }
613 767
614 while (padlen < 0) { 768 while (padlen < 0) {
615 dopr_outch(buffer, currlen, maxlen, ' '); 769 dopr_outch (buffer, currlen, maxlen, ' ');
616 ++padlen; 770 ++padlen;
617 } 771 }
618} 772}
619 773
620static void 774static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
621dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
622{ 775{
623 if (*currlen < maxlen) 776 if (*currlen < maxlen) {
624 buffer[(*currlen)++] = c; 777 buffer[(*currlen)] = c;
778 }
779 (*currlen)++;
625} 780}
626#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ 781#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
627 782
628#ifndef HAVE_VSNPRINTF 783#if !defined(HAVE_VSNPRINTF)
629int 784int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
630vsnprintf(char *str, size_t count, const char *fmt, va_list args)
631{ 785{
632 str[0] = 0; 786 return dopr(str, count, fmt, args);
633 dopr(str, count, fmt, args);
634
635 return(strlen(str));
636} 787}
637#endif /* !HAVE_VSNPRINTF */ 788#endif
638 789
639#ifndef HAVE_SNPRINTF 790#if !defined(HAVE_SNPRINTF)
640int 791int snprintf(char *str,size_t count,const char *fmt,...)
641snprintf(char *str,size_t count,const char *fmt,...)
642{ 792{
793 size_t ret;
643 va_list ap; 794 va_list ap;
644 795
645 va_start(ap, fmt); 796 va_start(ap, fmt);
646 (void) vsnprintf(str, count, fmt, ap); 797 ret = vsnprintf(str, count, fmt, ap);
647 va_end(ap); 798 va_end(ap);
648 799 return ret;
649 return(strlen(str));
650} 800}
801#endif
651 802
652#endif /* !HAVE_SNPRINTF */
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h
index dda558ffe..fe0c36dcd 100644
--- a/openbsd-compat/openbsd-compat.h
+++ b/openbsd-compat/openbsd-compat.h
@@ -1,4 +1,4 @@
1/* $Id: openbsd-compat.h,v 1.31 2005/09/29 23:55:50 dtucker Exp $ */ 1/* $Id: openbsd-compat.h,v 1.32 2005/11/24 08:58:21 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999-2003 Damien Miller. All rights reserved. 4 * Copyright (c) 1999-2003 Damien Miller. All rights reserved.
@@ -142,6 +142,10 @@ unsigned int arc4random(void);
142void arc4random_stir(void); 142void arc4random_stir(void);
143#endif /* !HAVE_ARC4RANDOM */ 143#endif /* !HAVE_ARC4RANDOM */
144 144
145#ifndef HAVE_ASPRINTF
146int asprintf(char **, const char *, ...);
147#endif
148
145#ifndef HAVE_OPENPTY 149#ifndef HAVE_OPENPTY
146int openpty(int *, int *, char *, struct termios *, struct winsize *); 150int openpty(int *, int *, char *, struct termios *, struct winsize *);
147#endif /* HAVE_OPENPTY */ 151#endif /* HAVE_OPENPTY */
@@ -160,6 +164,10 @@ long long strtoll(const char *, char **, int);
160long long strtonum(const char *, long long, long long, const char **); 164long long strtonum(const char *, long long, long long, const char **);
161#endif 165#endif
162 166
167#ifndef HAVE_VASPRINTF
168int vasprintf(char **, const char *, va_list);
169#endif
170
163#ifndef HAVE_VSNPRINTF 171#ifndef HAVE_VSNPRINTF
164int vsnprintf(char *, size_t, const char *, va_list); 172int vsnprintf(char *, size_t, const char *, va_list);
165#endif 173#endif