148 lines
5.2 KiB
C
148 lines
5.2 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2013 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 <stdarg.h>
|
|
#include "gtm_stdio.h"
|
|
#include "gtm_string.h"
|
|
|
|
#include "lv_val.h"
|
|
#include <rtnhdr.h>
|
|
#include "mv_stent.h"
|
|
#include "stack_frame.h"
|
|
#include "op.h"
|
|
#include "gdsroot.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "alias.h"
|
|
#include "compiler.h"
|
|
#include "parm_pool.h"
|
|
|
|
GBLREF mv_stent *mv_chain;
|
|
GBLREF unsigned char *stackbase, *stacktop, *msp, *stackwarn;
|
|
GBLREF symval *curr_symval;
|
|
GBLREF stack_frame *frame_pointer;
|
|
|
|
error_def(ERR_ACTLSTTOOLONG);
|
|
error_def(ERR_STACKCRIT);
|
|
error_def(ERR_STACKOFLOW);
|
|
|
|
void op_bindparm(UNIX_ONLY_COMMA(int frmc) int frmp_arg, ...)
|
|
{
|
|
va_list var;
|
|
uint4 mask;
|
|
register lv_val *a;
|
|
var_tabent *parm_name;
|
|
int i;
|
|
int frmp; /* formal argument pointer */
|
|
VMS_ONLY(int frmc;) /* formal argument count */
|
|
int actc;
|
|
unsigned int *prev_count_ptr;
|
|
unsigned int prev_count;
|
|
boolean_t error = FALSE;
|
|
lv_val **actp; /* actual pointer */
|
|
lv_val *new_var;
|
|
mvs_ntab_struct *ntab;
|
|
ht_ent_mname *tabent, **htepp;
|
|
parm_slot *curr_slot;
|
|
DBGRFCT_ONLY(mident_fixed vname;)
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
frmp = frmp_arg;
|
|
VMS_ONLY(va_count(frmc);)
|
|
if (TREF(parm_pool_ptr))
|
|
{
|
|
curr_slot = PARM_CURR_SLOT;
|
|
prev_count_ptr = &((*(curr_slot - 1)).mask_and_cnt.actualcnt);
|
|
prev_count = *prev_count_ptr;
|
|
/* If we were dealing with a new job, then push_parm would not have been called if the number of
|
|
* actuals was 0; so, by checking for proper frame value stored in the parameter pool we ensure
|
|
* that we are not looking at some uninitialized value here. Note that although we protect against
|
|
* fall-throughs into labels with a formallist now, in case two consecutive invocations to
|
|
* op_bindparm happen without a push_parm in between, do not attempt to use a previously utilized
|
|
* parameter set.
|
|
*/
|
|
if ((PARM_ACT_FRAME(curr_slot, prev_count) != frame_pointer) || (SAFE_TO_OVWRT <= prev_count))
|
|
actc = 0;
|
|
else
|
|
{ /* Acquire mask, actual count, and pointer to actual list from the parameter pool. */
|
|
mask = (*(curr_slot - 1)).mask_and_cnt.mask;
|
|
actc = prev_count;
|
|
if (0 == (TREF(parm_pool_ptr))->start_idx)
|
|
actp = &((*(TREF(parm_pool_ptr))->parms).actuallist);
|
|
else
|
|
actp = &((*(curr_slot - SLOTS_NEEDED_FOR_SET(actc))).actuallist);
|
|
}
|
|
} else
|
|
/* If the parameter pool is uninitialized, there are no parameters we can bind. */
|
|
return;
|
|
assert(0 <= frmc);
|
|
/* This would also guarantee that actc > 0. */
|
|
if (actc > frmc)
|
|
{
|
|
error = TRUE;
|
|
*prev_count_ptr += SAFE_TO_OVWRT;
|
|
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ACTLSTTOOLONG);
|
|
}
|
|
VAR_START(var, frmp_arg);
|
|
for (i = 0; i < frmc; i++, frmp = va_arg(var, int4), actp++)
|
|
{
|
|
if (i >= actc)
|
|
{ /* "Extra" formallist parm, not part of actual list - Needs a PVAL (implicit NEW) as doesn't have one yet */
|
|
PUSH_MV_STENT(MVST_PVAL);
|
|
new_var = mv_chain->mv_st_cont.mvs_pval.mvs_val = lv_getslot(curr_symval);
|
|
LVVAL_INIT(new_var, curr_symval);
|
|
ntab = &mv_chain->mv_st_cont.mvs_pval.mvs_ptab;
|
|
ntab->hte_addr = NULL; /* In case table gets expanded before we set it below */
|
|
} else if (!(mask & 1 << i))
|
|
{ /* Actual list parm - already has PVAL built by push_parm() */
|
|
ntab = &((mvs_pval_struct *)*actp)->mvs_ptab;
|
|
new_var = ((mvs_pval_struct *)*actp)->mvs_val;
|
|
} else
|
|
{ /* Actual list parm - dotted pass-by-reference parm */
|
|
PUSH_MV_STENT(MVST_NTAB);
|
|
ntab = &mv_chain->mv_st_cont.mvs_ntab;
|
|
new_var = *actp;
|
|
/* This sort of parameter is considered an alias */
|
|
assert(0 < new_var->stats.trefcnt);
|
|
INCR_TREFCNT(new_var);
|
|
}
|
|
htepp = (ht_ent_mname **)&frame_pointer->l_symtab[frmp]; /* address of l_symtab entry */
|
|
parm_name = &(((var_tabent *)frame_pointer->vartab_ptr)[frmp]);
|
|
assert(0 <= frmp && frmp < frame_pointer->vartab_len);
|
|
if (add_hashtab_mname_symval(&curr_symval->h_symtab, parm_name, NULL, &tabent))
|
|
lv_newname(tabent, curr_symval);
|
|
assert(tabent->value);
|
|
DEBUG_ONLY(ntab->nam_addr = parm_name); /* address of var_tabent */
|
|
ntab->hte_addr = tabent; /* save hash table entry addr */
|
|
ntab->save_value = (lv_val *)tabent->value; /* address of original lv_val */
|
|
DBGRFCT_ONLY(
|
|
memcpy(vname.c, tabent->key.var_name.addr, tabent->key.var_name.len);
|
|
vname.c[tabent->key.var_name.len] = '\0';
|
|
);
|
|
DBGRFCT((stderr, "op_bindparm: Resetting var '%s' with hte 0x"lvaddr" from 0x"lvaddr" to 0x"lvaddr"\n",
|
|
&vname.c, tabent, tabent->value, new_var));
|
|
tabent->value = (char *)new_var;
|
|
*htepp = tabent;
|
|
}
|
|
va_end(var);
|
|
/* Incrementing the actual count in parameter pool by a special value, so that we know that it is safe to
|
|
* overwrite the current params and there is no need to save them; if an error occurred earlier or actc
|
|
* is 0, then this addition has already been taken care of above.
|
|
*/
|
|
if (actc && !error)
|
|
*prev_count_ptr += SAFE_TO_OVWRT;
|
|
}
|