apr_snprintf.c 43 KB

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