The <error.h> header file
This header file contains the following functions:
ER_catch ER_throwVar ER_success ERD_dialog
ERD_process find_error_message
the following language extensions (implemented as macros):
ENDTRY errCode ONERR PASS
TRY
and the following predefined types:
Bool ERROR_FRAME
Functions
Catchs an error.
ER_catch setups an error handler (see also TRY,
ONERR and ENDTRY). It saves the task state in
ErrorFrame, which is usually a buffer
of type ERROR_FRAME, and returns 0. The state consists of the values of A2-A7,
D3-D7, and PC. It also records a pointer to the previously saved state, which
makes it a linked list/stack, and yet another two system pointers.
If ER_throwVar is called later on (note that some TIOS routines may perform
ER_throwVar in a case of error), it simulates a return from the
previously called ER_catch, and the error code passed into ER_throwVar
will become the result of ER_catch. The processor must be in User mode for this
to work properly.
NOTE: Usually you should not call
this function explicitely. Use TRY macro instead.
Throws an error.
ER_throwVar restores the state previously saved by ER_catch.
It then returns in such a way that ER_catch appears to have
returned with the value err_no (see also PASS).
See the TI-Basic manual for a meaning of the various error codes. ER_throwVar
should not be called with a value 0 as err_no. Think of ER_throwVar as a long
jump rather than a subroutine call. Execution does not return from the ER_throwVar call.
NOTE: It is not a good idea to use ER_throwVar to bail out to the TIOS from arbitrary
place. ER_throwVar will return you to the system as expected, but your program will remain
locked, and will throw "Invalid program reference" error on subsequent calls...
Pops the state from the error stack
ER_success pops the state previously saved by ER_catch off the stack,
i.e. removes the error frame from the linked list. You usually will not call this function
explicitely: the macro ONERR will do this for you.
Gives a TI-Basic error message string.
find_error_message returns a pointer to the text of the TI-Basic error message string
with code err_no. See TI-Basic manual for the list of various error codes. If
err_no is not a valid error code, the routine returns a pointer to the string
"Unknown ERROR code".
Displays an error dialog box.
ERD_dialog displays an error dialog box with a message corresponding to the
error code err_no. See the TI manual for a meaning of the various
error codes. ERD_dialog returns KEY_ENTER or
KEY_ESC, depending of whether the user
exits the dialog box by pressing ENTER or ESC key. This routine may cause
heap compression.
prog_flag is a flag which may be FALSE or
TRUE. Normally, it need to be FALSE,
but when it is TRUE, in addition to the standard button
whith message "Esc=CANCEL", another button with message "Enter=GOTO" will be
added in the error dialog box. This is mostly useless, but
error dialog boxes have this option (TIOS uses this when you break a BASIC program).
Note, however, that pressing Enter will not perform the actual transfer to the program
editor.
Process an error.
ERD_process processes the error with error code err_no by calling
ERD_dialog appropriately. Button "Enter=GOTO" will
be displayed only if the routine concludes from some system flags that the
routine is called from the TI-Basic interpreter (which will not be the case
if you called it from C or ASM program). Then, ERD_process responds by
starting appropriate application (for example text editor if the TI-Basic
interpretter was active and if the user pressed button "Enter=GOTO").
Principally, there is no difference between ERD_process and
ERD_dialog, except in event-driven applications
(see events.h header file).
Language extensions
TRY, ONERR, ENDTRY and PASS
are macros which extends the C language to implement the error handling mechanism which is
almost identical like in TI-Basic.
TRY begins the protected block. It is a macro which is implemented using
ER_catch function. If an error occurs in the protected block, program
execution transfers to the block after ONERR statement, else this
block will not be executed. In each case, the execution continues normally after
ENDTRY statement. This is ilustrated
in the following example:
TRY
// protected code
ONERR
// error handler
if (errCode == some_specific_code)
PASS; // pass on any unhandled errors to a higher level
ENDTRY
Variable errCode is automatically created in the error handler, and
it contains the error number to allow the program to check what caused the error. This variable
will be destroyed after ENDTRY statement.
It is important to say that you must not exit the protected block using
goto or return statements, else the error frame will not
be removed, so the further behaviour of the program will be unpredictable. If you really
want to exit from the protected block before its natural end (i.e. before ONERR
statement), call ER_success explicitely to remove the error frame
before exiting, i.e. do something like
TRY
...
if (I_really_must_exit_from_here)
{
ER_success ();
return;
}
...
ONERR
...
ENDTRY
There is also another possible caveat related to error handling. The TRY macro saves many of
the CPU registers on its execution context stack. Consequently, when an error is thrown, all
variables which reside in CPU registers are reset to their contents before the TRY macro was
called. This is only a problem with auto variables — global and static variables are never kept
in CPU registers. If code in an ONERR block needs the value of a variable
set in the TRY block, the code must arrange to make sure the C code optimizer does not put that
variable in a CPU register. This can be accomplished by declaring such variables to be volatile.
So, remember this rule: Auto variables changed in a TRY block must be declared volatile if they
are referenced in an ONERR block!!!
If you want to "protect" whole program, maybe the best method is to do something like
void _main (void)
{
TRY
main_prog ()
ONERR
// Do some error hanling, for example call simply ERD_process (errCode);
ENDTRY
}
void main_prog (void)
{
// Put your real code here
}
Macro ONERR ends the protected block and begins the error handler (see
TRY for more info). Variable errCode is
automatically created in the error handler, and it contains the error number to allow
the program to check what caused the error. This variable
will be destroyed after ENDTRY statement.
NOTE: Macro ONERR uses ER_success function to end the protected
block.
Macro ENDTRY terminates TRY ... ONERR ... ENDTRY structure
(see TRY for more info).
Macro PASS pass on any unhandled errors to a higher level of error handler (see
TRY for more info). In fact, it exectutes ER_throwVar
with errCode as an argument.
errCode is an automatic (local) variable which is automatically created in the error handler, and it
contains the error number to allow the program to check what caused the error. This variable
is automatically destroyed after ENDTRY statement, i.e. after execution
of the error handler. Variable errCode, because it is local to the ONERR
block, cannot be referenced outside the ONERR block.
Constants and predefined types
Bool is enumerated type for describing true or false values. It is defined as
enum Bool {FALSE, TRUE};
ERROR_FRAME is a type designed for capturing a task state needed for
catching errors using ER_catch command.
It is defined here as
typedef struct ErrorFrameStruct
{
unsigned long A2, A3, A4, A5, A6, A7;
unsigned long D3, D4, D5, D6, D7;
unsigned long NG_Control;
char *RetIndex;
unsigned long PC;
struct ErrorFrameStruct *Link;
} ERROR_FRAME[1];