Fetch Flex from Sourceforge.
[AROS-Contrib.git] / regina / signals.c
blobc9e85ce4e095551da8c0739fe58269cbd2f49a4f
1 #ifndef lint
2 static char *RCSid = "$Id$";
3 #endif
5 /*
6 * The Regina Rexx Interpreter
7 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "rexx.h"
25 #include <string.h>
26 #include <stdio.h>
27 #include <signal.h>
29 #ifdef VMS
30 # ifndef SIG_ERR
31 # define SIG_ERR BADSIG
32 # endif
33 #endif
35 /* at least dolphin does not have a properly ANSI C set of include files */
36 #ifndef SIG_ERR
37 # define SIG_ERR ((void(*)())(-1))
38 #endif
40 const char *signalnames[] = {
41 "ERROR",
42 "FAILURE",
43 "HALT",
44 "NOVALUE",
45 "NOTREADY",
46 "SYNTAX"
47 } ;
49 #ifdef TRACEMEM
50 void mark_signals( const tsd_t *TSD )
52 if (TSD->nextsig)
54 markmemory( TSD->nextsig, TRC_MATH ) ;
55 if (TSD->nextsig->descr)
56 markmemory( TSD->nextsig->descr, TRC_MATH ) ;
59 #endif
62 static trap *dupltraps( const tsd_t *TSD, const trap *traps )
64 trap *ptr=NULL ;
65 int i=0 ;
67 ptr = MallocTSD(sizeof(trap) * SIGNALS) ;
68 /* Stupid SunOS acc gives incorrect warning for the next line */
69 memcpy( ptr, traps, sizeof(trap) * SIGNALS) ;
70 for ( i=0; i<SIGNALS; i++ )
71 if (traps[i].name)
72 ptr[i].name = Str_dupTSD( traps[i].name ) ;
75 return ptr ;
79 sigtype *getsigs( proclevel level )
81 for (; level && (!level->sig); level=level->prev ) ;
82 return ((level) ? (level->sig) : (NULL)) ;
85 trap *gettraps( const tsd_t *TSD, proclevel level )
87 proclevel ptr=level ;
89 if (!ptr->traps)
91 for (ptr=level; ptr && ptr->traps==NULL; ptr=ptr->prev ) ;
92 if (ptr==NULL || ptr->traps==NULL)
93 exiterror( ERR_INTERPRETER_FAILURE, 1, __FILE__, __LINE__, "" ) ;
95 level->traps = dupltraps( TSD, ptr->traps ) ;
96 ptr = level ;
99 return ptr->traps ;
103 int condition_hook( tsd_t *TSD, int type, int errorno, int suberrorno, int lineno, streng *description, streng *condition_description )
105 trap *traps;
106 sigtype *sigptr=NULL ;
108 traps = gettraps( TSD, TSD->currlevel ) ;
109 /* if we dont know what to do, ... or */
110 /* if we don't *really* want to try to recover from these ... */
111 if (traps==NULL || type == SIGNAL_FATAL)
113 if (description)
114 Free_stringTSD( description ) ;
115 return 0 ;
118 if (lineno==(-1))
120 if (TSD->currentnode)
121 lineno = TSD->currentnode->lineno ;
122 else
123 #ifdef NDEBUG
124 lineno = 0 ;
125 #else
126 exiterror( ERR_INTERPRETER_FAILURE, 1, __FILE__, __LINE__, "" ) ;
127 #endif
129 if ( traps[type].on_off) /* condition is being trapped */
131 if ((traps[type].delayed) && (traps[type].ignored))
133 if (description)
134 Free_stringTSD( description ) ;
135 return 0 ;
138 sigptr = MallocTSD( sizeof( sigtype )) ;
140 sigptr->type = type ;
141 sigptr->info = NULL ; /* BUG: I don't really think this is used */
142 #if 0
143 sigptr->descr = description ;
144 #else
145 if (condition_description)
146 sigptr->descr = condition_description ;
147 else
148 sigptr->descr = description ;
149 #endif
150 sigptr->invoke = traps[type].invoked ;
151 sigptr->rc = errorno ;
152 sigptr->subrc = suberrorno ;
153 sigptr->lineno = lineno ;
155 if ( traps[type].invoked ) /* if SIGNAL ON */
157 /* traps[type].on_off = 0 ; */ /* turn trap off */
158 /* traps[type].trapped = 0 ; */ /* unecessary, just to be sure */
159 traps[type].delayed = 0 ; /* ... ditto ... */
160 setvalue( TSD, &SIGL_name, int_to_streng( TSD, lineno )) ;
161 if (type == SIGNAL_SYNTAX) /* special condition */
162 setvalue( TSD, &RC_name, int_to_streng( TSD, errorno )) ;
164 TSD->nextsig = sigptr ;
166 if (TSD->in_protected)
168 TSD->delayed_error_type = PROTECTED_DelayedSetjmpBuf;
169 longjmp( TSD->protect_return, 1 ) ;
171 longjmp( *(TSD->currlevel->buf), 1 ) ;
173 else
175 TSD->nextsig = sigptr ;
176 return 1 ;
180 if (description)
181 Free_stringTSD(description) ;
183 /* signal is not to be trapped */
184 return (traps[type].def_act) ;
188 int identify_trap( int type )
190 switch (type)
192 case X_S_HALT: return SIGNAL_HALT ;
193 case X_S_SYNTAX: return SIGNAL_SYNTAX ;
194 case X_S_NOVALUE: return SIGNAL_NOVALUE ;
195 case X_S_NOTREADY: return SIGNAL_NOTREADY ;
196 case X_S_ERROR: return SIGNAL_ERROR ;
197 case X_S_FAILURE: return SIGNAL_FAILURE ;
199 exiterror( ERR_INTERPRETER_FAILURE, 1, __FILE__, __LINE__, "" ) ;
200 return SIGNAL_FATAL ;
204 /* the rest should probably also be defined */
205 static const char *signals_names[] = {
206 "", "SIGHUP", "SIGINT", "", "", "", "", "", "", "",
207 "", "", "", "", "", "SIGTERM", "", "", "", "", "",
208 "", "", "", "", "", "", "", "", "", "",
209 "", ""
212 #if defined (HAVE_SIGACTION) && defined(SA_RESTART) && defined(HAVE__SIGHANDLER_T)
213 /* Most things only works if a signal doesn't break the current system call.
214 * sigaction has such a flag and should always been preferred. It has an
215 * exactlier defined standard.
216 * Defining a "signal()" here also overwrites signal calls in the whole
217 * program. FGC
219 signal_handler regina_signal(int signum,__sighandler_t action)
221 struct sigaction nsig,osig;
223 nsig.sa_handler = action;
224 sigemptyset(&nsig.sa_mask);
225 nsig.sa_flags = SA_RESTART;
226 if (sigaction(signum,&nsig,&osig) != 0)
227 return(SIG_ERR);
228 return(osig.sa_handler);
230 #elif defined(__AROS__)
231 signal_handler regina_signal(int signum,signal_handler action)
233 return SIG_ERR;
235 #else
236 signal_handler regina_signal(int signum,signal_handler action)
238 # if defined(__WINS__) || defined(__EPOC32__)
239 return 0;
240 # else
241 return( signal ( signum, action ) ) ;
242 # endif
244 #endif
246 /* Yuk! Some of these should *really* have been volatilized */
247 static void halt_handler( int num )
249 tsd_t *TSD = __regina_get_tsd(); /* The TSD must be fetched directly. */
251 #ifdef VMS
252 vms_killproc( TSD ) ;
253 #endif
255 if (regina_signal( num, halt_handler ) == SIG_ERR)
256 exiterror( ERR_SYSTEM_FAILURE, 0 ) ;
258 if (!condition_hook(TSD,
259 SIGNAL_HALT,
260 ERR_PROG_INTERRUPT,
262 lineno_of(TSD->currentnode),
263 Str_creTSD(signals_names[num]),
264 NULL
266 exiterror( ERR_PROG_INTERRUPT, 0 ) ;
268 return ;
271 #if !defined(__WINS__) && !defined(__EPOC32__) && !defined(__AROS__)
272 # if defined(SIGHUP)
273 static void hup_handler( int dummy )
275 tsd_t *TSD = __regina_get_tsd();
277 if (TSD->in_protected)
279 TSD->delayed_error_type = PROTECTED_DelayedExit;
280 TSD->expected_exit_error = 0;
281 longjmp( TSD->protect_return, 1 ) ;
283 TSD->MTExit( 0 ) ;
285 # endif
286 #endif
289 void signal_setup( const tsd_t *TSD )
291 TSD = TSD; /* keep compiler happy */
294 * EPOC32 does not have signal()!!
295 * AROS at the moment also lacks signal
297 #if !defined(__WINS__) && !defined(__EPOC32__) && !defined(__AROS__)
298 # if defined(SIGTERM)
299 if (regina_signal( SIGTERM, halt_handler ) == SIG_ERR)
300 exiterror( ERR_SYSTEM_FAILURE, 0 ) ;
301 # endif
302 # if defined(SIGINT)
303 if (regina_signal( SIGINT, halt_handler) == SIG_ERR)
304 exiterror( ERR_SYSTEM_FAILURE, 0 ) ;
305 # endif
306 # if defined(SIGHUP)
307 if (regina_signal( SIGHUP, (TSD->isclient)?(hup_handler):(halt_handler)) == SIG_ERR)
308 exiterror( ERR_SYSTEM_FAILURE, 0 ) ;
309 # endif
310 #endif
313 void set_rexx_halt( void )
315 halt_handler( SIGINT );