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