#ifndef _ERR_HANDLING_H_
#define _ERR_HANDLING_H_

#include <stdio.h>
#include <sys/errno.h>

/* ErrHDL Error handling utilities
   -------------------------------
   Makes code more readable by hiding annoying error condition checks.

Macros and routines:

  Spelling in uppercase indicates, that it the program flow
  may be modified (jump to OnError label or program exit).


  ERR_x

    Usage                        Error condition     Error message taken from
    -----------------------------------------------------------------------------------------
    ERR_SI(res=routine1(...))    res<0               errno
    ERR_SP(ptr=routine2(...))    ptr==NULL           errno
    ERR_I(res=routine3(...))     res<0               stored by routine3 using errhdl mechanism
    ERR_P(ptr=routine4(...))     ptr==NULL           stored by routine4 using errhdl mechanism

    The result assignment "res=" or "ptr=" is optional.

    Description:
    The routine routineX is called.
    If the result indicates an error, the source text  is saved and the
    program continues at the OnError label.
    The error message and the source code of the calling instructions is
    saved for a later call to ErrShow or ErrExit.

  ERR_EXIT("program_name")

    Show error and exit program.

  ERR_MSG("message")

    Signals an error condition. If "message" is replaced by a variable,
    take care that it is not modified until ErrShow is called.

  ERR_COD(cod)

    Signals an error condition as code from errno.h

  ErrShow("program_name")

    Show actual error message with traceback information to stdout
    or a file fil

Global Variables (read only)

  int ErrCode

    actual error message code
    = errno for system errors or
    = -1 for custom errors signaled by ERRMSG

  char *ErrMessage

    actual error message
*/

#define ERR_SI(R) { if(0>(R)) { ErrTxt(#R,1); goto OnError; }; }
#define ERR_SP(R) { if(NULL==(R)) { ErrTxt(#R,1); goto OnError; }; }
#define ERR_I(R) { if(0>(R)) { ErrTxt(#R,0); goto OnError; }; }
#define ERR_P(R) { if(NULL==(R)) { ErrTxt(#R,0); goto OnError; }; }
#define ERR_MSG(R) { ErrMsg(R); goto OnError; }
#define ERR_COD(R) { ErrCod(R); goto OnError; }

void ErrTxt(char *text, int systemError);
void ErrMsg(char *msg);
void ErrCod(int code);
void ErrShow(char *text); /* write out error message with stack info */
void ErrShort(char *msg); /* write out short error message */
void ERR_EXIT(char *text);
void ErrSetOutRtn(void (*rtn)(void *,char *), void *arg);
void ErrSetOutFile(FILE *file);

extern int ErrCode;
extern char *ErrMessage;

#endif /* _ERR_HANDLING_H_ */
