OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib-1.10.0/] [newlib/] [libc/] [stdlib/] [ecvtbuf.c] - Blame information for rev 1773

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1010 ivang
/*
2
FUNCTION
3
<<ecvtbuf>>, <<fcvtbuf>>---double or float to string
4
 
5
INDEX
6
        ecvtbuf
7
INDEX
8
        fcvtbuf
9
 
10
ANSI_SYNOPSIS
11
        #include <stdio.h>
12
 
13
        char *ecvtbuf(double <[val]>, int <[chars]>, int *<[decpt]>,
14
                       int *<[sgn]>, char *<[buf]>);
15
 
16
        char *fcvtbuf(double <[val]>, int <[decimals]>, int *<[decpt]>,
17
                       int *<[sgn]>, char *<[buf]>);
18
 
19
TRAD_SYNOPSIS
20
        #include <stdio.h>
21
 
22
        char *ecvtbuf(<[val]>, <[chars]>, <[decpt]>, <[sgn]>, <[buf]>);
23
        double <[val]>;
24
        int <[chars]>;
25
        int *<[decpt]>;
26
        int *<[sgn]>;
27
        char *<[buf]>;
28
 
29
        char *fcvtbuf(<[val]>, <[decimals]>, <[decpt]>, <[sgn]>, <[buf]>);
30
        double <[val]>;
31
        int <[decimals]>;
32
        int *<[decpt]>;
33
        int *<[sgn]>;
34
        char *<[buf]>;
35
 
36
DESCRIPTION
37
        <<ecvtbuf>> and <<fcvtbuf>> produce (null-terminated) strings
38
        of digits representating the <<double>> number <[val]>.
39
 
40
        The only difference between <<ecvtbuf>> and <<fcvtbuf>> is the
41
        interpretation of the second argument (<[chars]> or
42
        <[decimals]>). For <<ecvtbuf>>, the second argument <[chars]>
43
        specifies the total number of characters to write (which is
44
        also the number of significant digits in the formatted string,
45
        since these two functions write only digits). For <<fcvtbuf>>,
46
        the second argument <[decimals]> specifies the number of
47
        characters to write after the decimal point; all digits for
48
        the integer part of <[val]> are always included.
49
 
50
        Since <<ecvtbuf>> and <<fcvtbuf>> write only digits in the
51
        output string, they record the location of the decimal point
52
        in <<*<[decpt]>>>, and the sign of the number in <<*<[sgn]>>>.
53
        After formatting a number, <<*<[decpt]>>> contains the number
54
        of digits to the left of the decimal point.  <<*<[sgn]>>>
55
        contains <<0>> if the number is positive, and <<1>> if it is
56
        negative.  For both functions, you supply a pointer <[buf]> to
57
        an area of memory to hold the converted string.
58
 
59
RETURNS
60
        Both functions return a pointer to <[buf]>, the string
61
        containing a character representation of <[val]>.
62
 
63
PORTABILITY
64
        Neither function is ANSI C.
65
 
66
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
67
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
68
*/
69
 
70
#include <_ansi.h>
71
#include <stdlib.h>
72
#include <string.h>
73
#include <reent.h>
74
#include "mprec.h"
75
#include "local.h"
76
 
77
static void
78
_DEFUN (print_f, (ptr, buf, invalue, ndigit, type, dot, mode),
79
        struct _reent *ptr _AND
80
        char *buf _AND
81
        double invalue _AND
82
        int ndigit _AND
83
        char type _AND
84
        int dot _AND
85
        int mode)
86
{
87
  int decpt;
88
  int sign;
89
  char *p, *start, *end;
90
 
91
  start = p = _dtoa_r (ptr, invalue, mode, ndigit, &decpt, &sign, &end);
92
 
93
  if (decpt == 9999)
94
    {
95
      strcpy (buf, p);
96
      return;
97
    }
98
  while (*p && decpt > 0)
99
    {
100
      *buf++ = *p++;
101
      decpt--;
102
    }
103
  /* Even if not in buffer */
104
  while (decpt > 0)
105
    {
106
      *buf++ = '0';
107
      decpt--;
108
    }
109
 
110
  if (dot || *p)
111
    {
112
      if (p == start)
113
        *buf++ = '0';
114
      *buf++ = '.';
115
      while (decpt < 0 && ndigit > 0)
116
        {
117
          *buf++ = '0';
118
          decpt++;
119
          ndigit--;
120
        }
121
 
122
      /* Print rest of stuff */
123
      while (*p && ndigit > 0)
124
        {
125
          *buf++ = *p++;
126
          ndigit--;
127
        }
128
      /* And trailing zeros */
129
      while (ndigit > 0)
130
        {
131
          *buf++ = '0';
132
          ndigit--;
133
        }
134
    }
135
  *buf++ = 0;
136
}
137
 
138
/* Print number in e format with width chars after.
139
 
140
   TYPE is one of 'e' or 'E'.  It may also be one of 'g' or 'G' indicating
141
   that _gcvt is calling us and we should remove trailing zeroes.
142
 
143
   WIDTH is the number of digits of precision after the decimal point.  */
144
 
145
static void
146
_DEFUN (print_e, (ptr, buf, invalue, width, type, dot),
147
        struct _reent *ptr _AND
148
        char *buf _AND
149
        double invalue _AND
150
        int width _AND
151
        char type _AND
152
        int dot)
153
{
154
  int sign;
155
  char *end;
156
  char *p;
157
  int decpt;
158
  int top;
159
  int ndigit = width;
160
 
161
  p = _dtoa_r (ptr, invalue, 2, width + 1, &decpt, &sign, &end);
162
 
163
  if (decpt == 9999)
164
    {
165
      strcpy (buf, p);
166
      return;
167
    }
168
 
169
  *buf++ = *p++;
170
  if (dot || ndigit != 0)
171
    *buf++ = '.';
172
 
173
  while (*p && ndigit > 0)
174
    {
175
      *buf++ = *p++;
176
      ndigit--;
177
    }
178
 
179
  /* Add trailing zeroes to fill out to ndigits unless this is 'g' format.
180
     Also, convert g/G to e/E.  */
181
 
182
  if (type == 'g')
183
    type = 'e';
184
  else if (type == 'G')
185
    type = 'E';
186
  else
187
    {
188
      while (ndigit > 0)
189
        {
190
          *buf++ = '0';
191
          ndigit--;
192
        }
193
    }
194
 
195
  /* Add the exponent.  */
196
 
197
  *buf++ = type;
198
  decpt--;
199
  if (decpt < 0)
200
    {
201
      *buf++ = '-';
202
      decpt = -decpt;
203
    }
204
  else
205
    {
206
      *buf++ = '+';
207
    }
208
  if (decpt > 99)
209
    {
210
      int top = decpt / 100;
211
      *buf++ = top + '0';
212
      decpt -= top * 100;
213
    }
214
  top = decpt / 10;
215
  *buf++ = top + '0';
216
  decpt -= top * 10;
217
  *buf++ = decpt + '0';
218
 
219
  *buf++ = 0;
220
}
221
 
222
#ifndef _REENT_ONLY
223
 
224
/* Undocumented behaviour: when given NULL as a buffer, return a
225
   pointer to static space in the rent structure.  This is only to
226
   support ecvt and fcvt, which aren't ANSI anyway.  */
227
 
228
char *
229
_DEFUN (fcvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
230
        double invalue _AND
231
        int ndigit _AND
232
        int *decpt _AND
233
        int *sign _AND
234
        char *fcvt_buf)
235
{
236
  char *save;
237
  char *p;
238
  char *end;
239
  int done = 0;
240
 
241
  if (fcvt_buf == NULL)
242
    {
243
      if (_REENT->_cvtlen <= ndigit + 35)
244
        {
245
          if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
246
                                               ndigit + 36)) == NULL)
247
            return NULL;
248
          _REENT->_cvtlen = ndigit + 36;
249
          _REENT->_cvtbuf = fcvt_buf;
250
        }
251
 
252
      fcvt_buf = _REENT->_cvtbuf ;
253
    }
254
 
255
  save = fcvt_buf;
256
 
257
  if (invalue < 1.0 && invalue > -1.0)
258
    {
259
      p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
260
    }
261
  else
262
    {
263
      p = _dtoa_r (_REENT, invalue, 3, ndigit, decpt, sign, &end);
264
    }
265
 
266
  /* Now copy */
267
 
268
  done = -*decpt;
269
  while (p < end)
270
    {
271
      *fcvt_buf++ = *p++;
272
      done++;
273
    }
274
  /* And unsuppress the trailing zeroes */
275
  while (done < ndigit)
276
    {
277
      *fcvt_buf++ = '0';
278
      done++;
279
    }
280
  *fcvt_buf++ = 0;
281
  return save;
282
}
283
 
284
char *
285
_DEFUN (ecvtbuf, (invalue, ndigit, decpt, sign, fcvt_buf),
286
        double invalue _AND
287
        int ndigit _AND
288
        int *decpt _AND
289
        int *sign _AND
290
        char *fcvt_buf)
291
{
292
  char *save;
293
  char *p;
294
  char *end;
295
  int done = 0;
296
 
297
  if (fcvt_buf == NULL)
298
    {
299
      if (_REENT->_cvtlen <= ndigit)
300
        {
301
          if ((fcvt_buf = (char *) _realloc_r (_REENT, _REENT->_cvtbuf,
302
                                               ndigit + 1)) == NULL)
303
            return NULL;
304
          _REENT->_cvtlen = ndigit + 1;
305
          _REENT->_cvtbuf = fcvt_buf;
306
        }
307
 
308
      fcvt_buf = _REENT->_cvtbuf ;
309
    }
310
 
311
  save = fcvt_buf;
312
 
313
  p = _dtoa_r (_REENT, invalue, 2, ndigit, decpt, sign, &end);
314
 
315
  /* Now copy */
316
 
317
  while (p < end)
318
    {
319
      *fcvt_buf++ = *p++;
320
      done++;
321
    }
322
  /* And unsuppress the trailing zeroes */
323
  while (done < ndigit)
324
    {
325
      *fcvt_buf++ = '0';
326
      done++;
327
    }
328
  *fcvt_buf++ = 0;
329
  return save;
330
}
331
 
332
#endif
333
 
334
char *
335
_DEFUN (_gcvt, (ptr, invalue, ndigit, buf, type, dot),
336
        struct _reent *ptr _AND
337
        double invalue _AND
338
        int ndigit _AND
339
        char *buf _AND
340
        char type _AND
341
        int dot)
342
{
343
  char *save = buf;
344
 
345
  if (invalue < 0)
346
    {
347
      invalue = -invalue;
348
    }
349
 
350
  if (invalue == 0)
351
    {
352
      *buf++ = '0';
353
      *buf = '\0';
354
    }
355
  else
356
    /* Which one to print ?
357
       ANSI says that anything with more that 4 zeros after the . or more
358
       than precision digits before is printed in e with the qualification
359
       that trailing zeroes are removed from the fraction portion.  */
360
 
361
  if (0.0001 >= invalue || invalue >= _mprec_log10 (ndigit))
362
    {
363
      /* We subtract 1 from ndigit because in the 'e' format the precision is
364
         the number of digits after the . but in 'g' format it is the number
365
         of significant digits.
366
 
367
         We defer changing type to e/E so that print_e() can know it's us
368
         calling and thus should remove trailing zeroes.  */
369
 
370
      print_e (ptr, buf, invalue, ndigit - 1, type, dot);
371
    }
372
  else
373
    {
374
      int decpt;
375
      int sign;
376
      char *end;
377
      char *p;
378
 
379
      if (invalue < 1.0)
380
        {
381
          /* what we want is ndigits after the point */
382
          p = _dtoa_r (ptr, invalue, 3, ndigit, &decpt, &sign, &end);
383
        }
384
      else
385
        {
386
          p = _dtoa_r (ptr, invalue, 2, ndigit, &decpt, &sign, &end);
387
        }
388
 
389
      if (decpt == 9999)
390
        {
391
          strcpy (buf, p);
392
          return save;
393
        }
394
      while (*p && decpt > 0)
395
        {
396
          *buf++ = *p++;
397
          decpt--;
398
          ndigit--;
399
        }
400
      /* Even if not in buffer */
401
      while (decpt > 0 && ndigit > 0)
402
        {
403
          *buf++ = '0';
404
          decpt--;
405
          ndigit--;
406
        }
407
 
408
      if (dot || *p)
409
        {
410
          if (buf == save)
411
            *buf++ = '0';
412
          *buf++ = '.';
413
          while (decpt < 0 && ndigit > 0)
414
            {
415
              *buf++ = '0';
416
              decpt++;
417
              ndigit--;
418
            }
419
 
420
          /* Print rest of stuff */
421
          while (*p && ndigit > 0)
422
            {
423
              *buf++ = *p++;
424
              ndigit--;
425
            }
426
          /* And trailing zeros */
427
          if (dot)
428
            {
429
              while (ndigit > 0)
430
                {
431
                  *buf++ = '0';
432
                  ndigit--;
433
                }
434
            }
435
        }
436
      *buf++ = 0;
437
    }
438
 
439
  return save;
440
}
441
 
442
char *
443
_DEFUN (_dcvt, (ptr, buffer, invalue, precision, width, type, dot),
444
        struct _reent *ptr _AND
445
        char *buffer _AND
446
        double invalue _AND
447
        int precision _AND
448
        int width _AND
449
        char type _AND
450
        int dot)
451
{
452
  switch (type)
453
    {
454
    case 'f':
455
    case 'F':
456
      print_f (ptr, buffer, invalue, precision, type, precision == 0 ? dot : 1, 3);
457
      break;
458
    case 'g':
459
    case 'G':
460
      if (precision == 0)
461
        precision = 1;
462
      _gcvt (ptr, invalue, precision, buffer, type, dot);
463
      break;
464
    case 'e':
465
    case 'E':
466
      print_e (ptr, buffer, invalue, precision, type, dot);
467
    }
468
  return buffer;
469
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.