GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/stdlib/gcvt.c Lines: 0 52 0.0 %
Date: 2017-11-13 Branches: 0 36 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: gcvt.c,v 1.13 2013/11/01 19:05:11 guenther Exp $	*/
2
3
/*
4
 * Copyright (c) 2002, 2003, 2006, 2010
5
 *	Todd C. Miller <Todd.Miller@courtesan.com>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 *
19
 * Sponsored in part by the Defense Advanced Research Projects
20
 * Agency (DARPA) and Air Force Research Laboratory, Air Force
21
 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
22
 */
23
24
#include <locale.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include "gdtoa.h"
29
30
#define DEFPREC	6
31
32
char *
33
gcvt(double value, int ndigit, char *buf)
34
{
35
	char *digits, *dst, *src;
36
	int i, decpt, sign;
37
	struct lconv *lconv;
38
39
	lconv = localeconv();
40
	if (ndigit <= 0) {
41
		/* Match printf(3) behavior. */
42
		ndigit = ndigit ? DEFPREC : 1;
43
	}
44
45
	digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
46
	if (digits == NULL)
47
		return (NULL);
48
	if (decpt == 9999) {
49
		/*
50
		 * Infinity or NaN, convert to inf or nan with sign.
51
		 * We can't infer buffer size based on ndigit.
52
		 * We have to assume it is at least 5 chars.
53
		 */
54
		snprintf(buf, 5, "%s%s", sign ? "-" : "",
55
		    *digits == 'I' ? "inf" : "nan");
56
		__freedtoa(digits);
57
		return (buf);
58
	}
59
60
	dst = buf;
61
	if (sign)
62
		*dst++ = '-';
63
64
	/* Match printf(3) behavior for exponential vs. regular fomatting. */
65
	if (decpt <= -4 || decpt > ndigit) {
66
		/* exponential format (e.g. 1.2345e+13) */
67
		if (--decpt < 0) {
68
			sign = 1;
69
			decpt = -decpt;
70
		} else
71
			sign = 0;
72
		src = digits;
73
		*dst++ = *src++;
74
		if (*src != '\0') {
75
			*dst++ = *lconv->decimal_point;
76
			do {
77
				*dst++ = *src++;
78
			} while (*src != '\0');
79
		}
80
		*dst++ = 'e';
81
		if (sign)
82
			*dst++ = '-';
83
		else
84
			*dst++ = '+';
85
		if (decpt < 10) {
86
			*dst++ = '0';
87
			*dst++ = '0' + decpt;
88
			*dst = '\0';
89
		} else {
90
			/* XXX - optimize */
91
			for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
92
				continue;
93
			dst[i + 1] = '\0';
94
			while (decpt != 0) {
95
				dst[i--] = '0' + decpt % 10;
96
				decpt /= 10;
97
			}
98
		}
99
	} else {
100
		/* standard format */
101
		for (i = 0, src = digits; i < decpt; i++) {
102
			if (*src != '\0')
103
				*dst++ = *src++;
104
			else
105
				*dst++ = '0';
106
		}
107
		if (*src != '\0') {
108
			if (src == digits)
109
				*dst++ = '0';	/* zero before decimal point */
110
			*dst++ = *lconv->decimal_point;
111
			while (decpt < 0) {
112
				*dst++ = '0';
113
				decpt++;
114
			}
115
			for (i = decpt; digits[i] != '\0'; i++) {
116
				*dst++ = digits[i];
117
			}
118
		}
119
		*dst = '\0';
120
	}
121
	__freedtoa(digits);
122
	return (buf);
123
}