fspr_snprintf.c 41 KB

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