From 9be9df22e4576db0527d1401df3c2dd78cf5af14 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Thu, 1 Sep 2022 12:07:42 +0100 Subject: [PATCH] Add Sys.interpreter In native code, Sys.interpreter is simply Sys.executable_name, but in bytecode it is the path to the actual interpreter (which will only be Sys.executable_name for -custom or -output-complete-* programs) --- Changes | 4 ++++ runtime/caml/startup_aux.h | 3 ++- runtime/caml/sys.h | 2 +- runtime/startup_aux.c | 3 ++- runtime/startup_byt.c | 4 ++-- runtime/startup_nat.c | 2 +- runtime/sys.c | 9 +++++++-- stdlib/sys.ml.in | 2 ++ stdlib/sys.mli | 9 +++++++++ .../tests/match-side-effects/check_partial.ml | 18 +++++++++--------- 10 files changed, 39 insertions(+), 17 deletions(-) diff --git a/Changes b/Changes index d273f59ce053..c2594c2441ee 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,10 @@ Working version ### Standard library: +- #13???: Add Sys.interpreter containing the full path (if available) to the + currently executing runtime. + (David Allsopp, review by ???) + ### Other libraries: ### Tools: diff --git a/runtime/caml/startup_aux.h b/runtime/caml/startup_aux.h index b371ef09edf5..36ddfbc5ae8d 100644 --- a/runtime/caml/startup_aux.h +++ b/runtime/caml/startup_aux.h @@ -26,6 +26,7 @@ extern void caml_free_locale(void); /* readonly after startup */ struct caml_params { const char_os* exe_name; + const char_os* proc_exe_name; /* for meta.c */ const char* section_table; @@ -63,7 +64,7 @@ extern void caml_parse_ocamlrunparam (void); If [pooling] is 0, [caml_stat_*] functions will not be backed by a pool. */ extern int caml_startup_aux (int pooling); -void caml_init_exe_name(const char_os* exe_name); +void caml_init_exe_name(const char_os *, const char_os *); void caml_init_section_table(const char* section_table, asize_t section_table_size); diff --git a/runtime/caml/sys.h b/runtime/caml/sys.h index 23f5671e988d..ec3e4805f986 100644 --- a/runtime/caml/sys.h +++ b/runtime/caml/sys.h @@ -33,7 +33,7 @@ CAMLnoret CAMLextern void caml_sys_error (value); CAMLnoret CAMLextern void caml_sys_io_error (value); CAMLextern double caml_sys_time_unboxed(value); -CAMLextern void caml_sys_init (char_os * exe_name, char_os ** argv); +CAMLextern void caml_sys_init (char_os *, char_os *, char_os ** argv); CAMLextern void caml_locate_standard_library (const char_os *); CAMLnoret CAMLextern void caml_do_exit (int); diff --git a/runtime/startup_aux.c b/runtime/startup_aux.c index 138f97dac149..f36fbf6bc4df 100644 --- a/runtime/startup_aux.c +++ b/runtime/startup_aux.c @@ -200,8 +200,9 @@ CAMLexport void caml_shutdown(void) shutdown_happened = 1; } -void caml_init_exe_name(const char_os* exe_name) +void caml_init_exe_name(const char_os* proc_exe_name, const char_os* exe_name) { + params.proc_exe_name = proc_exe_name; params.exe_name = exe_name; } diff --git a/runtime/startup_byt.c b/runtime/startup_byt.c index 486b83662b93..aa2a17f4de0d 100644 --- a/runtime/startup_byt.c +++ b/runtime/startup_byt.c @@ -559,7 +559,7 @@ CAMLexport void caml_main(char_os **argv) caml_close_channel(chan); /* this also closes fd */ caml_stat_free(trail.section); /* Initialize system libraries */ - caml_sys_init(exe_name, argv + pos); + caml_sys_init(proc_self_exe, exe_name, argv + pos); /* Load debugging info, if b>=2 */ caml_load_main_debug_info(); /* ensure all globals are in major heap */ @@ -646,7 +646,7 @@ CAMLexport value caml_startup_code_exn( caml_modify_generational_global_root (&caml_global_data, caml_input_value_from_block(data, data_size)); /* Initialize system libraries */ - caml_sys_init(exe_name, argv); + caml_sys_init(exe_name, exe_name, argv); /* Load debugging info, if b>=2 */ caml_load_main_debug_info(); /* ensure all globals are in major heap */ diff --git a/runtime/startup_nat.c b/runtime/startup_nat.c index 61cb97b837e5..3340729568d6 100644 --- a/runtime/startup_nat.c +++ b/runtime/startup_nat.c @@ -122,7 +122,7 @@ value caml_startup_common(char_os **argv, int pooling) exe_name = proc_self_exe; else exe_name = caml_search_exe_in_path(exe_name); - caml_sys_init(exe_name, argv); + caml_sys_init(proc_self_exe, exe_name, argv); caml_maybe_expand_stack(); res = caml_start_program(Caml_state); caml_terminate_signals(); diff --git a/runtime/sys.c b/runtime/sys.c index d105d5357a2f..4a1abd610739 100644 --- a/runtime/sys.c +++ b/runtime/sys.c @@ -481,7 +481,12 @@ CAMLprim value caml_sys_executable_name(value unit) return caml_copy_string_of_os(caml_params->exe_name); } -void caml_sys_init(char_os * exe_name, char_os **argv) +CAMLprim value caml_sys_interpreter_name(value unit) +{ + return caml_copy_string_of_os(caml_params->proc_exe_name); +} + +void caml_sys_init(char_os * proc_exe_name, char_os * exe_name, char_os **argv) { #ifdef _WIN32 /* Initialises the caml_win32_* globals on Windows with the version of @@ -491,7 +496,7 @@ void caml_sys_init(char_os * exe_name, char_os **argv) caml_setup_win32_terminal(); #endif #endif - caml_init_exe_name(exe_name); + caml_init_exe_name((proc_exe_name ? proc_exe_name : exe_name), exe_name); main_argv = caml_alloc_array((void *)caml_copy_string_of_os, (char const **) argv); caml_register_generational_global_root(&main_argv); diff --git a/stdlib/sys.ml.in b/stdlib/sys.ml.in index 842ea845005f..37c7604d5692 100644 --- a/stdlib/sys.ml.in +++ b/stdlib/sys.ml.in @@ -23,6 +23,7 @@ type backend_type = external get_config: unit -> string * int * bool = "caml_sys_get_config" external get_executable_name : unit -> string = "caml_sys_executable_name" +external get_interpreter_name : unit -> string = "caml_sys_interpreter_name" external argv : string array = "%sys_argv" external big_endian : unit -> bool = "%big_endian" external word_size : unit -> int = "%word_size" @@ -34,6 +35,7 @@ external cygwin : unit -> bool = "%ostype_cygwin" external get_backend_type : unit -> backend_type = "%backend_type" let executable_name = get_executable_name() +let interpreter = get_interpreter_name() let (os_type, _, _) = get_config() let backend_type = get_backend_type () let big_endian = big_endian () diff --git a/stdlib/sys.mli b/stdlib/sys.mli index dfdb3155cd6f..d0e2a4f81101 100644 --- a/stdlib/sys.mli +++ b/stdlib/sys.mli @@ -32,6 +32,15 @@ val executable_name : string on the platform and whether the program was compiled to bytecode or a native executable. *) +val interpreter : string +(** The name of the file containing the interpreter currently running. For + native code, this is just {!executable_name}. This name may be absolute or + relative to the current directory, depending on the platform (Linux, Windows + and macOS should all return absolute paths). + + @since 5.3 +*) + external file_exists : string -> bool = "caml_sys_file_exists" (** Test if a file with the given name exists. *) diff --git a/testsuite/tests/match-side-effects/check_partial.ml b/testsuite/tests/match-side-effects/check_partial.ml index ef3519caa47d..7d8583fb9fc3 100644 --- a/testsuite/tests/match-side-effects/check_partial.ml +++ b/testsuite/tests/match-side-effects/check_partial.ml @@ -89,10 +89,10 @@ let guard_total : bool t ref -> int = function [%%expect {| (let (guard_total/306 = - (function param/383 : int + (function param/384 : int (if (opaque 0) 1 - (let (*match*/384 =o (field_mut 0 param/383)) - (if (isint *match*/384) (if *match*/384 12 0) + (let (*match*/385 =o (field_mut 0 param/384)) + (if (isint *match*/385) (if *match*/385 12 0) (raise (makeblock 0 (global Match_failure/20!) [0: "" 1 38]))))))) (apply (field_mut 1 (global Toploop!)) "guard_total" guard_total/306)) val guard_total : bool t ref -> int = @@ -106,15 +106,15 @@ let guard_needs_partial : bool t ref -> int = function necessary for soundness. *) [%%expect {| (let - (guard_needs_partial/385 = - (function param/387 : int - (let (*match*/388 =o (field_mut 0 param/387)) - (catch (if (isint *match*/388) (if *match*/388 (exit 9) 0) (exit 9)) + (guard_needs_partial/386 = + (function param/388 : int + (let (*match*/389 =o (field_mut 0 param/388)) + (catch (if (isint *match*/389) (if *match*/389 (exit 9) 0) (exit 9)) with (9) (if (opaque 0) 1 - (if (isint *match*/388) 12 + (if (isint *match*/389) 12 (raise (makeblock 0 (global Match_failure/20!) [0: "" 1 46])))))))) (apply (field_mut 1 (global Toploop!)) "guard_needs_partial" - guard_needs_partial/385)) + guard_needs_partial/386)) val guard_needs_partial : bool t ref -> int = |}];;