716 lines
22 KiB
C
716 lines
22 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2010, 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"
|
|
|
|
#ifdef GTM_TRIGGER
|
|
#include <errno.h>
|
|
#include "gtm_ctype.h"
|
|
#include "gtm_string.h"
|
|
#include "gtm_fcntl.h"
|
|
#include "gtm_unistd.h"
|
|
#include "gdsroot.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include <rtnhdr.h>
|
|
#include "gv_trigger.h"
|
|
#include "targ_alloc.h"
|
|
#include "filestruct.h"
|
|
#include "mv_stent.h" /* for COPY_SUBS_TO_GVCURRKEY macro */
|
|
#include "gvsub2str.h" /* for COPY_SUBS_TO_GVCURRKEY macro */
|
|
#include "format_targ_key.h" /* for COPY_SUBS_TO_GVCURRKEY macro */
|
|
#include "trigger.h"
|
|
#include "trigger_gbl_fill_xecute_buffer.h"
|
|
#include "trigger_scan_string.h"
|
|
#include "trigger_select_protos.h"
|
|
#include "trigger_user_name.h"
|
|
#include "change_reg.h"
|
|
#include "gvcst_protos.h"
|
|
#include "op.h"
|
|
#include "mupip_exit.h"
|
|
#include "zshow.h"
|
|
#include "util.h"
|
|
#include "compiler.h"
|
|
#include "mvalconv.h"
|
|
#include "op_tcommit.h"
|
|
#include "gdscc.h" /* needed for tp.h */
|
|
#include "gdskill.h" /* needed for tp.h */
|
|
#include "buddy_list.h" /* needed for tp.h */
|
|
#include "hashtab_int4.h" /* needed for tp.h */
|
|
#include "jnl.h" /* needed for tp.h */
|
|
#include "tp.h"
|
|
#include "t_retry.h"
|
|
#include "io_params.h"
|
|
#include "min_max.h" /* Needed for MIN */
|
|
#include "gtmimagename.h"
|
|
#include "gtmio.h"
|
|
#include "have_crit.h"
|
|
|
|
GBLREF sgmnt_addrs *cs_addrs;
|
|
GBLREF sgmnt_data_ptr_t cs_data;
|
|
GBLREF gd_region *gv_cur_region;
|
|
GBLREF gv_namehead *gv_target;
|
|
GBLREF gv_key *gv_currkey;
|
|
GBLREF gd_addr *gd_header;
|
|
GBLREF gv_key *gv_altkey;
|
|
GBLREF io_pair io_curr_device;
|
|
GBLREF io_pair io_std_device; /* standard device */
|
|
GBLREF sgm_info *sgm_info_ptr;
|
|
GBLREF int (*op_open_ptr)(mval *v, mval *p, int t, mval *mspace);
|
|
|
|
LITREF mval literal_hasht;
|
|
LITREF mval literal_zero;
|
|
LITREF mval literal_ten;
|
|
LITREF char *trigger_subs[];
|
|
|
|
#define TRIGGER_NAME_COMMENT "trigger name: "
|
|
#define TRIGGER_CYCLE_COMMENT " cycle: "
|
|
|
|
#define NAM_LEN(PTR, LEN) MIN(STRLEN((PTR)), (LEN))
|
|
|
|
#define COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(OUT_BUFF, OUT_PTR, VAL, VAL_LEN) \
|
|
{ \
|
|
mval op_val; \
|
|
\
|
|
assert(MAX_BUFF_SIZE >= VAL_LEN); \
|
|
if ((INTCAST(OUT_PTR - OUT_BUFF) + VAL_LEN) > MAX_BUFF_SIZE) \
|
|
{ \
|
|
STR2MVAL(op_val, OUT_BUFF, (unsigned int)(OUT_PTR - OUT_BUFF)); \
|
|
op_write(&op_val); \
|
|
io_curr_device.out->dollar.x = 0; \
|
|
OUT_PTR = OUT_BUFF; \
|
|
} \
|
|
memcpy(OUT_PTR, (const void *)VAL, VAL_LEN); \
|
|
OUT_PTR += VAL_LEN; \
|
|
}
|
|
|
|
#define COPY_SUBSCRIPT(OUT_BUFF, OUT_PTR, CHPTR, LEN_LEFT, IS_TYPE) \
|
|
{ \
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(OUT_BUFF, OUT_PTR, CHPTR, 1); \
|
|
CHPTR++; \
|
|
LEN_LEFT--; \
|
|
while ((0 < LEN_LEFT) && IS_TYPE(*CHPTR)) \
|
|
{ \
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(OUT_BUFF, OUT_PTR, CHPTR, 1); \
|
|
CHPTR++; \
|
|
LEN_LEFT--; \
|
|
} \
|
|
}
|
|
|
|
#define MAKE_ZWR_STR(STR, STR_LEN, OUT_START, OUT_STR) \
|
|
{ \
|
|
int lcl_len; \
|
|
unsigned char tmp_buff[MAX_ZWR_EXP_RATIO * MAX_BUFF_SIZE]; \
|
|
\
|
|
format2zwr((sm_uc_ptr_t)STR, STR_LEN, tmp_buff, &lcl_len); \
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(OUT_START, OUT_STR, tmp_buff, lcl_len); \
|
|
}
|
|
|
|
#define CHECK_FOR_M_NAME(START, PTR, LEN, STR, ERR, MAX_LEN) \
|
|
{ \
|
|
int lcl_len; \
|
|
int cur_len; \
|
|
\
|
|
assert(0 < MAX_LEN); \
|
|
if (!ISALPHA_ASCII(*PTR) && ('%' != *PTR)) \
|
|
{ \
|
|
lcl_len = STRLEN(START); \
|
|
CONV_STR_AND_PRINT(STR, lcl_len, START); \
|
|
ERR = TRIG_FAILURE; \
|
|
continue; \
|
|
} \
|
|
PTR++; \
|
|
LEN--; \
|
|
cur_len = 1; \
|
|
while ((0 < LEN) && ISALNUM_ASCII(*PTR)) \
|
|
{ \
|
|
if (MAX_LEN < ++cur_len) \
|
|
break; \
|
|
PTR++; \
|
|
LEN--; \
|
|
} \
|
|
}
|
|
|
|
#define INVALID_NAME_ERROR(ERR_STR, PTR, ERR_VAR, POS) \
|
|
{ \
|
|
int lcl_len; \
|
|
\
|
|
lcl_len = STRLEN(PTR); \
|
|
CONV_STR_AND_PRINT(ERR_STR, lcl_len, PTR); \
|
|
select_status = TRIG_FAILURE; \
|
|
}
|
|
|
|
error_def(ERR_MUNOACTION);
|
|
error_def(ERR_MUPCLIERR);
|
|
error_def(ERR_TRIGDEFBAD);
|
|
error_def(ERR_MUPCLIERR);
|
|
error_def(ERR_MUNOACTION);
|
|
|
|
|
|
STATICDEF char *triggerfile_quals[] = {"-name=", "", "-commands=", "-options=", "-delim=", "-zdelim=", "-pieces=", "-xecute="};
|
|
|
|
STATICFNDEF void write_subscripts(char *out_rec, char **out_ptr, char **sub_ptr, int *sub_len)
|
|
{
|
|
char *out_p, *ptr, *dst_ptr;
|
|
int str_len;
|
|
uint4 len_left, dst_len, len;
|
|
char dst[MAX_GVSUBS_LEN];
|
|
|
|
len_left = *sub_len;
|
|
ptr = *sub_ptr;
|
|
out_p = *out_ptr;
|
|
while (0 < len_left)
|
|
{
|
|
if (ISDIGIT_ASCII(*ptr) || ('-' == *ptr))
|
|
{
|
|
COPY_SUBSCRIPT(out_rec, out_p, ptr, len_left, ISDIGIT_ASCII);
|
|
} else if (ISALPHA_ASCII(*ptr) || ('%' == *ptr))
|
|
{
|
|
COPY_SUBSCRIPT(out_rec, out_p, ptr, len_left, ISALNUM_ASCII);
|
|
} else if ('"' == *ptr)
|
|
{
|
|
len = len_left;
|
|
trigger_scan_string(ptr, &len_left, dst, &dst_len);
|
|
MAKE_ZWR_STR(dst, dst_len, out_rec, out_p);
|
|
len_left--; /* Need to skip the trailing " */
|
|
ptr += (len - len_left);
|
|
} else
|
|
{
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_p, ptr, 1);
|
|
ptr++;
|
|
len_left--;
|
|
}
|
|
}
|
|
*sub_len = len_left;
|
|
*sub_ptr = ptr;
|
|
*out_ptr = out_p;
|
|
}
|
|
|
|
STATICFNDEF void write_out_trigger(char *gbl_name, uint4 gbl_name_len, uint4 file_name_len, mval *op_val, int nam_indx)
|
|
{
|
|
mval data_val;
|
|
char out_rec[MAX_BUFF_SIZE];
|
|
char *out_rec_ptr;
|
|
char *ptr1, *ptr2;
|
|
mname_entry gvent;
|
|
mval mi, trigger_count, trigger_value;
|
|
mval *mv_trig_cnt_ptr;
|
|
boolean_t multi_line;
|
|
boolean_t have_value, multi_record;
|
|
int count;
|
|
int indx, sub_indx;
|
|
int4 skip_chars;
|
|
int sub_len;
|
|
char *sub_ptr;
|
|
char *tmp_str_ptr, tmp_string[MAX_SRCLINE];
|
|
uint4 tmp_str_len;
|
|
char cycle[MAX_DIGITS_IN_INT + 1];
|
|
unsigned char util_buff[MAX_TRIG_UTIL_LEN];
|
|
int4 util_len;
|
|
char *xecute_buff;
|
|
int4 xecute_len;
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
BUILD_HASHT_SUB_SUB_CURRKEY(gbl_name, gbl_name_len, LITERAL_HASHCOUNT, LITERAL_HASHCOUNT_LEN);
|
|
if (gvcst_get(&trigger_count))
|
|
{
|
|
BUILD_HASHT_SUB_SUB_CURRKEY(gbl_name, gbl_name_len, LITERAL_HASHLABEL, STRLEN(LITERAL_HASHLABEL));
|
|
if (!gvcst_get(&trigger_value))
|
|
{ /* There has to be a #LABEL */
|
|
if (CDB_STAGNATE > t_tries)
|
|
t_retry(cdb_sc_triggermod);
|
|
else
|
|
{
|
|
assert(FALSE);
|
|
rts_error(VARLSTCNT(8) ERR_TRIGDEFBAD, 6, gbl_name_len, gbl_name, gbl_name_len, gbl_name,
|
|
LEN_AND_LIT("\"#LABEL\""));
|
|
}
|
|
}
|
|
skip_chars = 1;
|
|
if ((trigger_value.str.len != STRLEN(HASHT_GBL_CURLABEL))
|
|
|| (0 != memcmp(trigger_value.str.addr, HASHT_GBL_CURLABEL, trigger_value.str.len)))
|
|
{
|
|
if ((1 == trigger_value.str.len) && ('1' == *trigger_value.str.addr))
|
|
/* 1 == #LABEL - No leading blank in xecute string */
|
|
skip_chars = 0;
|
|
}
|
|
mv_trig_cnt_ptr = &trigger_count;
|
|
count = MV_FORCE_INT(mv_trig_cnt_ptr);
|
|
BUILD_HASHT_SUB_SUB_CURRKEY(gbl_name, gbl_name_len, LITERAL_HASHCYCLE, LITERAL_HASHCYCLE_LEN);
|
|
if (!gvcst_get(&trigger_value))
|
|
{ /* There has to be a #CYCLE */
|
|
if (CDB_STAGNATE > t_tries)
|
|
t_retry(cdb_sc_triggermod);
|
|
else
|
|
{
|
|
assert(FALSE);
|
|
rts_error(VARLSTCNT(8) ERR_TRIGDEFBAD, 6, gbl_name_len, gbl_name, gbl_name_len, gbl_name,
|
|
LEN_AND_LIT("\"#CYCLE\""));
|
|
}
|
|
}
|
|
assert(MAX_DIGITS_IN_INT >= trigger_value.str.len);
|
|
memcpy(cycle, trigger_value.str.addr, trigger_value.str.len);
|
|
cycle[trigger_value.str.len] = '\0';
|
|
xecute_buff = NULL;
|
|
for (indx = 1; indx <= count; indx++)
|
|
{
|
|
if ((0 != nam_indx) && (indx != nam_indx))
|
|
continue;
|
|
MV_FORCE_MVAL(&mi, indx);
|
|
BUILD_HASHT_SUB_MSUB_SUB_CURRKEY(gbl_name, gbl_name_len, mi, trigger_subs[TRIGNAME_SUB],
|
|
STRLEN(trigger_subs[TRIGNAME_SUB]));
|
|
out_rec_ptr = out_rec;
|
|
if (gvcst_get(&trigger_value))
|
|
{
|
|
*out_rec_ptr++ = COMMENT_LITERAL;
|
|
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, TRIGGER_NAME_COMMENT,
|
|
STR_LIT_LEN(TRIGGER_NAME_COMMENT));
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, trigger_value.str.addr,
|
|
trigger_value.str.len);
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, TRIGGER_CYCLE_COMMENT,
|
|
STR_LIT_LEN(TRIGGER_CYCLE_COMMENT));
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, cycle, STRLEN(cycle));
|
|
STR2MVAL((*op_val), out_rec, (unsigned int)(out_rec_ptr - out_rec));
|
|
op_write(op_val);
|
|
op_wteol(1);
|
|
}
|
|
out_rec_ptr = out_rec;
|
|
*out_rec_ptr++ = '+';
|
|
*out_rec_ptr++ = '^';
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, gbl_name, gbl_name_len);
|
|
BUILD_HASHT_SUB_MSUB_SUB_CURRKEY(gbl_name, gbl_name_len, mi, trigger_subs[GVSUBS_SUB],
|
|
STRLEN(trigger_subs[GVSUBS_SUB]));
|
|
if (gvcst_get(&trigger_value))
|
|
{
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, "(", 1);
|
|
sub_ptr = trigger_value.str.addr;
|
|
sub_len = trigger_value.str.len;
|
|
write_subscripts(out_rec, &out_rec_ptr, &sub_ptr, &sub_len);
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, ")", 1);
|
|
}
|
|
for (sub_indx = 0; sub_indx < NUM_SUBS; sub_indx++)
|
|
{
|
|
if ((GVSUBS_SUB == sub_indx) || (CHSET_SUB == sub_indx))
|
|
continue;
|
|
BUILD_HASHT_SUB_MSUB_SUB_CURRKEY(gbl_name, gbl_name_len, mi, trigger_subs[sub_indx],
|
|
STRLEN(trigger_subs[sub_indx]));
|
|
have_value = gvcst_get(&trigger_value);
|
|
multi_record = FALSE;
|
|
if (!have_value && (XECUTE_SUB == sub_indx))
|
|
{
|
|
op_gvdata(&data_val);
|
|
multi_record = (literal_ten.m[0] == data_val.m[0]) && (literal_ten.m[1] == data_val.m[1]);
|
|
}
|
|
if (have_value || multi_record)
|
|
{
|
|
if (TRIGNAME_SUB == sub_indx)
|
|
{ /* Output name only if it is user defined */
|
|
BUILD_HASHT_SUB_MSUB_SUB_MSUB_CURRKEY(gbl_name, gbl_name_len, mi,
|
|
trigger_subs[sub_indx], STRLEN(trigger_subs[sub_indx]), mi);
|
|
if (!trigger_user_name(trigger_value.str.addr, trigger_value.str.len))
|
|
continue;
|
|
trigger_value.str.len--; /* Don't include trailing # */
|
|
}
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, " ", 1);
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, triggerfile_quals[sub_indx],
|
|
STRLEN(triggerfile_quals[sub_indx]));
|
|
switch (sub_indx)
|
|
{
|
|
case DELIM_SUB:
|
|
case ZDELIM_SUB:
|
|
MAKE_ZWR_STR(trigger_value.str.addr, trigger_value.str.len, out_rec,
|
|
out_rec_ptr);
|
|
break;
|
|
case XECUTE_SUB:
|
|
/* After the buffer is malloc-ed by trigger_gbl_fill_xecute_buffer(), the
|
|
* only exits from the inner loop have to go to the free() below. Exits
|
|
* from the outer loop happen before the buffer is malloc-ed. So no leaks
|
|
* by error returns. But just to make sure, let's assert that the buffer
|
|
* pointer is NULL.
|
|
*/
|
|
assert(NULL == xecute_buff);
|
|
xecute_buff = trigger_gbl_fill_xecute_buffer(gbl_name, gbl_name_len, &mi,
|
|
multi_record ? NULL : &trigger_value, &xecute_len);
|
|
multi_line = (NULL != memchr(xecute_buff, '\n', xecute_len));
|
|
assert(NULL != xecute_buff);
|
|
if (multi_line)
|
|
{
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr,
|
|
XTENDED_START, XTENDED_START_LEN);
|
|
} else
|
|
{
|
|
tmp_str_ptr = xecute_buff + skip_chars;
|
|
tmp_str_len = xecute_len - skip_chars;
|
|
MAKE_ZWR_STR(tmp_str_ptr, tmp_str_len, out_rec, out_rec_ptr);
|
|
}
|
|
break;
|
|
default:
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr,
|
|
trigger_value.str.addr,trigger_value.str.len);
|
|
}
|
|
}
|
|
}
|
|
/* we had better have an XECUTE STRING, probably should check some buddies */
|
|
assert(NULL != xecute_buff);
|
|
STR2MVAL((*op_val), out_rec, (unsigned int)(out_rec_ptr - out_rec));
|
|
op_write(op_val);
|
|
op_wteol(1);
|
|
if (multi_line)
|
|
{
|
|
ptr1 = xecute_buff;
|
|
do
|
|
{
|
|
ptr2 = memchr(ptr1, '\n', xecute_len);
|
|
out_rec_ptr = out_rec;
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, ptr1, UINTCAST(ptr2 - ptr1));
|
|
STR2MVAL((*op_val), out_rec, (unsigned int)(out_rec_ptr - out_rec));
|
|
op_write(op_val);
|
|
op_wteol(1);
|
|
ptr1 = ptr2 + 1;
|
|
} while (ptr1 < (xecute_buff + xecute_len));
|
|
out_rec_ptr = out_rec;
|
|
COPY_TO_OUTPUT_AND_WRITE_IF_NEEDED(out_rec, out_rec_ptr, XTENDED_STOP, XTENDED_STOP_LEN);
|
|
STR2MVAL((*op_val), out_rec, (unsigned int)(out_rec_ptr - out_rec));
|
|
op_write(op_val);
|
|
op_wteol(1);
|
|
}
|
|
if (NULL != xecute_buff)
|
|
{
|
|
free(xecute_buff);
|
|
xecute_buff = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
STATICFNDEF void write_gbls_or_names(char *gbl_name, uint4 gbl_name_len, uint4 file_name_len, mval *op_val, boolean_t trig_name)
|
|
{
|
|
char save_name[MAX_MIDENT_LEN], curr_name[MAX_MIDENT_LEN];
|
|
boolean_t wildcard;
|
|
char save_currkey[SIZEOF(gv_key) + DBKEYSIZE(MAX_KEY_SZ)];
|
|
gd_region *save_gv_cur_region;
|
|
gv_key *save_gv_currkey;
|
|
gv_namehead *hasht_tree, *save_gv_target;
|
|
sgm_info *save_sgm_info_ptr;
|
|
sgmnt_addrs *csa;
|
|
mname_entry gvent;
|
|
mstr ms_gbl_nam;
|
|
mval mv_curr_nam;
|
|
mval mi, trigger_count, trig_gbl;
|
|
mval *mv_trig_cnt_ptr, mv_trigger_val;
|
|
int indx, count;
|
|
char *ptr;
|
|
uint4 curr_name_len;
|
|
int trigvn_len;
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
memcpy(save_name, gbl_name, gbl_name_len);
|
|
wildcard = (NULL != (ptr = memchr(gbl_name, '*', gbl_name_len)));
|
|
if (wildcard)
|
|
{
|
|
*ptr = '\0';
|
|
gbl_name_len--;
|
|
assert(INTCAST(ptr - gbl_name) == gbl_name_len);
|
|
}
|
|
mv_trig_cnt_ptr = &trigger_count;
|
|
memcpy(curr_name, gbl_name, gbl_name_len);
|
|
curr_name_len = gbl_name_len;
|
|
STR2MVAL(mv_curr_nam, gbl_name, gbl_name_len);
|
|
while (TRUE)
|
|
{
|
|
if (0 != memcmp(curr_name, save_name, gbl_name_len))
|
|
break;
|
|
if (trig_name)
|
|
{
|
|
BUILD_HASHT_SUB_SUB_CURRKEY(LITERAL_HASHTNAME, STR_LIT_LEN(LITERAL_HASHTNAME), curr_name, curr_name_len);
|
|
if (!gvcst_get(&mv_trigger_val))
|
|
{
|
|
if (wildcard)
|
|
{
|
|
op_gvorder(&mv_curr_nam);
|
|
if (0 == mv_curr_nam.str.len)
|
|
break;
|
|
memcpy(curr_name, mv_curr_nam.str.addr, mv_curr_nam.str.len);
|
|
curr_name_len = mv_curr_nam.str.len;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
ptr = mv_trigger_val.str.addr;
|
|
trigvn_len = STRLEN(mv_trigger_val.str.addr);
|
|
ptr += trigvn_len + 1;
|
|
A2I(ptr, mv_trigger_val.str.addr + mv_trigger_val.str.len, indx);
|
|
STR2MVAL(trig_gbl, mv_trigger_val.str.addr, trigvn_len);
|
|
SAVE_TRIGGER_REGION_INFO;
|
|
ms_gbl_nam.addr = mv_trigger_val.str.addr;
|
|
ms_gbl_nam.len = trigvn_len;
|
|
GV_BIND_NAME_ONLY(gd_header, &ms_gbl_nam);
|
|
csa = gv_target->gd_csa;
|
|
SETUP_TRIGGER_GLOBAL;
|
|
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
|
|
} else
|
|
{
|
|
STR2MVAL(trig_gbl, curr_name, curr_name_len);
|
|
indx = 0;
|
|
}
|
|
write_out_trigger(trig_gbl.str.addr, trig_gbl.str.len, file_name_len, op_val, indx);
|
|
if (trig_name)
|
|
{
|
|
RESTORE_TRIGGER_REGION_INFO;
|
|
}
|
|
if (wildcard)
|
|
{
|
|
if (trig_name)
|
|
{
|
|
BUILD_HASHT_SUB_SUB_CURRKEY(LITERAL_HASHTNAME, STR_LIT_LEN(LITERAL_HASHTNAME), curr_name,
|
|
curr_name_len);
|
|
} else
|
|
{
|
|
BUILD_HASHT_SUB_CURRKEY(curr_name, curr_name_len);
|
|
}
|
|
op_gvorder(&mv_curr_nam);
|
|
if (0 == mv_curr_nam.str.len)
|
|
break;
|
|
memcpy(curr_name, mv_curr_nam.str.addr, mv_curr_nam.str.len);
|
|
curr_name_len = mv_curr_nam.str.len;
|
|
} else
|
|
break;
|
|
}
|
|
}
|
|
|
|
STATICFNDEF void dump_all_triggers(uint4 file_name_len, mval *op_val)
|
|
{
|
|
mval curr_gbl_name, val;
|
|
gd_region *reg;
|
|
sgmnt_addrs *csa;
|
|
mname_entry gvent;
|
|
gv_namehead *hasht_tree, *save_gvtarget;
|
|
char save_currkey[SIZEOF(gv_key) + DBKEYSIZE(MAX_KEY_SZ)];
|
|
char save_altkey[SIZEOF(gv_key) + DBKEYSIZE(MAX_KEY_SZ)];
|
|
gv_key *save_gv_currkey;
|
|
gv_key *save_gv_altkey;
|
|
unsigned char *key;
|
|
mval trigger_value;
|
|
int reg_index;
|
|
mstr gbl_name;
|
|
char global[MAX_MIDENT_LEN];
|
|
int gbl_len;
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
assert(NULL != gd_header);
|
|
save_gvtarget = gv_target;
|
|
for (reg_index = 0, reg = gd_header->regions; reg_index < gd_header->n_regions; reg_index++, reg++)
|
|
{
|
|
if (!reg->open)
|
|
gv_init_reg(reg);
|
|
gv_cur_region = reg;
|
|
change_reg();
|
|
csa = cs_addrs;
|
|
SETUP_TRIGGER_GLOBAL;
|
|
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
|
|
if (0 != gv_target->root)
|
|
{
|
|
op_gvdata(&val);
|
|
if ((literal_ten.m[0] == val.m[0]) && (literal_ten.m[1] == val.m[1]))
|
|
{ /* $DATA(^#t) is 10 - get first subscript (trigger's global) */
|
|
BUILD_HASHT_SUB_CURRKEY(LITERAL_MAXHASHVAL, STR_LIT_LEN(LITERAL_MAXHASHVAL));
|
|
while (TRUE)
|
|
{
|
|
op_gvorder(&curr_gbl_name);
|
|
if (0 == curr_gbl_name.str.len)
|
|
break;
|
|
gbl_len = curr_gbl_name.str.len;
|
|
memcpy(global, curr_gbl_name.str.addr, gbl_len);
|
|
write_out_trigger(global, gbl_len, file_name_len, op_val, 0);
|
|
BUILD_HASHT_SUB_CURRKEY(global, gbl_len);
|
|
}
|
|
} else
|
|
assert((literal_zero.m[0] == val.m[0]) && (literal_zero.m[1] == val.m[1]));
|
|
}
|
|
}
|
|
}
|
|
|
|
boolean_t trigger_select(char *select_list, uint4 select_list_len, char *file_name, uint4 file_name_len)
|
|
{
|
|
char *sel_ptr, *prev_ptr, *ptr1, *ptr2;
|
|
int gbl_len, prev_len;
|
|
mstr gbl_name;
|
|
sgmnt_addrs *csa;
|
|
gv_namehead *hasht_tree, *save_gvtarget;
|
|
char save_currkey[SIZEOF(gv_key) + DBKEYSIZE(MAX_KEY_SZ)];
|
|
char save_altkey[SIZEOF(gv_key) + DBKEYSIZE(MAX_KEY_SZ)];
|
|
gv_key *save_gv_currkey;
|
|
gv_key *save_gv_altkey;
|
|
gd_region *save_gv_cur_region;
|
|
char save_select_list[MAX_BUFF_SIZE];
|
|
mname_entry gvent;
|
|
mval trigger_value;
|
|
int len, len1, badpos;
|
|
int local_errno;
|
|
boolean_t trig_name;
|
|
gv_namehead *save_gv_target;
|
|
sgm_info *save_sgm_info_ptr;
|
|
boolean_t dump_all;
|
|
mval op_val, op_pars;
|
|
boolean_t select_status;
|
|
io_pair save_io_curr_device;
|
|
|
|
static readonly unsigned char open_params_list[] =
|
|
{
|
|
(unsigned char)iop_m,
|
|
(unsigned char)iop_noreadonly,
|
|
(unsigned char)iop_nowrap,
|
|
(unsigned char)iop_stream,
|
|
(unsigned char)iop_eol
|
|
};
|
|
static readonly unsigned char use_params[] =
|
|
{
|
|
(unsigned char)iop_nowrap,
|
|
(unsigned char)iop_eol
|
|
};
|
|
static readonly unsigned char no_param = (unsigned char)iop_eol;
|
|
|
|
/* make a local copy of the select list and use it to avoid string-pool problems */
|
|
if (MAX_BUFF_SIZE <= select_list_len)
|
|
return TRIG_FAILURE;
|
|
memcpy(save_select_list, select_list, select_list_len);
|
|
save_select_list[select_list_len] = '\0';
|
|
gvinit();
|
|
dump_all = FALSE;
|
|
prev_len = 0;
|
|
op_pars.mvtype = MV_STR;
|
|
op_val.mvtype = MV_STR;
|
|
if (0 == file_name_len)
|
|
{
|
|
op_pars.str.len = SIZEOF(use_params);
|
|
op_pars.str.addr = (char *)use_params;
|
|
if (IS_MUPIP_IMAGE)
|
|
{
|
|
PRINTF("\n");
|
|
FFLUSH(NULL);
|
|
op_val.str.len = io_std_device.out->trans_name->len;
|
|
op_val.str.addr = io_std_device.out->trans_name->dollar_io;
|
|
} else
|
|
{
|
|
op_val.str.len = io_curr_device.out->trans_name->len;
|
|
op_val.str.addr = io_curr_device.out->trans_name->dollar_io;
|
|
}
|
|
} else
|
|
{
|
|
op_pars.str.len = SIZEOF(open_params_list);
|
|
op_pars.str.addr = (char *)open_params_list;
|
|
op_val.str.len = file_name_len;
|
|
op_val.str.addr = (char *)file_name;
|
|
(*op_open_ptr)(&op_val, &op_pars, 0, 0);
|
|
}
|
|
save_io_curr_device = io_curr_device;
|
|
op_use(&op_val, &op_pars);
|
|
if (0 == select_list_len)
|
|
dump_all = TRUE;
|
|
else
|
|
{
|
|
for (ptr1 = save_select_list, len = select_list_len;
|
|
(NULL != (ptr2 = strchr(ptr1, '*'))) && (len > (len1 = INTCAST(ptr2 - ptr1)));
|
|
ptr1 = ptr2 + 1)
|
|
{ /* look for either a real "dump-it-all" *, an error *, or a wildcard * */
|
|
/* A "*" anywhere in the select list (at a place where a global name would be) is the same as only a "*" */
|
|
len -= (len1 + 1); /* Length after the "*" -- len1 is length before the "*" */
|
|
assert((0 <= len1) && (0 <= len));
|
|
if (dump_all = ((0 == len1) && (0 == len) && (ptr1 == save_select_list))
|
|
|| ((0 == len1) && (0 == len) && (',' == *(ptr2 - 1)))
|
|
|| ((0 == len1) && (0 < len) && (',' == *(ptr2 + 1)))
|
|
|| ((0 < len1) && (0 == len) && (',' == *(ptr2 - 1)))
|
|
|| ((0 < len1) && (0 < len) && (',' == *(ptr2 - 1)) && (',' == *(ptr2 + 1))))
|
|
break;
|
|
}
|
|
}
|
|
select_status = TRIG_SUCCESS;
|
|
if (dump_all)
|
|
dump_all_triggers(file_name_len, &op_val);
|
|
else
|
|
{
|
|
len = select_list_len;
|
|
sel_ptr = strtok(save_select_list, ",");
|
|
do
|
|
{
|
|
trig_name = ('^' != *sel_ptr);
|
|
ptr1 = sel_ptr;
|
|
len1 = STRLEN(ptr1);
|
|
if (!trig_name)
|
|
{
|
|
ptr1++;
|
|
len1--;
|
|
CHECK_FOR_M_NAME(sel_ptr, ptr1, len1, "Invalid global variable name in SELECT list: ",
|
|
select_status, MAX_MIDENT_LEN);
|
|
if ((0 != len1) && ((1 != len1) || ('*' != *ptr1)))
|
|
{
|
|
badpos = len1;
|
|
INVALID_NAME_ERROR("Invalid global variable name in SELECT list: ", sel_ptr,
|
|
select_status, badpos);
|
|
continue;
|
|
}
|
|
SAVE_TRIGGER_REGION_INFO;
|
|
gbl_len = NAM_LEN(sel_ptr + 1, (int)(ptr1 - sel_ptr) - 1);
|
|
ptr1 = sel_ptr + 1;
|
|
if ((prev_len != gbl_len) || (0 != memcmp(prev_ptr, ptr1, gbl_len)))
|
|
{
|
|
gbl_name.addr = ptr1;
|
|
gbl_name.len = gbl_len;
|
|
prev_ptr = ptr1;
|
|
prev_len = gbl_len;
|
|
GV_BIND_NAME_ONLY(gd_header, &gbl_name);
|
|
if ('*' == *(ptr1 + gbl_len))
|
|
gbl_name.len++;
|
|
}
|
|
csa = gv_target->gd_csa;
|
|
SETUP_TRIGGER_GLOBAL;
|
|
} else
|
|
{
|
|
if (len1 != (badpos = validate_input_trigger_name(ptr1, len1, NULL))) /* assignment is intended */
|
|
{ /* is the input name valid */
|
|
INVALID_NAME_ERROR("Invalid name entry in SELECT list: ",
|
|
sel_ptr, select_status, badpos);
|
|
continue;
|
|
}
|
|
if (TRIGNAME_SEQ_DELIM == *(sel_ptr + (len1 - 1)))
|
|
/* drop the trailing # sign */
|
|
len1--;
|
|
gbl_name.addr = sel_ptr;
|
|
gbl_name.len = len1;
|
|
SAVE_TRIGGER_REGION_INFO;
|
|
SWITCH_TO_DEFAULT_REGION;
|
|
}
|
|
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
|
|
if (0 != gv_target->root)
|
|
write_gbls_or_names(gbl_name.addr, gbl_name.len, file_name_len, &op_val, trig_name);
|
|
RESTORE_TRIGGER_REGION_INFO;
|
|
} while (NULL != (sel_ptr = strtok(NULL, ","))); /* Embedded assignment is intended */
|
|
}
|
|
if (0 != file_name_len)
|
|
{
|
|
op_val.mvtype = op_pars.mvtype = MV_STR;
|
|
op_val.str.addr = (char *)file_name;;
|
|
op_val.str.len = file_name_len;
|
|
op_pars.str.len = SIZEOF(no_param);
|
|
op_pars.str.addr = (char *)&no_param;
|
|
op_close(&op_val, &op_pars);
|
|
/* Return back to the current device */
|
|
io_curr_device = save_io_curr_device;
|
|
}
|
|
return select_status;
|
|
}
|
|
|
|
#endif
|