It lacks 4th method that I find the best: with long jumps. I mean for example:
jmp_buf errbuf;
int result;
if( !( result = set_jmp ) )
{
/* Code to do on fail. Result may be some error code */
}
else
{
someaction( par1, par2, ..., errbuf);
anotheraction( par1, par2, ..., errbuf);
/* Etc. */
}
errbuf might be global if you prefer, but I'd rather avoid them. When something is wrong called function calls longjmp(errbuf, errorcode).