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    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
161static 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
166static 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
176static 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)                         \
296do                                                  \
297{                                                   \
298    INS_CHAR(ch, sp, bep, cc);                      \
299    width--;                                        \
300}                                                   \
301while (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 */
330static 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
373static 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
425static 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. */
447static 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
487static 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 */
517static 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 */
616static 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
635static 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
658static 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 */
683APR_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
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                    char buf[5];
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
1347static 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
1356APR_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
1388APR_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}
1409