diff --git a/lib.c b/lib.c index 81582d3..92747ee 100644 --- a/lib.c +++ b/lib.c @@ -828,21 +828,6 @@ void bclass(int c) } } -double errcheck(double x, const char *s) -{ - - if (errno == EDOM) { - errno = 0; - WARNING("%s argument out of domain", s); - x = 1; - } else if (errno == ERANGE) { - errno = 0; - WARNING("%s result out of range", s); - x = 1; - } - return x; -} - int isclvar(const char *s) /* is s of form var=something ? */ { const char *os = s; diff --git a/makefile b/makefile index 0240e5e..b7288e2 100644 --- a/makefile +++ b/makefile @@ -40,13 +40,13 @@ CC = $(HOSTCC) # change this is cross-compiling. # YACC = yacc -d -b awkgram YACC = bison -d -OFILES = b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o +OFILES = b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o math.o SOURCE = awk.h awkgram.tab.c awkgram.tab.h proto.h awkgram.y lex.c b.c main.c \ - maketab.c parse.c lib.c run.c tran.c proctab.c + maketab.c parse.c lib.c run.c tran.c proctab.c math.c LISTING = awk.h proto.h awkgram.y lex.c b.c main.c maketab.c parse.c \ - lib.c run.c tran.c + lib.c run.c tran.c math.c SHIP = README LICENSE FIXES $(SOURCE) awkgram.tab.[ch].bak makefile \ awk.1 @@ -83,7 +83,7 @@ tar: gitadd: git add README LICENSE FIXES \ awk.h proto.h awkgram.y lex.c b.c main.c maketab.c parse.c \ - lib.c run.c tran.c \ + lib.c run.c tran.c math.c \ makefile awk.1 testdir gitpush: diff --git a/math.c b/math.c new file mode 100644 index 0000000..f3d4885 --- /dev/null +++ b/math.c @@ -0,0 +1,94 @@ +/**************************************************************** +Copyright (C) Lucent Technologies 1997 +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name Lucent Technologies or any of +its entities not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +****************************************************************/ + +#pragma STDC FENV_ACCESS ON + +#include +#include +#include +#include + +#include "awk.h" + +#ifndef FE_DIVBYZERO +#define FE_DIVBYZERO 0 +#endif + +#ifndef FE_INVALID +#define FE_INVALID 0 +#endif + +#ifndef FE_OVERFLOW +#define FE_OVERFLOW 0 +#endif + +#ifndef FE_UNDERFLOW +#define FE_UNDERFLOW 0 +#endif + +#define errclear() \ + do { \ + errno = 0; \ + feclearexcept(FE_ALL_EXCEPT); \ + } while (0) + +static double errcheck(double x, const char *s) +{ + if (errno == EDOM || fetestexcept(FE_INVALID)) { + errno = 0; + WARNING("%s argument out of domain", s); + x = 1; + } else if (errno == ERANGE || fetestexcept(FE_DIVBYZERO | FE_OVERFLOW | + FE_UNDERFLOW)) { + errno = 0; + WARNING("%s result out of range", s); + x = 1; + } + + return x; +} + +double exp_errcheck(double x) +{ + errclear(); + return errcheck(exp(x), "exp"); +} + +double log_errcheck(double x) +{ + errclear(); + return errcheck(log(x), "log"); +} + +double pow_errcheck(double x, double y) +{ + errclear(); + return errcheck(pow(x, y), "pow"); +} + +double sqrt_errcheck(double x) +{ + errclear(); + return errcheck(sqrt(x), "sqrt"); +} diff --git a/proto.h b/proto.h index cfd4b7c..4cbb0e4 100644 --- a/proto.h +++ b/proto.h @@ -140,7 +140,6 @@ extern void WARNING(const char *, ...) extern void error(void); extern void eprint(void); extern void bclass(int); -extern double errcheck(double, const char *); extern int isclvar(const char *); extern bool is_valid_number(const char *s, bool trailing_stuff_ok, bool *no_trailing, double *result); @@ -198,3 +197,8 @@ extern FILE *popen(const char *, const char *); extern int pclose(FILE *); extern const char *flags2str(int flags); + +extern double exp_errcheck(double); +extern double log_errcheck(double); +extern double pow_errcheck(double, double); +extern double sqrt_errcheck(double); diff --git a/run.c b/run.c index 44c0f41..a3820cb 100644 --- a/run.c +++ b/run.c @@ -25,7 +25,6 @@ THIS SOFTWARE. #define DEBUG #include #include -#include #include #include #include @@ -1486,10 +1485,8 @@ Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ case POWER: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ i = ipow(i, (int) j); - else { - errno = 0; - i = errcheck(pow(i, j), "pow"); - } + else + i = pow_errcheck(i, j); break; default: /* can't happen */ FATAL("illegal arithmetic operator %d", n); @@ -1583,10 +1580,8 @@ Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */ case POWEQ: if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ xf = ipow(xf, (int) yf); - else { - errno = 0; - xf = errcheck(pow(xf, yf), "pow"); - } + else + xf = pow_errcheck(xf, yf); break; default: FATAL("illegal assignment operator %d", n); @@ -2081,18 +2076,15 @@ Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg lis u = u8_strlen(getsval(x)); break; case FLOG: - errno = 0; - u = errcheck(log(getfval(x)), "log"); + u = log_errcheck(getfval(x)); break; case FINT: modf(getfval(x), &u); break; case FEXP: - errno = 0; - u = errcheck(exp(getfval(x)), "exp"); + u = exp_errcheck(getfval(x)); break; case FSQRT: - errno = 0; - u = errcheck(sqrt(getfval(x)), "sqrt"); + u = sqrt_errcheck(getfval(x)); break; case FSIN: u = sin(getfval(x)); break;