Skip to content

Improve detection of errors from math functions #238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
94 changes: 94 additions & 0 deletions math.c
Original file line number Diff line number Diff line change
@@ -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 <errno.h>
#include <fenv.h>
#include <math.h>
#include <stdio.h>

#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");
}
6 changes: 5 additions & 1 deletion proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
22 changes: 7 additions & 15 deletions run.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ THIS SOFTWARE.
#define DEBUG
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <wctype.h>
#include <fcntl.h>
#include <setjmp.h>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down