text: /*
   * %CopyrightBegin%
   *
   * Copyright Ericsson AB 1996-2016. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   * %CopyrightEnd%
   */
  
  #ifndef __ERROR_H__
  #define __ERROR_H__
  
  #include "code_ix.h"
  
  /*
   * There are three primary exception classes:
   *
   *	- exit			Process termination - not an error.
   *	- error			Error (adds stacktrace; will be logged).
   *	- thrown		Nonlocal return (turns into a 'nocatch'
   *				error if not caught by the process).
   *
   * In addition, we define a number of exit codes as a convenient
   * short-hand: instead of building the error descriptor term at the time
   * the exception is raised, it is built as necessary when the exception
   * is handled. Examples are EXC_NORMAL, EXC_BADARG, EXC_BADARITH, etc.
   * Some of these have convenient aliases, like BADARG and BADARITH.
   */
  
  /*
   * Exception class tags (indices into the 'exception_tag' array)
   */
  #define EXTAG_OFFSET	0
  #define EXTAG_BITS	2
  
  #define EXTAG_ERROR	0
  #define EXTAG_EXIT	1
  #define EXTAG_THROWN	2
  
  #define NUMBER_EXC_TAGS 3	/* The number of exception class tags */
  
  /*
   * Index to the 'exception class tag' table.
   */
  #define EXC_CLASSBITS	((1<<EXTAG_BITS)-1)
  #define GET_EXC_CLASS(x) ((x) & EXC_CLASSBITS)
  
  /*
   * Exit code flags
   *
   * These flags make is easier and quicker to decide what to do with the
   * exception in the early stages, before a handler is found, and also
   * maintains some separation between the class tag and the actions.
   */
  #define EXF_OFFSET	EXTAG_BITS
  #define EXF_BITS	7
  
  #define EXF_PANIC         (1<<(0+EXF_OFFSET)) /* ignore catches */
  #define EXF_THROWN        (1<<(1+EXF_OFFSET)) /* nonlocal return */
  #define EXF_LOG           (1<<(2+EXF_OFFSET)) /* write to logger on termination */
  #define EXF_NATIVE        (1<<(3+EXF_OFFSET)) /* occurred in native code */
  #define EXF_SAVETRACE     (1<<(4+EXF_OFFSET)) /* save stack trace in internal form */
  #define EXF_ARGLIST       (1<<(5+EXF_OFFSET)) /* has arglist for top of trace */
  #define EXF_RESTORE_NFUNC (1<<(6+EXF_OFFSET)) /* restore original bif/nif */
  
  #define EXC_FLAGBITS	(((1<<(EXF_BITS+EXF_OFFSET))-1) \
  			 & ~((1<<(EXF_OFFSET))-1))
  
  /*
   * The primary fields of an exception code
   */
  #define EXF_PRIMARY	(EXF_PANIC | EXF_THROWN | EXF_LOG | EXF_NATIVE)
  #define PRIMARY_EXCEPTION(x) ((x) & (EXF_PRIMARY | EXC_CLASSBITS))
  #define NATIVE_EXCEPTION(x) ((x) | EXF_NATIVE)
  
  /*
   * Error code used for indexing into
   * the short-hand error descriptor table.
   */
  #define EXC_OFFSET	(EXF_OFFSET+EXF_BITS)
  #define EXC_BITS	5
  
  #define EXC_INDEXBITS	(((1<<(EXC_BITS+EXC_OFFSET))-1) \
  			 & ~((1<<(EXC_OFFSET))-1))
  
  #define GET_EXC_INDEX(x) (((x) & EXC_INDEXBITS) >> EXC_OFFSET)
  
  /*
   * Exit codes used for raising a fresh exception. The primary exceptions
   * share index 0 in the descriptor table. EXC_NULL signals that no
   * exception has occurred. The primary exit codes EXC_EXIT, EXC_ERROR
   * and EXC_THROWN are the basis for all other exit codes, and must
   * always have the EXF_SAVETRACE flag set so that a trace is saved
   * whenever a new exception occurs; the flag is then cleared.
   */
  #define EXC_NULL 0			/* Initial value for p->freason */
  #define EXC_PRIMARY (0 | EXF_SAVETRACE)
  #define EXC_ERROR  (EXC_PRIMARY | EXTAG_ERROR | EXF_LOG)
  					/* Generic error (exit term
  					 * in p->fvalue) */
  #define EXC_EXIT   (EXC_PRIMARY | EXTAG_EXIT)
  					/* Generic exit (exit term
  					 * in p->fvalue) */
  #define EXC_THROWN (EXC_PRIMARY | EXTAG_THROWN | EXF_THROWN)
  					/* Generic nonlocal return
  					 * (thrown term in p->fvalue) */
  
  #define EXC_ERROR_2 (EXC_ERROR | EXF_ARGLIST)
  					/* Error with given arglist term
  					 * (exit reason in p->fvalue) */
  
  #define EXC_NORMAL		((1 << EXC_OFFSET) | EXC_EXIT)
  					/* Normal exit (reason 'normal') */
  #define EXC_INTERNAL_ERROR	((2 << EXC_OFFSET) | EXC_ERROR | EXF_PANIC)
  					/* Things that shouldn't happen */
  #define EXC_BADARG		((3 << EXC_OFFSET) | EXC_ERROR)
  					/* Bad argument to a BIF */
  #define EXC_BADARITH		((4 << EXC_OFFSET) | EXC_ERROR)
  					/* Bad arithmetic */
  #define EXC_BADMATCH		((5 << EXC_OFFSET) | EXC_ERROR)
  					/* Bad match in function body */
  #define EXC_FUNCTION_CLAUSE	((6 << EXC_OFFSET) | EXC_ERROR)
  					 /* No matching function head */
  #define EXC_CASE_CLAUSE		((7 << EXC_OFFSET) | EXC_ERROR)
  					/* No matching case clause */
  #define EXC_IF_CLAUSE		((8 << EXC_OFFSET) | EXC_ERROR)
  					/* No matching if clause */
  #define EXC_UNDEF		((9 << EXC_OFFSET) | EXC_ERROR)
  				 	/* No farity that matches */
  #define EXC_BADFUN		((10 << EXC_OFFSET) | EXC_ERROR)
  					/* Not an existing fun */
  #define EXC_BADARITY		((11 << EXC_OFFSET) | EXC_ERROR)
  					/* Attempt to call fun with
  					 * wrong number of arguments. */
  #define EXC_TIMEOUT_VALUE	((12 << EXC_OFFSET) | EXC_ERROR)
  					/* Bad time out value */
  #define EXC_NOPROC		((13 << EXC_OFFSET) | EXC_ERROR)
  					/* No process or port */
  #define EXC_NOTALIVE		((14 << EXC_OFFSET) | EXC_ERROR)
  					/* Not distributed */
  #define EXC_SYSTEM_LIMIT	((15 << EXC_OFFSET) | EXC_ERROR)
  					/* Ran out of something */
  #define EXC_TRY_CLAUSE		((16 << EXC_OFFSET) | EXC_ERROR)
  					/* No matching try clause */
  #define EXC_NOTSUP		((17 << EXC_OFFSET) | EXC_ERROR)
  					/* Not supported */
  
  #define EXC_BADMAP		((18 << EXC_OFFSET) | EXC_ERROR)
  					/* Bad map */
  
  #define EXC_BADKEY		((19 << EXC_OFFSET) | EXC_ERROR)
  					/* Bad key in map */
  
  #define NUMBER_EXIT_CODES 20	/* The number of exit code indices */
  
  /*
   * Internal pseudo-error codes.
   */
  #define TRAP		(1 << EXC_OFFSET)	/* BIF Trap to erlang code */
  
  /*
   * Aliases for some common exit codes.
   */
  #define BADARG EXC_BADARG
  #define BADARITH EXC_BADARITH
  #define BADKEY EXC_BADKEY
  #define BADMAP EXC_BADMAP
  #define BADMATCH EXC_BADMATCH
  #define SYSTEM_LIMIT EXC_SYSTEM_LIMIT
  
  
  /*
   * Pseudo error codes (these are never seen by the user).
   */
  #define TLOAD_OK 0              /* The threaded code linking was successful */
  #define TLOAD_MAGIC_NUMBER 1    /* Wrong kind of object file */
  #define TLOAD_FORMAT 2          /* Format error while reading object code */
  #define TLOAD_MODULE 3          /* Module name in object code does not match */
  #define TLOAD_SIZE 4            /* Given size in object code differs from actual size */
  
  /*
   * The exception stack trace parameters.
   */
  #define MAX_BACKTRACE_SIZE 64    /* whatever - just not too huge */
  #define DEFAULT_BACKTRACE_SIZE 8
  
  /*
   * The table translating an exception code to an atom.
   */
  extern Eterm error_atom[NUMBER_EXIT_CODES];
  
  /*
   * The exception tag table.
   */
  extern Eterm exception_tag[NUMBER_EXC_TAGS];
  
  /* 
   * The quick-saved stack trace structure
   */
  struct StackTrace {
      Eterm header;	/* bignum header - must be first in struct */
      Eterm freason; /* original exception reason is saved in the struct */
      BeamInstr* pc;
      ErtsCodeMFA* current;
      int depth;	/* number of saved pointers in trace[] */
      BeamInstr *trace[1];  /* varying size - must be last in struct */
  };
  
  #endif /* __ERROR_H__ */
  