1 /* $NetBSD: print.c,v 1.6 2014/12/10 04:38:02 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2011, 2012, 2014 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.
23 #include <stdio.h> /* for sprintf */
26 #define LWRES__PRINT_SOURCE /* Used to get the lwres_print_* prototypes. */
28 #include <lwres/stdlib.h>
29 #include <lwres/string.h>
34 #define LWRES_PRINT_QUADFORMAT LWRES_PLATFORM_QUADFORMAT
37 lwres__print_sprintf(char *str
, const char *format
, ...) {
41 vsprintf(str
, format
, ap
);
47 * Return length of string that would have been written if not truncated.
51 lwres__print_snprintf(char *str
, size_t size
, const char *format
, ...) {
56 ret
= vsnprintf(str
, size
, format
, ap
);
63 * Return length of string that would have been written if not truncated.
67 lwres__print_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
77 unsigned long long tmpui
;
79 unsigned long precision
;
92 #ifdef HAVE_LONG_DOUBLE
98 INSIST(format
!= NULL
);
100 while (*format
!= '\0') {
101 if (*format
!= '%') {
115 dot
= space
= plus
= left
= zero
= alt
= h
= l
= q
= 0;
116 width
= precision
= 0;
118 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) {
475 case 'D': /*deprecated*/
476 INSIST("use %ld instead of %D" == NULL
);
478 case 'O': /*deprecated*/
479 INSIST("use %lo instead of %O" == NULL
);
481 case 'U': /*deprecated*/
482 INSIST("use %lu instead of %U" == NULL
);
486 #ifdef HAVE_LONG_DOUBLE
489 INSIST("long doubles are not supported" == NULL
);
500 * IEEE floating point.
501 * MIN 2.2250738585072014E-308
502 * MAX 1.7976931348623157E+308
503 * VAX floating point has a smaller range than IEEE.
505 * precisions > 324 don't make much sense.
506 * if we cap the precision at 512 we will not
509 if (precision
> 512U)
511 sprintf(fmt
, "%%%s%s.%lu%s%c", alt
? "#" : "",
512 plus
? "+" : space
? " " : "",
513 precision
, l
? "L" : "", *format
);
520 #ifdef HAVE_LONG_DOUBLE
522 ldbl
= va_arg(ap
, long double);
523 sprintf(buf
, fmt
, ldbl
);
527 dbl
= va_arg(ap
, double);
528 sprintf(buf
, fmt
, dbl
);
530 length
= strlen(buf
);
532 pad
= width
- length
;
536 count
+= length
+ pad
;
538 while (pad
> 0 && size
> 1U) {
544 while (*cp
!= ' ' && size
> 1U) {
548 while (pad
> 0 && size
> 1U) {