public inbox for cygwin-cvs@sourceware.org help / color / mirror / Atom feed
From: Corinna Vinschen <corinna@sourceware.org> To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: pty: Revise convert_mb_str() function. Date: Wed, 9 Sep 2020 21:44:44 +0000 (GMT) [thread overview] Message-ID: <20200909214444.15C123857C59@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=91908fe00096d0979dd021599865a1ad02179078 commit 91908fe00096d0979dd021599865a1ad02179078 Author: Takashi Yano via Cygwin-patches <cygwin-patches@cygwin.com> Date: Thu Sep 10 00:27:59 2020 +0900 Cygwin: pty: Revise convert_mb_str() function. - Use tmp_pathbuf instead of HeapAlloc()/HeapFree(). - Remove mb_str_free() function. - Consider the case where the multibyte string stops in the middle of a multibyte char. Diff: --- winsup/cygwin/fhandler_tty.cc | 135 +++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 47 deletions(-) diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 6de591d9b..0bfc32ea9 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -26,6 +26,7 @@ details. */ #include <asm/socket.h> #include "cygwait.h" #include "registry.h" +#include "tls_pbuf.h" #ifndef PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE #define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016 @@ -116,40 +117,63 @@ CreateProcessW_Hooked return CreateProcessW_Orig (n, c, pa, ta, inh, f, e, d, si, pi); } -static char * -convert_mb_str (UINT cp_to, size_t *len_to, - UINT cp_from, const char *ptr_from, size_t len_from) +static void +convert_mb_str (UINT cp_to, char *ptr_to, size_t *len_to, + UINT cp_from, const char *ptr_from, size_t len_from, + mbstate_t *mbp) { - char *buf; size_t nlen; - if (cp_to != cp_from) - { - size_t wlen = - MultiByteToWideChar (cp_from, 0, ptr_from, len_from, NULL, 0); - wchar_t *wbuf = (wchar_t *) - HeapAlloc (GetProcessHeap (), 0, wlen * sizeof (wchar_t)); - wlen = - MultiByteToWideChar (cp_from, 0, ptr_from, len_from, wbuf, wlen); - nlen = WideCharToMultiByte (cp_to, 0, wbuf, wlen, NULL, 0, NULL, NULL); - buf = (char *) HeapAlloc (GetProcessHeap (), 0, nlen); - nlen = WideCharToMultiByte (cp_to, 0, wbuf, wlen, buf, nlen, NULL, NULL); - HeapFree (GetProcessHeap (), 0, wbuf); - } + tmp_pathbuf tp; + wchar_t *wbuf = tp.w_get (); + int wlen = 0; + if (cp_from == CP_UTF7) + /* MB_ERR_INVALID_CHARS does not work properly for UTF-7. + Therefore, just convert string without checking */ + wlen = MultiByteToWideChar (cp_from, 0, ptr_from, len_from, + wbuf, NT_MAX_PATH); else { - /* Just copy */ - buf = (char *) HeapAlloc (GetProcessHeap (), 0, len_from); - memcpy (buf, ptr_from, len_from); - nlen = len_from; + char *tmpbuf = tp.c_get (); + memcpy (tmpbuf, mbp->__value.__wchb, mbp->__count); + if (mbp->__count + len_from > NT_MAX_PATH) + len_from = NT_MAX_PATH - mbp->__count; + memcpy (tmpbuf + mbp->__count, ptr_from, len_from); + int total_len = mbp->__count + len_from; + mbp->__count = 0; + int mblen = 0; + for (const char *p = tmpbuf; p < tmpbuf + total_len; p += mblen) + /* Max bytes in multibyte char is 4. */ + for (mblen = 1; mblen <= 4; mblen ++) + { + /* Try conversion */ + int l = MultiByteToWideChar (cp_from, MB_ERR_INVALID_CHARS, + p, mblen, + wbuf + wlen, NT_MAX_PATH - wlen); + if (l) + { /* Conversion Success */ + wlen += l; + break; + } + else if (mblen == 4) + { /* Conversion Fail */ + l = MultiByteToWideChar (cp_from, 0, p, 1, + wbuf + wlen, NT_MAX_PATH - wlen); + wlen += l; + mblen = 1; + break; + } + else if (p + mblen == tmpbuf + total_len) + { /* Multibyte char incomplete */ + memcpy (mbp->__value.__wchb, p, mblen); + mbp->__count = mblen; + break; + } + /* Retry conversion with extended length */ + } } + nlen = WideCharToMultiByte (cp_to, 0, wbuf, wlen, + ptr_to, *len_to, NULL, NULL); *len_to = nlen; - return buf; -} - -static void -mb_str_free (char *ptr) -{ - HeapFree (GetProcessHeap (), 0, ptr); } static bool @@ -1613,9 +1637,18 @@ fhandler_pty_master::write (const void *ptr, size_t len) if current application is native console application. */ if (to_be_read_from_pcon () && get_ttyp ()->h_pseudo_console) { - size_t nlen; - char *buf = convert_mb_str (CP_UTF8, &nlen, get_ttyp ()->term_code_page, - (const char *) ptr, len); + tmp_pathbuf tp; + char *buf = (char *) ptr; + size_t nlen = len; + if (get_ttyp ()->term_code_page != CP_UTF8) + { + static mbstate_t mbp; + buf = tp.c_get (); + nlen = NT_MAX_PATH; + convert_mb_str (CP_UTF8, buf, &nlen, + get_ttyp ()->term_code_page, (const char *) ptr, len, + &mbp); + } WaitForSingleObject (input_mutex, INFINITE); @@ -1650,7 +1683,6 @@ fhandler_pty_master::write (const void *ptr, size_t len) get_ttyp ()->pcon_start = false; } ReleaseMutex (input_mutex); - mb_str_free (buf); return len; } @@ -1658,7 +1690,6 @@ fhandler_pty_master::write (const void *ptr, size_t len) ReleaseMutex (input_mutex); - mb_str_free (buf); return len; } @@ -1975,13 +2006,16 @@ DWORD fhandler_pty_master::pty_master_fwd_thread () { DWORD rlen; - char outbuf[65536]; + tmp_pathbuf tp; + char *outbuf = tp.c_get (); + char *mbbuf = tp.c_get (); + static mbstate_t mbp; termios_printf ("Started."); for (;;) { get_ttyp ()->pcon_last_time = GetTickCount (); - if (!ReadFile (from_slave, outbuf, sizeof outbuf, &rlen, NULL)) + if (!ReadFile (from_slave, outbuf, NT_MAX_PATH, &rlen, NULL)) { termios_printf ("ReadFile for forwarding failed, %E"); break; @@ -2031,12 +2065,15 @@ fhandler_pty_master::pty_master_fwd_thread () else state = 0; - size_t nlen; - char *buf = convert_mb_str (get_ttyp ()->term_code_page, - &nlen, CP_UTF8, ptr, wlen); + if (get_ttyp ()->term_code_page != CP_UTF8) + { + size_t nlen = NT_MAX_PATH; + convert_mb_str (get_ttyp ()->term_code_page, mbbuf, &nlen, + CP_UTF8, ptr, wlen, &mbp); - ptr = buf; - wlen = rlen = nlen; + ptr = mbbuf; + wlen = rlen = nlen; + } /* OPOST processing was already done in pseudo console, so just write it to to_master_cyg. */ @@ -2051,15 +2088,20 @@ fhandler_pty_master::pty_master_fwd_thread () ptr += written; wlen = (rlen -= written); } - mb_str_free (buf); continue; } - size_t nlen; - char *buf = convert_mb_str (get_ttyp ()->term_code_page, &nlen, - GetConsoleOutputCP (), ptr, wlen); - ptr = buf; - wlen = rlen = nlen; + UINT cp_from = GetConsoleOutputCP (); + if (get_ttyp ()->term_code_page != cp_from) + { + size_t nlen = NT_MAX_PATH; + convert_mb_str (get_ttyp ()->term_code_page, mbbuf, &nlen, + cp_from, ptr, wlen, &mbp); + + ptr = mbbuf; + wlen = rlen = nlen; + } + acquire_output_mutex (INFINITE); while (rlen>0) { @@ -2072,7 +2114,6 @@ fhandler_pty_master::pty_master_fwd_thread () wlen = (rlen -= wlen); } release_output_mutex (); - mb_str_free (buf); } return 0; }
reply other threads:[~2020-09-09 21:44 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200909214444.15C123857C59@sourceware.org \ --to=corinna@sourceware.org \ --cc=cygwin-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).