2 static char *RCSid
= "$Id$";
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.
31 # define SIG_ERR BADSIG
35 /* at least dolphin does not have a properly ANSI C set of include files */
37 # define SIG_ERR ((void(*)())(-1))
40 const char *signalnames
[] = {
50 void mark_signals( const tsd_t
*TSD
)
54 markmemory( TSD
->nextsig
, TRC_MATH
) ;
55 if (TSD
->nextsig
->descr
)
56 markmemory( TSD
->nextsig
->descr
, TRC_MATH
) ;
62 static trap
*dupltraps( const tsd_t
*TSD
, const trap
*traps
)
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
++ )
72 ptr
[i
].name
= Str_dupTSD( traps
[i
].name
) ;
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
)
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
) ;
103 int condition_hook( tsd_t
*TSD
, int type
, int errorno
, int suberrorno
, int lineno
, streng
*description
, streng
*condition_description
)
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
)
114 Free_stringTSD( description
) ;
120 if (TSD
->currentnode
)
121 lineno
= TSD
->currentnode
->lineno
;
126 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
129 if ( traps
[type
].on_off
) /* condition is being trapped */
131 if ((traps
[type
].delayed
) && (traps
[type
].ignored
))
134 Free_stringTSD( description
) ;
138 sigptr
= MallocTSD( sizeof( sigtype
)) ;
140 sigptr
->type
= type
;
141 sigptr
->info
= NULL
; /* BUG: I don't really think this is used */
143 sigptr
->descr
= description
;
145 if (condition_description
)
146 sigptr
->descr
= condition_description
;
148 sigptr
->descr
= description
;
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 ) ;
175 TSD
->nextsig
= sigptr
;
181 Free_stringTSD(description
) ;
183 /* signal is not to be trapped */
184 return (traps
[type
].def_act
) ;
188 int identify_trap( int 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 "", "", "", "", "", "", "", "", "", "",
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
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)
228 return(osig
.sa_handler
);
230 #elif defined(__AROS__)
231 signal_handler
regina_signal(int signum
,signal_handler action
)
236 signal_handler
regina_signal(int signum
,signal_handler action
)
238 # if defined(__WINS__) || defined(__EPOC32__)
241 return( signal ( signum
, action
) ) ;
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. */
252 vms_killproc( TSD
) ;
255 if (regina_signal( num
, halt_handler
) == SIG_ERR
)
256 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
258 if (!condition_hook(TSD
,
262 lineno_of(TSD
->currentnode
),
263 Str_creTSD(signals_names
[num
]),
266 exiterror( ERR_PROG_INTERRUPT
, 0 ) ;
271 #if !defined(__WINS__) && !defined(__EPOC32__) && !defined(__AROS__)
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 ) ;
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 ) ;
303 if (regina_signal( SIGINT
, halt_handler
) == SIG_ERR
)
304 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
307 if (regina_signal( SIGHUP
, (TSD
->isclient
)?(hup_handler
):(halt_handler
)) == SIG_ERR
)
308 exiterror( ERR_SYSTEM_FAILURE
, 0 ) ;
313 void set_rexx_halt( void )
315 halt_handler( SIGINT
);