gcc/libgm2/libm2pim/dtoa.cc
Rainer Orth 0437cbdccb libgm2: Define missing configure macros [PR113888]
As detailed in PR modula2/113888, the 32-bit libm2pim/target.c doesn't
assemble in a Linux/sparc64 multilib build.  However, the root cause is
that the HAVE_EXP10* macros are never defined.  While I was at it, I
checked for other cases where the code uses HAVE_* macros that are
missing from config.h.in.

This patch adds the missing checks, changes the configure checks where
the names don't match what's used in the code, or corrects the code to
use the right names.

So far tested on sparc64-unknown-linux-gnu by building libgm2 (32 and
64-bit) and running the gm2 tests.

2024-02-12  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	libgm2:
	PR modula2/113888
	* configure.ac (GM2_CHECK_LIB): Rename gettimeofday guard to
	HAVE_GETTIMEOFDAY.
	(GM_CHECK_LIB): Check for settimeofday.
	(GM2_CHECK_LIB): Check for exp10, exp10f, exp10l in libm.
	(AC_CHECK_DECLS): Check for getenv.
	* configure, config.h.in: Regenerate.
	* libm2pim/dtoa.cc: Rename <strings.h>, <string.h> guards to
	HAVE_STRINGS_H, HAVE_STRING_H.
	* libm2pim/ldtoa.cc: Likewise.
2024-02-12 14:01:41 +01:00

262 lines
5.5 KiB
C++

/* dtoa.cc convert double to ascii and visa versa.
Copyright (C) 2009-2022 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
This file is part of GNU Modula-2.
GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#define GM2
#include <config.h>
#include <m2rts.h>
#define EXPORT(FUNC) m2pim ## _dtoa_ ## FUNC
#define M2EXPORT(FUNC) m2pim ## _M2_dtoa_ ## FUNC
#define M2LIBNAME "m2pim"
#if defined(HAVE_STRINGS_H)
#include <strings.h>
#endif
#if defined(HAVE_STRING_H)
#include <string.h>
#endif
#if defined(HAVE_STDDEF_H)
/* Obtain a definition for NULL. */
#include <stddef.h>
#endif
#if defined(HAVE_STDIO_H)
/* Obtain a definition for NULL. */
#include <stdio.h>
#endif
#if defined(HAVE_TIME_H)
/* Obtain a definition for NULL. */
#include <time.h>
#endif
#if defined(HAVE_STRING_H)
/* Obtain a definition for NULL. */
#include <string.h>
#endif
#if defined(HAVE_WCHAR_H)
/* Obtain a definition for NULL. */
#include <wchar.h>
#endif
#if defined(HAVE_STDLIB_H)
/* Obtain a prototype for free and malloc. */
#include <stdlib.h>
#endif
#if !defined(NULL)
#define NULL (void *)0
#endif
#if defined(HAVE_STDLIB_H)
#if !defined(_ISOC99_SOURCE)
#define _ISOC99_SOURCE
#endif
#include <stdlib.h>
#endif
#if defined(HAVE_ERRNO_H)
#include <errno.h>
#endif
#if defined(HAVE_SYS_ERRNO_H)
#include <sys/errno.h>
#endif
#if defined(HAVE_STRING_H)
#define MAX_FP_DIGITS 500
typedef enum Mode { maxsignicant, decimaldigits } Mode;
/* maxsignicant: return a string containing max(1,ndigits) significant
digits. The return string contains the string produced by ecvt.
decimaldigits: return a string produced by fcvt. The string will
contain ndigits past the decimal point (ndigits may be negative). */
extern "C" double
EXPORT(strtod) (const char *s, bool *error)
{
char *endp;
double d;
#if defined(HAVE_ERRNO_H)
errno = 0;
#endif
d = strtod (s, &endp);
if (endp != NULL && (*endp == '\0'))
#if defined(HAVE_ERRNO_H)
*error = (errno != 0);
#else
*error = false;
#endif
else
*error = true;
return d;
}
/* dtoa_calcmaxsig calculates the position of the decimal point
it also removes the decimal point and exponent from string, p. */
extern "C" int
EXPORT(calcmaxsig) (char *p, int ndigits)
{
char *e;
char *o;
int x;
e = strchr (p, 'E');
if (e == NULL)
x = 0;
else
{
*e = (char)0;
x = atoi (e + 1);
}
o = strchr (p, '.');
if (o == NULL)
return strlen (p) + x;
else
{
memmove (o, o + 1, ndigits - (o - p));
return o - p + x;
}
}
/* dtoa_calcdecimal calculates the position of the decimal point
it also removes the decimal point and exponent from string, p.
It truncates the digits in p accordingly to ndigits.
Ie ndigits is the number of digits after the '.'. */
extern "C" int
EXPORT(calcdecimal) (char *p, int str_size, int ndigits)
{
char *e;
char *o;
int x;
int l;
e = strchr (p, 'E');
if (e == NULL)
x = 0;
else
{
*e = (char)0;
x = atoi (e + 1);
}
l = strlen (p);
o = strchr (p, '.');
if (o == NULL)
x += strlen (p);
else
{
int m = strlen (o);
memmove (o, o + 1, l - (o - p));
if (m > 0)
o[m - 1] = '0';
x += o - p;
}
if ((x + ndigits >= 0) && (x + ndigits < str_size))
p[x + ndigits] = (char)0;
return x;
}
extern "C" bool
EXPORT(calcsign) (char *p, int str_size)
{
if (p[0] == '-')
{
memmove (p, p + 1, str_size - 1);
return true;
}
else
return false;
}
extern "C" char *
EXPORT(dtoa) (double d, int mode, int ndigits, int *decpt, bool *sign)
{
char format[50];
char *p;
int r;
switch (mode)
{
case maxsignicant:
ndigits += 20; /* Enough for exponent. */
p = (char *) malloc (ndigits);
snprintf (format, 50, "%s%d%s", "%.", ndigits - 20, "E");
snprintf (p, ndigits, format, d);
*sign = EXPORT(calcsign) (p, ndigits);
*decpt = EXPORT(calcmaxsig) (p, ndigits);
return p;
case decimaldigits:
p = (char *) malloc (MAX_FP_DIGITS + 20);
snprintf (format, 50, "%s%d%s", "%.", MAX_FP_DIGITS, "E");
snprintf (p, MAX_FP_DIGITS + 20, format, d);
*sign = EXPORT(calcsign) (p, MAX_FP_DIGITS + 20);
*decpt = EXPORT(calcdecimal) (p, MAX_FP_DIGITS + 20, ndigits);
return p;
default:
abort ();
}
}
#endif
#if defined(GM2)
/* GNU Modula-2 linking hooks. */
extern "C" void
M2EXPORT(init) (int, char **, char **)
{
}
extern "C" void
M2EXPORT(fini) (int, char **, char **)
{
}
extern "C" void
M2EXPORT(dep) (void)
{
}
extern "C" void __attribute__((__constructor__))
M2EXPORT(ctor) (void)
{
m2pim_M2RTS_RegisterModule ("dtoa", M2LIBNAME,
M2EXPORT(init), M2EXPORT(fini),
M2EXPORT(dep));
}
#endif