File: ecode_add.c

package info (click to toggle)
fis-gtm 6.2-000-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 30,784 kB
  • ctags: 42,554
  • sloc: ansic: 358,483; asm: 4,847; csh: 4,574; sh: 2,261; awk: 200; makefile: 86; sed: 13
file content (202 lines) | stat: -rw-r--r-- 7,859 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/****************************************************************
 *								*
 *	Copyright 2001, 2009 Fidelity Information Services, Inc	*
 *								*
 *	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.	*
 *								*
 ****************************************************************/

#include "mdef.h"

#include "gtm_string.h"		/* for memcpy() */

#include "min_max.h"		/* for MIN macro */
#include <rtnhdr.h>		/* for stack_frame.h */
#include "stack_frame.h"	/* for stack_frame type */
#include "error_trap.h"

#include "get_command_line.h"	/* for get_command_line() prototype */
#include "dollar_zlevel.h"	/* for dollar_zlevel() prototype */

GBLREF	dollar_ecode_type	dollar_ecode;			/* structure containing $ECODE related information */
GBLREF	dollar_stack_type	dollar_stack;			/* structure containing $STACK related information */
GBLREF	stack_frame		*error_frame;			/* "frame_pointer" at the time of adding the current ECODE */
GBLREF	stack_frame		*frame_pointer;

#define		INCR_ECODE_INDEX(ecode_index, str, strlen)				\
{											\
	memcpy(dollar_ecode.end, str, strlen);						\
	dollar_ecode.array[ecode_index].ecode_str.addr = dollar_ecode.end;		\
	dollar_ecode.array[ecode_index].ecode_str.len = strlen;				\
	/* -1 below for not calculating the terminating ',' as part of this ECODE, 	\
	 * but instead calculate that as part of the beginning of the next ECODE */	\
	dollar_ecode.end += strlen - 1;							\
	ecode_index++;									\
}

#define		DECR_ECODE_INDEX(ecode_index)						\
{											\
	ecode_index--;									\
	space_left += dollar_ecode.array[ecode_index].ecode_str.len - 1;		\
}

/* returns TRUE if able to fit in string held by tmpmval into dollar_stack
 * returns FALSE otherwise */
static	boolean_t	fill_dollar_stack_info(mval *mvalptr, mstr *mstrptr)
{
	ssize_t		space_left;

	if (mvalptr->str.len)
	{
		space_left = dollar_stack.top - dollar_stack.end;
		if (mvalptr->str.len > space_left)
		{
			dollar_stack.incomplete = TRUE; /* we stop storing $STACK(level) info once we reach a frame level
							 * that can't be fitted in the available space */
			return FALSE;
		}
		memcpy(dollar_stack.end, mvalptr->str.addr, mvalptr->str.len);
		mstrptr->addr = dollar_stack.end;
		mstrptr->len = mvalptr->str.len;
		dollar_stack.end += mstrptr->len;
		assert(dollar_stack.end <= dollar_stack.top);
	} else
		mstrptr->len = 0;
	return TRUE;
}

/* returns TRUE if able to fit in one $STACK(level,...) of information in global variable structure "dollar_stack".
 * returns FALSE otherwise */
static	boolean_t	fill_dollar_stack_level(int array_level, int frame_level, int cur_zlevel)
{
	mstr			*mstrptr;
	mval			tmpmval;
	dollar_stack_struct	*dstack;

	assert(FALSE == dollar_stack.incomplete);	/* we should not have come here if previous $STACK levels were incomplete */
	dstack = &dollar_stack.array[array_level];
	/* fill in $STACK(level) */
	if (frame_level)
		get_frame_creation_info(frame_level, cur_zlevel, &tmpmval);
	else
		get_command_line(&tmpmval, FALSE);	/* FALSE to indicate we want actual (not processed) command line */
	/* note that tmpmval at this point will most likely point to the stringpool. but we rely on stp_gcol to free it up */
	mstrptr = &dstack->mode_str;
	if (FALSE == fill_dollar_stack_info(&tmpmval, mstrptr))
		return FALSE;
	/* fill in $STACK(level,"ECODE") */
	dstack->ecode_ptr = (frame_level == (cur_zlevel - 1)) ? &dollar_ecode.array[dollar_ecode.index - 1] : NULL;

	/* fill in $STACK(level,"PLACE") */
	get_frame_place_mcode(frame_level, DOLLAR_STACK_PLACE, cur_zlevel, &tmpmval);
	mstrptr = &dstack->place_str;
	if (FALSE == fill_dollar_stack_info(&tmpmval, mstrptr))
		return FALSE;
	/* fill in $STACK(level,"MCODE") */
	get_frame_place_mcode(frame_level, DOLLAR_STACK_MCODE, cur_zlevel, &tmpmval);
	mstrptr = &dstack->mcode_str;
	if (FALSE == fill_dollar_stack_info(&tmpmval, mstrptr))
		return FALSE;
	return TRUE;
}

boolean_t	ecode_add(mstr *str)		/* add "str" to $ECODE and return whether SUCCESS or FAILURE as TRUE/FALSE */
{
	int		ecode_index, stack_index;
	boolean_t	shrink;
 	int		cur_zlevel, level;
	char		eclostmid_buf[MAX_DIGITS_IN_INT + STR_LIT_LEN(",Z,")], *dest;
	ssize_t		space_left, eclostmid_len;

	error_def(ERR_ECLOSTMID);

	dest = &eclostmid_buf[0];
	*dest++ = ',';
	*dest++ = 'Z';
	dest = (char *)i2asc((unsigned char *)dest, ERR_ECLOSTMID);
	*dest++ = ',';
	eclostmid_len = dest - &eclostmid_buf[0];
	assert(SIZEOF(eclostmid_buf) >= eclostmid_len);

	assert(str->len < DOLLAR_ECODE_ALLOC);
	space_left = dollar_ecode.top - dollar_ecode.end;
	ecode_index = dollar_ecode.index;
	shrink = FALSE;
	if (space_left < str->len)
	{
		shrink = TRUE;
		assert(1 == shrink); 	/* since we need a value of 1 (instead of any non-zero) for usage below */
		space_left -= eclostmid_len - 1;/* note : space_left can become negative but code below handles that */
	}
	if (ecode_index >= (DOLLAR_ECODE_MAXINDEX - shrink))
	{
		assert(DOLLAR_ECODE_MAXINDEX >= ecode_index);
		if (DOLLAR_ECODE_MAXINDEX == ecode_index)
		{
			DECR_ECODE_INDEX(ecode_index);
			shrink = TRUE;
		}
		if (shrink)
		{
			DECR_ECODE_INDEX(ecode_index);
			assert((DOLLAR_ECODE_MAXINDEX - 2) == ecode_index);
		}
	}
	assert(ecode_index < DOLLAR_ECODE_MAXINDEX);
	for ( ; space_left < (int)str->len; )	/* note explicit typecasting to make sure it is a signed comparison */
	{
		ecode_index--;
		if (1 > ecode_index)	/* if ecode_index == -1 ==> str->len > DOLLAR_ECODE_ALLOC so nothing can be done in PRO */
			return FALSE;	/* if ecode_index == 0 ==> first ECODE needs to be overlaid. we do not want to do that. */
		space_left += dollar_ecode.array[ecode_index].ecode_str.len - 1;
	}
	for (stack_index = 0; stack_index < dollar_stack.index; stack_index++)
	{
		if (dollar_stack.array[stack_index].ecode_ptr > &dollar_ecode.array[ecode_index])
			return FALSE;	/* do not want to overlay any ECODE that $STACK(level,"ECODE") is pointing to */
	}
	assert(0 <= ecode_index);
	if (dollar_ecode.index != ecode_index)
	{
		dollar_ecode.end = dollar_ecode.array[ecode_index].ecode_str.addr;
		dollar_ecode.index = ecode_index;
	}
	if (shrink)
	{
		INCR_ECODE_INDEX(dollar_ecode.index, &eclostmid_buf[0], (mstr_len_t)eclostmid_len);
	}
	INCR_ECODE_INDEX(dollar_ecode.index, str->addr, str->len);
	if ((1 == dollar_ecode.index)
			|| ((!dollar_stack.incomplete) && (2 == dollar_ecode.index)
				&& (dollar_ecode.first_ecode_error_frame == error_frame)))
	{	/* need to fill in $STACK entries if either the first ECODE or if an error in the first ECODE error-handler.
		 * do not fill in nested error $STACK info if the first ECODE's $STACK info itself was incompletely filled in */
		if (1 == dollar_ecode.index)
		{	/* first ECODE. note down error_frame info in "first_ecode_error_frame" as well as $STACK(level) info */
			dollar_ecode.first_ecode_error_frame = frame_pointer;
			assert(0 == dollar_stack.index);
		}
		cur_zlevel = dollar_zlevel();
		assert(dollar_stack.index <= cur_zlevel);
		for (level = dollar_stack.index; level < MIN(cur_zlevel, DOLLAR_STACK_MAXINDEX); )
		{	/* we do not store $STACK(level) info for levels > 256 */
			if (fill_dollar_stack_level(level, level, cur_zlevel))
				level++;	/* update array_level only if we had enough space to fill in all of above */
			else
				break;
		}
		if ((2 == dollar_ecode.index) && (cur_zlevel == dollar_stack.index) && (DOLLAR_STACK_MAXINDEX > cur_zlevel))
		{	/* if nested error occurred at the same frame_level as the first error,
			 * store $STACK information for the nested error in $STACK(frame_level+1)
			 */
			assert(level == dollar_stack.index);
			if (fill_dollar_stack_level(level, cur_zlevel - 1, cur_zlevel))
				level++;
		}
		dollar_stack.index = level;
	}
	return TRUE;
}