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 /*
18  * This code is based on, and used with the permission of, the
19  * SIO stdio-replacement strx_* functions by Panos Tsirigotis
20  * <panos@alumni.cs.colorado.edu> for xinetd.
21  */
22 
23 #include "config.h"
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <sys/types.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <math.h>
31 #include <netinet/in.h>
32 
33 #ifdef HAVE_LIMITS_H
34 #include <limits.h>
35 #endif
36 
37 typedef struct {
38     char *curpos;
39     char *endpos;
40 } ap_vformatter_buff;
41 
42 
43 #define API_EXPORT(type) type
44 #define API_EXPORT_NONSTD(type) type
45 
46 #define ap_isalnum(c) (isalnum(((unsigned char)(c))))
47 #define ap_isalpha(c) (isalpha(((unsigned char)(c))))
48 #define ap_iscntrl(c) (iscntrl(((unsigned char)(c))))
49 #define ap_isdigit(c) (isdigit(((unsigned char)(c))))
50 #define ap_isgraph(c) (isgraph(((unsigned char)(c))))
51 #define ap_islower(c) (islower(((unsigned char)(c))))
52 #define ap_isprint(c) (isprint(((unsigned char)(c))))
53 #define ap_ispunct(c) (ispunct(((unsigned char)(c))))
54 #define ap_isspace(c) (isspace(((unsigned char)(c))))
55 #define ap_isupper(c) (isupper(((unsigned char)(c))))
56 #define ap_isxdigit(c) (isxdigit(((unsigned char)(c))))
57 #define ap_tolower(c) (tolower(((unsigned char)(c))))
58 #define ap_toupper(c) (toupper(((unsigned char)(c))))
59 
60 
61 typedef enum {
62     NO = 0, YES = 1
63 } boolean_e;
64 
65 #ifndef FALSE
66 #define FALSE                           0
67 #endif
68 #ifndef TRUE
69 #define TRUE                            1
70 #endif
71 #ifndef AP_LONGEST_LONG
72 #define AP_LONGEST_LONG                 long
73 #endif
74 #define NUL                             '\0'
75 #define WIDE_INT              long
76 #define WIDEST_INT            AP_LONGEST_LONG
77 
78 typedef WIDE_INT wide_int;
79 typedef unsigned WIDE_INT u_wide_int;
80 typedef WIDEST_INT widest_int;
81 #ifdef __TANDEM
82 /* Although Tandem supports "long long" there is no unsigned variant. */
83 typedef unsigned long       u_widest_int;
84 #else
85 typedef unsigned WIDEST_INT u_widest_int;
86 #endif
87 typedef int bool_int;
88 
89 #define S_NULL                          "(null)"
90 #define S_NULL_LEN            6
91 
92 #define FLOAT_DIGITS                    6
93 #define EXPONENT_LENGTH                 10
94 
95 /*
96  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
97  *
98  * XXX: this is a magic number; do not decrease it
99  */
100 #define NUM_BUF_SIZE                    512
101 
102 /*
103  * cvt.c - IEEE floating point formatting routines for FreeBSD
104  * from GNU libc-4.6.27.  Modified to be thread safe.
105  */
106 
107 /*
108  *    ap_ecvt converts to decimal
109  *      the number of digits is specified by ndigit
110  *      decpt is set to the position of the decimal point
111  *      sign is set to 0 for positive, 1 for negative
112  */
113 
114 #define   NDIG      80
115 
116 /* buf must have at least NDIG bytes */
ap_cvt(double arg,int ndigits,int * decpt,int * sign,int eflag,char * buf)117 static char *ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf)
118 {
119     register int r2;
120     double fi, fj;
121     register char *p, *p1;
122 
123     if (ndigits >= NDIG - 1)
124           ndigits = NDIG - 2;
125     r2 = 0;
126     *sign = 0;
127     p = &buf[0];
128     if (arg < 0) {
129           *sign = 1;
130           arg = -arg;
131     }
132     arg = modf(arg, &fi);
133     p1 = &buf[NDIG];
134     /*
135      * Do integer part
136      */
137     if (fi != 0) {
138           p1 = &buf[NDIG];
139           while (p1 > &buf[0] && fi != 0) {
140               fj = modf(fi / 10, &fi);
141               *--p1 = (int) ((fj + .03) * 10) + '0';
142               r2++;
143           }
144           while (p1 < &buf[NDIG])
145               *p++ = *p1++;
146     }
147     else if (arg > 0) {
148           while ((fj = arg * 10) < 1) {
149               arg = fj;
150               r2--;
151           }
152     }
153     p1 = &buf[ndigits];
154     if (eflag == 0)
155           p1 += r2;
156     *decpt = r2;
157     if (p1 < &buf[0]) {
158           buf[0] = '\0';
159           return (buf);
160     }
161     while (p <= p1 && p < &buf[NDIG]) {
162           arg *= 10;
163           arg = modf(arg, &fj);
164           *p++ = (int) fj + '0';
165     }
166     if (p1 >= &buf[NDIG]) {
167           buf[NDIG - 1] = '\0';
168           return (buf);
169     }
170     p = p1;
171     *p1 += 5;
172     while (*p1 > '9') {
173           *p1 = '0';
174           if (p1 > buf)
175               ++ * --p1;
176           else {
177               *p1 = '1';
178               (*decpt)++;
179               if (eflag == 0) {
180                     if (p > buf)
181                         *p = '0';
182                     p++;
183               }
184           }
185     }
186     *p = '\0';
187     return (buf);
188 }
189 
ap_ecvt(double arg,int ndigits,int * decpt,int * sign,char * buf)190 static char *ap_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
191 {
192     return (ap_cvt(arg, ndigits, decpt, sign, 1, buf));
193 }
194 
ap_fcvt(double arg,int ndigits,int * decpt,int * sign,char * buf)195 static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
196 {
197     return (ap_cvt(arg, ndigits, decpt, sign, 0, buf));
198 }
199 
200 /*
201  * ap_gcvt  - Floating output conversion to
202  * minimal length string
203  */
204 
ap_gcvt(double number,int ndigit,char * buf,boolean_e altform)205 static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
206 {
207     int sign, decpt;
208     register char *p1, *p2;
209     register int i;
210     char buf1[NDIG];
211 
212     p1 = ap_ecvt(number, ndigit, &decpt, &sign, buf1);
213     p2 = buf;
214     if (sign)
215           *p2++ = '-';
216     for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
217           ndigit--;
218     if ((decpt >= 0 && decpt - ndigit > 4)
219           || (decpt < 0 && decpt < -3)) {                   /* use E-style */
220           decpt--;
221           *p2++ = *p1++;
222           *p2++ = '.';
223           for (i = 1; i < ndigit; i++)
224               *p2++ = *p1++;
225           *p2++ = 'e';
226           if (decpt < 0) {
227               decpt = -decpt;
228               *p2++ = '-';
229           }
230           else
231               *p2++ = '+';
232           if (decpt / 100 > 0)
233               *p2++ = decpt / 100 + '0';
234           if (decpt / 10 > 0)
235               *p2++ = (decpt % 100) / 10 + '0';
236           *p2++ = decpt % 10 + '0';
237     }
238     else {
239           if (decpt <= 0) {
240               if (*p1 != '0')
241                     *p2++ = '.';
242               while (decpt < 0) {
243                     decpt++;
244                     *p2++ = '0';
245               }
246           }
247           for (i = 1; i <= ndigit; i++) {
248               *p2++ = *p1++;
249               if (i == decpt)
250                     *p2++ = '.';
251           }
252           if (ndigit < decpt) {
253               while (ndigit++ < decpt)
254                     *p2++ = '0';
255               *p2++ = '.';
256           }
257     }
258     if (p2[-1] == '.' && !altform)
259           p2--;
260     *p2 = '\0';
261     return (buf);
262 }
263 
264 /*
265  * The INS_CHAR macro inserts a character in the buffer and writes
266  * the buffer back to disk if necessary
267  * It uses the char pointers sp and bep:
268  *      sp points to the next available character in the buffer
269  *      bep points to the end-of-buffer+1
270  * While using this macro, note that the nextb pointer is NOT updated.
271  *
272  * NOTE: Evaluation of the c argument should not have any side-effects
273  */
274 #define INS_CHAR(c, sp, bep, cc)                                      \
275               {                                                                 \
276                     if (sp >= bep) {                                  \
277                         vbuff->curpos = sp;                         \
278                         if (flush_func(vbuff))                        \
279                               return -1;                                        \
280                         sp = vbuff->curpos;                                     \
281                         bep = vbuff->endpos;                          \
282                     }                                                           \
283                     *sp++ = (c);                                                \
284                     cc++;                                                       \
285               }
286 
287 #define NUM( c )                        ( c - '0' )
288 
289 #define STR_TO_DEC( str, num )                    \
290     num = NUM( *str++ ) ;               \
291     while ( ap_isdigit( *str ) )                  \
292     {                                             \
293           num *= 10 ;                             \
294           num += NUM( *str++ ) ;                  \
295     }
296 
297 /*
298  * This macro does zero padding so that the precision
299  * requirement is satisfied. The padding is done by
300  * adding '0's to the left of the string that is going
301  * to be printed. We don't allow precision to be large
302  * enough that we continue past the start of s.
303  *
304  * NOTE: this makes use of the magic info that s is
305  * always based on num_buf with a size of NUM_BUF_SIZE.
306  */
307 #define FIX_PRECISION( adjust, precision, s, s_len )        \
308     if ( adjust ) {                                         \
309         int p = precision < NUM_BUF_SIZE - 1 ? precision : NUM_BUF_SIZE - 1; \
310           while ( s_len < p )                               \
311           {                                                           \
312               *--s = '0' ;                                  \
313               s_len++ ;                                               \
314           }                                                           \
315     }
316 
317 /*
318  * Macro that does padding. The padding is done by printing
319  * the character ch.
320  */
321 #define PAD( width, len, ch ) do                  \
322           {                                                 \
323               INS_CHAR( ch, sp, bep, cc ) ;       \
324               width-- ;                                     \
325           }                                                 \
326           while ( width > len )
327 
328 /*
329  * Prefix the character ch to the string str
330  * Increase length
331  * Set the has_prefix flag
332  */
333 #define PREFIX( str, length, ch )        *--str = ch ; length++ ; has_prefix = YES
334 
335 
336 /*
337  * Convert num to its decimal format.
338  * Return value:
339  *   - a pointer to a string containing the number (no sign)
340  *   - len contains the length of the string
341  *   - is_negative is set to TRUE or FALSE depending on the sign
342  *     of the number (always set to FALSE if is_unsigned is TRUE)
343  *
344  * The caller provides a buffer for the string: that is the buf_end argument
345  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
346  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
347  *
348  * Note: we have 2 versions. One is used when we need to use quads
349  * (conv_10_quad), the other when we don't (conv_10). We're assuming the
350  * latter is faster.
351  */
conv_10(register wide_int num,register bool_int is_unsigned,register bool_int * is_negative,char * buf_end,register int * len)352 static char *conv_10(register wide_int num, register bool_int is_unsigned,
353                          register bool_int *is_negative, char *buf_end,
354                          register int *len)
355 {
356     register char *p = buf_end;
357     register u_wide_int magnitude;
358 
359     if (is_unsigned) {
360           magnitude = (u_wide_int) num;
361           *is_negative = FALSE;
362     }
363     else {
364           *is_negative = (num < 0);
365 
366           /*
367            * On a 2's complement machine, negating the most negative integer
368            * results in a number that cannot be represented as a signed integer.
369            * Here is what we do to obtain the number's magnitude:
370            *      a. add 1 to the number
371            *      b. negate it (becomes positive)
372            *      c. convert it to unsigned
373            *      d. add 1
374            */
375           if (*is_negative) {
376               wide_int t = num + 1;
377 
378               magnitude = ((u_wide_int) -t) + 1;
379           }
380           else
381               magnitude = (u_wide_int) num;
382     }
383 
384     /*
385      * We use a do-while loop so that we write at least 1 digit
386      */
387     do {
388           register u_wide_int new_magnitude = magnitude / 10;
389 
390           *--p = (char) (magnitude - new_magnitude * 10 + '0');
391           magnitude = new_magnitude;
392     }
393     while (magnitude);
394 
395     *len = buf_end - p;
396     return (p);
397 }
398 
conv_10_quad(widest_int num,register bool_int is_unsigned,register bool_int * is_negative,char * buf_end,register int * len)399 static char *conv_10_quad(widest_int num, register bool_int is_unsigned,
400                          register bool_int *is_negative, char *buf_end,
401                          register int *len)
402 {
403     register char *p = buf_end;
404     u_widest_int magnitude;
405 
406     /*
407      * We see if we can use the faster non-quad version by checking the
408      * number against the largest long value it can be. If <=, we
409      * punt to the quicker version.
410      */
411     if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned))
412           return(conv_10( (wide_int)num, is_unsigned, is_negative,
413                  buf_end, len));
414 
415     if (is_unsigned) {
416           magnitude = (u_widest_int) num;
417           *is_negative = FALSE;
418     }
419     else {
420           *is_negative = (num < 0);
421 
422           /*
423            * On a 2's complement machine, negating the most negative integer
424            * results in a number that cannot be represented as a signed integer.
425            * Here is what we do to obtain the number's magnitude:
426            *      a. add 1 to the number
427            *      b. negate it (becomes positive)
428            *      c. convert it to unsigned
429            *      d. add 1
430            */
431           if (*is_negative) {
432               widest_int t = num + 1;
433 
434               magnitude = ((u_widest_int) -t) + 1;
435           }
436           else
437               magnitude = (u_widest_int) num;
438     }
439 
440     /*
441      * We use a do-while loop so that we write at least 1 digit
442      */
443     do {
444           u_widest_int new_magnitude = magnitude / 10;
445 
446           *--p = (char) (magnitude - new_magnitude * 10 + '0');
447           magnitude = new_magnitude;
448     }
449     while (magnitude);
450 
451     *len = buf_end - p;
452     return (p);
453 }
454 
455 
456 
conv_in_addr(struct in_addr * ia,char * buf_end,int * len)457 static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
458 {
459     unsigned addr = ntohl(ia->s_addr);
460     char *p = buf_end;
461     bool_int is_negative;
462     int sub_len;
463 
464     p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
465     *--p = '.';
466     p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
467     *--p = '.';
468     p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
469     *--p = '.';
470     p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
471 
472     *len = buf_end - p;
473     return (p);
474 }
475 
476 
477 
conv_sockaddr_in(struct sockaddr_in * si,char * buf_end,int * len)478 static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
479 {
480     char *p = buf_end;
481     bool_int is_negative;
482     int sub_len;
483 
484     p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
485     *--p = ':';
486     p = conv_in_addr(&si->sin_addr, p, &sub_len);
487 
488     *len = buf_end - p;
489     return (p);
490 }
491 
492 
493 
494 /*
495  * Convert a floating point number to a string formats 'f', 'e' or 'E'.
496  * The result is placed in buf, and len denotes the length of the string
497  * The sign is returned in the is_negative argument (and is not placed
498  * in buf).
499  */
conv_fp(register char format,register double num,boolean_e add_dp,int precision,bool_int * is_negative,char * buf,int * len)500 static char *conv_fp(register char format, register double num,
501     boolean_e add_dp, int precision, bool_int *is_negative,
502     char *buf, int *len)
503 {
504     register char *s = buf;
505     register char *p;
506     int decimal_point;
507     char buf1[NDIG];
508 
509     if (format == 'f')
510           p = ap_fcvt(num, precision, &decimal_point, is_negative, buf1);
511     else                      /* either e or E format */
512           p = ap_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
513 
514     /*
515      * Check for Infinity and NaN
516      */
517     if (ap_isalpha(*p)) {
518           *len = strlen(strcpy(buf, p));
519           *is_negative = FALSE;
520           return (buf);
521     }
522 
523     if (format == 'f') {
524           if (decimal_point <= 0) {
525               *s++ = '0';
526               if (precision > 0) {
527                     *s++ = '.';
528                     while (decimal_point++ < 0)
529                         *s++ = '0';
530               }
531               else if (add_dp)
532                     *s++ = '.';
533           }
534           else {
535               while (decimal_point-- > 0)
536                     *s++ = *p++;
537               if (precision > 0 || add_dp)
538                     *s++ = '.';
539           }
540     }
541     else {
542           *s++ = *p++;
543           if (precision > 0 || add_dp)
544               *s++ = '.';
545     }
546 
547     /*
548      * copy the rest of p, the NUL is NOT copied
549      */
550     while (*p)
551           *s++ = *p++;
552 
553     if (format != 'f') {
554           char temp[EXPONENT_LENGTH];   /* for exponent conversion */
555           int t_len;
556           bool_int exponent_is_negative;
557 
558           *s++ = format;                /* either e or E */
559           decimal_point--;
560           if (decimal_point != 0) {
561               p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative,
562                               &temp[EXPONENT_LENGTH], &t_len);
563               *s++ = exponent_is_negative ? '-' : '+';
564 
565               /*
566                * Make sure the exponent has at least 2 digits
567                */
568               if (t_len == 1)
569                     *s++ = '0';
570               while (t_len--)
571                     *s++ = *p++;
572           }
573           else {
574               *s++ = '+';
575               *s++ = '0';
576               *s++ = '0';
577           }
578     }
579 
580     *len = s - buf;
581     return (buf);
582 }
583 
584 
585 /*
586  * Convert num to a base X number where X is a power of 2. nbits determines X.
587  * For example, if nbits is 3, we do base 8 conversion
588  * Return value:
589  *      a pointer to a string containing the number
590  *
591  * The caller provides a buffer for the string: that is the buf_end argument
592  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
593  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
594  *
595  * As with conv_10, we have a faster version which is used when
596  * the number isn't quad size.
597  */
conv_p2(register u_wide_int num,register int nbits,char format,char * buf_end,register int * len)598 static char *conv_p2(register u_wide_int num, register int nbits,
599                          char format, char *buf_end, register int *len)
600 {
601     register int mask = (1 << nbits) - 1;
602     register char *p = buf_end;
603     static const char low_digits[] = "0123456789abcdef";
604     static const char upper_digits[] = "0123456789ABCDEF";
605     register const char *digits = (format == 'X') ? upper_digits : low_digits;
606 
607     do {
608           *--p = digits[num & mask];
609           num >>= nbits;
610     }
611     while (num);
612 
613     *len = buf_end - p;
614     return (p);
615 }
616 
conv_p2_quad(u_widest_int num,register int nbits,char format,char * buf_end,register int * len)617 static char *conv_p2_quad(u_widest_int num, register int nbits,
618                          char format, char *buf_end, register int *len)
619 {
620     register int mask = (1 << nbits) - 1;
621     register char *p = buf_end;
622     static const char low_digits[] = "0123456789abcdef";
623     static const char upper_digits[] = "0123456789ABCDEF";
624     register const char *digits = (format == 'X') ? upper_digits : low_digits;
625 
626     if (num <= ULONG_MAX)
627           return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));
628 
629     do {
630           *--p = digits[num & mask];
631           num >>= nbits;
632     }
633     while (num);
634 
635     *len = buf_end - p;
636     return (p);
637 }
638 
639 
640 /*
641  * Do format conversion placing the output in buffer
642  */
ap_vformatter(int (* flush_func)(ap_vformatter_buff *),ap_vformatter_buff * vbuff,const char * fmt,va_list ap)643 API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
644     ap_vformatter_buff *vbuff, const char *fmt, va_list ap)
645 {
646     register char *sp;
647     register char *bep;
648     register int cc = 0;
649     register int i;
650 
651     register char *s = NULL;
652     char *q;
653     int s_len;
654 
655     register int min_width = 0;
656     int precision = 0;
657     enum {
658           LEFT, RIGHT
659     } adjust;
660     char pad_char;
661     char prefix_char;
662 
663     double fp_num;
664     widest_int i_quad = (widest_int) 0;
665     u_widest_int ui_quad;
666     wide_int i_num = (wide_int) 0;
667     u_wide_int ui_num;
668 
669     char num_buf[NUM_BUF_SIZE];
670     char char_buf[2];                   /* for printing %% and %<unknown> */
671 
672     enum var_type_enum {
673           IS_QUAD, IS_LONG, IS_SHORT, IS_INT
674     };
675     enum var_type_enum var_type = IS_INT;
676 
677     /*
678      * Flag variables
679      */
680     boolean_e alternate_form;
681     boolean_e print_sign;
682     boolean_e print_blank;
683     boolean_e adjust_precision;
684     boolean_e adjust_width;
685     bool_int is_negative;
686 
687     sp = vbuff->curpos;
688     bep = vbuff->endpos;
689 
690     while (*fmt) {
691           if (*fmt != '%') {
692               INS_CHAR(*fmt, sp, bep, cc);
693           }
694           else {
695               /*
696                * Default variable settings
697                */
698               adjust = RIGHT;
699               alternate_form = print_sign = print_blank = NO;
700               pad_char = ' ';
701               prefix_char = NUL;
702 
703               fmt++;
704 
705               /*
706                * Try to avoid checking for flags, width or precision
707                */
708               if (!ap_islower(*fmt)) {
709                     /*
710                      * Recognize flags: -, #, BLANK, +
711                      */
712                     for (;; fmt++) {
713                         if (*fmt == '-')
714                               adjust = LEFT;
715                         else if (*fmt == '+')
716                               print_sign = YES;
717                         else if (*fmt == '#')
718                               alternate_form = YES;
719                         else if (*fmt == ' ')
720                               print_blank = YES;
721                         else if (*fmt == '0')
722                               pad_char = '0';
723                         else
724                               break;
725                     }
726 
727                     /*
728                      * Check if a width was specified
729                      */
730                     if (ap_isdigit(*fmt)) {
731                         STR_TO_DEC(fmt, min_width);
732                         adjust_width = YES;
733                     }
734                     else if (*fmt == '*') {
735                         min_width = va_arg(ap, int);
736                         fmt++;
737                         adjust_width = YES;
738                         if (min_width < 0) {
739                               adjust = LEFT;
740                               min_width = -min_width;
741                         }
742                     }
743                     else
744                         adjust_width = NO;
745 
746                     /*
747                      * Check if a precision was specified
748                      */
749                     if (*fmt == '.') {
750                         adjust_precision = YES;
751                         fmt++;
752                         if (ap_isdigit(*fmt)) {
753                               STR_TO_DEC(fmt, precision);
754                         }
755                         else if (*fmt == '*') {
756                               precision = va_arg(ap, int);
757                               fmt++;
758                               if (precision < 0)
759                                   precision = 0;
760                         }
761                         else
762                               precision = 0;
763                     }
764                     else
765                         adjust_precision = NO;
766               }
767               else
768                     adjust_precision = adjust_width = NO;
769 
770               /*
771                * Modifier check
772                */
773               if (*fmt == 'q') {
774                     var_type = IS_QUAD;
775                     fmt++;
776               }
777               else if (*fmt == 'l') {
778                     var_type = IS_LONG;
779                     fmt++;
780               }
781               else if (*fmt == 'h') {
782                     var_type = IS_SHORT;
783                     fmt++;
784               }
785               else {
786                     var_type = IS_INT;
787               }
788 
789               /*
790                * Argument extraction and printing.
791                * First we determine the argument type.
792                * Then, we convert the argument to a string.
793                * On exit from the switch, s points to the string that
794                * must be printed, s_len has the length of the string
795                * The precision requirements, if any, are reflected in s_len.
796                *
797                * NOTE: pad_char may be set to '0' because of the 0 flag.
798                *   It is reset to ' ' by non-numeric formats
799                */
800               switch (*fmt) {
801               case 'u':
802                     if (var_type == IS_QUAD) {
803                         i_quad = va_arg(ap, u_widest_int);
804                         s = conv_10_quad(i_quad, 1, &is_negative,
805                                   &num_buf[NUM_BUF_SIZE], &s_len);
806                     }
807                     else {
808                         if (var_type == IS_LONG)
809                               i_num = (wide_int) va_arg(ap, u_wide_int);
810                         else if (var_type == IS_SHORT)
811                               i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);
812                         else
813                               i_num = (wide_int) va_arg(ap, unsigned int);
814                         s = conv_10(i_num, 1, &is_negative,
815                                   &num_buf[NUM_BUF_SIZE], &s_len);
816                     }
817                     FIX_PRECISION(adjust_precision, precision, s, s_len);
818                     break;
819 
820               case 'd':
821               case 'i':
822                     if (var_type == IS_QUAD) {
823                         i_quad = va_arg(ap, widest_int);
824                         s = conv_10_quad(i_quad, 0, &is_negative,
825                                   &num_buf[NUM_BUF_SIZE], &s_len);
826                     }
827                     else {
828                         if (var_type == IS_LONG)
829                               i_num = (wide_int) va_arg(ap, wide_int);
830                         else if (var_type == IS_SHORT)
831                               i_num = (wide_int) (short) va_arg(ap, int);
832                         else
833                               i_num = (wide_int) va_arg(ap, int);
834                         s = conv_10(i_num, 0, &is_negative,
835                                   &num_buf[NUM_BUF_SIZE], &s_len);
836                     }
837                     FIX_PRECISION(adjust_precision, precision, s, s_len);
838 
839                     if (is_negative)
840                         prefix_char = '-';
841                     else if (print_sign)
842                         prefix_char = '+';
843                     else if (print_blank)
844                         prefix_char = ' ';
845                     break;
846 
847 
848               case 'o':
849                     if (var_type == IS_QUAD) {
850                         ui_quad = va_arg(ap, u_widest_int);
851                         s = conv_p2_quad(ui_quad, 3, *fmt,
852                                   &num_buf[NUM_BUF_SIZE], &s_len);
853                     }
854                     else {
855                         if (var_type == IS_LONG)
856                               ui_num = (u_wide_int) va_arg(ap, u_wide_int);
857                         else if (var_type == IS_SHORT)
858                               ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
859                         else
860                               ui_num = (u_wide_int) va_arg(ap, unsigned int);
861                         s = conv_p2(ui_num, 3, *fmt,
862                                   &num_buf[NUM_BUF_SIZE], &s_len);
863                     }
864                     FIX_PRECISION(adjust_precision, precision, s, s_len);
865                     if (alternate_form && *s != '0') {
866                         *--s = '0';
867                         s_len++;
868                     }
869                     break;
870 
871 
872               case 'x':
873               case 'X':
874                     if (var_type == IS_QUAD) {
875                         ui_quad = va_arg(ap, u_widest_int);
876                         s = conv_p2_quad(ui_quad, 4, *fmt,
877                                   &num_buf[NUM_BUF_SIZE], &s_len);
878                     }
879                     else {
880                         if (var_type == IS_LONG)
881                               ui_num = (u_wide_int) va_arg(ap, u_wide_int);
882                         else if (var_type == IS_SHORT)
883                               ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
884                         else
885                               ui_num = (u_wide_int) va_arg(ap, unsigned int);
886                         s = conv_p2(ui_num, 4, *fmt,
887                                   &num_buf[NUM_BUF_SIZE], &s_len);
888                     }
889                     FIX_PRECISION(adjust_precision, precision, s, s_len);
890                     if (alternate_form && i_num != 0) {
891                         *--s = *fmt;    /* 'x' or 'X' */
892                         *--s = '0';
893                         s_len += 2;
894                     }
895                     break;
896 
897 
898               case 's':
899                     s = va_arg(ap, char *);
900                     if (s != NULL) {
901                         s_len = strlen(s);
902                         if (adjust_precision && precision < s_len)
903                               s_len = precision;
904                     }
905                     else {
906                         s = S_NULL;
907                         s_len = S_NULL_LEN;
908                     }
909                     pad_char = ' ';
910                     break;
911 
912 
913               case 'f':
914               case 'e':
915               case 'E':
916                     fp_num = va_arg(ap, double);
917                     /*
918                      * * We use &num_buf[ 1 ], so that we have room for the sign
919                      */
920 #ifdef HAVE_ISNAN
921                     if (isnan(fp_num)) {
922                         s = "nan";
923                         s_len = 3;
924                     }
925                     else
926 #endif
927 #ifdef HAVE_ISINF
928                     if (isinf(fp_num)) {
929                         s = "inf";
930                         s_len = 3;
931                     }
932                     else
933 #endif
934                     {
935                         s = conv_fp(*fmt, fp_num, alternate_form,
936                                   (adjust_precision == NO) ? FLOAT_DIGITS : precision,
937                                         &is_negative, &num_buf[1], &s_len);
938                         if (is_negative)
939                               prefix_char = '-';
940                         else if (print_sign)
941                               prefix_char = '+';
942                         else if (print_blank)
943                               prefix_char = ' ';
944                     }
945                   break;
946 
947 
948               case 'g':
949               case 'G':
950                     if (adjust_precision == NO)
951                         precision = FLOAT_DIGITS;
952                     else if (precision == 0)
953                         precision = 1;
954                     /*
955                      * * We use &num_buf[ 1 ], so that we have room for the sign
956                      */
957                     s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],
958                                 alternate_form);
959                     if (*s == '-')
960                         prefix_char = *s++;
961                     else if (print_sign)
962                         prefix_char = '+';
963                     else if (print_blank)
964                         prefix_char = ' ';
965 
966                     s_len = strlen(s);
967 
968                     if (alternate_form && (q = strchr(s, '.')) == NULL) {
969                         s[s_len++] = '.';
970                         s[s_len] = '\0'; /* delimit for following strchr() */
971                     }
972                     if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
973                         *q = 'E';
974                     break;
975 
976 
977               case 'c':
978                     char_buf[0] = (char) (va_arg(ap, int));
979                     s = &char_buf[0];
980                     s_len = 1;
981                     pad_char = ' ';
982                     break;
983 
984 
985               case '%':
986                     char_buf[0] = '%';
987                     s = &char_buf[0];
988                     s_len = 1;
989                     pad_char = ' ';
990                     break;
991 
992 
993               case 'n':
994                     if (var_type == IS_QUAD)
995                         *(va_arg(ap, widest_int *)) = cc;
996                     else if (var_type == IS_LONG)
997                         *(va_arg(ap, long *)) = cc;
998                     else if (var_type == IS_SHORT)
999                         *(va_arg(ap, short *)) = cc;
1000                     else
1001                         *(va_arg(ap, int *)) = cc;
1002                     break;
1003 
1004                     /*
1005                      * This is where we extend the printf format, with a second
1006                      * type specifier
1007                      */
1008               case 'p':
1009                     switch(*++fmt) {
1010                         /*
1011                          * If the pointer size is equal to or smaller than the size
1012                          * of the largest unsigned int, we convert the pointer to a
1013                          * hex number, otherwise we print "%p" to indicate that we
1014                          * don't handle "%p".
1015                          */
1016                     case 'p':
1017 #ifdef AP_VOID_P_IS_QUAD
1018                         if (sizeof(void *) <= sizeof(u_widest_int)) {
1019                               ui_quad = (u_widest_int) va_arg(ap, void *);
1020                               s = conv_p2_quad(ui_quad, 4, 'x',
1021                                         &num_buf[NUM_BUF_SIZE], &s_len);
1022                         }
1023 #else
1024                         if (sizeof(void *) <= sizeof(u_wide_int)) {
1025                               ui_num = (u_wide_int) va_arg(ap, void *);
1026                               s = conv_p2(ui_num, 4, 'x',
1027                                         &num_buf[NUM_BUF_SIZE], &s_len);
1028                         }
1029 #endif
1030                         else {
1031                               s = "%p";
1032                               s_len = 2;
1033                               prefix_char = NUL;
1034                         }
1035                         pad_char = ' ';
1036                         break;
1037 
1038                         /* print a struct sockaddr_in as a.b.c.d:port */
1039                     case 'I':
1040                         {
1041                               struct sockaddr_in *si;
1042 
1043                               si = va_arg(ap, struct sockaddr_in *);
1044                               if (si != NULL) {
1045                                   s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
1046                                   if (adjust_precision && precision < s_len)
1047                                         s_len = precision;
1048                               }
1049                               else {
1050                                   s = S_NULL;
1051                                   s_len = S_NULL_LEN;
1052                               }
1053                               pad_char = ' ';
1054                         }
1055                         break;
1056 
1057                         /* print a struct in_addr as a.b.c.d */
1058                     case 'A':
1059                         {
1060                               struct in_addr *ia;
1061 
1062                               ia = va_arg(ap, struct in_addr *);
1063                               if (ia != NULL) {
1064                                   s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
1065                                   if (adjust_precision && precision < s_len)
1066                                         s_len = precision;
1067                               }
1068                               else {
1069                                   s = S_NULL;
1070                                   s_len = S_NULL_LEN;
1071                               }
1072                               pad_char = ' ';
1073                         }
1074                         break;
1075 
1076                     case NUL:
1077                         /* if %p ends the string, oh well ignore it */
1078                         continue;
1079 
1080                     default:
1081                         s = "bogus %p";
1082                         s_len = 8;
1083                         prefix_char = NUL;
1084                         break;
1085                     }
1086                     break;
1087 
1088               case NUL:
1089                     /*
1090                      * The last character of the format string was %.
1091                      * We ignore it.
1092                      */
1093                     continue;
1094 
1095 
1096                     /*
1097                      * The default case is for unrecognized %'s.
1098                      * We print %<char> to help the user identify what
1099                      * option is not understood.
1100                      * This is also useful in case the user wants to pass
1101                      * the output of format_converter to another function
1102                      * that understands some other %<char> (like syslog).
1103                      * Note that we can't point s inside fmt because the
1104                      * unknown <char> could be preceded by width etc.
1105                      */
1106               default:
1107                     char_buf[0] = '%';
1108                     char_buf[1] = *fmt;
1109                     s = char_buf;
1110                     s_len = 2;
1111                     pad_char = ' ';
1112                     break;
1113               }
1114 
1115               if (prefix_char != NUL && s != S_NULL && s != char_buf) {
1116                     *--s = prefix_char;
1117                     s_len++;
1118               }
1119 
1120               if (adjust_width && adjust == RIGHT && min_width > s_len) {
1121                     if (pad_char == '0' && prefix_char != NUL) {
1122                         INS_CHAR(*s, sp, bep, cc);
1123                         s++;
1124                         s_len--;
1125                         min_width--;
1126                     }
1127                     PAD(min_width, s_len, pad_char);
1128               }
1129 
1130               /*
1131                * Print the string s.
1132                */
1133               for (i = s_len; i != 0; i--) {
1134                     INS_CHAR(*s, sp, bep, cc);
1135                     s++;
1136               }
1137 
1138               if (adjust_width && adjust == LEFT && min_width > s_len)
1139                     PAD(min_width, s_len, pad_char);
1140           }
1141           fmt++;
1142     }
1143     vbuff->curpos = sp;
1144 
1145     return cc;
1146 }
1147 
1148 
snprintf_flush(ap_vformatter_buff * vbuff)1149 static int snprintf_flush(ap_vformatter_buff *vbuff)
1150 {
1151     /* if the buffer fills we have to abort immediately, there is no way
1152      * to "flush" an ap_snprintf... there's nowhere to flush it to.
1153      */
1154     return -1;
1155 }
1156 
1157 
ap_snprintf(char * buf,size_t len,const char * format,...)1158 API_EXPORT_NONSTD(int) ap_snprintf(char *buf, size_t len, const char *format,...)
1159 {
1160     int cc;
1161     va_list ap;
1162     ap_vformatter_buff vbuff;
1163 
1164     if (len == 0)
1165           return 0;
1166 
1167     /* save one byte for nul terminator */
1168     vbuff.curpos = buf;
1169     vbuff.endpos = buf + len - 1;
1170     va_start(ap, format);
1171     cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
1172     va_end(ap);
1173     *vbuff.curpos = '\0';
1174     return (cc == -1) ? len : cc;
1175 }
1176 
1177 
ap_vsnprintf(char * buf,size_t len,const char * format,va_list ap)1178 API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
1179                                    va_list ap)
1180 {
1181     int cc;
1182     ap_vformatter_buff vbuff;
1183 
1184     if (len == 0)
1185           return 0;
1186 
1187     /* save one byte for nul terminator */
1188     vbuff.curpos = buf;
1189     vbuff.endpos = buf + len - 1;
1190     cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
1191     *vbuff.curpos = '\0';
1192     return (cc == -1) ? len : cc;
1193 }
1194