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