mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-16 18:03:36 +00:00
Fix runtime program basename on Windows.
Several places in the runtime make use of the program basename. This is
computed by stripping any directory qualification from the value of argv[0].
Currently, this is done by searching for uses of '/' as a directory separator.
This does not work on Windows where '\' is the directory separator and paths
may also be drive qualified. This diff adds a function that will handle
Windows-style paths.
Also, none of the uses of the program basename in the runtime currently account
for the presence of the .exe executable extension on Windows. After this diff,
users won't have to, and in fact will not be allowed to, include the .exe
extension in the program name in these contexts.
runtime/mercury_runtime_util.[ch]:
Add a function, MR_get_program_basename(), whose job is
to strip any drive or directory qualification, and the executable
extension from a given path. On Windows, we use the OS's splitpath()
function to do this.
Add an XXX about the .exe extension on Cygwin.
runtime/mercury_wrapper.c:
Use the new function when computing:
- the name of the program-specific MERCURY_OPTIONS environment variable;
- the value of the --trace-count-if-exec runtime option;
- the value of the --coverage-test-if-exec runtime option.
doc/user_guide.texi:
Document that the .exe extension is not expected in the three spots above.
This commit is contained in:
@@ -10803,6 +10803,8 @@ The options given in this environment variable apply to every program;
|
||||
the options given in an environment variable
|
||||
whose name is of the form @env{MERCURY_OPTIONS_@var{progname}}
|
||||
apply only to programs named @var{progname}.
|
||||
Note that @var{progname} does @emph{not} include the @file{.exe} extension
|
||||
on those systems (e.g. Windows) that use it.
|
||||
Options may also be set for a particular executable at compile time
|
||||
by passing @samp{--runtime-flags} options
|
||||
to the invocations of @samp{ml} and @samp{c2init} which create that executable.
|
||||
@@ -11253,7 +11255,7 @@ events in the output, even the ones that were not executed.
|
||||
@item --trace-count-if-exec @var{prog}
|
||||
@findex --trace-count-if-exec (runtime option)
|
||||
Act as the @samp{--trace-count} option, but only if the executable is named
|
||||
@var{prog}.
|
||||
@var{prog} (excluding any @file{.exe} extension on Windows).
|
||||
This is to allow the collection of trace count information from only one
|
||||
Mercury program even if several Mercury programs are executed with the same
|
||||
setting of @env{MERCURY_OPTIONS}.
|
||||
@@ -11262,7 +11264,7 @@ setting of @env{MERCURY_OPTIONS}.
|
||||
@item --coverage-test-if-exec @var{prog}
|
||||
@findex --coverage-test-if-exec (runtime option)
|
||||
Act as the @samp{--coverage-test} option, but only if the executable is named
|
||||
@var{prog}.
|
||||
@var{prog} (excluding any @file{.exe} extension on Windows).
|
||||
This is to allow the collection of coverage test information from only one
|
||||
Mercury program even if several Mercury programs are executed with the same
|
||||
setting of @env{MERCURY_OPTIONS}.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// vim: ts=4 sw=4 expandtab ft=c
|
||||
|
||||
// Copyright (C) 2001-2002, 2006 The University of Melbourne.
|
||||
// Copyright (C) 2014, 2016, 2018 The Mercury team.
|
||||
// Copyright (C) 2014, 2016, 2018, 2023 The Mercury team.
|
||||
// This file is distributed under the terms specified in COPYING.LIB.
|
||||
|
||||
// This module contains utility functions for the rest of the Mercury runtime.
|
||||
@@ -10,9 +10,14 @@
|
||||
|
||||
#include "mercury_imp.h"
|
||||
#include "mercury_runtime_util.h"
|
||||
#include "mercury_string.h"
|
||||
#include "mercury_windows.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if defined(MR_WIN32) && !defined(MR_CYGWIN)
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
#ifdef MR_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
@@ -148,3 +153,39 @@ MR_setenv(const char *name, const char *value, int overwrite)
|
||||
#error "MR_setenv: unable to define"
|
||||
#endif
|
||||
}
|
||||
|
||||
// XXX TODO: Cygwin -- strip .exe extension if present.
|
||||
const char *
|
||||
MR_get_program_basename(const char *program_name)
|
||||
{
|
||||
const char *basename;
|
||||
|
||||
#if defined(MR_WIN32) && !defined(MR_CYGWIN)
|
||||
|
||||
wchar_t wname[_MAX_FNAME];
|
||||
|
||||
errno_t err = _wsplitpath_s(MR_utf8_to_wide(program_name),
|
||||
NULL, 0, // Ignore drive.
|
||||
NULL, 0, // Ignore directories.
|
||||
wname, _MAX_FNAME,
|
||||
NULL, 0 // Ignore .exe extension.
|
||||
);
|
||||
if (err != 0) {
|
||||
MR_fatal_error("Could not split path");
|
||||
}
|
||||
basename = MR_wide_to_utf8(wname, NULL);
|
||||
|
||||
#else
|
||||
|
||||
char *slash;
|
||||
|
||||
basename = MR_copy_string(program_name);
|
||||
slash = strrchr(basename, '/');
|
||||
if (slash != NULL) {
|
||||
basename = slash + 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return basename;
|
||||
}
|
||||
|
||||
@@ -27,4 +27,9 @@ extern void MR_checked_atexit(void (*func)(void));
|
||||
extern int MR_setenv(const char *name, const char *value,
|
||||
int overwrite);
|
||||
|
||||
// Strip any directory components from the argument.
|
||||
// On Windows, this will also strip the ".exe" extension.
|
||||
// A ".exe" extension on other systems (e.g. Linux) will be left alone.
|
||||
extern const char *MR_get_program_basename(const char *);
|
||||
|
||||
#endif // MERCURY_RUNTIME_UTIL_H
|
||||
|
||||
@@ -55,6 +55,7 @@ ENDINIT
|
||||
#include "mercury_deep_profiling.h"
|
||||
#include "mercury_memory.h" // for MR_copy_string()
|
||||
#include "mercury_memory_handlers.h" // for MR_default_handler
|
||||
#include "mercury_runtime_util.h" // for MR_get_program_basename()
|
||||
#include "mercury_thread.h" // for MR_debug_threads
|
||||
#include "mercury_threadscope.h"
|
||||
|
||||
@@ -1076,17 +1077,9 @@ MR_process_environment_options(void)
|
||||
gen_env_options = (char *) "";
|
||||
}
|
||||
|
||||
// Find out the program's name, stripping off any directory names.
|
||||
// XXX WINDOWS: the path separator is incorrect for non-Cygwin Windows.
|
||||
// It also does not handle drive qualified paths. And presumably the
|
||||
// name of the program-specific options should not include the .exe
|
||||
// extension.
|
||||
progname = MR_progname;
|
||||
for (s = progname; *s != '\0'; s++) {
|
||||
if (*s == '/') {
|
||||
progname = s + 1;
|
||||
}
|
||||
}
|
||||
// Find out the program's name, stripping off any directory names and the
|
||||
// .exe extension on those systems that use it.
|
||||
progname = MR_get_program_basename(MR_progname);
|
||||
|
||||
// Build the program-specific option's name: MERCURY_OPTIONS_progname.
|
||||
mercury_options_len = strlen(MERCURY_OPTIONS);
|
||||
@@ -1407,6 +1400,7 @@ struct MR_option MR_long_opts[] = {
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
MR_process_options(int argc, char **argv)
|
||||
{
|
||||
@@ -2341,12 +2335,7 @@ MR_matches_exec_name(const char *option)
|
||||
char *s;
|
||||
const char *exec_name;
|
||||
|
||||
s = strrchr(MR_progname, '/');
|
||||
if (s == NULL) {
|
||||
exec_name = MR_progname;
|
||||
} else {
|
||||
exec_name = s + 1;
|
||||
}
|
||||
exec_name = MR_get_program_basename(MR_progname);
|
||||
|
||||
if (MR_streq(option, exec_name)) {
|
||||
return MR_TRUE;
|
||||
|
||||
Reference in New Issue
Block a user