mprintf.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. *
  24. * Purpose:
  25. * A merge of Bjorn Reese's format() function and Daniel's dsprintf()
  26. * 1.0. A full blooded printf() clone with full support for <num>$
  27. * everywhere (parameters, widths and precisions) including variabled
  28. * sized parameters (like doubles, long longs, long doubles and even
  29. * void * in 64-bit architectures).
  30. *
  31. * Current restrictions:
  32. * - Max 128 parameters
  33. * - No 'long double' support.
  34. *
  35. * If you ever want truly portable and good *printf() clones, the project that
  36. * took on from here is named 'Trio' and you find more details on the trio web
  37. * page at https://daniel.haxx.se/projects/trio/
  38. */
  39. #include "curl_setup.h"
  40. #include "dynbuf.h"
  41. #include <curl/mprintf.h>
  42. #include "curl_memory.h"
  43. /* The last #include file should be: */
  44. #include "memdebug.h"
  45. /*
  46. * If SIZEOF_SIZE_T has not been defined, default to the size of long.
  47. */
  48. #ifdef HAVE_LONGLONG
  49. # define LONG_LONG_TYPE long long
  50. # define HAVE_LONG_LONG_TYPE
  51. #else
  52. # if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
  53. # define LONG_LONG_TYPE __int64
  54. # define HAVE_LONG_LONG_TYPE
  55. # else
  56. # undef LONG_LONG_TYPE
  57. # undef HAVE_LONG_LONG_TYPE
  58. # endif
  59. #endif
  60. /*
  61. * Non-ANSI integer extensions
  62. */
  63. #if (defined(_WIN32_WCE)) || \
  64. (defined(__MINGW32__)) || \
  65. (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
  66. # define MP_HAVE_INT_EXTENSIONS
  67. #endif
  68. /*
  69. * Max integer data types that mprintf.c is capable
  70. */
  71. #ifdef HAVE_LONG_LONG_TYPE
  72. # define mp_intmax_t LONG_LONG_TYPE
  73. # define mp_uintmax_t unsigned LONG_LONG_TYPE
  74. #else
  75. # define mp_intmax_t long
  76. # define mp_uintmax_t unsigned long
  77. #endif
  78. #define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
  79. fit negative DBL_MAX (317 letters) */
  80. #define MAX_PARAMETERS 128 /* lame static limit */
  81. #ifdef __AMIGA__
  82. # undef FORMAT_INT
  83. #endif
  84. /* Lower-case digits. */
  85. static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  86. /* Upper-case digits. */
  87. static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  88. #define OUTCHAR(x) \
  89. do { \
  90. if(stream((unsigned char)(x), (FILE *)data) != -1) \
  91. done++; \
  92. else \
  93. return done; /* return immediately on failure */ \
  94. } while(0)
  95. /* Data type to read from the arglist */
  96. typedef enum {
  97. FORMAT_UNKNOWN = 0,
  98. FORMAT_STRING,
  99. FORMAT_PTR,
  100. FORMAT_INT,
  101. FORMAT_INTPTR,
  102. FORMAT_LONG,
  103. FORMAT_LONGLONG,
  104. FORMAT_DOUBLE,
  105. FORMAT_LONGDOUBLE,
  106. FORMAT_WIDTH /* For internal use */
  107. } FormatType;
  108. /* conversion and display flags */
  109. enum {
  110. FLAGS_NEW = 0,
  111. FLAGS_SPACE = 1<<0,
  112. FLAGS_SHOWSIGN = 1<<1,
  113. FLAGS_LEFT = 1<<2,
  114. FLAGS_ALT = 1<<3,
  115. FLAGS_SHORT = 1<<4,
  116. FLAGS_LONG = 1<<5,
  117. FLAGS_LONGLONG = 1<<6,
  118. FLAGS_LONGDOUBLE = 1<<7,
  119. FLAGS_PAD_NIL = 1<<8,
  120. FLAGS_UNSIGNED = 1<<9,
  121. FLAGS_OCTAL = 1<<10,
  122. FLAGS_HEX = 1<<11,
  123. FLAGS_UPPER = 1<<12,
  124. FLAGS_WIDTH = 1<<13, /* '*' or '*<num>$' used */
  125. FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */
  126. FLAGS_PREC = 1<<15, /* precision was specified */
  127. FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */
  128. FLAGS_CHAR = 1<<17, /* %c story */
  129. FLAGS_FLOATE = 1<<18, /* %e or %E */
  130. FLAGS_FLOATG = 1<<19 /* %g or %G */
  131. };
  132. struct va_stack {
  133. FormatType type;
  134. int flags;
  135. long width; /* width OR width parameter number */
  136. long precision; /* precision OR precision parameter number */
  137. union {
  138. char *str;
  139. void *ptr;
  140. union {
  141. mp_intmax_t as_signed;
  142. mp_uintmax_t as_unsigned;
  143. } num;
  144. double dnum;
  145. } data;
  146. };
  147. struct nsprintf {
  148. char *buffer;
  149. size_t length;
  150. size_t max;
  151. };
  152. struct asprintf {
  153. struct dynbuf *b;
  154. bool fail; /* if an alloc has failed and thus the output is not the complete
  155. data */
  156. };
  157. static long dprintf_DollarString(char *input, char **end)
  158. {
  159. int number = 0;
  160. while(ISDIGIT(*input)) {
  161. if(number < MAX_PARAMETERS) {
  162. number *= 10;
  163. number += *input - '0';
  164. }
  165. input++;
  166. }
  167. if(number <= MAX_PARAMETERS && ('$' == *input)) {
  168. *end = ++input;
  169. return number;
  170. }
  171. return 0;
  172. }
  173. static bool dprintf_IsQualifierNoDollar(const char *fmt)
  174. {
  175. #if defined(MP_HAVE_INT_EXTENSIONS)
  176. if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
  177. return TRUE;
  178. }
  179. #endif
  180. switch(*fmt) {
  181. case '-': case '+': case ' ': case '#': case '.':
  182. case '0': case '1': case '2': case '3': case '4':
  183. case '5': case '6': case '7': case '8': case '9':
  184. case 'h': case 'l': case 'L': case 'z': case 'q':
  185. case '*': case 'O':
  186. #if defined(MP_HAVE_INT_EXTENSIONS)
  187. case 'I':
  188. #endif
  189. return TRUE;
  190. default:
  191. return FALSE;
  192. }
  193. }
  194. /******************************************************************
  195. *
  196. * Pass 1:
  197. * Create an index with the type of each parameter entry and its
  198. * value (may vary in size)
  199. *
  200. * Returns zero on success.
  201. *
  202. ******************************************************************/
  203. static int dprintf_Pass1(const char *format, struct va_stack *vto,
  204. char **endpos, va_list arglist)
  205. {
  206. char *fmt = (char *)format;
  207. int param_num = 0;
  208. long this_param;
  209. long width;
  210. long precision;
  211. int flags;
  212. long max_param = 0;
  213. long i;
  214. while(*fmt) {
  215. if(*fmt++ == '%') {
  216. if(*fmt == '%') {
  217. fmt++;
  218. continue; /* while */
  219. }
  220. flags = FLAGS_NEW;
  221. /* Handle the positional case (N$) */
  222. param_num++;
  223. this_param = dprintf_DollarString(fmt, &fmt);
  224. if(0 == this_param)
  225. /* we got no positional, get the next counter */
  226. this_param = param_num;
  227. if(this_param > max_param)
  228. max_param = this_param;
  229. /*
  230. * The parameter with number 'i' should be used. Next, we need
  231. * to get SIZE and TYPE of the parameter. Add the information
  232. * to our array.
  233. */
  234. width = 0;
  235. precision = 0;
  236. /* Handle the flags */
  237. while(dprintf_IsQualifierNoDollar(fmt)) {
  238. #if defined(MP_HAVE_INT_EXTENSIONS)
  239. if(!strncmp(fmt, "I32", 3)) {
  240. flags |= FLAGS_LONG;
  241. fmt += 3;
  242. }
  243. else if(!strncmp(fmt, "I64", 3)) {
  244. flags |= FLAGS_LONGLONG;
  245. fmt += 3;
  246. }
  247. else
  248. #endif
  249. switch(*fmt++) {
  250. case ' ':
  251. flags |= FLAGS_SPACE;
  252. break;
  253. case '+':
  254. flags |= FLAGS_SHOWSIGN;
  255. break;
  256. case '-':
  257. flags |= FLAGS_LEFT;
  258. flags &= ~FLAGS_PAD_NIL;
  259. break;
  260. case '#':
  261. flags |= FLAGS_ALT;
  262. break;
  263. case '.':
  264. if('*' == *fmt) {
  265. /* The precision is picked from a specified parameter */
  266. flags |= FLAGS_PRECPARAM;
  267. fmt++;
  268. param_num++;
  269. i = dprintf_DollarString(fmt, &fmt);
  270. if(i)
  271. precision = i;
  272. else
  273. precision = param_num;
  274. if(precision > max_param)
  275. max_param = precision;
  276. }
  277. else {
  278. flags |= FLAGS_PREC;
  279. precision = strtol(fmt, &fmt, 10);
  280. }
  281. if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
  282. (FLAGS_PREC | FLAGS_PRECPARAM))
  283. /* it is not permitted to use both kinds of precision for the same
  284. argument */
  285. return 1;
  286. break;
  287. case 'h':
  288. flags |= FLAGS_SHORT;
  289. break;
  290. #if defined(MP_HAVE_INT_EXTENSIONS)
  291. case 'I':
  292. #if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
  293. flags |= FLAGS_LONGLONG;
  294. #else
  295. flags |= FLAGS_LONG;
  296. #endif
  297. break;
  298. #endif
  299. case 'l':
  300. if(flags & FLAGS_LONG)
  301. flags |= FLAGS_LONGLONG;
  302. else
  303. flags |= FLAGS_LONG;
  304. break;
  305. case 'L':
  306. flags |= FLAGS_LONGDOUBLE;
  307. break;
  308. case 'q':
  309. flags |= FLAGS_LONGLONG;
  310. break;
  311. case 'z':
  312. /* the code below generates a warning if -Wunreachable-code is
  313. used */
  314. #if (SIZEOF_SIZE_T > SIZEOF_LONG)
  315. flags |= FLAGS_LONGLONG;
  316. #else
  317. flags |= FLAGS_LONG;
  318. #endif
  319. break;
  320. case 'O':
  321. #if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
  322. flags |= FLAGS_LONGLONG;
  323. #else
  324. flags |= FLAGS_LONG;
  325. #endif
  326. break;
  327. case '0':
  328. if(!(flags & FLAGS_LEFT))
  329. flags |= FLAGS_PAD_NIL;
  330. /* FALLTHROUGH */
  331. case '1': case '2': case '3': case '4':
  332. case '5': case '6': case '7': case '8': case '9':
  333. flags |= FLAGS_WIDTH;
  334. width = strtol(fmt-1, &fmt, 10);
  335. break;
  336. case '*': /* Special case */
  337. flags |= FLAGS_WIDTHPARAM;
  338. param_num++;
  339. i = dprintf_DollarString(fmt, &fmt);
  340. if(i)
  341. width = i;
  342. else
  343. width = param_num;
  344. if(width > max_param)
  345. max_param = width;
  346. break;
  347. case '\0':
  348. fmt--;
  349. default:
  350. break;
  351. }
  352. } /* switch */
  353. /* Handle the specifier */
  354. i = this_param - 1;
  355. if((i < 0) || (i >= MAX_PARAMETERS))
  356. /* out of allowed range */
  357. return 1;
  358. switch(*fmt) {
  359. case 'S':
  360. flags |= FLAGS_ALT;
  361. /* FALLTHROUGH */
  362. case 's':
  363. vto[i].type = FORMAT_STRING;
  364. break;
  365. case 'n':
  366. vto[i].type = FORMAT_INTPTR;
  367. break;
  368. case 'p':
  369. vto[i].type = FORMAT_PTR;
  370. break;
  371. case 'd': case 'i':
  372. vto[i].type = FORMAT_INT;
  373. break;
  374. case 'u':
  375. vto[i].type = FORMAT_INT;
  376. flags |= FLAGS_UNSIGNED;
  377. break;
  378. case 'o':
  379. vto[i].type = FORMAT_INT;
  380. flags |= FLAGS_OCTAL;
  381. break;
  382. case 'x':
  383. vto[i].type = FORMAT_INT;
  384. flags |= FLAGS_HEX|FLAGS_UNSIGNED;
  385. break;
  386. case 'X':
  387. vto[i].type = FORMAT_INT;
  388. flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
  389. break;
  390. case 'c':
  391. vto[i].type = FORMAT_INT;
  392. flags |= FLAGS_CHAR;
  393. break;
  394. case 'f':
  395. vto[i].type = FORMAT_DOUBLE;
  396. break;
  397. case 'e':
  398. vto[i].type = FORMAT_DOUBLE;
  399. flags |= FLAGS_FLOATE;
  400. break;
  401. case 'E':
  402. vto[i].type = FORMAT_DOUBLE;
  403. flags |= FLAGS_FLOATE|FLAGS_UPPER;
  404. break;
  405. case 'g':
  406. vto[i].type = FORMAT_DOUBLE;
  407. flags |= FLAGS_FLOATG;
  408. break;
  409. case 'G':
  410. vto[i].type = FORMAT_DOUBLE;
  411. flags |= FLAGS_FLOATG|FLAGS_UPPER;
  412. break;
  413. default:
  414. vto[i].type = FORMAT_UNKNOWN;
  415. break;
  416. } /* switch */
  417. vto[i].flags = flags;
  418. vto[i].width = width;
  419. vto[i].precision = precision;
  420. if(flags & FLAGS_WIDTHPARAM) {
  421. /* we have the width specified from a parameter, so we make that
  422. parameter's info setup properly */
  423. long k = width - 1;
  424. if((k < 0) || (k >= MAX_PARAMETERS))
  425. /* out of allowed range */
  426. return 1;
  427. vto[i].width = k;
  428. vto[k].type = FORMAT_WIDTH;
  429. vto[k].flags = FLAGS_NEW;
  430. /* can't use width or precision of width! */
  431. vto[k].width = 0;
  432. vto[k].precision = 0;
  433. }
  434. if(flags & FLAGS_PRECPARAM) {
  435. /* we have the precision specified from a parameter, so we make that
  436. parameter's info setup properly */
  437. long k = precision - 1;
  438. if((k < 0) || (k >= MAX_PARAMETERS))
  439. /* out of allowed range */
  440. return 1;
  441. vto[i].precision = k;
  442. vto[k].type = FORMAT_WIDTH;
  443. vto[k].flags = FLAGS_NEW;
  444. /* can't use width or precision of width! */
  445. vto[k].width = 0;
  446. vto[k].precision = 0;
  447. }
  448. *endpos++ = fmt + ((*fmt == '\0') ? 0 : 1); /* end of this sequence */
  449. }
  450. }
  451. /* Read the arg list parameters into our data list */
  452. for(i = 0; i<max_param; i++) {
  453. /* Width/precision arguments must be read before the main argument
  454. they are attached to */
  455. if(vto[i].flags & FLAGS_WIDTHPARAM) {
  456. vto[vto[i].width].data.num.as_signed =
  457. (mp_intmax_t)va_arg(arglist, int);
  458. }
  459. if(vto[i].flags & FLAGS_PRECPARAM) {
  460. vto[vto[i].precision].data.num.as_signed =
  461. (mp_intmax_t)va_arg(arglist, int);
  462. }
  463. switch(vto[i].type) {
  464. case FORMAT_STRING:
  465. vto[i].data.str = va_arg(arglist, char *);
  466. break;
  467. case FORMAT_INTPTR:
  468. case FORMAT_UNKNOWN:
  469. case FORMAT_PTR:
  470. vto[i].data.ptr = va_arg(arglist, void *);
  471. break;
  472. case FORMAT_INT:
  473. #ifdef HAVE_LONG_LONG_TYPE
  474. if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
  475. vto[i].data.num.as_unsigned =
  476. (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
  477. else if(vto[i].flags & FLAGS_LONGLONG)
  478. vto[i].data.num.as_signed =
  479. (mp_intmax_t)va_arg(arglist, mp_intmax_t);
  480. else
  481. #endif
  482. {
  483. if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
  484. vto[i].data.num.as_unsigned =
  485. (mp_uintmax_t)va_arg(arglist, unsigned long);
  486. else if(vto[i].flags & FLAGS_LONG)
  487. vto[i].data.num.as_signed =
  488. (mp_intmax_t)va_arg(arglist, long);
  489. else if(vto[i].flags & FLAGS_UNSIGNED)
  490. vto[i].data.num.as_unsigned =
  491. (mp_uintmax_t)va_arg(arglist, unsigned int);
  492. else
  493. vto[i].data.num.as_signed =
  494. (mp_intmax_t)va_arg(arglist, int);
  495. }
  496. break;
  497. case FORMAT_DOUBLE:
  498. vto[i].data.dnum = va_arg(arglist, double);
  499. break;
  500. case FORMAT_WIDTH:
  501. /* Argument has been read. Silently convert it into an integer
  502. * for later use
  503. */
  504. vto[i].type = FORMAT_INT;
  505. break;
  506. default:
  507. break;
  508. }
  509. }
  510. return 0;
  511. }
  512. static int dprintf_formatf(
  513. void *data, /* untouched by format(), just sent to the stream() function in
  514. the second argument */
  515. /* function pointer called for each output character */
  516. int (*stream)(int, FILE *),
  517. const char *format, /* %-formatted string */
  518. va_list ap_save) /* list of parameters */
  519. {
  520. /* Base-36 digits for numbers. */
  521. const char *digits = lower_digits;
  522. /* Pointer into the format string. */
  523. char *f;
  524. /* Number of characters written. */
  525. int done = 0;
  526. long param; /* current parameter to read */
  527. long param_num = 0; /* parameter counter */
  528. struct va_stack vto[MAX_PARAMETERS];
  529. char *endpos[MAX_PARAMETERS];
  530. char **end;
  531. char work[BUFFSIZE];
  532. struct va_stack *p;
  533. /* 'workend' points to the final buffer byte position, but with an extra
  534. byte as margin to avoid the (false?) warning Coverity gives us
  535. otherwise */
  536. char *workend = &work[sizeof(work) - 2];
  537. /* Do the actual %-code parsing */
  538. if(dprintf_Pass1(format, vto, endpos, ap_save))
  539. return 0;
  540. end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
  541. created for us */
  542. f = (char *)format;
  543. while(*f != '\0') {
  544. /* Format spec modifiers. */
  545. int is_alt;
  546. /* Width of a field. */
  547. long width;
  548. /* Precision of a field. */
  549. long prec;
  550. /* Decimal integer is negative. */
  551. int is_neg;
  552. /* Base of a number to be written. */
  553. unsigned long base;
  554. /* Integral values to be written. */
  555. mp_uintmax_t num;
  556. /* Used to convert negative in positive. */
  557. mp_intmax_t signed_num;
  558. char *w;
  559. if(*f != '%') {
  560. /* This isn't a format spec, so write everything out until the next one
  561. OR end of string is reached. */
  562. do {
  563. OUTCHAR(*f);
  564. } while(*++f && ('%' != *f));
  565. continue;
  566. }
  567. ++f;
  568. /* Check for "%%". Note that although the ANSI standard lists
  569. '%' as a conversion specifier, it says "The complete format
  570. specification shall be `%%'," so we can avoid all the width
  571. and precision processing. */
  572. if(*f == '%') {
  573. ++f;
  574. OUTCHAR('%');
  575. continue;
  576. }
  577. /* If this is a positional parameter, the position must follow immediately
  578. after the %, thus create a %<num>$ sequence */
  579. param = dprintf_DollarString(f, &f);
  580. if(!param)
  581. param = param_num;
  582. else
  583. --param;
  584. param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
  585. third %s will pick the 3rd argument */
  586. p = &vto[param];
  587. /* pick up the specified width */
  588. if(p->flags & FLAGS_WIDTHPARAM) {
  589. width = (long)vto[p->width].data.num.as_signed;
  590. param_num++; /* since the width is extracted from a parameter, we
  591. must skip that to get to the next one properly */
  592. if(width < 0) {
  593. /* "A negative field width is taken as a '-' flag followed by a
  594. positive field width." */
  595. width = -width;
  596. p->flags |= FLAGS_LEFT;
  597. p->flags &= ~FLAGS_PAD_NIL;
  598. }
  599. }
  600. else
  601. width = p->width;
  602. /* pick up the specified precision */
  603. if(p->flags & FLAGS_PRECPARAM) {
  604. prec = (long)vto[p->precision].data.num.as_signed;
  605. param_num++; /* since the precision is extracted from a parameter, we
  606. must skip that to get to the next one properly */
  607. if(prec < 0)
  608. /* "A negative precision is taken as if the precision were
  609. omitted." */
  610. prec = -1;
  611. }
  612. else if(p->flags & FLAGS_PREC)
  613. prec = p->precision;
  614. else
  615. prec = -1;
  616. is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
  617. switch(p->type) {
  618. case FORMAT_INT:
  619. num = p->data.num.as_unsigned;
  620. if(p->flags & FLAGS_CHAR) {
  621. /* Character. */
  622. if(!(p->flags & FLAGS_LEFT))
  623. while(--width > 0)
  624. OUTCHAR(' ');
  625. OUTCHAR((char) num);
  626. if(p->flags & FLAGS_LEFT)
  627. while(--width > 0)
  628. OUTCHAR(' ');
  629. break;
  630. }
  631. if(p->flags & FLAGS_OCTAL) {
  632. /* Octal unsigned integer. */
  633. base = 8;
  634. goto unsigned_number;
  635. }
  636. else if(p->flags & FLAGS_HEX) {
  637. /* Hexadecimal unsigned integer. */
  638. digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
  639. base = 16;
  640. goto unsigned_number;
  641. }
  642. else if(p->flags & FLAGS_UNSIGNED) {
  643. /* Decimal unsigned integer. */
  644. base = 10;
  645. goto unsigned_number;
  646. }
  647. /* Decimal integer. */
  648. base = 10;
  649. is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
  650. if(is_neg) {
  651. /* signed_num might fail to hold absolute negative minimum by 1 */
  652. signed_num = p->data.num.as_signed + (mp_intmax_t)1;
  653. signed_num = -signed_num;
  654. num = (mp_uintmax_t)signed_num;
  655. num += (mp_uintmax_t)1;
  656. }
  657. goto number;
  658. unsigned_number:
  659. /* Unsigned number of base BASE. */
  660. is_neg = 0;
  661. number:
  662. /* Number of base BASE. */
  663. /* Supply a default precision if none was given. */
  664. if(prec == -1)
  665. prec = 1;
  666. /* Put the number in WORK. */
  667. w = workend;
  668. while(num > 0) {
  669. *w-- = digits[num % base];
  670. num /= base;
  671. }
  672. width -= (long)(workend - w);
  673. prec -= (long)(workend - w);
  674. if(is_alt && base == 8 && prec <= 0) {
  675. *w-- = '0';
  676. --width;
  677. }
  678. if(prec > 0) {
  679. width -= prec;
  680. while(prec-- > 0 && w >= work)
  681. *w-- = '0';
  682. }
  683. if(is_alt && base == 16)
  684. width -= 2;
  685. if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
  686. --width;
  687. if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
  688. while(width-- > 0)
  689. OUTCHAR(' ');
  690. if(is_neg)
  691. OUTCHAR('-');
  692. else if(p->flags & FLAGS_SHOWSIGN)
  693. OUTCHAR('+');
  694. else if(p->flags & FLAGS_SPACE)
  695. OUTCHAR(' ');
  696. if(is_alt && base == 16) {
  697. OUTCHAR('0');
  698. if(p->flags & FLAGS_UPPER)
  699. OUTCHAR('X');
  700. else
  701. OUTCHAR('x');
  702. }
  703. if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
  704. while(width-- > 0)
  705. OUTCHAR('0');
  706. /* Write the number. */
  707. while(++w <= workend) {
  708. OUTCHAR(*w);
  709. }
  710. if(p->flags & FLAGS_LEFT)
  711. while(width-- > 0)
  712. OUTCHAR(' ');
  713. break;
  714. case FORMAT_STRING:
  715. /* String. */
  716. {
  717. static const char null[] = "(nil)";
  718. const char *str;
  719. size_t len;
  720. str = (char *) p->data.str;
  721. if(!str) {
  722. /* Write null[] if there's space. */
  723. if(prec == -1 || prec >= (long) sizeof(null) - 1) {
  724. str = null;
  725. len = sizeof(null) - 1;
  726. /* Disable quotes around (nil) */
  727. p->flags &= (~FLAGS_ALT);
  728. }
  729. else {
  730. str = "";
  731. len = 0;
  732. }
  733. }
  734. else if(prec != -1)
  735. len = (size_t)prec;
  736. else if(*str == '\0')
  737. len = 0;
  738. else
  739. len = strlen(str);
  740. width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
  741. if(p->flags & FLAGS_ALT)
  742. OUTCHAR('"');
  743. if(!(p->flags&FLAGS_LEFT))
  744. while(width-- > 0)
  745. OUTCHAR(' ');
  746. for(; len && *str; len--)
  747. OUTCHAR(*str++);
  748. if(p->flags&FLAGS_LEFT)
  749. while(width-- > 0)
  750. OUTCHAR(' ');
  751. if(p->flags & FLAGS_ALT)
  752. OUTCHAR('"');
  753. }
  754. break;
  755. case FORMAT_PTR:
  756. /* Generic pointer. */
  757. {
  758. void *ptr;
  759. ptr = (void *) p->data.ptr;
  760. if(ptr) {
  761. /* If the pointer is not NULL, write it as a %#x spec. */
  762. base = 16;
  763. digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
  764. is_alt = 1;
  765. num = (size_t) ptr;
  766. is_neg = 0;
  767. goto number;
  768. }
  769. else {
  770. /* Write "(nil)" for a nil pointer. */
  771. static const char strnil[] = "(nil)";
  772. const char *point;
  773. width -= (long)(sizeof(strnil) - 1);
  774. if(p->flags & FLAGS_LEFT)
  775. while(width-- > 0)
  776. OUTCHAR(' ');
  777. for(point = strnil; *point != '\0'; ++point)
  778. OUTCHAR(*point);
  779. if(!(p->flags & FLAGS_LEFT))
  780. while(width-- > 0)
  781. OUTCHAR(' ');
  782. }
  783. }
  784. break;
  785. case FORMAT_DOUBLE:
  786. {
  787. char formatbuf[32]="%";
  788. char *fptr = &formatbuf[1];
  789. size_t left = sizeof(formatbuf)-strlen(formatbuf);
  790. int len;
  791. width = -1;
  792. if(p->flags & FLAGS_WIDTH)
  793. width = p->width;
  794. else if(p->flags & FLAGS_WIDTHPARAM)
  795. width = (long)vto[p->width].data.num.as_signed;
  796. prec = -1;
  797. if(p->flags & FLAGS_PREC)
  798. prec = p->precision;
  799. else if(p->flags & FLAGS_PRECPARAM)
  800. prec = (long)vto[p->precision].data.num.as_signed;
  801. if(p->flags & FLAGS_LEFT)
  802. *fptr++ = '-';
  803. if(p->flags & FLAGS_SHOWSIGN)
  804. *fptr++ = '+';
  805. if(p->flags & FLAGS_SPACE)
  806. *fptr++ = ' ';
  807. if(p->flags & FLAGS_ALT)
  808. *fptr++ = '#';
  809. *fptr = 0;
  810. if(width >= 0) {
  811. if(width >= (long)sizeof(work))
  812. width = sizeof(work)-1;
  813. /* RECURSIVE USAGE */
  814. len = curl_msnprintf(fptr, left, "%ld", width);
  815. fptr += len;
  816. left -= len;
  817. }
  818. if(prec >= 0) {
  819. /* for each digit in the integer part, we can have one less
  820. precision */
  821. size_t maxprec = sizeof(work) - 2;
  822. double val = p->data.dnum;
  823. if(width > 0 && prec <= width)
  824. maxprec -= width;
  825. while(val >= 10.0) {
  826. val /= 10;
  827. maxprec--;
  828. }
  829. if(prec > (long)maxprec)
  830. prec = (long)maxprec-1;
  831. if(prec < 0)
  832. prec = 0;
  833. /* RECURSIVE USAGE */
  834. len = curl_msnprintf(fptr, left, ".%ld", prec);
  835. fptr += len;
  836. }
  837. if(p->flags & FLAGS_LONG)
  838. *fptr++ = 'l';
  839. if(p->flags & FLAGS_FLOATE)
  840. *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
  841. else if(p->flags & FLAGS_FLOATG)
  842. *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
  843. else
  844. *fptr++ = 'f';
  845. *fptr = 0; /* and a final null-termination */
  846. #ifdef __clang__
  847. #pragma clang diagnostic push
  848. #pragma clang diagnostic ignored "-Wformat-nonliteral"
  849. #endif
  850. /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
  851. output characters */
  852. #ifdef HAVE_SNPRINTF
  853. (snprintf)(work, sizeof(work), formatbuf, p->data.dnum);
  854. #else
  855. (sprintf)(work, formatbuf, p->data.dnum);
  856. #endif
  857. #ifdef __clang__
  858. #pragma clang diagnostic pop
  859. #endif
  860. DEBUGASSERT(strlen(work) <= sizeof(work));
  861. for(fptr = work; *fptr; fptr++)
  862. OUTCHAR(*fptr);
  863. }
  864. break;
  865. case FORMAT_INTPTR:
  866. /* Answer the count of characters written. */
  867. #ifdef HAVE_LONG_LONG_TYPE
  868. if(p->flags & FLAGS_LONGLONG)
  869. *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
  870. else
  871. #endif
  872. if(p->flags & FLAGS_LONG)
  873. *(long *) p->data.ptr = (long)done;
  874. else if(!(p->flags & FLAGS_SHORT))
  875. *(int *) p->data.ptr = (int)done;
  876. else
  877. *(short *) p->data.ptr = (short)done;
  878. break;
  879. default:
  880. break;
  881. }
  882. f = *end++; /* goto end of %-code */
  883. }
  884. return done;
  885. }
  886. /* fputc() look-alike */
  887. static int addbyter(int output, FILE *data)
  888. {
  889. struct nsprintf *infop = (struct nsprintf *)data;
  890. unsigned char outc = (unsigned char)output;
  891. if(infop->length < infop->max) {
  892. /* only do this if we haven't reached max length yet */
  893. infop->buffer[0] = outc; /* store */
  894. infop->buffer++; /* increase pointer */
  895. infop->length++; /* we are now one byte larger */
  896. return outc; /* fputc() returns like this on success */
  897. }
  898. return -1;
  899. }
  900. int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
  901. va_list ap_save)
  902. {
  903. int retcode;
  904. struct nsprintf info;
  905. info.buffer = buffer;
  906. info.length = 0;
  907. info.max = maxlength;
  908. retcode = dprintf_formatf(&info, addbyter, format, ap_save);
  909. if(info.max) {
  910. /* we terminate this with a zero byte */
  911. if(info.max == info.length) {
  912. /* we're at maximum, scrap the last letter */
  913. info.buffer[-1] = 0;
  914. DEBUGASSERT(retcode);
  915. retcode--; /* don't count the nul byte */
  916. }
  917. else
  918. info.buffer[0] = 0;
  919. }
  920. return retcode;
  921. }
  922. int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
  923. {
  924. int retcode;
  925. va_list ap_save; /* argument pointer */
  926. va_start(ap_save, format);
  927. retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
  928. va_end(ap_save);
  929. return retcode;
  930. }
  931. /* fputc() look-alike */
  932. static int alloc_addbyter(int output, FILE *data)
  933. {
  934. struct asprintf *infop = (struct asprintf *)data;
  935. unsigned char outc = (unsigned char)output;
  936. if(Curl_dyn_addn(infop->b, &outc, 1)) {
  937. infop->fail = 1;
  938. return -1; /* fail */
  939. }
  940. return outc; /* fputc() returns like this on success */
  941. }
  942. /* appends the formatted string, returns 0 on success, 1 on error */
  943. int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
  944. {
  945. struct asprintf info;
  946. info.b = dyn;
  947. info.fail = 0;
  948. (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
  949. if(info.fail) {
  950. Curl_dyn_free(info.b);
  951. return 1;
  952. }
  953. return 0;
  954. }
  955. char *curl_mvaprintf(const char *format, va_list ap_save)
  956. {
  957. struct asprintf info;
  958. struct dynbuf dyn;
  959. info.b = &dyn;
  960. Curl_dyn_init(info.b, DYN_APRINTF);
  961. info.fail = 0;
  962. (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
  963. if(info.fail) {
  964. Curl_dyn_free(info.b);
  965. return NULL;
  966. }
  967. if(Curl_dyn_len(info.b))
  968. return Curl_dyn_ptr(info.b);
  969. return strdup("");
  970. }
  971. char *curl_maprintf(const char *format, ...)
  972. {
  973. va_list ap_save;
  974. char *s;
  975. va_start(ap_save, format);
  976. s = curl_mvaprintf(format, ap_save);
  977. va_end(ap_save);
  978. return s;
  979. }
  980. static int storebuffer(int output, FILE *data)
  981. {
  982. char **buffer = (char **)data;
  983. unsigned char outc = (unsigned char)output;
  984. **buffer = outc;
  985. (*buffer)++;
  986. return outc; /* act like fputc() ! */
  987. }
  988. int curl_msprintf(char *buffer, const char *format, ...)
  989. {
  990. va_list ap_save; /* argument pointer */
  991. int retcode;
  992. va_start(ap_save, format);
  993. retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
  994. va_end(ap_save);
  995. *buffer = 0; /* we terminate this with a zero byte */
  996. return retcode;
  997. }
  998. int curl_mprintf(const char *format, ...)
  999. {
  1000. int retcode;
  1001. va_list ap_save; /* argument pointer */
  1002. va_start(ap_save, format);
  1003. retcode = dprintf_formatf(stdout, fputc, format, ap_save);
  1004. va_end(ap_save);
  1005. return retcode;
  1006. }
  1007. int curl_mfprintf(FILE *whereto, const char *format, ...)
  1008. {
  1009. int retcode;
  1010. va_list ap_save; /* argument pointer */
  1011. va_start(ap_save, format);
  1012. retcode = dprintf_formatf(whereto, fputc, format, ap_save);
  1013. va_end(ap_save);
  1014. return retcode;
  1015. }
  1016. int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
  1017. {
  1018. int retcode;
  1019. retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
  1020. *buffer = 0; /* we terminate this with a zero byte */
  1021. return retcode;
  1022. }
  1023. int curl_mvprintf(const char *format, va_list ap_save)
  1024. {
  1025. return dprintf_formatf(stdout, fputc, format, ap_save);
  1026. }
  1027. int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
  1028. {
  1029. return dprintf_formatf(whereto, fputc, format, ap_save);
  1030. }