Article View: comp.sys.atari.st
Article #40028Re: Changing Rez: What we _really_ want to know
From: Edgar Roeder
Date: Thu, 04 Jan 1990 14:50
Date: Thu, 04 Jan 1990 14:50
320 lines
10942 bytes
10942 bytes
In article <8912301917.AA19200@TIS.COM>, dmb@TIS.COM (David M. Baggett) writes:
> P.S.> Could some kind soul please repost the "all about terminate handlers"
> article here? Thanks.
Sorry, i don't have this document, but i have prepared another one. The file is
in Info-format, suitable for reading with GNU-emacs, but it should be readable
as text too.
Hope this helps!
- Edgar
---------------------- cut here ------------------------
Info file: etv_term, -*-Text-*-
produced by texinfo-format-buffer
from file: etv_term.txi
This file documents the TOS terminate handler etv_term and what you can
do with it.
File: etv_term Node: Intro, Prev: Concept Index, Up: Top, Next: Top
The Terminate handler
*********************
Some people on the net asked for documentation about the terminate
vector. Here is what i have collected over the past few years. Some of
the details required a lot of experimenting, but all the presented
solutions work with all TOS versions (although undocumented features are
used).
- Edgar
File: etv_term Node: Top, Prev: Intro, Up: (dir), Next: Actions
When is the Terminate Handler called ?
======================================
The logical vector #0x102 "etv_term" at address 0x400 is called by
`Pterm()' before a program is terminated. This can have several
causes. Either
1. an explicit call to
* the gemdos functions `Pterm0()', `Pterm()' or `Ptermres()' or
* `trap #2' with argument 0 in register D0 or
2. another program (a resident monitor like templmon or a shell or an
accessory) directly calls one of the above functions or
3. `Pterm()' (in early TOS versions `Pterm0()') is called
from one of the exception routines (after some bombs or mushrooms
have been drawn) or
4. `Pterm(-32)' is called when ^C is pressed during screen-I/O
Since in cases 2--4 above the user program normally has not
initiated the program termination, the terminate vector is the last
(and only) chance to do some cleanup work before execution is
finished.
* Menu:
* Actions:: What can a terminate handler do
* Call:: How the handler is called
* Installation:: How to install a handler
* Concept Index::
File: etv_term Node: Actions, Prev: Top, Up: Top, Next: Call
What you want to do in the Handler
==================================
Before Program Termination (cases 2 + 3)
----------------------------------------
* give some good-bye message to the user
* flush buffered output streams (files are closed after the call to
etv_term by TOS)
* deinstall modified system vectors (*Note Installation::)
* modify the return code to signal an error condition to the calling
program (*Note Return Code::)
* prevent termination (probably after asking the user) and go to a
safe place to restart the program (for example the prompt in an
interpreter) or enter a debugger (in case 3 above)
If ^C is pressed (case 4)
-------------------------
* ignore it completely (*Note Ignore ^C::)
* ask the user wether to ignore it or to terminate the program
* go to a safe place and cancel the current action of the program
So what we need to know about terminate handlers are the
restrictions, which TOS-functions can be called, how we can access
the parameter to `Pterm' and how we can resume execution at
the place where ^C was pressed.
* Menu:
* Restrictions:: What can be called from a handler
* Return Code:: access the program's return code
* Ignore ^C:: avoid program termination
File: etv_term Node: Call, Prev: Actions, Up: Top, Next: Installation
How is the handler called ?
===========================
The etv_term vector is called via `jsr' in supervisor mode. The
calling routine (`Pterm()') was called in C with one parameter (the
return code for the program) on the stack (*Note Return Code::).
File: etv_term Node: Installation, Prev: Call, Up: Top, Next: Concept Index
How can i install my own routine ?
==================================
If you are in supervisor mode (after a call to `Super()' from user
mode with a parameter != 1L or in a routine executed by
`Supexec()') you can directly set the variable at `0x400' to
the address of your routine:
*((void (**)()) 0x400) = own_routine;
More portable and the recommended way is a call to the Bios function #5
(`Setexc()'):
old_routine = (void (*)()) Setexc(0x102, own_routine);
The terminate handler itself has no parameter and no return value:
void own_routine(void);
File: etv_term Node: Restrictions, Prev: Actions, Up: Actions, Next: Return Code
What can be done in a terminate handler ?
=========================================
This depends on what should happen after the handler has finished. We
have three cases:
1. cleanup and terminate execution of the program
2. resume execution at some safe point (eg. top level of program)
3. ignore the termination request (*Note Ignore ^C::)
In case 1 we should restore the original terminate handler before we
leave our program. This can be done like the installation with
Setexc(0x102, old_routine);
If our terminate handler is not removed before other programs are
started, the handler will also be called when these other programs are
about to be terminated. In a shell this can be used to control the
behavior of other programs with respect to ^C.
In case 2 we should return to user mode since this is the normal mode of
execution for user programs. This can be done with a call to the gemdos
function `Super()' after calling `longjmp()'. A sample code
fragment could be this:
#include <setjmp.h>
jmp_buf global_exit;
long stackpointer;
void
terminate_handler(void)
{
...
longjmp(global_exit,1);
}
toplevel_routine()
{
int ret;
...
stackpointer = Super(0L);
ret = setjmp(global_exit);
Super(stackpointer);
switch(ret) {
...
}
...
}
In the cases 1 and 2 you may call any routines (including gemdos, bios,
xbios, aes and vdi) since we leave the normal flow of execution anyway
and so no information needs to be preserved. But you have to be
careful, if `Pterm()' was called as the result of a processor
exception (eg. bus error): probably some internal data structures are
in an unstable state.
In case 3 it is important to know where the `Pterm()'-call
happened. As a thumb rule you can call xbios or bios safely from any
place. But if you have switched to user mode (and want to decide
between cases 1, 2 or 3 later), you cannot use the old userstack. Some
people might prefer using the user stack in supervisor mode too. Also
gemdos - if called from user mode - uses a part of the user stack below
the user stack pointer (~40 bytes) to save some registers. And this is
just the case if `Pterm()' was called via `trap #1'.
File: etv_term Node: Return Code, Prev: Restrictions, Up: Actions, Next: Ignore ^C
How can the argument to `Pterm()' be accessed ?
===============================================
`Pterm()' is called from C. The argument to `Pterm()' can
thus be found on the stack. Since it is also programmed in C we can
access the parameter with the help of processor register A6 the
frame pointer in C. `Pterm()' calls (*etv_term)() directly. At
the entry of our routine A6 still points to the right frame. So
we can get the return value for the program (the parameter of
`Pterm()') simply as the word 8 bytes above the frame pointer (as
usual in C).
The value of the return code can be read and compared against -32 to
decide wether ^C was pressed (or `Pterm(-32)' called). So we can
distinguish the several causes for a `Pterm()'-call. We can also
change this value on the stack to change our program's return value.
If you are using KAOS-TOS (some patches to Blitter-TOS from the german
magazine c't - don't ask me about it since TOS 1.4 is certainly better)
the return value if ^C was pressed is different. Here it is -68 if ^C
was pressed and -69 if an exception occured.
File: etv_term Node: Ignore ^C, Prev: Return Code, Up: Actions
How can ^C be ignored ?
=======================
Several solutions exist for this problem. One is to use only functions
ignoring ^C for screen-I/O (`Crawio()', `Crawcin()' or bios
functions).
But you can also use the terminate-vector for this task. TOS was
programmed in C and the compiler did not know that `Pterm()' is not
supposed to return to the calling routine. Now if `Pterm()'
returns no surprising effects are observed and the execution goes on as
if ^C was not pressed. But remember that this is not guaranteed to work
to all eternity (but it works from TOS 1.0 - 1.4).
To ignore ^C all you have to do in the terminate handler is to check for
the return value -32 and before the rts instruction do an extra
`unlk a6' to pop the frame of the C-function `Pterm()'. The
program will continue as if ^C was never touched.
File: etv_term Node: Concept Index, Prev: Installation, Up: Top, Next: Intro
Concept Index
*************
* Menu:
* access return code: Return Code.
* actions: Actions.
* call: Call.
* calling conditions: Top.
* etv_term: Top.
* get address of old handler: Installation.
* ignore ^C: Ignore ^C.
* install a new handler: Installation.
* installation: Installation.
* restrictions: Restrictions.
* resume execution: Ignore ^C.
* return code: Return Code.
* stackpointer: Restrictions.
* switch to user mode: Restrictions.
* terminate handler: Intro.
* terminate vector: Top.
* test return code: Return Code.
Tag table:
Node: Intro184
Node: Top619
Node: Actions1810
Node: Call3154
Node: Installation3484
Node: Restrictions4139
Node: Return Code6592
Node: Ignore ^C7771
Node: Concept Index8674
End tag table
--
Mail: Edgar R\"oder E-Mail: roeder@cs.uni-sb.de
Liesbet-Dill-Stra\ss e 3
D-6602 Dudweiler -o- -o-
W-Germany ^
Phone: 06897/74643 '---'
Technical Details
Message-ID:
<2009@sbsvax.UUCP>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!mcsun!unido!sbsvax!roederReferences:
<8912301917.AA19200@TIS.COM>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!mcsun!unido!sbsvax!roeder From: roeder@sbsvax.UUCP (Edgar Roeder) Newsgroups: comp.sys.atari.st Subject: Re: Changing Rez: What we _really_ want to know Summary: All about terminate handlers Message-ID: <2009@sbsvax.UUCP> Date: 4 Jan 90 14:50:38 GMT References: <8912301917.AA19200@TIS.COM> Organization: Universitaet des Saarlandes, Saarbruecken, W-Germany Lines: 320