Annotation of embedaddon/ntp/libntp/dolfptoa.c, revision 1.1
1.1 ! misho 1: /*
! 2: * dolfptoa - do the grunge work of converting an l_fp number to decimal
! 3: */
! 4: #include <stdio.h>
! 5:
! 6: #include "ntp_fp.h"
! 7: #include "lib_strbuf.h"
! 8: #include "ntp_string.h"
! 9: #include "ntp_stdlib.h"
! 10:
! 11: char *
! 12: dolfptoa(
! 13: u_long fpi,
! 14: u_long fpv,
! 15: int neg,
! 16: short ndec,
! 17: int msec
! 18: )
! 19: {
! 20: register u_char *cp, *cpend;
! 21: register u_long lwork;
! 22: register int dec;
! 23: u_char cbuf[24];
! 24: u_char *cpdec;
! 25: char *buf;
! 26: char *bp;
! 27:
! 28: /*
! 29: * Get a string buffer before starting
! 30: */
! 31: LIB_GETBUF(buf);
! 32:
! 33: /*
! 34: * Zero the character buffer
! 35: */
! 36: memset((char *) cbuf, 0, sizeof(cbuf));
! 37:
! 38: /*
! 39: * safeguard against sign extensions and other mishaps on 64 bit platforms
! 40: * the code following is designed for and only for 32-bit inputs and
! 41: * only 32-bit worth of input are supplied.
! 42: */
! 43: fpi &= 0xffffffff;
! 44: fpv &= 0xffffffff;
! 45:
! 46: /*
! 47: * Work on the integral part. This is biased by what I know
! 48: * compiles fairly well for a 68000.
! 49: */
! 50: cp = cpend = &cbuf[10];
! 51: lwork = fpi;
! 52: if (lwork & 0xffff0000) {
! 53: register u_long lten = 10;
! 54: register u_long ltmp;
! 55:
! 56: do {
! 57: ltmp = lwork;
! 58: lwork /= lten;
! 59: ltmp -= (lwork << 3) + (lwork << 1);
! 60: if (cp < cbuf) abort(); /* rather die a horrible death than trash the memory */
! 61: *--cp = (u_char)ltmp;
! 62: } while (lwork & 0xffff0000);
! 63: }
! 64: if (lwork != 0) {
! 65: register u_short sten = 10;
! 66: register u_short stmp;
! 67: register u_short swork = (u_short)lwork;
! 68:
! 69: do {
! 70: stmp = swork;
! 71: swork = (u_short) (swork/sten);
! 72: stmp = (u_short)(stmp - ((swork<<3) + (swork<<1)));
! 73: if (cp < cbuf) abort(); /* rather die a horrible death than trash the memory */
! 74: *--cp = (u_char)stmp;
! 75: } while (swork != 0);
! 76: }
! 77:
! 78: /*
! 79: * Done that, now deal with the problem of the fraction. First
! 80: * determine the number of decimal places.
! 81: */
! 82: if (msec) {
! 83: dec = ndec + 3;
! 84: if (dec < 3)
! 85: dec = 3;
! 86: cpdec = &cbuf[13];
! 87: } else {
! 88: dec = ndec;
! 89: if (dec < 0)
! 90: dec = 0;
! 91: cpdec = &cbuf[10];
! 92: }
! 93: if (dec > 12)
! 94: dec = 12;
! 95:
! 96: /*
! 97: * If there's a fraction to deal with, do so.
! 98: */
! 99: if (fpv != 0) {
! 100: l_fp work;
! 101:
! 102: work.l_ui = 0;
! 103: work.l_uf = fpv;
! 104: while (dec > 0) {
! 105: l_fp ftmp;
! 106:
! 107: dec--;
! 108: /*
! 109: * The scheme here is to multiply the
! 110: * fraction (0.1234...) by ten. This moves
! 111: * a junk of BCD into the units part.
! 112: * record that and iterate.
! 113: */
! 114: work.l_ui = 0;
! 115: L_LSHIFT(&work);
! 116: ftmp = work;
! 117: L_LSHIFT(&work);
! 118: L_LSHIFT(&work);
! 119: L_ADD(&work, &ftmp);
! 120: *cpend++ = (u_char)work.l_ui;
! 121: if (work.l_uf == 0)
! 122: break;
! 123: if (cpend > (cbuf + sizeof(cbuf))) abort(); /* rather die a horrible death than trash the memory */
! 124: }
! 125:
! 126: /*
! 127: * Rounding is rotten
! 128: */
! 129: if (work.l_uf & 0x80000000) {
! 130: register u_char *tp = cpend;
! 131:
! 132: *(--tp) += 1;
! 133: while (*tp >= 10) {
! 134: *tp = 0;
! 135: *(--tp) += 1;
! 136: };
! 137: if (tp < cp)
! 138: cp = tp;
! 139: }
! 140: }
! 141: cpend += dec;
! 142:
! 143:
! 144: /*
! 145: * We've now got the fraction in cbuf[], with cp pointing at
! 146: * the first character, cpend pointing past the last, and
! 147: * cpdec pointing at the first character past the decimal.
! 148: * Remove leading zeros, then format the number into the
! 149: * buffer.
! 150: */
! 151: while (cp < cpdec) {
! 152: if (*cp != 0)
! 153: break;
! 154: cp++;
! 155: }
! 156: if (cp == cpdec)
! 157: --cp;
! 158:
! 159: bp = buf;
! 160: if (neg)
! 161: *bp++ = '-';
! 162: while (cp < cpend) {
! 163: if (cp == cpdec)
! 164: *bp++ = '.';
! 165: *bp++ = (char)(*cp++ + '0'); /* ascii dependent? */
! 166: }
! 167: *bp = '\0';
! 168:
! 169: /*
! 170: * Done!
! 171: */
! 172: return buf;
! 173: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>