@c ---------------------------------------------------------------------- @node matherr, math @subheading Syntax @example #include enum fdversion _fdlib_version = _SVID_; int matherr(struct exception *exc); @end example @subheading Description @code{matherr} is a user-definable handler for errors in math library functions. It is only supported in the alternate math library (link with @samp{-lm}), and will only be called if the global variable @code{_fdlib_version} is set to either @code{_SVID_} or @code{_XOPEN_} (@pxref{libm}). You also need to mask the Invalid Operation exception in the x87 control word (@pxref{_control87}) or install a handler for signal @code{SIGFPE} (@pxref{signal}), or else some exceptions will generate @code{SIGFPE} and your program will be terminated before it gets a chance to call @code{matherr}. DJGPP versions 2.02 and later mask all FP exceptions at startup, so this consideration applies only to programs that unmask FP exceptions at run time. If the above conditions are met, every math function will call @code{matherr} when a numerical exception is detected. The default version of @code{matherr}, supplied with @file{libm.a}, does nothing and returns zero (the @code{_SVID_} version will then print an error message to the standard error stream and set @code{errno}). This default behavior is inappropriate in some cases. For example, an interactive program which runs in a windowed environment might want the error message to go to a particular window, or pop up a dialog box; a fault-tolerant program might want to fall back to backup procedures so that meaningful results are returned to the application code, etc. In such cases, you should include your own version of @code{matherr} in your program. @code{matherr} is called with a single argument @var{exc} which is a pointer to a structure defined on @code{} like this: @example struct exception @{ int type; char *name; double arg1, arg2, retval; @}; @end example The member @code{type} is an integer code describing the type of exception that has occured. It can be one of the following: @table @code @item DOMAIN Argument(s) are outside the valid function domain (e.g., @code{log(-1)}). @item SING Argument(s) would result in a singularity (e.g., @code{log(0)}). @item OVERFLOW The result causes overflow, like in @code{exp(10000)}. @item UNDERFLOW The result causes underflow, like in @code{exp(-10000)}. @item TLOSS The result loses all significant digits, like in @code{sin(10e100)}. @end table These codes are defined on @code{}. The member @code{name} points to the string that is the name of the function which generated the exception. The members @code{arg1} and @code{arg2} are the values of the arguments with which the function was called (@code{arg2} is undefined if the function only accepts a single argument). The member @code{retval} is set to the default value that will be returned by the math library function; @code{matherr} can change it to return a different value. @subheading Return Value @code{matherr} should return zero if it couldn't handle the exception, or non-zero if the exception was handled. If @code{matherr} returns zero, under @code{_SVID_} version an error message is printed which includes the name of the function and the exception type, and under @code{_SVID_} and @code{_XOPEN_} @code{errno} is set to an appropriate value. If @code{matherr} returns non-zero, no error message is printed and @code{errno} is left unchanged. @subheading Portability @portability !ansi, !posix @subheading Example @example #include int matherr(register struct exception *x) @{ switch (x->type) @{ case DOMAIN: /* change sqrt to return sqrt(-arg1), not NaN */ if (!strcmp(x->name, "sqrt")) @{ x->retval = sqrt(-x->arg1); return 1; /* be silent: no message, don't set errno */ @} /* FALL THROUGH */ case SING: /* all other domain or sing exceptions, print message and abort */ fprintf(stderr, "domain exception in %s\n", x->name); abort(); break; @} return 0; /* all other exceptions, execute default procedure */ @} @end example