520 lines
13 KiB
C
520 lines
13 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2012 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"
|
|
|
|
#include "gdsroot.h"
|
|
#include "gdsblk.h"
|
|
#include "gdskill.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "filestruct.h"
|
|
#include "gdscc.h"
|
|
#include "io.h"
|
|
#include "iottdef.h"
|
|
#include "jnl.h"
|
|
#include "rtnhdr.h"
|
|
#include "stack_frame.h"
|
|
#include "stringpool.h"
|
|
#include "svnames.h"
|
|
#include "buddy_list.h" /* needed for tp.h */
|
|
#include "hashtab_int4.h" /* needed for tp.h */
|
|
#include "tp.h"
|
|
#include "error.h"
|
|
#include "op.h"
|
|
#include "mvalconv.h"
|
|
#include "zroutines.h"
|
|
#include "getstorage.h"
|
|
#include "get_command_line.h"
|
|
#include "getzposition.h"
|
|
#include "getzprocess.h"
|
|
#include "get_ret_targ.h"
|
|
#include "mv_stent.h"
|
|
#include "dollar_zlevel.h"
|
|
#include "gtmmsg.h"
|
|
#include "error_trap.h"
|
|
#include "setzdir.h"
|
|
#include "get_reference.h"
|
|
#include "dollar_quit.h"
|
|
#ifdef UNIX
|
|
#include "iormdef.h"
|
|
#endif
|
|
|
|
#define ESC_OFFSET 4
|
|
#define MAX_COMMAND_LINE_LENGTH 255
|
|
|
|
GBLREF mval dollar_zproc;
|
|
GBLREF mval dollar_zdir;
|
|
GBLREF stack_frame *frame_pointer;
|
|
GBLREF mval dollar_estack_delta;
|
|
GBLREF spdesc stringpool;
|
|
GBLREF io_pair io_curr_device;
|
|
GBLREF io_log_name *io_root_log_name;
|
|
GBLREF io_log_name *dollar_principal;
|
|
GBLREF mval dollar_ztrap;
|
|
GBLREF mval dollar_zgbldir;
|
|
GBLREF mval dollar_job;
|
|
GBLREF uint4 dollar_zjob;
|
|
GBLREF mval dollar_zstatus;
|
|
GBLREF mval dollar_zstep;
|
|
GBLREF int dollar_zmaxtptime;
|
|
GBLREF mval dollar_zsource;
|
|
GBLREF int4 dollar_zsystem;
|
|
GBLREF int4 dollar_zeditor;
|
|
GBLREF uint4 dollar_tlevel;
|
|
GBLREF uint4 dollar_trestart;
|
|
GBLREF mval dollar_etrap;
|
|
GBLREF mval dollar_zerror;
|
|
GBLREF mval dollar_zyerror;
|
|
GBLREF mval dollar_system;
|
|
GBLREF mval dollar_zinterrupt;
|
|
GBLREF boolean_t dollar_zininterrupt;
|
|
GBLREF int4 zdir_form;
|
|
GBLREF boolean_t ztrap_explicit_null; /* whether $ZTRAP was explicitly set to NULL in this frame */
|
|
GBLREF mval dollar_ztexit;
|
|
GBLREF size_t totalAlloc;
|
|
GBLREF size_t totalRmalloc;
|
|
GBLREF size_t totalUsed;
|
|
GBLREF size_t totalAllocGta;
|
|
GBLREF size_t totalRallocGta;
|
|
GBLREF size_t totalUsedGta;
|
|
GBLREF mstr dollar_zchset;
|
|
GBLREF mstr dollar_zpatnumeric;
|
|
GBLREF boolean_t dollar_zquit_anyway;
|
|
#ifdef GTM_TRIGGER
|
|
GBLREF mstr *dollar_ztname;
|
|
GBLREF mval *dollar_ztdata;
|
|
GBLREF mval *dollar_ztoldval;
|
|
GBLREF mval *dollar_ztriggerop;
|
|
GBLREF mval dollar_ztslate;
|
|
GBLREF mval *dollar_ztupdate;
|
|
GBLREF mval *dollar_ztvalue;
|
|
GBLREF mval dollar_ztwormhole;
|
|
GBLREF int4 gtm_trigger_depth;
|
|
GBLREF boolean_t ztwormhole_used; /* TRUE if $ztwormhole was used by trigger code */
|
|
#endif
|
|
|
|
error_def(ERR_TEXT);
|
|
error_def(ERR_UNIMPLOP);
|
|
error_def(ERR_ZDIROUTOFSYNC);
|
|
|
|
LITREF mval literal_zero, literal_one, literal_null;
|
|
LITREF char gtm_release_name[];
|
|
LITREF int4 gtm_release_name_len;
|
|
|
|
void op_svget(int varnum, mval *v)
|
|
{
|
|
io_log_name *tl;
|
|
int count;
|
|
unsigned int ucount;
|
|
char *c1, *c2;
|
|
mval *mvp;
|
|
# ifdef UNIX
|
|
d_rm_struct *d_rm;
|
|
# endif
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
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(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, 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 = (unsigned int)(totalAlloc + totalAllocGta);
|
|
MV_FORCE_UMVAL(v, ucount);
|
|
break;
|
|
case SV_ZREALSTOR:
|
|
ucount = (unsigned int)(totalRmalloc + totalRallocGta);
|
|
MV_FORCE_UMVAL(v, ucount);
|
|
break;
|
|
case SV_ZUSEDSTOR:
|
|
ucount = (unsigned int)(totalUsed + totalUsedGta);
|
|
MV_FORCE_UMVAL(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(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(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(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(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(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(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(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(VARLSTCNT(1) ERR_UNIMPLOP);
|
|
# endif
|
|
case SV_ZTLEVEL:
|
|
# ifdef GTM_TRIGGER
|
|
MV_FORCE_MVAL(v, gtm_trigger_depth);
|
|
break;
|
|
# else
|
|
rts_error(VARLSTCNT(1) ERR_UNIMPLOP);
|
|
# endif
|
|
case SV_ZONLNRLBK:
|
|
# ifdef UNIX
|
|
count = TREF(dollar_zonlnrlbk);
|
|
MV_FORCE_MVAL(v, count);
|
|
break;
|
|
# else
|
|
rts_error(VARLSTCNT(1) ERR_UNIMPLOP);
|
|
# endif
|
|
default:
|
|
GTMASSERT;
|
|
}
|
|
}
|