4 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or 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.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: print.c,v 1.35 2008/02/18 23:46:59 tbox Exp */
27 #include <stdio.h> /* for sprintf() */
28 #include <string.h> /* for strlen() */
30 #define ISC__PRINT_SOURCE /* Used to get the isc_print_* prototypes. */
32 #include <isc/assertions.h>
35 #include <isc/print.h>
36 #include <isc/stdlib.h>
40 isc_print_sprintf(char *str
, const char *format
, ...) {
44 vsprintf(str
, format
, ap
);
50 * Return length of string that would have been written if not truncated.
54 isc_print_snprintf(char *str
, size_t size
, const char *format
, ...) {
59 ret
= vsnprintf(str
, size
, format
, ap
);
66 * Return length of string that would have been written if not truncated.
70 isc_print_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
83 unsigned long precision
;
96 #ifdef HAVE_LONG_DOUBLE
102 INSIST(format
!= NULL
);
104 while (*format
!= '\0') {
105 if (*format
!= '%') {
119 dot
= neg
= space
= plus
= left
= zero
= alt
= h
= l
= q
= 0;
120 width
= precision
= 0;
122 length
= pad
= zeropad
= 0;
125 if (*format
== '#') {
128 } else if (*format
== '-') {
132 } else if (*format
== ' ') {
136 } else if (*format
== '+') {
140 } else if (*format
== '0') {
151 if (*format
== '*') {
152 width
= va_arg(ap
, int);
154 } else if (isdigit((unsigned char)*format
)) {
156 width
= strtoul(format
, &e
, 10);
163 if (*format
== '.') {
166 if (*format
== '*') {
167 precision
= va_arg(ap
, int);
169 } else if (isdigit((unsigned char)*format
)) {
171 precision
= strtoul(format
, &e
, 10);
197 if (*format
== 'l') {
216 p
= va_arg(ap
, short *);
221 p
= va_arg(ap
, long *);
226 p
= va_arg(ap
, int *);
234 tmpi
= va_arg(ap
, isc_int64_t
);
236 tmpi
= va_arg(ap
, long int);
238 tmpi
= va_arg(ap
, int);
251 if (tmpui
<= 0xffffffffU
)
253 (unsigned long)tmpui
);
258 lo
= tmpui
% 1000000000;
260 mid
= tmpui
% 1000000000;
261 hi
= tmpui
/ 1000000000;
263 sprintf(buf
, "%lu", hi
);
266 sprintf(buf
+ strlen(buf
), "%lu", mid
);
267 sprintf(buf
+ strlen(buf
), "%lu", lo
);
272 tmpui
= va_arg(ap
, isc_uint64_t
);
274 tmpui
= va_arg(ap
, long int);
276 tmpui
= va_arg(ap
, int);
277 if (tmpui
<= 0xffffffffU
)
278 sprintf(buf
, alt
? "%#lo" : "%lo",
279 (unsigned long)tmpui
);
284 lo
= tmpui
% 010000000000;
285 tmpui
/= 010000000000;
286 mid
= tmpui
% 010000000000;
287 hi
= tmpui
/ 010000000000;
290 alt
? "%#lo" : "%lo",
292 sprintf(buf
+ strlen(buf
),
296 alt
? "%#lo" : "%lo",
298 sprintf(buf
+ strlen(buf
), "%lo", lo
);
303 tmpui
= va_arg(ap
, isc_uint64_t
);
305 tmpui
= va_arg(ap
, unsigned long int);
307 tmpui
= va_arg(ap
, unsigned int);
308 if (tmpui
<= 0xffffffffU
)
310 (unsigned long)tmpui
);
315 lo
= tmpui
% 1000000000;
317 mid
= tmpui
% 1000000000;
318 hi
= tmpui
/ 1000000000;
320 sprintf(buf
, "%lu", hi
);
323 sprintf(buf
+ strlen(buf
), "%lu", mid
);
324 sprintf(buf
+ strlen(buf
), "%lu", lo
);
329 tmpui
= va_arg(ap
, isc_uint64_t
);
331 tmpui
= va_arg(ap
, unsigned long int);
333 tmpui
= va_arg(ap
, unsigned int);
339 if (tmpui
<= 0xffffffffU
)
341 (unsigned long)tmpui
);
343 unsigned long hi
= tmpui
>>32;
344 unsigned long lo
= tmpui
& 0xffffffff;
345 sprintf(buf
, "%lx", hi
);
346 sprintf(buf
+ strlen(buf
), "%lx", lo
);
351 tmpui
= va_arg(ap
, isc_uint64_t
);
353 tmpui
= va_arg(ap
, unsigned long int);
355 tmpui
= va_arg(ap
, unsigned int);
361 if (tmpui
<= 0xffffffffU
)
363 (unsigned long)tmpui
);
365 unsigned long hi
= tmpui
>>32;
366 unsigned long lo
= tmpui
& 0xffffffff;
367 sprintf(buf
, "%lX", hi
);
368 sprintf(buf
+ strlen(buf
), "%lX", lo
);
372 if (precision
!= 0 || width
!= 0) {
373 length
= strlen(buf
);
374 if (length
< precision
)
375 zeropad
= precision
- length
;
376 else if (length
< width
&& zero
)
377 zeropad
= width
- length
;
379 pad
= width
- length
-
380 zeropad
- strlen(head
);
385 count
+= strlen(head
) + strlen(buf
) + pad
+
388 while (pad
> 0 && size
> 1) {
395 while (*cp
!= '\0' && size
> 1) {
399 while (zeropad
> 0 && size
> 1) {
405 while (*cp
!= '\0' && size
> 1) {
409 while (pad
> 0 && size
> 1) {
420 cp
= va_arg(ap
, char *);
423 if (precision
!= 0) {
425 * cp need not be NULL terminated.
432 while (n
!= 0 && *tp
!= '\0')
434 length
= precision
- n
;
439 pad
= width
- length
;
443 count
+= pad
+ length
;
445 while (pad
> 0 && size
> 1) {
451 while (precision
> 0 && *cp
!= '\0' &&
458 while (*cp
!= '\0' && size
> 1) {
462 while (pad
> 0 && size
> 1) {
477 while (width
-- > 0 && size
> 1) {
481 if (!left
&& size
> 1) {
494 v
= va_arg(ap
, void *);
495 sprintf(buf
, "%p", v
);
496 length
= strlen(buf
);
497 if (precision
> length
)
498 zeropad
= precision
- length
;
500 pad
= width
- length
- zeropad
;
504 count
+= length
+ pad
+ zeropad
;
506 while (pad
> 0 && size
> 1) {
512 if (zeropad
> 0 && buf
[0] == '0' &&
513 (buf
[1] == 'x' || buf
[1] == 'X')) {
522 while (zeropad
> 0 && size
> 1) {
528 while (*cp
!= '\0' && size
> 1) {
532 while (pad
> 0 && size
> 1) {
538 case 'D': /*deprecated*/
539 INSIST("use %ld instead of %D" == NULL
);
540 case 'O': /*deprecated*/
541 INSIST("use %lo instead of %O" == NULL
);
542 case 'U': /*deprecated*/
543 INSIST("use %lu instead of %U" == NULL
);
546 #ifdef HAVE_LONG_DOUBLE
549 INSIST("long doubles are not supported" == NULL
);
560 * IEEE floating point.
561 * MIN 2.2250738585072014E-308
562 * MAX 1.7976931348623157E+308
563 * VAX floating point has a smaller range than IEEE.
565 * precisions > 324 don't make much sense.
566 * if we cap the precision at 512 we will not
571 sprintf(fmt
, "%%%s%s.%lu%s%c", alt
? "#" : "",
572 plus
? "+" : space
? " " : "",
573 precision
, l
? "L" : "", *format
);
580 #ifdef HAVE_LONG_DOUBLE
582 ldbl
= va_arg(ap
, long double);
583 sprintf(buf
, fmt
, ldbl
);
587 dbl
= va_arg(ap
, double);
588 sprintf(buf
, fmt
, dbl
);
590 length
= strlen(buf
);
592 pad
= width
- length
;
596 count
+= length
+ pad
;
598 while (pad
> 0 && size
> 1) {
604 while (*cp
!= ' ' && size
> 1) {
608 while (pad
> 0 && size
> 1) {