Coverage Report

Created: 2026-02-26 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ntp-dev/libntp/dolfptoa.c
Line
Count
Source
1
/*
2
 * dolfptoa - do the grunge work of converting an l_fp number to decimal
3
 */
4
#include <config.h>
5
#include <stdio.h>
6
7
#include "ntp_fp.h"
8
#include "ntp_stdlib.h"
9
10
char *
11
dolfptoa(
12
  u_int32 fpi,
13
  u_int32 fpv,
14
  char sign,
15
  short ndec,
16
  int msec
17
  )
18
0
{
19
0
  u_char *cp, *cpend, *cpdec;
20
0
  int dec;
21
0
  u_char cbuf[24];
22
0
  char *buf, *bp;
23
24
  /*
25
   * Get a string buffer before starting
26
   */
27
0
  LIB_GETBUF(buf);
28
29
  /*
30
   * Zero the character buffer
31
   */
32
0
  ZERO(cbuf);
33
34
  /*
35
   * Work on the integral part. This should work reasonable on
36
   * all machines with 32 bit arithmetic. Please note that 32 bits
37
   * can *always* be represented with at most 10 decimal digits,
38
   * including a possible rounding from the fractional part.
39
   */
40
0
  cp = cpend = cpdec = &cbuf[10];
41
0
  for (dec = (int)(cp - cbuf); dec > 0 && fpi != 0; dec--) {
42
    /* can add another digit */
43
0
    u_int32 digit;
44
    
45
0
    digit  = fpi;
46
0
    fpi   /= 10U;
47
0
    digit -= (fpi << 3) + (fpi << 1); /* i*10 */
48
0
    *--cp  = (u_char)digit;
49
0
  }
50
51
  /*
52
   * Done that, now deal with the problem of the fraction.  First
53
   * determine the number of decimal places.
54
   */
55
0
  dec = ndec;
56
0
  if (dec < 0)
57
0
    dec = 0;
58
0
  if (msec) {
59
0
    dec   += 3;
60
0
    cpdec += 3;
61
0
  }
62
0
  if ((size_t)dec > sizeof(cbuf) - (cpend - cbuf))
63
0
    dec = (int)(sizeof(cbuf) - (cpend - cbuf));
64
  
65
  /*
66
   * If there's a fraction to deal with, do so.
67
   */
68
0
  for (/*NOP*/;  dec > 0 && fpv != 0;  dec--)  {
69
0
    u_int32 digit, tmph, tmpl;
70
    
71
    /*
72
     * The scheme here is to multiply the fraction
73
     * (0.1234...) by ten.  This moves a junk of BCD into
74
     * the units part.  record that and iterate.
75
     * multiply by shift/add in two dwords.
76
     */
77
0
    digit = 0;
78
0
    M_LSHIFT(digit, fpv);
79
0
    tmph = digit;
80
0
    tmpl = fpv;
81
0
    M_LSHIFT(digit, fpv);
82
0
    M_LSHIFT(digit, fpv);
83
0
    M_ADD(digit, fpv, tmph, tmpl);
84
0
    *cpend++ = (u_char)digit;
85
0
  }
86
87
  /* decide whether to round or simply extend by zeros */
88
0
  if (dec > 0) {
89
    /* only '0' digits left -- just reposition end */
90
0
    cpend += dec; 
91
0
  } else {
92
    /* some bits remain in 'fpv'; do round */
93
0
    u_char *tp    = cpend;
94
0
    int     carry = ((fpv & 0x80000000) != 0);
95
96
0
    for (dec = (int)(tp - cbuf);  carry && dec > 0;  dec--) {
97
0
      *--tp += 1;
98
0
      if (*tp == 10)
99
0
        *tp = 0;
100
0
      else 
101
0
        carry = FALSE;
102
0
    }
103
104
0
    if (tp < cp) /* rounding from 999 to 1000 or similiar? */
105
0
      cp = tp;
106
0
  }
107
108
  /*
109
   * We've now got the fraction in cbuf[], with cp pointing at
110
   * the first character, cpend pointing past the last, and
111
   * cpdec pointing at the first character past the decimal.
112
   * Remove leading zeros, then format the number into the
113
   * buffer.
114
   */
115
0
  while (cp < cpdec && *cp == 0)
116
0
    cp++;
117
0
  if (cp >= cpdec)
118
0
    cp = cpdec - 1;
119
120
0
  bp = buf;
121
0
  if (sign)
122
0
    *bp++ = sign;
123
0
  while (cp < cpend) {
124
0
    if (cp == cpdec)
125
0
      *bp++ = '.';
126
0
    *bp++ = (char)(*cp++) + '0';
127
0
  }
128
0
  *bp = '\0';
129
130
  /*
131
   * Done!
132
   */
133
0
  return buf;
134
0
}
135
136
137
char *
138
mfptoa(
139
  u_int32 fpi,
140
  u_int32 fpf,
141
  short ndec
142
  )
143
0
{
144
0
  int isneg;
145
146
0
  isneg = M_ISNEG(fpi);
147
0
  if (isneg) {
148
0
    M_NEG(fpi, fpf);
149
0
  }
150
151
0
  return dolfptoa(fpi, fpf, (isneg?'-':'+'), ndec, FALSE);
152
0
}
153
154
155
char *
156
mfptoms(
157
  u_int32 fpi,
158
  u_int32 fpf,
159
  short ndec
160
  )
161
0
{
162
0
  int isneg;
163
164
0
  isneg = M_ISNEG(fpi);
165
0
  if (isneg) {
166
0
    M_NEG(fpi, fpf);
167
0
  }
168
169
0
  return dolfptoa(fpi, fpf, (isneg?'-':'+'), ndec, TRUE);
170
0
}
171
172