2012-02-05 11:35:58 -05:00
|
|
|
/****************************************************************
|
2012-03-24 14:06:46 -04:00
|
|
|
* Copyright 2001, 2012 Fidelity Information Services, Inc *
|
2012-02-05 11:35:58 -05:00
|
|
|
* *
|
|
|
|
* This source code contains the intellectual property *
|
|
|
|
* of its copyright holder(s), and is made available *
|
|
|
|
* under a license. If you do not know the terms of *
|
|
|
|
* the license, please stop and do not read further. *
|
|
|
|
* *
|
|
|
|
****************************************************************/
|
|
|
|
|
|
|
|
#ifndef ERROR_TRAP_H
|
|
|
|
#define ERROR_TRAP_H
|
|
|
|
|
|
|
|
#define IS_ETRAP (err_act == &dollar_etrap.str)
|
2012-03-24 14:06:46 -04:00
|
|
|
#define ETRAP_IN_EFFECT (!ztrap_explicit_null && (0 == dollar_ztrap.str.len))
|
2012-02-05 11:35:58 -05:00
|
|
|
|
|
|
|
#define DOLLAR_ECODE_MAXINDEX 32 /* maximum of 32 ecodes in $ECODE */
|
|
|
|
#define DOLLAR_STACK_MAXINDEX 256 /* maximum of 256 levels will be stored for $STACK(level) */
|
|
|
|
|
|
|
|
#define DOLLAR_ECODE_ALLOC (1 << 15) /* 32K chunk memory malloced for $ECODE */
|
|
|
|
#define DOLLAR_STACK_ALLOC (1 << 15) /* 32K chunk memory malloced for $STACK(level) */
|
|
|
|
|
|
|
|
#define STACK_ZTRAP_EXPLICIT_NULL -1 /* used to indicate an explicit SET $ZTRAP = "" */
|
|
|
|
|
|
|
|
typedef void (*error_ret_fnptr)(void);
|
|
|
|
|
|
|
|
typedef struct dollar_ecode
|
|
|
|
{
|
|
|
|
mstr ecode_str;
|
|
|
|
} dollar_ecode_struct;
|
|
|
|
|
|
|
|
typedef struct dollar_stack /* contents of a single $STACK(level) entry */
|
|
|
|
{
|
|
|
|
mstr mode_str; /* $STACK(level) */
|
|
|
|
dollar_ecode_struct *ecode_ptr; /* $STACK(level,"ECODE") */
|
|
|
|
mstr mcode_str; /* $STACK(level,"MCODE") */
|
|
|
|
mstr place_str; /* $STACK(level,"PLACE") */
|
|
|
|
} dollar_stack_struct;
|
|
|
|
|
|
|
|
typedef enum stack_mode
|
|
|
|
{
|
|
|
|
DOLLAR_STACK_INVALID,
|
|
|
|
DOLLAR_STACK_ECODE, /* $STACK(level,"ECODE") */
|
|
|
|
DOLLAR_STACK_PLACE, /* $STACK(level,"PLACE") */
|
|
|
|
DOLLAR_STACK_MCODE, /* $STACK(level,"MCODE") */
|
|
|
|
DOLLAR_STACK_MODE /* $STACK(level) i.e. how this frame got created */
|
|
|
|
} stack_mode_t;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *begin; /* beginning of malloced memory holding the complete $ECODE */
|
|
|
|
char *end; /* pointer to where next $ECODE can be added */
|
|
|
|
char *top; /* allocated end of malloced memory holding the complete $ECODE */
|
|
|
|
dollar_ecode_struct *array; /* array of DOLLAR_ECODE_MAXINDEX dollar_ecode_struct structures */
|
|
|
|
uint4 index; /* current count of number of filled structures in array */
|
|
|
|
int4 error_last_ecode; /* last error code number */
|
|
|
|
unsigned char *error_last_b_line; /* ptr to beginning of line where error occurred */
|
|
|
|
struct stack_frame_struct *first_ecode_error_frame; /* "frame_pointer" at the time of adding the first ECODE */
|
|
|
|
unsigned char *error_rtn_addr; /* CODE_ADDRESS(ERROR_RTN) */
|
|
|
|
unsigned char *error_rtn_ctxt; /* GTM_CONTEXT(ERROR_RTN) */
|
|
|
|
error_ret_fnptr error_return_addr; /* CODE_ADDRESS(ERROR_RETURN) */
|
|
|
|
} dollar_ecode_type;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *begin; /* beginning of malloced memory holding all $STACK(level) detail */
|
|
|
|
char *end; /* pointer to where next $STACK(level) detail can be added */
|
|
|
|
char *top; /* allocated end of malloced memory holding all $STACK(level) detail */
|
|
|
|
dollar_stack_struct *array; /* array of DOLLAR_STACK_MAXINDEX dollar_stack_struct structures */
|
|
|
|
uint4 index; /* current count of number of filled structures in array */
|
|
|
|
boolean_t incomplete; /* TRUE if we were not able to fit in all $STACK info */
|
|
|
|
} dollar_stack_type;
|
|
|
|
|
|
|
|
/* reset all $ECODE related variables to correspond to $ECODE = NULL state */
|
|
|
|
#define NULLIFY_DOLLAR_ECODE \
|
|
|
|
{ \
|
|
|
|
GBLREF dollar_ecode_type dollar_ecode; \
|
|
|
|
GBLREF dollar_stack_type dollar_stack; \
|
|
|
|
\
|
|
|
|
dollar_ecode.end = dollar_ecode.begin; \
|
|
|
|
dollar_ecode.index = 0; \
|
|
|
|
dollar_stack.end = dollar_stack.begin; \
|
|
|
|
dollar_stack.index = 0; \
|
|
|
|
dollar_stack.incomplete = FALSE; \
|
|
|
|
dollar_ecode.first_ecode_error_frame = NULL; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* nullify "error_frame" */
|
2012-03-24 14:06:46 -04:00
|
|
|
#define NULLIFY_ERROR_FRAME \
|
|
|
|
{ \
|
|
|
|
GBLREF stack_frame *error_frame; \
|
|
|
|
\
|
|
|
|
error_frame = NULL; \
|
|
|
|
DBGEHND((stderr, "%s: Nullifying previous error_frame (was 0x"lvaddr")\n", __FILE__, error_frame)); \
|
2012-02-05 11:35:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set "error_frame" to point to "frame_pointer" and mark it as an error frame type. This is an indication that
|
|
|
|
* whenever we unwind back to this frame, we need to transfer control to error_rtn_addr/ctxt (taken care of by getframe).
|
|
|
|
*/
|
|
|
|
#define SET_ERROR_FRAME(fp) \
|
|
|
|
{ \
|
2012-03-24 14:06:46 -04:00
|
|
|
GBLREF stack_frame *error_frame; \
|
2012-02-05 11:35:58 -05:00
|
|
|
\
|
|
|
|
fp->flags |= SFF_ETRAP_ERR; \
|
|
|
|
error_frame = fp; \
|
2012-03-24 14:06:46 -04:00
|
|
|
DBGEHND((stderr, "%s: Setting error_frame as 0x"lvaddr"\n", __FILE__, fp)); \
|
2012-02-05 11:35:58 -05:00
|
|
|
}
|
|
|
|
|
2012-03-24 14:06:46 -04:00
|
|
|
/* invoke the function error_return() if the necessity of error-rethrow is detected. Note the extra
|
|
|
|
* "&" value on the various assert(FALSE) type statements. This allows us to know which of these asserts
|
|
|
|
* failed.
|
|
|
|
*/
|
2012-02-05 11:35:58 -05:00
|
|
|
#define INVOKE_ERROR_RET_IF_NEEDED \
|
|
|
|
{ \
|
|
|
|
GBLREF dollar_ecode_type dollar_ecode; \
|
|
|
|
GBLREF stack_frame *error_frame; \
|
|
|
|
\
|
|
|
|
if (NULL != error_frame) \
|
|
|
|
{ \
|
|
|
|
if (error_frame == frame_pointer) \
|
|
|
|
{ \
|
|
|
|
if (dollar_ecode.index) /* non-zero implies non-NULL $ECODE */ \
|
|
|
|
{ /* this is an error frame and $ECODE is non-NULL during QUIT out of this frame. \
|
|
|
|
* rethrow the error at lower level */ \
|
|
|
|
(*dollar_ecode.error_return_addr)(); \
|
2012-03-24 14:06:46 -04:00
|
|
|
/* While error_return does not usually return in UNIX, it can if we are \
|
|
|
|
* unwinding a job-interrupt frame because error rethrowing terminates when a \
|
|
|
|
* job-interrupt frame is unwound which instead of re-throwing in the \
|
|
|
|
* interrupted frame sends an error to the operator log. But in VMS, we dont \
|
2012-02-05 11:35:58 -05:00
|
|
|
* do the latter so it is possible if the current frame is of type SFT_DM that \
|
2012-03-24 14:06:46 -04:00
|
|
|
* we don't rethrow and don't do a MUM_TSTART either. Assert accordingly. \
|
2012-02-05 11:35:58 -05:00
|
|
|
*/ \
|
|
|
|
VMS_ONLY(assert(SFT_DM & frame_pointer->type);) \
|
|
|
|
} else \
|
|
|
|
{ \
|
2012-03-24 14:06:46 -04:00
|
|
|
assert(FALSE & 2); \
|
2012-02-05 11:35:58 -05:00
|
|
|
NULLIFY_ERROR_FRAME; /* don't know how we reached here. reset it in PRO */ \
|
|
|
|
} \
|
|
|
|
} else if (error_frame < frame_pointer) \
|
|
|
|
{ \
|
2012-03-24 14:06:46 -04:00
|
|
|
assert(FALSE & 3); \
|
2012-02-05 11:35:58 -05:00
|
|
|
NULLIFY_ERROR_FRAME; /* don't know how we reached here. reset it in PRO */ \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
void ecode_init(void);
|
|
|
|
void ecode_get(int level, mval *result); /* return $ECODE (if "level" < 0) or $STACK(level,"ECODE") in "result" */
|
|
|
|
void ecode_set(int errnum); /* convert "errnum" to error-string and call ecode_add() */
|
|
|
|
boolean_t ecode_add(mstr *str); /* add "str" to $ECODE */
|
|
|
|
void error_return(void);
|
|
|
|
#ifdef VMS
|
|
|
|
void error_return_vms(void);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void get_dollar_stack_info(int level, stack_mode_t mode, mval *result);
|
|
|
|
void get_frame_creation_info(int level, int cur_zlevel, mval *result);
|
|
|
|
void get_frame_place_mcode(int level, stack_mode_t mode, int cur_zlevel, mval *result);
|
|
|
|
|
|
|
|
#endif /* ERROR_TRAP_H */
|