Coverage Report

Created: 2023-05-19 06:16

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