Bug Summary

File:libs/apr/strings/apr_snprintf.c
Location:line 113, column 5
Description:Value stored to 'p1' is never read

Annotated Source Code

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