diff -r 21069f8841d0 -r 4cb876518d2a Makefile --- a/Makefile Wed Sep 28 17:39:22 2011 +0900 +++ b/Makefile Fri Oct 07 16:54:23 2011 +0900 @@ -39,7 +39,7 @@ OSRCS += eln.c SRCS += tokenizern.c historyn.c CLEANFILES+=tokenizern.c.tmp tokenizern.c historyn.c.tmp historyn.c -CPPFLAGS+=-DWIDECHAR +CPPFLAGS+=-DWIDECHAR -DUSE_UCS_CODEPOINT .endif LIBEDITDIR?=${.CURDIR} diff -r 21069f8841d0 -r 4cb876518d2a chared.c --- a/chared.c Wed Sep 28 17:39:22 2011 +0900 +++ b/chared.c Fri Oct 07 16:54:23 2011 +0900 @@ -45,6 +45,7 @@ * chared.c: Character editor utilities */ #include +#include #include "el.h" private void ch__clearmacro (EditLine *); @@ -211,7 +212,7 @@ protected int cv__isword(Int p) { - if (Isalnum(p) || p == '_') + if (Isalnum(p) || p == CHR('_')) return 1; if (Isgraph(p)) return 2; @@ -663,7 +664,7 @@ for (;;) { el->el_line.cursor = cp; - *cp = ' '; + *cp = CHR(' '); el->el_line.lastchar = cp + 1; re_refresh(el); @@ -673,10 +674,9 @@ break; } - switch (ch) { - - case 0010: /* Delete and backspace */ - case 0177: + switch (ct_wctob(ch)) { + case 0010: /* backspace */ + case 0177: /* Delete - not CSI */ if (len == 0) { len = -1; break; @@ -684,9 +684,9 @@ cp--; continue; - case 0033: /* ESC */ + case 0033: /* ESC - not CSI */ case '\r': /* Newline */ - case '\n': + case '\n': /* Form feed */ buf[len] = ch; break; @@ -702,7 +702,7 @@ break; } - el->el_line.buffer[0] = '\0'; + el->el_line.buffer[0] = CHR('\0'); el->el_line.lastchar = el->el_line.buffer; el->el_line.cursor = el->el_line.buffer; return (int)len; @@ -724,7 +724,7 @@ return 0; else { for (ptr = el->el_line.cursor - 1; - ptr >= el->el_line.buffer && *ptr != '\n'; + ptr >= el->el_line.buffer && *ptr != CHR('\n'); ptr--) continue; return (int)(el->el_line.cursor - ptr - 1); diff -r 21069f8841d0 -r 4cb876518d2a chartype.c --- a/chartype.c Wed Sep 28 17:39:22 2011 +0900 +++ b/chartype.c Fri Oct 07 16:54:23 2011 +0900 @@ -79,7 +79,9 @@ { char *dst; ssize_t used = 0; + size_t width; + /* XXX: stateful encoding is not supported */ if (!s) return NULL; if (!conv->cbuff) @@ -87,25 +89,37 @@ if (!conv->cbuff) return NULL; +#define do_resize(required) \ +do { \ + ssize_t remain = \ + (ssize_t)(conv->csize - (size_t)(dst - conv->cbuff)); \ + if (remain < (ssize_t)(required)) { \ + used = dst - conv->cbuff; \ + ct_conv_buff_resize( \ + conv, \ + conv->csize + \ + (/*CONSTCOND*/required>CT_BUFSIZ ? required:CT_BUFSIZ), \ + (size_t)0); \ + if (!conv->cbuff) \ + return NULL; \ + dst = conv->cbuff + used; \ + } \ +} while (/*CONSTCOND*/0) + dst = conv->cbuff; while (*s) { - used = (ssize_t)(conv->csize - (size_t)(dst - conv->cbuff)); - if (used < 5) { - used = dst - conv->cbuff; - ct_conv_buff_resize(conv, conv->csize + CT_BUFSIZ, - (size_t)0); - if (!conv->cbuff) - return NULL; - dst = conv->cbuff + used; - } - used = ct_encode_char(dst, (size_t)5, *s); + width = ct_enc_width(*s); + do_resize(width); + used = ct_encode_char(dst, width, *s); if (used == -1) /* failed to encode, need more buffer space */ abort(); ++s; dst += used; } + do_resize(1); *dst = '\0'; return conv->cbuff; +#undef do_resize } public Char * @@ -120,7 +134,7 @@ if (!conv->wbuff) return NULL; - len = ct_mbstowcs(NULL, s, (size_t)0); + len = ct_mbstowcs(NULL, s, 0); if (len == (size_t)-1) return NULL; if (len > conv->wsize) @@ -143,8 +157,14 @@ /* Make sure we have enough space in the conversion buffer to store all * the argv strings. */ - for (i = 0, bufspace = 0; i < argc; ++i) - bufspace += argv[i] ? strlen(argv[i]) + 1 : 0; + for (i = 0, bufspace = 0; i < argc; ++i) { + size_t len = 0; + if (argv[i]) + len = ct_mbstowcs(NULL, argv[i], 0); + if (len == (size_t)-1) + len = 0; + bufspace += len + 1; + } ct_conv_buff_resize(conv, (size_t)0, bufspace); if (!conv->wsize) return NULL; @@ -157,7 +177,7 @@ continue; } else { wargv[i] = p; - bytes = (ssize_t)mbstowcs(p, argv[i], bufspace); + bytes = (ssize_t)ct_mbstowcs(p, argv[i], bufspace); } if (bytes == -1) { el_free(wargv); @@ -172,40 +192,33 @@ } +protected ssize_t +ct_encode_char(char *dst, size_t len, Char c) +{ + char buf[MB_LEN_MAX]; + ssize_t l = 0; + + l = (ssize_t)ct_wctomb(buf, c); + if (dst) { + if (l == -1 || (ssize_t)len < l) + return -1; + memcpy(dst, buf, (size_t)l); + } + + return l; +} + protected size_t ct_enc_width(Char c) { - /* UTF-8 encoding specific values */ - if (c < 0x80) - return 1; - else if (c < 0x0800) - return 2; - else if (c < 0x10000) - return 3; - else if (c < 0x110000) - return 4; - else - return 0; /* not a valid codepoint */ -} + ssize_t ret = ct_encode_char(NULL, 0, c); -protected ssize_t -ct_encode_char(char *dst, size_t len, Char c) -{ - ssize_t l = 0; - if (len < ct_enc_width(c)) - return -1; - l = ct_wctomb(dst, c); - - if (l < 0) { - ct_wctomb_reset; - l = 0; - } - return l; + return ret >=0 ? ret:0; } #endif protected const Char * -ct_visual_string(const Char *s) +ct_visual_string(EditLine *el, const Char *s) { static Char *buff = NULL; static size_t buffsize = 0; @@ -221,7 +234,8 @@ } dst = buff; while (*s) { - used = ct_visual_char(dst, buffsize - (size_t)(dst - buff), *s); + used = ct_visual_char(el, dst, buffsize - (size_t)(dst - buff), + *s); if (used == -1) { /* failed to encode, need more buffer space */ used = dst - buff; buffsize += CT_BUFSIZ; @@ -253,10 +267,14 @@ } - protected int -ct_visual_width(Char c) +/*ARGSUSED*/ +ct_visual_width(EditLine *el __attribute__((__unused__)), Char c) { +#ifdef WIDECHAR + char buf[MB_LEN_MAX]; + int buflen; +#endif int t = ct_chr_class(c); switch (t) { case CHTYPE_ASCIICTL: @@ -269,16 +287,25 @@ case CHTYPE_PRINT: return wcwidth(c); case CHTYPE_NONPRINT: - if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */ - return 8; /* \U+12345 */ - else - return 7; /* \U+1234 */ -#else +#ifdef USE_UCS_CODEPOINT + if ((el->el_flags & MULTIBYTE_UCS)) { + /* prefer standard 4-byte display over 5-byte */ + if (c > 0xffff) + return 8; /* \U+12345 */ + else + return 7; /* \U+1234 */ + } +#endif /* USE_UCS_CODEPOINT */ + buflen = ct_wctomb(buf, c); + if (buflen == -1) + return 0; /* just ignore */ + return buflen*4; /* \123\123...\123 */ +#else /* WIDECHAR */ case CHTYPE_PRINT: return 1; case CHTYPE_NONPRINT: return 4; /* \123 */ -#endif +#endif /* WIDECHAR */ default: return 0; /* should not happen */ } @@ -286,20 +313,28 @@ protected ssize_t -ct_visual_char(Char *dst, size_t len, Char c) +/*ARGSUSED*/ +ct_visual_char(EditLine *el __attribute__((__unused__)), Char *dst, size_t len, + Char c) { +#ifdef WIDECHAR + char buf[MB_LEN_MAX]; + int buflen, i; +#endif int t = ct_chr_class(c); switch (t) { case CHTYPE_TAB: case CHTYPE_NL: case CHTYPE_ASCIICTL: + case CHTYPE_ASCIIDEL: if (len < 2) return -1; /* insufficient space */ - *dst++ = '^'; - if (c == '\177') - *dst = '?'; /* DEL -> ^? */ + *dst++ = CHR('^'); + if (t == CHTYPE_ASCIIDEL) + *dst = CHR('?'); /* DEL -> ^? */ else - *dst = c | 0100; /* uncontrolify it */ + /* uncontrolify it */ + *dst = STR("@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_")[ct_wctob(c) & 0037]; return 2; case CHTYPE_PRINT: if (len < 1) @@ -309,29 +344,45 @@ case CHTYPE_NONPRINT: /* we only use single-width glyphs for display, * so this is right */ - if ((ssize_t)len < ct_visual_width(c)) + if ((ssize_t)len < ct_visual_width(el, c)) return -1; /* insufficient space */ +#define tooctaldigit(v) (CHR('0'+((v) & 7))) #ifdef WIDECHAR - *dst++ = '\\'; - *dst++ = 'U'; - *dst++ = '+'; -#define tohexdigit(v) "0123456789ABCDEF"[v] - if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */ - *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf); - *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf); - *dst++ = tohexdigit(((unsigned int) c >> 8) & 0xf); - *dst++ = tohexdigit(((unsigned int) c >> 4) & 0xf); - *dst = tohexdigit(((unsigned int) c ) & 0xf); - return c > 0xffff ? 8 : 7; -#else - *dst++ = '\\'; -#define tooctaldigit(v) ((v) + '0') - *dst++ = tooctaldigit(((unsigned int) c >> 6) & 0x7); - *dst++ = tooctaldigit(((unsigned int) c >> 3) & 0x7); - *dst++ = tooctaldigit(((unsigned int) c ) & 0x7); -#endif - /*FALLTHROUGH*/ - /* these two should be handled outside this function */ +#ifdef USE_UCS_CODEPOINT + if ((el->el_flags & MULTIBYTE_UCS)) { + *dst++ = '\\'; + *dst++ = 'U'; + *dst++ = '+'; +#define tohexdigit(v) (STR("0123456789ABCDEF")[v]) + /* prefer standard 4-byte display over 5-byte */ + if (c > 0xffff) + *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf); + *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf); + *dst++ = tohexdigit(((unsigned int) c >> 8) & 0xf); + *dst++ = tohexdigit(((unsigned int) c >> 4) & 0xf); + *dst = tohexdigit(((unsigned int) c ) & 0xf); + return c > 0xffff ? 8 : 7; + } +#endif /* USE_UCS_CODEPOINT */ + buflen = ct_wctomb(buf, c); + if (buflen == -1) + return -1; + for (i=0; i> 6); + *dst++ = tooctaldigit(byte >> 3); + *dst++ = tooctaldigit(byte ); + } + return buflen*4; +#else /* WIDECHAR */ + *dst++ = CHR('\\'); + *dst++ = tooctaldigit((unsigned int) c >> 6); + *dst++ = tooctaldigit((unsigned int) c >> 3); + *dst++ = tooctaldigit((unsigned int) c ); + return 4; +#endif /* WIDECHAR */ + default: /* we should never hit the default */ return 0; } @@ -343,11 +394,13 @@ protected int ct_chr_class(Char c) { - if (c == '\t') + if (c == CHR('\t')) return CHTYPE_TAB; - else if (c == '\n') + else if (c == CHR('\n')) return CHTYPE_NL; - else if (IsASCII(c) && Iscntrl(c)) + else if (Iscntrl(c) && ct_wctob(c) == 0177) /* XXX: not CSI */ + return CHTYPE_ASCIIDEL; + else if (Iscntrl(c) && IsASCII(c)) return CHTYPE_ASCIICTL; else if (Isprint(c)) return CHTYPE_PRINT; diff -r 21069f8841d0 -r 4cb876518d2a chartype.h --- a/chartype.h Wed Sep 28 17:39:22 2011 +0900 +++ b/chartype.h Fri Oct 07 16:54:23 2011 +0900 @@ -36,44 +36,92 @@ #ifndef _h_chartype_f #define _h_chartype_f - - #ifdef WIDECHAR -/* Ideally we should also test the value of the define to see if it - * supports non-BMP code points without requiring UTF-16, but nothing - * seems to actually advertise this properly, despite Unicode 3.1 having - * been around since 2001... */ -#if !defined(__NetBSD__) && !defined(__sun) && !(defined(__APPLE__) && defined(__MACH__)) -#ifndef __STDC_ISO_10646__ -/* In many places it is assumed that the first 127 code points are ASCII - * compatible, so ensure wchar_t indeed does ISO 10646 and not some other - * funky encoding that could break us in weird and wonderful ways. */ - #error wchar_t must store ISO 10646 characters -#endif -#endif +#ifdef __STDC_ISO_10646__ /* Oh for a with char32_t and __STDC_UTF_32__ in it... + * Surrogate pair cannot be handled correctly. * ref: ISO/IEC DTR 19769 */ #if WCHAR_MAX < INT32_MAX #warning Build environment does not support non-BMP characters #endif -#define ct_mbtowc mbtowc -#define ct_mbtowc_reset mbtowc(0,0,(size_t)0) -#define ct_wctomb wctomb -#define ct_wctomb_reset wctomb(0,0) -#define ct_wcstombs wcstombs -#define ct_mbstowcs mbstowcs +#else /* __STDC_ISO_10646__ */ + +#ifdef USE_UCS_CODEPOINT +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__sun) +/* assumes that all UTF-8 locales use UCS4 representation in wchar_t. */ +#define UTF8_CODESET_NAME "UTF-8" +#else +#warning UCS codepoint not supported +#undef USE_UCS_CODEPOINT +#endif +#endif /* USE_UCS_CODEPOINT */ + +#endif /* __STDC_ISO_10646__ */ + + +#define ct_mbstate_reset(s) memset((s), 0, sizeof (mbstate_t)) +#define ct_wctob(wc) wctob((wc)) + +/* special functions to prevent disturbing the internal state of + * mb/wc functions. + */ +static __inline int +ct_mbtowc(wchar_t *pwc, const char *s, size_t n) +{ + size_t ret; + mbstate_t state; + ct_mbstate_reset(&state); + ret = mbrtowc(pwc, s, n, &state); + return ret == (size_t)-2 || ret == (size_t)-1 ? -1 : (int)ret; +} +static __inline int +ct_wctomb(char *s, const wchar_t wc) +{ + size_t ret; + mbstate_t state; + ct_mbstate_reset(&state); + ret = wcrtomb(s, wc, &state); + return ret == (size_t)-2 || ret == (size_t)-1 ? -1 : (int)ret; +} +static __inline size_t +ct_mbstowcs(wchar_t *pwcs, const char *s, size_t n) +{ + mbstate_t state; + ct_mbstate_reset(&state); + return mbsrtowcs(pwcs, &s, n, &state); +} +static __inline size_t +ct_wcstombs(char *s, const wchar_t *pwcs, size_t n) +{ + mbstate_t state; + ct_mbstate_reset(&state); + return wcsrtombs(s, &pwcs, n, &state); +} +static __inline int +ct_mblen(const char *s, size_t n) +{ + size_t ret; + mbstate_t state; + ct_mbstate_reset(&state); + ret = mbrlen(s, n, &state); + return ret == (size_t)-2 || ret == (size_t)-1 ? -1 : (int)ret; +} + #define Char wchar_t #define Int wint_t +#define CT_EOF WEOF +#define CharToInt(wc) ((wint_t)wc) #define FUN(prefix,rest) prefix ## _w ## rest #define FUNW(type) type ## _w #define TYPE(type) type ## W #define FSTR "%ls" -#define STR(x) L ## x +#define STR(x) L ## x +#define CHR(x) L ## x #define UC(c) c #define Isalpha(x) iswalpha(x) #define Isalnum(x) iswalnum(x) @@ -88,7 +136,7 @@ #define Toupper(x) towupper(x) #define Tolower(x) towlower(x) -#define IsASCII(x) (x < 0x100) +#define IsASCII(x) (isascii(wctob(x))) #define Strlen(x) wcslen(x) #define Strchr(s,c) wcschr(s,c) @@ -109,20 +157,20 @@ #else /* NARROW */ -#define ct_mbtowc error -#define ct_mbtowc_reset -#define ct_wctomb error -#define ct_wctomb_reset #define ct_wcstombs(a, b, c) (strncpy(a, b, c), strlen(a)) #define ct_mbstowcs(a, b, c) (strncpy(a, b, c), strlen(a)) +#define ct_wctob(wc) ((int)(unsigned char)(wc)) #define Char char #define Int int +#define CT_EOF EOF +#define CharToInt(c) ((int)(unsigned char)(c)) #define FUN(prefix,rest) prefix ## _ ## rest #define FUNW(type) type #define TYPE(type) type #define FSTR "%s" -#define STR(x) x +#define STR(x) x +#define CHR(x) x #define UC(c) (unsigned char)(c) #define Isalpha(x) isalpha((unsigned char)x) @@ -205,38 +253,40 @@ * character cannot be encoded, -1 if there was not enough space available). */ /* The maximum buffer size to hold the most unwieldly visual representation, - * in this case \U+nnnnn. */ -#define VISUAL_WIDTH_MAX ((size_t)8) + * in this case \123\123...\123. */ +#define VISUAL_WIDTH_MAX ((size_t)(MB_LEN_MAX+1)) /* The terminal is thought of in terms of X columns by Y lines. In the cases * where a wide character takes up more than one column, the adjacent * occupied column entries will contain this faux character. */ -#define MB_FILL_CHAR ((Char)-1) +#define MB_FILL_CHAR (CT_EOF) /* Visual width of character c, taking into account ^? , \0177 and \U+nnnnn * style visual expansions. */ -protected int ct_visual_width(Char); +protected int ct_visual_width(EditLine *, Char); /* Turn the given character into the appropriate visual format, matching * the width given by ct_visual_width(). Returns the number of characters used * up, or -1 if insufficient space. Buffer length is in count of Char's. */ -protected ssize_t ct_visual_char(Char *, size_t, Char); +protected ssize_t ct_visual_char(EditLine *, Char *, size_t, Char); /* Convert the given string into visual format, using the ct_visual_char() * function. Uses a static buffer, so not threadsafe. */ -protected const Char *ct_visual_string(const Char *); +protected const Char *ct_visual_string(EditLine *, const Char *); /* printable character, use ct_visual_width() to find out display width */ #define CHTYPE_PRINT ( 0) /* control character found inside the ASCII portion of the charset */ #define CHTYPE_ASCIICTL (-1) +/* a DEL */ +#define CHTYPE_ASCIIDEL (-2) /* a \t */ -#define CHTYPE_TAB (-2) +#define CHTYPE_TAB (-3) /* a \n */ -#define CHTYPE_NL (-3) +#define CHTYPE_NL (-4) /* non-printable character */ -#define CHTYPE_NONPRINT (-4) +#define CHTYPE_NONPRINT (-5) /* classification of character c, as one of the above defines */ protected int ct_chr_class(Char c); #endif diff -r 21069f8841d0 -r 4cb876518d2a common.c --- a/common.c Wed Sep 28 17:39:22 2011 +0900 +++ b/common.c Fri Oct 07 16:54:23 2011 +0900 @@ -56,7 +56,7 @@ { re_goto_bottom(el); - *el->el_line.lastchar = '\0'; + *el->el_line.lastchar = CHR('\0'); return CC_EOF; } @@ -70,7 +70,7 @@ { int count = el->el_state.argument; - if (c == '\0') + if (c == CHR('\0')) return CC_ERROR; if (el->el_line.lastchar + el->el_state.argument >= @@ -388,12 +388,12 @@ if (el->el_state.doingarg) { /* if doing an arg, add this in... */ if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) - el->el_state.argument = c - '0'; + el->el_state.argument = c - CHR('0'); else { if (el->el_state.argument > 1000000) return CC_ERROR; el->el_state.argument = - (el->el_state.argument * 10) + (c - '0'); + (el->el_state.argument * 10) + (c - CHR('0')); } return CC_ARGHACK; } @@ -417,9 +417,9 @@ if (el->el_state.argument > 1000000) return CC_ERROR; el->el_state.argument = (el->el_state.argument * 10) + - (c - '0'); + (c - CHR('0')); } else { /* else starting an argument */ - el->el_state.argument = c - '0'; + el->el_state.argument = c - CHR('0'); el->el_state.doingarg = 1; } return CC_ARGHACK; @@ -552,8 +552,8 @@ { re_goto_bottom(el); - *el->el_line.lastchar++ = '\n'; - *el->el_line.lastchar = '\0'; + *el->el_line.lastchar++ = CHR('\n'); + *el->el_line.lastchar = CHR('\0'); return CC_NEWLINE; } @@ -647,7 +647,7 @@ int sv_event = el->el_history.eventno; el->el_chared.c_undo.len = -1; - *el->el_line.lastchar = '\0'; /* just in case */ + *el->el_line.lastchar = CHR('\0'); /* just in case */ if (el->el_history.eventno == 0) { /* save the current buffer * away */ @@ -684,7 +684,7 @@ el_action_t beep = CC_REFRESH, rval; el->el_chared.c_undo.len = -1; - *el->el_line.lastchar = '\0'; /* just in case */ + *el->el_line.lastchar = CHR('\0'); /* just in case */ el->el_history.eventno -= el->el_state.argument; @@ -714,7 +714,7 @@ el->el_chared.c_vcmd.action = NOP; el->el_chared.c_undo.len = -1; - *el->el_line.lastchar = '\0'; /* just in case */ + *el->el_line.lastchar = CHR('\0'); /* just in case */ if (el->el_history.eventno < 0) { #ifdef DEBUG_EDIT (void) fprintf(el->el_errfile, @@ -782,7 +782,7 @@ el->el_chared.c_vcmd.action = NOP; el->el_chared.c_undo.len = -1; - *el->el_line.lastchar = '\0'; /* just in case */ + *el->el_line.lastchar = CHR('\0'); /* just in case */ if (el->el_history.eventno == 0) return CC_ERROR; @@ -836,11 +836,11 @@ /* * Move to the line requested */ - if (*(ptr = el->el_line.cursor) == '\n') + if (*(ptr = el->el_line.cursor) == CHR('\n')) ptr--; for (; ptr >= el->el_line.buffer; ptr--) - if (*ptr == '\n' && --el->el_state.argument <= 0) + if (*ptr == CHR('\n') && --el->el_state.argument <= 0) break; if (el->el_state.argument > 0) @@ -849,14 +849,14 @@ /* * Move to the beginning of the line */ - for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) + for (ptr--; ptr >= el->el_line.buffer && *ptr != CHR('\n'); ptr--) continue; /* * Move to the character requested */ for (ptr++; - nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; + nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != CHR('\n'); ptr++) continue; @@ -880,7 +880,7 @@ * Move to the line requested */ for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) - if (*ptr == '\n' && --el->el_state.argument <= 0) + if (*ptr == CHR('\n') && --el->el_state.argument <= 0) break; if (el->el_state.argument > 0) @@ -890,7 +890,7 @@ * Move to the character requested */ for (ptr++; - nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; + nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != CHR('\n'); ptr++) continue; @@ -911,7 +911,7 @@ int tmplen; tmplen = c_gets(el, tmpbuf, STR("\n: ")); - terminal__putc(el, '\n'); + terminal__putc(el, CHR('\n')); if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) terminal_beep(el); diff -r 21069f8841d0 -r 4cb876518d2a el.c --- a/el.c Wed Sep 28 17:39:22 2011 +0900 +++ b/el.c Fri Oct 07 16:54:23 2011 +0900 @@ -86,9 +86,18 @@ */ el->el_flags = 0; #ifdef WIDECHAR - if (setlocale(LC_CTYPE, NULL) != NULL){ - if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) - el->el_flags |= CHARSET_IS_UTF8; + if (MB_CUR_MAX > 1) { + if (ct_mblen(NULL, 0)) + el->el_flags |= MULTIBYTE_STATEFUL; + else { + el->el_flags |= MULTIBYTE_STATELESS; +#ifdef USE_UCS_CODEPOINT +#ifndef __STDC_ISO_10646__ + if (!strcmp(nl_langinfo(CODESET), UTF8_CODESET_NAME)) +#endif /* __STDC_ISO_10646__ */ + el->el_flags |= MULTIBYTE_UCS; +#endif /* USE_UCS_CODEPOINT */ + } } #endif @@ -273,7 +282,8 @@ void *ptr = va_arg(ap, void *); rv = hist_set(el, func, ptr); - if (!(el->el_flags & CHARSET_IS_UTF8)) + if (!(el->el_flags & MULTIBYTE_STATELESS) && + !(el->el_flags & MULTIBYTE_STATEFUL)) el->el_flags &= ~NARROW_HISTORY; break; } @@ -547,13 +557,13 @@ dptr = ct_decode_string(ptr, &el->el_scratch); if (!dptr) continue; - if (len > 0 && dptr[len - 1] == '\n') + if (len > 0 && dptr[len - 1] == CHR('\n')) --len; /* loop until first non-space char or EOL */ - while (*dptr != '\0' && Isspace(*dptr)) + while (*dptr != CHR('\0') && Isspace(*dptr)) dptr++; - if (*dptr == '#') + if (*dptr == CHR('#')) continue; /* ignore, this is a comment line */ if ((error = parse_line(el, dptr)) == -1) break; diff -r 21069f8841d0 -r 4cb876518d2a el.h --- a/el.h Wed Sep 28 17:39:22 2011 +0900 +++ b/el.h Fri Oct 07 16:54:23 2011 +0900 @@ -53,14 +53,18 @@ #define EL_BUFSIZ ((size_t)1024) /* Maximum line size */ -#define HANDLE_SIGNALS 0x01 -#define NO_TTY 0x02 -#define EDIT_DISABLED 0x04 -#define UNBUFFERED 0x08 -#define CHARSET_IS_UTF8 0x10 -#define IGNORE_EXTCHARS 0x20 /* Ignore characters read > 0xff */ -#define NARROW_HISTORY 0x40 -#define NARROW_READ 0x80 +#define HANDLE_SIGNALS 0x0001 +#define NO_TTY 0x0002 +#define EDIT_DISABLED 0x0004 +#define UNBUFFERED 0x0008 +#define MULTIBYTE_STATELESS 0x0010 +#ifdef USE_UCS_CODEPOINT +#define MULTIBYTE_UCS 0x0020 +#endif +#define MULTIBYTE_STATEFUL 0x0040 /* XXX: not supported */ +#define IGNORE_EXTCHARS 0x0080 /* Ignore characters read > 0xff */ +#define NARROW_HISTORY 0x0100 +#define NARROW_READ 0x0200 typedef int bool_t; /* True or not */ diff -r 21069f8841d0 -r 4cb876518d2a eln.c --- a/eln.c Wed Sep 28 17:39:22 2011 +0900 +++ b/eln.c Fri Oct 07 16:54:23 2011 +0900 @@ -50,14 +50,16 @@ int num_read; wchar_t wc = 0; - if (!(el->el_flags & CHARSET_IS_UTF8)) + if (!(el->el_flags & MULTIBYTE_STATELESS) && + !(el->el_flags & MULTIBYTE_STATEFUL)) el->el_flags |= IGNORE_EXTCHARS; num_read = el_wgetc (el, &wc); - if (!(el->el_flags & CHARSET_IS_UTF8)) + if (!(el->el_flags & MULTIBYTE_STATELESS) && + !(el->el_flags & MULTIBYTE_STATEFUL)) el->el_flags &= ~IGNORE_EXTCHARS; if (num_read > 0) - *cp = (char)wc; + *cp = (char)wctob(wc); return num_read; } @@ -76,9 +78,7 @@ { const wchar_t *tmp; - el->el_flags |= IGNORE_EXTCHARS; tmp = el_wgets(el, nread); - el->el_flags &= ~IGNORE_EXTCHARS; return ct_encode_string(tmp, &el->el_lgcyconv); } @@ -90,7 +90,7 @@ const wchar_t **wargv; wargv = (const wchar_t **) - ct_decode_argv(argc, argv, &el->el_lgcyconv); + __UNCONST(ct_decode_argv(argc, argv, &el->el_lgcyconv)); if (!wargv) return -1; ret = el_wparse(el, argc, wargv); @@ -154,7 +154,7 @@ break; argv[0] = NULL; wargv = (const wchar_t **) - ct_decode_argv(i, argv, &el->el_lgcyconv); + __UNCONST(ct_decode_argv(i, argv, &el->el_lgcyconv)); if (!wargv) { ret = -1; goto out; diff -r 21069f8841d0 -r 4cb876518d2a filecomplete.c --- a/filecomplete.c Wed Sep 28 17:39:22 2011 +0900 +++ b/filecomplete.c Fri Oct 07 16:54:23 2011 +0900 @@ -52,8 +52,26 @@ #include "histedit.h" #include "filecomplete.h" -static const Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', - '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; +static const Char break_chars[] = { + CHR(' '), + CHR('\t'), + CHR('\n'), + CHR('\"'), + CHR('\\'), + CHR('\''), + CHR('`'), + CHR('@'), /* XXX: not portable character */ + CHR('$'), + CHR('>'), + CHR('<'), + CHR('='), + CHR(';'), + CHR('|'), + CHR('&'), + CHR('{'), + CHR('('), + CHR('\0') +}; /********************************/ @@ -448,7 +466,7 @@ len = (size_t)(li->cursor - ctemp); temp = el_malloc((len + 1) * sizeof(*temp)); (void)Strncpy(temp, ctemp, len); - temp[len] = '\0'; + temp[len] = CHR('\0'); /* these can be used by function called in completion_matches() */ /* or (*attempted_completion_function)() */ diff -r 21069f8841d0 -r 4cb876518d2a hist.c --- a/hist.c Wed Sep 28 17:39:22 2011 +0900 +++ b/hist.c Fri Oct 07 16:54:23 2011 +0900 @@ -130,14 +130,15 @@ } (void) Strncpy(el->el_line.buffer, hp, (size_t)(el->el_line.limit - el->el_line.buffer)); - el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = '\0'; + el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = + CHR('\0'); el->el_line.lastchar = el->el_line.buffer + Strlen(el->el_line.buffer); if (el->el_line.lastchar > el->el_line.buffer - && el->el_line.lastchar[-1] == '\n') + && el->el_line.lastchar[-1] == CHR('\n')) el->el_line.lastchar--; if (el->el_line.lastchar > el->el_line.buffer - && el->el_line.lastchar[-1] == ' ') + && el->el_line.lastchar[-1] == CHR(' ')) el->el_line.lastchar--; #ifdef KSHVI if (el->el_map.type == MAP_VI) @@ -200,7 +201,7 @@ if (!newbuf) return 0; - (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf)); + (void) memset(&newbuf[oldsz], 0, (newsz - oldsz) * sizeof(*newbuf)); el->el_history.last = newbuf + (el->el_history.last - el->el_history.buf); diff -r 21069f8841d0 -r 4cb876518d2a history.c --- a/history.c Wed Sep 28 17:39:22 2011 +0900 +++ b/history.c Fri Oct 07 16:54:23 2011 +0900 @@ -386,7 +386,7 @@ return -1; } (void) Strncpy(s, h->cursor->ev.str, len); - s[len - 1] = '\0'; + s[len - 1] = CHR('\0'); (void) Strncat(s, str, len - Strlen(s) - 1); h_free(evp->str); evp->str = s; diff -r 21069f8841d0 -r 4cb876518d2a keymacro.c --- a/keymacro.c Wed Sep 28 17:39:22 2011 +0900 +++ b/keymacro.c Fri Oct 07 16:54:23 2011 +0900 @@ -191,7 +191,7 @@ keymacro_add(EditLine *el, const Char *key, keymacro_value_t *val, int ntype) { - if (key[0] == '\0') { + if (key[0] == CHR('\0')) { (void) fprintf(el->el_errfile, "keymacro_add: Null extended-key not allowed.\n"); return; @@ -218,15 +218,16 @@ protected void keymacro_clear(EditLine *el, el_action_t *map, const Char *in) { -#ifdef WIDECHAR - if (*in > N_KEYS) /* can't be in the map */ - return; -#endif - if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) && + int ch = ct_wctob(*in); + + if (ch == EOF || ch >= N_KEYS) + return; + + if ((map[ch] == ED_SEQUENCE_LEAD_IN) && ((map == el->el_map.key && - el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) || + el->el_map.alt[ch] != ED_SEQUENCE_LEAD_IN) || (map == el->el_map.alt && - el->el_map.key[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN))) + el->el_map.key[ch] != ED_SEQUENCE_LEAD_IN))) (void) keymacro_delete(el, in); } @@ -239,7 +240,7 @@ keymacro_delete(EditLine *el, const Char *key) { - if (key[0] == '\0') { + if (key[0] == CHR('\0')) { (void) fprintf(el->el_errfile, "keymacro_delete: Null extended-key not allowed.\n"); return -1; @@ -264,7 +265,7 @@ if (el->el_keymacro.map == NULL && *key == 0) return; - el->el_keymacro.buf[0] = '"'; + el->el_keymacro.buf[0] = CHR('\"'); if (node_lookup(el, key, el->el_keymacro.map, (size_t)1) <= -1) /* key is not bound */ (void) fprintf(el->el_errfile, "Unbound extended key \"" FSTR @@ -294,7 +295,7 @@ } else { *val = ptr->val; if (ptr->type != XK_CMD) - *ch = '\0'; + *ch = CHR('\0'); return ptr->type; } } else { @@ -329,7 +330,7 @@ xm->sibling = node__get(*str); /* setup new node */ ptr = xm->sibling; } - if (*++str == '\0') { + if (*++str == CHR('\0')) { /* we're there */ if (ptr->next != NULL) { node__put(el, ptr->next); @@ -396,7 +397,7 @@ prev_ptr = xm; ptr = xm->sibling; } - if (*++str == '\0') { + if (*++str == CHR('\0')) { /* we're there */ if (prev_ptr == NULL) *inptr = ptr->sibling; @@ -503,7 +504,7 @@ /* If match put this char into el->el_keymacro.buf. Recurse */ if (ptr->ch == *str) { /* match found */ - used = ct_visual_char(el->el_keymacro.buf + cnt, + used = ct_visual_char(el, el->el_keymacro.buf + cnt, KEY_BUFSIZ - cnt, ptr->ch); if (used == -1) return -1; /* ran out of buffer space */ @@ -515,8 +516,8 @@ /* next node is null so key should be complete */ if (str[1] == 0) { size_t px = cnt + (size_t)used; - el->el_keymacro.buf[px] = '"'; - el->el_keymacro.buf[px + 1] = '\0'; + el->el_keymacro.buf[px] = CHR('\"'); + el->el_keymacro.buf[px + 1] = CHR('\0'); keymacro_kprint(el, el->el_keymacro.buf, &ptr->val, ptr->type); return 0; @@ -545,8 +546,8 @@ ssize_t used; if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */ - el->el_keymacro.buf[++cnt] = '"'; - el->el_keymacro.buf[++cnt] = '\0'; + el->el_keymacro.buf[++cnt] = CHR('\"'); + el->el_keymacro.buf[++cnt] = CHR('\0'); (void) fprintf(el->el_errfile, "Some extended keys too long for internal print buffer"); (void) fprintf(el->el_errfile, " \"" FSTR "...\"\n", @@ -561,12 +562,12 @@ return -1; } /* put this char at end of str */ - used = ct_visual_char(el->el_keymacro.buf + cnt, KEY_BUFSIZ - cnt, + used = ct_visual_char(el, el->el_keymacro.buf + cnt, KEY_BUFSIZ - cnt, ptr->ch); if (ptr->next == NULL) { /* print this key and function */ - el->el_keymacro.buf[cnt + (size_t)used ] = '"'; - el->el_keymacro.buf[cnt + (size_t)used + 1] = '\0'; + el->el_keymacro.buf[cnt + (size_t)used ] = CHR('\"'); + el->el_keymacro.buf[cnt + (size_t)used + 1] = CHR('\0'); keymacro_kprint(el, el->el_keymacro.buf, &ptr->val, ptr->type); } else (void) node_enum(el, ptr->next, cnt + (size_t)used); @@ -593,7 +594,7 @@ switch (ntype) { case XK_STR: case XK_EXE: - (void) keymacro__decode_str(val->str, unparsbuf, + (void) keymacro__decode_str(el, val->str, unparsbuf, sizeof(unparsbuf), ntype == XK_STR ? "\"\"" : "[]"); (void) fprintf(el->el_outfile, fmt, @@ -634,7 +635,8 @@ * Make a printable version of the ey */ protected size_t -keymacro__decode_str(const Char *str, char *buf, size_t len, const char *sep) +keymacro__decode_str(EditLine *el, const Char *str, char *buf, size_t len, + const char *sep) { char *b = buf, *eb = b + len; const Char *p; @@ -651,7 +653,7 @@ for (p = str; *p != 0; p++) { Char dbuf[VISUAL_WIDTH_MAX]; Char *p2 = dbuf; - ssize_t l = ct_visual_char(dbuf, VISUAL_WIDTH_MAX, *p); + ssize_t l = ct_visual_char(el, dbuf, VISUAL_WIDTH_MAX, *p); while (l-- > 0) { ssize_t n = ct_encode_char(b, (size_t)(eb - b), *p2++); if (n == -1) /* ran out of space */ diff -r 21069f8841d0 -r 4cb876518d2a keymacro.h --- a/keymacro.h Wed Sep 28 17:39:22 2011 +0900 +++ b/keymacro.h Fri Oct 07 16:54:23 2011 +0900 @@ -70,7 +70,7 @@ protected void keymacro_print(EditLine *, const Char *); protected void keymacro_kprint(EditLine *, const Char *, keymacro_value_t *, int); -protected size_t keymacro__decode_str(const Char *, char *, size_t, +protected size_t keymacro__decode_str(EditLine *, const Char *, char *, size_t, const char *); #endif /* _h_el_keymacro */ diff -r 21069f8841d0 -r 4cb876518d2a map.c --- a/map.c Wed Sep 28 17:39:22 2011 +0900 +++ b/map.c Fri Oct 07 16:54:23 2011 +0900 @@ -1065,8 +1065,9 @@ map_init_meta(el); map_init_nls(el); - buf[0] = CONTROL('X'); - buf[1] = CONTROL('X'); + /* XXX: not CSI */ + buf[0] = CONTROL(CHR('X')); + buf[1] = CONTROL(CHR('X')); buf[2] = 0; keymacro_add(el, buf, keymacro_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD); @@ -1124,8 +1125,8 @@ char outbuf[EL_BUFSIZ]; el_bindings_t *bp, *ep; - if (in[0] == '\0' || in[1] == '\0') { - (void) keymacro__decode_str(in, outbuf, sizeof(outbuf), ""); + if (in[0] == CHR('\0') || in[1] == CHR('\0')) { + (void) keymacro__decode_str(el, in, outbuf, sizeof(outbuf), ""); ep = &el->el_map.help[el->el_map.nfunc]; for (bp = el->el_map.help; bp < ep; bp++) if (bp->func == map[(unsigned char) *in]) { @@ -1154,7 +1155,7 @@ lastbuf[1] = 0; if (map[first] == ED_UNASSIGNED) { if (first == last) { - (void) keymacro__decode_str(firstbuf, unparsbuf, + (void) keymacro__decode_str(el, firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "%-15s-> is undefined\n", unparsbuf); @@ -1165,15 +1166,15 @@ for (bp = el->el_map.help; bp < ep; bp++) { if (bp->func == map[first]) { if (first == last) { - (void) keymacro__decode_str(firstbuf, unparsbuf, - sizeof(unparsbuf), STRQQ); + (void) keymacro__decode_str(el, firstbuf, + unparsbuf, sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "%-15s-> " FSTR "\n", unparsbuf, bp->name); } else { - (void) keymacro__decode_str(firstbuf, unparsbuf, - sizeof(unparsbuf), STRQQ); - (void) keymacro__decode_str(lastbuf, extrabuf, - sizeof(extrabuf), STRQQ); + (void) keymacro__decode_str(el, firstbuf, + unparsbuf, sizeof(unparsbuf), STRQQ); + (void) keymacro__decode_str(el, lastbuf, + extrabuf, sizeof(extrabuf), STRQQ); (void) fprintf(el->el_outfile, "%-4s to %-7s-> " FSTR "\n", unparsbuf, extrabuf, bp->name); @@ -1183,14 +1184,14 @@ } #ifdef MAP_DEBUG if (map == el->el_map.key) { - (void) keymacro__decode_str(firstbuf, unparsbuf, + (void) keymacro__decode_str(el, firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "BUG!!! %s isn't bound to anything.\n", unparsbuf); (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n", first, el->el_map.key[first]); } else { - (void) keymacro__decode_str(firstbuf, unparsbuf, + (void) keymacro__decode_str(el, firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "BUG!!! %s isn't bound to anything.\n", unparsbuf); @@ -1261,37 +1262,37 @@ ntype = XK_CMD; key = rem = 0; for (argc = 1; (p = argv[argc]) != NULL; argc++) - if (p[0] == '-') + if (p[0] == CHR('-')) switch (p[1]) { - case 'a': + case CHR('a'): map = el->el_map.alt; break; - case 's': + case CHR('s'): ntype = XK_STR; break; #ifdef notyet - case 'c': + case CHR('c'): ntype = XK_EXE; break; #endif - case 'k': + case CHR('k'): key = 1; break; - case 'r': + case CHR('r'): rem = 1; break; - case 'v': + case CHR('v'): map_init_vi(el); return 0; - case 'e': + case CHR('e'): map_init_emacs(el); return 0; - case 'l': + case CHR('l'): ep = &el->el_map.help[el->el_map.nfunc]; for (bp = el->el_map.help; bp < ep; bp++) (void) fprintf(el->el_outfile, @@ -1312,7 +1313,7 @@ } if (key) in = argv[argc++]; - else if ((in = parse__string(inbuf, argv[argc++])) == NULL) { + else if ((in = parse__string(el, inbuf, argv[argc++])) == NULL) { (void) fprintf(el->el_errfile, "" FSTR ": Invalid \\ or ^ in instring.\n", argv[0]); @@ -1348,7 +1349,7 @@ switch (ntype) { case XK_STR: case XK_EXE: - if ((out = parse__string(outbuf, argv[argc])) == NULL) { + if ((out = parse__string(el, outbuf, argv[argc])) == NULL) { (void) fprintf(el->el_errfile, "" FSTR ": Invalid \\ or ^ in outstring.\n", argv[0]); return -1; diff -r 21069f8841d0 -r 4cb876518d2a parse.c --- a/parse.c Wed Sep 28 17:39:22 2011 +0900 +++ b/parse.c Fri Oct 07 16:54:23 2011 +0900 @@ -101,7 +101,7 @@ if (argc < 1) return -1; - ptr = Strchr(argv[0], ':'); + ptr = Strchr(argv[0], CHR(':')); if (ptr != NULL) { Char *tprog; size_t l; @@ -113,7 +113,7 @@ if (tprog == NULL) return 0; (void) Strncpy(tprog, argv[0], l); - tprog[l] = '\0'; + tprog[l] = CHR('\0'); ptr++; l = (size_t)el_match(el->el_prog, tprog); el_free(tprog); @@ -135,87 +135,131 @@ * Parse a string of the form ^ \ \ \U+xxxx and return * the appropriate character or -1 if the escape is not valid */ -protected int -parse__escape(const Char **ptr) +protected Int +/*ARGSUSED*/ +parse__escape(EditLine *el __attribute__((__unused__)), const Char **ptr) { const Char *p; Int c; +#ifdef WIDECHAR + int cont = 0; + mbstate_t state; + + ct_mbstate_reset(&state); +#endif p = *ptr; +#ifdef WIDECHAR +retry: +#endif if (p[1] == 0) - return -1; + return CT_EOF; - if (*p == '\\') { + if (*p == CHR('\\')) { p++; switch (*p) { - case 'a': - c = '\007'; /* Bell */ + case CHR('a'): + c = CHR('\007'); /* Bell */ break; - case 'b': - c = '\010'; /* Backspace */ + case CHR('b'): + c = CHR('\010'); /* Backspace */ break; - case 't': - c = '\011'; /* Horizontal Tab */ + case CHR('t'): + c = CHR('\011'); /* Horizontal Tab */ break; - case 'n': - c = '\012'; /* New Line */ + case CHR('n'): + c = CHR('\012'); /* New Line */ break; - case 'v': - c = '\013'; /* Vertical Tab */ + case CHR('v'): + c = CHR('\013'); /* Vertical Tab */ break; - case 'f': - c = '\014'; /* Form Feed */ + case CHR('f'): + c = CHR('\014'); /* Form Feed */ break; - case 'r': - c = '\015'; /* Carriage Return */ + case CHR('r'): + c = CHR('\015'); /* Carriage Return */ break; - case 'e': - c = '\033'; /* Escape */ + case CHR('e'): + c = CHR('\033'); /* Escape */ break; - case 'U': /* Unicode \U+xxxx or \U+xxxxx format */ +#ifdef USE_UCS_CODEPOINT + case CHR('U'): /* Unicode \U+xxxx or \U+xxxxx format */ { - int i; + int i, val; const Char hex[] = STR("0123456789ABCDEF"); const Char *h; + ++p; - if (*p++ != '+') - return -1; - c = 0; + if (*p++ != CHR('+')) + return CT_EOF; + val = 0; for (i = 0; i < 5; ++i) { - h = Strchr(hex, *p++); - if (!h && i < 4) - return -1; - else if (h) - c = (c << 4) | ((int)(h - hex)); + h = Strchr(hex, *p++); /* can match to \0 */ + if ((!h || !*h) && i < 4) + return CT_EOF; + else if (h && *h) + val = (val << 4) | ((int)(h - hex)); else --p; } - if (c > 0x10FFFF) /* outside valid character range */ - return -1; + if (val > 0x10FFFF) /* outside valid character range */ + return CT_EOF; + c = (Int)val; +#ifndef __STDC_ISO_10646__ + if (!(el->el_flags & MULTIBYTE_UCS)) { + /* treat as a single byte character in the + current locale. */ + if (val >= 0x100) + return CT_EOF; + c = btowc(val); + } +#endif break; } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': +#endif + case CHR('0'): + case CHR('1'): + case CHR('2'): + case CHR('3'): + case CHR('4'): + case CHR('5'): + case CHR('6'): + case CHR('7'): + /* singlebyte/multibyte \xxx form */ { - int cnt, ch; + Char ch; + int cnt, val; +#ifdef WIDECHAR + size_t ret; + char mbc; +#endif - for (cnt = 0, c = 0; cnt < 3; cnt++) { - ch = *p++; - if (ch < '0' || ch > '7') { - p--; + for (cnt = 0, val = 0; cnt < 3; cnt++) { + ch = *p; + if (ch < CHR('0') || ch > CHR('7')) break; + val = (val << 3) | (int)(ch - CHR('0')); + p++; + } + if (val < 0 || val >= 0x100) + return CT_EOF; +#ifdef WIDECHAR + mbc = (char)val; + ret = mbrtowc(&ch, &mbc, 1, &state); + if (ret == (size_t)-2) { + if (*p == CHR('\\')) { + cont = 1; + goto retry; } - c = (c << 3) | (ch - '0'); - } - if ((c & (wint_t)0xffffff00) != (wint_t)0) - return -1; + return CT_EOF; + } else if (ret == (size_t)-1) + return CT_EOF; + c = (Int)ch; + cont = 0; +#else + c = (char)val; +#endif --p; break; } @@ -223,11 +267,17 @@ c = *p; break; } - } else if (*p == '^') { + } else if (*p == CHR('^')) { + /* XXX: not CSI */ p++; - c = (*p == '?') ? '\177' : (*p & 0237); - } else + c = (*p == CHR('?')) ? CHR('\177') : (*p & 0237); + } else { c = *p; + } +#ifdef WIDECHAR + if (cont) + return CT_EOF; +#endif *ptr = ++p; return c; } @@ -236,27 +286,27 @@ * Parse the escapes from in and put the raw string out */ protected Char * -parse__string(Char *out, const Char *in) +parse__string(EditLine *el, Char *out, const Char *in) { Char *rv = out; - int n; + Int n; for (;;) switch (*in) { - case '\0': - *out = '\0'; + case CHR('\0'): + *out = CHR('\0'); return rv; - case '\\': - case '^': - if ((n = parse__escape(&in)) == -1) + case CHR('\\'): + case CHR('^'): + if ((n = parse__escape(el, &in)) == CT_EOF) return NULL; - *out++ = n; + *out++ = (Char)n; break; - case 'M': - if (in[1] == '-' && in[2] != '\0') { - *out++ = '\033'; + case CHR('M'): + if (in[1] == CHR('-') && in[2] != CHR('\0')) { + *out++ = CHR('\033'); /* XXX: not CSI */ in += 2; break; } diff -r 21069f8841d0 -r 4cb876518d2a parse.h --- a/parse.h Wed Sep 28 17:39:22 2011 +0900 +++ b/parse.h Fri Oct 07 16:54:23 2011 +0900 @@ -41,8 +41,8 @@ #define _h_el_parse protected int parse_line(EditLine *, const Char *); -protected int parse__escape(const Char **); -protected Char *parse__string(Char *, const Char *); +protected Int parse__escape(EditLine *, const Char **); +protected Char *parse__string(EditLine *, Char *, const Char *); protected int parse_cmd(EditLine *, const Char *); #endif /* _h_el_parse */ diff -r 21069f8841d0 -r 4cb876518d2a prompt.c --- a/prompt.c Wed Sep 28 17:39:22 2011 +0900 +++ b/prompt.c Fri Oct 07 16:54:23 2011 +0900 @@ -57,7 +57,7 @@ /*ARGSUSED*/ prompt_default(EditLine *el __attribute__((__unused__))) { - static Char a[3] = {'?', ' ', '\0'}; + static Char a[3] = {CHR('?'), CHR(' '), CHR('\0')}; return a; } @@ -70,7 +70,7 @@ /*ARGSUSED*/ prompt_default_r(EditLine *el __attribute__((__unused__))) { - static Char a[1] = {'\0'}; + static Char a[1] = {CHR('\0')}; return a; } @@ -123,11 +123,11 @@ el->el_prompt.p_func = prompt_default; el->el_prompt.p_pos.v = 0; el->el_prompt.p_pos.h = 0; - el->el_prompt.p_ignore = '\0'; + el->el_prompt.p_ignore = CHR('\0'); el->el_rprompt.p_func = prompt_default_r; el->el_rprompt.p_pos.v = 0; el->el_rprompt.p_pos.h = 0; - el->el_rprompt.p_ignore = '\0'; + el->el_rprompt.p_ignore = CHR('\0'); return 0; } diff -r 21069f8841d0 -r 4cb876518d2a read.c --- a/read.c Wed Sep 28 17:39:22 2011 +0900 +++ b/read.c Fri Oct 07 16:54:23 2011 +0900 @@ -294,33 +294,18 @@ return OKCMD; } -#ifdef WIDECHAR -/* utf8_islead(): - * Test whether a byte is a leading byte of a UTF-8 sequence. +/* read_byte(): + * Read a byte from the tty. */ private int -utf8_islead(int c) -{ - return c < 0x80 || /* single byte char */ - (c >= 0xc2 && c <= 0xf4); /* start of multibyte sequence */ -} -#endif - -/* read_char(): - * Read a character from the tty. - */ -private int -read_char(EditLine *el, Char *cp) +read_byte(EditLine *el, char *cp) { ssize_t num_read; int tried = 0; - char cbuf[MB_LEN_MAX]; - size_t cbp = 0; - int bytes = 0; again: el->el_signal->sig_no = 0; - while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) { + while ((num_read = read(el->el_infd, cp, (size_t)1)) == -1) { switch (el->el_signal->sig_no) { case SIGCONT: FUN(el,set)(el, EL_REFRESH); @@ -339,33 +324,69 @@ } } + return num_read; +} + +/* read_char(): + * Read a character from the tty. + */ +private int +read_char(EditLine *el, Char *cp) +{ #ifdef WIDECHAR - if (el->el_flags & CHARSET_IS_UTF8) { - if (!utf8_islead((unsigned char)cbuf[0])) - goto again; /* discard the byte we read and try again */ - ++cbp; - if ((bytes = ct_mbtowc(cp, cbuf, cbp)) == -1) { - ct_mbtowc_reset; - if (cbp >= MB_LEN_MAX) { /* "shouldn't happen" */ - *cp = '\0'; - return -1; - } - goto again; + ssize_t num_read; + size_t num_bytes; + char byte; + mbstate_t state; + + if ((el->el_flags & MULTIBYTE_STATEFUL) != 0) { + /* stateful */ + /* XXX: notyet */ + num_read = read_byte(el, &byte); + if (num_read <= 0 || + (*cp = btowc(byte)) == WEOF) { + *cp = CHR('\0'); + return num_read ? 0 : -1; } - } else if (isascii((unsigned char)cbuf[0]) || - /* we don't support other multibyte charsets */ - ++cbp != 1 || - /* Try non-ASCII characters in a 8-bit character set */ - (bytes = ct_mbtowc(cp, cbuf, cbp)) != 1) -#endif - *cp = (unsigned char)cbuf[0]; + return (int)num_read; + } - if ((el->el_flags & IGNORE_EXTCHARS) && bytes > 1) { - cbp = 0; /* skip this character */ + /* single byte / stateless multibyte */ + ct_mbstate_reset(&state); + again: + num_read = read_byte(el, &byte); + if (num_read <= 0) { + *cp = CHR('\0'); + return (int)num_read; + } + + num_bytes = mbrtowc(cp, &byte, 1, &state); + switch (num_bytes) { + case (size_t)-1: + /* illegal sequence or other errors */ + if (errno != EILSEQ) { + *cp = CHR('\0'); + return -1; + } + /* ELSEQ: just ignore the sequence and retry */ + ct_mbstate_reset(&state); + goto again; + case (size_t)-2: + /* incomplete sequence */ + goto again; + default: + break; + } + + if ((el->el_flags & IGNORE_EXTCHARS) && !IsASCII(*cp)) { + /* skip this character */ + ct_mbstate_reset(&state); goto again; } - - return (int)num_read; + return 1; +#else + return read_byte(el, cp); +#endif } /* read_pop(): @@ -402,14 +423,14 @@ if (ma->level < 0) break; - if (ma->macro[0][ma->offset] == '\0') { + if (ma->macro[0][ma->offset] == CHR('\0')) { read_pop(ma); continue; } *cp = ma->macro[0][ma->offset++]; - if (ma->macro[0][ma->offset] == '\0') { + if (ma->macro[0][ma->offset] == CHR('\0')) { /* Needed for QuoteMode On */ read_pop(ma); } @@ -499,7 +520,7 @@ cp++; if (el->el_flags & UNBUFFERED) break; - if (cp[-1] == '\r' || cp[-1] == '\n') + if (cp[-1] == CHR('\r') || cp[-1] == CHR('\n')) break; } if (num == -1) { @@ -549,7 +570,7 @@ cp = &el->el_line.buffer[idx]; } cp++; - crlf = cp[-1] == '\r' || cp[-1] == '\n'; + crlf = cp[-1] == CHR('\r') || cp[-1] == CHR('\n'); if (el->el_flags & UNBUFFERED) break; if (crlf) @@ -579,7 +600,7 @@ break; } if (el->el_errno == EINTR) { - el->el_line.buffer[0] = '\0'; + el->el_line.buffer[0] = CHR('\0'); el->el_line.lastchar = el->el_line.cursor = el->el_line.buffer; break; @@ -659,7 +680,8 @@ if ((el->el_flags & UNBUFFERED) == 0) num = 0; else if (num == -1) { - *el->el_line.lastchar++ = CONTROL('d'); + /* XXX: not CSI */ + *el->el_line.lastchar++ = CONTROL(CHR('d')); el->el_line.cursor = el->el_line.lastchar; num = 1; } @@ -708,7 +730,7 @@ goto done; noedit: el->el_line.cursor = el->el_line.lastchar = cp; - *cp = '\0'; + *cp = CHR('\0'); *nread = (int)(el->el_line.cursor - el->el_line.buffer); done: if (*nread == 0) { diff -r 21069f8841d0 -r 4cb876518d2a refresh.c --- a/refresh.c Wed Sep 28 17:39:22 2011 +0900 +++ b/refresh.c Fri Oct 07 16:54:23 2011 +0900 @@ -110,7 +110,7 @@ for(i = 1; i < lins; i++) el->el_vdisplay[i - 1] = el->el_vdisplay[i]; - firstline[0] = '\0'; /* empty the string */ + firstline[0] = CHR('\0'); /* empty the string */ el->el_vdisplay[i - 1] = firstline; } else el->el_refresh.r_cursor.v++; @@ -130,14 +130,14 @@ switch (ct_chr_class((Char)c)) { case CHTYPE_TAB: /* expand the tab */ for (;;) { - re_putc(el, ' ', 1); + re_putc(el, CHR(' '), 1); if ((el->el_refresh.r_cursor.h & 07) == 0) break; /* go until tab stop */ } break; case CHTYPE_NL: { int oldv = el->el_refresh.r_cursor.v; - re_putc(el, '\0', 0); /* assure end of line */ + re_putc(el, CHR('\0'), 0); /* assure end of line */ if (oldv == el->el_refresh.r_cursor.v) /* XXX */ re_nextline(el); break; @@ -148,7 +148,7 @@ default: { Char visbuf[VISUAL_WIDTH_MAX]; ssize_t i, n = - ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c); + ct_visual_char(el, visbuf, VISUAL_WIDTH_MAX, (Char)c); for (i = 0; n-- > 0; ++i) re_putc(el, visbuf[i], 1); break; @@ -167,7 +167,7 @@ ELRE_DEBUG(1, (__F, "printing %5x '%c'\r\n", c, c)); while (shift && (el->el_refresh.r_cursor.h + w > el->el_terminal.t_size.h)) - re_putc(el, ' ', 1); + re_putc(el, CHR(' '), 1); el->el_vdisplay[el->el_refresh.r_cursor.v] [el->el_refresh.r_cursor.h] = c; @@ -184,7 +184,7 @@ if (el->el_refresh.r_cursor.h >= el->el_terminal.t_size.h) { /* assure end of line */ el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_terminal.t_size.h] - = '\0'; + = CHR('\0'); re_nextline(el); } } @@ -280,14 +280,14 @@ * one character gap to the input buffer. */ while (--rhdiff > 0) /* pad out with spaces */ - re_putc(el, ' ', 1); + re_putc(el, CHR(' '), 1); prompt_print(el, EL_RPROMPT); } else { el->el_rprompt.p_pos.h = 0; /* flag "not using rprompt" */ el->el_rprompt.p_pos.v = 0; } - re_putc(el, '\0', 0); /* make line ended with NUL, no cursor shift */ + re_putc(el, CHR('\0'), 0); /* make line ended with NUL, no cursor shift */ el->el_refresh.r_newcv = el->el_refresh.r_cursor.v; @@ -324,7 +324,7 @@ #ifdef DEBUG_REFRESH terminal_overwrite(el, "C\b", (size_t)2); #endif /* DEBUG_REFRESH */ - el->el_display[i][0] = '\0'; + el->el_display[i][0] = CHR('\0'); } el->el_refresh.r_oldcv = el->el_refresh.r_newcv; /* set for next time */ @@ -345,7 +345,7 @@ { terminal_move_to_line(el, el->el_refresh.r_oldcv); - terminal__putc(el, '\n'); + terminal__putc(el, CHR('\n')); re_clear_display(el); terminal__flush(el); } @@ -378,7 +378,7 @@ a = b - num; while (a >= &d[dat]) *b-- = *a--; - d[dlen] = '\0'; /* just in case */ + d[dlen] = CHR('\0'); /* just in case */ } ELRE_DEBUG(1, (__F, @@ -414,7 +414,7 @@ if (num <= 0) return; if (dat + num >= dlen) { - d[dat] = '\0'; + d[dat] = CHR('\0'); return; } ELRE_DEBUG(1, @@ -427,7 +427,7 @@ a = b + num; while (a < &d[dlen]) *b++ = *a++; - d[dlen] = '\0'; /* just in case */ + d[dlen] = CHR('\0'); /* just in case */ } ELRE_DEBUG(1, (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n", @@ -524,29 +524,29 @@ * back up past the beginning. */ while (ofd < o) { - if (o[-1] != ' ') + if (o[-1] != CHR(' ')) break; o--; } oe = o; - *oe = '\0'; + *oe = CHR('\0'); while (*n) n++; /* remove blanks from end of new */ while (nfd < n) { - if (n[-1] != ' ') + if (n[-1] != CHR(' ')) break; n--; } ne = n; - *ne = '\0'; + *ne = CHR('\0'); /* * if no diff, continue to next line of redraw */ - if (*ofd == '\0' && *nfd == '\0') { + if (*ofd == CHR('\0') && *nfd == CHR('\0')) { ELRE_DEBUG(1, (__F, "no difference.\r\n")); return; } @@ -973,15 +973,15 @@ size_t i; for (i = 0; i < width; i++) { - if (*src == '\0') + if (*src == CHR('\0')) break; *dst++ = *src++; } for (; i < width; i++) - *dst++ = ' '; + *dst++ = CHR(' '); - *dst = '\0'; + *dst = CHR('\0'); } @@ -1024,7 +1024,7 @@ h = 0; v++; } - h += ct_visual_width(*cp); + h += ct_visual_width(el, *cp); break; } @@ -1056,7 +1056,7 @@ { int w = Width((Char)c); while (w > 1 && el->el_cursor.h + w > el->el_terminal.t_size.h) - re_fastputc(el, ' '); + re_fastputc(el, CHR(' ')); terminal__putc(el, c); el->el_display[el->el_cursor.v][el->el_cursor.h++] = c; @@ -1089,12 +1089,12 @@ } if (EL_HAS_AUTO_MARGINS) { if (EL_HAS_MAGIC_MARGINS) { - terminal__putc(el, ' '); - terminal__putc(el, '\b'); + terminal__putc(el, CHR(' ')); + terminal__putc(el, CHR('\b')); } } else { - terminal__putc(el, '\r'); - terminal__putc(el, '\n'); + terminal__putc(el, CHR('\r')); + terminal__putc(el, CHR('\n')); } } } @@ -1112,7 +1112,7 @@ c = el->el_line.cursor[-1]; - if (c == '\t' || el->el_line.cursor != el->el_line.lastchar) { + if (c == CHR('\t') || el->el_line.cursor != el->el_line.lastchar) { re_refresh(el); /* too hard to handle */ return; } @@ -1130,10 +1130,11 @@ re_fastputc(el, c); break; case CHTYPE_ASCIICTL: + case CHTYPE_ASCIIDEL: case CHTYPE_NONPRINT: { Char visbuf[VISUAL_WIDTH_MAX]; ssize_t i, n = - ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c); + ct_visual_char(el, visbuf, VISUAL_WIDTH_MAX, (Char)c); for (i = 0; n-- > 0; ++i) re_fastputc(el, visbuf[i]); break; @@ -1154,7 +1155,7 @@ el->el_cursor.v = 0; el->el_cursor.h = 0; for (i = 0; i < el->el_terminal.t_size.v; i++) - el->el_display[i][0] = '\0'; + el->el_display[i][0] = CHR('\0'); el->el_refresh.r_oldcv = 0; } @@ -1177,7 +1178,7 @@ } else { terminal_move_to_line(el, el->el_refresh.r_oldcv); /* go to last line */ - terminal__putc(el, '\r'); /* go to BOL */ - terminal__putc(el, '\n'); /* go to new line */ + terminal__putc(el, CHR('\r')); /* go to BOL */ + terminal__putc(el, CHR('\n')); /* go to new line */ } } diff -r 21069f8841d0 -r 4cb876518d2a search.c --- a/search.c Wed Sep 28 17:39:22 2011 +0900 +++ b/search.c Fri Oct 07 16:54:23 2011 +0900 @@ -72,7 +72,7 @@ return -1; el->el_search.patlen = 0; el->el_search.patdir = -1; - el->el_search.chacha = '\0'; + el->el_search.chacha = CHR('\0'); el->el_search.chadir = CHAR_FWD; el->el_search.chatflg = 0; return 0; @@ -182,7 +182,7 @@ if (el->el_search.patlen != 0) { (void) Strncpy(el->el_search.patbuf, el->el_line.buffer, el->el_search.patlen); - el->el_search.patbuf[el->el_search.patlen] = '\0'; + el->el_search.patbuf[el->el_search.patlen] = CHR('\0'); } else el->el_search.patlen = Strlen(el->el_search.patbuf); } @@ -205,10 +205,10 @@ protected el_action_t ce_inc_search(EditLine *el, int dir) { - static const Char STRfwd[] = {'f', 'w', 'd', '\0'}, - STRbck[] = {'b', 'c', 'k', '\0'}; - static Char pchar = ':';/* ':' = normal, '?' = failed */ - static Char endcmd[2] = {'\0', '\0'}; + static const Char STRfwd[] = {CHR('f'), CHR('w'), CHR('d'), CHR('\0')}, + STRbck[] = {CHR('b'), CHR('c'), CHR('k'), CHR('\0')}; + static Char pchar = CHR(':');/* ':' = normal, '?' = failed */ + static Char endcmd[2] = {CHR('\0'), CHR('\0')}; Char ch, *ocursor = el->el_line.cursor, oldpchar = pchar; const Char *cp; @@ -227,17 +227,17 @@ for (;;) { if (el->el_search.patlen == 0) { /* first round */ - pchar = ':'; + pchar = CHR(':'); #ifdef ANCHOR #define LEN 2 - el->el_search.patbuf[el->el_search.patlen++] = '.'; - el->el_search.patbuf[el->el_search.patlen++] = '*'; + el->el_search.patbuf[el->el_search.patlen++] = CHR('.'); + el->el_search.patbuf[el->el_search.patlen++] = CHR('*'); #else #define LEN 0 #endif } done = redo = 0; - *el->el_line.lastchar++ = '\n'; + *el->el_line.lastchar++ = CHR('\n'); for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? STRbck : STRfwd; *cp; *el->el_line.lastchar++ = *cp++) continue; @@ -246,7 +246,7 @@ cp < &el->el_search.patbuf[el->el_search.patlen]; *el->el_line.lastchar++ = *cp++) continue; - *el->el_line.lastchar = '\0'; + *el->el_line.lastchar = CHR('\0'); re_refresh(el); if (FUN(el,getc)(el, &ch) != 1) @@ -261,7 +261,7 @@ el->el_search.patbuf[el->el_search.patlen++] = ch; *el->el_line.lastchar++ = ch; - *el->el_line.lastchar = '\0'; + *el->el_line.lastchar = CHR('\0'); re_refresh(el); } break; @@ -302,7 +302,7 @@ el->el_line.lastchar, 1, ce__isword); while (el->el_line.cursor < cp && - *el->el_line.cursor != '\n') { + *el->el_line.cursor != CHR('\n')) { if (el->el_search.patlen >= EL_BUFSIZ - LEN) { terminal_beep(el); @@ -314,7 +314,7 @@ *el->el_line.cursor++; } el->el_line.cursor = ocursor; - *el->el_line.lastchar = '\0'; + *el->el_line.lastchar = CHR('\0'); re_refresh(el); break; } else if (isglob(*cp)) { @@ -337,24 +337,24 @@ } while (el->el_line.lastchar > el->el_line.buffer && - *el->el_line.lastchar != '\n') - *el->el_line.lastchar-- = '\0'; - *el->el_line.lastchar = '\0'; + *el->el_line.lastchar != CHR('\n')) + *el->el_line.lastchar-- = CHR('\0'); + *el->el_line.lastchar = CHR('\0'); if (!done) { /* Can't search if unmatched '[' */ for (cp = &el->el_search.patbuf[el->el_search.patlen-1], - ch = ']'; + ch = CHR(']'); cp >= &el->el_search.patbuf[LEN]; cp--) - if (*cp == '[' || *cp == ']') { + if (*cp == CHR('[') || *cp == CHR(']')) { ch = *cp; break; } - if (el->el_search.patlen > LEN && ch != '[') { + if (el->el_search.patlen > LEN && ch != CHR('[')) { if (redo && newdir == dir) { - if (pchar == '?') { /* wrap around */ + if (pchar == CHR('?')) { /* wrap around */ el->el_history.eventno = newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff; if (hist_get(el) == CC_ERROR) @@ -374,12 +374,12 @@ } #ifdef ANCHOR el->el_search.patbuf[el->el_search.patlen++] = - '.'; + CHR('.'); el->el_search.patbuf[el->el_search.patlen++] = - '*'; + CHR('*'); #endif el->el_search.patbuf[el->el_search.patlen] = - '\0'; + CHR('\0'); if (el->el_line.cursor < el->el_line.buffer || el->el_line.cursor > el->el_line.lastchar || (ret = ce_search_line(el, newdir)) @@ -402,7 +402,7 @@ } el->el_search.patlen -= LEN; el->el_search.patbuf[el->el_search.patlen] = - '\0'; + CHR('\0'); if (ret == CC_ERROR) { terminal_beep(el); if (el->el_history.eventno != @@ -413,14 +413,15 @@ return CC_ERROR; } el->el_line.cursor = ocursor; - pchar = '?'; + pchar = CHR('?'); } else { - pchar = ':'; + pchar = CHR(':'); } } ret = ce_inc_search(el, newdir); - if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') + if (ret == CC_ERROR && + pchar == CHR('?') && oldpchar == CHR(':')) /* * break abort of failed search at last * non-failed @@ -458,8 +459,8 @@ ssize_t tmplen; #ifdef ANCHOR - tmpbuf[0] = '.'; - tmpbuf[1] = '*'; + tmpbuf[0] = CHR('.'); + tmpbuf[1] = CHR('*'); #endif tmplen = LEN; @@ -472,7 +473,7 @@ tmplen += LEN; ch = tmpbuf[tmplen]; - tmpbuf[tmplen] = '\0'; + tmpbuf[tmplen] = CHR('\0'); if (tmplen == LEN) { /* @@ -483,26 +484,26 @@ return CC_ERROR; } #ifdef ANCHOR - if (el->el_search.patbuf[0] != '.' && - el->el_search.patbuf[0] != '*') { + if (el->el_search.patbuf[0] != CHR('.') && + el->el_search.patbuf[0] != CHR('*')) { (void) Strncpy(tmpbuf, el->el_search.patbuf, sizeof(tmpbuf) / sizeof(*tmpbuf) - 1); - el->el_search.patbuf[0] = '.'; - el->el_search.patbuf[1] = '*'; + el->el_search.patbuf[0] = CHR('.'); + el->el_search.patbuf[1] = CHR('*'); (void) Strncpy(&el->el_search.patbuf[2], tmpbuf, EL_BUFSIZ - 3); el->el_search.patlen++; - el->el_search.patbuf[el->el_search.patlen++] = '.'; - el->el_search.patbuf[el->el_search.patlen++] = '*'; - el->el_search.patbuf[el->el_search.patlen] = '\0'; + el->el_search.patbuf[el->el_search.patlen++] = CHR('.'); + el->el_search.patbuf[el->el_search.patlen++] = CHR('*'); + el->el_search.patbuf[el->el_search.patlen] = CHR('\0'); } #endif } else { #ifdef ANCHOR - tmpbuf[tmplen++] = '.'; - tmpbuf[tmplen++] = '*'; + tmpbuf[tmplen++] = CHR('.'); + tmpbuf[tmplen++] = CHR('*'); #endif - tmpbuf[tmplen] = '\0'; + tmpbuf[tmplen] = CHR('\0'); (void) Strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); el->el_search.patlen = (size_t)tmplen; } @@ -533,7 +534,7 @@ #ifdef ANCHOR ocp = &pattern[1]; oc = *ocp; - *ocp = '^'; + *ocp = CHR('^'); #else ocp = pattern; oc = *ocp; @@ -550,7 +551,7 @@ *ocp = oc; return CC_ERROR; } else { - for (; *cp != '\0' && cp < el->el_line.limit; cp++) { + for (; *cp != CHR('\0') && cp < el->el_line.limit; cp++) { if (el_match(cp, ocp)) { *ocp = oc; el->el_line.cursor = cp; diff -r 21069f8841d0 -r 4cb876518d2a terminal.c --- a/terminal.c Wed Sep 28 17:39:22 2011 +0900 +++ b/terminal.c Fri Oct 07 16:54:23 2011 +0900 @@ -85,7 +85,7 @@ #define TC_BUFSIZE ((size_t)2048) #define GoodStr(a) (el->el_terminal.t_str[a] != NULL && \ - el->el_terminal.t_str[a][0] != '\0') + el->el_terminal.t_str[a][0] != '\0') #define Str(a) el->el_terminal.t_str[a] #define Val(a) el->el_terminal.t_val[a] @@ -495,7 +495,7 @@ if ((del = where - el->el_cursor.v) > 0) { while (del > 0) { if (EL_HAS_AUTO_MARGINS && - el->el_display[el->el_cursor.v][0] != '\0') { + el->el_display[el->el_cursor.v][0] != CHR('\0')) { size_t h = (size_t) (el->el_terminal.t_size.h - 1); #ifdef WIDECHAR @@ -520,7 +520,7 @@ del = 0; } else { for (; del > 0; del--) - terminal__putc(el, '\n'); + terminal__putc(el, CHR('\n')); /* because the \n will become \r\n */ el->el_cursor.h = 0; } @@ -560,7 +560,7 @@ return; } if (!where) { /* if where is first column */ - terminal__putc(el, '\r'); /* do a CR */ + terminal__putc(el, CHR('\r')); /* do a CR */ el->el_cursor.h = 0; return; } @@ -591,7 +591,7 @@ i < (where & ~0x7); i += 8) terminal__putc(el, - '\t'); + CHR('\t')); /* then tab over */ el->el_cursor.h = where & ~0x7; } @@ -623,12 +623,13 @@ (((unsigned int) where >> 3) + (where & 07))) : (-del > where)) { - terminal__putc(el, '\r');/* do a CR */ + terminal__putc(el, + CHR('\r'));/* do a CR */ el->el_cursor.h = 0; goto mc_again; /* and try again */ } for (i = 0; i < -del; i++) - terminal__putc(el, '\b'); + terminal__putc(el, CHR('\b')); } } } @@ -656,7 +657,7 @@ do { /* terminal__putc() ignores any MB_FILL_CHARs */ - terminal__putc(el, *cp++); + terminal__putc(el, CharToInt(*cp++)); el->el_cursor.h++; } while (--n); @@ -677,7 +678,7 @@ el->el_cursor.h++; #endif } else { - terminal__putc(el, ' '); + terminal__putc(el, CHR(' ')); el->el_cursor.h = 1; } } @@ -763,7 +764,7 @@ el->el_cursor.h += num; do - terminal__putc(el, *cp++); + terminal__putc(el, CharToInt(*cp++)); while (--num); if (GoodStr(T_ip)) /* have to make num chars insert */ @@ -776,7 +777,7 @@ if (GoodStr(T_ic)) /* have to make num chars insert */ terminal_tputs(el, Str(T_ic), 1); - terminal__putc(el, *cp++); + terminal__putc(el, CharToInt(*cp++)); el->el_cursor.h++; @@ -800,7 +801,7 @@ terminal_tputs(el, Str(T_ce), 1); else { for (i = 0; i < num; i++) - terminal__putc(el, ' '); + terminal__putc(el, CHR(' ')); el->el_cursor.h += num; /* have written num spaces */ } } @@ -821,8 +822,8 @@ /* clear to bottom of screen */ terminal_tputs(el, Str(T_cd), Val(T_li)); } else { - terminal__putc(el, '\r'); - terminal__putc(el, '\n'); + terminal__putc(el, CHR('\r')); + terminal__putc(el, CHR('\n')); } } @@ -837,7 +838,7 @@ /* what termcap says we should use */ terminal_tputs(el, Str(T_bl), 1); else - terminal__putc(el, '\007'); /* an ASCII bell; ^G */ + terminal__putc(el, CHR('\007')); /* an ASCII bell; ^G */ } @@ -1040,18 +1041,19 @@ terminal_reset_arrow(EditLine *el) { funckey_t *arrow = el->el_terminal.t_fkey; - static const Char strA[] = {033, '[', 'A', '\0'}; - static const Char strB[] = {033, '[', 'B', '\0'}; - static const Char strC[] = {033, '[', 'C', '\0'}; - static const Char strD[] = {033, '[', 'D', '\0'}; - static const Char strH[] = {033, '[', 'H', '\0'}; - static const Char strF[] = {033, '[', 'F', '\0'}; - static const Char stOA[] = {033, 'O', 'A', '\0'}; - static const Char stOB[] = {033, 'O', 'B', '\0'}; - static const Char stOC[] = {033, 'O', 'C', '\0'}; - static const Char stOD[] = {033, 'O', 'D', '\0'}; - static const Char stOH[] = {033, 'O', 'H', '\0'}; - static const Char stOF[] = {033, 'O', 'F', '\0'}; + /* XXX: ESC(033) is not portable character */ + static const Char strA[] = {033, CHR('['), CHR('A'), CHR('\0')}; + static const Char strB[] = {033, CHR('['), CHR('B'), CHR('\0')}; + static const Char strC[] = {033, CHR('['), CHR('C'), CHR('\0')}; + static const Char strD[] = {033, CHR('['), CHR('D'), CHR('\0')}; + static const Char strH[] = {033, CHR('['), CHR('H'), CHR('\0')}; + static const Char strF[] = {033, CHR('['), CHR('F'), CHR('\0')}; + static const Char stOA[] = {033, CHR('O'), CHR('A'), CHR('\0')}; + static const Char stOB[] = {033, CHR('O'), CHR('B'), CHR('\0')}; + static const Char stOC[] = {033, CHR('O'), CHR('C'), CHR('\0')}; + static const Char stOD[] = {033, CHR('O'), CHR('D'), CHR('\0')}; + static const Char stOH[] = {033, CHR('O'), CHR('H'), CHR('\0')}; + static const Char stOF[] = {033, CHR('O'), CHR('F'), CHR('\0')}; keymacro_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); keymacro_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); @@ -1131,7 +1133,7 @@ funckey_t *arrow = el->el_terminal.t_fkey; for (i = 0; i < A_K_NKEYS; i++) - if (*name == '\0' || Strcmp(name, arrow[i].name) == 0) + if (*name == CHR('\0') || Strcmp(name, arrow[i].name) == 0) if (arrow[i].type != XK_NOD) keymacro_kprint(el, arrow[i].name, &arrow[i].fun, arrow[i].type); @@ -1170,7 +1172,7 @@ for (n = 0; n < VISUAL_WIDTH_MAX && p[n]; ++n) wt_str[n] = p[n]; while (n < VISUAL_WIDTH_MAX) - wt_str[n++] = '\0'; + wt_str[n++] = CHR('\0'); px = wt_str; j = (unsigned char) *p; /* @@ -1240,7 +1242,7 @@ i = ct_encode_char(buf, (size_t)MB_LEN_MAX, c); if (i <= 0) return (int)i; - buf[i] = '\0'; + buf[i] = CHR('\0'); return fputs(buf, el->el_outfile); } @@ -1261,8 +1263,8 @@ terminal_writec(EditLine *el, Int c) { Char visbuf[VISUAL_WIDTH_MAX +1]; - ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); - visbuf[vcnt] = '\0'; + ssize_t vcnt = ct_visual_char(el, visbuf, VISUAL_WIDTH_MAX, c); + visbuf[vcnt] = CHR('\0'); terminal_overwrite(el, visbuf, (size_t)vcnt); terminal__flush(el); } @@ -1297,7 +1299,7 @@ const char *ub; if (*ts && **ts) { ub = ct_encode_string(ct_visual_string( - ct_decode_string(*ts, &el->el_scratch)), + el, ct_decode_string(*ts, &el->el_scratch)), &el->el_scratch); } else { ub = "(empty)"; @@ -1584,7 +1586,7 @@ } arg_cols = 0; i = Strtol(*argv, &ep, 10); - if (*ep != '\0' || i < 0) { + if (*ep != CHR('\0') || i < 0) { if (!silent) (void) fprintf(el->el_errfile, "echotc: Bad value `" FSTR "' for rows.\n", @@ -1618,7 +1620,7 @@ return -1; } i = Strtol(*argv, &ep, 10); - if (*ep != '\0' || i < 0) { + if (*ep != CHR('\0') || i < 0) { if (!silent) (void) fprintf(el->el_errfile, "echotc: Bad value `" FSTR "' for cols.\n", @@ -1634,7 +1636,7 @@ return -1; } i = Strtol(*argv, &ep, 10); - if (*ep != '\0' || i < 0) { + if (*ep != CHR('\0') || i < 0) { if (!silent) (void) fprintf(el->el_errfile, "echotc: Bad value `" FSTR "' for rows.\n", @@ -1642,7 +1644,7 @@ return -1; } arg_rows = (int) i; - if (*ep != '\0') { + if (*ep != CHR('\0')) { if (!silent) (void) fprintf(el->el_errfile, "echotc: Bad value `" FSTR "'.\n", *argv); diff -r 21069f8841d0 -r 4cb876518d2a tokenizer.c --- a/tokenizer.c Wed Sep 28 17:39:22 2011 +0900 +++ b/tokenizer.c Fri Oct 07 16:54:23 2011 +0900 @@ -90,7 +90,7 @@ FUN(tok,finish)(TYPE(Tokenizer) *tok) { - *tok->wptr = '\0'; + *tok->wptr = CHR('\0'); if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) { tok->argv[tok->argc++] = tok->wstart; tok->argv[tok->argc] = NULL; @@ -205,7 +205,7 @@ co = (int)(tok->wptr - tok->wstart); } switch (*ptr) { - case '\'': + case CHR('\''): tok->flags |= TOK_KEEP; tok->flags &= ~TOK_EAT; switch (tok->quote) { @@ -237,7 +237,7 @@ } break; - case '"': + case CHR('\"'): tok->flags &= ~TOK_EAT; tok->flags |= TOK_KEEP; switch (tok->quote) { @@ -268,7 +268,7 @@ } break; - case '\\': + case CHR('\\'): tok->flags |= TOK_KEEP; tok->flags &= ~TOK_EAT; switch (tok->quote) { @@ -299,7 +299,7 @@ } break; - case '\n': + case CHR('\n'): tok->flags &= ~TOK_EAT; switch (tok->quote) { case Q_none: @@ -325,7 +325,7 @@ } break; - case '\0': + case CHR('\0'): switch (tok->quote) { case Q_none: /* Finish word and return */ @@ -373,7 +373,7 @@ case Q_doubleone: - *tok->wptr++ = '\\'; + *tok->wptr++ = CHR('\\'); tok->quote = Q_double; *tok->wptr++ = *ptr; break; @@ -428,7 +428,7 @@ if (cursoro != NULL) *cursoro = co; FUN(tok,finish)(tok); - *argv = (const Char **)tok->argv; + *argv = (const Char **)__UNCONST(tok->argv); *argc = (int)tok->argc; return 0; } @@ -445,6 +445,6 @@ memset(&li, 0, sizeof(li)); li.buffer = line; - li.cursor = li.lastchar = Strchr(line, '\0'); + li.cursor = li.lastchar = Strchr(line, CHR('\0')); return FUN(tok,line(tok, &li, argc, argv, NULL, NULL)); } diff -r 21069f8841d0 -r 4cb876518d2a tty.c --- a/tty.c Wed Sep 28 17:39:22 2011 +0900 +++ b/tty.c Fri Oct 07 16:54:23 2011 +0900 @@ -902,7 +902,7 @@ const ttymap_t *tp; el_action_t *map, *alt; const el_action_t *dmap, *dalt; - new[1] = old[1] = '\0'; + new[1] = old[1] = CHR('\0'); map = el->el_map.key; alt = el->el_map.alt; @@ -1192,30 +1192,31 @@ strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name)); name[sizeof(name) - 1] = '\0'; - while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') + while (argv && *argv && + argv[0][0] == CHR('-') && argv[0][2] == CHR('\0')) switch (argv[0][1]) { - case 'a': + case CHR('a'): aflag++; argv++; break; - case 'd': + case CHR('d'): argv++; tios = &el->el_tty.t_ed; z = ED_IO; break; - case 'x': + case CHR('x'): argv++; tios = &el->el_tty.t_ex; z = EX_IO; break; - case 'q': + case CHR('q'): argv++; tios = &el->el_tty.t_ts; z = QU_IO; break; default: (void) fprintf(el->el_errfile, - "%s: Unknown switch `%c'.\n", + "%s: Unknown switch `%lc'.\n", name, argv[0][1]); return -1; } @@ -1267,16 +1268,18 @@ while (argv && (s = *argv++)) { const Char *p; switch (*s) { - case '+': - case '-': - x = (char)*s++; + case CHR('+'): + x = '+'; + break; + case CHR('-'): + x = '-'; break; default: x = '\0'; break; } d = s; - p = Strchr(s, '='); + p = Strchr(s, CHR('=')); for (m = ttymodes; m->m_name; m++) if ((p ? strncmp(m->m_name, ct_encode_string(d, &el->el_scratch), (size_t)(p - d)) : strcmp(m->m_name, ct_encode_string(d, &el->el_scratch))) == 0 && @@ -1290,7 +1293,7 @@ } if (p) { int c = ffs((int)m->m_value); - int v = *++p ? parse__escape(&p) : + int v = *++p ? ct_wctob(parse__escape(el, &p)) : el->el_tty.t_vdisable; assert(c != 0); c--; diff -r 21069f8841d0 -r 4cb876518d2a vi.c --- a/vi.c Wed Sep 28 17:39:22 2011 +0900 +++ b/vi.c Fri Oct 07 16:54:23 2011 +0900 @@ -1060,7 +1060,7 @@ len = (size_t)(el->el_line.lastchar - el->el_line.buffer); len = ct_mbstowcs(el->el_line.buffer, cp, len); - if (len > 0 && el->el_line.buffer[len -1] == '\n') + if (len > 0 && el->el_line.buffer[len -1] == CHR('\n')) --len; } else