| File: | libs/apr/strings/apr_snprintf.c |
| Location: | line 518, column 1 |
| Description: | Address of stack memory associated with local variable 'is_negative' is still referred to by the global variable 'is_negative' upon returning to the caller. This will be a dangling reference |
| 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]; | |||
| 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 | } |