139 lines
3.8 KiB
C
139 lines
3.8 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 "compiler.h"
|
|
#include "opcode.h"
|
|
#include "indir_enum.h"
|
|
#include "toktyp.h"
|
|
#include "mdq.h"
|
|
#include "mmemory.h"
|
|
#include "advancewindow.h"
|
|
#include "cmd.h"
|
|
#include "fullbool.h"
|
|
|
|
error_def(ERR_INDEXTRACHARS);
|
|
error_def(ERR_SPOREOL);
|
|
|
|
typedef struct jmpchntype
|
|
{
|
|
struct
|
|
{
|
|
struct jmpchntype *fl,*bl;
|
|
} link;
|
|
triple *jmptrip;
|
|
} jmpchn;
|
|
|
|
int m_if(void)
|
|
{
|
|
triple *ref0, *ref1, *ref2, *jmpref, ifpos_in_chain, *triptr;
|
|
oprtype x, y, *ta_opr;
|
|
boolean_t first_time, t_set, is_commarg;
|
|
jmpchn *jmpchain, *nxtjmp;
|
|
DCL_THREADGBL_ACCESS;
|
|
|
|
SETUP_THREADGBL_ACCESS;
|
|
ifpos_in_chain = TREF(pos_in_chain);
|
|
jmpchain = (jmpchn *)mcalloc(SIZEOF(jmpchn));
|
|
dqinit(jmpchain, link);
|
|
if (TK_EOL == TREF(window_token))
|
|
return TRUE;
|
|
is_commarg = (1 == TREF(last_source_column));
|
|
FOR_END_OF_SCOPE(0, x);
|
|
assert(INDR_REF == x.oprclass);
|
|
if (TK_SPACE == TREF(window_token))
|
|
{
|
|
jmpref = newtriple(OC_JMPTCLR);
|
|
jmpref->operand[0] = x;
|
|
nxtjmp = (jmpchn *)mcalloc(SIZEOF(jmpchn));
|
|
nxtjmp->jmptrip = jmpref;
|
|
dqins(jmpchain, link, nxtjmp);
|
|
} else
|
|
{
|
|
first_time = TRUE;
|
|
for (;;)
|
|
{
|
|
ta_opr = (oprtype *)mcalloc(SIZEOF(oprtype));
|
|
if (!bool_expr(TRUE, ta_opr))
|
|
return FALSE;
|
|
if (((OC_JMPNEQ == (ref0 = (TREF(curtchain))->exorder.bl)->opcode))
|
|
&& (OC_COBOOL == (ref1 = ref0->exorder.bl)->opcode)
|
|
&& (OC_INDGLVN == (ref2 = ref1->exorder.bl)->opcode))
|
|
{ /* short-circuit only optimization that turns a trailing INDGLVN COBOOL into separate indirect IF */
|
|
dqdel(ref0, exorder);
|
|
ref1->opcode = OC_JMPTSET;
|
|
ref1->operand[0] = put_indr(ta_opr);
|
|
ref2->opcode = OC_COMMARG;
|
|
ref2->operand[1] = put_ilit((mint)indir_if);
|
|
}
|
|
t_set = (OC_JMPTSET == (TREF(curtchain))->exorder.bl->opcode);
|
|
if (!t_set)
|
|
newtriple(OC_CLRTEST);
|
|
if (TREF(expr_start) != TREF(expr_start_orig) && (OC_NOOP != (TREF(expr_start))->opcode))
|
|
{
|
|
assert((OC_GVSAVTARG == (TREF(expr_start))->opcode));
|
|
if ((OC_GVRECTARG != (TREF(curtchain))->exorder.bl->opcode)
|
|
|| ((TREF(curtchain))->exorder.bl->operand[0].oprval.tref != TREF(expr_start)))
|
|
newtriple(OC_GVRECTARG)->operand[0] = put_tref(TREF(expr_start));
|
|
}
|
|
jmpref = newtriple(OC_JMP);
|
|
jmpref->operand[0] = x;
|
|
nxtjmp = (jmpchn *)mcalloc(SIZEOF(jmpchn));
|
|
nxtjmp->jmptrip = jmpref;
|
|
dqins(jmpchain, link, nxtjmp);
|
|
tnxtarg(ta_opr);
|
|
if (first_time)
|
|
{
|
|
if (!t_set)
|
|
newtriple(OC_SETTEST);
|
|
if (TREF(expr_start) != TREF(expr_start_orig) && (OC_NOOP != (TREF(expr_start))->opcode))
|
|
{
|
|
assert((OC_GVSAVTARG == (TREF(expr_start))->opcode));
|
|
if ((OC_GVRECTARG != (TREF(curtchain))->exorder.bl->opcode)
|
|
|| ((TREF(curtchain))->exorder.bl->operand[0].oprval.tref != TREF(expr_start)))
|
|
newtriple(OC_GVRECTARG)->operand[0] = put_tref(TREF(expr_start));
|
|
}
|
|
first_time = FALSE;
|
|
}
|
|
if (TK_COMMA != TREF(window_token))
|
|
break;
|
|
advancewindow();
|
|
}
|
|
}
|
|
if (is_commarg)
|
|
{
|
|
while (TK_SPACE == TREF(window_token)) /* Eat up trailing white space */
|
|
advancewindow();
|
|
if (TK_EOL != TREF(window_token))
|
|
{
|
|
stx_error(ERR_INDEXTRACHARS);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
if ((TK_EOL != TREF(window_token)) && (TK_SPACE != TREF(window_token)))
|
|
{
|
|
stx_error(ERR_SPOREOL);
|
|
return FALSE;
|
|
}
|
|
if (!linetail())
|
|
{ tnxtarg(&x);
|
|
dqloop(jmpchain,link,nxtjmp)
|
|
{
|
|
ref1 = nxtjmp->jmptrip;
|
|
ref1->operand[0] = x;
|
|
}
|
|
TREF(pos_in_chain) = ifpos_in_chain;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|