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