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