/[ascend]/trunk/base/generic/utilities/ascSignal.c
ViewVC logotype

Annotation of /trunk/base/generic/utilities/ascSignal.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1003 - (hide annotations) (download) (as text)
Sun Dec 31 02:35:27 2006 UTC (16 years, 2 months ago) by johnpye
File MIME type: text/x-csrc
File size: 15738 byte(s)
Some progress on fixing test_ascSignal.c
1 johnpye 526 /* 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, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330,
18     Boston, MA 02111-1307, USA.
19 johnpye 953 *//** @file
20     Signal handling protocol definitions for ASCEND
21    
22     Start of making signal handling in ASCEND
23     code somewhat sane. Still needs to somehow
24     support the management of jmp_buf's so that
25     handlers will longjmp to the right place.
26    
27     A better alternative is to make all our code check/return
28     status flags based on a variable set by the trap
29     and cleared by recipient.
30 johnpye 526 *//*
31 johnpye 953 by Benjamin Andrew Allan, May 27, 1997
32     Last in CVS $Revision: 1.9 $ $Date: 1999/01/19 12:23:20 $ $Author: mthomas $
33    
34     10/15/2005 - Changed ascresetneeded() so that any previously
35     registered handlers are reset before return.
36     - Added Asc_SignalRecover() to standard handler
37     Asc_SignalTrap() so handlers are reset if necessary. (JDS)
38     12/10/2005 - Changed storage of signal handlers from gl_list's
39     to local arrays. gl_list's can't legally hold
40     function pointers. (JDS)
41 johnpye 968 18 Dec 06 - Removed ascresetneeded (moved to SConstruct)
42 johnpye 953 */
43    
44 johnpye 997 #define _GNU_SOURCE /* enables feenableexcept (http://gcc.gnu.org/ml/fortran/2005-10/msg00365.html) */
45 ben.allan 14 #include <stdio.h>
46 johnpye 968 #include "config.h"
47 johnpye 399 #include "ascConfig.h"
48 johnpye 85
49 johnpye 968 #include <signal.h>
50     #include <setjmp.h>
51 johnpye 85
52 johnpye 968 #ifdef HAVE_C99FPE
53     # include <fenv.h>
54     #endif
55    
56 aw0a 1 #ifdef __WIN32__
57 johnpye 85 # include <process.h>
58 aw0a 1 #else
59 johnpye 85 # include <unistd.h>
60 aw0a 1 #endif
61 johnpye 85
62 johnpye 399 #include "ascMalloc.h"
63     #include "ascSignal.h"
64 johnpye 1002 #include "ascPanic.h"
65 aw0a 1
66 johnpye 1002 #define SIGNAL_DEBUG
67    
68 johnpye 956 /*------------------------------------------------------------------------------
69     GLOBALS AND FOWARD DECS
70     */
71    
72 aw0a 1 /* test buf for initialization */
73 johnpye 997 JMP_BUF g_fpe_env;
74     JMP_BUF g_seg_env;
75     JMP_BUF g_int_env;
76 aw0a 1
77 johnpye 968 #ifdef HAVE_C99FPE
78     fenv_t g_fenv;
79     #endif
80    
81 aw0a 1 /* for future use */
82     jmp_buf g_foreign_code_call_env;
83    
84 johnpye 953 static SigHandlerFn **f_fpe_traps = NULL; /**< array for pushed SIGFPE handlers */
85 jds 102 static int f_fpe_top_of_stack = -1; /**< top of SIGFPE stack, -1 for empty */
86 aw0a 1
87 johnpye 953 static SigHandlerFn **f_int_traps = NULL; /**< array for pushed SIGINT handlers */
88 jds 102 static int f_int_top_of_stack = -1; /**< top of SIGFPE stack, -1 for empty */
89    
90 johnpye 953 static SigHandlerFn **f_seg_traps = NULL; /**< array for pushed SIGSEGV handlers */
91 jds 102 static int f_seg_top_of_stack = -1; /**< top of SIGFPE stack, -1 for empty */
92    
93 johnpye 968 #ifdef HAVE_C99FPE
94     static fenv_t *f_fenv_stack = NULL;
95     static int f_fenv_stack_top = -1;
96     #endif
97    
98 johnpye 956 static void initstack (SigHandlerFn **traps, int *stackptr, int sig);
99     static int pop_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp);
100     static int push_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp);
101     static void reset_trap(int signum, SigHandlerFn **tlist, int tos);
102 johnpye 1002 static void print_stack(int signum, SigHandlerFn **tlist, int tos);
103 aw0a 1
104 johnpye 968 #ifdef HAVE_C99FPE
105     static int fenv_pop(fenv_t *stack, int *top);
106 johnpye 997 static int fenv_push(fenv_t *stack,int *top, int excepts);
107 johnpye 968 #endif
108    
109 johnpye 956 /*------------------------------------------------------------------------------
110     API FUNCTIONS
111 johnpye 953 */
112 johnpye 89
113 johnpye 953 /**
114     Initialise ASCEND signal handling
115    
116     Does not establish any traps, just the structures for maintaining them.
117     Pushes the existing traps, if any, on the bottom of the created stacks.
118    
119     @NOTE Cannot be called twice successfully.
120    
121     @return 0 if successful, 1 if out of memory, 2 otherwise.
122     */
123 aw0a 1 int Asc_SignalInit(void)
124     {
125 jds 102 /* initialize SIGFPE stack */
126 johnpye 1002
127     #ifdef SIGNAL_DEBUG
128     CONSOLE_DEBUG("Initialising signal stack");
129     #endif
130    
131 jds 102 if (f_fpe_traps == NULL) {
132 johnpye 953 f_fpe_traps = ASC_NEW_ARRAY_CLEAR(SigHandlerFn*,MAX_TRAP_DEPTH);
133 jds 102 if (f_fpe_traps == NULL) {
134     return 1;
135     }
136 jds 59 }
137 jds 102 f_fpe_top_of_stack = -1;
138    
139 johnpye 968 #ifdef HAVE_C99FPE
140     if(f_fenv_stack==NULL){ /* if we haven't already initialised this... */
141     f_fenv_stack = ASC_NEW_ARRAY_CLEAR(fenv_t,MAX_TRAP_DEPTH);
142 johnpye 1002 if(f_fenv_stack == NULL){
143     return 1; /* failed to allocate */
144     }
145 johnpye 968 }
146     f_fenv_stack_top = -1;
147     #endif
148    
149 jds 102 /* initialize SIGINT stack */
150     if (f_int_traps == NULL) {
151 johnpye 953 f_int_traps = ASC_NEW_ARRAY_CLEAR(SigHandlerFn*,MAX_TRAP_DEPTH);
152 johnpye 1002 if(f_int_traps == NULL){
153     /* failed malloc: free the earlier stuff */
154     ASC_FREE(f_fpe_traps);
155 jds 102 f_fpe_traps = NULL;
156     return 1;
157     }
158     }
159     f_int_top_of_stack = -1;
160    
161     /* initialize SIGSEGV stack */
162     if (f_seg_traps == NULL) {
163 johnpye 953 f_seg_traps = ASC_NEW_ARRAY_CLEAR(SigHandlerFn*,MAX_TRAP_DEPTH);
164 jds 102 if (f_seg_traps == NULL) {
165 johnpye 1002 /* failed malloc: free the earlier stuff */
166     ASC_FREE(f_fpe_traps);
167 jds 102 f_fpe_traps = NULL;
168 johnpye 1002 ASC_FREE(f_int_traps);
169 jds 102 f_int_traps = NULL;
170     return 1;
171     }
172     }
173     f_seg_top_of_stack = -1;
174    
175 johnpye 1003 /* old signals are *not* stored */
176 jds 102 initstack(f_fpe_traps, &f_fpe_top_of_stack, SIGFPE);
177     initstack(f_int_traps, &f_int_top_of_stack, SIGINT);
178     initstack(f_seg_traps, &f_seg_top_of_stack, SIGSEGV);
179 johnpye 190
180 johnpye 968 #ifdef HAVE_C99FPE
181 johnpye 997 CONSOLE_DEBUG("Initialise FPE state to stack (%d)",f_fenv_stack_top);
182     fenv_push(f_fenv_stack,&f_fenv_stack_top,0);
183 johnpye 968 #endif
184    
185 aw0a 1 return 0;
186     }
187    
188 johnpye 953 /**
189     Clears and destroys the stacks of signal handlers.
190     */
191 aw0a 1 void Asc_SignalDestroy(void)
192     {
193 jds 102 ascfree(f_fpe_traps);
194     ascfree(f_int_traps);
195     ascfree(f_seg_traps);
196 johnpye 1002 #ifdef HAVE_C99FPE
197     if(f_fenv_stack){
198     ASC_FREE(f_fenv_stack);
199     f_fenv_stack = NULL;
200     }
201     #endif
202 jds 59 f_fpe_traps = f_int_traps = f_seg_traps = NULL;
203 jds 102 f_fpe_top_of_stack = f_int_top_of_stack = f_seg_top_of_stack = -1;
204 johnpye 1002
205     #ifdef SIGNAL_DEBUG
206     CONSOLE_DEBUG("Destroyed signal stack");
207     #endif
208 aw0a 1 }
209    
210 johnpye 956 /**
211 johnpye 953 This function reinstalls all the signal handlers this module
212     has been informed of. This should be called after every
213     trapped exception and at any other time when the status of
214     exception handlers may have become not well defined.
215     The most recently pushed handler is installed for each supported
216     signal. If nothing on stack, SIG_DFL gets installed.
217    
218     @NOTE that if somebody installs a handler without going through
219     our push/pop, theirs is liable to be forgotten.
220     */
221 johnpye 968 void Asc_SignalRecover(int force){
222     #ifndef ASC_RESETNEEDED
223     if(force){
224     #endif
225 johnpye 1002 # ifdef SIGNAL_DEBUG
226     CONSOLE_DEBUG("Resetting traps");
227     # endif
228 johnpye 968 reset_trap(SIGFPE, f_fpe_traps, f_fpe_top_of_stack);
229     reset_trap(SIGINT, f_int_traps, f_int_top_of_stack);
230     reset_trap(SIGSEGV, f_seg_traps, f_seg_top_of_stack);
231     #ifndef ASC_RESETNEEDED
232     }
233     #endif
234 aw0a 1 }
235    
236 johnpye 968 int Asc_SignalHandlerPushDefault(int signum){
237     return Asc_SignalHandlerPush(signum, &Asc_SignalTrap);
238     }
239    
240 johnpye 953 /**
241     Add a handler to the stack of signal handlers for the given signal.
242    
243     There is a maximum stack limit, so returns 1 if limit exceeded.
244     Returns -1 if stack of signal requested does not exist.
245     Pushing a NULL handler does NOT change anything at all.
246     On a successful return, the handler has been installed and will
247     remain installed until a Asc_SignalHandlerPop or another push.
248     */
249     int Asc_SignalHandlerPush(int signum, SigHandlerFn *tp)
250 aw0a 1 {
251     int err;
252 jds 59 if (tp == NULL) {
253 aw0a 1 return 0;
254     }
255 johnpye 1002
256     #ifdef SIGNAL_DEBUG
257     CONSOLE_DEBUG("Pushing handler at %p for signal %d",tp,signum);
258     #endif
259    
260 aw0a 1 switch (signum) {
261 jds 59 case SIGFPE:
262 johnpye 968 //CONSOLE_DEBUG("PUSH SIGFPE");
263 jds 102 err = push_trap(f_fpe_traps, &f_fpe_top_of_stack, tp);
264 johnpye 968 #ifdef HAVE_C99FPE
265 johnpye 997 if(tp == SIG_IGN){
266 johnpye 1002 err = fenv_push(f_fenv_stack, &f_fenv_stack_top,FE_ALL_EXCEPT);
267 johnpye 997 }else{
268     err = fenv_push(f_fenv_stack, &f_fenv_stack_top,0);
269     }
270 johnpye 968 #endif
271 jds 59 break;
272     case SIGINT:
273 johnpye 1002 CONSOLE_DEBUG("PUSH SIGINT");
274 jds 102 err = push_trap(f_int_traps, &f_int_top_of_stack, tp);
275 jds 59 break;
276     case SIGSEGV:
277 johnpye 961 /* CONSOLE_DEBUG("PUSH SIGSEGV"); */
278 jds 102 err = push_trap(f_seg_traps, &f_seg_top_of_stack, tp);
279 jds 59 break;
280     default:
281     return -1;
282 aw0a 1 }
283 johnpye 1003 if(err != 0){
284 johnpye 1002 ERROR_REPORTER_HERE(ASC_PROG_ERROR,"Error from push_trap or fenv_push (err = %d, signal=#%d).",err, signum);
285 aw0a 1 return err;
286     }
287 johnpye 1002 (void)SIGNAL(signum, tp); /* install */
288 aw0a 1 return 0;
289     }
290    
291 johnpye 968 int Asc_SignalHandlerPopDefault(int signum){
292     return Asc_SignalHandlerPop(signum, &Asc_SignalTrap);
293     }
294    
295 johnpye 956 /* see ascSignal.h */
296 johnpye 953 int Asc_SignalHandlerPop(int signum, SigHandlerFn *tp){
297 aw0a 1 int err;
298 johnpye 1002 #ifdef SIGNAL_DEBUG
299     CONSOLE_DEBUG("Popping signal stack for signal %d (expecting top to be %p)",signum,tp);
300     #endif
301    
302 aw0a 1 switch (signum) {
303     case SIGFPE:
304 johnpye 1003 CONSOLE_DEBUG("POP SIGFPE");
305 jds 102 err = pop_trap(f_fpe_traps, &f_fpe_top_of_stack, tp);
306 johnpye 1003 #if 0 && defined(HAVE_C99FPE)
307     if(!err){
308     err = fenv_pop(f_fenv_stack, &f_fenv_stack_top);
309     }
310 johnpye 968 #endif
311 aw0a 1 break;
312     case SIGINT:
313 johnpye 1002 CONSOLE_DEBUG("POP SIGINT");
314 jds 102 err = pop_trap(f_int_traps, &f_int_top_of_stack, tp);
315 aw0a 1 break;
316     case SIGSEGV:
317 johnpye 1003 CONSOLE_DEBUG("POP SIGSEGV");
318 jds 102 err = pop_trap(f_seg_traps, &f_seg_top_of_stack, tp);
319 aw0a 1 break;
320     default:
321 johnpye 85 CONSOLE_DEBUG("popping invalid signal type (signum = %d)", signum);
322 aw0a 1 return -1;
323     }
324     if (err != 0 && tp != NULL) {
325 johnpye 85 CONSOLE_DEBUG("stack pop mismatch");
326 johnpye 190 ERROR_REPORTER_HERE(ASC_PROG_ERROR,"Asc_Signal (%d) stack pop mismatch.",signum);
327 aw0a 1 return err;
328     }
329 johnpye 1003 SIGNAL(signum,Asc_SignalStackTop(signum));
330 aw0a 1 return 0;
331     }
332    
333     void Asc_SignalTrap(int sigval) {
334 johnpye 1002 #ifdef SIGNAL_DEBUG
335     CONSOLE_DEBUG("Caught signal #%d",sigval);
336     #endif
337 aw0a 1 switch(sigval) {
338     case SIGFPE:
339 johnpye 968 ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Floating point error caught");
340 johnpye 85 CONSOLE_DEBUG("SIGFPE caught");
341 johnpye 1002 #ifdef HAVE_C99FPE
342 aw0a 1 FPRESET;
343 johnpye 1002 #endif
344 johnpye 997 LONGJMP(g_fpe_env,sigval);
345 aw0a 1 break;
346     case SIGINT:
347 johnpye 85 CONSOLE_DEBUG("SIGINT (Ctrl-C) caught");
348 johnpye 997 LONGJMP(g_int_env,sigval);
349 aw0a 1 break;
350     case SIGSEGV:
351 johnpye 85 CONSOLE_DEBUG("SIGSEGV caught");
352 johnpye 997 LONGJMP(g_seg_env,sigval);
353 aw0a 1 break;
354     default:
355 johnpye 85 CONSOLE_DEBUG("Installed on unexpected signal (sigval = %d).", sigval);
356     CONSOLE_DEBUG("Returning ... who knows where :-)");
357 aw0a 1 break;
358     }
359     return;
360     }
361 johnpye 956
362 johnpye 1002 void Asc_SignalPrintStack(int signum){
363     switch(signum){
364     case SIGINT:
365     print_stack(SIGINT,f_int_traps,f_int_top_of_stack);
366     return;
367     case SIGFPE:
368     print_stack(SIGFPE,f_fpe_traps,f_fpe_top_of_stack);
369     return;
370     case SIGSEGV:
371     print_stack(SIGSEGV,f_seg_traps,f_seg_top_of_stack);
372     return;
373     default:
374     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal %d",signum);
375     }
376     }
377    
378     int Asc_SignalStackLength(int signum){
379     switch(signum){
380     case SIGINT:
381 johnpye 1003 return f_int_top_of_stack + 1;
382 johnpye 1002 case SIGFPE:
383 johnpye 1003 return f_fpe_top_of_stack + 1;
384 johnpye 1002 case SIGSEGV:
385 johnpye 1003 return f_seg_top_of_stack + 1;
386 johnpye 1002 default:
387     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal %d",signum);
388 johnpye 1003 return 0;
389 johnpye 1002 }
390     }
391    
392 johnpye 1003 SigHandlerFn *Asc_SignalStackTop(int signum){
393     SigHandlerFn **stack;
394     int *ptr;
395     switch(signum){
396     case SIGINT:
397     stack = f_int_traps; ptr = &f_int_top_of_stack; break;
398     case SIGFPE:
399     stack = f_fpe_traps; ptr = &f_fpe_top_of_stack; break;
400     case SIGSEGV:
401     stack = f_seg_traps; ptr = &f_seg_top_of_stack; break;
402     }
403     if(stack==NULL)return NULL;
404     if(ptr==NULL)return NULL;
405     if(*ptr < 0) return NULL;
406     if(*ptr >= MAX_TRAP_DEPTH) return NULL;
407     return stack[*ptr];
408     }
409 johnpye 1002
410 johnpye 956 /*------------------------------------------------------------------------------
411     UTILITY FUNCTIONS
412     */
413    
414     /*
415 johnpye 968 Removed ascresetneeded from here. This is a build-time configuration test
416     rather than a runtime test (and causes annoyance when running ASCEND through
417     a debugger).
418 johnpye 956
419 johnpye 968 So far the following seem to need reset trapped signals after
420     a longjmp, or unconditionally.
421     HPUX cc -Aa -D_HPUX_SOURCE
422     Solaris cc
423     AIX xlc
424     IRIX cc
425     Windows
426 johnpye 956
427 johnpye 968 The following retain the last trap set with or without a call to longjmp
428     and so don't need resetting of traps.
429     SunOS4 acc
430     OSF32 cc
431     NetBSD gcc 2.4.5 -ansi
432     Linux gcc (i386)
433 johnpye 956 */
434    
435 johnpye 968 //------------------------------------
436     // COMMOM STACK ROUTINES (shared by the three different signal handler stacks)
437 johnpye 956
438 johnpye 968 static void initstack(SigHandlerFn **traps, int *stackptr, int sig){
439 johnpye 956 SigHandlerFn *old;
440 johnpye 1002 old = SIGNAL(sig,SIG_DFL);
441     if (old != SIG_ERR && old != SIG_DFL){
442     CONSOLE_DEBUG("Initialising stack for signal %d to %p",sig,old);
443 johnpye 956 traps[0] = old;
444     *stackptr = 0;
445 johnpye 1002 (void)SIGNAL(sig,old);
446 johnpye 1003 }else{
447     CONSOLE_DEBUG("Initialising stack for signal %d as empty",sig);
448     *stackptr = -1;
449 johnpye 956 }
450     }
451    
452     static void reset_trap(int signum, SigHandlerFn **tlist, int tos){
453     SigHandlerFn *tp;
454 johnpye 1002 SigHandlerFn *oldfn;
455 johnpye 956 if ((tlist != NULL) && (tos >= 0) && (tos < MAX_TRAP_DEPTH)) {
456 johnpye 1003 oldfn = signal(signum,SIG_DFL);
457 johnpye 956 tp = tlist[tos];
458     if (tp != SIG_ERR) {
459 johnpye 1003 #ifndef ASC_RESETNEEDED
460 johnpye 1002 if(tp!=oldfn){
461 johnpye 1003 ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Resetting signal %d (was=%p, new=%p",signum,oldfn,tp);
462 johnpye 1002 }
463     #endif
464 johnpye 1003 (void)signal(signum,tp);
465 johnpye 956 }
466 johnpye 1002 }else{
467     (void)SIGNAL(signum,SIG_DFL);
468 johnpye 956 }
469     }
470    
471     /**
472     Append a pointer to the list given, if the list is not full.
473     */
474     static int push_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp){
475     if (tlist == NULL) {
476 johnpye 1003 ERROR_REPORTER_HERE(ASC_PROG_ERR,"TLIST is NULL");
477 johnpye 956 return -1;
478     }
479     if (stackptr == NULL) {
480 johnpye 1003 ERROR_REPORTER_HERE(ASC_PROG_ERR,"STACKPTR is NULL");
481 johnpye 956 return -1;
482     }
483     if (tp == NULL) {
484 johnpye 1003 ERROR_REPORTER_HERE(ASC_PROG_ERR,"TP is NULL");
485 johnpye 956 return 2;
486     }
487     if (*stackptr > MAX_TRAP_DEPTH-1) {
488 johnpye 1003 ERROR_REPORTER_HERE(ASC_PROG_ERR,"stackptr >= capacity");
489 johnpye 956 return 1;
490     }
491     ++(*stackptr);
492     tlist[*stackptr] = tp;
493     return 0;
494     }
495    
496    
497 johnpye 1003 /**
498     @return 0 on success, 2 on NULL tlist or stackptr input, 1 on empty stack
499     or -1 on mismatched input tp and stack data
500    
501     Any non-zero return code leaves the stack as it was.
502 johnpye 956 */
503     static int pop_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp){
504     SigHandlerFn *oldtrap;
505    
506     if ((tlist == NULL) || (stackptr == NULL)) {
507     return 2;
508     }
509     if (*stackptr < 0) {
510     return 1;
511     }
512     oldtrap = tlist[*stackptr];
513 johnpye 1003 if(oldtrap != tp)return -1;
514 johnpye 956 tlist[*stackptr] = NULL;
515     --(*stackptr);
516 johnpye 1003 return 0;
517 johnpye 956 }
518 johnpye 968
519 johnpye 1002 static void print_stack(int signum, SigHandlerFn **tlist, int tos){
520     int i;
521     CONSOLE_DEBUG("---------------");
522 johnpye 1003 for(i=0;i<=tos;++i){
523 johnpye 1002 CONSOLE_DEBUG("Signal #%d, stack %d/%d: %p",signum,i,tos,tlist[i]);
524     }
525     CONSOLE_DEBUG("--------------- = %d",tos);
526     }
527    
528 johnpye 968 /*------------------------------------------
529     FPE ENV STACK
530     */
531    
532     #ifdef HAVE_C99FPE
533    
534     /**
535     Store current FPU state so that we can reset it later (after we've done
536     some stuff)
537    
538     return 0 on success
539     */
540 johnpye 997 static int fenv_push(fenv_t *stack, int *top, int excepts){
541     CONSOLE_DEBUG("Pushing FENV flags %d",excepts);
542    
543 johnpye 968 if(*top > MAX_TRAP_DEPTH - 1){
544     ERROR_REPORTER_HERE(ASC_PROG_ERR,"FPE stack is full");
545     return 1;
546     }
547     if(*top < -1){
548     ERROR_REPORTER_HERE(ASC_PROG_ERR,"stack top < -1");
549     return 2;
550     }
551     if(stack==NULL){
552     ERROR_REPORTER_HERE(ASC_PROG_ERR,"stack is NULL");
553     return 3;
554     }
555     fenv_t *fe = &stack[++(*top)];
556     if(fegetenv(fe)){
557     ERROR_REPORTER_HERE(ASC_PROG_ERR,"unable to get env");
558     return 4;
559     }
560 johnpye 997 fesetexceptflag(&g_fenv, excepts);
561 johnpye 968 //CONSOLE_DEBUG("Enabled div-by-zero FPE exception (%d)",*top);
562     return 0;
563     }
564    
565     /**
566 johnpye 997 Restore a saved FPU state. Return 0 on success.
567 johnpye 968 */
568     static int fenv_pop(fenv_t *stack, int *top){
569 johnpye 997 CONSOLE_DEBUG("Popping FENV flags");
570    
571 johnpye 968 if(*top < 0){
572     ERROR_REPORTER_HERE(ASC_PROG_ERR,"FPE stack is empty");
573     return 1;
574     }
575     if(stack==NULL){
576     ERROR_REPORTER_HERE(ASC_PROG_ERR,"stack is NULL");
577     return 2;
578     }
579     fenv_t *fe = &stack[(*top)--];
580     if(fesetenv(fe)){
581     ERROR_REPORTER_HERE(ASC_PROG_ERR,"unable to set env");
582     return 3;
583     }
584     //CONSOLE_DEBUG("Restorted FPE state");
585     return 0;
586     }
587    
588     #endif /* HAVE_C99FPE */
589    

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