fis-gtm/sr_port/str2gvargs.c

281 lines
6.8 KiB
C

/****************************************************************
* *
* Copyright 2002, 2010 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_ctype.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "subscript.h"
#include "str2gvargs.h"
#include "zshow.h"
#ifdef UNICODE_SUPPORTED
#include "gtm_utf8.h"
#endif
#ifdef GTM_TRIGGER
#include "rtnhdr.h"
#include "gv_trigger.h"
#endif
static mval subsc[MAX_GVSUBSCRIPTS]; /* At return, op_gvargs elements will be pointing to elements of this array, hence static */
static MSTR_DEF(subsc_buffer, 0, NULL); /* Buffer space (subsc_buffer.addr) will be allocated on the first call.
* Buffer space to hold string mvals in subsc; we don't want to use stringpool because
* this module is called from both DDPGVUSR and GTMSHR, and stringpool is not set up in
* DDPGVUSR. In addition, if we use stringpool, we might have to garbage collect, which
* means pulling in all GBLDEFs and functions referenced in stp_gcol into DDPGVUSR.
* That will be a link nightmare! */
boolean_t str2gvargs(char *cp, int len, gvargs_t *op_gvargs)
{ /* IMPORTANT : op_gvargs will point to static area which gets overwritten by the next call to this function. Callers should
make a copy of op_gvargs if necessary */
char *p1, *p2, *c_top, *c_ref, ch, *subsc_ptr, *dstptr, *strnext;
int count;
mval *spt;
int chcode, chtmp;
mstr_len_t chlen;
boolean_t naked, concat, dot_seen, dollarzch, isdolar;
error_def(ERR_NOTGBL);
error_def(ERR_GVINVALID);
error_def(ERR_LPARENREQD);
error_def(ERR_NUMUNXEOR);
error_def(ERR_STRUNXEOR);
error_def(ERR_DLRCUNXEOR);
error_def(ERR_DLRCTOOBIG);
error_def(ERR_EORNOTFND);
error_def(ERR_RPARENREQD);
error_def(ERR_DLRCILLEGAL);
assert(SIZEOF(op_gvargs->count) == SIZEOF(op_gvargs->args[0]));
naked = FALSE;
concat = FALSE;
c_ref = cp;
c_top = cp + len;
assert(0 < len); /* why is our code calling with "" string? */
if (len > subsc_buffer.len)
{
if (NULL != subsc_buffer.addr)
free(subsc_buffer.addr);
subsc_buffer.len = (ZWR_EXP_RATIO(MAX_KEY_SZ) < len ? len : ZWR_EXP_RATIO(MAX_KEY_SZ));
subsc_buffer.addr = malloc(subsc_buffer.len);
}
spt = subsc;
count = 0;
if (0 >= len || '^' != *cp++)
rts_error(VARLSTCNT(4) ERR_NOTGBL, 2, (len > 0) ? len : 0, c_ref);
spt->mvtype = MV_STR;
spt->str.addr = cp;
ch = *cp;
if ('(' == ch)
{
spt->str.len = INTCAST(cp - spt->str.addr - 1);
naked = TRUE;
} else
{
cp++;
if (!(VALFIRSTCHAR_WITH_TRIG(ch)))
rts_error(VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref);
for ( ; cp < c_top && *cp != '('; )
{
ch = *cp++;
if (!ISALPHA_ASCII(ch) && !ISDIGIT_ASCII(ch))
rts_error(VARLSTCNT(4) ERR_GVINVALID, 2, len, c_ref);
}
spt->str.len = INTCAST(cp - spt->str.addr);
op_gvargs->args[count] = spt;
count++;
spt++;
}
subsc_ptr = subsc_buffer.addr;
if (cp < c_top)
{
if ('(' != *cp++)
rts_error(VARLSTCNT(4) ERR_LPARENREQD, 2, len, c_ref);
for (; ;)
{
spt->mvtype = MV_STR;
ch = *cp;
if ('\"' == ch)
{
if (!concat)
{
spt->str.addr = subsc_ptr;
p1 = subsc_ptr;
} else
p2 = p1;
++cp;
for (; ;)
{
if (cp == c_top)
rts_error(VARLSTCNT(4) ERR_STRUNXEOR, 2, len, c_ref);
if ('\"' == *cp)
if ('\"' != *++cp)
break;
*p1++ = *cp++;
}
if (!concat)
{
spt->str.len = INTCAST(p1 - spt->str.addr);
subsc_ptr = p1;
} else
{
spt->str.len += (mstr_len_t)(p1 - p2);
subsc_ptr += p1 - p2;
}
if ('_' == *cp)
{
cp++;
concat = TRUE;
continue;
}
} else if ('$' == ch)
{
cp++;
chtmp = toupper(*cp);
isdolar = (3 <= c_top - cp && 'C' == chtmp || '(' == cp[1]);
if (!isdolar)
isdolar = (5 <= c_top - cp && 'Z' == chtmp && 'C' == cp[1] && 'H' == cp[2] && '(' == cp[3]);
if (!isdolar)
rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
if ('Z' == chtmp)
{
dollarzch = TRUE;
cp += 4;
} else
{
dollarzch = FALSE;
cp += 2;
}
for (; ;)
{
A2I(cp, c_top, chcode);
if (0 > chcode)
rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
dstptr = (!concat) ? subsc_ptr : p1;
if (!gtm_utf8_mode || dollarzch)
{
if (255 < chcode)
{
if (dollarzch)
rts_error(VARLSTCNT(6) ERR_DLRCTOOBIG, 4, len, c_ref,
LEN_AND_LIT("$CHAR()"));
else
rts_error(VARLSTCNT(6) ERR_DLRCTOOBIG, 4, len, c_ref,
LEN_AND_LIT("$ZCHAR()"));
}
*dstptr = chcode;
chlen = 1;
}
#ifdef UNICODE_SUPPORTED
else {
strnext = (char *)UTF8_WCTOMB(chcode, dstptr);
chlen = INTCAST(strnext - dstptr);
if (0 == chlen)
rts_error(VARLSTCNT(5) ERR_DLRCILLEGAL, 3, len, c_ref, chcode);
}
#endif
if (!concat)
{
spt->str.addr = subsc_ptr;
spt->str.len = chlen;
subsc_ptr += chlen;
p1 = subsc_ptr;
} else
{
p1 += chlen;
spt->str.len += chlen;
subsc_ptr += chlen;
}
if (',' == *cp)
{
concat = TRUE;
if (++cp == c_top)
rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
continue;
}
if (')' != *cp)
rts_error(VARLSTCNT(4) ERR_DLRCUNXEOR, 2, len, c_ref);
break;
}
cp++;
if ('_' == *cp)
{
cp++;
concat = TRUE;
continue;
}
} else
{
dot_seen = FALSE;
if (!ISDIGIT_ASCII(ch) && '.' != ch && '-' != ch && '+' != ch)
rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
if (!concat)
{
spt->str.addr = subsc_ptr;
p1 = subsc_ptr;
} else
p2 = p1;
*p1++ = *cp++;
for (; ;)
{
if (cp == c_top)
rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
if (!ISDIGIT_ASCII(*cp))
{
if ('.' != *cp)
break;
else if (!dot_seen)
dot_seen = TRUE;
else
rts_error(VARLSTCNT(4) ERR_NUMUNXEOR, 2, len, c_ref);
}
*p1++ = *cp++;
}
if (!concat)
{
spt->str.len = INTCAST(p1 - spt->str.addr);
subsc_ptr = p1;
} else
{
spt->str.len += (mstr_len_t)(p1 - p2);
subsc_ptr += p1 - p2;
}
if ('_' == *cp)
{
cp++;
concat = TRUE;
continue;
}
}
op_gvargs->args[count] = spt;
count++;
spt++;
if (',' != *cp)
break;
concat = FALSE;
cp++;
}
if (')' != *cp++)
rts_error(VARLSTCNT(4) ERR_RPARENREQD, 2, len, c_ref);
if (cp < c_top)
rts_error(VARLSTCNT(4) ERR_EORNOTFND, 2, len, c_ref);
}
op_gvargs->count = count;
return naked;
}