fis-gtm/sr_port/zwr2format.c

282 lines
6.6 KiB
C

/****************************************************************
* *
* Copyright 2001, 2009 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_stdlib.h"
#include "gtm_string.h"
#include "gtm_ctype.h"
#include "zshow.h"
#include "patcode.h"
#ifdef UNICODE_SUPPORTED
#include "gtm_utf8.h"
#endif
LITREF unsigned char lower_to_upper_table[];
#define FORMAT_PRINTABLE(cp) \
{ \
memcpy(&dstptr[des->len], cpstart, (cp) - cpstart); \
des->len += (int)((cp) - cpstart); \
}
#define FORMAT_CHAR(c) \
{ \
dstptr[des->len] = c; \
++(des->len); \
}
/* Routine that transforms a ZWR subscript to the internal string representation */
boolean_t zwr2format(mstr *src, mstr *des)
{
unsigned char ch, chtmp, *cp, *cpstart, *end, *dstptr, *strnext;
int fastate, num;
des->len = 0;
if (src->len > 0)
{
cp = (unsigned char *)src->addr;
end = cp + src->len;
dstptr = (unsigned char*)des->addr;
fastate = 0;
for (cpstart = cp; cp < end; )
{
switch(fastate)
{
case 0: /* state that interprets graphic vs. non-graphic */
ch = *cp++;
if ('$' == ch)
{
ch = chtmp = lower_to_upper_table[*cp++];
if (('C' != ch) && (('Z' != ch) || ('C' != (ch = lower_to_upper_table[*cp++])) ||
('H' != (ch = lower_to_upper_table[*cp++]))))
return FALSE;
if ('(' != (ch = *cp++))
return FALSE;
fastate = ('C' == chtmp) ? 2 : 3;
} else if ('"' == ch)
{ /* beginning of a quoted string: prepare for the new graphic substring */
fastate = 1;
cpstart = cp;
} else if ('0' <= ch && ch <= '9')
{ /* a numeric subscript */
FORMAT_CHAR(ch);
fastate = 4;
} else if ('.' == ch)
{
FORMAT_CHAR(ch);
fastate = 5;
} else
return FALSE;
break;
case 1: /* Continuation of graphic string */
ch = *cp++;
if ('"' == ch)
{
if (cp < end)
{
switch (*cp)
{
case '"': /* print the graphic string upto the first quote */
FORMAT_PRINTABLE(cp);
cpstart = ++cp;
break;
case '_':
FORMAT_PRINTABLE(cp - 1);
fastate = 0;
++cp;
break;
default:
return FALSE;
}
} else
FORMAT_PRINTABLE(cp - 1);
}
break;
case 2: /* parsing the string after $C( */
A2I(cp, end, num); /* NOTE: cp is updated accordingly */
if (num < 0)
return FALSE;
if (!gtm_utf8_mode)
{
if (num > 255)
return FALSE;
FORMAT_CHAR(num);
}
#ifdef UNICODE_SUPPORTED
else {
strnext = UTF8_WCTOMB(num, &dstptr[des->len]);
if (strnext == &dstptr[des->len])
return FALSE; /* illegal code points in $C() */
des->len += (int)(strnext - &dstptr[des->len]);
}
#endif
switch(ch = *cp++)
{
case ',':
break;
case ')':
if (cp < end && '_' != *cp++)
return FALSE;
fastate = 0;
break;
default:
return FALSE;
break;
}
break;
case 3: /* parsing the string after $ZCH( */
A2I(cp, end, num); /* NOTE: cp is updated accordingly */
if (num < 0 || num > 255)
return FALSE;
FORMAT_CHAR(num);
switch(ch = *cp++)
{
case ',':
break;
case ')':
if (cp < end && '_' != *cp++)
return FALSE;
fastate = 0;
break;
default:
return FALSE;
break;
}
break;
case 4: /* a numeric subscript - decimal might still come */
ch = *cp++;
if ('0' <= ch && ch <= '9')
{
FORMAT_CHAR(ch);
} else if ('.' == ch)
{
FORMAT_CHAR(ch);
fastate = 5;
} else
return FALSE;
break;
case 5: /* a numeric subscript - already seen decimal */
ch = *cp++;
if ('0' <= ch && ch <= '9')
{
FORMAT_CHAR(ch);
} else
return FALSE;
break;
default:
return FALSE;
break;
}
}
}
return TRUE;
}
/* Routine to compute the length of the KEY in ZWR format */
int zwrkeylength(char* ptr, int len)
{
int keylength, keystate;
unsigned ch, chtmp;
boolean_t keepgoing;
keylength = 0; /* determine length of key */
keystate = 0;
keepgoing = TRUE;
while ((keylength < len) && keepgoing) /* slightly different here from go_load since we can get kill records too */
{
ch = ptr[keylength++];
switch (keystate)
{
case 0: /* in global name */
if ('=' == ch) /* end of key */
{
keylength--;
keepgoing = FALSE;
}
else if ('(' == ch) /* start of subscripts */
keystate = 1;
break;
case 1: /* in subscripts area, but out of "..." or $C(...) */
switch (ch)
{
case ')': /* end of subscripts ==> end of key */
keepgoing = FALSE;
break;
case '"': /* step into "..." */
keystate = 2;
break;
case '$': /* step into $C(...) */
chtmp = TOUPPER(ptr[keylength]);
assert(('C' == chtmp && '(' == ptr[keylength + 1]) ||
('Z' == chtmp && 'C' == TOUPPER(ptr[keylength + 1]) &&
'H' == TOUPPER(ptr[keylength + 2]) && '(' == ptr[keylength + 3]));
keylength += ('C' == chtmp) ? 2 : 4;
keystate = 3;
break;
}
break;
case 2: /* in "..." */
if ('"' == ch)
{
switch (ptr[keylength])
{
case '"': /* "" */
keylength++;
break;
case '_': /* _$C(...) or _$ZCH(...) */
assert('$' == ptr[keylength + 1]);
chtmp = TOUPPER(ptr[keylength + 2]);
assert(('C' == chtmp && '(' == ptr[keylength + 3]) || ('Z' == chtmp &&
'C' == TOUPPER(ptr[keylength + 3]) && 'H' == TOUPPER(ptr[keylength + 4]) &&
'(' == ptr[keylength + 5]));
keylength += ('C' == chtmp) ? 4 : 6;
keystate = 3;
break;
default: /* step out of "..." */
keystate = 1;
}
}
break;
case 3: /* in $C(...) or $ZCH(...) */
if (')' == ch)
{
if ('_' == ptr[keylength]) /* step into "..." or $C(...) or $ZCH(...) */
{
assert('"' == ptr[keylength + 1] || '$' == ptr[keylength + 1]);
if ('"' == ptr[keylength + 1])
{ /* step into "..." by advancing over the begin quote */
keylength += 2;
keystate = 2;
} else
{ /* step into $C(..) or $ZCH(...) but do not advance over dollar ($) */
keylength += 1;
keystate = 1;
}
break;
}
else
keystate = 1; /* step out of $C(...) */
}
break;
default:
assert(FALSE);
break;
}
}
return keylength;
}