diff options
author | Rickard Green <[email protected]> | 2017-08-23 14:26:23 +0200 |
---|---|---|
committer | Rickard Green <[email protected]> | 2017-08-23 14:26:23 +0200 |
commit | db8fba1aace21af71e015e2620ed6e7c1a5bfab2 (patch) | |
tree | b270e4ab7bf4c09342400c1fbfcdcd5264cec45f /erts/emulator/beam | |
parent | 8453bda5805bc8a2d4709b5d15643fb0512a8a23 (diff) | |
parent | d50bc5031eb0889c894bf20f5206cfc06162f30a (diff) | |
download | otp-db8fba1aace21af71e015e2620ed6e7c1a5bfab2.tar.gz otp-db8fba1aace21af71e015e2620ed6e7c1a5bfab2.tar.bz2 otp-db8fba1aace21af71e015e2620ed6e7c1a5bfab2.zip |
Merge branch 'maint'
* maint:
Unicode support for erlang:display_string/1
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/bif.c | 15 | ||||
-rw-r--r-- | erts/emulator/beam/global.h | 1 | ||||
-rw-r--r-- | erts/emulator/beam/utils.c | 46 |
3 files changed, 56 insertions, 6 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 8e3b28cd60..7e26af5abd 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -3889,15 +3889,18 @@ BIF_RETTYPE display_string_1(BIF_ALIST_1) { Process* p = BIF_P; Eterm string = BIF_ARG_1; - Sint len = is_string(string); - char *str; + Sint len = erts_unicode_list_to_buf_len(string); + Sint written; + byte *str; + int res; - if (len <= 0) { + if (len < 0) { BIF_ERROR(p, BADARG); } - str = (char *) erts_alloc(ERTS_ALC_T_TMP, sizeof(char)*(len + 1)); - if (intlist_to_buf(string, str, len) != len) - erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error\n", __FILE__, __LINE__); + str = (byte *) erts_alloc(ERTS_ALC_T_TMP, sizeof(char)*(len + 1)); + res = erts_unicode_list_to_buf(string, str, len, &written); + if (res != 0 || written != len) + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error (%d)\n", __FILE__, __LINE__, res); str[len] = '\0'; erts_fprintf(stderr, "%s", str); erts_free(ERTS_ALC_T_TMP, (void *) str); diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 9ea29e7626..27a6202bb7 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1281,6 +1281,7 @@ int erts_utf8_to_latin1(byte* dest, const byte* source, int slen); void bin_write(fmtfn_t, void*, byte*, size_t); Sint intlist_to_buf(Eterm, char*, Sint); /* most callers pass plain char*'s */ int erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len, Sint* written); +Sint erts_unicode_list_to_buf_len(Eterm list); struct Sint_buf { #if defined(ARCH_64) diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index a88158cd3a..d93c232d66 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -3675,6 +3675,52 @@ erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len, Sint* written) return res; } +Sint +erts_unicode_list_to_buf_len(Eterm list) +{ + Eterm* listptr; + Sint sz = 0; + + if (is_nil(list)) { + return 0; + } + if (is_not_list(list)) { + return -1; + } + listptr = list_val(list); + + while (1) { + Sint val; + + if (is_not_small(CAR(listptr))) { + return -1; + } + val = signed_val(CAR(listptr)); + if (0 <= val && val < 0x80) { + sz++; + } else if (val < 0x800) { + sz += 2; + } else if (val < 0x10000UL) { + if (0xD800 <= val && val <= 0xDFFF) { + return -1; + } + sz += 3; + } else if (val < 0x110000) { + sz += 4; + } else { + return -1; + } + list = CDR(listptr); + if (is_nil(list)) { + return sz; + } + if (is_not_list(list)) { + return -1; + } + listptr = list_val(list); + } +} + /* ** Convert an integer to a byte list ** return pointer to converted stuff (need not to be at start of buf!) |