235 lines
6.3 KiB
C
235 lines
6.3 KiB
C
|
/****************************************************************
|
||
|
* *
|
||
|
* Copyright 2001, 2011 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_string.h"
|
||
|
|
||
|
#include "mlkdef.h"
|
||
|
#include "zshow.h"
|
||
|
#include "patcode.h"
|
||
|
#include "compiler.h" /* for CHARMAXARGS */
|
||
|
#include "rtnhdr.h"
|
||
|
#include "stack_frame.h"
|
||
|
#include "mv_stent.h" /* for POP_MV_STENT */
|
||
|
|
||
|
#ifdef UNICODE_SUPPORTED
|
||
|
#include "gtm_utf8.h"
|
||
|
#include "gtm_icu_api.h" /* U_ISPRINT() needs this header */
|
||
|
#endif
|
||
|
|
||
|
GBLREF uint4 *pattern_typemask;
|
||
|
GBLREF boolean_t gtm_utf8_mode;
|
||
|
GBLREF mv_stent *mv_chain;
|
||
|
GBLREF unsigned char *stackbase, *stacktop, *msp, *stackwarn;
|
||
|
GBLREF int process_exiting;
|
||
|
|
||
|
LITDEF MSTR_CONST(quote, QUOTE);
|
||
|
LITDEF MSTR_CONST(quote_concat, QUOTE_CONCAT);
|
||
|
LITDEF MSTR_CONST(close_paren, CLOSE_PAREN);
|
||
|
LITDEF MSTR_CONST(close_paren_quote, CLOSE_PAREN_QUOTE);
|
||
|
|
||
|
error_def(ERR_STACKOFLOW);
|
||
|
error_def(ERR_STACKCRIT);
|
||
|
|
||
|
/* The following macro prints the last contiguous sequence of printable (graphic) characters
|
||
|
* that have been processed so far to the zshow buffer. It also resets the size of the next
|
||
|
* next sequence that may follow */
|
||
|
#define ZWR_PRINTABLE \
|
||
|
{ \
|
||
|
graphic_str->str.len = src_cnt - strstart; \
|
||
|
graphic_str->str.addr = v->str.addr + strstart; \
|
||
|
zshow_output(output, &graphic_str->str); \
|
||
|
}
|
||
|
|
||
|
/* The routine that does formatting for ZWRITE command.
|
||
|
* NOTE: this routine does almost the same formatting as format2zwr(). However,
|
||
|
* the main difference is this routine feeds the formatted results to the zshow
|
||
|
* output handling routine (zshow_output()) instead of storing in a pre-allocated
|
||
|
* destination buffer */
|
||
|
void mval_write(zshow_out *output, mval *v, boolean_t flush)
|
||
|
{
|
||
|
sm_uc_ptr_t cp;
|
||
|
uint4 ch;
|
||
|
int fastate = 0, ncommas, src_len, src_cnt, strstart, chlen;
|
||
|
boolean_t isctl, isill;
|
||
|
char *strnext;
|
||
|
mval *graphic_str, lmv;
|
||
|
|
||
|
MV_FORCE_STR(v);
|
||
|
src_len = v->str.len;
|
||
|
if (src_len > 0)
|
||
|
{
|
||
|
if (val_iscan(v))
|
||
|
{
|
||
|
output->flush = flush;
|
||
|
zshow_output(output, &v->str);
|
||
|
return;
|
||
|
}
|
||
|
fastate = 0;
|
||
|
strstart = 0;
|
||
|
|
||
|
if (!process_exiting)
|
||
|
{ /* Only if not exiting in case we are called from mdb_condition_handler with stack overflow */
|
||
|
PUSH_MV_STENT(MVST_MVAL);
|
||
|
graphic_str = &mv_chain->mv_st_cont.mvs_mval;
|
||
|
} else
|
||
|
graphic_str = &lmv;
|
||
|
graphic_str->mvtype = MV_STR;
|
||
|
graphic_str->str.len = 0; /* initialize len in case stp_gcol gets called before actual set of len occurs below */
|
||
|
|
||
|
/* Note that throughout this module, we use v->str.addr[xxx] to access the input string instead of
|
||
|
* maintaining a pointer variable. This is because we call zshow_output at lot of places and each
|
||
|
* of them can invoke stp_gcol in turn changing the value of v->str.addr.
|
||
|
*/
|
||
|
for (src_cnt = 0; src_cnt < src_len; src_cnt += chlen)
|
||
|
{
|
||
|
if (!gtm_utf8_mode)
|
||
|
{
|
||
|
ch = (unsigned char)v->str.addr[src_cnt];
|
||
|
isctl = ((pattern_typemask[ch] & PATM_C) != 0);
|
||
|
isill = FALSE;
|
||
|
chlen = 1;
|
||
|
}
|
||
|
UNICODE_ONLY(
|
||
|
else
|
||
|
{
|
||
|
strnext = (char *)UTF8_MBTOWC(&v->str.addr[src_cnt], &v->str.addr[src_len], ch);
|
||
|
isill = (WEOF == ch) ? (ch = (unsigned char)v->str.addr[src_cnt], TRUE) : FALSE;
|
||
|
if (!isill)
|
||
|
isctl = !U_ISPRINT(ch);
|
||
|
chlen = (int)(strnext - &v->str.addr[src_cnt]);
|
||
|
}
|
||
|
)
|
||
|
switch(fastate)
|
||
|
{
|
||
|
case 0: /* beginning of the string */
|
||
|
case 1: /* beginning of a new substring followed by a graphic character */
|
||
|
if (isill)
|
||
|
{
|
||
|
if (src_cnt > 0)
|
||
|
{ /* close previous string with quote and prepare for
|
||
|
concatenation */
|
||
|
ZWR_PRINTABLE;
|
||
|
zshow_output(output, "e_concat);
|
||
|
}
|
||
|
mval_nongraphic(output, LIT_AND_LEN(DOLLARZCH), ch);
|
||
|
fastate = 3;
|
||
|
ncommas = 0;
|
||
|
} else if (isctl)
|
||
|
{
|
||
|
if (src_cnt > 0)
|
||
|
{ /* close previous string with quote and prepare for
|
||
|
concatenation */
|
||
|
ZWR_PRINTABLE;
|
||
|
zshow_output(output, "e_concat);
|
||
|
}
|
||
|
mval_nongraphic(output, LIT_AND_LEN(DOLLARCH), ch);
|
||
|
fastate = 2;
|
||
|
ncommas = 0;
|
||
|
} else
|
||
|
{ /* graphic characters */
|
||
|
if (0 == fastate) /* the initial quote in the beginning */
|
||
|
{
|
||
|
zshow_output(output, "e);
|
||
|
fastate = 1;
|
||
|
}
|
||
|
if ('"' == ch)
|
||
|
{
|
||
|
ZWR_PRINTABLE;
|
||
|
zshow_output(output, "e);
|
||
|
strstart = src_cnt;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case 2: /* subsequent characters following a non-graphic character in the form
|
||
|
of $CHAR(x,) */
|
||
|
if (isill)
|
||
|
{
|
||
|
mval_nongraphic(output, LIT_AND_LEN(CLOSE_PAREN_DOLLARZCH), ch);
|
||
|
fastate = 3;
|
||
|
} else if(isctl)
|
||
|
{
|
||
|
ncommas++;
|
||
|
if (CHARMAXARGS == ncommas)
|
||
|
{
|
||
|
ncommas = 0;
|
||
|
mval_nongraphic(output, LIT_AND_LEN(CLOSE_PAREN_DOLLARCH), ch);
|
||
|
} else
|
||
|
mval_nongraphic(output, LIT_AND_LEN(COMMA), ch);
|
||
|
} else
|
||
|
{
|
||
|
zshow_output(output, &close_paren_quote);
|
||
|
if ('"' == ch)
|
||
|
zshow_output(output, "e);
|
||
|
strstart = src_cnt;
|
||
|
fastate = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 3: /* subsequent characters following an illegal character in the form of $ZCHAR(x,) */
|
||
|
if(isill)
|
||
|
{
|
||
|
ncommas++;
|
||
|
if (CHARMAXARGS == ncommas)
|
||
|
{
|
||
|
ncommas = 0;
|
||
|
mval_nongraphic(output, LIT_AND_LEN(CLOSE_PAREN_DOLLARZCH), ch);
|
||
|
} else
|
||
|
mval_nongraphic(output, LIT_AND_LEN(COMMA), ch);
|
||
|
} else if (isctl)
|
||
|
{
|
||
|
mval_nongraphic(output, LIT_AND_LEN(CLOSE_PAREN_DOLLARCH), ch);
|
||
|
fastate = 2;
|
||
|
} else
|
||
|
{
|
||
|
zshow_output(output, &close_paren_quote);
|
||
|
if ('"' == ch)
|
||
|
zshow_output(output, "e);
|
||
|
strstart = src_cnt;
|
||
|
fastate = 1;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
assert(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* close up */
|
||
|
switch(fastate)
|
||
|
{
|
||
|
case 1:
|
||
|
ZWR_PRINTABLE;
|
||
|
zshow_output(output, "e);
|
||
|
break;
|
||
|
case 2:
|
||
|
case 3:
|
||
|
zshow_output(output, &close_paren);
|
||
|
break;
|
||
|
default:
|
||
|
assert(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
if (!process_exiting)
|
||
|
{
|
||
|
POP_MV_STENT();
|
||
|
}
|
||
|
} else
|
||
|
{
|
||
|
zshow_output(output, "e);
|
||
|
zshow_output(output, "e);
|
||
|
}
|
||
|
if (flush)
|
||
|
{
|
||
|
output->flush = TRUE;
|
||
|
zshow_output(output, 0);
|
||
|
}
|
||
|
}
|