4 * Copyright (C) 2004, 2005, 2007 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.10 2007/06/19 23:47:22 tbox Exp */
25 #include <stdio.h> /* for sprintf */
28 #define LWRES__PRINT_SOURCE /* Used to get the lwres_print_* prototypes. */
30 #include <lwres/stdlib.h>
35 #define LWRES_PRINT_QUADFORMAT LWRES_PLATFORM_QUADFORMAT
38 lwres__print_sprintf(char *str
, const char *format
, ...) {
42 vsprintf(str
, format
, ap
);
48 * Return length of string that would have been written if not truncated.
52 lwres__print_snprintf(char *str
, size_t size
, const char *format
, ...) {
57 ret
= vsnprintf(str
, size
, format
, ap
);
64 * Return length of string that would have been written if not truncated.
68 lwres__print_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
78 unsigned long long tmpui
;
80 unsigned long precision
;
93 #ifdef HAVE_LONG_DOUBLE
99 INSIST(format
!= NULL
);
101 while (*format
!= '\0') {
102 if (*format
!= '%') {
116 dot
= space
= plus
= left
= zero
= alt
= h
= l
= q
= 0;
117 width
= precision
= 0;
119 length
= pad
= zeropad
= 0;
122 if (*format
== '#') {
125 } else if (*format
== '-') {
129 } else if (*format
== ' ') {
133 } else if (*format
== '+') {
137 } else if (*format
== '0') {
148 if (*format
== '*') {
149 width
= va_arg(ap
, int);
151 } else if (isdigit((unsigned char)*format
)) {
153 width
= strtoul(format
, &e
, 10);
160 if (*format
== '.') {
163 if (*format
== '*') {
164 precision
= va_arg(ap
, int);
166 } else if (isdigit((unsigned char)*format
)) {
168 precision
= strtoul(format
, &e
, 10);
194 if (*format
== 'l') {
213 p
= va_arg(ap
, short *);
218 p
= va_arg(ap
, long *);
223 p
= va_arg(ap
, int *);
231 tmpi
= va_arg(ap
, long long int);
233 tmpi
= va_arg(ap
, long int);
235 tmpi
= va_arg(ap
, int);
248 sprintf(buf
, "%" LWRES_PRINT_QUADFORMAT
"u",
254 unsigned long long int);
256 tmpui
= va_arg(ap
, long int);
258 tmpui
= va_arg(ap
, int);
260 alt
? "%#" LWRES_PRINT_QUADFORMAT
"o"
261 : "%" LWRES_PRINT_QUADFORMAT
"o",
267 unsigned long long int);
269 tmpui
= va_arg(ap
, unsigned long int);
271 tmpui
= va_arg(ap
, unsigned int);
272 sprintf(buf
, "%" LWRES_PRINT_QUADFORMAT
"u",
278 unsigned long long int);
280 tmpui
= va_arg(ap
, unsigned long int);
282 tmpui
= va_arg(ap
, unsigned int);
288 sprintf(buf
, "%" LWRES_PRINT_QUADFORMAT
"x",
294 unsigned long long int);
296 tmpui
= va_arg(ap
, unsigned long int);
298 tmpui
= va_arg(ap
, unsigned int);
304 sprintf(buf
, "%" LWRES_PRINT_QUADFORMAT
"X",
308 if (precision
!= 0U || width
!= 0U) {
309 length
= strlen(buf
);
310 if (length
< precision
)
311 zeropad
= precision
- length
;
312 else if (length
< width
&& zero
)
313 zeropad
= width
- length
;
315 pad
= width
- length
-
316 zeropad
- strlen(head
);
321 count
+= strlen(head
) + strlen(buf
) + pad
+
324 while (pad
> 0 && size
> 1U) {
331 while (*cp
!= '\0' && size
> 1U) {
335 while (zeropad
> 0 && size
> 1U) {
341 while (*cp
!= '\0' && size
> 1U) {
345 while (pad
> 0 && size
> 1U) {
356 cp
= va_arg(ap
, char *);
359 if (precision
!= 0U) {
361 * cp need not be NULL terminated.
368 while (n
!= 0U && *tp
!= '\0')
370 length
= precision
- n
;
375 pad
= width
- length
;
379 count
+= pad
+ length
;
381 while (pad
> 0 && size
> 1U) {
387 while (precision
> 0U && *cp
!= '\0' &&
394 while (*cp
!= '\0' && size
> 1U) {
398 while (pad
> 0 && size
> 1U) {
413 while (width
-- > 0U && size
> 1U) {
417 if (!left
&& size
> 1U) {
430 v
= va_arg(ap
, void *);
431 sprintf(buf
, "%p", v
);
432 length
= strlen(buf
);
433 if (precision
> length
)
434 zeropad
= precision
- length
;
436 pad
= width
- length
- zeropad
;
440 count
+= length
+ pad
+ zeropad
;
442 while (pad
> 0 && size
> 1U) {
448 if (zeropad
> 0 && buf
[0] == '0' &&
449 (buf
[1] == 'x' || buf
[1] == 'X')) {
458 while (zeropad
> 0 && size
> 1U) {
464 while (*cp
!= '\0' && size
> 1U) {
468 while (pad
> 0 && size
> 1U) {
474 case 'D': /*deprecated*/
475 INSIST("use %ld instead of %D" == NULL
);
476 case 'O': /*deprecated*/
477 INSIST("use %lo instead of %O" == NULL
);
478 case 'U': /*deprecated*/
479 INSIST("use %lu instead of %U" == NULL
);
482 #ifdef HAVE_LONG_DOUBLE
485 INSIST("long doubles are not supported" == NULL
);
496 * IEEE floating point.
497 * MIN 2.2250738585072014E-308
498 * MAX 1.7976931348623157E+308
499 * VAX floating point has a smaller range than IEEE.
501 * precisions > 324 don't make much sense.
502 * if we cap the precision at 512 we will not
505 if (precision
> 512U)
507 sprintf(fmt
, "%%%s%s.%lu%s%c", alt
? "#" : "",
508 plus
? "+" : space
? " " : "",
509 precision
, l
? "L" : "", *format
);
516 #ifdef HAVE_LONG_DOUBLE
518 ldbl
= va_arg(ap
, long double);
519 sprintf(buf
, fmt
, ldbl
);
523 dbl
= va_arg(ap
, double);
524 sprintf(buf
, fmt
, dbl
);
526 length
= strlen(buf
);
528 pad
= width
- length
;
532 count
+= length
+ pad
;
534 while (pad
> 0 && size
> 1U) {
540 while (*cp
!= ' ' && size
> 1U) {
544 while (pad
> 0 && size
> 1U) {