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; } }
/* 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; }
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
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; } }
/* 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; }
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; }