aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/erl_driver.xml4
-rw-r--r--erts/doc/src/erlang.xml6
-rw-r--r--erts/emulator/Makefile.in10
-rw-r--r--erts/emulator/beam/atom.names1
-rw-r--r--erts/emulator/beam/beam_load.c5
-rw-r--r--erts/emulator/beam/bif.c17
-rw-r--r--erts/emulator/beam/bif.tab1
-rwxr-xr-xerts/emulator/beam/erl_bif_info.c4
-rw-r--r--erts/emulator/beam/erl_init.c53
-rw-r--r--erts/emulator/beam/erl_unicode.c63
-rw-r--r--erts/emulator/beam/ops.tab2
-rw-r--r--erts/emulator/beam/packet_parser.c2
-rw-r--r--erts/emulator/beam/sys.h14
-rw-r--r--erts/emulator/drivers/common/efile_drv.c2
-rw-r--r--erts/emulator/sys/common/erl_sys_common_misc.c204
-rw-r--r--erts/emulator/test/decode_packet_SUITE.erl3
-rw-r--r--erts/emulator/test/num_bif_SUITE.erl22
-rwxr-xr-xerts/emulator/utils/gen_git_version40
-rw-r--r--erts/lib_src/common/erl_printf_format.c10
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin54120 -> 54360 bytes
-rw-r--r--erts/preloaded/ebin/prim_file.beambin41128 -> 44092 bytes
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl16
-rw-r--r--erts/preloaded/src/prim_file.erl208
23 files changed, 501 insertions, 186 deletions
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 1212c34586..0e27f8a5bd 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -1960,9 +1960,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len
emulator thread. This enables the driver to perform
time-consuming, blocking operations without blocking the
emulator.</p>
- <p>Erlang is by default started without an async thread pool. The
- number of async threads that the runtime system should use
- is specified by the
+ <p>The async thread pool size can be set with the
<seealso marker="erl#async_thread_pool_size">+A</seealso>
command line argument of <seealso marker="erl">erl(1)</seealso>.
If no async thread pool is available, the call is made
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index b336a135e7..5a63aaadc6 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -592,7 +592,9 @@ false</pre>
request, a response, a header or an end of header
mark. Invalid lines are returned as <c><anno>HttpError</anno></c>.</p>
<p>Recognized request methods and header fields are returned as atoms.
- Others are returned as strings.</p>
+ Others are returned as strings. Strings of unrecognized header fields
+ are formatted with only capital letters first and after hyphen characters
+ (like <c>"Sec-Websocket-Key"</c>).</p>
<p>The protocol type <c>http</c> should only be used for
the first line when a <c><anno>HttpRequest</anno></c> or a
<c><anno>HttpResponse</anno></c> is expected. The following calls
@@ -975,7 +977,7 @@ true
<type>
<v>Float = float()</v>
<v>Options = [Option]</v>
- <v>Option = {decimals, Decimals::0..249} |
+ <v>Option = {decimals, Decimals::0..253} |
{scientific, Decimals::0..249} |
compact</v>
</type>
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 3e44bbb8db..7033ea0a3d 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -20,6 +20,8 @@
include $(ERL_TOP)/make/target.mk
include ../vsn.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
+include $(TARGET)/gen_git_version.mk
+
ENABLE_ALLOC_TYPE_VARS = @ENABLE_ALLOC_TYPE_VARS@
HIPE_ENABLED=@HIPE_ENABLED@
@@ -196,7 +198,7 @@ else
EMU_CC = @EMU_CC@
endif
WFLAGS = @WFLAGS@
-CFLAGS = @STATIC_CFLAGS@ $(TYPE_FLAGS) $(FLAVOR_FLAGS) $(DEFS) $(WFLAGS) $(THR_DEFS) $(ARCHCFLAGS)
+CFLAGS = @STATIC_CFLAGS@ $(TYPE_FLAGS) $(FLAVOR_FLAGS) $(DEFS) $(WFLAGS) $(THR_DEFS) $(ARCHCFLAGS) $(GIT_VSN)
HCC = @HCC@
LD = @LD@
DEXPORT = @DEXPORT@
@@ -1006,6 +1008,12 @@ DEP_FLAGS=-MM $(MG_FLAG) $(CFLAGS) $(INCLUDES) -Idrivers/common -Idrivers/$(ERLA
SYS_SRC=$(ALL_SYS_SRC)
endif
+.PHONY: $(TARGET)/gen_git_version.mk
+$(TARGET)/gen_git_version.mk:
+# We touch beam/erl_bif.info.c if we regenerated the git version to force a
+# rebuild.
+ if $(gen_verbose)utils/gen_git_version $@; then touch beam/erl_bif_info.c; fi
+
.PHONY: depend
ifdef VOID_EMULATOR
depend:
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index f138324e1f..ce60bb9bbc 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -269,6 +269,7 @@ atom hipe_architecture
atom http httph https http_response http_request http_header http_eoh http_error http_bin httph_bin
atom id
atom if_clause
+atom ignore
atom imports
atom in
atom in_exiting
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index f57fa2bfbb..81c1ea749a 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -1853,7 +1853,10 @@ load_code(LoaderState* stp)
unsigned tag;
switch (last_op->a[arg].val) {
- case 0: /* Floating point number */
+ case 0:
+ /* Floating point number.
+ * Not generated by the compiler in R16B and later.
+ */
{
Eterm* hp;
/* XXX:PaN - Halfword should use ARCH_64 variant instead */
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 46f76624a5..df084e1185 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2963,15 +2963,14 @@ BIF_RETTYPE float_to_list_2(BIF_ALIST_2)
Eterm* tp = tuple_val(arg);
if (*tp == arity_two && is_small(tp[2])) {
decimals = signed_val(tp[2]);
- if (decimals > 0 && decimals < sizeof(fbuf) - 6 /* "X." ++ "e+YY" */)
- switch (tp[1]) {
- case am_decimals:
- fmt_type = FMT_FIXED;
- continue;
- case am_scientific:
- fmt_type = FMT_SCIENTIFIC;
- continue;
- }
+ switch (tp[1]) {
+ case am_decimals:
+ fmt_type = FMT_FIXED;
+ continue;
+ case am_scientific:
+ fmt_type = FMT_SCIENTIFIC;
+ continue;
+ }
}
}
goto badarg;
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 4aaf466008..e313188901 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -522,6 +522,7 @@ bif erlang:nif_error/2
bif prim_file:internal_name2native/1
bif prim_file:internal_native2name/1
bif prim_file:internal_normalize_utf8/1
+bif prim_file:is_translatable/1
bif file:native_name_encoding/0
#
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index a601e4fb39..8582a8954b 100755
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -69,7 +69,11 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE
" [no-c-stack-objects]"
#endif
#ifndef OTP_RELEASE
+#ifdef ERLANG_GIT_VERSION
+ " [source-" ERLANG_GIT_VERSION "]"
+#else
" [source]"
+#endif
#endif
#ifdef ARCH_64
#if HALFWORD_HEAP
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 223c9c4d7e..ec3e0d54cb 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -981,19 +981,64 @@ erl_start(int argc, char **argv)
break;
case 'f':
if (!strncmp(argv[i],"-fn",3)) {
+ int warning_type = ERL_FILENAME_WARNING_WARNING;
arg = get_arg(argv[i]+3, argv[i+1], &i);
switch (*arg) {
case 'u':
- erts_set_user_requested_filename_encoding(ERL_FILENAME_UTF8);
+ switch (*(argv[i]+4)) {
+ case 'w':
+ case 0:
+ break;
+ case 'i':
+ warning_type = ERL_FILENAME_WARNING_IGNORE;
+ break;
+ case 'e':
+ warning_type = ERL_FILENAME_WARNING_ERROR;
+ break;
+ default:
+ erts_fprintf(stderr, "bad type of warnings for "
+ "wrongly coded filename: %s\n", argv[i]+4);
+ erts_usage();
+ }
+ erts_set_user_requested_filename_encoding
+ (
+ ERL_FILENAME_UTF8,
+ warning_type
+ );
break;
case 'l':
- erts_set_user_requested_filename_encoding(ERL_FILENAME_LATIN1);
+ erts_set_user_requested_filename_encoding
+ (
+ ERL_FILENAME_LATIN1,
+ warning_type
+ );
break;
case 'a':
- erts_set_user_requested_filename_encoding(ERL_FILENAME_UNKNOWN);
+ switch (*(argv[i]+4)) {
+ case 'w':
+ case 0:
+ break;
+ case 'i':
+ warning_type = ERL_FILENAME_WARNING_IGNORE;
+ break;
+ case 'e':
+ warning_type = ERL_FILENAME_WARNING_ERROR;
+ break;
+ default:
+ erts_fprintf(stderr, "bad type of warnings for "
+ "wrongly coded filename: %s\n", argv[i]+4);
+ erts_usage();
+ }
+ erts_set_user_requested_filename_encoding
+ (
+ ERL_FILENAME_UNKNOWN,
+ warning_type
+ );
break;
default:
- erts_fprintf(stderr, "bad filename encoding %s, can be (l,u or a)\n", arg);
+ erts_fprintf(stderr, "bad filename encoding %s, can be "
+ "(l,u or a, optionally followed by w, "
+ "i or e)\n", arg);
erts_usage();
}
break;
diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c
index 99108af937..80982f3760 100644
--- a/erts/emulator/beam/erl_unicode.c
+++ b/erts/emulator/beam/erl_unicode.c
@@ -2573,8 +2573,20 @@ BIF_RETTYPE prim_file_internal_native2name_1(BIF_ALIST_1)
case ERL_FILENAME_UTF8:
bytes = erts_get_aligned_binary_bytes(BIF_ARG_1, &temp_alloc);
if (erts_analyze_utf8(bytes,size,&err_pos,&num_chars,NULL) != ERTS_UTF8_OK) {
+ Eterm *hp = HAlloc(BIF_P,3);
+ Eterm warn_type = NIL;
erts_free_aligned_binary_bytes(temp_alloc);
- goto noconvert;
+ switch (erts_get_filename_warning_type()) {
+ case ERL_FILENAME_WARNING_IGNORE:
+ warn_type = am_ignore;
+ break;
+ case ERL_FILENAME_WARNING_ERROR:
+ warn_type = am_error;
+ break;
+ default:
+ warn_type = am_warning;
+ }
+ BIF_RET(TUPLE2(hp,am_error,warn_type));
}
num_built = 0;
num_eaten = 0;
@@ -2607,9 +2619,8 @@ BIF_RETTYPE prim_file_internal_native2name_1(BIF_ALIST_1)
erts_free_aligned_binary_bytes(temp_alloc);
BIF_RET(ret);
default:
- goto noconvert;
+ break;
}
- noconvert:
BIF_RET(BIF_ARG_1);
}
@@ -2646,6 +2657,52 @@ BIF_RETTYPE prim_file_internal_normalize_utf8_1(BIF_ALIST_1)
BIF_RET(ret);
}
+BIF_RETTYPE prim_file_is_translatable_1(BIF_ALIST_1)
+{
+ ERTS_DECLARE_DUMMY(Eterm real_bin);
+ ERTS_DECLARE_DUMMY(Uint offset);
+ Uint size;
+ Uint num_chars;
+ Uint bitsize;
+ ERTS_DECLARE_DUMMY(Uint bitoffs);
+ byte *temp_alloc = NULL;
+ byte *bytes;
+ byte *err_pos;
+ int status;
+
+ if (is_not_binary(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+ size = binary_size(BIF_ARG_1);
+ ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, offset, bitoffs, bitsize);
+ if (bitsize != 0) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+ if (size == 0) {
+ BIF_RET(am_true);
+ }
+
+ /*
+ * If the encoding is latin1, the pathname is always translatable.
+ */
+ switch (erts_get_native_filename_encoding()) {
+ case ERL_FILENAME_LATIN1:
+ BIF_RET(am_true);
+ case ERL_FILENAME_WIN_WCHAR:
+ if (erts_get_user_requested_filename_encoding() == ERL_FILENAME_LATIN1) {
+ BIF_RET(am_true);
+ }
+ }
+
+ /*
+ * Check whether the binary contains legal UTF-8 sequences.
+ */
+ bytes = erts_get_aligned_binary_bytes(BIF_ARG_1, &temp_alloc);
+ status = erts_analyze_utf8(bytes, size, &err_pos, &num_chars, NULL);
+ erts_free_aligned_binary_bytes(temp_alloc);
+ BIF_RET(status == ERTS_UTF8_OK ? am_true : am_false);
+}
+
BIF_RETTYPE file_native_name_encoding_0(BIF_ALIST_0)
{
switch (erts_get_native_filename_encoding()) {
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 6764e88c81..8a79b4910e 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1021,7 +1021,7 @@ bif0 u$bif:erlang:node/0 Dst=d => node Dst
bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => i_get Src Dst
-bif2 Jump=j u$bif:erlang:element/2 S1=s S2=s Dst=d => gen_element(Jump, S1, S2, Dst)
+bif2 Jump=j u$bif:erlang:element/2 S1=s S2=rxy Dst=d => gen_element(Jump, S1, S2, Dst)
bif1 Fail Bif Literal=q Dst => move Literal x | bif1 Fail Bif x Dst
bif1 p Bif S1 Dst => bif1_body Bif S1 Dst
diff --git a/erts/emulator/beam/packet_parser.c b/erts/emulator/beam/packet_parser.c
index 1e301e3593..7c9b2d444a 100644
--- a/erts/emulator/beam/packet_parser.c
+++ b/erts/emulator/beam/packet_parser.c
@@ -67,7 +67,7 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n)
#define HTTP_HDR_HASH_SIZE 53
#define HTTP_METH_HASH_SIZE 13
-#define HTTP_MAX_NAME_LEN 20
+#define HTTP_MAX_NAME_LEN 50
static char tspecial[128];
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 249a9c05c2..9416a91480 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -1029,10 +1029,22 @@ char* win32_errorstr(int);
#define ERL_FILENAME_UTF8_MAC (3)
#define ERL_FILENAME_WIN_WCHAR (4)
+/************************************************************************
+ * If a filename in for example list_dir is not in the right encoding, it
+ * will be skipped in the resulting list, but depending on a startup setting
+ * we will inform the user in different ways. These macros define the
+ * different reactions to wrongly coded filenames. In the error case an
+ * exception will be thrown by prim_file.
+ ************************************************************************/
+#define ERL_FILENAME_WARNING_WARNING (0)
+#define ERL_FILENAME_WARNING_IGNORE (1)
+#define ERL_FILENAME_WARNING_ERROR (2)
+
int erts_get_native_filename_encoding(void);
/* The set function is only to be used by erl_init! */
-void erts_set_user_requested_filename_encoding(int encoding);
+void erts_set_user_requested_filename_encoding(int encoding, int warning);
int erts_get_user_requested_filename_encoding(void);
+int erts_get_filename_warning_type(void);
void erts_init_sys_common_misc(void);
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index fda6cf2e53..2279fec72a 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -2263,6 +2263,8 @@ file_stop(ErlDrvData e)
desc->fd = FILE_FD_INVALID;
desc->flags = 0;
cq_execute(desc);
+ } else {
+ EF_FREE(desc);
}
} else {
if (desc->fd != FILE_FD_INVALID) {
diff --git a/erts/emulator/sys/common/erl_sys_common_misc.c b/erts/emulator/sys/common/erl_sys_common_misc.c
index 1bf5fa89f4..0b31c125e5 100644
--- a/erts/emulator/sys/common/erl_sys_common_misc.c
+++ b/erts/emulator/sys/common/erl_sys_common_misc.c
@@ -47,14 +47,16 @@
/* Written once and only once */
static int filename_encoding = ERL_FILENAME_UNKNOWN;
+static int filename_warning = ERL_FILENAME_WARNING_WARNING;
#if defined(__WIN32__) || defined(__DARWIN__)
static int user_filename_encoding = ERL_FILENAME_UTF8; /* Default unicode on windows */
#else
static int user_filename_encoding = ERL_FILENAME_LATIN1;
#endif
-void erts_set_user_requested_filename_encoding(int encoding)
+void erts_set_user_requested_filename_encoding(int encoding, int warning)
{
user_filename_encoding = encoding;
+ filename_warning = warning;
}
int erts_get_user_requested_filename_encoding(void)
@@ -62,6 +64,11 @@ int erts_get_user_requested_filename_encoding(void)
return user_filename_encoding;
}
+int erts_get_filename_warning_type(void)
+{
+ return filename_warning;
+}
+
void erts_init_sys_common_misc(void)
{
#if defined(__WIN32__)
@@ -107,9 +114,9 @@ int erts_get_native_filename_encoding(void)
}
/* For internal use by sys_double_to_chars_fast() */
-static char* float_first_trailing_zero(char* p)
+static char* find_first_trailing_zero(char* p)
{
- for (--p; *p == '0' && *(p-1) == '0'; --p);
+ for (; *(p-1) == '0'; --p);
if (*(p-1) == '.') ++p;
return p;
}
@@ -120,34 +127,83 @@ sys_double_to_chars(double fp, char *buffer, size_t buffer_size)
return sys_double_to_chars_ext(fp, buffer, buffer_size, SYS_DEFAULT_FLOAT_DECIMALS);
}
+/* Convert float to string using fixed point notation.
+ * decimals must be >= 0
+ * if compact != 0, the trailing 0's will be truncated
+ */
int
-sys_double_to_chars_fast(double f, char *outbuf, int maxlen, int decimals, int compact)
+sys_double_to_chars_fast(double f, char *buffer, int buffer_size, int decimals,
+ int compact)
{
- enum {
- FRAC_SIZE = 52
- , EXP_SIZE = 11
- , EXP_MASK = (1ll << EXP_SIZE) - 1
- , FRAC_MASK = (1ll << FRAC_SIZE) - 1
- , FRAC_MASK2 = (1ll << (FRAC_SIZE + 1)) - 1
- , MAX_FLOAT = 1ll << (FRAC_SIZE+1)
+ /* Note that some C compilers don't support "static const" propagation
+ * so we use a defines */
+ #define SYS_DOUBLE_RND_CONST 0.55555555555555555
+ #define FRAC_SIZE 52
+ #define EXP_SIZE 11
+ #define EXP_MASK ((1ll << EXP_SIZE) - 1)
+ #define MAX_DECIMALS (sizeof(cs_sys_double_pow10) \
+ / sizeof(cs_sys_double_pow10[0]))
+ #define FRAC_MASK ((1ll << FRAC_SIZE) - 1)
+ #define FRAC_MASK2 ((1ll << (FRAC_SIZE + 1)) - 1)
+ #define MAX_FLOAT (1ll << (FRAC_SIZE+1))
+
+ static const double cs_sys_double_pow10[] = {
+ SYS_DOUBLE_RND_CONST / 1ll,
+ SYS_DOUBLE_RND_CONST / 10ll,
+ SYS_DOUBLE_RND_CONST / 100ll,
+ SYS_DOUBLE_RND_CONST / 1000ll,
+ SYS_DOUBLE_RND_CONST / 10000ll,
+ SYS_DOUBLE_RND_CONST / 100000ll,
+ SYS_DOUBLE_RND_CONST / 1000000ll,
+ SYS_DOUBLE_RND_CONST / 10000000ll,
+ SYS_DOUBLE_RND_CONST / 100000000ll,
+ SYS_DOUBLE_RND_CONST / 1000000000ll,
+ SYS_DOUBLE_RND_CONST / 10000000000ll,
+ SYS_DOUBLE_RND_CONST / 100000000000ll,
+ SYS_DOUBLE_RND_CONST / 1000000000000ll,
+ SYS_DOUBLE_RND_CONST / 10000000000000ll,
+ SYS_DOUBLE_RND_CONST / 100000000000000ll,
+ SYS_DOUBLE_RND_CONST / 1000000000000000ll,
+ SYS_DOUBLE_RND_CONST / 10000000000000000ll,
+ SYS_DOUBLE_RND_CONST / 100000000000000000ll,
+ SYS_DOUBLE_RND_CONST / 1000000000000000000ll
};
- long long mantissa, int_part, int_part2, frac_part;
+ long long mantissa, int_part = 0, frac_part = 0;
short exp;
- int sign, i, n, m, max;
- double absf;
+ int max;
+ int neg;
+ double fr;
union { long long L; double F; } x;
- char c, *p = outbuf;
- int digit, roundup;
+ char *p = buffer;
+
+ if (decimals < 0)
+ return -1;
- x.F = f;
+ /* Round the number to given decimal places. The number of 5's in the
+ * SYS_DOUBLE_RND_CONST constant is chosen such that adding any more 5's doesn't
+ * change the double precision of the number, i.e.:
+ * 1> term_to_binary(0.55555555555555555, [{minor_version, 1}]).
+ * <<131,70,63,225,199,28,113,199,28,114>>
+ * 2> term_to_binary(0.5555555555555555555, [{minor_version, 1}]).
+ * <<131,70,63,225,199,28,113,199,28,114>>
+ */
+ if (f >= 0) {
+ neg = 0;
+ fr = decimals < MAX_DECIMALS ? (f + cs_sys_double_pow10[decimals]) : f;
+ x.F = fr;
+ } else {
+ neg = 1;
+ fr = decimals < MAX_DECIMALS ? (f - cs_sys_double_pow10[decimals]) : f;
+ x.F = -fr;
+ }
exp = (x.L >> FRAC_SIZE) & EXP_MASK;
mantissa = x.L & FRAC_MASK;
- sign = x.L >= 0 ? 1 : -1;
+
if (exp == EXP_MASK) {
if (mantissa == 0) {
- if (sign == -1)
+ if (neg)
*p++ = '-';
*p++ = 'i';
*p++ = 'n';
@@ -158,101 +214,79 @@ sys_double_to_chars_fast(double f, char *outbuf, int maxlen, int decimals, int c
*p++ = 'n';
}
*p = '\0';
- return p - outbuf;
+ return p - buffer;
}
exp -= EXP_MASK >> 1;
mantissa |= (1ll << FRAC_SIZE);
- frac_part = 0;
- int_part = 0;
- absf = f * sign;
-
- /* Don't bother with optimizing too large numbers and decimals */
- if (absf > MAX_FLOAT || decimals > maxlen-17) {
- int len = erts_snprintf(outbuf, maxlen, "%.*f", decimals, f);
- if (len >= maxlen)
+
+ /* Don't bother with optimizing too large numbers or too large precision */
+ if (x.F > MAX_FLOAT || decimals >= MAX_DECIMALS) {
+ int len = erts_snprintf(buffer, buffer_size, "%.*f", decimals, f);
+ char* p = buffer + len;
+ if (len >= buffer_size)
return -1;
- p = outbuf + len;
/* Delete trailing zeroes */
if (compact)
- p = float_first_trailing_zero(outbuf + len);
+ p = find_first_trailing_zero(p);
*p = '\0';
- return p - outbuf;
- }
-
- if (exp >= FRAC_SIZE)
+ return p - buffer;
+ } else if (exp >= FRAC_SIZE) {
int_part = mantissa << (exp - FRAC_SIZE);
- else if (exp >= 0) {
+ } else if (exp >= 0) {
int_part = mantissa >> (FRAC_SIZE - exp);
frac_part = (mantissa << (exp + 1)) & FRAC_MASK2;
- }
- else /* if (exp < 0) */
+ } else /* if (exp < 0) */ {
frac_part = (mantissa & FRAC_MASK2) >> -(exp + 1);
+ }
- if (int_part == 0) {
- if (sign == -1)
+ if (!int_part) {
+ if (neg)
*p++ = '-';
*p++ = '0';
} else {
- int ret;
+ int ret, i, n;
while (int_part != 0) {
- int_part2 = int_part / 10;
- *p++ = (char)(int_part - ((int_part2 << 3) + (int_part2 << 1)) + '0');
- int_part = int_part2;
+ long long j = int_part / 10;
+ *p++ = (char)(int_part - ((j << 3) + (j << 1)) + '0');
+ int_part = j;
}
- if (sign == -1)
+ if (neg)
*p++ = '-';
/* Reverse string */
- ret = p - outbuf;
+ ret = p - buffer;
for (i = 0, n = ret/2; i < n; i++) {
- int j = ret - i - 1;
- c = outbuf[i];
- outbuf[i] = outbuf[j];
- outbuf[j] = c;
+ int j = ret - i - 1;
+ char c = buffer[i];
+ buffer[i] = buffer[j];
+ buffer[j] = c;
}
}
- if (decimals != 0)
+
+ if (decimals > 0) {
+ int i;
*p++ = '.';
- max = maxlen - (p - outbuf) - 1 /* leave room for trailing '\0' */;
- if (max > decimals)
+ max = buffer_size - (p - buffer) - 1 /* leave room for trailing '\0' */;
+
+ if (decimals > max)
+ return -1; /* the number is not large enough to fit in the buffer */
+
max = decimals;
- for (m = 0; m < max; m++) {
- /* frac_part *= 10; */
- frac_part = (frac_part << 3) + (frac_part << 1);
- *p++ = (char)((frac_part >> (FRAC_SIZE + 1)) + '0');
- frac_part &= FRAC_MASK2;
- }
+ for (i = 0; i < max; i++) {
+ /* frac_part *= 10; */
+ frac_part = (frac_part << 3) + (frac_part << 1);
- roundup = 0;
- /* Rounding - look at the next digit */
- frac_part = (frac_part << 3) + (frac_part << 1);
- digit = (frac_part >> (FRAC_SIZE + 1));
- if (digit > 5)
- roundup = 1;
- else if (digit == 5) {
- frac_part &= FRAC_MASK2;
- if (frac_part != 0) roundup = 1;
- }
- if (roundup) {
- char d;
- int pos = p - outbuf - 1;
- do {
- d = outbuf[pos];
- if (d == '-') break;
- if (d == '.') continue;
- if (++d != ':') {
- outbuf[pos] = d;
- break;
- }
- outbuf[pos] = '0';
- } while (--pos);
+ *p++ = (char)((frac_part >> (FRAC_SIZE + 1)) + '0');
+ frac_part &= FRAC_MASK2;
+ }
+
+ /* Delete trailing zeroes */
+ if (compact)
+ p = find_first_trailing_zero(p);
}
- /* Delete trailing zeroes */
- if (compact && *(p - 1) == '0')
- p = float_first_trailing_zero(--p);
*p = '\0';
- return p - outbuf;
+ return p - buffer;
}
diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl
index 4acbe8c6e0..1714551e15 100644
--- a/erts/emulator/test/decode_packet_SUITE.erl
+++ b/erts/emulator/test/decode_packet_SUITE.erl
@@ -403,6 +403,9 @@ http_request(Msg) ->
{"Other-Field: with some text\r\n",
{http_header,0, "Other-Field" ,undefined, "with some text"},
{http_header,0,<<"Other-Field">>,undefined,<<"with some text">>}},
+ {"Make-sure-a-LONG-HEaDer-fIeLd-is-fORMATTED-NicelY: with some text\r\n",
+ {http_header,0, "Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely" ,undefined, "with some text"},
+ {http_header,0,<<"Make-Sure-A-Long-Header-Field-Is-Formatted-Nicely">>,undefined,<<"with some text">>}},
{"Multi-Line: Once upon a time in a land far far away,\r\n"
" there lived a princess imprisoned in the highest tower\r\n"
" of the most haunted castle.\r\n",
diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl
index bf33c337ee..c625e655ce 100644
--- a/erts/emulator/test/num_bif_SUITE.erl
+++ b/erts/emulator/test/num_bif_SUITE.erl
@@ -128,10 +128,17 @@ t_float_to_list(Config) when is_list(Config) ->
"-1.00000000000000000000e+00" = float_to_list(-1.0, []),
"-1.00000000000000000000" = float_to_list(-1.0, [{decimals, 20}]),
{'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{decimals, -1}])),
- {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{decimals, 250}])),
+ {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{decimals, 254}])),
+ {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{scientific, 250}])),
{'EXIT', {badarg, _}} = (catch float_to_list(1.0e+300, [{decimals, 1}])),
"1.0e+300" = float_to_list(1.0e+300, [{scientific, 1}]),
- "1.0" = float_to_list(1.0, [{decimals, 249}, compact]),
+ "1.0" = float_to_list(1.0, [{decimals, 249}, compact]),
+ "1" = float_to_list(1.0, [{decimals, 0}]),
+ "2" = float_to_list(1.9, [{decimals, 0}]),
+ "123456789012345680.0" = erlang:float_to_list(
+ 123456789012345678.0, [{decimals, 236}, compact]),
+ {'EXIT', {badarg, _}} = (catch float_to_list(
+ 123456789012345678.0, [{decimals, 237}])),
Expected = "1." ++ string:copies("0", 249) ++ "e+00",
Expected = float_to_list(1.0, [{scientific, 249}, compact]),
@@ -139,7 +146,8 @@ t_float_to_list(Config) when is_list(Config) ->
X2 = float_to_list(1.0, [{scientific, 20}]),
X1 = X2,
"1.000e+00" = float_to_list(1.0, [{scientific, 3}]),
- "1.000" = float_to_list(1.0, [{decimals, 3}]),
+ "1.000" = float_to_list(1.0, [{decimals, 3}]),
+ "1.0" = float_to_list(1.0, [{decimals, 1}]),
"1.0" = float_to_list(1.0, [{decimals, 3}, compact]),
"1.12" = float_to_list(1.123, [{decimals, 2}]),
"1.123" = float_to_list(1.123, [{decimals, 3}]),
@@ -148,6 +156,14 @@ t_float_to_list(Config) when is_list(Config) ->
"1.12300" = float_to_list(1.123, [{decimals, 5}]),
"1.123" = float_to_list(1.123, [{decimals, 5}, compact]),
"1.1234" = float_to_list(1.1234,[{decimals, 6}, compact]),
+ "1.01" = float_to_list(1.005, [{decimals, 2}]),
+ "-1.01" = float_to_list(-1.005,[{decimals, 2}]),
+ "0.999" = float_to_list(0.999, [{decimals, 3}]),
+ "-0.999" = float_to_list(-0.999,[{decimals, 3}]),
+ "1.0" = float_to_list(0.999, [{decimals, 2}, compact]),
+ "-1.0" = float_to_list(-0.999,[{decimals, 2}, compact]),
+ "0.5" = float_to_list(0.5, [{decimals, 1}]),
+ "-0.5" = float_to_list(-0.5, [{decimals, 1}]),
"2.333333" = erlang:float_to_list(7/3, [{decimals, 6}, compact]),
"2.333333" = erlang:float_to_list(7/3, [{decimals, 6}]),
"0.00000000000000000000e+00" = float_to_list(0.0, [compact]),
diff --git a/erts/emulator/utils/gen_git_version b/erts/emulator/utils/gen_git_version
new file mode 100755
index 0000000000..d93a97cbbb
--- /dev/null
+++ b/erts/emulator/utils/gen_git_version
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+OUTPUT_FILE=$1
+
+if command -v git 2>&1 >/dev/null &&
+ test -d $ERL_TOP/.git -o -f $ERL_TOP/.git
+then
+ VSN=`git describe --match "OTP_R[0-9][0-9][A-B]*" HEAD`
+ case "$VSN" in
+ OTP_R*-g*)
+ VSN=`echo $VSN | sed -e 's/.*-g\\(.*\\)/\\1/g'` ;;
+ *) VSN="na" ;;
+ esac
+else
+ VSN="na"
+fi
+
+
+# Only update the file if there has been a change to
+# the version number.
+if test -r $OUTPUT_FILE
+then
+ VC=`sed -n -e 's/^.*"\\\\"\\(.*\\)\\\\"".*/\\1/p' < $OUTPUT_FILE`
+else
+ VC=unset
+fi
+echo "VSN = $VSN"
+echo "VC = $VC"
+if test "$VSN" != "$VC"
+then
+ echo "# Automatically generated by $0 - DO NOT EDIT." > $OUTPUT_FILE
+ if test "$VSN" = "na"
+ then
+ echo "# GIT_VSN=-DERLANG_GIT_VERSION=\"\\\"$VSN\\\"\"" >> $OUTPUT_FILE
+ else
+ echo "GIT_VSN=-DERLANG_GIT_VERSION=\"\\\"$VSN\\\"\"" >> $OUTPUT_FILE
+ fi
+ exit 0
+fi
+exit 1 \ No newline at end of file
diff --git a/erts/lib_src/common/erl_printf_format.c b/erts/lib_src/common/erl_printf_format.c
index 384b1b1ad7..00df3f068f 100644
--- a/erts/lib_src/common/erl_printf_format.c
+++ b/erts/lib_src/common/erl_printf_format.c
@@ -335,7 +335,7 @@ static int fmt_double(fmtfn_t fn,void*arg,double val,
int fi = 0;
char format_str[7];
char sbuf[32];
- char *bufp;
+ char *bufp = sbuf;
double dexp;
int exp;
size_t max_size = 1;
@@ -425,12 +425,12 @@ static int fmt_double(fmtfn_t fn,void*arg,double val,
max_size++; /* '\0' */
- if (max_size < sizeof(sbuf))
- bufp = sbuf;
- else {
+ if (max_size >= sizeof(sbuf)) {
bufp = (char *) malloc(sizeof(char)*max_size);
if (!bufp) {
res = -ENOMEM;
+ /* Make sure not to trigger free */
+ bufp = sbuf;
goto out;
}
}
@@ -448,10 +448,10 @@ static int fmt_double(fmtfn_t fn,void*arg,double val,
res = fmt_fld(fn, arg, bufp, size, 0, width, 0, new_fmt, count);
+ out:
if (bufp != sbuf)
free((void *) bufp);
- out:
if (erts_printf_unblock_fpe)
(*erts_printf_unblock_fpe)(fpe_was_unmasked);
return res;
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index f8c2df3a5a..4a3af265c1 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index ca93edbe25..f7b3aac376 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index d36fdeba3f..7490954f2d 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -149,8 +149,18 @@ start_it("inet", Id, Pid, Hosts) ->
start_it("efile", Id, Pid, _Hosts) ->
process_flag(trap_exit, true),
- {ok, Port} = prim_file:open([binary]),
- init_ack(Pid),
+ {ok, Port} = prim_file:start(),
+ %% Check that we started in a valid directory.
+ case prim_file:get_cwd(Port) of
+ {error, _} ->
+ %% At this point in the startup, we have no error_logger at all.
+ Report = "Invalid current directory or invalid filename "
+ "mode: loader cannot read current directory\n",
+ erlang:display(Report),
+ exit({error, invalid_current_directory});
+ _ ->
+ init_ack(Pid)
+ end,
MultiGet = case erlang:system_info(thread_pool_size) of
0 -> false;
_ -> true
@@ -434,7 +444,7 @@ efile_multi_get_file_from_port2(_MFs, 0, _Max, State, _Paths, _Fun, _Ref, Ret) -
efile_par_get_file(Ref, State, {Mod,File} = MF, Paths, Pid, Fun) ->
%% One port for each file read in "parallel":
- case prim_file:open([binary]) of
+ case prim_file:start() of
{ok, Port} ->
Port0 = State#state.data,
State1 = State#state{data = Port},
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 50adf9c89d..bf8879c2a0 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -50,9 +50,9 @@
write_file_info/2, write_file_info/3, write_file_info/4,
make_link/2, make_link/3,
make_symlink/2, make_symlink/3,
- read_link/1, read_link/2,
+ read_link/1, read_link/2, read_link_all/1, read_link_all/2,
read_link_info/1, read_link_info/2, read_link_info/3,
- list_dir/1, list_dir/2]).
+ list_dir/1, list_dir/2, list_dir_all/1, list_dir_all/2]).
%% How to start and stop the ?DRV port.
-export([start/0, stop/1]).
@@ -152,16 +152,19 @@
-export([internal_name2native/1,
internal_native2name/1,
- internal_normalize_utf8/1]).
+ internal_normalize_utf8/1,
+ is_translatable/1]).
-type prim_file_name() :: string() | unicode:unicode_binary().
+-type prim_file_name_error() :: 'error' | 'ignore' | 'warning'.
-spec internal_name2native(prim_file_name()) -> binary().
internal_name2native(_) ->
erlang:nif_error(undefined).
--spec internal_native2name(binary()) -> prim_file_name().
+-spec internal_native2name(binary()) ->
+ prim_file_name() | {'error',prim_file_name_error()}.
internal_native2name(_) ->
erlang:nif_error(undefined).
@@ -171,6 +174,11 @@ internal_native2name(_) ->
internal_normalize_utf8(_) ->
erlang:nif_error(undefined).
+-spec is_translatable(prim_file_name()) -> boolean().
+
+is_translatable(_) ->
+ erlang:nif_error(undefined).
+
%%% End of BIFs
%%%-----------------------------------------------------------------
@@ -210,12 +218,7 @@ open(_, _) ->
%% Opens a port that can be used for open/3 or read_file/2.
%% Returns {ok, Port} | {error, Reason}.
open(Portopts) when is_list(Portopts) ->
- case drv_open(?FD_DRV, Portopts) of
- {error, _} = Error ->
- Error;
- Other ->
- Other
- end;
+ drv_open(?FD_DRV, [binary|Portopts]);
open(_) ->
{error, badarg}.
@@ -607,13 +610,7 @@ sendfile(#file_descriptor{module = ?MODULE, data = {Port, _}},
%% Returns {ok, Port}, the Port should be used as first argument in all
%% the following functions. Returns {error, Reason} upon failure.
start() ->
- try erlang:open_port({spawn, ?DRV}, [binary]) of
- Port ->
- {ok, Port}
- catch
- error:Reason ->
- {error, Reason}
- end.
+ drv_open(?DRV, [binary]).
stop(Port) when is_port(Port) ->
try erlang:port_close(Port) of
@@ -667,7 +664,8 @@ get_cwd_int(Drive) ->
get_cwd_int({?DRV, [binary]}, Drive).
get_cwd_int(Port, Drive) ->
- drv_command(Port, <<?FILE_PWD, Drive>>).
+ drv_command(Port, <<?FILE_PWD, Drive>>,
+ fun handle_fname_response/1).
@@ -679,10 +677,17 @@ set_cwd(Dir) ->
set_cwd(Port, Dir) when is_port(Port) ->
set_cwd_int(Port, Dir).
-set_cwd_int(Port, Dir) ->
- %% Dir is now either a string or an EXIT tuple.
- %% An EXIT tuple will fail in the following catch.
- drv_command(Port, [?FILE_CHDIR, pathname(Dir)]).
+set_cwd_int(Port, Dir) when is_binary(Dir) ->
+ case prim_file:is_translatable(Dir) of
+ false ->
+ {error, no_translation};
+ true ->
+ drv_command(Port, [?FILE_CHDIR, pathname(Dir)])
+ end;
+set_cwd_int(Port, Dir) when is_list(Dir) ->
+ drv_command(Port, [?FILE_CHDIR, pathname(Dir)]);
+set_cwd_int(_, _) ->
+ {error, badarg}.
@@ -775,7 +780,8 @@ altname(Port, File) when is_port(Port) ->
altname_int(Port, File).
altname_int(Port, File) ->
- drv_command(Port, [?FILE_ALTNAME, pathname(File)]).
+ drv_command(Port, [?FILE_ALTNAME, pathname(File)],
+ fun handle_fname_response/1).
%% write_file_info/{2,3,4}
@@ -868,7 +874,20 @@ read_link(Port, Link) when is_port(Port) ->
read_link_int(Port, Link).
read_link_int(Port, Link) ->
- drv_command(Port, [?FILE_READLINK, pathname(Link)]).
+ drv_command(Port, [?FILE_READLINK, pathname(Link)],
+ fun handle_fname_response/1).
+
+%% read_link_all/{2,3}
+
+read_link_all(Link) ->
+ read_link_all_int({?DRV, [binary]}, Link).
+
+read_link_all(Port, Link) when is_port(Port) ->
+ read_link_all_int(Port, Link).
+
+read_link_all_int(Port, Link) ->
+ drv_command(Port, [?FILE_READLINK, pathname(Link)],
+ fun handle_fname_response_all/1).
@@ -910,20 +929,112 @@ list_dir(Port, Dir) when is_port(Port) ->
list_dir_int(Port, Dir).
list_dir_int(Port, Dir) ->
- drv_command(Port, [?FILE_READDIR, pathname(Dir)], []).
-
+ drv_command(Port, [?FILE_READDIR, pathname(Dir)],
+ fun(P) ->
+ case list_dir_response(P, []) of
+ {ok, RawNames} ->
+ {ok, list_dir_convert(RawNames)};
+ Error ->
+ Error
+ end
+ end).
+
+list_dir_all(Dir) ->
+ list_dir_all_int({?DRV, [binary]}, Dir).
+
+list_dir_all(Port, Dir) when is_port(Port) ->
+ list_dir_all_int(Port, Dir).
+
+list_dir_all_int(Port, Dir) ->
+ drv_command(Port, [?FILE_READDIR, pathname(Dir)],
+ fun(P) ->
+ case list_dir_response(P, []) of
+ {ok, RawNames} ->
+ {ok, list_dir_convert_all(RawNames)};
+ Error ->
+ Error
+ end
+ end).
+
+list_dir_response(Port, Acc0) ->
+ case drv_get_response(Port) of
+ {lfname, []} ->
+ {ok, Acc0};
+ {lfname, Names} ->
+ Acc = [Name || <<L:16,Name:L/binary>> <= Names] ++ Acc0,
+ list_dir_response(Port, Acc);
+ Error ->
+ Error
+ end.
+list_dir_convert([Name|Names]) ->
+ %% If the filename cannot be converted, return error or ignore
+ %% with optional error logger warning, depending on +fn{u|a}{i|e|w}
+ %% emulator switches.
+ case prim_file:internal_native2name(Name) of
+ {error, warning} ->
+ error_logger:warning_msg("Non-unicode filename ~p ignored\n",
+ [Name]),
+ list_dir_convert(Names);
+ {error, ignore} ->
+ list_dir_convert(Names);
+ {error, error} ->
+ {error, {no_translation, Name}};
+ Converted when is_list(Converted) ->
+ [Converted|list_dir_convert(Names)]
+ end;
+list_dir_convert([]) -> [].
+
+list_dir_convert_all([Name|Names]) ->
+ %% If the filename cannot be converted, retain the filename as
+ %% a binary.
+ case prim_file:internal_native2name(Name) of
+ {error, _} ->
+ [Name|list_dir_convert(Names)];
+ Converted when is_list(Converted) ->
+ [Converted|list_dir_convert(Names)]
+ end;
+list_dir_convert_all([]) -> [].
%%%-----------------------------------------------------------------
%%% Functions to communicate with the driver
+handle_fname_response(Port) ->
+ case drv_get_response(Port) of
+ {fname, Name} ->
+ case prim_file:internal_native2name(Name) of
+ {error, warning} ->
+ error_logger:warning_msg("Non-unicode filename ~p "
+ "ignored when reading link\n",
+ [Name]),
+ {error, einval};
+ {error, _} ->
+ {error, einval};
+ Converted when is_list(Converted) ->
+ {ok, Converted}
+ end;
+ Error ->
+ Error
+ end.
+handle_fname_response_all(Port) ->
+ case drv_get_response(Port) of
+ {fname, Name} ->
+ case prim_file:internal_native2name(Name) of
+ {error, _} ->
+ {ok, Name};
+ Converted when is_list(Converted) ->
+ {ok, Converted}
+ end;
+ Error ->
+ Error
+ end.
%% Opens a driver port and converts any problems into {error, emfile}.
%% Returns {ok, Port} when successful.
drv_open(Driver, Portopts) ->
- try erlang:open_port({spawn, Driver}, Portopts) of
+ try erlang:open_port({spawn_driver, Driver}, Portopts) of
Port ->
{ok, Port}
catch
@@ -1028,19 +1139,10 @@ drv_command_nt(Port, Command, R) when is_port(Port) ->
%% Receives the response from a driver port.
%% Returns: {ok, ListOrBinary}|{error, Reason}
-drv_get_response(Port, R) when is_list(R) ->
- case drv_get_response(Port) of
- ok ->
- {ok, R};
- {ok, Name} ->
- drv_get_response(Port, [Name|R]);
- {append, Names} ->
- drv_get_response(Port, append(Names, R));
- Error ->
- Error
- end;
-drv_get_response(Port, _) ->
- drv_get_response(Port).
+drv_get_response(Port, undefined) ->
+ drv_get_response(Port);
+drv_get_response(Port, Fun) when is_function(Fun, 1) ->
+ Fun(Port).
drv_get_response(Port) ->
erlang:bump_reductions(100),
@@ -1060,10 +1162,6 @@ drv_get_response(Port) ->
%%%-----------------------------------------------------------------
%%% Utility functions.
-append([I | Is], R) when is_list(R) -> append(Is, [I | R]);
-append([], R) -> R.
-
-
%% Converts a list of mode atoms into a mode word for the driver.
%% Returns {Mode, Portopts, Setopts} where Portopts is a list of
%% options for erlang:open_port/2 and Setopts is a list of
@@ -1205,18 +1303,10 @@ translate_response(?FILE_RESP_N2DATA = X, L0) when is_list(L0) ->
end;
translate_response(?FILE_RESP_EOF, []) ->
eof;
-translate_response(?FILE_RESP_FNAME, []) ->
- ok;
-translate_response(?FILE_RESP_FNAME, Data) when is_binary(Data) ->
- {ok, prim_file:internal_native2name(Data)};
translate_response(?FILE_RESP_FNAME, Data) ->
- {ok, Data};
-translate_response(?FILE_RESP_LFNAME, []) ->
- ok;
-translate_response(?FILE_RESP_LFNAME, Data) when is_binary(Data) ->
- {append, transform_lfname(Data)};
+ {fname, Data};
translate_response(?FILE_RESP_LFNAME, Data) ->
- {append, transform_lfname(Data)};
+ {lfname, Data};
translate_response(?FILE_RESP_ALL_DATA, Data) ->
{ok, Data};
translate_response(X, Data) ->
@@ -1332,16 +1422,6 @@ transform_ldata(0, List, [Size | Sizes], R) ->
{Front, Rear} = lists_split(List, Size),
transform_ldata(0, Rear, Sizes, [Front | R]).
-transform_lfname(<<>>) -> [];
-transform_lfname(<<L:16, Name:L/binary, Names/binary>>) ->
- [ prim_file:internal_native2name(Name) | transform_lfname(Names)];
-transform_lfname([]) -> [];
-transform_lfname([L1,L2|Names]) ->
- L = (L1 bsl 8) bor L2,
- {Name, Rest} = lists_split(Names, L),
- [Name | transform_lfname(Rest)].
-
-
lists_split(List, 0) when is_list(List) ->
{[], List};
lists_split(List, N) when is_list(List), is_integer(N), N < 0 ->