]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind9/lib/lwres/print.c
This commit was generated by cvs2svn to compensate for changes in r151970,
[FreeBSD/FreeBSD.git] / contrib / bind9 / lib / lwres / print.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
4  *
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.
8  *
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.
16  */
17
18 /* $Id: print.c,v 1.2.4.3 2004/09/16 07:01:13 marka Exp $ */
19
20 #include <config.h>
21
22 #include <ctype.h>
23 #include <stdio.h>              /* for sprintf */
24 #include <string.h>
25
26 #define LWRES__PRINT_SOURCE     /* Used to get the lwres_print_* prototypes. */
27
28 #include <stdlib.h>
29
30 #include "assert_p.h"
31 #include "print_p.h"
32
33 int
34 lwres__print_sprintf(char *str, const char *format, ...) {
35         va_list ap;
36
37         va_start(ap, format);
38         vsprintf(str, format, ap);
39         va_end(ap);
40         return (strlen(str));
41 }
42
43 /*
44  * Return length of string that would have been written if not truncated.
45  */
46
47 int
48 lwres__print_snprintf(char *str, size_t size, const char *format, ...) {
49         va_list ap;
50         int ret;
51
52         va_start(ap, format);
53         ret = vsnprintf(str, size, format, ap);
54         va_end(ap);
55         return (ret);
56
57 }
58
59 /*
60  * Return length of string that would have been written if not truncated.
61  */
62
63 int
64 lwres__print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
65         int h;
66         int l;
67         int q;
68         int alt;
69         int zero;
70         int left;
71         int plus;
72         int space;
73         int neg;
74         long long tmpi;
75         unsigned long long tmpui;
76         unsigned long width;
77         unsigned long precision;
78         unsigned int length;
79         char buf[1024];
80         char c;
81         void *v;
82         char *save = str;
83         const char *cp;
84         const char *head;
85         int count = 0;
86         int pad;
87         int zeropad;
88         int dot;
89         double dbl;
90 #ifdef HAVE_LONG_DOUBLE
91         long double ldbl;
92 #endif
93         char fmt[32];
94
95         INSIST(str != NULL);
96         INSIST(format != NULL);
97
98         while (*format != '\0') {
99                 if (*format != '%') {
100                         if (size > 1U) {
101                                 *str++ = *format;
102                                 size--;
103                         }
104                         count++;
105                         format++;
106                         continue;
107                 }
108                 format++;
109
110                 /*
111                  * Reset flags.
112                  */
113                 dot = neg = space = plus = left = zero = alt = h = l = q = 0;
114                 width = precision = 0;
115                 head = "";
116                 length = pad = zeropad = 0;
117
118                 do {
119                         if (*format == '#') {
120                                 alt = 1;
121                                 format++;
122                         } else if (*format == '-') {
123                                 left = 1;
124                                 zero = 0;
125                                 format++;
126                         } else if (*format == ' ') {
127                                 if (!plus)
128                                         space = 1;
129                                 format++;
130                         } else if (*format == '+') {
131                                 plus = 1;
132                                 space = 0;
133                                 format++;
134                         } else if (*format == '0') {
135                                 if (!left)
136                                         zero = 1;
137                                 format++;
138                         } else
139                                 break;
140                 } while (1);
141
142                 /*
143                  * Width.
144                  */
145                 if (*format == '*') {
146                         width = va_arg(ap, int);
147                         format++;
148                 } else if (isdigit((unsigned char)*format)) {
149                         char *e;
150                         width = strtoul(format, &e, 10);
151                         format = e;
152                 }
153
154                 /*
155                  * Precision.
156                  */
157                 if (*format == '.') {
158                         format++;
159                         dot = 1;
160                         if (*format == '*') {
161                                 precision = va_arg(ap, int);
162                                 format++;
163                         } else if (isdigit((unsigned char)*format)) {
164                                 char *e;
165                                 precision = strtoul(format, &e, 10);
166                                 format = e;
167                         }
168                 }
169
170                 switch (*format) {
171                 case '\0':
172                         continue;
173                 case '%':
174                         if (size > 1U) {
175                                 *str++ = *format;
176                                 size--;
177                         }
178                         count++;
179                         break;
180                 case 'q':
181                         q = 1;
182                         format++;
183                         goto doint;
184                 case 'h':
185                         h = 1;
186                         format++;
187                         goto doint;
188                 case 'l':
189                         l = 1;
190                         format++;
191                         if (*format == 'l') {
192                                 q = 1;
193                                 format++;
194                         }
195                         goto doint;
196                 case 'n':
197                 case 'i':
198                 case 'd':
199                 case 'o':
200                 case 'u':
201                 case 'x':
202                 case 'X':
203                 doint:
204                         if (precision != 0U)
205                                 zero = 0;
206                         switch (*format) {
207                         case 'n':
208                                 if (h) {
209                                         short int *p;
210                                         p = va_arg(ap, short *);
211                                         REQUIRE(p != NULL);
212                                         *p = str - save;
213                                 } else if (l) {
214                                         long int *p;
215                                         p = va_arg(ap, long *);
216                                         REQUIRE(p != NULL);
217                                         *p = str - save;
218                                 } else {
219                                         int *p;
220                                         p = va_arg(ap, int *);
221                                         REQUIRE(p != NULL);
222                                         *p = str - save;
223                                 }
224                                 break;
225                         case 'i':
226                         case 'd':
227                                 if (q)
228                                         tmpi = va_arg(ap, long long int);
229                                 else if (l)
230                                         tmpi = va_arg(ap, long int);
231                                 else
232                                         tmpi = va_arg(ap, int);
233                                 if (tmpi < 0) {
234                                         head = "-";
235                                         tmpui = -tmpi;
236                                 } else {
237                                         if (plus)
238                                                 head = "+";
239                                         else if (space)
240                                                 head = " ";
241                                         else
242                                                 head = "";
243                                         tmpui = tmpi;
244                                 }
245                                 sprintf(buf, "%llu",
246                                         tmpui);
247                                 goto printint;
248                         case 'o':
249                                 if (q)
250                                         tmpui = va_arg(ap,
251                                                        unsigned long long int);
252                                 else if (l)
253                                         tmpui = va_arg(ap, long int);
254                                 else
255                                         tmpui = va_arg(ap, int);
256                                 sprintf(buf,
257                                         alt ? "%#llo" : "%llo", tmpui);
258                                 goto printint;
259                         case 'u':
260                                 if (q)
261                                         tmpui = va_arg(ap,
262                                                        unsigned long long int);
263                                 else if (l)
264                                         tmpui = va_arg(ap, unsigned long int);
265                                 else
266                                         tmpui = va_arg(ap, unsigned int);
267                                 sprintf(buf, "%llu", tmpui);
268                                 goto printint;
269                         case 'x':
270                                 if (q)
271                                         tmpui = va_arg(ap,
272                                                        unsigned long long int);
273                                 else if (l)
274                                         tmpui = va_arg(ap, unsigned long int);
275                                 else
276                                         tmpui = va_arg(ap, unsigned int);
277                                 if (alt) {
278                                         head = "0x";
279                                         if (precision > 2U)
280                                                 precision -= 2;
281                                 }
282                                 sprintf(buf, "%llx", tmpui);
283                                 goto printint;
284                         case 'X':
285                                 if (q)
286                                         tmpui = va_arg(ap,
287                                                        unsigned long long int);
288                                 else if (l)
289                                         tmpui = va_arg(ap, unsigned long int);
290                                 else
291                                         tmpui = va_arg(ap, unsigned int);
292                                 if (alt) {
293                                         head = "0X";
294                                         if (precision > 2U)
295                                                 precision -= 2;
296                                 }
297                                 sprintf(buf, "%llX", tmpui);
298                                 goto printint;
299                         printint:
300                                 if (precision != 0U || width != 0U) {
301                                         length = strlen(buf);
302                                         if (length < precision)
303                                                 zeropad = precision - length;
304                                         else if (length < width && zero)
305                                                 zeropad = width - length;
306                                         if (width != 0U) {
307                                                 pad = width - length -
308                                                       zeropad - strlen(head);
309                                                 if (pad < 0)
310                                                         pad = 0;
311                                         }
312                                 }
313                                 count += strlen(head) + strlen(buf) + pad +
314                                          zeropad;
315                                 if (!left) {
316                                         while (pad > 0 && size > 1U) {
317                                                 *str++ = ' ';
318                                                 size--;
319                                                 pad--;
320                                         }
321                                 }
322                                 cp = head;
323                                 while (*cp != '\0' && size > 1U) {
324                                         *str++ = *cp++;
325                                         size--;
326                                 }
327                                 while (zeropad > 0 && size > 1U) {
328                                         *str++ = '0';
329                                         size--;
330                                         zeropad--;
331                                 }
332                                 cp = buf;
333                                 while (*cp != '\0' && size > 1U) {
334                                         *str++ = *cp++;
335                                         size--;
336                                 }
337                                 while (pad > 0 && size > 1U) {
338                                         *str++ = ' ';
339                                         size--;
340                                         pad--;
341                                 }
342                                 break;
343                         default:
344                                 break;
345                         }
346                         break;
347                 case 's':
348                         cp = va_arg(ap, char *);
349                         REQUIRE(cp != NULL);
350
351                         if (precision != 0U) {
352                                 /*
353                                  * cp need not be NULL terminated.
354                                  */
355                                 const char *tp;
356                                 unsigned long n;
357
358                                 n = precision;
359                                 tp = cp;
360                                 while (n != 0U && *tp != '\0')
361                                         n--, tp++;
362                                 length = precision - n;
363                         } else {
364                                 length = strlen(cp);
365                         }
366                         if (width != 0U) {
367                                 pad = width - length;
368                                 if (pad < 0)
369                                         pad = 0;
370                         }
371                         count += pad + length;
372                         if (!left)
373                                 while (pad > 0 && size > 1U) {
374                                         *str++ = ' ';
375                                         size--;
376                                         pad--;
377                                 }
378                         if (precision != 0U)
379                                 while (precision > 0U && *cp != '\0' &&
380                                        size > 1U) {
381                                         *str++ = *cp++;
382                                         size--;
383                                         precision--;
384                                 }
385                         else
386                                 while (*cp != '\0' && size > 1U) {
387                                         *str++ = *cp++;
388                                         size--;
389                                 }
390                         while (pad > 0 && size > 1U) {
391                                 *str++ = ' ';
392                                 size--;
393                                 pad--;
394                         }
395                         break;
396                 case 'c':
397                         c = va_arg(ap, int);
398                         if (width > 0U) {
399                                 count += width;
400                                 width--;
401                                 if (left) {
402                                         *str++ = c;
403                                         size--;
404                                 }
405                                 while (width-- > 0U && size > 1U) {
406                                         *str++ = ' ';
407                                         size--;
408                                 }
409                                 if (!left && size > 1U) {
410                                         *str++ = c;
411                                         size--;
412                                 }
413                         } else {
414                                 count++;
415                                 if (size > 1U) {
416                                         *str++ = c;
417                                         size--;
418                                 }
419                         }
420                         break;
421                 case 'p':
422                         v = va_arg(ap, void *);
423                         sprintf(buf, "%p", v);
424                         length = strlen(buf);
425                         if (precision > length)
426                                 zeropad = precision - length;
427                         if (width > 0U) {
428                                 pad = width - length - zeropad;
429                                 if (pad < 0)
430                                         pad = 0;
431                         }
432                         count += length + pad + zeropad;
433                         if (!left)
434                                 while (pad > 0 && size > 1U) {
435                                         *str++ = ' ';
436                                         size--;
437                                         pad--;
438                                 }
439                         cp = buf;
440                         if (zeropad > 0 && buf[0] == '0' &&
441                             (buf[1] == 'x' || buf[1] == 'X')) {
442                                 if (size > 1U) {
443                                         *str++ = *cp++;
444                                         size--;
445                                 }
446                                 if (size > 1U) {
447                                         *str++ = *cp++;
448                                         size--;
449                                 }
450                                 while (zeropad > 0 && size > 1U) {
451                                         *str++ = '0';
452                                         size--;
453                                         zeropad--;
454                                 }
455                         }
456                         while (*cp != '\0' && size > 1U) {
457                                 *str++ = *cp++;
458                                 size--;
459                         }
460                         while (pad > 0 && size > 1U) {
461                                 *str++ = ' ';
462                                 size--;
463                                 pad--;
464                         }
465                         break;
466                 case 'D':       /*deprecated*/
467                         INSIST("use %ld instead of %D" == NULL);
468                 case 'O':       /*deprecated*/
469                         INSIST("use %lo instead of %O" == NULL);
470                 case 'U':       /*deprecated*/
471                         INSIST("use %lu instead of %U" == NULL);
472
473                 case 'L':
474 #ifdef HAVE_LONG_DOUBLE
475                         l = 1;
476 #else
477                         INSIST("long doubles are not supported" == NULL);
478 #endif
479                         /*FALLTHROUGH*/
480                 case 'e':
481                 case 'E':
482                 case 'f':
483                 case 'g':
484                 case 'G':
485                         if (!dot)
486                                 precision = 6;
487                         /*
488                          * IEEE floating point.
489                          * MIN 2.2250738585072014E-308
490                          * MAX 1.7976931348623157E+308
491                          * VAX floating point has a smaller range than IEEE.
492                          *
493                          * precisions > 324 don't make much sense.
494                          * if we cap the precision at 512 we will not
495                          * overflow buf.
496                          */
497                         if (precision > 512U)
498                                 precision = 512;
499                         sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
500                                 plus ? "+" : space ? " " : "",
501                                 precision, l ? "L" : "", *format);
502                         switch (*format) {
503                         case 'e':
504                         case 'E':
505                         case 'f':
506                         case 'g':
507                         case 'G':
508 #ifdef HAVE_LONG_DOUBLE
509                                 if (l) {
510                                         ldbl = va_arg(ap, long double);
511                                         sprintf(buf, fmt, ldbl);
512                                 } else
513 #endif
514                                 {
515                                         dbl = va_arg(ap, double);
516                                         sprintf(buf, fmt, dbl);
517                                 }
518                                 length = strlen(buf);
519                                 if (width > 0U) {
520                                         pad = width - length;
521                                         if (pad < 0)
522                                                 pad = 0;
523                                 }
524                                 count += length + pad;
525                                 if (!left)
526                                         while (pad > 0 && size > 1U) {
527                                                 *str++ = ' ';
528                                                 size--;
529                                                 pad--;
530                                         }
531                                 cp = buf;
532                                 while (*cp != ' ' && size > 1U) {
533                                         *str++ = *cp++;
534                                         size--;
535                                 }
536                                 while (pad > 0 && size > 1U) {
537                                         *str++ = ' ';
538                                         size--;
539                                         pad--;
540                                 }
541                                 break;
542                         default:
543                                 continue;
544                         }
545                         break;
546                 default:
547                         continue;
548                 }
549                 format++;
550         }
551         if (size > 0U)
552                 *str = '\0';
553         return (count);
554 }