io.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598
  1. /*
  2. * Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
  16. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. * SUCH DAMAGE.
  26. */
  27. #include "mpdecimal.h"
  28. #include <assert.h>
  29. #include <ctype.h>
  30. #include <errno.h>
  31. #include <limits.h>
  32. #include <locale.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include "mpd_io.h"
  37. #include "typearith.h"
  38. /* This file contains functions for decimal <-> string conversions, including
  39. PEP-3101 formatting for numeric types. */
  40. #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && __GNUC__ >= 7
  41. #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
  42. #pragma GCC diagnostic ignored "-Wmisleading-indentation"
  43. #endif
  44. /*
  45. * Work around the behavior of tolower() and strcasecmp() in certain
  46. * locales. For example, in tr_TR.utf8:
  47. *
  48. * tolower((unsigned char)'I') == 'I'
  49. *
  50. * u is the exact uppercase version of l; n is strlen(l) or strlen(l)+1
  51. */
  52. static inline int
  53. _mpd_strneq(const char *s, const char *l, const char *u, size_t n)
  54. {
  55. while (--n != SIZE_MAX) {
  56. if (*s != *l && *s != *u) {
  57. return 0;
  58. }
  59. s++; u++; l++;
  60. }
  61. return 1;
  62. }
  63. static mpd_ssize_t
  64. strtoexp(const char *s)
  65. {
  66. char *end;
  67. mpd_ssize_t retval;
  68. errno = 0;
  69. retval = mpd_strtossize(s, &end, 10);
  70. if (errno == 0 && !(*s != '\0' && *end == '\0'))
  71. errno = EINVAL;
  72. return retval;
  73. }
  74. /*
  75. * Scan 'len' words. The most significant word contains 'r' digits,
  76. * the remaining words are full words. Skip dpoint. The string 's' must
  77. * consist of digits and an optional single decimal point at 'dpoint'.
  78. */
  79. static void
  80. string_to_coeff(mpd_uint_t *data, const char *s, const char *dpoint, int r,
  81. size_t len)
  82. {
  83. int j;
  84. if (r > 0) {
  85. data[--len] = 0;
  86. for (j = 0; j < r; j++, s++) {
  87. if (s == dpoint) s++;
  88. data[len] = 10 * data[len] + (*s - '0');
  89. }
  90. }
  91. while (--len != SIZE_MAX) {
  92. data[len] = 0;
  93. for (j = 0; j < MPD_RDIGITS; j++, s++) {
  94. if (s == dpoint) s++;
  95. data[len] = 10 * data[len] + (*s - '0');
  96. }
  97. }
  98. }
  99. /*
  100. * Partially verify a numeric string of the form:
  101. *
  102. * [cdigits][.][cdigits][eE][+-][edigits]
  103. *
  104. * If successful, return a pointer to the location of the first
  105. * relevant coefficient digit. This digit is either non-zero or
  106. * part of one of the following patterns:
  107. *
  108. * ["0\x00", "0.\x00", "0.E", "0.e", "0E", "0e"]
  109. *
  110. * The locations of a single optional dot or indicator are stored
  111. * in 'dpoint' and 'exp'.
  112. *
  113. * The end of the string is stored in 'end'. If an indicator [eE]
  114. * occurs without trailing [edigits], the condition is caught
  115. * later by strtoexp().
  116. */
  117. static const char *
  118. scan_dpoint_exp(const char *s, const char **dpoint, const char **exp,
  119. const char **end)
  120. {
  121. const char *coeff = NULL;
  122. *dpoint = NULL;
  123. *exp = NULL;
  124. for (; *s != '\0'; s++) {
  125. switch (*s) {
  126. case '.':
  127. if (*dpoint != NULL || *exp != NULL)
  128. return NULL;
  129. *dpoint = s;
  130. break;
  131. case 'E': case 'e':
  132. if (*exp != NULL)
  133. return NULL;
  134. *exp = s;
  135. if (*(s+1) == '+' || *(s+1) == '-')
  136. s++;
  137. break;
  138. default:
  139. if (!isdigit((unsigned char)*s))
  140. return NULL;
  141. if (coeff == NULL && *exp == NULL) {
  142. if (*s == '0') {
  143. if (!isdigit((unsigned char)*(s+1)))
  144. if (!(*(s+1) == '.' &&
  145. isdigit((unsigned char)*(s+2))))
  146. coeff = s;
  147. }
  148. else {
  149. coeff = s;
  150. }
  151. }
  152. break;
  153. }
  154. }
  155. *end = s;
  156. return coeff;
  157. }
  158. /* scan the payload of a NaN */
  159. static const char *
  160. scan_payload(const char *s, const char **end)
  161. {
  162. const char *coeff;
  163. while (*s == '0')
  164. s++;
  165. coeff = s;
  166. while (isdigit((unsigned char)*s))
  167. s++;
  168. *end = s;
  169. return (*s == '\0') ? coeff : NULL;
  170. }
  171. /* convert a character string to a decimal */
  172. void
  173. mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
  174. uint32_t *status)
  175. {
  176. mpd_ssize_t q, r, len;
  177. const char *coeff, *end;
  178. const char *dpoint = NULL, *exp = NULL;
  179. size_t digits;
  180. uint8_t sign = MPD_POS;
  181. mpd_set_flags(dec, 0);
  182. dec->len = 0;
  183. dec->exp = 0;
  184. /* sign */
  185. if (*s == '+') {
  186. s++;
  187. }
  188. else if (*s == '-') {
  189. mpd_set_negative(dec);
  190. sign = MPD_NEG;
  191. s++;
  192. }
  193. if (_mpd_strneq(s, "nan", "NAN", 3)) { /* NaN */
  194. s += 3;
  195. mpd_setspecial(dec, sign, MPD_NAN);
  196. if (*s == '\0')
  197. return;
  198. /* validate payload: digits only */
  199. if ((coeff = scan_payload(s, &end)) == NULL)
  200. goto conversion_error;
  201. /* payload consists entirely of zeros */
  202. if (*coeff == '\0')
  203. return;
  204. digits = end - coeff;
  205. /* prec >= 1, clamp is 0 or 1 */
  206. if (digits > (size_t)(ctx->prec-ctx->clamp))
  207. goto conversion_error;
  208. } /* sNaN */
  209. else if (_mpd_strneq(s, "snan", "SNAN", 4)) {
  210. s += 4;
  211. mpd_setspecial(dec, sign, MPD_SNAN);
  212. if (*s == '\0')
  213. return;
  214. /* validate payload: digits only */
  215. if ((coeff = scan_payload(s, &end)) == NULL)
  216. goto conversion_error;
  217. /* payload consists entirely of zeros */
  218. if (*coeff == '\0')
  219. return;
  220. digits = end - coeff;
  221. if (digits > (size_t)(ctx->prec-ctx->clamp))
  222. goto conversion_error;
  223. }
  224. else if (_mpd_strneq(s, "inf", "INF", 3)) {
  225. s += 3;
  226. if (*s == '\0' || _mpd_strneq(s, "inity", "INITY", 6)) {
  227. /* numeric-value: infinity */
  228. mpd_setspecial(dec, sign, MPD_INF);
  229. return;
  230. }
  231. goto conversion_error;
  232. }
  233. else {
  234. /* scan for start of coefficient, decimal point, indicator, end */
  235. if ((coeff = scan_dpoint_exp(s, &dpoint, &exp, &end)) == NULL)
  236. goto conversion_error;
  237. /* numeric-value: [exponent-part] */
  238. if (exp) {
  239. /* exponent-part */
  240. end = exp; exp++;
  241. dec->exp = strtoexp(exp);
  242. if (errno) {
  243. if (!(errno == ERANGE &&
  244. (dec->exp == MPD_SSIZE_MAX ||
  245. dec->exp == MPD_SSIZE_MIN)))
  246. goto conversion_error;
  247. }
  248. }
  249. digits = end - coeff;
  250. if (dpoint) {
  251. size_t fracdigits = end-dpoint-1;
  252. if (dpoint > coeff) digits--;
  253. if (fracdigits > MPD_MAX_PREC) {
  254. goto conversion_error;
  255. }
  256. if (dec->exp < MPD_SSIZE_MIN+(mpd_ssize_t)fracdigits) {
  257. dec->exp = MPD_SSIZE_MIN;
  258. }
  259. else {
  260. dec->exp -= (mpd_ssize_t)fracdigits;
  261. }
  262. }
  263. if (digits > MPD_MAX_PREC) {
  264. goto conversion_error;
  265. }
  266. if (dec->exp > MPD_EXP_INF) {
  267. dec->exp = MPD_EXP_INF;
  268. }
  269. if (dec->exp == MPD_SSIZE_MIN) {
  270. dec->exp = MPD_SSIZE_MIN+1;
  271. }
  272. }
  273. _mpd_idiv_word(&q, &r, (mpd_ssize_t)digits, MPD_RDIGITS);
  274. len = (r == 0) ? q : q+1;
  275. if (len == 0) {
  276. goto conversion_error; /* GCOV_NOT_REACHED */
  277. }
  278. if (!mpd_qresize(dec, len, status)) {
  279. mpd_seterror(dec, MPD_Malloc_error, status);
  280. return;
  281. }
  282. dec->len = len;
  283. string_to_coeff(dec->data, coeff, dpoint, (int)r, len);
  284. mpd_setdigits(dec);
  285. mpd_qfinalize(dec, ctx, status);
  286. return;
  287. conversion_error:
  288. /* standard wants a positive NaN */
  289. mpd_seterror(dec, MPD_Conversion_syntax, status);
  290. }
  291. /* convert a character string to a decimal, use a maxcontext for conversion */
  292. void
  293. mpd_qset_string_exact(mpd_t *dec, const char *s, uint32_t *status)
  294. {
  295. mpd_context_t maxcontext;
  296. mpd_maxcontext(&maxcontext);
  297. mpd_qset_string(dec, s, &maxcontext, status);
  298. if (*status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
  299. /* we want exact results */
  300. mpd_seterror(dec, MPD_Invalid_operation, status);
  301. }
  302. *status &= MPD_Errors;
  303. }
  304. /* Print word x with n decimal digits to string s. dot is either NULL
  305. or the location of a decimal point. */
  306. #define EXTRACT_DIGIT(s, x, d, dot) \
  307. if (s == dot) *s++ = '.'; *s++ = '0' + (char)(x / d); x %= d
  308. static inline char *
  309. word_to_string(char *s, mpd_uint_t x, int n, char *dot)
  310. {
  311. switch(n) {
  312. #ifdef CONFIG_64
  313. case 20: EXTRACT_DIGIT(s, x, 10000000000000000000ULL, dot); /* GCOV_NOT_REACHED */
  314. case 19: EXTRACT_DIGIT(s, x, 1000000000000000000ULL, dot);
  315. case 18: EXTRACT_DIGIT(s, x, 100000000000000000ULL, dot);
  316. case 17: EXTRACT_DIGIT(s, x, 10000000000000000ULL, dot);
  317. case 16: EXTRACT_DIGIT(s, x, 1000000000000000ULL, dot);
  318. case 15: EXTRACT_DIGIT(s, x, 100000000000000ULL, dot);
  319. case 14: EXTRACT_DIGIT(s, x, 10000000000000ULL, dot);
  320. case 13: EXTRACT_DIGIT(s, x, 1000000000000ULL, dot);
  321. case 12: EXTRACT_DIGIT(s, x, 100000000000ULL, dot);
  322. case 11: EXTRACT_DIGIT(s, x, 10000000000ULL, dot);
  323. #endif
  324. case 10: EXTRACT_DIGIT(s, x, 1000000000UL, dot);
  325. case 9: EXTRACT_DIGIT(s, x, 100000000UL, dot);
  326. case 8: EXTRACT_DIGIT(s, x, 10000000UL, dot);
  327. case 7: EXTRACT_DIGIT(s, x, 1000000UL, dot);
  328. case 6: EXTRACT_DIGIT(s, x, 100000UL, dot);
  329. case 5: EXTRACT_DIGIT(s, x, 10000UL, dot);
  330. case 4: EXTRACT_DIGIT(s, x, 1000UL, dot);
  331. case 3: EXTRACT_DIGIT(s, x, 100UL, dot);
  332. case 2: EXTRACT_DIGIT(s, x, 10UL, dot);
  333. default: if (s == dot) *s++ = '.'; *s++ = '0' + (char)x;
  334. }
  335. *s = '\0';
  336. return s;
  337. }
  338. /* Print exponent x to string s. Undefined for MPD_SSIZE_MIN. */
  339. static inline char *
  340. exp_to_string(char *s, mpd_ssize_t x)
  341. {
  342. char sign = '+';
  343. if (x < 0) {
  344. sign = '-';
  345. x = -x;
  346. }
  347. *s++ = sign;
  348. return word_to_string(s, x, mpd_word_digits(x), NULL);
  349. }
  350. /* Print the coefficient of dec to string s. len(dec) > 0. */
  351. static inline char *
  352. coeff_to_string(char *s, const mpd_t *dec)
  353. {
  354. mpd_uint_t x;
  355. mpd_ssize_t i;
  356. /* most significant word */
  357. x = mpd_msword(dec);
  358. s = word_to_string(s, x, mpd_word_digits(x), NULL);
  359. /* remaining full words */
  360. for (i=dec->len-2; i >= 0; --i) {
  361. x = dec->data[i];
  362. s = word_to_string(s, x, MPD_RDIGITS, NULL);
  363. }
  364. return s;
  365. }
  366. /* Print the coefficient of dec to string s. len(dec) > 0. dot is either
  367. NULL or a pointer to the location of a decimal point. */
  368. static inline char *
  369. coeff_to_string_dot(char *s, char *dot, const mpd_t *dec)
  370. {
  371. mpd_uint_t x;
  372. mpd_ssize_t i;
  373. /* most significant word */
  374. x = mpd_msword(dec);
  375. s = word_to_string(s, x, mpd_word_digits(x), dot);
  376. /* remaining full words */
  377. for (i=dec->len-2; i >= 0; --i) {
  378. x = dec->data[i];
  379. s = word_to_string(s, x, MPD_RDIGITS, dot);
  380. }
  381. return s;
  382. }
  383. /* Format type */
  384. #define MPD_FMT_LOWER 0x00000000
  385. #define MPD_FMT_UPPER 0x00000001
  386. #define MPD_FMT_TOSCI 0x00000002
  387. #define MPD_FMT_TOENG 0x00000004
  388. #define MPD_FMT_EXP 0x00000008
  389. #define MPD_FMT_FIXED 0x00000010
  390. #define MPD_FMT_PERCENT 0x00000020
  391. #define MPD_FMT_SIGN_SPACE 0x00000040
  392. #define MPD_FMT_SIGN_PLUS 0x00000080
  393. /* Default place of the decimal point for MPD_FMT_TOSCI, MPD_FMT_EXP */
  394. #define MPD_DEFAULT_DOTPLACE 1
  395. /*
  396. * Set *result to the string representation of a decimal. Return the length
  397. * of *result, not including the terminating '\0' character.
  398. *
  399. * Formatting is done according to 'flags'. A return value of -1 with *result
  400. * set to NULL indicates MPD_Malloc_error.
  401. *
  402. * 'dplace' is the default place of the decimal point. It is always set to
  403. * MPD_DEFAULT_DOTPLACE except for zeros in combination with MPD_FMT_EXP.
  404. */
  405. static mpd_ssize_t
  406. _mpd_to_string(char **result, const mpd_t *dec, int flags, mpd_ssize_t dplace)
  407. {
  408. char *decstring = NULL, *cp = NULL;
  409. mpd_ssize_t ldigits;
  410. mpd_ssize_t mem = 0, k;
  411. if (mpd_isspecial(dec)) {
  412. mem = sizeof "-Infinity%";
  413. if (mpd_isnan(dec) && dec->len > 0) {
  414. /* diagnostic code */
  415. mem += dec->digits;
  416. }
  417. cp = decstring = mpd_alloc(mem, sizeof *decstring);
  418. if (cp == NULL) {
  419. *result = NULL;
  420. return -1;
  421. }
  422. if (mpd_isnegative(dec)) {
  423. *cp++ = '-';
  424. }
  425. else if (flags&MPD_FMT_SIGN_SPACE) {
  426. *cp++ = ' ';
  427. }
  428. else if (flags&MPD_FMT_SIGN_PLUS) {
  429. *cp++ = '+';
  430. }
  431. if (mpd_isnan(dec)) {
  432. if (mpd_isqnan(dec)) {
  433. strcpy(cp, "NaN");
  434. cp += 3;
  435. }
  436. else {
  437. strcpy(cp, "sNaN");
  438. cp += 4;
  439. }
  440. if (dec->len > 0) { /* diagnostic code */
  441. cp = coeff_to_string(cp, dec);
  442. }
  443. }
  444. else if (mpd_isinfinite(dec)) {
  445. strcpy(cp, "Infinity");
  446. cp += 8;
  447. }
  448. else { /* debug */
  449. abort(); /* GCOV_NOT_REACHED */
  450. }
  451. }
  452. else {
  453. assert(dec->len > 0);
  454. /*
  455. * For easier manipulation of the decimal point's location
  456. * and the exponent that is finally printed, the number is
  457. * rescaled to a virtual representation with exp = 0. Here
  458. * ldigits denotes the number of decimal digits to the left
  459. * of the decimal point and remains constant once initialized.
  460. *
  461. * dplace is the location of the decimal point relative to
  462. * the start of the coefficient. Note that 3) always holds
  463. * when dplace is shifted.
  464. *
  465. * 1) ldigits := dec->digits - dec->exp
  466. * 2) dplace := ldigits (initially)
  467. * 3) exp := ldigits - dplace (initially exp = 0)
  468. *
  469. * 0.00000_.____._____000000.
  470. * ^ ^ ^ ^
  471. * | | | |
  472. * | | | `- dplace >= digits
  473. * | | `- dplace in the middle of the coefficient
  474. * | ` dplace = 1 (after the first coefficient digit)
  475. * `- dplace <= 0
  476. */
  477. ldigits = dec->digits + dec->exp;
  478. if (flags&MPD_FMT_EXP) {
  479. ;
  480. }
  481. else if (flags&MPD_FMT_FIXED || (dec->exp <= 0 && ldigits > -6)) {
  482. /* MPD_FMT_FIXED: always use fixed point notation.
  483. * MPD_FMT_TOSCI, MPD_FMT_TOENG: for a certain range,
  484. * override exponent notation. */
  485. dplace = ldigits;
  486. }
  487. else if (flags&MPD_FMT_TOENG) {
  488. if (mpd_iszero(dec)) {
  489. /* If the exponent is divisible by three,
  490. * dplace = 1. Otherwise, move dplace one
  491. * or two places to the left. */
  492. dplace = -1 + mod_mpd_ssize_t(dec->exp+2, 3);
  493. }
  494. else { /* ldigits-1 is the adjusted exponent, which
  495. * should be divisible by three. If not, move
  496. * dplace one or two places to the right. */
  497. dplace += mod_mpd_ssize_t(ldigits-1, 3);
  498. }
  499. }
  500. /*
  501. * Basic space requirements:
  502. *
  503. * [-][.][coeffdigits][E][-][expdigits+1][%]['\0']
  504. *
  505. * If the decimal point lies outside of the coefficient digits,
  506. * space is adjusted accordingly.
  507. */
  508. if (dplace <= 0) {
  509. mem = -dplace + dec->digits + 2;
  510. }
  511. else if (dplace >= dec->digits) {
  512. mem = dplace;
  513. }
  514. else {
  515. mem = dec->digits;
  516. }
  517. mem += (MPD_EXPDIGITS+1+6);
  518. cp = decstring = mpd_alloc(mem, sizeof *decstring);
  519. if (cp == NULL) {
  520. *result = NULL;
  521. return -1;
  522. }
  523. if (mpd_isnegative(dec)) {
  524. *cp++ = '-';
  525. }
  526. else if (flags&MPD_FMT_SIGN_SPACE) {
  527. *cp++ = ' ';
  528. }
  529. else if (flags&MPD_FMT_SIGN_PLUS) {
  530. *cp++ = '+';
  531. }
  532. if (dplace <= 0) {
  533. /* space: -dplace+dec->digits+2 */
  534. *cp++ = '0';
  535. *cp++ = '.';
  536. for (k = 0; k < -dplace; k++) {
  537. *cp++ = '0';
  538. }
  539. cp = coeff_to_string(cp, dec);
  540. }
  541. else if (dplace >= dec->digits) {
  542. /* space: dplace */
  543. cp = coeff_to_string(cp, dec);
  544. for (k = 0; k < dplace-dec->digits; k++) {
  545. *cp++ = '0';
  546. }
  547. }
  548. else {
  549. /* space: dec->digits+1 */
  550. cp = coeff_to_string_dot(cp, cp+dplace, dec);
  551. }
  552. /*
  553. * Conditions for printing an exponent:
  554. *
  555. * MPD_FMT_TOSCI, MPD_FMT_TOENG: only if ldigits != dplace
  556. * MPD_FMT_FIXED: never (ldigits == dplace)
  557. * MPD_FMT_EXP: always
  558. */
  559. if (ldigits != dplace || flags&MPD_FMT_EXP) {
  560. /* space: expdigits+2 */
  561. *cp++ = (flags&MPD_FMT_UPPER) ? 'E' : 'e';
  562. cp = exp_to_string(cp, ldigits-dplace);
  563. }
  564. }
  565. if (flags&MPD_FMT_PERCENT) {
  566. *cp++ = '%';
  567. }
  568. assert(cp < decstring+mem);
  569. assert(cp-decstring < MPD_SSIZE_MAX);
  570. *cp = '\0';
  571. *result = decstring;
  572. return (mpd_ssize_t)(cp-decstring);
  573. }
  574. char *
  575. mpd_to_sci(const mpd_t *dec, int fmt)
  576. {
  577. char *res;
  578. int flags = MPD_FMT_TOSCI;
  579. flags |= fmt ? MPD_FMT_UPPER : MPD_FMT_LOWER;
  580. (void)_mpd_to_string(&res, dec, flags, MPD_DEFAULT_DOTPLACE);
  581. return res;
  582. }
  583. char *
  584. mpd_to_eng(const mpd_t *dec, int fmt)
  585. {
  586. char *res;
  587. int flags = MPD_FMT_TOENG;
  588. flags |= fmt ? MPD_FMT_UPPER : MPD_FMT_LOWER;
  589. (void)_mpd_to_string(&res, dec, flags, MPD_DEFAULT_DOTPLACE);
  590. return res;
  591. }
  592. mpd_ssize_t
  593. mpd_to_sci_size(char **res, const mpd_t *dec, int fmt)
  594. {
  595. int flags = MPD_FMT_TOSCI;
  596. flags |= fmt ? MPD_FMT_UPPER : MPD_FMT_LOWER;
  597. return _mpd_to_string(res, dec, flags, MPD_DEFAULT_DOTPLACE);
  598. }
  599. mpd_ssize_t
  600. mpd_to_eng_size(char **res, const mpd_t *dec, int fmt)
  601. {
  602. int flags = MPD_FMT_TOENG;
  603. flags |= fmt ? MPD_FMT_UPPER : MPD_FMT_LOWER;
  604. return _mpd_to_string(res, dec, flags, MPD_DEFAULT_DOTPLACE);
  605. }
  606. /* Copy a single UTF-8 char to dest. See: The Unicode Standard, version 5.2,
  607. chapter 3.9: Well-formed UTF-8 byte sequences. */
  608. static int
  609. _mpd_copy_utf8(char dest[5], const char *s)
  610. {
  611. const unsigned char *cp = (const unsigned char *)s;
  612. unsigned char lb, ub;
  613. int count, i;
  614. if (*cp == 0) {
  615. /* empty string */
  616. dest[0] = '\0';
  617. return 0;
  618. }
  619. else if (*cp <= 0x7f) {
  620. /* ascii */
  621. dest[0] = *cp;
  622. dest[1] = '\0';
  623. return 1;
  624. }
  625. else if (0xc2 <= *cp && *cp <= 0xdf) {
  626. lb = 0x80; ub = 0xbf;
  627. count = 2;
  628. }
  629. else if (*cp == 0xe0) {
  630. lb = 0xa0; ub = 0xbf;
  631. count = 3;
  632. }
  633. else if (*cp <= 0xec) {
  634. lb = 0x80; ub = 0xbf;
  635. count = 3;
  636. }
  637. else if (*cp == 0xed) {
  638. lb = 0x80; ub = 0x9f;
  639. count = 3;
  640. }
  641. else if (*cp <= 0xef) {
  642. lb = 0x80; ub = 0xbf;
  643. count = 3;
  644. }
  645. else if (*cp == 0xf0) {
  646. lb = 0x90; ub = 0xbf;
  647. count = 4;
  648. }
  649. else if (*cp <= 0xf3) {
  650. lb = 0x80; ub = 0xbf;
  651. count = 4;
  652. }
  653. else if (*cp == 0xf4) {
  654. lb = 0x80; ub = 0x8f;
  655. count = 4;
  656. }
  657. else {
  658. /* invalid */
  659. goto error;
  660. }
  661. dest[0] = *cp++;
  662. if (*cp < lb || ub < *cp) {
  663. goto error;
  664. }
  665. dest[1] = *cp++;
  666. for (i = 2; i < count; i++) {
  667. if (*cp < 0x80 || 0xbf < *cp) {
  668. goto error;
  669. }
  670. dest[i] = *cp++;
  671. }
  672. dest[i] = '\0';
  673. return count;
  674. error:
  675. dest[0] = '\0';
  676. return -1;
  677. }
  678. int
  679. mpd_validate_lconv(mpd_spec_t *spec)
  680. {
  681. size_t n;
  682. #if CHAR_MAX == SCHAR_MAX
  683. const char *cp = spec->grouping;
  684. while (*cp != '\0') {
  685. if (*cp++ < 0) {
  686. return -1;
  687. }
  688. }
  689. #endif
  690. n = strlen(spec->dot);
  691. if (n == 0 || n > 4) {
  692. return -1;
  693. }
  694. if (strlen(spec->sep) > 4) {
  695. return -1;
  696. }
  697. return 0;
  698. }
  699. int
  700. mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps)
  701. {
  702. char *cp = (char *)fmt;
  703. int have_align = 0, n;
  704. /* defaults */
  705. spec->min_width = 0;
  706. spec->prec = -1;
  707. spec->type = caps ? 'G' : 'g';
  708. spec->align = '>';
  709. spec->sign = '-';
  710. spec->dot = "";
  711. spec->sep = "";
  712. spec->grouping = "";
  713. /* presume that the first character is a UTF-8 fill character */
  714. if ((n = _mpd_copy_utf8(spec->fill, cp)) < 0) {
  715. return 0;
  716. }
  717. /* alignment directive, prefixed by a fill character */
  718. if (*cp && (*(cp+n) == '<' || *(cp+n) == '>' ||
  719. *(cp+n) == '=' || *(cp+n) == '^')) {
  720. cp += n;
  721. spec->align = *cp++;
  722. have_align = 1;
  723. } /* alignment directive */
  724. else {
  725. /* default fill character */
  726. spec->fill[0] = ' ';
  727. spec->fill[1] = '\0';
  728. if (*cp == '<' || *cp == '>' ||
  729. *cp == '=' || *cp == '^') {
  730. spec->align = *cp++;
  731. have_align = 1;
  732. }
  733. }
  734. /* sign formatting */
  735. if (*cp == '+' || *cp == '-' || *cp == ' ') {
  736. spec->sign = *cp++;
  737. }
  738. /* zero padding */
  739. if (*cp == '0') {
  740. /* zero padding implies alignment, which should not be
  741. * specified twice. */
  742. if (have_align) {
  743. return 0;
  744. }
  745. spec->align = 'z';
  746. spec->fill[0] = *cp++;
  747. spec->fill[1] = '\0';
  748. }
  749. /* minimum width */
  750. if (isdigit((unsigned char)*cp)) {
  751. if (*cp == '0') {
  752. return 0;
  753. }
  754. errno = 0;
  755. spec->min_width = mpd_strtossize(cp, &cp, 10);
  756. if (errno == ERANGE || errno == EINVAL) {
  757. return 0;
  758. }
  759. }
  760. /* thousands separator */
  761. if (*cp == ',') {
  762. spec->dot = ".";
  763. spec->sep = ",";
  764. spec->grouping = "\003\003";
  765. cp++;
  766. }
  767. /* fraction digits or significant digits */
  768. if (*cp == '.') {
  769. cp++;
  770. if (!isdigit((unsigned char)*cp)) {
  771. return 0;
  772. }
  773. errno = 0;
  774. spec->prec = mpd_strtossize(cp, &cp, 10);
  775. if (errno == ERANGE || errno == EINVAL) {
  776. return 0;
  777. }
  778. }
  779. /* type */
  780. if (*cp == 'E' || *cp == 'e' || *cp == 'F' || *cp == 'f' ||
  781. *cp == 'G' || *cp == 'g' || *cp == '%') {
  782. spec->type = *cp++;
  783. }
  784. else if (*cp == 'N' || *cp == 'n') {
  785. /* locale specific conversion */
  786. struct lconv *lc;
  787. /* separator has already been specified */
  788. if (*spec->sep) {
  789. return 0;
  790. }
  791. spec->type = *cp++;
  792. spec->type = (spec->type == 'N') ? 'G' : 'g';
  793. lc = localeconv();
  794. spec->dot = lc->decimal_point;
  795. spec->sep = lc->thousands_sep;
  796. spec->grouping = lc->grouping;
  797. if (mpd_validate_lconv(spec) < 0) {
  798. return 0; /* GCOV_NOT_REACHED */
  799. }
  800. }
  801. /* check correctness */
  802. if (*cp != '\0') {
  803. return 0;
  804. }
  805. return 1;
  806. }
  807. /*
  808. * The following functions assume that spec->min_width <= MPD_MAX_PREC, which
  809. * is made sure in mpd_qformat_spec. Then, even with a spec that inserts a
  810. * four-byte separator after each digit, nbytes in the following struct
  811. * cannot overflow.
  812. */
  813. /* Multibyte string */
  814. typedef struct {
  815. mpd_ssize_t nbytes; /* length in bytes */
  816. mpd_ssize_t nchars; /* length in chars */
  817. mpd_ssize_t cur; /* current write index */
  818. char *data;
  819. } mpd_mbstr_t;
  820. static inline void
  821. _mpd_bcopy(char *dest, const char *src, mpd_ssize_t n)
  822. {
  823. while (--n >= 0) {
  824. dest[n] = src[n];
  825. }
  826. }
  827. static inline void
  828. _mbstr_copy_char(mpd_mbstr_t *dest, const char *src, mpd_ssize_t n)
  829. {
  830. dest->nbytes += n;
  831. dest->nchars += (n > 0 ? 1 : 0);
  832. dest->cur -= n;
  833. if (dest->data != NULL) {
  834. _mpd_bcopy(dest->data+dest->cur, src, n);
  835. }
  836. }
  837. static inline void
  838. _mbstr_copy_ascii(mpd_mbstr_t *dest, const char *src, mpd_ssize_t n)
  839. {
  840. dest->nbytes += n;
  841. dest->nchars += n;
  842. dest->cur -= n;
  843. if (dest->data != NULL) {
  844. _mpd_bcopy(dest->data+dest->cur, src, n);
  845. }
  846. }
  847. static inline void
  848. _mbstr_copy_pad(mpd_mbstr_t *dest, mpd_ssize_t n)
  849. {
  850. dest->nbytes += n;
  851. dest->nchars += n;
  852. dest->cur -= n;
  853. if (dest->data != NULL) {
  854. char *cp = dest->data + dest->cur;
  855. while (--n >= 0) {
  856. cp[n] = '0';
  857. }
  858. }
  859. }
  860. /*
  861. * Copy a numeric string to dest->data, adding separators in the integer
  862. * part according to spec->grouping. If leading zero padding is enabled
  863. * and the result is smaller than spec->min_width, continue adding zeros
  864. * and separators until the minimum width is reached.
  865. *
  866. * The final length of dest->data is stored in dest->nbytes. The number
  867. * of UTF-8 characters is stored in dest->nchars.
  868. *
  869. * First run (dest->data == NULL): determine the length of the result
  870. * string and store it in dest->nbytes.
  871. *
  872. * Second run (write to dest->data): data is written in chunks and in
  873. * reverse order, starting with the rest of the numeric string.
  874. */
  875. static void
  876. _mpd_add_sep_dot(mpd_mbstr_t *dest,
  877. const char *sign, /* location of optional sign */
  878. const char *src, mpd_ssize_t n_src, /* integer part and length */
  879. const char *dot, /* location of optional decimal point */
  880. const char *rest, mpd_ssize_t n_rest, /* remaining part and length */
  881. const mpd_spec_t *spec)
  882. {
  883. mpd_ssize_t n_sep, n_sign, consume;
  884. const char *g;
  885. int pad = 0;
  886. n_sign = sign ? 1 : 0;
  887. n_sep = (mpd_ssize_t)strlen(spec->sep);
  888. /* Initial write index: set to location of '\0' in the output string.
  889. * Irrelevant for the first run. */
  890. dest->cur = dest->nbytes;
  891. dest->nbytes = dest->nchars = 0;
  892. _mbstr_copy_ascii(dest, rest, n_rest);
  893. if (dot) {
  894. _mbstr_copy_char(dest, dot, (mpd_ssize_t)strlen(dot));
  895. }
  896. g = spec->grouping;
  897. consume = *g;
  898. while (1) {
  899. /* If the group length is 0 or CHAR_MAX or greater than the
  900. * number of source bytes, consume all remaining bytes. */
  901. if (*g == 0 || *g == CHAR_MAX || consume > n_src) {
  902. consume = n_src;
  903. }
  904. n_src -= consume;
  905. if (pad) {
  906. _mbstr_copy_pad(dest, consume);
  907. }
  908. else {
  909. _mbstr_copy_ascii(dest, src+n_src, consume);
  910. }
  911. if (n_src == 0) {
  912. /* Either the real source of intpart digits or the virtual
  913. * source of padding zeros is exhausted. */
  914. if (spec->align == 'z' &&
  915. dest->nchars + n_sign < spec->min_width) {
  916. /* Zero padding is set and length < min_width:
  917. * Generate n_src additional characters. */
  918. n_src = spec->min_width - (dest->nchars + n_sign);
  919. /* Next iteration:
  920. * case *g == 0 || *g == CHAR_MAX:
  921. * consume all padding characters
  922. * case consume < g*:
  923. * fill remainder of current group
  924. * case consume == g*
  925. * copying is a no-op */
  926. consume = *g - consume;
  927. /* Switch on virtual source of zeros. */
  928. pad = 1;
  929. continue;
  930. }
  931. break;
  932. }
  933. if (n_sep > 0) {
  934. /* If padding is switched on, separators are counted
  935. * as padding characters. This rule does not apply if
  936. * the separator would be the first character of the
  937. * result string. */
  938. if (pad && n_src > 1) n_src -= 1;
  939. _mbstr_copy_char(dest, spec->sep, n_sep);
  940. }
  941. /* If non-NUL, use the next value for grouping. */
  942. if (*g && *(g+1)) g++;
  943. consume = *g;
  944. }
  945. if (sign) {
  946. _mbstr_copy_ascii(dest, sign, 1);
  947. }
  948. if (dest->data) {
  949. dest->data[dest->nbytes] = '\0';
  950. }
  951. }
  952. /*
  953. * Convert a numeric-string to its locale-specific appearance.
  954. * The string must have one of these forms:
  955. *
  956. * 1) [sign] digits [exponent-part]
  957. * 2) [sign] digits '.' [digits] [exponent-part]
  958. *
  959. * Not allowed, since _mpd_to_string() never returns this form:
  960. *
  961. * 3) [sign] '.' digits [exponent-part]
  962. *
  963. * Input: result->data := original numeric string (ASCII)
  964. * result->bytes := strlen(result->data)
  965. * result->nchars := strlen(result->data)
  966. *
  967. * Output: result->data := modified or original string
  968. * result->bytes := strlen(result->data)
  969. * result->nchars := number of characters (possibly UTF-8)
  970. */
  971. static int
  972. _mpd_apply_lconv(mpd_mbstr_t *result, const mpd_spec_t *spec, uint32_t *status)
  973. {
  974. const char *sign = NULL, *intpart = NULL, *dot = NULL;
  975. const char *rest, *dp;
  976. char *decstring;
  977. mpd_ssize_t n_int, n_rest;
  978. /* original numeric string */
  979. dp = result->data;
  980. /* sign */
  981. if (*dp == '+' || *dp == '-' || *dp == ' ') {
  982. sign = dp++;
  983. }
  984. /* integer part */
  985. assert(isdigit((unsigned char)*dp));
  986. intpart = dp++;
  987. while (isdigit((unsigned char)*dp)) {
  988. dp++;
  989. }
  990. n_int = (mpd_ssize_t)(dp-intpart);
  991. /* decimal point */
  992. if (*dp == '.') {
  993. dp++; dot = spec->dot;
  994. }
  995. /* rest */
  996. rest = dp;
  997. n_rest = result->nbytes - (mpd_ssize_t)(dp-result->data);
  998. if (dot == NULL && (*spec->sep == '\0' || *spec->grouping == '\0')) {
  999. /* _mpd_add_sep_dot() would not change anything */
  1000. return 1;
  1001. }
  1002. /* Determine the size of the new decimal string after inserting the
  1003. * decimal point, optional separators and optional padding. */
  1004. decstring = result->data;
  1005. result->data = NULL;
  1006. _mpd_add_sep_dot(result, sign, intpart, n_int, dot,
  1007. rest, n_rest, spec);
  1008. result->data = mpd_alloc(result->nbytes+1, 1);
  1009. if (result->data == NULL) {
  1010. *status |= MPD_Malloc_error;
  1011. mpd_free(decstring);
  1012. return 0;
  1013. }
  1014. /* Perform actual writes. */
  1015. _mpd_add_sep_dot(result, sign, intpart, n_int, dot,
  1016. rest, n_rest, spec);
  1017. mpd_free(decstring);
  1018. return 1;
  1019. }
  1020. /* Add padding to the formatted string if necessary. */
  1021. static int
  1022. _mpd_add_pad(mpd_mbstr_t *result, const mpd_spec_t *spec, uint32_t *status)
  1023. {
  1024. if (result->nchars < spec->min_width) {
  1025. mpd_ssize_t add_chars, add_bytes;
  1026. size_t lpad = 0, rpad = 0;
  1027. size_t n_fill, len, i, j;
  1028. char align = spec->align;
  1029. uint8_t err = 0;
  1030. char *cp;
  1031. n_fill = strlen(spec->fill);
  1032. add_chars = (spec->min_width - result->nchars);
  1033. /* max value: MPD_MAX_PREC * 4 */
  1034. add_bytes = add_chars * (mpd_ssize_t)n_fill;
  1035. cp = result->data = mpd_realloc(result->data,
  1036. result->nbytes+add_bytes+1,
  1037. sizeof *result->data, &err);
  1038. if (err) {
  1039. *status |= MPD_Malloc_error;
  1040. mpd_free(result->data);
  1041. return 0;
  1042. }
  1043. if (align == 'z') {
  1044. align = '=';
  1045. }
  1046. if (align == '<') {
  1047. rpad = add_chars;
  1048. }
  1049. else if (align == '>' || align == '=') {
  1050. lpad = add_chars;
  1051. }
  1052. else { /* align == '^' */
  1053. lpad = add_chars/2;
  1054. rpad = add_chars-lpad;
  1055. }
  1056. len = result->nbytes;
  1057. if (align == '=' && (*cp == '-' || *cp == '+' || *cp == ' ')) {
  1058. /* leave sign in the leading position */
  1059. cp++; len--;
  1060. }
  1061. memmove(cp+n_fill*lpad, cp, len);
  1062. for (i = 0; i < lpad; i++) {
  1063. for (j = 0; j < n_fill; j++) {
  1064. cp[i*n_fill+j] = spec->fill[j];
  1065. }
  1066. }
  1067. cp += (n_fill*lpad + len);
  1068. for (i = 0; i < rpad; i++) {
  1069. for (j = 0; j < n_fill; j++) {
  1070. cp[i*n_fill+j] = spec->fill[j];
  1071. }
  1072. }
  1073. result->nbytes += add_bytes;
  1074. result->nchars += add_chars;
  1075. result->data[result->nbytes] = '\0';
  1076. }
  1077. return 1;
  1078. }
  1079. /* Round a number to prec digits. The adjusted exponent stays the same
  1080. or increases by one if rounding up crosses a power of ten boundary.
  1081. If result->digits would exceed MPD_MAX_PREC+1, MPD_Invalid_operation
  1082. is set and the result is NaN. */
  1083. static inline void
  1084. _mpd_round(mpd_t *result, const mpd_t *a, mpd_ssize_t prec,
  1085. const mpd_context_t *ctx, uint32_t *status)
  1086. {
  1087. mpd_ssize_t exp = a->exp + a->digits - prec;
  1088. if (prec <= 0) {
  1089. mpd_seterror(result, MPD_Invalid_operation, status); /* GCOV_NOT_REACHED */
  1090. return; /* GCOV_NOT_REACHED */
  1091. }
  1092. if (mpd_isspecial(a) || mpd_iszero(a)) {
  1093. mpd_qcopy(result, a, status); /* GCOV_NOT_REACHED */
  1094. return; /* GCOV_NOT_REACHED */
  1095. }
  1096. mpd_qrescale_fmt(result, a, exp, ctx, status);
  1097. if (result->digits > prec) {
  1098. mpd_qrescale_fmt(result, result, exp+1, ctx, status);
  1099. }
  1100. }
  1101. /*
  1102. * Return the string representation of an mpd_t, formatted according to 'spec'.
  1103. * The format specification is assumed to be valid. Memory errors are indicated
  1104. * as usual. This function is quiet.
  1105. */
  1106. char *
  1107. mpd_qformat_spec(const mpd_t *dec, const mpd_spec_t *spec,
  1108. const mpd_context_t *ctx, uint32_t *status)
  1109. {
  1110. mpd_uint_t dt[MPD_MINALLOC_MAX];
  1111. mpd_t tmp = {MPD_STATIC|MPD_STATIC_DATA,0,0,0,MPD_MINALLOC_MAX,dt};
  1112. mpd_ssize_t dplace = MPD_DEFAULT_DOTPLACE;
  1113. mpd_mbstr_t result;
  1114. mpd_spec_t stackspec;
  1115. char type = spec->type;
  1116. int flags = 0;
  1117. if (spec->min_width > MPD_MAX_PREC) {
  1118. *status |= MPD_Invalid_operation;
  1119. return NULL;
  1120. }
  1121. if (isupper((unsigned char)type)) {
  1122. type = (char)tolower((unsigned char)type);
  1123. flags |= MPD_FMT_UPPER;
  1124. }
  1125. if (spec->sign == ' ') {
  1126. flags |= MPD_FMT_SIGN_SPACE;
  1127. }
  1128. else if (spec->sign == '+') {
  1129. flags |= MPD_FMT_SIGN_PLUS;
  1130. }
  1131. if (mpd_isspecial(dec)) {
  1132. if (spec->align == 'z') {
  1133. stackspec = *spec;
  1134. stackspec.fill[0] = ' ';
  1135. stackspec.fill[1] = '\0';
  1136. stackspec.align = '>';
  1137. spec = &stackspec;
  1138. }
  1139. assert(strlen(spec->fill) == 1); /* annotation for scan-build */
  1140. if (type == '%') {
  1141. flags |= MPD_FMT_PERCENT;
  1142. }
  1143. }
  1144. else {
  1145. uint32_t workstatus = 0;
  1146. mpd_ssize_t prec;
  1147. switch (type) {
  1148. case 'g': flags |= MPD_FMT_TOSCI; break;
  1149. case 'e': flags |= MPD_FMT_EXP; break;
  1150. case '%': flags |= MPD_FMT_PERCENT;
  1151. if (!mpd_qcopy(&tmp, dec, status)) {
  1152. return NULL;
  1153. }
  1154. tmp.exp += 2;
  1155. dec = &tmp;
  1156. type = 'f'; /* fall through */
  1157. case 'f': flags |= MPD_FMT_FIXED; break;
  1158. default: abort(); /* debug: GCOV_NOT_REACHED */
  1159. }
  1160. if (spec->prec >= 0) {
  1161. if (spec->prec > MPD_MAX_PREC) {
  1162. *status |= MPD_Invalid_operation;
  1163. goto error;
  1164. }
  1165. switch (type) {
  1166. case 'g':
  1167. prec = (spec->prec == 0) ? 1 : spec->prec;
  1168. if (dec->digits > prec) {
  1169. _mpd_round(&tmp, dec, prec, ctx,
  1170. &workstatus);
  1171. dec = &tmp;
  1172. }
  1173. break;
  1174. case 'e':
  1175. if (mpd_iszero(dec)) {
  1176. dplace = 1-spec->prec;
  1177. }
  1178. else {
  1179. _mpd_round(&tmp, dec, spec->prec+1, ctx,
  1180. &workstatus);
  1181. dec = &tmp;
  1182. }
  1183. break;
  1184. case 'f':
  1185. mpd_qrescale(&tmp, dec, -spec->prec, ctx,
  1186. &workstatus);
  1187. dec = &tmp;
  1188. break;
  1189. }
  1190. }
  1191. if (type == 'f') {
  1192. if (mpd_iszero(dec) && dec->exp > 0) {
  1193. mpd_qrescale(&tmp, dec, 0, ctx, &workstatus);
  1194. dec = &tmp;
  1195. }
  1196. }
  1197. if (workstatus&MPD_Errors) {
  1198. *status |= (workstatus&MPD_Errors);
  1199. goto error;
  1200. }
  1201. }
  1202. /*
  1203. * At this point, for all scaled or non-scaled decimals:
  1204. * 1) 1 <= digits <= MAX_PREC+1
  1205. * 2) adjexp(scaled) = adjexp(orig) [+1]
  1206. * 3) case 'g': MIN_ETINY <= exp <= MAX_EMAX+1
  1207. * case 'e': MIN_ETINY-MAX_PREC <= exp <= MAX_EMAX+1
  1208. * case 'f': MIN_ETINY <= exp <= MAX_EMAX+1
  1209. * 4) max memory alloc in _mpd_to_string:
  1210. * case 'g': MAX_PREC+36
  1211. * case 'e': MAX_PREC+36
  1212. * case 'f': 2*MPD_MAX_PREC+30
  1213. */
  1214. result.nbytes = _mpd_to_string(&result.data, dec, flags, dplace);
  1215. result.nchars = result.nbytes;
  1216. if (result.nbytes < 0) {
  1217. *status |= MPD_Malloc_error;
  1218. goto error;
  1219. }
  1220. if (*spec->dot != '\0' && !mpd_isspecial(dec)) {
  1221. if (result.nchars > MPD_MAX_PREC+36) {
  1222. /* Since a group length of one is not explicitly
  1223. * disallowed, ensure that it is always possible to
  1224. * insert a four byte separator after each digit. */
  1225. *status |= MPD_Invalid_operation;
  1226. mpd_free(result.data);
  1227. goto error;
  1228. }
  1229. if (!_mpd_apply_lconv(&result, spec, status)) {
  1230. goto error;
  1231. }
  1232. }
  1233. if (spec->min_width) {
  1234. if (!_mpd_add_pad(&result, spec, status)) {
  1235. goto error;
  1236. }
  1237. }
  1238. mpd_del(&tmp);
  1239. return result.data;
  1240. error:
  1241. mpd_del(&tmp);
  1242. return NULL;
  1243. }
  1244. char *
  1245. mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx,
  1246. uint32_t *status)
  1247. {
  1248. mpd_spec_t spec;
  1249. if (!mpd_parse_fmt_str(&spec, fmt, 1)) {
  1250. *status |= MPD_Invalid_operation;
  1251. return NULL;
  1252. }
  1253. return mpd_qformat_spec(dec, &spec, ctx, status);
  1254. }
  1255. /*
  1256. * The specification has a *condition* called Invalid_operation and an
  1257. * IEEE *signal* called Invalid_operation. The former corresponds to
  1258. * MPD_Invalid_operation, the latter to MPD_IEEE_Invalid_operation.
  1259. * MPD_IEEE_Invalid_operation comprises the following conditions:
  1260. *
  1261. * [MPD_Conversion_syntax, MPD_Division_impossible, MPD_Division_undefined,
  1262. * MPD_Fpu_error, MPD_Invalid_context, MPD_Invalid_operation,
  1263. * MPD_Malloc_error]
  1264. *
  1265. * In the following functions, 'flag' denotes the condition, 'signal'
  1266. * denotes the IEEE signal.
  1267. */
  1268. static const char *mpd_flag_string[MPD_NUM_FLAGS] = {
  1269. "Clamped",
  1270. "Conversion_syntax",
  1271. "Division_by_zero",
  1272. "Division_impossible",
  1273. "Division_undefined",
  1274. "Fpu_error",
  1275. "Inexact",
  1276. "Invalid_context",
  1277. "Invalid_operation",
  1278. "Malloc_error",
  1279. "Not_implemented",
  1280. "Overflow",
  1281. "Rounded",
  1282. "Subnormal",
  1283. "Underflow",
  1284. };
  1285. static const char *mpd_signal_string[MPD_NUM_FLAGS] = {
  1286. "Clamped",
  1287. "IEEE_Invalid_operation",
  1288. "Division_by_zero",
  1289. "IEEE_Invalid_operation",
  1290. "IEEE_Invalid_operation",
  1291. "IEEE_Invalid_operation",
  1292. "Inexact",
  1293. "IEEE_Invalid_operation",
  1294. "IEEE_Invalid_operation",
  1295. "IEEE_Invalid_operation",
  1296. "Not_implemented",
  1297. "Overflow",
  1298. "Rounded",
  1299. "Subnormal",
  1300. "Underflow",
  1301. };
  1302. /* print conditions to buffer, separated by spaces */
  1303. int
  1304. mpd_snprint_flags(char *dest, int nmemb, uint32_t flags)
  1305. {
  1306. char *cp;
  1307. int n, j;
  1308. assert(nmemb >= MPD_MAX_FLAG_STRING);
  1309. *dest = '\0'; cp = dest;
  1310. for (j = 0; j < MPD_NUM_FLAGS; j++) {
  1311. if (flags & (1U<<j)) {
  1312. n = snprintf(cp, nmemb, "%s ", mpd_flag_string[j]);
  1313. if (n < 0 || n >= nmemb) return -1;
  1314. cp += n; nmemb -= n;
  1315. }
  1316. }
  1317. if (cp != dest) {
  1318. *(--cp) = '\0';
  1319. }
  1320. return (int)(cp-dest);
  1321. }
  1322. /* print conditions to buffer, in list form */
  1323. int
  1324. mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[])
  1325. {
  1326. char *cp;
  1327. int n, j;
  1328. assert(nmemb >= MPD_MAX_FLAG_LIST);
  1329. if (flag_string == NULL) {
  1330. flag_string = mpd_flag_string;
  1331. }
  1332. *dest = '[';
  1333. *(dest+1) = '\0';
  1334. cp = dest+1;
  1335. --nmemb;
  1336. for (j = 0; j < MPD_NUM_FLAGS; j++) {
  1337. if (flags & (1U<<j)) {
  1338. n = snprintf(cp, nmemb, "%s, ", flag_string[j]);
  1339. if (n < 0 || n >= nmemb) return -1;
  1340. cp += n; nmemb -= n;
  1341. }
  1342. }
  1343. /* erase the last ", " */
  1344. if (cp != dest+1) {
  1345. cp -= 2;
  1346. }
  1347. *cp++ = ']';
  1348. *cp = '\0';
  1349. return (int)(cp-dest); /* strlen, without NUL terminator */
  1350. }
  1351. /* print signals to buffer, in list form */
  1352. int
  1353. mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[])
  1354. {
  1355. char *cp;
  1356. int n, j;
  1357. int ieee_invalid_done = 0;
  1358. assert(nmemb >= MPD_MAX_SIGNAL_LIST);
  1359. if (signal_string == NULL) {
  1360. signal_string = mpd_signal_string;
  1361. }
  1362. *dest = '[';
  1363. *(dest+1) = '\0';
  1364. cp = dest+1;
  1365. --nmemb;
  1366. for (j = 0; j < MPD_NUM_FLAGS; j++) {
  1367. uint32_t f = flags & (1U<<j);
  1368. if (f) {
  1369. if (f&MPD_IEEE_Invalid_operation) {
  1370. if (ieee_invalid_done) {
  1371. continue;
  1372. }
  1373. ieee_invalid_done = 1;
  1374. }
  1375. n = snprintf(cp, nmemb, "%s, ", signal_string[j]);
  1376. if (n < 0 || n >= nmemb) return -1;
  1377. cp += n; nmemb -= n;
  1378. }
  1379. }
  1380. /* erase the last ", " */
  1381. if (cp != dest+1) {
  1382. cp -= 2;
  1383. }
  1384. *cp++ = ']';
  1385. *cp = '\0';
  1386. return (int)(cp-dest); /* strlen, without NUL terminator */
  1387. }
  1388. /* The following two functions are mainly intended for debugging. */
  1389. void
  1390. mpd_fprint(FILE *file, const mpd_t *dec)
  1391. {
  1392. char *decstring;
  1393. decstring = mpd_to_sci(dec, 1);
  1394. if (decstring != NULL) {
  1395. fprintf(file, "%s\n", decstring);
  1396. mpd_free(decstring);
  1397. }
  1398. else {
  1399. fputs("mpd_fprint: output error\n", file); /* GCOV_NOT_REACHED */
  1400. }
  1401. }
  1402. void
  1403. mpd_print(const mpd_t *dec)
  1404. {
  1405. char *decstring;
  1406. decstring = mpd_to_sci(dec, 1);
  1407. if (decstring != NULL) {
  1408. printf("%s\n", decstring);
  1409. mpd_free(decstring);
  1410. }
  1411. else {
  1412. fputs("mpd_fprint: output error\n", stderr); /* GCOV_NOT_REACHED */
  1413. }
  1414. }