Import bind-9.3.4
[dragonfly.git] / contrib / bind-9.3 / lib / lwres / print.c
blob15522284e5d5867e4d62cef00c59cb5405dd22df
1 /*
2 * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: print.c,v 1.2.4.7 2005/10/14 01:38:51 marka Exp $ */
20 #include <config.h>
22 #include <ctype.h>
23 #include <stdio.h> /* for sprintf */
24 #include <string.h>
26 #define LWRES__PRINT_SOURCE /* Used to get the lwres_print_* prototypes. */
28 #include <lwres/stdlib.h>
30 #include "assert_p.h"
31 #include "print_p.h"
33 #define LWRES_PRINT_QUADFORMAT LWRES_PLATFORM_QUADFORMAT
35 int
36 lwres__print_sprintf(char *str, const char *format, ...) {
37 va_list ap;
39 va_start(ap, format);
40 vsprintf(str, format, ap);
41 va_end(ap);
42 return (strlen(str));
46 * Return length of string that would have been written if not truncated.
49 int
50 lwres__print_snprintf(char *str, size_t size, const char *format, ...) {
51 va_list ap;
52 int ret;
54 va_start(ap, format);
55 ret = vsnprintf(str, size, format, ap);
56 va_end(ap);
57 return (ret);
62 * Return length of string that would have been written if not truncated.
65 int
66 lwres__print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
67 int h;
68 int l;
69 int q;
70 int alt;
71 int zero;
72 int left;
73 int plus;
74 int space;
75 long long tmpi;
76 unsigned long long tmpui;
77 unsigned long width;
78 unsigned long precision;
79 unsigned int length;
80 char buf[1024];
81 char c;
82 void *v;
83 char *save = str;
84 const char *cp;
85 const char *head;
86 int count = 0;
87 int pad;
88 int zeropad;
89 int dot;
90 double dbl;
91 #ifdef HAVE_LONG_DOUBLE
92 long double ldbl;
93 #endif
94 char fmt[32];
96 INSIST(str != NULL);
97 INSIST(format != NULL);
99 while (*format != '\0') {
100 if (*format != '%') {
101 if (size > 1U) {
102 *str++ = *format;
103 size--;
105 count++;
106 format++;
107 continue;
109 format++;
112 * Reset flags.
114 dot = space = plus = left = zero = alt = h = l = q = 0;
115 width = precision = 0;
116 head = "";
117 length = pad = zeropad = 0;
119 do {
120 if (*format == '#') {
121 alt = 1;
122 format++;
123 } else if (*format == '-') {
124 left = 1;
125 zero = 0;
126 format++;
127 } else if (*format == ' ') {
128 if (!plus)
129 space = 1;
130 format++;
131 } else if (*format == '+') {
132 plus = 1;
133 space = 0;
134 format++;
135 } else if (*format == '0') {
136 if (!left)
137 zero = 1;
138 format++;
139 } else
140 break;
141 } while (1);
144 * Width.
146 if (*format == '*') {
147 width = va_arg(ap, int);
148 format++;
149 } else if (isdigit((unsigned char)*format)) {
150 char *e;
151 width = strtoul(format, &e, 10);
152 format = e;
156 * Precision.
158 if (*format == '.') {
159 format++;
160 dot = 1;
161 if (*format == '*') {
162 precision = va_arg(ap, int);
163 format++;
164 } else if (isdigit((unsigned char)*format)) {
165 char *e;
166 precision = strtoul(format, &e, 10);
167 format = e;
171 switch (*format) {
172 case '\0':
173 continue;
174 case '%':
175 if (size > 1U) {
176 *str++ = *format;
177 size--;
179 count++;
180 break;
181 case 'q':
182 q = 1;
183 format++;
184 goto doint;
185 case 'h':
186 h = 1;
187 format++;
188 goto doint;
189 case 'l':
190 l = 1;
191 format++;
192 if (*format == 'l') {
193 q = 1;
194 format++;
196 goto doint;
197 case 'n':
198 case 'i':
199 case 'd':
200 case 'o':
201 case 'u':
202 case 'x':
203 case 'X':
204 doint:
205 if (precision != 0U)
206 zero = 0;
207 switch (*format) {
208 case 'n':
209 if (h) {
210 short int *p;
211 p = va_arg(ap, short *);
212 REQUIRE(p != NULL);
213 *p = str - save;
214 } else if (l) {
215 long int *p;
216 p = va_arg(ap, long *);
217 REQUIRE(p != NULL);
218 *p = str - save;
219 } else {
220 int *p;
221 p = va_arg(ap, int *);
222 REQUIRE(p != NULL);
223 *p = str - save;
225 break;
226 case 'i':
227 case 'd':
228 if (q)
229 tmpi = va_arg(ap, long long int);
230 else if (l)
231 tmpi = va_arg(ap, long int);
232 else
233 tmpi = va_arg(ap, int);
234 if (tmpi < 0) {
235 head = "-";
236 tmpui = -tmpi;
237 } else {
238 if (plus)
239 head = "+";
240 else if (space)
241 head = " ";
242 else
243 head = "";
244 tmpui = tmpi;
246 sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "u",
247 tmpui);
248 goto printint;
249 case 'o':
250 if (q)
251 tmpui = va_arg(ap,
252 unsigned long long int);
253 else if (l)
254 tmpui = va_arg(ap, long int);
255 else
256 tmpui = va_arg(ap, int);
257 sprintf(buf,
258 alt ? "%#" LWRES_PRINT_QUADFORMAT "o"
259 : "%" LWRES_PRINT_QUADFORMAT "o",
260 tmpui);
261 goto printint;
262 case 'u':
263 if (q)
264 tmpui = va_arg(ap,
265 unsigned long long int);
266 else if (l)
267 tmpui = va_arg(ap, unsigned long int);
268 else
269 tmpui = va_arg(ap, unsigned int);
270 sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "u",
271 tmpui);
272 goto printint;
273 case 'x':
274 if (q)
275 tmpui = va_arg(ap,
276 unsigned long long int);
277 else if (l)
278 tmpui = va_arg(ap, unsigned long int);
279 else
280 tmpui = va_arg(ap, unsigned int);
281 if (alt) {
282 head = "0x";
283 if (precision > 2U)
284 precision -= 2;
286 sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "x",
287 tmpui);
288 goto printint;
289 case 'X':
290 if (q)
291 tmpui = va_arg(ap,
292 unsigned long long int);
293 else if (l)
294 tmpui = va_arg(ap, unsigned long int);
295 else
296 tmpui = va_arg(ap, unsigned int);
297 if (alt) {
298 head = "0X";
299 if (precision > 2U)
300 precision -= 2;
302 sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "X",
303 tmpui);
304 goto printint;
305 printint:
306 if (precision != 0U || width != 0U) {
307 length = strlen(buf);
308 if (length < precision)
309 zeropad = precision - length;
310 else if (length < width && zero)
311 zeropad = width - length;
312 if (width != 0U) {
313 pad = width - length -
314 zeropad - strlen(head);
315 if (pad < 0)
316 pad = 0;
319 count += strlen(head) + strlen(buf) + pad +
320 zeropad;
321 if (!left) {
322 while (pad > 0 && size > 1U) {
323 *str++ = ' ';
324 size--;
325 pad--;
328 cp = head;
329 while (*cp != '\0' && size > 1U) {
330 *str++ = *cp++;
331 size--;
333 while (zeropad > 0 && size > 1U) {
334 *str++ = '0';
335 size--;
336 zeropad--;
338 cp = buf;
339 while (*cp != '\0' && size > 1U) {
340 *str++ = *cp++;
341 size--;
343 while (pad > 0 && size > 1U) {
344 *str++ = ' ';
345 size--;
346 pad--;
348 break;
349 default:
350 break;
352 break;
353 case 's':
354 cp = va_arg(ap, char *);
355 REQUIRE(cp != NULL);
357 if (precision != 0U) {
359 * cp need not be NULL terminated.
361 const char *tp;
362 unsigned long n;
364 n = precision;
365 tp = cp;
366 while (n != 0U && *tp != '\0')
367 n--, tp++;
368 length = precision - n;
369 } else {
370 length = strlen(cp);
372 if (width != 0U) {
373 pad = width - length;
374 if (pad < 0)
375 pad = 0;
377 count += pad + length;
378 if (!left)
379 while (pad > 0 && size > 1U) {
380 *str++ = ' ';
381 size--;
382 pad--;
384 if (precision != 0U)
385 while (precision > 0U && *cp != '\0' &&
386 size > 1U) {
387 *str++ = *cp++;
388 size--;
389 precision--;
391 else
392 while (*cp != '\0' && size > 1U) {
393 *str++ = *cp++;
394 size--;
396 while (pad > 0 && size > 1U) {
397 *str++ = ' ';
398 size--;
399 pad--;
401 break;
402 case 'c':
403 c = va_arg(ap, int);
404 if (width > 0U) {
405 count += width;
406 width--;
407 if (left) {
408 *str++ = c;
409 size--;
411 while (width-- > 0U && size > 1U) {
412 *str++ = ' ';
413 size--;
415 if (!left && size > 1U) {
416 *str++ = c;
417 size--;
419 } else {
420 count++;
421 if (size > 1U) {
422 *str++ = c;
423 size--;
426 break;
427 case 'p':
428 v = va_arg(ap, void *);
429 sprintf(buf, "%p", v);
430 length = strlen(buf);
431 if (precision > length)
432 zeropad = precision - length;
433 if (width > 0U) {
434 pad = width - length - zeropad;
435 if (pad < 0)
436 pad = 0;
438 count += length + pad + zeropad;
439 if (!left)
440 while (pad > 0 && size > 1U) {
441 *str++ = ' ';
442 size--;
443 pad--;
445 cp = buf;
446 if (zeropad > 0 && buf[0] == '0' &&
447 (buf[1] == 'x' || buf[1] == 'X')) {
448 if (size > 1U) {
449 *str++ = *cp++;
450 size--;
452 if (size > 1U) {
453 *str++ = *cp++;
454 size--;
456 while (zeropad > 0 && size > 1U) {
457 *str++ = '0';
458 size--;
459 zeropad--;
462 while (*cp != '\0' && size > 1U) {
463 *str++ = *cp++;
464 size--;
466 while (pad > 0 && size > 1U) {
467 *str++ = ' ';
468 size--;
469 pad--;
471 break;
472 case 'D': /*deprecated*/
473 INSIST("use %ld instead of %D" == NULL);
474 case 'O': /*deprecated*/
475 INSIST("use %lo instead of %O" == NULL);
476 case 'U': /*deprecated*/
477 INSIST("use %lu instead of %U" == NULL);
479 case 'L':
480 #ifdef HAVE_LONG_DOUBLE
481 l = 1;
482 #else
483 INSIST("long doubles are not supported" == NULL);
484 #endif
485 /*FALLTHROUGH*/
486 case 'e':
487 case 'E':
488 case 'f':
489 case 'g':
490 case 'G':
491 if (!dot)
492 precision = 6;
494 * IEEE floating point.
495 * MIN 2.2250738585072014E-308
496 * MAX 1.7976931348623157E+308
497 * VAX floating point has a smaller range than IEEE.
499 * precisions > 324 don't make much sense.
500 * if we cap the precision at 512 we will not
501 * overflow buf.
503 if (precision > 512U)
504 precision = 512;
505 sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
506 plus ? "+" : space ? " " : "",
507 precision, l ? "L" : "", *format);
508 switch (*format) {
509 case 'e':
510 case 'E':
511 case 'f':
512 case 'g':
513 case 'G':
514 #ifdef HAVE_LONG_DOUBLE
515 if (l) {
516 ldbl = va_arg(ap, long double);
517 sprintf(buf, fmt, ldbl);
518 } else
519 #endif
521 dbl = va_arg(ap, double);
522 sprintf(buf, fmt, dbl);
524 length = strlen(buf);
525 if (width > 0U) {
526 pad = width - length;
527 if (pad < 0)
528 pad = 0;
530 count += length + pad;
531 if (!left)
532 while (pad > 0 && size > 1U) {
533 *str++ = ' ';
534 size--;
535 pad--;
537 cp = buf;
538 while (*cp != ' ' && size > 1U) {
539 *str++ = *cp++;
540 size--;
542 while (pad > 0 && size > 1U) {
543 *str++ = ' ';
544 size--;
545 pad--;
547 break;
548 default:
549 continue;
551 break;
552 default:
553 continue;
555 format++;
557 if (size > 0U)
558 *str = '\0';
559 return (count);