Exemple #1
0
void show_source_line(char* buf, boolean_t warn)
{
	char 	*b, *c, *c_top;
	int	chlen, chwidth;
	unsigned int ch;
	error_def(ERR_SRCLIN);
	error_def(ERR_SRCLOC);

	for (c = (char *)source_buffer, b = buf, c_top = c + last_source_column - 1; c < c_top; )
	{
		if (*c == '\t')
			*b++ = *c++;
		else if (!gtm_utf8_mode || *(uchar_ptr_t)c <= ASCII_MAX)
		{
			*b++ = ' ';
			c++;
		}
#ifdef UNICODE_SUPPORTED
		else
		{
			chlen = (int)(UTF8_MBTOWC(c, c_top, ch) - (uchar_ptr_t)c);
			if (WEOF != ch && 0 < (chwidth = UTF8_WCWIDTH(ch)))
			{
				memset(b, ' ', chwidth);
				b += chwidth;
			}
			c += chlen;
		}
#endif
	}
	memcpy(b, ARROW, STR_LIT_LEN(ARROW));
	b += STR_LIT_LEN(ARROW);
	*b = '\0';
	if (warn)
	{
		dec_nofac = TRUE;
		dec_err(VARLSTCNT (6) ERR_SRCLIN, 4, LEN_AND_STR((char *)source_buffer), b - buf, buf);
		if (!run_time)
			dec_err(VARLSTCNT(6) ERR_SRCLOC, 4, last_source_column, source_line, source_name_len, source_file_name);
		dec_nofac = FALSE;
	}
}
Exemple #2
0
/* Returns the total display column width of a UTF-8 string given its address and byte length.
 * The third parameter (strict) is used to specify how both illegal characters should be handled.
 * The fourth parameter (nonprintwidth) is to specify what width to give for unprintable characters.
 *	It is currently 0 if coming through $ZWIDTH and 1 if coming through util_output (for historical reasons).
 * If strict is TRUE, this routine
 * 	- triggers BADCHAR error if it encounters any illegal characters irrespective of VIEW BADCHAR setting.
 * If strict is FALSE, this routine
 * 	- does NOT do BADCHAR check.
 *	- treats illegal characters as unprintable characters (for width).
 */
int gtm_wcswidth(unsigned char* ptr, int len, boolean_t strict, int nonprintwidth)
{
	int		strwidth, cwidth;
	uint4		ch;
	unsigned char	*ptrtop, *ptrnext;

	assert(gtm_utf8_mode);
	ptrtop = ptr + len;
	for (strwidth = 0; ptr < ptrtop; ptr = ptrnext)
	{
		ptrnext = UTF8_MBTOWC(ptr, ptrtop, ch);
		if (WEOF != ch && -1 != (cwidth = UTF8_WCWIDTH(ch)))
			strwidth += cwidth;
		else if (strict && (WEOF == ch))
			UTF8_BADCHAR(0, ptr, ptrtop, 0, NULL);
		else
			strwidth += nonprintwidth;
	}
	assert(ptr == ptrtop);
	return strwidth;
}
Exemple #3
0
int	iorm_rdone(mint *v, int4 timeout)
{
	mval		tmp;
	int		ret;
        uint4		codepoint;
	gtm_chset_t	ichset;

	*v = -1;
	ret = iorm_readfl(&tmp, -1, timeout);
	if (ret)
	{
		if (0 != tmp.str.len)
		{
			ichset = io_curr_device.in->ichset;
			switch(ichset)
			{
				case CHSET_M:
					codepoint = (unsigned char)tmp.str.addr[0];
					break;
				case CHSET_UTF8:
					UTF8_MBTOWC(tmp.str.addr, tmp.str.addr + tmp.str.len, codepoint);
					break;
				case CHSET_UTF16BE:
					UTF16BE_MBTOWC(tmp.str.addr, tmp.str.addr + tmp.str.len, codepoint);
					break;
				case CHSET_UTF16LE:
					UTF16LE_MBTOWC(tmp.str.addr, tmp.str.addr + tmp.str.len, codepoint);
					break;
				case CHSET_UTF16:
					GTMASSERT;
				default:
#ifdef __MVS
					codepoint = (unsigned char)tmp.str.addr[0];
					break;
#else
					GTMASSERT;
#endif
			}
			UNICODE_ONLY(assert(WEOF != codepoint);)
		} else
Exemple #4
0
int 	write_str(void *str832, unsigned int len, unsigned int start_x, boolean_t move, boolean_t multibyte)
{
	/*
	  writes a specified string starting from the current cursor position
	  and returns the cursor back to the same place.

		str832		-> the string to write, may be Unicode code points
		len		-> the length of the string
		start_x		-> is the current cursor's column in the window.
		move		-> whether the cursor moves or not.
		multibyte	-> str832 is always bytes, if utf8_active then multibyte possible

	  returns -1 if error, 0 if successful
	*/

	int		number_of_lines_up, number_of_chars_left, written, ret, outlen;
	unsigned int	cur_x;
	int		width = io_curr_device.in->width, cur_width, line_width, this_width;
	int		fildes = ((d_tt_struct *)((io_curr_device.in)->dev_sp))->fildes;
	unsigned char	*str, string[TTDEF_BUF_SZ], *outptr, *outtop, *strstart, *nextptr;
	wint_t		*str32, temp32;
	io_desc		*io_ptr = io_curr_device.in;
	d_tt_struct	*tt_ptr;
	boolean_t	utf8_active, writenewline;

	assert(width);
	tt_ptr = (d_tt_struct *)io_ptr->dev_sp;
	utf8_active = gtm_utf8_mode ? (CHSET_M != io_ptr->ichset) : FALSE;
	if (utf8_active && !multibyte)
		str32 = (wint_t *)str832;
	else
		str = (unsigned char *)str832;
	if (multibyte && utf8_active)
	{
		outptr = str;
		outtop = str + len;
	}
	cur_x = start_x % width;	/* start_x is absolute, get relative value into cur_x */
	number_of_lines_up = 0;
#ifdef UNICODE_SUPPORTED
	if (utf8_active)
	{
		cur_width = width - cur_x;
		for (line_width = 0; 0 < len; )
		{
			writenewline = FALSE;
			if (multibyte)
			{	/* go through mb string one line at a time */
				for (strstart = outptr ; outptr < outtop; )
				{
					nextptr = UTF8_MBTOWC(outptr, outtop, temp32);
					GTM_IO_WCWIDTH(temp32, this_width);
					if ((line_width + this_width) > cur_width)
					{
						writenewline = TRUE;
						break;
					}
					line_width += this_width;
					outptr = nextptr;
				}
				outlen = (int)(outptr - strstart);
				len -= outlen;
			} else
			{
				for (outptr = string, outtop = string + SIZEOF(string);
					(0 < len) && ((outptr + GTM_MB_LEN_MAX) < outtop);
						str32++, len--)
				{
					GTM_IO_WCWIDTH(*str32, this_width);
					if ((line_width + this_width) > cur_width)
					{
						writenewline = TRUE;
						break;
					}
					line_width += this_width;
					temp32 = *str32;	/* preserve argument */
					outptr = UTF8_WCTOMB(temp32, outptr);
				}
				outlen =(int)(outptr - string);
				strstart = string;
			}
			assert(!writenewline || len);
			assert(line_width <= cur_width);
			if (line_width >= cur_width)	/* our write has positioned us to end of width. write new line */
				writenewline = TRUE;
			/* either end of input, end of conversion buffer, or full line */
			if (0 < outlen)
			{	/* something to write */
				DOWRITERL_A(fildes, strstart, outlen, written);
				if (0 > written)
					return -1;
			}
			if (!writenewline)
			{
				if (0 < len)
					continue;	/* end of buffer in middle of line so no EOL */
				if (0 == len)
				{	/* last line is partial so no new line */
					cur_x = cur_x + line_width;
					break;
				}
			}
			/* -------------------------------------------------------------------------
			* for terminals that have the EAT_NEWLINE_GLITCH auto_margin doesn't work
			* even though AUTO_RIGHT_MARGIN may be 1. So you have to check both
			* before writing the TTEOL
			* -------------------------------------------------------------------------
			*/
			if (!AUTO_RIGHT_MARGIN || EAT_NEWLINE_GLITCH)
			{
				DOWRITERC(fildes, NATIVE_TTEOL, strlen(NATIVE_TTEOL), ret);
				if (0 != ret)
					return -1;
			}
			number_of_lines_up++;
			cur_x = line_width = 0;
			cur_width = width;
		}
	} else
	{
#endif
		for ( ; 0 < len; )
		{
			cur_width = width - cur_x;
			if (cur_width)
			{
				if (len < cur_width)
					cur_width = len;
				DOWRITERL_A(fildes, str, cur_width, written);
				if (0 > written)
					return -1;
				str += written;
				len -= written;
				cur_x += cur_width;
			}
			if ((cur_x < width) && (0 == len))
				break;	/* last line is partial so no new line */
			/* -------------------------------------------------------------------------
		 	 * for terminals that have the EAT_NEWLINE_GLITCH auto_margin doesn't work
		 	 * even though AUTO_RIGHT_MARGIN may be 1. So you have to check both
		 	 * before writing the TTEOL
		 	 * -------------------------------------------------------------------------
		 	 */
			if (!AUTO_RIGHT_MARGIN || EAT_NEWLINE_GLITCH)
			{
		    		DOWRITERC(fildes, NATIVE_TTEOL, strlen(NATIVE_TTEOL), ret);
				if (0 != ret)
					return -1;
			}
			number_of_lines_up++;
			cur_x = 0;
			cur_width = width;
		}
#ifdef UNICODE_SUPPORTED
	}
#endif
	number_of_chars_left = cur_x - start_x;
	if (!move)
	{
		ret = write_loop(fildes, (unsigned char *)CURSOR_UP, number_of_lines_up);
		if (0 > ret)
			return -1;
		if (number_of_chars_left > 0)
		{
			ret = write_loop(fildes, (unsigned char *)CURSOR_LEFT, number_of_chars_left);
			if (0 > ret)
				return -1;
		} else
		{
			ret = write_loop(fildes, (unsigned char *)CURSOR_RIGHT, -number_of_chars_left);
			if (0 > ret)
				return -1;
		}
	}
	return 0;
}
void show_source_line(boolean_t warn)
{
	char 		*b, *b_top, *c, *c_top, *buf;
	char		source_line_buff[MAX_SRCLINE + SIZEOF(ARROW)];
	ssize_t		buflen;
	int		chlen, chwidth;
	unsigned int	ch, line_chwidth = 0;
	boolean_t	unable_to_complete_arrow = FALSE;
	mstr		msgstr;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	buf = source_line_buff;
	buflen = SIZEOF(source_line_buff);
	b_top = buf + buflen - STR_LIT_LEN(ARROW) - 1; /* allow room for arrow and string terminator */
	for (c = (char *)source_buffer, b = buf, c_top = c + TREF(last_source_column) - 1; c < c_top;)
	{
		if ('\t' == *c)
		{
			if ((b + 1) > b_top)
			{
				unable_to_complete_arrow = TRUE;
				break;
			}
			*b++ = *c++;
		}
		else if (!gtm_utf8_mode || (ASCII_MAX >= *(uchar_ptr_t)c))
		{
			if ((b + 1) > b_top)
			{
				unable_to_complete_arrow = TRUE;
				break;
			}
			*b++ = ' ';
			c++;
		}
#		ifdef UNICODE_SUPPORTED
		else
		{
			chlen = (int)(UTF8_MBTOWC(c, c_top, ch) - (uchar_ptr_t)c);
			if (WEOF != ch && (0 < (chwidth = UTF8_WCWIDTH(ch))))	/* assignment */
			{
				if ((b + chwidth) > b_top)
				{
					unable_to_complete_arrow = TRUE;
					break;
				}
				memset(b, ' ', chwidth);
				b += chwidth;
			}
			c += chlen;
		}
#		endif
	}
	if (unable_to_complete_arrow)
	{
		msgstr.addr = buf;
		msgstr.len = buflen;
		dec_nofac = TRUE;
		gtm_getmsg(ERR_ARROWNTDSP, &msgstr);
		dec_nofac = FALSE;
	} else
	{
		memcpy(b, ARROW, STR_LIT_LEN(ARROW));
		b += STR_LIT_LEN(ARROW);
		*b = '\0';
	}
	if (warn)
	{
		for (c = (char *)source_buffer; c < (char *)source_buffer + STRLEN((char *)source_buffer) - 1; )
		{
			if ('\t' == *c)
			{
				line_chwidth++;
				c++;
			}
			else if (!gtm_utf8_mode || (ASCII_MAX >= *(uchar_ptr_t)c))
			{
				line_chwidth++;
				c++;
			} else
			{
#			ifdef UNICODE_SUPPORTED		/* funky positioning makes VMS compiler happy */
				chlen = (int)(UTF8_MBTOWC(c, (char *)source_buffer + STRLEN((char *)source_buffer) - 1, ch)
						- (uchar_ptr_t)c);
				if ((WEOF != ch) && 0 < (chwidth = UTF8_WCWIDTH(ch)))
					line_chwidth += chwidth;
				c += chlen;
#			endif
			}
		}
		dec_nofac = TRUE;
		if (MAXLINESIZEFORDISPLAY > line_chwidth)
			if (unable_to_complete_arrow)
				dec_err(VARLSTCNT(6) ERR_SRCLIN, 4, LEN_AND_STR((char *)source_buffer), msgstr.len, msgstr.addr);
			else
				dec_err(VARLSTCNT(6) ERR_SRCLIN, 4, LEN_AND_STR((char *)source_buffer), b - buf, buf);
		else
			dec_err(VARLSTCNT(2) ERR_SRCLNNTDSP, 1, MAXLINESIZEFORDISPLAY);
		if (!run_time)
			dec_err(VARLSTCNT(6) ERR_SRCLOC, 4, TREF(last_source_column), source_line,
				source_name_len, source_file_name);
		dec_nofac = FALSE;
	}
}
Exemple #6
0
/* write ASCII characters converting to UTF16 if needed
 * 	returns bytes written
*/
int  iorm_write_utf_ascii(io_desc *iod, char *string, int len)
{
	int		outlen, mblen, status;
	wint_t		utf_code;
	unsigned char	*outstart, *out, *top, *outptr, *nextoutptr, *outptrtop, *nextmb;
	d_rm_struct	*rm_ptr;
	boolean_t	ch_set;

	ESTABLISH_RET_GTMIO_CH(&iod->pair, -1, ch_set);
	rm_ptr = (d_rm_struct *)iod->dev_sp;
	assert(NULL != rm_ptr);
	if (CHSET_UTF8 != iod->ochset)
	{
		outstart = outptr = &rm_ptr->outbuf[rm_ptr->out_bytes];
		outptrtop = rm_ptr->outbuf + rm_ptr->recordsize;	/* buffer is larger than recordsize to allow for EOL */
		assert(len <= (&rm_ptr->outbuf[rm_ptr->outbufsize] - outstart));
		for (out = (unsigned char*)string, top = out + len, outlen = 0; out < top && outptr <= outptrtop;
				out = nextmb, outptr = nextoutptr)
		{
			nextmb = UTF8_MBTOWC(out, top, utf_code);
			assert(nextmb == (out + 1));
			if (WEOF == utf_code)
			{
				iod->dollar.za = 9;
				UTF8_BADCHAR((int)(nextmb - out), out, top, 0, NULL);
			}
			if (CHSET_UTF16BE == iod->ochset)
				nextoutptr = UTF16BE_WCTOMB(utf_code, outptr);
			else
				nextoutptr = UTF16LE_WCTOMB(utf_code, outptr);
			if (nextoutptr == outptr)
			{	/* invalid codepoint */
				iod->dollar.za = 9;
				UTF8_BADCHAR((int)(nextmb - out), out, top, chset_names[iod->ochset].len,
						chset_names[iod->ochset].addr);
			}
			mblen = (int)(nextoutptr - outptr);
			outlen += mblen;
		}
	} else
	{
		outstart = (unsigned char *)string;
		outlen = len;
	}
	if (0 < outlen)
	{
		if (rm_ptr->output_encrypted)
		{
			REALLOC_CRYPTBUF_IF_NEEDED(outlen);
			WRITE_ENCRYPTED_DATA(rm_ptr, iod->trans_name, outstart, outlen, pvt_crypt_buf.addr);
			outptr = (unsigned char *)pvt_crypt_buf.addr;
		} else
			outptr = outstart;
		DOWRITERC_RM(rm_ptr, outptr, outlen, status);
		ISSUE_NOPRINCIO_IF_NEEDED_RM(status, ==, iod);
		rm_ptr->write_occurred = TRUE;
		rm_ptr->out_bytes += outlen;
	}
	REVERT_GTMIO_CH(&iod->pair, ch_set);
	return outlen;
}
Exemple #7
0
sm_uc_ptr_t  dump_record(sm_uc_ptr_t rp, block_id blk, sm_uc_ptr_t bp, sm_uc_ptr_t b_top)
{
	sm_uc_ptr_t	r_top, key_top, cptr0, cptr1, cptr_top, cptr_base = NULL, cptr_next = NULL;
	char		key_buf[MAX_KEY_SZ + 1], *temp_ptr, *temp_key, util_buff[MAX_UTIL_LEN];
	char		*prefix_str, *space_str, *dot_str, *format_str;
	unsigned char	cc;
	short int	size;
	int4		util_len, head;
	uint4 		ch;
	int		buf_len, field_width,fastate, chwidth = 0;
        ssize_t   	chlen;
	block_id	blk_id;
	boolean_t	rechdr_displayed = FALSE;
	sgmnt_addrs	*csa;

	if (rp >= b_top)
		return NULL;
	head = cli_present("HEADER");
	GET_SHORT(size, &((rec_hdr_ptr_t)rp)->rsiz);
	cc = ((rec_hdr_ptr_t)rp)->cmpc;
	if ((CLI_NEGATED != head) && !patch_is_fdmp)
	{
		MEMCPY_LIT(util_buff, "Rec:");
		util_len = SIZEOF("Rec:") - 1;
		util_len += i2hex_nofill(patch_rec_counter, (uchar_ptr_t)&util_buff[util_len], 4);
		MEMCPY_LIT(&util_buff[util_len], "  Blk ");
		util_len += SIZEOF("  Blk ") - 1;
		util_len += i2hex_nofill(blk, (uchar_ptr_t)&util_buff[util_len], 8);
		MEMCPY_LIT(&util_buff[util_len], "  Off ");
		util_len += SIZEOF("  Off ") - 1;
		util_len += i2hex_nofill((int)(rp - bp), (uchar_ptr_t)&util_buff[util_len], 4);
		MEMCPY_LIT(&util_buff[util_len], "  Size ");
		util_len += SIZEOF("  Size ") - 1;
		util_len += i2hex_nofill(size, (uchar_ptr_t)&util_buff[util_len], 4);
		MEMCPY_LIT(&util_buff[util_len], "  Cmpc ");
		util_len += SIZEOF("  Cmpc ") - 1;
		util_len += i2hex_nofill(cc, (uchar_ptr_t)&util_buff[util_len], 2);
		MEMCPY_LIT(&util_buff[util_len], "  ");
		util_len += SIZEOF("  ") - 1;
		util_buff[util_len] = 0;
		util_out_print(util_buff, FALSE);
	}
	r_top = rp + size;
	if (r_top > b_top)
		r_top = b_top;
	else  if (r_top < rp + SIZEOF(rec_hdr))
		r_top = rp + SIZEOF(rec_hdr);
	if (cc > patch_comp_count)
		cc = patch_comp_count;
	if (((blk_hdr_ptr_t)bp)->levl)
		key_top = r_top - SIZEOF(block_id);
	else
	{
		for (key_top = rp + SIZEOF(rec_hdr);  key_top < r_top;)
			if (!*key_top++ && !*key_top++)
				break;
	}
	size = key_top - rp - SIZEOF(rec_hdr);
	if (size > SIZEOF(patch_comp_key) - 2 - cc)
		size = SIZEOF(patch_comp_key) - 2 - cc;
	if (size < 0)
		size = 0;
	memcpy(&patch_comp_key[cc], rp + SIZEOF(rec_hdr), size);
	patch_comp_count = cc + size;
	patch_comp_key[patch_comp_count] = patch_comp_key[patch_comp_count + 1] = 0;
	if (patch_is_fdmp)
	{
		if (dse_fdmp(key_top, (int)(r_top - key_top)))
			patch_fdmp_recs++;
	} else
	{
		if (r_top - SIZEOF(block_id) >= key_top)
		{
			GET_LONG(blk_id, key_top);
			if ((((blk_hdr_ptr_t)bp)->levl) || (blk_id <= cs_addrs->ti->total_blks))
			{
				MEMCPY_LIT(util_buff, "Ptr ");
				util_len = SIZEOF("Ptr ") - 1;
				util_len += i2hex_nofill(blk_id, (uchar_ptr_t)&util_buff[util_len], SIZEOF(blk_id) * 2);
				MEMCPY_LIT(&util_buff[util_len], "  ");
				util_len += SIZEOF("  ") - 1;
				util_buff[util_len] = 0;
				util_out_print(util_buff, FALSE);
			}
		}
		util_out_print("Key ", FALSE);
		if (r_top == b_top
			&& ((blk_hdr_ptr_t)bp)->levl && !((rec_hdr_ptr_t)rp)->cmpc
			&& r_top - rp == SIZEOF(rec_hdr) + SIZEOF(block_id))
				util_out_print("*", FALSE);
		else  if (patch_comp_key[0])
		{
			util_out_print("^", FALSE);
			csa = cs_addrs;
			RETRIEVE_ROOT_VAL(patch_comp_key, key_buf, temp_ptr, temp_key, buf_len);
			INIT_ROOT_GVT(key_buf, buf_len, curr_gbl_root);
		}
		print_target((uchar_ptr_t)patch_comp_key);
		util_out_print(0, TRUE);
		if (CLI_PRESENT != head)
		{
			prefix_str = "           |";
			if (wide_out)
			{
				format_str = "   !AD";
				dot_str = "   .";
				space_str = "    ";
				field_width = 4;
			} else
			{
				format_str = "  !AD";
				dot_str = "  .";
				space_str = "   ";
				field_width = 3;
			}
			fastate = 0;
			for (cptr0 = rp;  cptr0 < r_top;  cptr0 += NUM_BYTES_PER_LINE)
			{
				if (util_interrupt)
				{ /* return, rather than signal ERR_CTRLC so that the calling routine
				     can deal with that signal and do the appropriate cleanup */
					return NULL;
				}
				util_len = 8;
				i2hex_blkfill((int)(cptr0 - bp), (uchar_ptr_t)util_buff, 8);
				MEMCPY_LIT(&util_buff[util_len], " : |");
				util_len += SIZEOF(" : |") - 1;
				util_buff[util_len] = 0;
				util_out_print(util_buff, FALSE);
				/* Dump hexadecimal byte values */
				for (cptr1 = cptr0;  cptr1 < (cptr0 + NUM_BYTES_PER_LINE);  cptr1++)
				{
					if (cptr1 < r_top)
					{
						i2hex_blkfill(*(sm_uc_ptr_t)cptr1, (uchar_ptr_t)util_buff, field_width);
						util_buff[field_width] = 0;
						util_out_print(util_buff, FALSE);
					} else
						util_out_print(space_str, FALSE);
				}
				util_out_print("|", TRUE);
				util_out_print(prefix_str, FALSE);
				/* Display character/wide-character glyphs */
				for (cptr1 = cptr0, cptr_top = cptr0 + NUM_BYTES_PER_LINE;  cptr1 < cptr_top;  cptr1++)
				{
					if (!rechdr_displayed && (cptr1 == (rp + SIZEOF(rec_hdr))))
						rechdr_displayed = TRUE;
					assert(rechdr_displayed || (cptr1 < (rp + SIZEOF(rec_hdr))));
					assert(!rechdr_displayed || (cptr1 >= (rp + SIZEOF(rec_hdr))));
					switch (fastate)
					{
					case 0: /* prints single-byte characters or intepret
						   multi-byte characters */
						if (cptr1 >= r_top)
							util_out_print(space_str, FALSE);
						else if (!gtm_utf8_mode || IS_ASCII(*cptr1) || !rechdr_displayed)
						{ /* single-byte characters */
							if (PRINTABLE(*(sm_uc_ptr_t)cptr1))
								util_out_print(format_str, FALSE, 1, cptr1);
							else
								util_out_print(dot_str, FALSE);
						}
#ifdef UNICODE_SUPPORTED
						else { /* multi-byte characters */
							cptr_next = UTF8_MBTOWC(cptr1, r_top, ch);
							chlen = cptr_next - cptr1;
							if (WEOF == ch || !U_ISPRINT(ch))
							{ /* illegal or non-printable characters */
								cptr1--;
								fastate = 1;
							} else
							{ /* multi-byte printable characters */
								cptr_base = cptr1;
								chwidth = UTF8_WCWIDTH(ch);
								assert(chwidth >= 0 && chwidth <= 2);
								cptr1--;
								fastate = 2;
							}
						}
#endif
						break;

					case 1: /* illegal or non-printable characters */
						util_out_print(dot_str, FALSE);
						if (--chlen <= 0)
							fastate = 0;
						break;

					case 2: /* printable multi-byte characters */
						if (chlen-- > 1) /* fill leading bytes with spaces */
							util_out_print(space_str, FALSE);
						else
						{
							util_out_print("!AD", FALSE, field_width - chwidth, space_str);
							if (0 < chwidth)
								util_out_print("!AD", FALSE, cptr_next - cptr_base, cptr_base);
							fastate = 0;
						}
						break;
					}
				}
				util_out_print("|", TRUE);
			}
		}
		if (CLI_NEGATED != head)
			util_out_print(0, TRUE);
	}
	return (r_top == b_top) ? NULL : r_top;
}