]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/apr/strings/apr_snprintf.c
Upgrade to OpenSSH 7.9p1.
[FreeBSD/FreeBSD.git] / contrib / apr / strings / apr_snprintf.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr.h"
18 #include "apr_private.h"
19
20 #include "apr_lib.h"
21 #include "apr_strings.h"
22 #include "apr_network_io.h"
23 #include "apr_portable.h"
24 #include "apr_errno.h"
25 #include <math.h>
26 #if APR_HAVE_CTYPE_H
27 #include <ctype.h>
28 #endif
29 #if APR_HAVE_NETINET_IN_H
30 #include <netinet/in.h>
31 #endif
32 #if APR_HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
34 #endif
35 #if APR_HAVE_ARPA_INET_H
36 #include <arpa/inet.h>
37 #endif
38 #if APR_HAVE_LIMITS_H
39 #include <limits.h>
40 #endif
41 #if APR_HAVE_STRING_H
42 #include <string.h>
43 #endif
44
45 typedef enum {
46     NO = 0, YES = 1
47 } boolean_e;
48
49 #ifndef FALSE
50 #define FALSE 0
51 #endif
52 #ifndef TRUE
53 #define TRUE 1
54 #endif
55 #define NUL '\0'
56
57 static const char null_string[] = "(null)";
58 #define S_NULL ((char *)null_string)
59 #define S_NULL_LEN 6
60
61 #define FLOAT_DIGITS 6
62 #define EXPONENT_LENGTH 10
63
64 /*
65  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
66  *
67  * NOTICE: this is a magic number; do not decrease it
68  */
69 #define NUM_BUF_SIZE 512
70
71 /*
72  * cvt - IEEE floating point formatting routines.
73  *       Derived from UNIX V7, Copyright(C) Caldera International Inc.
74  */
75
76 /*
77  *    apr_ecvt converts to decimal
78  *      the number of digits is specified by ndigit
79  *      decpt is set to the position of the decimal point
80  *      sign is set to 0 for positive, 1 for negative
81  */
82
83 #define NDIG 80
84
85 /* buf must have at least NDIG bytes */
86 static char *apr_cvt(double arg, int ndigits, int *decpt, int *sign, 
87                      int eflag, char *buf)
88 {
89     register int r2;
90     double fi, fj;
91     register char *p, *p1;
92     
93     if (ndigits >= NDIG - 1)
94         ndigits = NDIG - 2;
95     r2 = 0;
96     *sign = 0;
97     p = &buf[0];
98     if (arg < 0) {
99         *sign = 1;
100         arg = -arg;
101     }
102     arg = modf(arg, &fi);
103     p1 = &buf[NDIG];
104     /*
105      * Do integer part
106      */
107     if (fi != 0) {
108         p1 = &buf[NDIG];
109         while (p1 > &buf[0] && fi != 0) {
110             fj = modf(fi / 10, &fi);
111             *--p1 = (int) ((fj + .03) * 10) + '0';
112             r2++;
113         }
114         while (p1 < &buf[NDIG])
115             *p++ = *p1++;
116     }
117     else if (arg > 0) {
118         while ((fj = arg * 10) < 1) {
119             arg = fj;
120             r2--;
121         }
122     }
123     p1 = &buf[ndigits];
124     if (eflag == 0)
125         p1 += r2;
126     if (p1 < &buf[0]) {
127         *decpt = -ndigits;
128         buf[0] = '\0';
129         return (buf);
130     }
131     *decpt = r2;
132     while (p <= p1 && p < &buf[NDIG]) {
133         arg *= 10;
134         arg = modf(arg, &fj);
135         *p++ = (int) fj + '0';
136     }
137     if (p1 >= &buf[NDIG]) {
138         buf[NDIG - 1] = '\0';
139         return (buf);
140     }
141     p = p1;
142     *p1 += 5;
143     while (*p1 > '9') {
144         *p1 = '0';
145         if (p1 > buf)
146             ++ * --p1;
147         else {
148             *p1 = '1';
149             (*decpt)++;
150             if (eflag == 0) {
151                 if (p > buf)
152                     *p = '0';
153                 p++;
154             }
155         }
156     }
157     *p = '\0';
158     return (buf);
159 }
160
161 static char *apr_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
162 {
163     return (apr_cvt(arg, ndigits, decpt, sign, 1, buf));
164 }
165
166 static char *apr_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
167 {
168     return (apr_cvt(arg, ndigits, decpt, sign, 0, buf));
169 }
170
171 /*
172  * apr_gcvt  - Floating output conversion to
173  * minimal length string
174  */
175
176 static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform)
177 {
178     int sign, decpt;
179     register char *p1, *p2;
180     register int i;
181     char buf1[NDIG];
182
183     p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1);
184     p2 = buf;
185     if (sign)
186         *p2++ = '-';
187     for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
188         ndigit--;
189     if ((decpt >= 0 && decpt - ndigit > 4)
190         || (decpt < 0 && decpt < -3)) {                /* use E-style */
191         decpt--;
192         *p2++ = *p1++;
193         *p2++ = '.';
194         for (i = 1; i < ndigit; i++)
195             *p2++ = *p1++;
196         *p2++ = 'e';
197         if (decpt < 0) {
198             decpt = -decpt;
199             *p2++ = '-';
200         }
201         else
202             *p2++ = '+';
203         if (decpt / 100 > 0)
204             *p2++ = decpt / 100 + '0';
205         if (decpt / 10 > 0)
206             *p2++ = (decpt % 100) / 10 + '0';
207         *p2++ = decpt % 10 + '0';
208     }
209     else {
210         if (decpt <= 0) {
211             if (*p1 != '0')
212                 *p2++ = '.';
213             while (decpt < 0) {
214                 decpt++;
215                 *p2++ = '0';
216             }
217         }
218         for (i = 1; i <= ndigit; i++) {
219             *p2++ = *p1++;
220             if (i == decpt)
221                 *p2++ = '.';
222         }
223         if (ndigit < decpt) {
224             while (ndigit++ < decpt)
225                 *p2++ = '0';
226             *p2++ = '.';
227         }
228     }
229     if (p2[-1] == '.' && !altform)
230         p2--;
231     *p2 = '\0';
232     return (buf);
233 }
234
235 /*
236  * The INS_CHAR macro inserts a character in the buffer and writes
237  * the buffer back to disk if necessary
238  * It uses the char pointers sp and bep:
239  *      sp points to the next available character in the buffer
240  *      bep points to the end-of-buffer+1
241  * While using this macro, note that the nextb pointer is NOT updated.
242  *
243  * NOTE: Evaluation of the c argument should not have any side-effects
244  */
245 #define INS_CHAR(c, sp, bep, cc)                    \
246 {                                                   \
247     if (sp) {                                       \
248         if (sp >= bep) {                            \
249             vbuff->curpos = sp;                     \
250             if (flush_func(vbuff))                  \
251                 return -1;                          \
252             sp = vbuff->curpos;                     \
253             bep = vbuff->endpos;                    \
254         }                                           \
255         *sp++ = (c);                                \
256     }                                               \
257     cc++;                                           \
258 }
259
260 #define NUM(c) (c - '0')
261
262 #define STR_TO_DEC(str, num)                        \
263     num = NUM(*str++);                              \
264     while (apr_isdigit(*str))                       \
265     {                                               \
266         num *= 10 ;                                 \
267         num += NUM(*str++);                         \
268     }
269
270 /*
271  * This macro does zero padding so that the precision
272  * requirement is satisfied. The padding is done by
273  * adding '0's to the left of the string that is going
274  * to be printed. We don't allow precision to be large
275  * enough that we continue past the start of s.
276  *
277  * NOTE: this makes use of the magic info that s is
278  * always based on num_buf with a size of NUM_BUF_SIZE.
279  */
280 #define FIX_PRECISION(adjust, precision, s, s_len)  \
281     if (adjust) {                                   \
282         apr_size_t p = (precision + 1 < NUM_BUF_SIZE) \
283                      ? precision : NUM_BUF_SIZE - 1;  \
284         while (s_len < p)                           \
285         {                                           \
286             *--s = '0';                             \
287             s_len++;                                \
288         }                                           \
289     }
290
291 /*
292  * Macro that does padding. The padding is done by printing
293  * the character ch.
294  */
295 #define PAD(width, len, ch)                         \
296 do                                                  \
297 {                                                   \
298     INS_CHAR(ch, sp, bep, cc);                      \
299     width--;                                        \
300 }                                                   \
301 while (width > len)
302
303 /*
304  * Prefix the character ch to the string str
305  * Increase length
306  * Set the has_prefix flag
307  */
308 #define PREFIX(str, length, ch)                     \
309     *--str = ch;                                    \
310     length++;                                       \
311     has_prefix=YES;
312
313
314 /*
315  * Convert num to its decimal format.
316  * Return value:
317  *   - a pointer to a string containing the number (no sign)
318  *   - len contains the length of the string
319  *   - is_negative is set to TRUE or FALSE depending on the sign
320  *     of the number (always set to FALSE if is_unsigned is TRUE)
321  *
322  * The caller provides a buffer for the string: that is the buf_end argument
323  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
324  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
325  *
326  * Note: we have 2 versions. One is used when we need to use quads
327  * (conv_10_quad), the other when we don't (conv_10). We're assuming the
328  * latter is faster.
329  */
330 static char *conv_10(register apr_int32_t num, register int is_unsigned,
331                      register int *is_negative, char *buf_end,
332                      register apr_size_t *len)
333 {
334     register char *p = buf_end;
335     register apr_uint32_t magnitude = num;
336
337     if (is_unsigned) {
338         *is_negative = FALSE;
339     }
340     else {
341         *is_negative = (num < 0);
342
343         /*
344          * On a 2's complement machine, negating the most negative integer 
345          * results in a number that cannot be represented as a signed integer.
346          * Here is what we do to obtain the number's magnitude:
347          *      a. add 1 to the number
348          *      b. negate it (becomes positive)
349          *      c. convert it to unsigned
350          *      d. add 1
351          */
352         if (*is_negative) {
353             apr_int32_t t = num + 1;
354             magnitude = ((apr_uint32_t) -t) + 1;
355         }
356     }
357
358     /*
359      * We use a do-while loop so that we write at least 1 digit 
360      */
361     do {
362         register apr_uint32_t new_magnitude = magnitude / 10;
363
364         *--p = (char) (magnitude - new_magnitude * 10 + '0');
365         magnitude = new_magnitude;
366     }
367     while (magnitude);
368
369     *len = buf_end - p;
370     return (p);
371 }
372
373 static char *conv_10_quad(apr_int64_t num, register int is_unsigned,
374                      register int *is_negative, char *buf_end,
375                      register apr_size_t *len)
376 {
377     register char *p = buf_end;
378     apr_uint64_t magnitude = num;
379
380     /*
381      * We see if we can use the faster non-quad version by checking the
382      * number against the largest long value it can be. If <=, we
383      * punt to the quicker version.
384      */
385     if ((magnitude <= APR_UINT32_MAX && is_unsigned)
386         || (num <= APR_INT32_MAX && num >= APR_INT32_MIN && !is_unsigned))
387             return(conv_10((apr_int32_t)num, is_unsigned, is_negative, buf_end, len));
388
389     if (is_unsigned) {
390         *is_negative = FALSE;
391     }
392     else {
393         *is_negative = (num < 0);
394
395         /*
396          * On a 2's complement machine, negating the most negative integer 
397          * results in a number that cannot be represented as a signed integer.
398          * Here is what we do to obtain the number's magnitude:
399          *      a. add 1 to the number
400          *      b. negate it (becomes positive)
401          *      c. convert it to unsigned
402          *      d. add 1
403          */
404         if (*is_negative) {
405             apr_int64_t t = num + 1;
406             magnitude = ((apr_uint64_t) -t) + 1;
407         }
408     }
409
410     /*
411      * We use a do-while loop so that we write at least 1 digit 
412      */
413     do {
414         apr_uint64_t new_magnitude = magnitude / 10;
415
416         *--p = (char) (magnitude - new_magnitude * 10 + '0');
417         magnitude = new_magnitude;
418     }
419     while (magnitude);
420
421     *len = buf_end - p;
422     return (p);
423 }
424
425 static char *conv_in_addr(struct in_addr *ia, char *buf_end, apr_size_t *len)
426 {
427     unsigned addr = ntohl(ia->s_addr);
428     char *p = buf_end;
429     int is_negative;
430     apr_size_t sub_len;
431
432     p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
433     *--p = '.';
434     p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
435     *--p = '.';
436     p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
437     *--p = '.';
438     p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
439
440     *len = buf_end - p;
441     return (p);
442 }
443
444
445 /* Must be passed a buffer of size NUM_BUF_SIZE where buf_end points
446  * to 1 byte past the end of the buffer. */
447 static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *len)
448 {
449     char *p = buf_end;
450     int is_negative;
451     apr_size_t sub_len;
452     char *ipaddr_str;
453
454     p = conv_10(sa->port, TRUE, &is_negative, p, &sub_len);
455     *--p = ':';
456     ipaddr_str = buf_end - NUM_BUF_SIZE;
457     if (apr_sockaddr_ip_getbuf(ipaddr_str, sa->addr_str_len, sa)) {
458         /* Should only fail if the buffer is too small, which it
459          * should not be; but fail safe anyway: */
460         *--p = '?';
461         *len = buf_end - p;
462         return p;
463     }
464     sub_len = strlen(ipaddr_str);
465 #if APR_HAVE_IPV6
466     if (sa->family == APR_INET6 &&
467         !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) {
468         *(p - 1) = ']';
469         p -= sub_len + 2;
470         *p = '[';
471         memcpy(p + 1, ipaddr_str, sub_len);
472     }
473     else
474 #endif
475     {
476         p -= sub_len;
477         memcpy(p, ipaddr_str, sub_len);
478     }
479
480     *len = buf_end - p;
481     return (p);
482 }
483
484
485
486 #if APR_HAS_THREADS
487 static char *conv_os_thread_t(apr_os_thread_t *tid, char *buf_end, apr_size_t *len)
488 {
489     union {
490         apr_os_thread_t tid;
491         apr_uint64_t u64;
492         apr_uint32_t u32;
493     } u;
494     int is_negative;
495
496     u.tid = *tid;
497     switch(sizeof(u.tid)) {
498     case sizeof(apr_int32_t):
499         return conv_10(u.u32, TRUE, &is_negative, buf_end, len);
500     case sizeof(apr_int64_t):
501         return conv_10_quad(u.u64, TRUE, &is_negative, buf_end, len);
502     default:
503         /* not implemented; stick 0 in the buffer */
504         return conv_10(0, TRUE, &is_negative, buf_end, len);
505     }
506 }
507 #endif
508
509
510
511 /*
512  * Convert a floating point number to a string formats 'f', 'e' or 'E'.
513  * The result is placed in buf, and len denotes the length of the string
514  * The sign is returned in the is_negative argument (and is not placed
515  * in buf).
516  */
517 static char *conv_fp(register char format, register double num,
518     boolean_e add_dp, int precision, int *is_negative,
519     char *buf, apr_size_t *len)
520 {
521     register char *s = buf;
522     register char *p;
523     int decimal_point;
524     char buf1[NDIG];
525
526     if (format == 'f')
527         p = apr_fcvt(num, precision, &decimal_point, is_negative, buf1);
528     else /* either e or E format */
529         p = apr_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
530
531     /*
532      * Check for Infinity and NaN
533      */
534     if (apr_isalpha(*p)) {
535         *len = strlen(p);
536         memcpy(buf, p, *len + 1);
537         *is_negative = FALSE;
538         return (buf);
539     }
540
541     if (format == 'f') {
542         if (decimal_point <= 0) {
543             *s++ = '0';
544             if (precision > 0) {
545                 *s++ = '.';
546                 while (decimal_point++ < 0)
547                     *s++ = '0';
548             }
549             else if (add_dp)
550                 *s++ = '.';
551         }
552         else {
553             while (decimal_point-- > 0)
554                 *s++ = *p++;
555             if (precision > 0 || add_dp)
556                 *s++ = '.';
557         }
558     }
559     else {
560         *s++ = *p++;
561         if (precision > 0 || add_dp)
562             *s++ = '.';
563     }
564
565     /*
566      * copy the rest of p, the NUL is NOT copied
567      */
568     while (*p)
569         *s++ = *p++;
570
571     if (format != 'f') {
572         char temp[EXPONENT_LENGTH];        /* for exponent conversion */
573         apr_size_t t_len;
574         int exponent_is_negative;
575
576         *s++ = format;                /* either e or E */
577         decimal_point--;
578         if (decimal_point != 0) {
579             p = conv_10((apr_int32_t) decimal_point, FALSE, &exponent_is_negative,
580                         &temp[EXPONENT_LENGTH], &t_len);
581             *s++ = exponent_is_negative ? '-' : '+';
582
583             /*
584              * Make sure the exponent has at least 2 digits
585              */
586             if (t_len == 1)
587                 *s++ = '0';
588             while (t_len--)
589                 *s++ = *p++;
590         }
591         else {
592             *s++ = '+';
593             *s++ = '0';
594             *s++ = '0';
595         }
596     }
597
598     *len = s - buf;
599     return (buf);
600 }
601
602
603 /*
604  * Convert num to a base X number where X is a power of 2. nbits determines X.
605  * For example, if nbits is 3, we do base 8 conversion
606  * Return value:
607  *      a pointer to a string containing the number
608  *
609  * The caller provides a buffer for the string: that is the buf_end argument
610  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
611  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
612  *
613  * As with conv_10, we have a faster version which is used when
614  * the number isn't quad size.
615  */
616 static char *conv_p2(register apr_uint32_t num, register int nbits,
617                      char format, char *buf_end, register apr_size_t *len)
618 {
619     register int mask = (1 << nbits) - 1;
620     register char *p = buf_end;
621     static const char low_digits[] = "0123456789abcdef";
622     static const char upper_digits[] = "0123456789ABCDEF";
623     register const char *digits = (format == 'X') ? upper_digits : low_digits;
624
625     do {
626         *--p = digits[num & mask];
627         num >>= nbits;
628     }
629     while (num);
630
631     *len = buf_end - p;
632     return (p);
633 }
634
635 static char *conv_p2_quad(apr_uint64_t num, register int nbits,
636                      char format, char *buf_end, register apr_size_t *len)
637 {
638     register int mask = (1 << nbits) - 1;
639     register char *p = buf_end;
640     static const char low_digits[] = "0123456789abcdef";
641     static const char upper_digits[] = "0123456789ABCDEF";
642     register const char *digits = (format == 'X') ? upper_digits : low_digits;
643
644     if (num <= APR_UINT32_MAX)
645         return(conv_p2((apr_uint32_t)num, nbits, format, buf_end, len));
646
647     do {
648         *--p = digits[num & mask];
649         num >>= nbits;
650     }
651     while (num);
652
653     *len = buf_end - p;
654     return (p);
655 }
656
657 #if APR_HAS_THREADS
658 static char *conv_os_thread_t_hex(apr_os_thread_t *tid, char *buf_end, apr_size_t *len)
659 {
660     union {
661         apr_os_thread_t tid;
662         apr_uint64_t u64;
663         apr_uint32_t u32;
664     } u;
665     int is_negative;
666
667     u.tid = *tid;
668     switch(sizeof(u.tid)) {
669     case sizeof(apr_int32_t):
670         return conv_p2(u.u32, 4, 'x', buf_end, len);
671     case sizeof(apr_int64_t):
672         return conv_p2_quad(u.u64, 4, 'x', buf_end, len);
673     default:
674         /* not implemented; stick 0 in the buffer */
675         return conv_10(0, TRUE, &is_negative, buf_end, len);
676     }
677 }
678 #endif
679
680 /*
681  * Do format conversion placing the output in buffer
682  */
683 APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *),
684     apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap)
685 {
686     register char *sp;
687     register char *bep;
688     register int cc = 0;
689     register apr_size_t i;
690
691     register char *s = NULL;
692     char *q;
693     apr_size_t s_len = 0;
694
695     register apr_size_t min_width = 0;
696     apr_size_t precision = 0;
697     enum {
698         LEFT, RIGHT
699     } adjust;
700     char pad_char;
701     char prefix_char;
702
703     double fp_num;
704     apr_int64_t i_quad = 0;
705     apr_uint64_t ui_quad;
706     apr_int32_t i_num = 0;
707     apr_uint32_t ui_num = 0;
708
709     char num_buf[NUM_BUF_SIZE];
710     char char_buf[2];                /* for printing %% and %<unknown> */
711     char buf[5];                     /* for printing %B, %F, and %S */
712
713     enum var_type_enum {
714             IS_QUAD, IS_LONG, IS_SHORT, IS_INT
715     };
716     enum var_type_enum var_type = IS_INT;
717
718     /*
719      * Flag variables
720      */
721     boolean_e alternate_form;
722     boolean_e print_sign;
723     boolean_e print_blank;
724     boolean_e adjust_precision;
725     boolean_e adjust_width;
726     int is_negative;
727
728     sp = vbuff->curpos;
729     bep = vbuff->endpos;
730
731     while (*fmt) {
732         if (*fmt != '%') {
733             INS_CHAR(*fmt, sp, bep, cc);
734         }
735         else {
736             /*
737              * Default variable settings
738              */
739             boolean_e print_something = YES;
740             adjust = RIGHT;
741             alternate_form = print_sign = print_blank = NO;
742             pad_char = ' ';
743             prefix_char = NUL;
744
745             fmt++;
746
747             /*
748              * Try to avoid checking for flags, width or precision
749              */
750             if (!apr_islower(*fmt)) {
751                 /*
752                  * Recognize flags: -, #, BLANK, +
753                  */
754                 for (;; fmt++) {
755                     if (*fmt == '-')
756                         adjust = LEFT;
757                     else if (*fmt == '+')
758                         print_sign = YES;
759                     else if (*fmt == '#')
760                         alternate_form = YES;
761                     else if (*fmt == ' ')
762                         print_blank = YES;
763                     else if (*fmt == '0')
764                         pad_char = '0';
765                     else
766                         break;
767                 }
768
769                 /*
770                  * Check if a width was specified
771                  */
772                 if (apr_isdigit(*fmt)) {
773                     STR_TO_DEC(fmt, min_width);
774                     adjust_width = YES;
775                 }
776                 else if (*fmt == '*') {
777                     int v = va_arg(ap, int);
778                     fmt++;
779                     adjust_width = YES;
780                     if (v < 0) {
781                         adjust = LEFT;
782                         min_width = (apr_size_t)(-v);
783                     }
784                     else
785                         min_width = (apr_size_t)v;
786                 }
787                 else
788                     adjust_width = NO;
789
790                 /*
791                  * Check if a precision was specified
792                  */
793                 if (*fmt == '.') {
794                     adjust_precision = YES;
795                     fmt++;
796                     if (apr_isdigit(*fmt)) {
797                         STR_TO_DEC(fmt, precision);
798                     }
799                     else if (*fmt == '*') {
800                         int v = va_arg(ap, int);
801                         fmt++;
802                         precision = (v < 0) ? 0 : (apr_size_t)v;
803                     }
804                     else
805                         precision = 0;
806                 }
807                 else
808                     adjust_precision = NO;
809             }
810             else
811                 adjust_precision = adjust_width = NO;
812
813             /*
814              * Modifier check.  In same cases, APR_OFF_T_FMT can be
815              * "lld" and APR_INT64_T_FMT can be "ld" (that is, off_t is
816              * "larger" than int64). Check that case 1st.
817              * Note that if APR_OFF_T_FMT is "d",
818              * the first if condition is never true. If APR_INT64_T_FMT
819              * is "d' then the second if condition is never true.
820              */
821             if ((sizeof(APR_OFF_T_FMT) > sizeof(APR_INT64_T_FMT)) &&
822                 ((sizeof(APR_OFF_T_FMT) == 4 &&
823                  fmt[0] == APR_OFF_T_FMT[0] &&
824                  fmt[1] == APR_OFF_T_FMT[1]) ||
825                 (sizeof(APR_OFF_T_FMT) == 3 &&
826                  fmt[0] == APR_OFF_T_FMT[0]) ||
827                 (sizeof(APR_OFF_T_FMT) > 4 &&
828                  strncmp(fmt, APR_OFF_T_FMT, 
829                          sizeof(APR_OFF_T_FMT) - 2) == 0))) {
830                 /* Need to account for trailing 'd' and null in sizeof() */
831                 var_type = IS_QUAD;
832                 fmt += (sizeof(APR_OFF_T_FMT) - 2);
833             }
834             else if ((sizeof(APR_INT64_T_FMT) == 4 &&
835                  fmt[0] == APR_INT64_T_FMT[0] &&
836                  fmt[1] == APR_INT64_T_FMT[1]) ||
837                 (sizeof(APR_INT64_T_FMT) == 3 &&
838                  fmt[0] == APR_INT64_T_FMT[0]) ||
839                 (sizeof(APR_INT64_T_FMT) > 4 &&
840                  strncmp(fmt, APR_INT64_T_FMT, 
841                          sizeof(APR_INT64_T_FMT) - 2) == 0)) {
842                 /* Need to account for trailing 'd' and null in sizeof() */
843                 var_type = IS_QUAD;
844                 fmt += (sizeof(APR_INT64_T_FMT) - 2);
845             }
846             else if (*fmt == 'q') {
847                 var_type = IS_QUAD;
848                 fmt++;
849             }
850             else if (*fmt == 'l') {
851                 var_type = IS_LONG;
852                 fmt++;
853             }
854             else if (*fmt == 'h') {
855                 var_type = IS_SHORT;
856                 fmt++;
857             }
858             else {
859                 var_type = IS_INT;
860             }
861
862             /*
863              * Argument extraction and printing.
864              * First we determine the argument type.
865              * Then, we convert the argument to a string.
866              * On exit from the switch, s points to the string that
867              * must be printed, s_len has the length of the string
868              * The precision requirements, if any, are reflected in s_len.
869              *
870              * NOTE: pad_char may be set to '0' because of the 0 flag.
871              *   It is reset to ' ' by non-numeric formats
872              */
873             switch (*fmt) {
874             case 'u':
875                 if (var_type == IS_QUAD) {
876                     i_quad = va_arg(ap, apr_uint64_t);
877                     s = conv_10_quad(i_quad, 1, &is_negative,
878                             &num_buf[NUM_BUF_SIZE], &s_len);
879                 }
880                 else {
881                     if (var_type == IS_LONG)
882                         i_num = (apr_int32_t) va_arg(ap, apr_uint32_t);
883                     else if (var_type == IS_SHORT)
884                         i_num = (apr_int32_t) (unsigned short) va_arg(ap, unsigned int);
885                     else
886                         i_num = (apr_int32_t) va_arg(ap, unsigned int);
887                     s = conv_10(i_num, 1, &is_negative,
888                             &num_buf[NUM_BUF_SIZE], &s_len);
889                 }
890                 FIX_PRECISION(adjust_precision, precision, s, s_len);
891                 break;
892
893             case 'd':
894             case 'i':
895                 if (var_type == IS_QUAD) {
896                     i_quad = va_arg(ap, apr_int64_t);
897                     s = conv_10_quad(i_quad, 0, &is_negative,
898                             &num_buf[NUM_BUF_SIZE], &s_len);
899                 }
900                 else {
901                     if (var_type == IS_LONG)
902                         i_num = va_arg(ap, apr_int32_t);
903                     else if (var_type == IS_SHORT)
904                         i_num = (short) va_arg(ap, int);
905                     else
906                         i_num = va_arg(ap, int);
907                     s = conv_10(i_num, 0, &is_negative,
908                             &num_buf[NUM_BUF_SIZE], &s_len);
909                 }
910                 FIX_PRECISION(adjust_precision, precision, s, s_len);
911
912                 if (is_negative)
913                     prefix_char = '-';
914                 else if (print_sign)
915                     prefix_char = '+';
916                 else if (print_blank)
917                     prefix_char = ' ';
918                 break;
919
920
921             case 'o':
922                 if (var_type == IS_QUAD) {
923                     ui_quad = va_arg(ap, apr_uint64_t);
924                     s = conv_p2_quad(ui_quad, 3, *fmt,
925                             &num_buf[NUM_BUF_SIZE], &s_len);
926                 }
927                 else {
928                     if (var_type == IS_LONG)
929                         ui_num = va_arg(ap, apr_uint32_t);
930                     else if (var_type == IS_SHORT)
931                         ui_num = (unsigned short) va_arg(ap, unsigned int);
932                     else
933                         ui_num = va_arg(ap, unsigned int);
934                     s = conv_p2(ui_num, 3, *fmt,
935                             &num_buf[NUM_BUF_SIZE], &s_len);
936                 }
937                 FIX_PRECISION(adjust_precision, precision, s, s_len);
938                 if (alternate_form && *s != '0') {
939                     *--s = '0';
940                     s_len++;
941                 }
942                 break;
943
944
945             case 'x':
946             case 'X':
947                 if (var_type == IS_QUAD) {
948                     ui_quad = va_arg(ap, apr_uint64_t);
949                     s = conv_p2_quad(ui_quad, 4, *fmt,
950                             &num_buf[NUM_BUF_SIZE], &s_len);
951                 }
952                 else {
953                     if (var_type == IS_LONG)
954                         ui_num = va_arg(ap, apr_uint32_t);
955                     else if (var_type == IS_SHORT)
956                         ui_num = (unsigned short) va_arg(ap, unsigned int);
957                     else
958                         ui_num = va_arg(ap, unsigned int);
959                     s = conv_p2(ui_num, 4, *fmt,
960                             &num_buf[NUM_BUF_SIZE], &s_len);
961                 }
962                 FIX_PRECISION(adjust_precision, precision, s, s_len);
963                 if (alternate_form && ui_num != 0) {
964                     *--s = *fmt;        /* 'x' or 'X' */
965                     *--s = '0';
966                     s_len += 2;
967                 }
968                 break;
969
970
971             case 's':
972                 s = va_arg(ap, char *);
973                 if (s != NULL) {
974                     if (!adjust_precision) {
975                         s_len = strlen(s);
976                     }
977                     else {
978                         /* From the C library standard in section 7.9.6.1:
979                          * ...if the precision is specified, no more then
980                          * that many characters are written.  If the
981                          * precision is not specified or is greater
982                          * than the size of the array, the array shall
983                          * contain a null character.
984                          *
985                          * My reading is is precision is specified and
986                          * is less then or equal to the size of the
987                          * array, no null character is required.  So
988                          * we can't do a strlen.
989                          *
990                          * This figures out the length of the string
991                          * up to the precision.  Once it's long enough
992                          * for the specified precision, we don't care
993                          * anymore.
994                          *
995                          * NOTE: you must do the length comparison
996                          * before the check for the null character.
997                          * Otherwise, you'll check one beyond the
998                          * last valid character.
999                          */
1000                         const char *walk;
1001
1002                         for (walk = s, s_len = 0;
1003                              (s_len < precision) && (*walk != '\0');
1004                              ++walk, ++s_len);
1005                     }
1006                 }
1007                 else {
1008                     s = S_NULL;
1009                     s_len = S_NULL_LEN;
1010                 }
1011                 pad_char = ' ';
1012                 break;
1013
1014
1015             case 'f':
1016             case 'e':
1017             case 'E':
1018                 fp_num = va_arg(ap, double);
1019                 /*
1020                  * We use &num_buf[ 1 ], so that we have room for the sign
1021                  */
1022                 s = NULL;
1023 #ifdef HAVE_ISNAN
1024                 if (isnan(fp_num)) {
1025                     s = "nan";
1026                     s_len = 3;
1027                 }
1028 #endif
1029 #ifdef HAVE_ISINF
1030                 if (!s && isinf(fp_num)) {
1031                     s = "inf";
1032                     s_len = 3;
1033                 }
1034 #endif
1035                 if (!s) {
1036                     s = conv_fp(*fmt, fp_num, alternate_form,
1037                                 (int)((adjust_precision == NO) ? FLOAT_DIGITS : precision),
1038                                 &is_negative, &num_buf[1], &s_len);
1039                     if (is_negative)
1040                         prefix_char = '-';
1041                     else if (print_sign)
1042                         prefix_char = '+';
1043                     else if (print_blank)
1044                         prefix_char = ' ';
1045                 }
1046                 break;
1047
1048
1049             case 'g':
1050             case 'G':
1051                 if (adjust_precision == NO)
1052                     precision = FLOAT_DIGITS;
1053                 else if (precision == 0)
1054                     precision = 1;
1055                 /*
1056                  * * We use &num_buf[ 1 ], so that we have room for the sign
1057                  */
1058                 s = apr_gcvt(va_arg(ap, double), (int) precision, &num_buf[1],
1059                             alternate_form);
1060                 if (*s == '-')
1061                     prefix_char = *s++;
1062                 else if (print_sign)
1063                     prefix_char = '+';
1064                 else if (print_blank)
1065                     prefix_char = ' ';
1066
1067                 s_len = strlen(s);
1068
1069                 if (alternate_form && (q = strchr(s, '.')) == NULL) {
1070                     s[s_len++] = '.';
1071                     s[s_len] = '\0'; /* delimit for following strchr() */
1072                 }
1073                 if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
1074                     *q = 'E';
1075                 break;
1076
1077
1078             case 'c':
1079                 char_buf[0] = (char) (va_arg(ap, int));
1080                 s = &char_buf[0];
1081                 s_len = 1;
1082                 pad_char = ' ';
1083                 break;
1084
1085
1086             case '%':
1087                 char_buf[0] = '%';
1088                 s = &char_buf[0];
1089                 s_len = 1;
1090                 pad_char = ' ';
1091                 break;
1092
1093
1094             case 'n':
1095                 if (var_type == IS_QUAD)
1096                     *(va_arg(ap, apr_int64_t *)) = cc;
1097                 else if (var_type == IS_LONG)
1098                     *(va_arg(ap, long *)) = cc;
1099                 else if (var_type == IS_SHORT)
1100                     *(va_arg(ap, short *)) = cc;
1101                 else
1102                     *(va_arg(ap, int *)) = cc;
1103                 print_something = NO;
1104                 break;
1105
1106                 /*
1107                  * This is where we extend the printf format, with a second
1108                  * type specifier
1109                  */
1110             case 'p':
1111                 switch(*++fmt) {
1112                 /*
1113                  * If the pointer size is equal to or smaller than the size
1114                  * of the largest unsigned int, we convert the pointer to a
1115                  * hex number, otherwise we print "%p" to indicate that we
1116                  * don't handle "%p".
1117                  */
1118                 case 'p':
1119 #if APR_SIZEOF_VOIDP == 8
1120                     if (sizeof(void *) <= sizeof(apr_uint64_t)) {
1121                         ui_quad = (apr_uint64_t) va_arg(ap, void *);
1122                         s = conv_p2_quad(ui_quad, 4, 'x',
1123                                 &num_buf[NUM_BUF_SIZE], &s_len);
1124                     }
1125 #else
1126                     if (sizeof(void *) <= sizeof(apr_uint32_t)) {
1127                         ui_num = (apr_uint32_t) va_arg(ap, void *);
1128                         s = conv_p2(ui_num, 4, 'x',
1129                                 &num_buf[NUM_BUF_SIZE], &s_len);
1130                     }
1131 #endif
1132                     else {
1133                         s = "%p";
1134                         s_len = 2;
1135                         prefix_char = NUL;
1136                     }
1137                     pad_char = ' ';
1138                     break;
1139
1140                 /* print an apr_sockaddr_t as a.b.c.d:port */
1141                 case 'I':
1142                 {
1143                     apr_sockaddr_t *sa;
1144
1145                     sa = va_arg(ap, apr_sockaddr_t *);
1146                     if (sa != NULL) {
1147                         s = conv_apr_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len);
1148                         if (adjust_precision && precision < s_len)
1149                             s_len = precision;
1150                     }
1151                     else {
1152                         s = S_NULL;
1153                         s_len = S_NULL_LEN;
1154                     }
1155                     pad_char = ' ';
1156                 }
1157                 break;
1158
1159                 /* print a struct in_addr as a.b.c.d */
1160                 case 'A':
1161                 {
1162                     struct in_addr *ia;
1163
1164                     ia = va_arg(ap, struct in_addr *);
1165                     if (ia != NULL) {
1166                         s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
1167                         if (adjust_precision && precision < s_len)
1168                             s_len = precision;
1169                     }
1170                     else {
1171                         s = S_NULL;
1172                         s_len = S_NULL_LEN;
1173                     }
1174                     pad_char = ' ';
1175                 }
1176                 break;
1177
1178                 /* print the error for an apr_status_t */
1179                 case 'm':
1180                 {
1181                     apr_status_t *mrv;
1182
1183                     mrv = va_arg(ap, apr_status_t *);
1184                     if (mrv != NULL) {
1185                         s = apr_strerror(*mrv, num_buf, NUM_BUF_SIZE-1);
1186                         s_len = strlen(s);
1187                     }
1188                     else {
1189                         s = S_NULL;
1190                         s_len = S_NULL_LEN;
1191                     }
1192                     pad_char = ' ';
1193                 }
1194                 break;
1195
1196                 case 'T':
1197 #if APR_HAS_THREADS
1198                 {
1199                     apr_os_thread_t *tid;
1200
1201                     tid = va_arg(ap, apr_os_thread_t *);
1202                     if (tid != NULL) {
1203                         s = conv_os_thread_t(tid, &num_buf[NUM_BUF_SIZE], &s_len);
1204                         if (adjust_precision && precision < s_len)
1205                             s_len = precision;
1206                     }
1207                     else {
1208                         s = S_NULL;
1209                         s_len = S_NULL_LEN;
1210                     }
1211                     pad_char = ' ';
1212                 }
1213 #else
1214                     char_buf[0] = '0';
1215                     s = &char_buf[0];
1216                     s_len = 1;
1217                     pad_char = ' ';
1218 #endif
1219                     break;
1220
1221                 case 't':
1222 #if APR_HAS_THREADS
1223                 {
1224                     apr_os_thread_t *tid;
1225
1226                     tid = va_arg(ap, apr_os_thread_t *);
1227                     if (tid != NULL) {
1228                         s = conv_os_thread_t_hex(tid, &num_buf[NUM_BUF_SIZE], &s_len);
1229                         if (adjust_precision && precision < s_len)
1230                             s_len = precision;
1231                     }
1232                     else {
1233                         s = S_NULL;
1234                         s_len = S_NULL_LEN;
1235                     }
1236                     pad_char = ' ';
1237                 }
1238 #else
1239                     char_buf[0] = '0';
1240                     s = &char_buf[0];
1241                     s_len = 1;
1242                     pad_char = ' ';
1243 #endif
1244                     break;
1245
1246                 case 'B':
1247                 case 'F':
1248                 case 'S':
1249                 {
1250                     apr_off_t size = 0;
1251
1252                     if (*fmt == 'B') {
1253                         apr_uint32_t *arg = va_arg(ap, apr_uint32_t *);
1254                         size = (arg) ? *arg : 0;
1255                     }
1256                     else if (*fmt == 'F') {
1257                         apr_off_t *arg = va_arg(ap, apr_off_t *);
1258                         size = (arg) ? *arg : 0;
1259                     }
1260                     else {
1261                         apr_size_t *arg = va_arg(ap, apr_size_t *);
1262                         size = (arg) ? *arg : 0;
1263                     }
1264
1265                     s = apr_strfsize(size, buf);
1266                     s_len = strlen(s);
1267                     pad_char = ' ';
1268                 }
1269                 break;
1270
1271                 case NUL:
1272                     /* if %p ends the string, oh well ignore it */
1273                     continue;
1274
1275                 default:
1276                     s = "bogus %p";
1277                     s_len = 8;
1278                     prefix_char = NUL;
1279                     (void)va_arg(ap, void *); /* skip the bogus argument on the stack */
1280                     break;
1281                 }
1282                 break;
1283
1284             case NUL:
1285                 /*
1286                  * The last character of the format string was %.
1287                  * We ignore it.
1288                  */
1289                 continue;
1290
1291
1292                 /*
1293                  * The default case is for unrecognized %'s.
1294                  * We print %<char> to help the user identify what
1295                  * option is not understood.
1296                  * This is also useful in case the user wants to pass
1297                  * the output of format_converter to another function
1298                  * that understands some other %<char> (like syslog).
1299                  * Note that we can't point s inside fmt because the
1300                  * unknown <char> could be preceded by width etc.
1301                  */
1302             default:
1303                 char_buf[0] = '%';
1304                 char_buf[1] = *fmt;
1305                 s = char_buf;
1306                 s_len = 2;
1307                 pad_char = ' ';
1308                 break;
1309             }
1310
1311             if (prefix_char != NUL && s != S_NULL && s != char_buf) {
1312                 *--s = prefix_char;
1313                 s_len++;
1314             }
1315
1316             if (adjust_width && adjust == RIGHT && min_width > s_len) {
1317                 if (pad_char == '0' && prefix_char != NUL) {
1318                     INS_CHAR(*s, sp, bep, cc);
1319                     s++;
1320                     s_len--;
1321                     min_width--;
1322                 }
1323                 PAD(min_width, s_len, pad_char);
1324             }
1325
1326             /*
1327              * Print the string s. 
1328              */
1329             if (print_something == YES) {
1330                 for (i = s_len; i != 0; i--) {
1331                       INS_CHAR(*s, sp, bep, cc);
1332                     s++;
1333                 }
1334             }
1335
1336             if (adjust_width && adjust == LEFT && min_width > s_len)
1337                 PAD(min_width, s_len, pad_char);
1338         }
1339         fmt++;
1340     }
1341     vbuff->curpos = sp;
1342
1343     return cc;
1344 }
1345
1346
1347 static int snprintf_flush(apr_vformatter_buff_t *vbuff)
1348 {
1349     /* if the buffer fills we have to abort immediately, there is no way
1350      * to "flush" an apr_snprintf... there's nowhere to flush it to.
1351      */
1352     return -1;
1353 }
1354
1355
1356 APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, 
1357                                      const char *format, ...)
1358 {
1359     int cc;
1360     va_list ap;
1361     apr_vformatter_buff_t vbuff;
1362
1363     if (len == 0) {
1364         /* NOTE: This is a special case; we just want to return the number
1365          * of chars that would be written (minus \0) if the buffer
1366          * size was infinite. We leverage the fact that INS_CHAR
1367          * just does actual inserts iff the buffer pointer is non-NULL.
1368          * In this case, we don't care what buf is; it can be NULL, since
1369          * we don't touch it at all.
1370          */
1371         vbuff.curpos = NULL;
1372         vbuff.endpos = NULL;
1373     } else {
1374         /* save one byte for nul terminator */
1375         vbuff.curpos = buf;
1376         vbuff.endpos = buf + len - 1;
1377     }
1378     va_start(ap, format);
1379     cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);
1380     va_end(ap);
1381     if (len != 0) {
1382         *vbuff.curpos = '\0';
1383     }
1384     return (cc == -1) ? (int)len - 1 : cc;
1385 }
1386
1387
1388 APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format,
1389                                va_list ap)
1390 {
1391     int cc;
1392     apr_vformatter_buff_t vbuff;
1393
1394     if (len == 0) {
1395         /* See above note */
1396         vbuff.curpos = NULL;
1397         vbuff.endpos = NULL;
1398     } else {
1399         /* save one byte for nul terminator */
1400         vbuff.curpos = buf;
1401         vbuff.endpos = buf + len - 1;
1402     }
1403     cc = apr_vformatter(snprintf_flush, &vbuff, format, ap);
1404     if (len != 0) {
1405         *vbuff.curpos = '\0';
1406     }
1407     return (cc == -1) ? (int)len - 1 : cc;
1408 }