2 * The Regina Rexx Interpreter
3 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library 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 GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 # define SIG_ERR BADSIG
31 /* at least dolphin does not have a properly ANSI C set of include files */
33 # define SIG_ERR ((void(*)())(-1))
36 const char *signalnames
[] = {
47 void mark_signals( const tsd_t
*TSD
)
51 markmemory( TSD
->nextsig
, TRC_MATH
) ;
52 if (TSD
->nextsig
->descr
)
53 markmemory( TSD
->nextsig
->descr
, TRC_MATH
) ;
59 static trap
*dupltraps( const tsd_t
*TSD
, const trap
*traps
)
64 ptr
= (trap
*)MallocTSD( sizeof(trap
) * SIGNALS
) ;
65 /* Stupid SunOS acc gives incorrect warning for the next line */
66 memcpy( ptr
, traps
, sizeof(trap
) * SIGNALS
) ;
67 for ( i
= 0; i
< SIGNALS
; i
++ )
69 ptr
[i
].name
= Str_dupTSD( traps
[i
].name
) ;
76 sigtype
*getsigs( proclevel level
)
78 for (; level
&& (!level
->sig
); level
=level
->prev
) ;
79 return ((level
) ? (level
->sig
) : (NULL
)) ;
82 trap
*gettraps( const tsd_t
*TSD
, proclevel level
)
88 for (ptr
=level
; ptr
&& ptr
->traps
==NULL
; ptr
=ptr
->prev
) ;
89 if (ptr
==NULL
|| ptr
->traps
==NULL
)
90 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
92 level
->traps
= dupltraps( TSD
, ptr
->traps
) ;
100 int condition_hook( tsd_t
*TSD
, int type
, int errorno
, int suberrorno
, int lineno
, streng
*description
, streng
*condition_description
)
103 sigtype
*sigptr
=NULL
;
105 traps
= gettraps( TSD
, TSD
->currlevel
) ;
106 /* if we dont know what to do, ... or */
107 /* if we don't *really* want to try to recover from these ... */
108 if (traps
==NULL
|| type
== SIGNAL_FATAL
)
111 Free_stringTSD( description
) ;
117 if (TSD
->currentnode
)
118 lineno
= TSD
->currentnode
->lineno
;
123 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
126 if ( traps
[type
].on_off
) /* condition is being trapped */
128 if ((traps
[type
].delayed
) && (traps
[type
].ignored
))
131 Free_stringTSD( description
) ;
135 sigptr
= (sigtype
*)MallocTSD( sizeof( sigtype
)) ;
137 sigptr
->type
= type
;
138 sigptr
->info
= NULL
; /* BUG: I don't really think this is used */
140 sigptr
->descr
= description
;
142 if (condition_description
)
143 sigptr
->descr
= condition_description
;
145 sigptr
->descr
= description
;
147 sigptr
->invoke
= traps
[type
].invoked
;
148 sigptr
->rc
= errorno
;
149 sigptr
->subrc
= suberrorno
;
150 sigptr
->lineno
= lineno
;
152 if ( traps
[type
].invoked
) /* if SIGNAL ON */
154 /* traps[type].on_off = 0 ; */ /* turn trap off */
155 /* traps[type].trapped = 0 ; */ /* unecessary, just to be sure */
156 traps
[type
].delayed
= 0 ; /* ... ditto ... */
157 set_reserved_value( TSD
, POOL0_SIGL
, NULL
, lineno
, VFLAG_NUM
);
158 if (type
== SIGNAL_SYNTAX
) /* special condition */
159 set_reserved_value( TSD
, POOL0_RC
, NULL
, errorno
, VFLAG_NUM
);
161 TSD
->nextsig
= sigptr
;
163 jump_rexx_signal( TSD
);
167 TSD
->nextsig
= sigptr
;
173 Free_stringTSD(description
) ;
175 /* signal is not to be trapped */
176 return (traps
[type
].def_act
) ;
180 int identify_trap( int type
)
184 case X_S_HALT
: return SIGNAL_HALT
;
185 case X_S_SYNTAX
: return SIGNAL_SYNTAX
;
186 case X_S_NOVALUE
: return SIGNAL_NOVALUE
;
187 case X_S_NOTREADY
: return SIGNAL_NOTREADY
;
188 case X_S_ERROR
: return SIGNAL_ERROR
;
189 case X_S_FAILURE
: return SIGNAL_FAILURE
;
190 case X_S_LOSTDIGITS
: return SIGNAL_LOSTDIGITS
;
192 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
193 return SIGNAL_FATAL
;
197 /* the rest should probably also be defined */
198 static const char *signals_names
[] = {
199 "", "SIGHUP", "SIGINT", "", "", "", "", "", "", "",
200 "", "", "", "", "", "SIGTERM", "", "", "", "", "",
201 "SIGBREAK", "", "", "", "", "", "", "", "", "",
205 #if defined (HAVE_SIGACTION) && defined(SA_RESTART) && defined(HAVE__SIGHANDLER_T)
206 /* Most things only works if a signal doesn't break the current system call.
207 * sigaction has such a flag and should always been preferred. It has an
208 * exactlier defined standard.
209 * Defining a "signal()" here also overwrites signal calls in the whole
212 signal_handler
regina_signal(int signum
,__sighandler_t action
)
214 struct sigaction nsig
,osig
;
216 nsig
.sa_handler
= action
;
217 sigemptyset(&nsig
.sa_mask
);
218 nsig
.sa_flags
= SA_RESTART
;
219 if (sigaction(signum
,&nsig
,&osig
) != 0)
221 return(osig
.sa_handler
);
223 #elif defined(__AROS__)
224 signal_handler
regina_signal(int signum
,signal_handler action
)
229 signal_handler
regina_signal(int signum
,signal_handler action
)
231 # if defined(__WINS__) || defined(__EPOC32__)
234 return( signal ( signum
, action
) ) ;
240 * halt_raised is invoked by the interpreter's main loop after detecting a
242 * This routine raises the HALT condition and probably terminates the current
245 void halt_raised( tsd_t
*TSD
)
247 int sig
= TSD
->HaltRaised
;
251 if ( condition_hook( TSD
,
255 lineno_of( TSD
->currentnode
),
256 Str_creTSD( signals_names
[sig
] ),
261 * FIXME: Why do we use vms_killproc instead of using exiterror() ?
265 exiterror( ERR_PROG_INTERRUPT
, 0 );
268 #if !defined(__WINS__) && !defined(__EPOC32__) && !defined(__AROS__)
269 /* Yuk! Some of these should *really* have been volatilized */
270 static void halt_handler( int num
)
274 * Braindamaged Win32 systems raise ^C in a different thread. We need a
275 * synchroneous alert. We just set a global flag in the halt handler and
276 * reset it here doing the proper functionality for the signal. One
277 * thread has to pick the signal during execution in the main loop.
280 regina_signal( num
, halt_handler
);
281 __regina_Win32CtrlCRaised
= SIGINT
;
283 tsd_t
*TSD
= __regina_get_tsd(); /* The TSD must be fetched directly. */
286 if (regina_signal( num
, halt_handler
) == SIG_ERR
)
287 exiterror( ERR_SYSTEM_FAILURE
, 0 );
288 TSD
->HaltRaised
= num
;
293 static void hup_handler( int dummy
)
296 * FGC: FIXME: Doing an exit is too heavy and too early. Maybe, we
297 * should ignore it completely. Every IO request will return EPIPE or
298 * similar, and we can do a graceful shutdown then.
300 exiterror( ERR_PROG_INTERRUPT
, 0 );
306 void signal_setup( const tsd_t
*TSD
)
308 TSD
= TSD
; /* keep compiler happy */
311 * EPOC32 does not have signal()!!
312 * AROS at the moment also lacks signal
314 #if !defined(__WINS__) && !defined(__EPOC32__) && !defined(__AROS__)
315 # if defined(SIGTERM)
316 if (regina_signal( SIGTERM
, halt_handler
) == SIG_ERR
)
317 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
320 if (regina_signal( SIGINT
, halt_handler
) == SIG_ERR
)
321 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
323 # if defined(SIGBREAK)
324 if (regina_signal( SIGBREAK
, halt_handler
) == SIG_ERR
)
325 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
328 if (regina_signal( SIGHUP
, (TSD
->isclient
)?(hup_handler
):(halt_handler
)) == SIG_ERR
)
329 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
334 void set_rexx_halt( tsd_t
*TSD
)
336 TSD
->HaltRaised
= SIGINT
;