[Main]
Name=TRY
Type=Language Extension
Header Files=error.h
Real Definition=#define TRY { ERROR_FRAME __errFrame; unsigned short errCode; errCode = ER_catch (__errFrame); if (!errCode) {

[Description]
Starts a protected block of code.

[Explanation]
TRY,
<A HREF="$$LINK(error.h/ONERR)">ONERR</A>,
<A HREF="$$LINK(error.h/ENDTRY)">ENDTRY</A>,
<A HREF="$$LINK(error.h/FINALLY)">FINALLY</A>,
<A HREF="$$LINK(error.h/ENDFINAL)">ENDFINAL</A>, and
<A HREF="$$LINK(error.h/PASS)">PASS</A>
are macros which extend the C language to implement an error handling mechanism which is
almost identical to the commonly-used exception handling as well as error handling in TI-Basic.
<BR><BR>
TRY begins the protected block. It is a macro which is implemented using the
<A HREF="$$LINK(error.h/ER_catch)">ER_catch</A> function. If an error occurs in the protected block, program
execution transfers to the block after the <A HREF="$$LINK(error.h/ONERR)">ONERR</A> or
<A HREF="$$LINK(error.h/FINALLY)">FINALLY</A> statement.
<BR><BR>
However, <A HREF="$$LINK(error.h/ONERR)">ONERR</A> and <A HREF="$$LINK(error.h/FINALLY)">FINALLY</A>
are entirely different. The <A HREF="$$LINK(error.h/ONERR)">ONERR</A> block will not
be executed if there was no error, and it is assumed to either handle the
error or call <A HREF="$$LINK(error.h/PASS)">PASS</A>. The error is cleared, so if
<A HREF="$$LINK(error.h/PASS)">PASS</A> is not called, the execution continues
normally after the <A HREF="$$LINK(error.h/ENDTRY)">ENDTRY</A> statement.
<BR><BR>
<A HREF="$$LINK(error.h/FINALLY)">FINALLY</A>, on the other hand, is not implemented
to handle errors, but instead to create a block of code which will always be
executed, regardless of whether there was an error or not. It does not clear
the error (or more precisely, <A HREF="$$LINK(error.h/ENDFINAL)">ENDFINAL</A> throws
it again). This can be used in a function which allocates memory, destroys
the contents of the screen, or does something else which always needs cleaning up.
If the function throws an error in a protected block, the memory should
always be freed again, the screen should be restored, etc. But the error
should not be handled at the same time; instead, it must be handled on a
higher level (often even in the calling function).
<BR><BR>
The usage of <A HREF="$$LINK(error.h/ONERR)">ONERR</A> is illustrated in the following example:
<PRE>TRY
  // <I>&lt;protected code&gt;</I>
ONERR
  if (errCode == <I>some_specific_code</I>)
    // <I>&lt;error handler&gt;</I>
  else
    // <I>pass on any unhandled errors to a higher level</I>
    PASS;
ENDTRY
</PRE>
The usage of <A HREF="$$LINK(error.h/FINALLY)">FINALLY</A> is illustrated in the following example:
<PRE>TRY
  ...
  // <I>&lt;allocate memory&gt;</I>
  TRY
    // <I>&lt;protected code&gt;</I>
  FINALLY
    // <I>&lt;free the allocated memory&gt;</I>
  ENDFINAL
  ...
ONERR
  // <I>&lt;error handler&gt;</I>
ENDTRY
</PRE>
The variable <A HREF="$$LINK(error.h/errCode)">errCode</A> 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 the <A HREF="$$LINK(error.h/ENDTRY)">ENDTRY</A>/<A HREF="$$LINK(error.h/ENDFINAL)">ENDFINAL</A> statement.
<BR><BR>
It is important to say that you must not exit the protected block using
<A HREF="$$INFOLINK(keywords/goto)">goto</A> or <A HREF="$$INFOLINK(keywords/return)">return</A> statements, else the error frame will not
be removed, so the further behavior of the program will be unpredictable.
If you really want to exit from the protected block before its natural end
(i.e. before the <A HREF="$$LINK(error.h/ONERR)">ONERR</A> or <A HREF="$$LINK(error.h/FINALLY)">FINALLY</A> statement),
call <A HREF="$$LINK(error.h/ER_success)">ER_success</A> explicitely to remove the error frame
before exiting, i.e. do something like
<PRE>TRY
  ...
  if (<I>I_really_must_exit_from_here</I>)
  {
    ER_success ();
    return;
  }
  ...
ONERR
  ...
ENDTRY
</PRE>
But in general this is a very bad practice and should be avoided even if it
requires some extra code. For example, you can rewrite the code like this:
<PRE>TRY
  ...
  if (!<I>I_really_must_exit_from_here</I>)
  {
    ...
  }
ONERR
  ...
ENDTRY
if (<I>I_really_must_exit_from_here</I>)
  return;
</PRE>
There is also another possible caveat related to error handling. The TRY macro (or
<A HREF="$$LINK(error.h/ER_catch)">ER_catch</A>, more precisely) saves many of
the registers on its execution context stack, since <A HREF="$$LINK(error.h/ER_catch)">ER_catch</A> needs to
simulate a return identical to the return of any normal function. Consequently, when an error is thrown, all
variables which reside in registers are reset to their contents before the TRY macro was
called. If code in an <A HREF="$$LINK(error.h/ONERR)">ONERR</A> or <A HREF="$$LINK(error.h/FINALLY)">FINALLY</A>
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 register. This can be
accomplished by declaring such variables to be <A HREF="$$INFOLINK(keywords/volatile)">volatile</A>.
So, remember this rule: Variables changed in a TRY block must be declared volatile if they
are referenced in an <A HREF="$$LINK(error.h/ONERR)">ONERR</A> or <A HREF="$$LINK(error.h/FINALLY)">FINALLY</A> block!
<BR><BR>
If you want to protect the whole program, passing all unhandled errors to the operating system,
you can define <CODE>ENABLE_ERROR_RETURN</CODE> instead of using a
TRY...<A HREF="$$LINK(error.h/ONERR)">ONERR</A>...<A HREF="$$LINK(error.h/ENDTRY)">ENDTRY</A> block.
See the section <A HREF="$$INFOLINK(htretval/reterr)">Returning Errors</A>
for more information.

[References]
Out=error.h/ER_catch, error.h/errCode
