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>