File: | libs/apr/strings/apr_snprintf.c |
Location: | line 113, column 5 |
Description: | Value stored to 'p1' is never read |
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 | |
44 | typedef 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 | |
57 | typedef WIDE_INTlong wide_int; |
58 | typedef unsigned WIDE_INTlong u_wide_int; |
59 | typedef apr_int64_t widest_int; |
60 | #ifdef __TANDEM |
61 | /* Although Tandem supports "long long" there is no unsigned variant. */ |
62 | typedef unsigned long u_widest_int; |
63 | #else |
64 | typedef apr_uint64_t u_widest_int; |
65 | #endif |
66 | typedef 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 */ |
96 | static 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 | |
171 | static 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 | |
176 | static 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 | |
186 | static 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) \ |
306 | do \ |
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 | } \ |
311 | while (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 | */ |
340 | static 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 | |
387 | static 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 | |
446 | static 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 | |
467 | static 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 |
500 | static 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 | */ |
529 | static 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 | */ |
628 | static 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 | |
647 | static 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 |
670 | static 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 | */ |
694 | APR_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 | |
1308 | static 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 | |
1317 | APR_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 | |
1349 | APR_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 | } |