static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags, FAR void *p) { union { uint32_t dw; FAR void *p; } u; uint8_t bits; /* Check for alternate form */ if (IS_ALTFORM(flags)) { /* Prefix the number with "0x" */ obj->put(obj, '0'); obj->put(obj, 'x'); } u.dw = 0; u.p = p; for (bits = 8*sizeof(void *); bits > 0; bits -= 4) { uint8_t nibble = (uint8_t)((u.dw >> (bits - 4)) & 0xf); if (nibble < 10) { obj->put(obj, nibble + '0'); } else { obj->put(obj, nibble + 'a' - 10); } } }
static void llutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned long long lln) { /* Perform the integer conversion according to the format specifier */ switch (fmt) { case 'd': case 'i': /* Signed base 10 */ { #ifdef CONFIG_NOPRINTF_FIELDWIDTH if ((long long)lln < 0) { obj->put(obj, '-'); lln = (unsigned long long)(-(long long)lln); } else if (IS_SHOWPLUS(flags)) { obj->put(obj, '+'); } #endif /* Convert the unsigned value to a string. */ llutodec(obj, (unsigned long long)lln); } break; case 'u': /* Unigned base 10 */ { #ifdef CONFIG_NOPRINTF_FIELDWIDTH if (IS_SHOWPLUS(flags)) { obj->put(obj, '+'); } #endif /* Convert the unsigned value to a string. */ llutodec(obj, (unsigned long long)lln); } break; case 'x': case 'X': /* Hexadecimal */ { /* Check for alternate form */ if (IS_ALTFORM(flags)) { /* Prefix the number with "0x" */ obj->put(obj, '0'); obj->put(obj, 'x'); } /* Convert the unsigned value to a string. */ if (fmt == 'X') { llutohex(obj, (unsigned long long)lln, 'A'); } else { llutohex(obj, (unsigned long long)lln, 'a'); } } break; case 'o': /* Octal */ { /* Check for alternate form */ if (IS_ALTFORM(flags)) { /* Prefix the number with '0' */ obj->put(obj, '0'); } /* Convert the unsigned value to a string. */ llutooct(obj, (unsigned long long)lln); } break; case 'b': /* Binary */ { /* Convert the unsigned value to a string. */ llutobin(obj, (unsigned long long)lln); } break; case 'p': default: break; } }
static char* cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch, int *length) { int mode, dsgn; char *digits, *bp, *rve; if (ch == 'f') { mode = 3; /* ndigits after the decimal point */ } else { /* To obtain ndigits after the decimal point for the 'e' and 'E' * formats, round to ndigits + 1 significant figures. */ if (ch == 'e' || ch == 'E') { ndigits++; } mode = 2; /* ndigits significant digits */ } if (value < 0) { value = -value; *sign = '-'; } else { *sign = '\000'; } digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); if ((ch != 'g' && ch != 'G') || IS_ALTFORM(flags)) { /* Print trailing zeros */ bp = digits + ndigits; if (ch == 'f') { if (*digits == '0' && value) { *decpt = -ndigits + 1; } bp += *decpt; } if (value == 0) { /* kludge for __dtoa irregularity */ rve = bp; } while (rve < bp) { *rve++ = '0'; } } *length = rve - digits; return digits; }
static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, uint8_t flags, double value) { FAR char *digits; /* String returned by __dtoa */ FAR char *digalloc; /* Copy of digits to be freed after usage */ FAR char *rve; /* Points to the end of the return value */ int expt; /* Integer value of exponent */ int numlen; /* Actual number of digits returned by cvt */ int nchars; /* Number of characters to print */ int dsgn; /* Unused sign indicator */ int i; /* Special handling for NaN and Infinity */ if (isnan(value)) { lib_dtoa_string(obj, "NaN"); return; } if (isinf(value)) { if (value < 0.0) { obj->put(obj, '-'); } lib_dtoa_string(obj, "Infinity"); return; } /* Non-zero... positive or negative */ if (value < 0) { value = -value; SET_NEGATE(flags); } /* Perform the conversion */ digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve); digalloc = digits; numlen = rve - digits; if (IS_NEGATE(flags)) { obj->put(obj, '-'); } else if (IS_SHOWPLUS(flags)) { obj->put(obj, '+'); } /* Special case exact zero or the case where the number is smaller than * the print precision. */ if (value == 0 || expt < -prec) { /* kludge for __dtoa irregularity */ obj->put(obj, '0'); /* A decimal point is printed only in the alternate form or if a * particular precision is requested. */ if (prec > 0 || IS_ALTFORM(flags)) { obj->put(obj, '.'); /* Always print at least one digit to the right of the decimal point. */ prec = MAX(1, prec); } } /* A non-zero value will be printed */ else { /* Handle the case where the value is less than 1.0 (in magnitude) and * will need a leading zero. */ if (expt <= 0) { /* Print a single zero to the left of the decimal point */ obj->put(obj, '0'); /* Print the decimal point */ obj->put(obj, '.'); /* Print any leading zeros to the right of the decimal point */ if (expt < 0) { nchars = MIN(-expt, prec); zeroes(obj, nchars); prec -= nchars; } } /* Handle the general case where the value is greater than 1.0 (in * magnitude). */ else { /* Print the integer part to the left of the decimal point */ for (i = expt; i > 0; i--) { if (*digits != '\0') { obj->put(obj, *digits); digits++; } else { obj->put(obj, '0'); } } /* Get the length of the fractional part */ numlen -= expt; /* If there is no fractional part, then a decimal point is printed * only in the alternate form or if a particular precision is * requested. */ if (numlen > 0 || prec > 0 || IS_ALTFORM(flags)) { /* Print the decimal point */ obj->put(obj, '.'); /* Always print at least one digit to the right of the decimal * point. */ prec = MAX(1, prec); } } /* If a precision was specified, then limit the number digits to the * right of the decimal point. */ if (prec > 0) { nchars = MIN(numlen, prec); } else { nchars = numlen; } /* Print the fractional part to the right of the decimal point */ for (i = nchars; i > 0; i--) { obj->put(obj, *digits); digits++; } /* Decremnt to get the number of trailing zeroes to print */ prec -= nchars; } /* Finally, print any trailing zeroes */ zeroes(obj, prec); /* Is this memory supposed to be freed or not? */ #if 0 if (digalloc) { lib_free(digalloc); } #endif }
static void lib_dtoa(FAR struct lib_outstream_s *obj, int ch, int prec, uint8_t flags, double _double) { FAR char *cp; /* Handy char pointer (short term usage) */ FAR char *cp_free = NULL; /* BIONIC: copy of cp to be freed after usage */ char expstr[7]; /* Buffer for exponent string */ char sign; /* Temporary negative sign for floats */ int expt; /* Integer value of exponent */ int expsize = 0; /* Character count for expstr */ int ndig; /* Actual number of digits returned by cvt */ int size; /* Size of converted field or string */ int i; cp = cvt(_double, prec, flags, &sign, &expt, ch, &ndig); cp_free = cp; if (ch == 'g' || ch == 'G') { /* 'g' or 'G' fmt */ if (expt <= -4 || expt > prec) { ch = (ch == 'g') ? 'e' : 'E'; } else { ch = 'g'; } } if (ch <= 'e') { /* 'e' or 'E' fmt */ --expt; expsize = exponent(expstr, expt, ch); size = expsize + ndig; if (ndig > 1 || IS_ALTFORM(flags)) { ++size; } } else if (ch == 'f') { /* f fmt */ if (expt > 0) { size = expt; if (prec || IS_ALTFORM(flags)) { size += prec + 1; } } else /* "0.X" */ { size = prec + 2; } } else if (expt >= ndig) { /* fixed g fmt */ size = expt; if (IS_ALTFORM(flags)) { ++size; } } else { size = ndig + (expt > 0 ? 1 : 2 - expt); } if (sign) { obj->put(obj, '-'); } if (_double == 0) { /* kludge for __dtoa irregularity */ obj->put(obj, '0'); if (expt < ndig || IS_ALTFORM(flags)) { obj->put(obj, '.'); i = ndig - 1; while (i > 0) { obj->put(obj, '0'); i--; } } } else if (expt <= 0) { obj->put(obj, '0'); obj->put(obj, '.'); i = ndig; while (i > 0) { obj->put(obj, *cp); i--; cp++; } } else if (expt >= ndig) { i = ndig; while (i > 0) { obj->put(obj, *cp); i--; cp++; } i = expt - ndig; while (i > 0) { obj->put(obj, '0'); i--; } if (IS_ALTFORM(flags)) { obj->put(obj, '.'); } } else { /* print the integer */ i = expt; while (i > 0) { obj->put(obj, *cp); i--; cp++; } /* print the decimal place */ obj->put(obj, '.'); /* print the decimal */ i = ndig - expt; while (i > 0) { obj->put(obj, *cp); i--; cp++; } } }