diff options
author | Björn-Egil Dahlberg <[email protected]> | 2016-05-13 16:48:10 +0200 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2016-05-13 16:48:10 +0200 |
commit | 4fba4b14c4f9aa03294d8d187fe0dd1202744e82 (patch) | |
tree | bfcdef0c8ab9e14c1bf149c0a0f0d6b9c8ce39d3 | |
parent | 66da26c92043c71740ea628469ad6ada747b89bf (diff) | |
parent | 88095fc0adb871671ff9763bd5868d7c0c0ac350 (diff) | |
download | otp-4fba4b14c4f9aa03294d8d187fe0dd1202744e82.tar.gz otp-4fba4b14c4f9aa03294d8d187fe0dd1202744e82.tar.bz2 otp-4fba4b14c4f9aa03294d8d187fe0dd1202744e82.zip |
Merge branch 'egil/erts/nif-format_term/OTP-13580'
* egil/erts/nif-format_term/OTP-13580:
runtime_tools: Change erts_snprintf to enif_snprintf
erts: Document enif_snprintf
erts: Add tests for enif_snprintf
erts: Add enif_snprintf
Conflicts:
erts/emulator/beam/erl_nif_api_funcs.h
-rw-r--r-- | erts/doc/src/erl_nif.xml | 9 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 10 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.h | 3 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif_api_funcs.h | 2 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 17 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 20 | ||||
-rw-r--r-- | lib/runtime_tools/c_src/dyntrace.c | 20 | ||||
-rw-r--r-- | lib/runtime_tools/c_src/dyntrace_lttng.h | 6 |
8 files changed, 69 insertions, 18 deletions
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index fefec3eeb6..33a4fee182 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -1763,6 +1763,15 @@ enif_map_iterator_destroy(env, &iter); <desc><p>Get the byte size of a resource object <c>obj</c> obtained by <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.</p></desc> </func> + + <func><name><ret>int</ret><nametext>enif_snprintf(char *str, size_t size, const char *format, ...)</nametext></name> + <fsummary>Format strings and Erlang terms</fsummary> + <desc> + <p>Similar to <c>snprintf</c> but this format string also accepts <c>"%T"</c> which formats Erlang terms. + </p> + </desc> + </func> + <func> <name><ret>void</ret><nametext>enif_system_info(ErlNifSysInfo *sys_info_ptr, size_t size)</nametext></name> <fsummary>Get information about the Erlang runtime system</fsummary> diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 8a3007d52a..159dc66ad5 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -1810,6 +1810,16 @@ int enif_fprintf(void* filep, const char* format, ...) return ret; } +int enif_snprintf(char *buffer, size_t size, const char* format, ...) +{ + int ret; + va_list arglist; + va_start(arglist, format); + ret = erts_vsnprintf(buffer, size, format, arglist); + va_end(arglist); + return ret; +} + /*********************************************************** ** Memory managed (GC'ed) "resource" objects ** ***********************************************************/ diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index 02c82415fd..da7a754757 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -49,9 +49,10 @@ ** 2.8: 18.0 add enif_has_pending_exception ** 2.9: 18.2 enif_getenv ** 2.10: Time API +** 2.11: 19.0 enif_snprintf */ #define ERL_NIF_MAJOR_VERSION 2 -#define ERL_NIF_MINOR_VERSION 10 +#define ERL_NIF_MINOR_VERSION 11 /* * The emulator will refuse to load a nif-lib with a major version diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index 1bdac51d1f..b211ab4b16 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -174,6 +174,7 @@ ERL_NIF_API_FUNC_DECL(int, enif_term_to_binary, (ErlNifEnv *env, ERL_NIF_TERM te ERL_NIF_API_FUNC_DECL(size_t, enif_binary_to_term, (ErlNifEnv *env, const unsigned char* data, size_t sz, ERL_NIF_TERM *term, unsigned int opts)); ERL_NIF_API_FUNC_DECL(int, enif_port_command, (ErlNifEnv *env, const ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg)); ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*)); +ERL_NIF_API_FUNC_DECL(int,enif_snprintf,(char * buffer, size_t size, const char *format, ...)); /* ** ADD NEW ENTRIES HERE (before this comment) !!! @@ -330,6 +331,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*)); # define enif_binary_to_term ERL_NIF_API_FUNC_MACRO(enif_binary_to_term) # define enif_port_command ERL_NIF_API_FUNC_MACRO(enif_port_command) # define enif_is_on_dirty_scheduler ERL_NIF_API_FUNC_MACRO(enif_is_on_dirty_scheduler) +# define enif_snprintf ERL_NIF_API_FUNC_MACRO(enif_snprintf) /* ** ADD NEW ENTRIES HERE (before this comment) diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index a1e1495480..a0e9f1bad6 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -45,7 +45,8 @@ nif_now_time/1, nif_cpu_time/1, nif_unique_integer/1, nif_is_process_alive/1, nif_is_port_alive/1, nif_term_to_binary/1, nif_binary_to_term/1, - nif_port_command/1 + nif_port_command/1, + nif_snprintf/1 ]). -export([many_args_100/100]). @@ -79,8 +80,8 @@ all() -> nif_now_time, nif_cpu_time, nif_unique_integer, nif_is_process_alive, nif_is_port_alive, nif_term_to_binary, nif_binary_to_term, - nif_port_command - ]. + nif_port_command, + nif_snprintf]. init_per_testcase(_Case, Config) -> Config. @@ -1952,9 +1953,18 @@ nif_port_command(Config) -> port_close(Port), {'EXIT', {badarg, _}} = (catch port_command_nif(Port, "hello\n")), + ok. +nif_snprintf(Config) -> + ensure_lib_loaded(Config), + <<"ok",0>> = format_term_nif(3,ok), + <<"o",0>> = format_term_nif(2,ok), + <<"\"hello world\"",0>> = format_term_nif(14,"hello world"), + <<"{{hello,world,-33},3.14",_/binary>> = format_term_nif(50,{{hello,world, -33}, 3.14, self()}), + <<"{{hello,world,-33},",0>> = format_term_nif(20,{{hello,world, -33}, 3.14, self()}), ok. + %% The NIFs: lib_version() -> undefined. call_history() -> ?nif_stub. @@ -2015,6 +2025,7 @@ is_port_alive_nif(_) -> ?nif_stub. term_to_binary_nif(_, _) -> ?nif_stub. binary_to_term_nif(_, _, _) -> ?nif_stub. port_command_nif(_, _) -> ?nif_stub. +format_term_nif(_,_) -> ?nif_stub. %% maps is_map_nif(_) -> ?nif_stub. diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 73073ad59f..13846244d4 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -1998,6 +1998,23 @@ static ERL_NIF_TERM port_command(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar return atom_true; } +static ERL_NIF_TERM format_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifBinary obin; + unsigned int size; + + if (!enif_get_uint(env, argv[0], &size)) + return enif_make_badarg(env); + if (!enif_alloc_binary(size,&obin)) + return enif_make_badarg(env); + + if (enif_snprintf((char*)obin.data, (size_t)size, "%T", argv[1]) < 0) + return atom_false; + + return enif_make_binary(env,&obin); +} + + static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, @@ -2073,7 +2090,8 @@ static ErlNifFunc nif_funcs[] = {"is_port_alive_nif", 1, is_port_alive}, {"term_to_binary_nif", 2, term_to_binary}, {"binary_to_term_nif", 3, binary_to_term}, - {"port_command_nif", 2, port_command} + {"port_command_nif", 2, port_command}, + {"format_term_nif", 2, format_term} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload) diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 0178d95efb..e7a4a73373 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -433,7 +433,7 @@ static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv char class[LTTNG_BUFFER_SZ]; enif_get_tuple(env, argv[4], &arity, &tuple); - erts_snprintf(class, LTTNG_BUFFER_SZ, "%T", tuple[0]); + enif_snprintf(class, LTTNG_BUFFER_SZ, "%T", tuple[0]); if (enif_get_tuple(env, argv[3], &arity, &tuple)) { enif_get_uint(env, tuple[2], &len); @@ -465,7 +465,7 @@ static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv char msg[LTTNG_BUFFER_SZ]; lttng_pid_to_str(argv[4], to); - erts_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); + enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); LTTNG3(message_send, pid, to, msg); } else if (argv[0] == atom_send_to_non_existing_process) { @@ -473,7 +473,7 @@ static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv char msg[LTTNG_BUFFER_SZ]; lttng_pid_to_str(argv[4], to); - erts_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); + enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); /* mark it as non existing ? */ LTTNG3(message_send, pid, to, msg); @@ -496,7 +496,7 @@ static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM a char msg[LTTNG_BUFFER_SZ]; lttng_pid_to_str(argv[2], pid); - erts_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); + enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); LTTNG2(message_receive, pid, msg); } @@ -560,11 +560,11 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg /* register */ } else if (argv[0] == atom_register) { char name[LTTNG_BUFFER_SZ]; - erts_snprintf(name, LTTNG_BUFFER_SZ, "%T", argv[3]); + enif_snprintf(name, LTTNG_BUFFER_SZ, "%T", argv[3]); LTTNG3(process_register, pid, name, "register"); } else if (argv[0] == atom_unregister) { char name[LTTNG_BUFFER_SZ]; - erts_snprintf(name, LTTNG_BUFFER_SZ, "%T", argv[3]); + enif_snprintf(name, LTTNG_BUFFER_SZ, "%T", argv[3]); LTTNG3(process_register, pid, name, "unregister"); /* link */ } else if (argv[0] == atom_link) { @@ -582,7 +582,7 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg /* exit */ } else if (argv[0] == atom_exit) { char reason[LTTNG_BUFFER_SZ]; - erts_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]); + enif_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]); LTTNG2(process_exit, pid, reason); } return atom_ok; @@ -622,11 +622,11 @@ static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg lttng_decl_procbuf(pid); lttng_pid_to_str(argv[3], pid); - erts_snprintf(driver, LTTNG_BUFFER_SZ, "%T", argv[4]); + enif_snprintf(driver, LTTNG_BUFFER_SZ, "%T", argv[4]); LTTNG3(port_open, pid, driver, port); } else if (argv[0] == atom_closed) { char reason[LTTNG_BUFFER_SZ]; - erts_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]); + enif_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]); LTTNG2(port_exit, port, reason); /* link */ @@ -705,7 +705,7 @@ static ERL_NIF_TERM trace_running_ports(ErlNifEnv* env, int argc, const ERL_NIF_ lttng_decl_mfabuf(where); lttng_portid_to_str(argv[2], pid); - erts_snprintf(where, LTTNG_BUFFER_SZ, "%T", argv[3]); + enif_snprintf(where, LTTNG_BUFFER_SZ, "%T", argv[3]); /* running ports */ if (argv[0] == atom_in) { diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h index 3550a1cab5..2a3224e191 100644 --- a/lib/runtime_tools/c_src/dyntrace_lttng.h +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -59,10 +59,10 @@ char Name[LTTNG_MFA_BUFFER_SZ] #define lttng_pid_to_str(pid, name) \ - erts_snprintf(name, LTTNG_PROC_BUFFER_SZ, "%T", (pid)) + enif_snprintf(name, LTTNG_PROC_BUFFER_SZ, "%T", (pid)) #define lttng_portid_to_str(pid, name) \ - erts_snprintf(name, LTTNG_PORT_BUFFER_SZ, "%T", (pid)) + enif_snprintf(name, LTTNG_PORT_BUFFER_SZ, "%T", (pid)) #define lttng_proc_to_str(p, name) \ lttng_pid_to_str(((p) ? (p)->common.id : ERTS_INVALID_PID), name) @@ -71,7 +71,7 @@ lttng_portid_to_str(((p) ? (p)->common.id : ERTS_INVALID_PORT), name) #define lttng_mfa_to_str(m,f,a, Name) \ - erts_snprintf(Name, LTTNG_MFA_BUFFER_SZ, "%T:%T/%lu", (Eterm)(m), (Eterm)(f), (Uint)(a)) + enif_snprintf(Name, LTTNG_MFA_BUFFER_SZ, "%T:%T/%lu", (Eterm)(m), (Eterm)(f), (Uint)(a)) /* Process scheduling */ |