2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)handlecond.c 1.22 04/05/09 Copyright 1985-2004 J. Schilling */
15 * setup/clear a condition handler for a software signal
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License version 2
20 * as published by the Free Software Foundation.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License along with
28 * this program; see the file COPYING. If not, write to the Free Software
29 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 * A procedure frame is marked to have handlers if the
33 * previous freme pointer for this procedure is odd.
34 * The even base value, in this case actually points to a SIGBLK which
35 * holds the saved "real" frame pointer.
36 * The SIGBLK mentioned above may me the start of a chain of SIGBLK's,
37 * containing different handlers.
39 * This will work on processors which support a frame pointer chain
41 * On a processor which doesn't support this I think of a method
42 * where handlecond() has an own chain of frames, holding chains of
44 * In this case, a parameter has to be added to handlecond() and
45 * unhandlecond(). This parameter will be an opaque cookie which is zero
46 * on the first call to handlecond() in a procedure.
47 * A new cookie will be returned by handlecond() which must be used on
48 * each subsequent call to handlecond() and unhandlecond() in the same
51 * Copyright (c) 1985-2004 J. Schilling
62 #if !defined(AV_OFFSET) || !defined(FP_INDIR)
63 # ifdef HAVE_SCANSTACK
64 # undef HAVE_SCANSTACK
71 extern SIGBLK *__roothandle;
72 #endif /* HAVE_SCANSTACK */
74 #define is_even(p) ((((long)(p)) & 1) == 0)
75 #define even(p) (((long)(p)) & ~1L)
76 #if defined(__sun) && defined(__i386)
78 * Solaris x86 has a broken frame.h which defines the frame ptr to int.
80 #define odd(p) (((Intptr_t)(p)) | 1)
82 #define odd(p) (void *)(((Intptr_t)(p)) | 1)
86 #define even(p) (((long)(p)) - 1) /* will this work with 64 bit ?? */
89 EXPORT void starthandlecond __PR((SIGBLK *sp));
93 handlecond(const char *signame,
95 int (*func)(const char *, long, long),
99 handlecond(signame, sp, func, arg1)
106 register SIGBLK *this;
107 register SIGBLK *last = (SIGBLK *)NULL;
108 #ifdef HAVE_SCANSTACK
109 struct frame *fp = (struct frame *)NULL;
113 if (signame == NULL || (slen = strlen(signame)) == 0) {
114 raisecond("handle_bad_name", (long)signame);
118 #ifdef HAVE_SCANSTACK
119 fp = (struct frame *)getfp();
120 fp = (struct frame *)fp->fr_savfp; /* point to frame of caller */
121 if (is_even(fp->fr_savfp)) {
123 * Easy case: no handlers yet
124 * save real framepointer in sp->sb_savfp
126 sp->sb_savfp = (long **)fp->fr_savfp;
127 this = (SIGBLK *)NULL;
129 this = (SIGBLK *)even(fp->fr_savfp);
135 for (; this; this = this->sb_signext) {
138 * If a SIGBLK is reused, the name must not change.
140 if (this->sb_signame != NULL &&
141 !streql(this->sb_signame, signame)) {
142 raisecond("handle_reused_block", (long)signame);
145 sp->sb_sigfun = func;
146 sp->sb_sigarg = arg1;
149 if (this->sb_signame != NULL &&
150 streql(this->sb_signame, signame)) {
151 if (last == (SIGBLK *)NULL) {
153 * 'this' is the first entry in chain
155 if (this->sb_signext == (SIGBLK *)NULL) {
157 * only 'this' entry is in chain, copy
158 * saved real frame pointer into new sp
160 sp->sb_savfp = this->sb_savfp;
162 #ifdef HAVE_SCANSTACK
164 * make second entry first link in chain
166 this->sb_signext->sb_savfp =
168 fp->fr_savfp = odd(this->sb_signext);
171 * Cannot happen if scanning the stack
174 raisecond("handle_is_empty", (long)0);
178 continue; /* don't trash 'last' ptr */
180 last->sb_signext = this->sb_signext;
185 sp->sb_signext = (SIGBLK *)NULL;
186 sp->sb_signame = signame;
187 sp->sb_siglen = slen;
188 sp->sb_sigfun = func;
189 sp->sb_sigarg = arg1;
191 * If there is a chain append to end of the chain, else make it first
194 last->sb_signext = sp;
195 #ifdef HAVE_SCANSTACK
197 fp->fr_savfp = odd(sp);
200 * Cannot happen if scanning the stack is not possible...
203 raisecond("handle_is_empty", (long)0);
213 #ifdef HAVE_SCANSTACK
214 struct frame *fp = NULL;
217 * As the SCO OpenServer C-Compiler has a bug that may cause
218 * the first function call to getfp() been done before the
219 * new stack frame is created, we call getfp() twice.
224 sp->sb_signext = (SIGBLK *)NULL;
225 sp->sb_signame = NULL;
227 sp->sb_sigfun = (handlefunc_t)NULL;
230 #ifdef HAVE_SCANSTACK
231 fp = (struct frame *)getfp();
232 fp = (struct frame *)fp->fr_savfp; /* point to frame of caller */
234 if (is_even(fp->fr_savfp)) {
236 * Easy case: no handlers yet
237 * save real framepointer in sp
239 sp->sb_savfp = (long **)fp->fr_savfp;
240 fp->fr_savfp = odd(sp);
242 raisecond("handle_not_empty", (long)0);
246 sp->sb_savfp = (long **)__roothandle;
255 #ifdef HAVE_SCANSTACK
256 register struct frame *fp;
257 register SIGBLK *sps;
260 * As the SCO OpenServer C-Compiler has a bug that may cause
261 * the first function call to getfp() been done before the
262 * new stack frame is created, we call getfp() twice.
265 fp = (struct frame *)getfp();
266 fp = (struct frame *)fp->fr_savfp; /* point to frame of caller */
268 if (!is_even(fp->fr_savfp)) { /* if handlers */
269 sps = (SIGBLK *)even(fp->fr_savfp); /* point to SIGBLK */
270 /* real framepointer */
271 #if defined(__sun) && defined(__i386)
272 fp->fr_savfp = (intptr_t)sps->sb_savfp;
274 fp->fr_savfp = (struct frame *)sps->sb_savfp;
278 if (__roothandle == NULL) {
279 raisecond("handle_is_empty", (long)0);
283 * Pop top level handler chain.
285 __roothandle = (SIGBLK *)__roothandle->sb_savfp;