=head1 LUAUNPANIC

luaunpanic - lua wrapped into an unpanic library

=head1 DESCRIPTION

This library wraps lua so that lua's default panic behaviour (in other words: end of your application...) never happens.

The lua code base in use here is version B<5.3.4>.

=head2 Why this library

Because playing with C<abort()> try catch in C is not easy, this library hides all the technical difficuly of a correct I<try/catch> pattern in the C language over I<all> lua methods. In addition, for those wanting to catch any lua error without this library, there is a difficulty at the very beginning: setting a try/catch handler can abort without the abort being already set... this library handles also this bootstrap case.

=head2 Wrappers semantics

=over

=item

Any function like C<type lua_xxx(...args...)> has a wrapper like C<short luaunpanic_xxx(type *luaunpanic_result, ...args...)>.

Return code is C<0> if C<luaunpanic_xxx> did panic, C<1> if <luaunpanic_xxx> succeeded. In the later case C<*luaunpanic_result> contains the result.

In other words, non-void native calls such as:

  if (lua_call(xxx)) {
     yyy /* failure */
  } else {
     zzz /* success */
  }

should be translated to:

  if (luaunpanic_call(&luarc, xxx) || luarcrc) {
    yyy /* failure */
  } else {
    zzz /* success */
  }

=item

Any function like C<void lua_xxx(...args...)> has a wrapper like C<short luaunpanic_xxx(...args...)>.

Return code is C<0> if C<luaunpanic_xxx> did panic, C<1> if <luaunpanic_xxx> succeeded.

In other words, void native calls such as:

  lua_call(xxx);

should be translated to:

  if (luaunpanic_call(xxx)) {
    /* failure */
  }

=item

Exceptions are lua calls that will do an abort: if you look to the documentation, despite they have a return code for semantic purpose, they will I<never> return in Lua: they exist only for the purpose of generating an exception. These functions are:

=over

=item C<lua_error>

=item C<luaL_error>

=item C<luaL_argerror>

=back

The corresponding luaunpanic_wrappers will, on the contrary, always return the value 1 to indicate a failure. The argument C<&luarc> itself will I<not> be updated. Therefore the usage for such functions is e.g;:

  if (luaunpanicL_argerror(&luarc, L, arg, extramsg)) {
    /* failure */
  } else {
    /* cannot happen */
  }

and since it is guaranteed that C<rc> is not updated, it is equivalent, but quite false to be writen like in the general case:

  if (luaunpanicL_argerror(&luarc, L, arg, extramsg) || luarc) {
    /* failure */
  } else {
    /* cannot happen */
  }


=back

Lua return code semantic is preserved and native behaviour is preserved:

=over

=item

luaunpanic wrappers always return C<0> in case of success, C<1> in case of failure.

=item

The C<lua_State> pointer returned with the unpanic versions of C<lua_State> creation methods can still be used with I<native> lua methods.

=item

Anything that would abort will not if it is done using a luaunpanic method.

=back

=head1 NOTES

Obviously, this is targetting embedded lua interpreters into third-party libraries: by using luaunpanic, you make sure that your library will never exit because of lua default I<abort()> behaviour.

=head1 SEE ALSO

L<Lua error handing in C|https://www.lua.org/manual/5.3/manual.html#4.6>
