Ejemplo n.º 1
0
void init_callin_functable(void)
{
	unsigned char 	*env_top, *address_top;
	uint4 		address_len;
	int		save_errno;

	address_top = GTM64_ONLY(i2ascl)NON_GTM64_ONLY(i2asc)(gtmvectortable_address, (UINTPTR_T)(&callintogtm_vectortable[0]));
	*address_top = '\0';
	address_len = (uint4)(address_top - &gtmvectortable_address[0]);
	env_top = &gtmvectortable_env[0];
	MEMCPY_LIT(env_top, GTM_CALLIN_START_ENV);
	memcpy((env_top + strlen(GTM_CALLIN_START_ENV)), gtmvectortable_address, address_len);
	*(env_top + strlen(GTM_CALLIN_START_ENV) + address_len) = '\0';
	if (PUTENV((char *)gtmvectortable_env))
	{
		save_errno = errno;
		rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("putenv"), CALLFROM, save_errno);
	}
}
Ejemplo n.º 2
0
/*
 * ------------------------------------------
 * Hang the process for a specified time.
 *
 *	Goes to sleep for a positive value.
 *	Any caught signal will terminate the sleep
 *	following the execution of that signal's catching routine.
 *
 * Arguments:
 *	num - time to sleep
 *
 * Return:
 *	none
 * ------------------------------------------
 */
void op_hang(mval* num)
{
	int		ms;
	mv_stent	*mv_zintcmd;
	ABS_TIME	cur_time, end_time;
#	ifdef VMS
	uint4 		time[2];
	int4		efn_mask, status;
#	endif
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	ms = 0;
	MV_FORCE_NUM(num);
	if (num->mvtype & MV_INT)
	{
		if (0 < num->m[1])
		{
			assert(MV_BIAS >= 1000);	/* if formats change overflow may need attention */
			ms = num->m[1] * (1000 / MV_BIAS);
		}
	} else if (0 == num->sgn) 		/* if sign is not 0 it means num is negative */
		ms = mval2i(num) * 1000;	/* too big to care about fractional amounts */
	if (ms)
	{
		if (TREF(tpnotacidtime) * 1000 < ms)
			TPNOTACID_CHECK(HANGSTR);
#		if defined(DEBUG) && defined(UNIX)
		if (gtm_white_box_test_case_enabled
			&& (WBTEST_DEFERRED_TIMERS == gtm_white_box_test_case_number)
			&& (3 > gtm_white_box_test_case_count)
			&& (123000 == ms))
		{
			DEFER_INTERRUPTS(INTRPT_NO_TIMER_EVENTS);
			DBGFPF((stderr, "OP_HANG: will sleep for 20 seconds\n"));
			LONG_SLEEP(20);
			DBGFPF((stderr, "OP_HANG: done sleeping\n"));
			ENABLE_INTERRUPTS(INTRPT_NO_TIMER_EVENTS);
			return;
		}
		if (gtm_white_box_test_case_enabled
			&& (WBTEST_BREAKMPC == gtm_white_box_test_case_number)
			&& (0 == gtm_white_box_test_case_count)
			&& (999 == ms))
		{
			frame_pointer->old_frame_pointer->mpc = (unsigned char *)GTM64_ONLY(0xdeadbeef12345678)
				NON_GTM64_ONLY(0xdead1234);
			return;
		}
		/* Upon seeing a .999s hang this white-box test launches a timer that pops with a period of UTIL_OUT_SYSLOG_INTERVAL
		 * and prints a long message via util_out_ptr.
		 */
		if (gtm_white_box_test_case_enabled
			&& (WBTEST_UTIL_OUT_BUFFER_PROTECTION == gtm_white_box_test_case_number)
			&& (0 == gtm_white_box_test_case_count)
			&& (999 == ms))
		{
			start_timer((TID)&util_out_syslog_dump, UTIL_OUT_SYSLOG_INTERVAL, util_out_syslog_dump, 0, NULL);
			return;
		}
#		endif
		sys_get_curr_time(&cur_time);
		mv_zintcmd = find_mvstent_cmd(ZINTCMD_HANG, restart_pc, restart_ctxt, FALSE);
		if (!mv_zintcmd)
			add_int_to_abs_time(&cur_time, ms, &end_time);
		else
		{
			end_time = mv_zintcmd->mv_st_cont.mvs_zintcmd.end_or_remain;
			cur_time = sub_abs_time(&end_time, &cur_time);	/* get remaing time to sleep */
			if (0 <= cur_time.at_sec)
				ms = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000);
			else
				ms = 0;		/* all done */
			/* restore/pop previous zintcmd_active[ZINTCMD_HANG] hints */
			TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_prior;
			TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last
				= mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_ctxt_prior;
			TAREF1(zintcmd_active, ZINTCMD_HANG).count--;
			assert(0 <= TAREF1(zintcmd_active, ZINTCMD_HANG).count);
			if (mv_chain == mv_zintcmd)
				POP_MV_STENT();	/* just pop if top of stack */
			else
			{	/* flag as not active */
				mv_zintcmd->mv_st_cont.mvs_zintcmd.command = ZINTCMD_NOOP;
				mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_check = NULL;
			}
			if (0 == ms)
				return;		/* done HANGing */
		}
		UNIX_ONLY(hiber_start(ms);)
		VMS_ONLY(
			time[0] = -time_low_ms(ms);
			time[1] = -time_high_ms(ms) - 1;
			efn_mask = (1 << efn_outofband | 1 << efn_timer);
			if (SS$_NORMAL != (status = sys$setimr(efn_timer, &time, NULL, &time, 0)))
				rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$setimr"), CALLFROM, status);
			if (SS$_NORMAL != (status = sys$wflor(efn_outofband, efn_mask)))
				rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$wflor"), CALLFROM, status);
		)
		if (outofband)
Ejemplo n.º 3
0
/*
 * ------------------------------------------
 * Hang the process for a specified time.
 *
 *	Goes to sleep for a positive value.
 *	Any caught signal will terminate the sleep
 *	following the execution of that signal's catching routine.
 *
 * 	The actual hang duration should be NO LESS than the specified
 * 	duration for specified durations greater than .001 seconds.
 * 	Certain applications depend on this assumption.
 *
 * Arguments:
 *	num - time to sleep
 *
 * Return:
 *	none
 * ------------------------------------------
 */
void op_hang(mval* num)
{
	int		ms;
	double		tmp;
	mv_stent	*mv_zintcmd;
	ABS_TIME	cur_time, end_time;
#	ifdef VMS
	uint4 		time[2];
	int4		efn_mask, status;
#	endif
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	ms = 0;
	MV_FORCE_NUM(num);
	if (num->mvtype & MV_INT)
	{
		if (0 < num->m[1])
		{
			assert(MV_BIAS >= 1000);	/* if formats change overflow may need attention */
			ms = num->m[1] * (1000 / MV_BIAS);
		}
	} else if (0 == num->sgn) 		/* if sign is not 0 it means num is negative */
	{
		tmp = mval2double(num) * (double)1000;
		ms = ((double)MAXPOSINT4 >= tmp) ? (int)tmp : (int)MAXPOSINT4;
	}
	if (ms)
	{
		if (TREF(tpnotacidtime) * 1000 < ms)
			TPNOTACID_CHECK(HANGSTR);
#		if defined(DEBUG) && defined(UNIX)
		if (WBTEST_ENABLED(WBTEST_DEFERRED_TIMERS) && (3 > gtm_white_box_test_case_count) && (123000 == ms))
		{
			DEFER_INTERRUPTS(INTRPT_NO_TIMER_EVENTS);
			DBGFPF((stderr, "OP_HANG: will sleep for 20 seconds\n"));
			LONG_SLEEP(20);
			DBGFPF((stderr, "OP_HANG: done sleeping\n"));
			ENABLE_INTERRUPTS(INTRPT_NO_TIMER_EVENTS);
			return;
		}
		if (WBTEST_ENABLED(WBTEST_BREAKMPC)&& (0 == gtm_white_box_test_case_count) && (999 == ms))
		{
			frame_pointer->old_frame_pointer->mpc = (unsigned char *)GTM64_ONLY(0xdeadbeef12345678)
				NON_GTM64_ONLY(0xdead1234);
			return;
		}
		if (WBTEST_ENABLED(WBTEST_UTIL_OUT_BUFFER_PROTECTION) && (0 == gtm_white_box_test_case_count) && (999 == ms))
		{	/* Upon seeing a .999s hang this white-box test launches a timer that pops with a period of
		 	 * UTIL_OUT_SYSLOG_INTERVAL and prints a long message via util_out_ptr.
			 */
			start_timer((TID)&util_out_syslog_dump, UTIL_OUT_SYSLOG_INTERVAL, util_out_syslog_dump, 0, NULL);
			return;
		}
#		endif
		sys_get_curr_time(&cur_time);
		mv_zintcmd = find_mvstent_cmd(ZINTCMD_HANG, restart_pc, restart_ctxt, FALSE);
		if (!mv_zintcmd)
			add_int_to_abs_time(&cur_time, ms, &end_time);
		else
		{
			end_time = mv_zintcmd->mv_st_cont.mvs_zintcmd.end_or_remain;
			cur_time = sub_abs_time(&end_time, &cur_time);	/* get remaing time to sleep */
			if (0 <= cur_time.at_sec)
				ms = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000);
			else
				ms = 0;		/* all done */
			/* restore/pop previous zintcmd_active[ZINTCMD_HANG] hints */
			TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_prior;
			TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last
				= mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_ctxt_prior;
			TAREF1(zintcmd_active, ZINTCMD_HANG).count--;
			assert(0 <= TAREF1(zintcmd_active, ZINTCMD_HANG).count);
			if (mv_chain == mv_zintcmd)
				POP_MV_STENT();	/* just pop if top of stack */
			else
			{	/* flag as not active */
				mv_zintcmd->mv_st_cont.mvs_zintcmd.command = ZINTCMD_NOOP;
				mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_check = NULL;
			}
			if (0 == ms)
				return;		/* done HANGing */
		}
#		ifdef UNIX
		if (ms < 10)
			SLEEP_USEC(ms * 1000, TRUE);	/* Finish the sleep if it is less than 10ms. */
		else
			hiber_start(ms);
#		elif defined(VMS)
		time[0] = -time_low_ms(ms);
		time[1] = -time_high_ms(ms) - 1;
		efn_mask = (1 << efn_outofband | 1 << efn_timer);
		if (SS$_NORMAL != (status = sys$setimr(efn_timer, &time, NULL, &time, 0)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$setimr"), CALLFROM, status);
		if (SS$_NORMAL != (status = sys$wflor(efn_outofband, efn_mask)))
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$wflor"), CALLFROM, status);
		if (outofband)
		{
			if (SS$_WASCLR == (status = sys$readef(efn_timer, &efn_mask)))
			{
				if (SS$_NORMAL != (status = sys$cantim(&time, 0)))
					rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$cantim"),
						CALLFROM, status);
			} else
				assertpro(SS$_WASSET == status);
		}
#		endif
	} else
		rel_quant();
	if (outofband)
	{
		PUSH_MV_STENT(MVST_ZINTCMD);
		mv_chain->mv_st_cont.mvs_zintcmd.end_or_remain = end_time;
		mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_check = restart_ctxt;
		mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_check = restart_pc;
		/* save current information from zintcmd_active */
		mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_prior = TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last;
		mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_prior = TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last;
		TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = restart_pc;
		TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last = restart_ctxt;
		TAREF1(zintcmd_active, ZINTCMD_HANG).count++;
		mv_chain->mv_st_cont.mvs_zintcmd.command = ZINTCMD_HANG;
		outofband_action(FALSE);
	}
	return;
}
Ejemplo n.º 4
0
Archivo: cli_port.c Proyecto: 5HT/mumps
int cli_parse_two_numbers(char *qual_name, const char delimiter, uint4 *first_num, uint4 *second_num)
{ /* Parse two unsigned base 10 numbers separated by the given delimiter. Eg. -LOG_INTERVAL=10,20 (on VMS, -LOG_INTERVAL="10,20").
   * Both Unix and VMS accept the qualifier as a string. NOTE: On VMS, such qualifiers are quoted strings.
   * Both numbers are optional (eg. -LOG_INTERVAL=10, or -LOG_INTERVAL=",20", or -LOG_INTERVAL=,).
   * Return values:
   * 		     CLI_2NUM_FIRST_SPECIFIED  (binary 10), first number specified, second not
   * 		     CLI_2NUM_SECOND_SPECIFIED (binary 01), first number not specified, second is
   * 		     CLI_2NUM_BOTH_SPECIFIED   (binary 11) (CLI_2NUM_FIRST_SPECIFIED | CLI_2NUM_SECOND_SPECIFIED), both specified
   * 		     0 (binary 00), error in parsing either number
   */
	char		*first_num_str, *second_num_str, *two_num_str_top, *num_endptr;
	char		two_num_qual_str[128];
	unsigned short	two_num_qual_len;
	uint4		num;
	int		retval = 0;

	two_num_qual_len = sizeof(two_num_qual_str);
	if (!cli_get_str(qual_name, two_num_qual_str, &two_num_qual_len))
	{
		util_out_print("Error parsing !AZ qualifier", TRUE, qual_name);
		return 0;
	}
#ifdef VMS
	/* DCL does not strip quotes included in the command line. However, the DEFAULT value (see mupip_cmd.cld) is stripped
	 * of quotes. */
	if ('"' == two_num_qual_str[0])
	{
		assert('"' == two_num_qual_str[two_num_qual_len - 1]); /* end quote should exist */
		first_num_str = &two_num_qual_str[1]; /* Skip begin quote */
		two_num_qual_str[two_num_qual_len - 1] = '\0'; /* Zap end quote */
		two_num_qual_len -= 2; /* Quotes gone */
	} else
#endif
		first_num_str = two_num_qual_str;
	for (second_num_str = first_num_str, two_num_str_top = first_num_str + two_num_qual_len;
		second_num_str < two_num_str_top && delimiter != *second_num_str;
		second_num_str++)
		;
	if (delimiter == *second_num_str)
		*second_num_str++ = '\0';
	if (*first_num_str != '\0') /* VMS issues EINVAL if strtoul is passed null string */
	{
		errno = 0;
		num = (uint4)STRTOUL(first_num_str, &num_endptr, 10);
		if ((0 == num && (0 != errno || (num_endptr == first_num_str && *first_num_str != '\0'))) ||
		    (0 != errno && GTM64_ONLY(UINT_MAX == num) NON_GTM64_ONLY(ULONG_MAX == num)))
		{
			util_out_print("Error parsing or invalid parameter for !AZ", TRUE, qual_name);
			return 0;
		}
		*first_num = num;
		retval |= CLI_2NUM_FIRST_SPECIFIED;
	} /* else, first number not specified */
	if (second_num_str < two_num_str_top && *second_num_str != '\0')
	{
		errno = 0;
		num = (uint4)STRTOUL(second_num_str, &num_endptr, 10);
		if ((0 == num && (0 != errno || (num_endptr == second_num_str && *second_num_str != '\0'))) ||
		    (0 != errno && GTM64_ONLY(UINT_MAX == num) NON_GTM64_ONLY(ULONG_MAX == num)))
		{
			util_out_print("Error parsing or invalid parameter for LOG_INTERVAL", TRUE);
			return 0;
		}
		*second_num = num;
		retval |= CLI_2NUM_SECOND_SPECIFIED;
	} /* else, second number not specified */
	return retval;
}
Ejemplo n.º 5
0
void op_svget(int varnum, mval *v)
{
	io_log_name	*tl;
	int 		count;
	gtm_uint64_t	ucount;
	char		*c1, *c2;
	mval		*mvp;
#	ifdef UNIX
	d_rm_struct	*d_rm;
#	endif
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
#	if defined(UNIX) && defined(DEBUG)
	if (gtm_white_box_test_case_enabled && (WBTEST_HUGE_ALLOC == gtm_white_box_test_case_number))
	{
		if (1 == gtm_white_box_test_case_count)
			totalAlloc = totalAllocGta = totalRmalloc = totalRallocGta = totalUsed = totalUsedGta = 0xffff;
		else if (2 == gtm_white_box_test_case_count)
			totalAlloc = totalAllocGta = totalRmalloc = totalRallocGta = totalUsed = totalUsedGta = 0xfffffff;
		else if (3 == gtm_white_box_test_case_count)
		{
#			ifdef GTM64
			if (8 == SIZEOF(size_t))
				totalAlloc = totalAllocGta = totalRmalloc = totalRallocGta
					= totalUsed = totalUsedGta = 0xfffffffffffffff;
			else
#			endif
				totalAlloc = totalAllocGta = totalRmalloc = totalRallocGta = totalUsed = totalUsedGta = 0xfffffff;
		} else
			totalAlloc = totalAllocGta = totalRmalloc = totalRallocGta = totalUsed
				= totalUsedGta = GTM64_ONLY(SIZEOF(size_t)) NON_GTM64_ONLY(SIZEOF(size_t) > 4 ? 4 : SIZEOF(size_t));
	}
#	endif
	switch (varnum)
	{
		case SV_HOROLOG:
			op_horolog(v);
			break;
		case SV_ZGBLDIR:
			v->mvtype = MV_STR;
			v->str = dollar_zgbldir.str;
			break;
		case SV_PRINCIPAL:
			tl = dollar_principal ? dollar_principal : io_root_log_name->iod->trans_name;
			v->str.addr = tl->dollar_io;
			v->str.len = tl->len;
			/*** The following should be in the I/O code ***/
			if (ESC == *v->str.addr)
			{
				if (5 > v->str.len)
					v->str.len = 0;
				else
				{
					v->str.addr += ESC_OFFSET;
					v->str.len -= ESC_OFFSET;
				}
			}
			s2pool(&(v->str));
			v->mvtype = MV_STR;
			break;
		case SV_ZIO:
			v->mvtype = MV_STR;
			/* NOTE:	This is **NOT** equivalent to :
			 *		io_curr_log_name->dollar_io
			 */
			v->str.addr = io_curr_device.in->trans_name->dollar_io;
			v->str.len = io_curr_device.in->trans_name->len;
			if (ESC == *v->str.addr)
			{
				if (5 > v->str.len)
					v->str.len = 0;
				else
				{
					v->str.addr += ESC_OFFSET;
					v->str.len -= ESC_OFFSET;
				}
			}
			s2pool(&(v->str));
			break;
		case SV_JOB:
			*v = dollar_job;
			break;
		case SV_REFERENCE:
			get_reference(v);
			break;
		case SV_SYSTEM:
			*v = dollar_system;
			break;
		case SV_STORAGE:
			/* double2mval(v, getstorage()); Causes issues with unaligned stack on x86_64 - remove until fixed */
			i2mval(v, getstorage());
			break;
		case SV_TLEVEL:
			count = (int)dollar_tlevel;
			MV_FORCE_MVAL(v, count);
			break;
		case SV_TRESTART:
			MV_FORCE_MVAL(v, (int)((MAX_VISIBLE_TRESTART < dollar_trestart) ? MAX_VISIBLE_TRESTART : dollar_trestart));
			break;
		case SV_X:
			count = (int)io_curr_device.out->dollar.x;
			MV_FORCE_MVAL(v, count);
			break;
		case SV_Y:
			count = (int)io_curr_device.out->dollar.y;
			MV_FORCE_MVAL(v, count);
			break;
		case SV_ZA:
			count = (int)io_curr_device.in->dollar.za;
			MV_FORCE_MVAL(v, count);
			break;
		case SV_ZB:
			c1 = (char *)io_curr_device.in->dollar.zb;
			c2 = c1 + SIZEOF(io_curr_device.in->dollar.zb);
			ENSURE_STP_FREE_SPACE(SIZEOF(io_curr_device.in->dollar.zb));
			v->mvtype = MV_STR;
			v->str.addr = (char *)stringpool.free;
			while (c1 < c2 && *c1)
				*stringpool.free++ = *c1++;
			v->str.len = INTCAST((char *)stringpool.free - v->str.addr);
			break;
		case SV_ZC:	/****THESE ARE DUMMY VALUES ONLY!!!!!!!!!!!!!!!!!****/
			MV_FORCE_MVAL(v, 0);
			break;
		case SV_ZCMDLINE:
			get_command_line(v, TRUE);	/* TRUE to indicate we want $ZCMDLINE
							   (i.e. processed not actual command line) */
			break;
		case SV_ZEOF:
#			ifdef UNIX
			if (rm == io_curr_device.in->type)
			{
				d_rm = (d_rm_struct *)io_curr_device.in->dev_sp;
				if (RM_READ != d_rm->lastop)
				{
					*v = literal_zero;
					break;
				}
			}
#			endif
			*v = io_curr_device.in->dollar.zeof ? literal_one : literal_zero;
			break;
		case SV_ZQUIT:
			*v = dollar_zquit_anyway ? literal_one : literal_zero;
			break;
		case SV_IO:
			v->str.addr = io_curr_device.in->name->dollar_io;
			v->str.len = io_curr_device.in->name->len;
			/*** The following should be in the I/O code ***/
			if (ESC == *v->str.addr)
			{
				if (5 > v->str.len)
					v->str.len = 0;
				else
				{
					v->str.addr += ESC_OFFSET;
					v->str.len -= ESC_OFFSET;
				}
			}
			s2pool(&(v->str));
			v->mvtype = MV_STR;
			break;
		case SV_PROMPT:
			v->mvtype = MV_STR;
			v->str.addr = (TREF(gtmprompt)).addr;
			v->str.len = (TREF(gtmprompt)).len;
			s2pool(&v->str);
			break;
		case SV_ZCOMPILE:
			v->mvtype = MV_STR;
			v->str = TREF(dollar_zcompile);
			s2pool(&(v->str));
			break;
		case SV_ZDIR:
			setzdir(NULL, v);
			if (v->str.len != dollar_zdir.str.len || 0 != memcmp(v->str.addr, dollar_zdir.str.addr, v->str.len))
				gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_ZDIROUTOFSYNC, 4, v->str.len, v->str.addr,
					   dollar_zdir.str.len, dollar_zdir.str.addr);
			SKIP_DEVICE_IF_NOT_NEEDED(v);
			s2pool(&(v->str));
			break;
		case SV_ZSTEP:
			*v = dollar_zstep;
			break;
		case SV_ZMODE:
			*v = TREF(dollar_zmode);
			break;
		case SV_ZMAXTPTIME:
			i2mval(v, TREF(dollar_zmaxtptime));
			break;
		case SV_ZPOS:
			getzposition(v);
			break;
		case SV_ZPROC:
			getzprocess();
			*v = dollar_zproc;
			break;
		case SV_ZLEVEL:
			count = dollar_zlevel();
			MV_FORCE_MVAL(v, count);
			break;
		case SV_ZROUTINES:
			if (!TREF(zro_root))
				zro_init();
			v->mvtype = MV_STR;
			v->str = TREF(dollar_zroutines);
			s2pool(&(v->str));
			break;
		case SV_ZSOURCE:
			v->mvtype = MV_STR;
			v->str = dollar_zsource.str;
			break;
		case SV_ZSTATUS:
			*v = dollar_zstatus;
			s2pool(&(v->str));
			break;
		case SV_ZTRAP:
			v->mvtype = MV_STR;
			v->str = dollar_ztrap.str;
			assert(!v->str.len || !ztrap_explicit_null);
			s2pool(&(v->str));
			break;
		case SV_DEVICE:
			get_dlr_device(v);
			break;
		case SV_KEY:
			get_dlr_key(v);
			break;
		case SV_ZVERSION:
			v->mvtype = MV_STR;
			v->str.addr = (char *)gtm_release_name;
			v->str.len = gtm_release_name_len;
			break;
		case SV_ZSYSTEM:
			MV_FORCE_MVAL(v, dollar_zsystem);
			break;
		case SV_ZCSTATUS:
			/* Maintain the external $ZCSTATUS == 1 for SUCCESS on UNIX while internal good is 0 */
			MV_FORCE_MVAL(v, UNIX_ONLY((0 == TREF(dollar_zcstatus)) ? 1 : ) TREF(dollar_zcstatus));
			break;
		case SV_ZEDITOR:
			MV_FORCE_MVAL(v, dollar_zeditor);
			break;
		case SV_QUIT:
			MV_FORCE_MVAL(v, dollar_quit());
			break;
		case SV_ECODE:
			ecode_get(-1, v);
			break;
		case SV_ESTACK:
			count = (dollar_zlevel() - 1) - dollar_estack_delta.m[0];
			MV_FORCE_MVAL(v, count);
			break;
		case SV_ETRAP:
			v->mvtype = MV_STR;
			v->str = dollar_etrap.str;
			assert(!v->str.len || !ztrap_explicit_null);
			s2pool(&(v->str));
			break;
		case SV_STACK:
			count = (dollar_zlevel() - 1);
			MV_FORCE_MVAL(v, count);
			break;
		case SV_ZERROR:
			v->mvtype = MV_STR;
			v->str = dollar_zerror.str;
			s2pool(&(v->str));
			break;
		case SV_ZYERROR:
			v->mvtype = MV_STR;
			v->str = dollar_zyerror.str;
			s2pool(&(v->str));
			break;
		case SV_ZINTERRUPT:
			v->mvtype = MV_STR;
			v->str = dollar_zinterrupt.str;
			s2pool(&(v->str));
			break;
		case SV_ZININTERRUPT:
			MV_FORCE_MVAL(v, dollar_zininterrupt);
			break;
		case SV_ZJOB:
			MV_FORCE_UMVAL(v, dollar_zjob);
			break;
		case SV_ZDATE_FORM:
			MV_FORCE_MVAL(v, TREF(zdate_form));
			break;
		case SV_ZTEXIT:
			*v = dollar_ztexit;
			break;
		case SV_ZALLOCSTOR:
			ucount = (gtm_uint64_t)totalAlloc + (gtm_uint64_t)totalAllocGta;
			ui82mval(v, ucount);
			break;
		case SV_ZREALSTOR:
			ucount = (gtm_uint64_t)totalRmalloc + (gtm_uint64_t)totalRallocGta;
			ui82mval(v, ucount);
			break;
		case SV_ZUSEDSTOR:
			ucount = (gtm_uint64_t)totalUsed + (gtm_uint64_t)totalUsedGta;
			ui82mval(v, ucount);
			break;
		case SV_ZCHSET:
			v->mvtype = MV_STR;
			v->str = dollar_zchset;
			break;
		case SV_ZPATNUMERIC:
			v->mvtype = MV_STR;
			v->str = dollar_zpatnumeric;
			break;
		case SV_ZTNAME:
		case SV_ZTCODE:		/* deprecated */
#			ifdef GTM_TRIGGER
			if (NULL == dollar_ztname)
				memcpy(v, &literal_null, SIZEOF(mval));
			else
			{
				v->mvtype = MV_STR;
				v->str.addr = dollar_ztname->addr;
				v->str.len = dollar_ztname->len;
			}
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTDATA:
#			ifdef GTM_TRIGGER
			/* Value comes from GT.M, but it might be numeric and need conversion to a string */
			assert(!dollar_ztdata || MV_DEFINED(dollar_ztdata));
			if (NULL != dollar_ztdata)
				MV_FORCE_STR(dollar_ztdata);
			memcpy(v, (NULL != dollar_ztdata) ? dollar_ztdata : &literal_null, SIZEOF(mval));
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTDELIM:
#			ifdef GTM_TRIGGER
			assert(!dollar_ztdelim || MV_DEFINED(dollar_ztdelim));
			if (NULL == dollar_ztdelim || !(MV_STR & dollar_ztdelim->mvtype) || (0 == dollar_ztdelim->str.len))
				memcpy(v, &literal_null, SIZEOF(mval));
			else
				memcpy(v, dollar_ztdelim, SIZEOF(mval));
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTOLDVAL:
#			ifdef GTM_TRIGGER
			/* Value comes from GT.M, but it might be numeric and need conversion to a string */
			assert(!dollar_ztoldval || MV_DEFINED(dollar_ztoldval));
			if (NULL != dollar_ztoldval)
				MV_FORCE_STR(dollar_ztoldval);
			memcpy(v, (NULL != dollar_ztoldval) ? dollar_ztoldval : &literal_null, SIZEOF(mval));
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTRIGGEROP:
#			ifdef GTM_TRIGGER
			/* Value comes from GT.M, but assert it's a string */
			assert(!dollar_ztriggerop || (MV_STR & dollar_ztriggerop->mvtype));
			memcpy(v, (NULL != dollar_ztriggerop) ? dollar_ztriggerop : &literal_null, SIZEOF(mval));
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTUPDATE:
#			ifdef GTM_TRIGGER
			/* Value comes from GT.M, but if there were no delims involved, the value will be undefined, and
			 * we return a "literal_null".
			 */
			memcpy(v, ((NULL != dollar_ztupdate && (MV_STR & dollar_ztupdate->mvtype)) ? dollar_ztupdate
				   : &literal_null), SIZEOF(mval));
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTVALUE:
#			ifdef GTM_TRIGGER
			/* Value comes from user-land so make sure things are proper */
			assert(!dollar_ztvalue || MV_DEFINED(dollar_ztvalue));
			if (NULL != dollar_ztvalue)
				MV_FORCE_STR(dollar_ztvalue);
			memcpy(v, (NULL != dollar_ztvalue) ? dollar_ztvalue : &literal_null, SIZEOF(mval));
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTWORMHOLE:
#			ifdef GTM_TRIGGER
			/* Value comes from user-land so make sure things are proper */
			mvp = &dollar_ztwormhole;
			if (MV_DEFINED(mvp))
			{
				MV_FORCE_STR(mvp);
				memcpy(v, mvp, SIZEOF(mval));
			} else
				memcpy(v, &literal_null, SIZEOF(mval));
			ztwormhole_used = TRUE;
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTSLATE:
#			ifdef GTM_TRIGGER
			/* Value comes from user-land so make sure things are proper */
			assert(MV_DEFINED((&dollar_ztslate)));
			mvp = &dollar_ztslate;
			MV_FORCE_STR(mvp);
			memcpy(v, mvp, SIZEOF(mval));
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZTLEVEL:
#			ifdef GTM_TRIGGER
			MV_FORCE_MVAL(v, gtm_trigger_depth);
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZONLNRLBK:
#			ifdef UNIX
			count = TREF(dollar_zonlnrlbk);
			MV_FORCE_MVAL(v, count);
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZCLOSE:
#			ifdef UNIX
			count = TREF(dollar_zclose);
			MV_FORCE_MVAL(v, count);
			break;
#			else
			rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_UNIMPLOP);
#			endif
		case SV_ZKEY:
			get_dlr_zkey(v);
			break;
		default:
			assertpro(FALSE);
	}
}