/[ascend]/branches/relerrorlist/ascend/utilities/ascSignal.c
ViewVC logotype

Contents of /branches/relerrorlist/ascend/utilities/ascSignal.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3217 - (show annotations) (download) (as text)
Sat Oct 28 07:01:00 2017 UTC (12 months, 3 weeks ago) by jpye
File MIME type: text/x-csrc
File size: 18756 byte(s)
fixing va_copy errors and snprintf warnings from gcc 7.2.0

1 /* ASCEND modelling environment
2 Copyright (C) 1997 Benjamin Andrew Allan
3 Copyright (C) 2006 Carnegie Mellon University
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *//** @file
18 Signal handling protocol definitions for ASCEND
19
20 Start of making signal handling in ASCEND
21 code somewhat sane. Still needs to somehow
22 support the management of jmp_buf's so that
23 handlers will longjmp to the right place.
24
25 A better alternative is to make all our code check/return
26 status flags based on a variable set by the trap
27 and cleared by recipient.
28 *//*
29 by Benjamin Andrew Allan, May 27, 1997
30 Last in CVS $Revision: 1.9 $ $Date: 1999/01/19 12:23:20 $ $Author: mthomas $
31
32 10/15/2005 - Changed ascresetneeded() so that any previously
33 registered handlers are reset before return.
34 - Added Asc_SignalRecover() to standard handler
35 Asc_SignalTrap() so handlers are reset if necessary. (JDS)
36 12/10/2005 - Changed storage of signal handlers from gl_list's
37 to local arrays. gl_list's can't legally hold
38 function pointers. (JDS)
39 18 Dec 06 - Removed ascresetneeded (moved to SConstruct)
40 25 Jan 12 - Add debug capability for contents of stacks (JDP)
41 */
42
43 #include "ascSignal.h"
44 #ifdef ASC_SIGNAL_TRAPS
45
46 /*-------- this file will do nothing unless ASC_SIGNAL_TRAPS is turned on -----*/
47
48 #include <stdio.h>
49
50
51 #include <signal.h>
52
53 #ifdef HAVE_C99FPE
54 # include <fenv.h>
55 #endif
56
57
58 #ifdef __WIN32__
59 # include <process.h>
60 #else
61 # include <unistd.h>
62 #endif
63
64 #include <ascend/general/ascMalloc.h>
65 #include "ascSignal.h"
66 #include <ascend/general/panic.h>
67
68 //#define SIGNAL_DEBUG
69 #ifdef SIGNAL_DEBUG
70 # define MSG CONSOLE_DEBUG
71 #else
72 # define MSG(ARGS...) ((void)0)
73 #endif
74 /*------------------------------------------------------------------------------
75 GLOBALS AND FOWARD DECS
76 */
77
78 /* test buf for initialization */
79 JMP_BUF g_fpe_env;
80 JMP_BUF g_seg_env;
81 JMP_BUF g_int_env;
82
83 #ifdef HAVE_C99FPE
84 fexcept_t g_fenv;
85 #endif
86
87 /* for future use */
88 jmp_buf g_foreign_code_call_env;
89
90 /**
91 Struct to store signal stacks, with support for debugging names and
92 location where handlers were pushed.
93 */
94 typedef struct{
95 SigHandlerFn *handler;
96 #ifdef SIGNAL_DEBUG
97 char *name;
98 char *file;
99 int line;
100 #endif
101 } SignalStackItem;
102
103 typedef struct{
104 SignalStackItem fpe_traps[MAX_TRAP_DEPTH];
105 int fpe_top;
106 SignalStackItem int_traps[MAX_TRAP_DEPTH];
107 int int_top;
108 SignalStackItem seg_traps[MAX_TRAP_DEPTH];
109 int seg_top;
110 } SignalStacks;
111
112 static SignalStacks *f_traps = NULL;
113
114 #if 0
115 static SigHandlerFn **f_fpe_traps = NULL; /**< array for pushed SIGFPE handlers */
116 static int f_fpe_top_of_stack = -1; /**< top of SIGFPE stack, -1 for empty */
117
118 static SigHandlerFn **f_int_traps = NULL; /**< array for pushed SIGINT handlers */
119 static int f_int_top_of_stack = -1; /**< top of SIGFPE stack, -1 for empty */
120
121 static SigHandlerFn **f_seg_traps = NULL; /**< array for pushed SIGSEGV handlers */
122 static int f_seg_top_of_stack = -1; /**< top of SIGFPE stack, -1 for empty */
123 #endif
124
125 #ifdef HAVE_C99FPE
126 static fenv_t *f_fenv_stack = NULL;
127 static int f_fenv_stack_top = -1;
128 #endif
129
130 static void initstack(int sig);
131 static int pop_trap(int signum, SigHandlerFn *tp, char *name, char *file, int line);
132 static int push_trap(int signum, SigHandlerFn *func, char *name, char *file, int line);
133 static void reset_trap(int signum);
134
135 #ifdef HAVE_C99FPE
136 static int fenv_pop(fenv_t *stack, int *top);
137 static int fenv_push(fenv_t *stack,int *top, int excepts);
138 #endif
139
140 #define SIGNAME(SIGNUM) (SIGNUM==SIGFPE?"SIGFPE":(SIGNUM==SIGINT?"SIGINT":(SIGNUM==SIGSEGV?"SIGSEGV":"unknown")))
141 /*------------------------------------------------------------------------------
142 API FUNCTIONS
143 */
144
145 /**
146 Initialise ASCEND signal handling
147
148 Does not establish any traps, just the structures for maintaining them.
149 Pushes the existing traps, if any, on the bottom of the created stacks.
150
151 @NOTE Cannot be called twice successfully.
152
153 @return 0 if successful, 1 if out of memory, 2 otherwise.
154 */
155 int Asc_SignalInit(void){
156 /* initialize SIGFPE stack */
157
158 # ifdef ASC_RESETNEEDED
159 MSG("Initialising signal stack (with resets needed)");
160 # else
161 MSG("Initialising signal stack (with resets not required)");
162 # endif
163
164 if(f_traps == NULL){
165 f_traps = ASC_NEW(SignalStacks);
166 if(!f_traps){
167 return 1;
168 }
169 f_traps->fpe_top = -1;
170 f_traps->int_top = -1;
171 f_traps->seg_top = -1;
172 }
173
174 #ifdef HAVE_C99FPE
175 if(f_fenv_stack==NULL){ /* if we haven't already initialised this... */
176 f_fenv_stack = ASC_NEW_ARRAY_CLEAR(fenv_t,MAX_TRAP_DEPTH);
177 if(f_fenv_stack == NULL){
178 return 1; /* failed to allocate */
179 }
180 }
181 f_fenv_stack_top = -1;
182 #endif
183
184 /* old signals are *not* stored */
185 initstack(SIGFPE);
186 initstack(SIGINT);
187 initstack(SIGSEGV);
188
189 #ifdef HAVE_C99FPE
190 MSG("Initialise FPE state to stack (%d)",f_fenv_stack_top);
191 fenv_push(f_fenv_stack,&f_fenv_stack_top,0);
192 #endif
193
194 return 0;
195 }
196
197 /**
198 Clears and destroys the stacks of signal handlers.
199 */
200 void Asc_SignalDestroy(void){
201 #ifdef HAVE_C99FPE
202 MSG("Restoring FPE state from stack (%d)",f_fenv_stack_top);
203 fenv_pop(f_fenv_stack,&f_fenv_stack_top);
204 #endif
205
206 ascfree(f_traps);
207 #ifdef HAVE_C99FPE
208 if(f_fenv_stack){
209 ASC_FREE(f_fenv_stack);
210 f_fenv_stack = NULL;
211 }
212 #endif
213 f_traps = NULL;
214 MSG("Destroyed signal stack");
215 }
216
217 /**
218 This function reinstalls all the signal handlers this module
219 has been informed of. This should be called after every
220 trapped exception and at any other time when the status of
221 exception handlers may have become not well defined.
222 The most recently pushed handler is installed for each supported
223 signal. If nothing on stack, SIG_DFL gets installed.
224
225 @NOTE that if somebody installs a handler without going through
226 our push/pop, theirs is liable to be forgotten.
227 */
228 void Asc_SignalRecover(int force){
229 #ifndef ASC_RESETNEEDED
230 if(force){
231 #endif
232 MSG("Resetting traps");
233 reset_trap(SIGFPE);
234 reset_trap(SIGINT);
235 reset_trap(SIGSEGV);
236 #ifndef ASC_RESETNEEDED
237 }
238 #endif
239 }
240
241 /**
242 Add a handler to the stack of signal handlers for the given signal.
243
244 There is a maximum stack limit, so returns 1 if limit exceeded.
245 Returns -1 if stack of signal requested does not exist.
246 Pushing a NULL handler does NOT change anything at all.
247 On a successful return, the handler has been installed and will
248 remain installed until a Asc_SignalHandlerPop or another push.
249
250 @return 0 on success, -2 if func is NULL, -1 if unsupported signal is given,
251 -3 if 'signal' returns SIG_ERR.
252 */
253 int Asc_SignalHandlerPush_impl(int signum, SigHandlerFn *func, char *name
254 , char *file, int line
255 ){
256 int err;
257 if (func == NULL) {
258 return -2;
259 }
260
261 MSG("Pushing handler %s for signal %s(%d)",name,SIGNAME(signum),signum);
262
263 err = push_trap(signum, func, name, file, line);
264
265 if(err != 0){
266 ERROR_REPORTER_HERE(ASC_PROG_ERROR,"Error pushing %s to stack (err = %d, signal=%s(%d))."
267 ,name, err, SIGNAME(signum), signum
268 );
269 return err;
270 }
271
272 #if 0
273 /* TODO we can try introducing this code to solve the issues of the test_ascSignal
274 test cases, but really it's possible that our approach isn't really the right
275 one (and still not sure this fixes things on Windows, anyway). More work required. */
276 #ifdef __linux__
277 struct sigaction new_action, old_action;
278 new_action.sa_handler = func;
279 sigemptyset(&new_action.sa_mask);
280 new_action.sa_flags = 0;
281 sigaction(signum, NULL, &old_action);
282 /* FIXME we should have provision for dealing with signals currently set to SIG_IGN */
283 int err1 = sigaction(signum, &new_action, NULL);
284 sigset_t sigset;
285 sigprocmask(0, NULL, &sigset);
286 if(sigismember(&sigset, signum)){
287 sigemptyset(&sigset);
288 sigaddset(&sigset, signum);
289 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
290 }
291 return err1;
292 #else
293 return SIG_ERR==SIGNAL(signum, func); /* install */
294 #endif
295 #else
296 return SIG_ERR==SIGNAL(signum, func); /* install */
297 #endif
298 }
299
300
301 int Asc_SignalHandlerPop_impl(int signum, SigHandlerFn *tp, char *name
302 , char *file, int line
303 ){
304 int err;
305 MSG("(%s:%d) Popping signal stack for signal %s (%d) (expecting top to be %p '%s')",file,line,SIGNAME(signum),signum,tp,name);
306
307 err = pop_trap(signum, tp, name, file, line);
308
309 if (err != 0 && tp != NULL) {
310 MSG("stack pop mismatch");
311 ERROR_REPORTER_HERE(ASC_PROG_ERROR,"Asc_Signal (%d) stack pop mismatch.",signum);
312 return err;
313 }
314
315 #if 0
316 /* see comments above */
317 #ifdef __linux__
318 struct sigaction new_action, old_action;
319 new_action.sa_handler = Asc_SignalStackTop(signum);
320 sigemptyset(&new_action.sa_mask);
321 new_action.sa_flags = 0;
322 sigaction(signum, NULL, &old_action);
323 /* FIXME we should have provision for dealing with signals currently set to SIG_IGN */
324 sigaction(signum, &new_action, NULL);
325 sigset_t sigset;
326 sigprocmask(0, NULL, &sigset);
327 if(sigismember(&sigset, signum)){
328 sigemptyset(&sigset);
329 sigaddset(&sigset, signum);
330 sigprocmask(SIG_UNBLOCK, &sigset, NULL);
331 }
332 return err;
333 #else
334 SIGNAL(signum,Asc_SignalStackTop(signum));
335 return err;
336 #endif
337 #else
338 SIGNAL(signum,Asc_SignalStackTop(signum));
339 return err;
340 #endif
341 }
342
343 void Asc_SignalTrap(int sigval){
344 MSG("Caught signal #%d",sigval);
345 switch(sigval) {
346 case SIGFPE:
347 ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Floating point error caught");
348 MSG("SIGFPE caught");
349 #ifdef HAVE_C99FPE
350 FPRESET;
351 #endif
352 LONGJMP(g_fpe_env,sigval);
353 case SIGINT:
354 MSG("SIGINT (Ctrl-C) caught");
355 LONGJMP(g_int_env,sigval);
356 case SIGSEGV:
357 MSG("SIGSEGV caught");
358 LONGJMP(g_seg_env,sigval);
359 default:
360 MSG("Unrecognised signal %d caught",sigval);
361 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Installed on unexpected signal (sigval = %d). Returning (who knows where...)", sigval);
362 return;
363 }
364 }
365
366 void Asc_SignalPrintStack(int signum){
367 if(!f_traps){
368 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler not initialised!");
369 return;
370 }
371 SignalStackItem *stack;
372 int *index;
373 switch(signum){
374 case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
375 case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
376 case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
377 default:
378 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
379 return;
380 }
381 int i = 0;
382 const char *signame = (signum==SIGFPE?"SIGFPE":SIGNAME(signum));
383
384 #define LMAX 4096
385 char str[LMAX], *end = str;
386 int ch;
387 if(*index == -1){
388 fprintf(stderr,"%s handler stack: empty\n",signame);
389 }else{
390 for(i = 0; i <= *index; ++i){
391 #ifdef SIGNAL_DEBUG
392 ch = SNPRINTF(end, LMAX - (end - str), "%s ", stack[i].name);
393 #else
394 ch = SNPRINTF(end, LMAX - (end - str), "%p ", stack[i].handler);
395 #endif
396 end += ch;
397 if(ch<0)break;
398 }
399 fprintf(stderr,"%s handler stack: %s\n",signame,str);
400 }
401 }
402
403 int Asc_SignalStackLength(int signum){
404 int *index;
405 switch(signum){
406 case SIGFPE: index = &(f_traps->fpe_top); break;
407 case SIGINT: index = &(f_traps->int_top); break;
408 case SIGSEGV: index = &(f_traps->seg_top); break;
409 default:
410 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d",signum);
411 return 0;
412 }
413 return *index + 1;
414 }
415
416 SigHandlerFn *Asc_SignalStackTop(int signum){
417 if(!f_traps)return NULL;
418 SignalStackItem *stack;
419 int *index;
420 switch(signum){
421 case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
422 case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
423 case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
424 default:
425 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
426 return NULL;
427 }
428 if(*index < 0)return NULL;
429 if(*index >= MAX_TRAP_DEPTH)return NULL;
430 return stack[*index].handler;
431 }
432
433 /*------------------------------------------------------------------------------
434 UTILITY FUNCTIONS
435 */
436
437 /*
438 Removed ascresetneeded from here. This is a build-time configuration test
439 rather than a runtime test (and causes annoyance when running ASCEND through
440 a debugger).
441
442 So far the following seem to need reset trapped signals after
443 a longjmp, or unconditionally.
444 HPUX cc -Aa -D_HPUX_SOURCE
445 Solaris cc
446 AIX xlc
447 IRIX cc
448 Windows
449
450 The following retain the last trap set with or without a call to longjmp
451 and so don't need resetting of traps.
452 SunOS4 acc
453 OSF32 cc
454 NetBSD gcc 2.4.5 -ansi
455 Linux gcc (i386)
456 */
457
458 //------------------------------------
459 // COMMOM STACK ROUTINES (shared by the three different signal handler stacks)
460
461 static void initstack(int sig){
462 SigHandlerFn *old;
463 SignalStackItem *stack;
464 int *index;
465 switch(sig){
466 case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
467 case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
468 case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
469 default:
470 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", sig);
471 return;
472 }
473 old = SIGNAL(sig, SIG_DFL);
474 if(old != SIG_ERR && old != SIG_DFL){
475 MSG("Initialising stack for signal %d to %p",sig,old);
476 stack[0].handler = old;
477 #ifdef SIGNAL_DEBUG
478 if(old == SIG_DFL){
479 stack[0].name = "SIG_DFL";
480 }else{
481 stack[0].name = "preexisting";
482 }
483 stack[0].file = "unknown";
484 stack[0].line = 0;
485 #endif
486 *index = 0;
487 (void)SIGNAL(sig,old);
488 }else{
489 MSG("Initialising stack for signal %d as empty",sig);
490 *index = -1;
491 }
492 }
493
494 static void reset_trap(int signum){
495 SignalStackItem top;
496 SigHandlerFn *oldfn;
497
498 if(f_traps){
499 SignalStackItem *stack;
500 int *index;
501 switch(signum){
502 case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
503 case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
504 case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
505 default:
506 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
507 return;
508 }
509 if(*index >= 0 && *index < MAX_TRAP_DEPTH){
510 oldfn = signal(signum,SIG_DFL); (void)oldfn;
511 top = stack[*index];
512 if(top.handler != SIG_ERR && top.handler != SIG_DFL){
513 /* reset the signal, if it's not already set to what we want */
514 MSG("Resetting signal %s from %p to %p (%s)"
515 ,SIGNAME(signum)
516 ,oldfn,top.handler,top.name
517 );
518 (void)SIGNAL(signum,top.handler);
519 return;
520 }
521 }
522 MSG("Resetting %s handler to SIG_DFL (stack empty or invalid)"
523 ,SIGNAME(signum)
524 );
525 (void)SIGNAL(signum,SIG_DFL);
526 }else{
527 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler not yet initialised! Setting %s handler to SIG_DFL.",SIGNAME(signum));
528 (void)SIGNAL(signum,SIG_DFL);
529 return;
530 }
531 }
532
533 /**
534 Append a pointer to the list given, if the list is not full.
535 */
536 static int push_trap(int signum, SigHandlerFn *func, char *name, char *file, int line){
537 if(!f_traps){
538 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler list f_traps not initialised");
539 return -1;
540 }
541 SignalStackItem *stack;
542 int *index;
543 switch(signum){
544 case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
545 case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
546 case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
547 default:
548 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
549 return -2;
550 }
551
552 if (*index > MAX_TRAP_DEPTH-1) {
553 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler stack for %s is full!"
554 ,SIGNAME(signum)
555 );
556 return 1;
557 }
558 ++(*index);
559 stack[*index].handler = func;
560 #ifdef SIGNAL_DEBUG
561 stack[*index].name = name;
562 stack[*index].file = file;
563 stack[*index].line = line;
564 #endif
565 return 0;
566 }
567
568
569 /**
570 @return 0 on success, 2 on NULL tlist or stackptr input, 1 on empty stack
571 or -1 on mismatched input tp and stack data
572
573 Any non-zero return code leaves the stack as it was.
574 */
575 static int pop_trap(int signum, SigHandlerFn *func, char *name, char *file, int line){
576 int err = 0;
577 if(!f_traps){
578 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler list f_traps not initialised");
579 return 2;
580 }
581 SignalStackItem *stack;
582 int *index;
583 switch(signum){
584 case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
585 case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
586 case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
587 default:
588 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
589 return 3;
590 }
591
592 if(*index < 0)return 1;
593
594 if(stack[*index].handler != func){
595 #ifdef SIGNAL_DEBUG
596 error_reporter(ASC_PROG_ERR,file,line,name,"Request to pop '%s' (%p), but top of stack contains '%s' (%p)!"
597 ,name,func,stack[*index].name,stack[*index].handler
598 );
599 #else
600 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Request to pop handler %p, but top of stack contains %p!"
601 ,func,stack[*index].handler
602 );
603 #endif
604 err = 4;
605 }
606 stack[*index].handler = NULL;
607 #ifdef SIGNAL_DEBUG
608 stack[*index].name = NULL;
609 stack[*index].file = NULL;
610 stack[*index].line = 0;
611 #endif
612 --(*index);
613 return err;
614 }
615
616 /*------------------------------------------
617 FPE ENV STACK
618 */
619
620 #ifdef HAVE_C99FPE
621
622 /**
623 Store current FPU state so that we can reset it later (after we've done
624 some stuff)
625
626 return 0 on success
627 */
628 static int fenv_push(fenv_t *stack, int *top, int excepts){
629 MSG("Pushing FENV flags %d",excepts);
630
631 if(*top > MAX_TRAP_DEPTH - 1){
632 ERROR_REPORTER_HERE(ASC_PROG_ERR,"FPE stack is full");
633 return 1;
634 }
635 if(*top < -1){
636 ERROR_REPORTER_HERE(ASC_PROG_ERR,"stack top < -1");
637 return 2;
638 }
639 if(stack==NULL){
640 ERROR_REPORTER_HERE(ASC_PROG_ERR,"stack is NULL");
641 return 3;
642 }
643 fenv_t *fe = &stack[++(*top)];
644 if(fegetenv(fe)){
645 ERROR_REPORTER_HERE(ASC_PROG_ERR,"unable to get env");
646 return 4;
647 }
648 fesetexceptflag(&g_fenv, excepts);
649 MSG("Enabled div-by-zero FPE exception (%d)",*top);
650 return 0;
651 }
652
653 /**
654 Restore a saved FPU state. Return 0 on success.
655 */
656 static int fenv_pop(fenv_t *stack, int *top){
657 MSG("Popping FENV flags");
658 if(*top < 0){
659 ERROR_REPORTER_HERE(ASC_PROG_ERR,"FPE stack is empty");
660 return 1;
661 }
662 if(stack==NULL){
663 ERROR_REPORTER_HERE(ASC_PROG_ERR,"stack is NULL");
664 return 2;
665 }
666 fenv_t *fe = &stack[(*top)--];
667 if(fesetenv(fe)){
668 ERROR_REPORTER_HERE(ASC_PROG_ERR,"unable to set env");
669 return 3;
670 }
671 MSG("Restorted FPE state");
672 return 0;
673 }
674
675 #endif /* HAVE_C99FPE */
676
677 #endif /* ASC_SIGNAL_TRAPS */

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22