[m-rev.] for review: move some conversion functions into the runtime.

Julien Fischer jfischer at opturion.com
Mon Oct 16 00:51:18 AEDT 2023


For review by anyone.

The upcoming changes referred to below are related the creation of
trace count files and also the program-specific Mercury options on
Windows.

--------------------------------------

Move some conversion functions into the runtime.

Move the functions that convert between the UTF-8 and wide encodings of a
string on Windows from the library into the runtime. Upcoming changes will
require their presence in the runtime.

library/io.m:
     Move ML_utf8_to_wide() and ML_wide_to_utf8() from here ...

runtime/mercury_string.[ch]:
     ... to here and s/ML_/MR_/.

library/dir.m:
library/io.call_system.m:
library/io.environment.m:
library/io.file.m:
library/io.stream_ops.m:
     Conform to the above change.

Julien.

diff --git a/library/dir.m b/library/dir.m
index 05c5c84..ed0f43f 100644
--- a/library/dir.m
+++ b/library/dir.m
@@ -1034,7 +1034,7 @@ current_directory(Result, !IO) :-

      wbuf = _wgetcwd(NULL, 1);
      if (wbuf != NULL) {
-        CurDir = ML_wide_to_utf8(wbuf, MR_ALLOC_ID);
+        CurDir = MR_wide_to_utf8(wbuf, MR_ALLOC_ID);
          Error = 0;
          free(wbuf);
      } else {
@@ -1306,7 +1306,7 @@ make_single_directory(DirName, Result, !IO) :-
          will_not_modify_trail, does_not_affect_liveness, may_not_duplicate],
  "
  #if defined(MR_WIN32)
-    if (CreateDirectoryW(ML_utf8_to_wide(DirName), NULL)) {
+    if (CreateDirectoryW(MR_utf8_to_wide(DirName), NULL)) {
          Status = ML_MAKE_SINGLE_DIRECTORY_OK;
          Error = 0;
      } else {
@@ -1777,7 +1777,7 @@ open_2(DirName, DirPattern, Result, !IO) :-

      DirStream = MR_GC_NEW_ATTRIB(struct ML_DIR_STREAM, MR_ALLOC_ID);

-    DirStream->handle = FindFirstFileW(ML_utf8_to_wide(DirPattern), &file_data);
+    DirStream->handle = FindFirstFileW(MR_utf8_to_wide(DirPattern), &file_data);
      if (DirStream->handle == INVALID_HANDLE_VALUE) {
          Error = GetLastError();
          if (Error == ERROR_NO_MORE_FILES) {
@@ -1786,7 +1786,7 @@ open_2(DirName, DirPattern, Result, !IO) :-
          DirStream->pending_entry = NULL;
      } else {
          Error = 0;
-        DirStream->pending_entry = ML_wide_to_utf8(file_data.cFileName, MR_ALLOC_ID);
+        DirStream->pending_entry = MR_wide_to_utf8(file_data.cFileName, MR_ALLOC_ID);
      }
      IsWin32Error = MR_YES;

@@ -2031,7 +2031,7 @@ read_entry(DirStream, Result, !IO) :-
          Error = 0;
          IsWin32Error = MR_YES;
          HaveFileName = MR_YES;
-        FileName = ML_wide_to_utf8(file_data.cFileName, MR_ALLOC_ID);
+        FileName = MR_wide_to_utf8(file_data.cFileName, MR_ALLOC_ID);
      } else {
          Error = GetLastError();
          IsWin32Error = MR_YES;
diff --git a/library/io.call_system.m b/library/io.call_system.m
index ef23c49..7bd5b96 100644
--- a/library/io.call_system.m
+++ b/library/io.call_system.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1993-2012 The University of Melbourne.
-% Copyright (C) 2013-2022 The Mercury team.
+% Copyright (C) 2013-2023 The Mercury team.
  % This file is distributed under the terms specified in COPYING.LIB.
  %---------------------------------------------------------------------------%
  %
@@ -53,6 +53,14 @@

  %---------------------------------------------------------------------------%

+:- pragma foreign_decl("C", "
+#if defined(MR_WIN32)
+   #include ""mercury_string.h"" // For MR_utf8_to_wide.
+#endif
+").
+
+%---------------------------------------------------------------------------%
+
  call_system(Command, Result, !IO) :-
      io.call_system.call_system_return_signal(Command, Result0, !IO),
      (
@@ -143,7 +151,7 @@ call_system_return_signal(Command, Result, !IO) :-
  #else   // !MR_THREAD_SAFE || !MR_HAVE_POSIX_SPAWN || !MR_HAVE_ENVIRON

    #ifdef MR_WIN32
-    Status = _wsystem(ML_utf8_to_wide(Command));
+    Status = _wsystem(MR_utf8_to_wide(Command));
    #else
      Status = system(Command);
    #endif
diff --git a/library/io.environment.m b/library/io.environment.m
index c16d83c..28354aa 100644
--- a/library/io.environment.m
+++ b/library/io.environment.m
@@ -70,6 +70,14 @@

  %---------------------------------------------------------------------------%

+:- pragma foreign_decl("C", "
+#if defined(MR_WIN32)
+   #include ""mercury_string.h"" // For MR_utf8_to_wide.
+#endif
+").
+
+%---------------------------------------------------------------------------%
+
  get_environment_var(Var, OptValue, !IO) :-
      promise_pure (
          ( if semipure getenv(Var, Value) then
@@ -272,9 +280,9 @@ record_env_var_and_value(EnvVarName, EnvVarValue, !EnvVarAL) :-
          does_not_affect_liveness, no_sharing],
  "
  #ifdef MR_WIN32
-    wchar_t *ValueW = _wgetenv(ML_utf8_to_wide(Var));
+    wchar_t *ValueW = _wgetenv(MR_utf8_to_wide(Var));
      if (ValueW != NULL) {
-        Value = ML_wide_to_utf8(ValueW, MR_ALLOC_ID);
+        Value = MR_wide_to_utf8(ValueW, MR_ALLOC_ID);
      } else {
          Value = NULL;
      }
@@ -315,7 +323,7 @@ record_env_var_and_value(EnvVarName, EnvVarValue, !EnvVarAL) :-
  "
  #ifdef MR_WIN32
      SUCCESS_INDICATOR =
-        (_wputenv_s(ML_utf8_to_wide(Var), ML_utf8_to_wide(Value)) == 0);
+        (_wputenv_s(MR_utf8_to_wide(Var), MR_utf8_to_wide(Value)) == 0);
  #else
      SUCCESS_INDICATOR = (setenv(Var, Value, 1) == 0);
  #endif
diff --git a/library/io.file.m b/library/io.file.m
index 6de7b4c..3bf535c 100644
--- a/library/io.file.m
+++ b/library/io.file.m
@@ -240,7 +240,7 @@ remove_file(FileName, Result, !IO) :-
      int rc;
  #ifdef MR_WIN32
      // XXX _wremove will not delete an empty directory; _wrmdir does that.
-    rc = _wremove(ML_utf8_to_wide(FileName));
+    rc = _wremove(MR_utf8_to_wide(FileName));
  #else
      rc = remove(FileName);
  #endif
@@ -375,8 +375,8 @@ rename_file(OldFileName, NewFileName, Result, !IO) :-
  "
      int rc;
  #ifdef MR_WIN32
-    rc = _wrename(ML_utf8_to_wide(OldFileName),
-        ML_utf8_to_wide(NewFileName));
+    rc = _wrename(MR_utf8_to_wide(OldFileName),
+        MR_utf8_to_wide(NewFileName));
  #else
      rc = rename(OldFileName, NewFileName);
  #endif
@@ -661,7 +661,7 @@ check_file_accessibility(FileName, AccessTypes, Result, !IO) :-
      }

    #ifdef MR_WIN32
-    access_result = _waccess(ML_utf8_to_wide(FileName), mode);
+    access_result = _waccess(MR_utf8_to_wide(FileName), mode);
    #else
      access_result = access(FileName, mode);
    #endif
@@ -848,7 +848,7 @@ file_type(FollowSymLinks, FileName, Result, !IO) :-
  #ifdef MR_HAVE_STAT
    #ifdef MR_WIN32
      struct _stat s;
-    int stat_result = _wstat(ML_utf8_to_wide(FileName), &s);
+    int stat_result = _wstat(MR_utf8_to_wide(FileName), &s);
    #else
      struct stat s;
      int stat_result;
@@ -1064,7 +1064,7 @@ file_modification_time(File, Result, !IO) :-
  #ifdef MR_HAVE_STAT
    #ifdef MR_WIN32
      struct _stat s;
-    int stat_result = _wstat(ML_utf8_to_wide(FileName), &s);
+    int stat_result = _wstat(MR_utf8_to_wide(FileName), &s);
    #else
      struct stat s;
      int stat_result = stat(FileName, &s);
@@ -1215,7 +1215,7 @@ make_temp_file(Dir, Prefix, Suffix, Result, !IO) :-
          flags = O_WRONLY | O_CREAT | O_EXCL;
          do {
              #ifdef MR_WIN32
-                fd = _wopen(ML_utf8_to_wide(FileName), flags, 0600);
+                fd = _wopen(MR_utf8_to_wide(FileName), flags, 0600);
              #else
                  fd = open(FileName, flags, 0600);
              #endif
@@ -1435,6 +1435,9 @@ make_temp_directory(ParentDirName, Prefix, Suffix, Result, !IO) :-
  %---------------------%

  :- pragma foreign_decl("C", "
+#ifdef MR_WIN32
+    #include ""mercury_string.h"" // For MR_ut8_to_wide.
+#endif
  #ifdef MR_HAVE_UNISTD_H
      #include <unistd.h>
  #endif
diff --git a/library/io.m b/library/io.m
index e2c91a5..f921115 100644
--- a/library/io.m
+++ b/library/io.m
@@ -6035,11 +6035,6 @@ extern MR_Word          ML_io_user_globals;

  void                    mercury_init_io(void);

-#ifdef MR_WIN32
-    wchar_t             *ML_utf8_to_wide(const char *s);
-    char                *ML_wide_to_utf8(const wchar_t *ws,
-                            MR_AllocSiteInfoPtr alloc_id);
-#endif
  ").

  :- pragma foreign_code("C", "
@@ -6116,46 +6111,6 @@ mercury_init_io(void)
      pthread_mutex_init(&ML_io_next_stream_id_lock, MR_MUTEX_ATTR);
  #endif
  }
-
-#ifdef MR_WIN32
-
-// Accessing Unicode file names on Windows requires that we use the functions
-// taking wide character strings.
-wchar_t *
-ML_utf8_to_wide(const char *s)
-{
-    int     wslen;
-    wchar_t *ws;
-
-    wslen = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
-    if (wslen == 0) {
-        MR_fatal_error(""ML_utf8_to_wide: MultiByteToWideChar failed"");
-    }
-    ws = MR_GC_NEW_ARRAY(wchar_t, wslen);
-    if (0 == MultiByteToWideChar(CP_UTF8, 0, s, -1, ws, wslen)) {
-        MR_fatal_error(""ML_utf8_to_wide: MultiByteToWideChar failed"");
-    }
-    return ws;
-}
-
-char *
-ML_wide_to_utf8(const wchar_t *ws, MR_AllocSiteInfoPtr alloc_id)
-{
-    char    *s;
-    int     bytes;
-
-    bytes = WideCharToMultiByte(CP_UTF8, 0, ws, -1, NULL, 0, NULL, NULL);
-    if (bytes == 0) {
-        MR_fatal_error(""ML_wide_to_utf8: WideCharToMultiByte failed"");
-    }
-    MR_allocate_aligned_string_msg(s, bytes, alloc_id);
-    if (0 == WideCharToMultiByte(CP_UTF8, 0, ws, -1, s, bytes, NULL, NULL)) {
-        MR_fatal_error(""ML_wide_to_utf8: WideCharToMultiByte failed"");
-    }
-    return s;
-}
-
-#endif // MR_WIN32
  ").

  %---------------------%
diff --git a/library/io.stream_ops.m b/library/io.stream_ops.m
index 07c47d3..f0902eb 100644
--- a/library/io.stream_ops.m
+++ b/library/io.stream_ops.m
@@ -875,6 +875,11 @@ stderr_stream_2(Stream, !IO) :-
  %---------------------------------------------------------------------------%

  :- pragma foreign_decl("C", "
+
+#if defined(MR_WIN32)
+  #include ""mercury_string.h"" // For MR_utf8_to_wide.
+#endif
+
  extern MercuryFile      mercury_stdin;
  extern MercuryFile      mercury_stdout;
  extern MercuryFile      mercury_stderr;
@@ -976,7 +981,7 @@ mercury_open(const char *filename, const char *openmode,
      FILE            *f;

  #ifdef MR_WIN32
-    f = _wfopen(ML_utf8_to_wide(filename), ML_utf8_to_wide(openmode));
+    f = _wfopen(MR_utf8_to_wide(filename), MR_utf8_to_wide(openmode));
  #else
      f = fopen(filename, openmode);
  #endif
diff --git a/runtime/mercury_string.c b/runtime/mercury_string.c
index 7492a69..a5e20a7 100644
--- a/runtime/mercury_string.c
+++ b/runtime/mercury_string.c
@@ -1,13 +1,14 @@
  // vim: ts=4 sw=4 expandtab ft=c

  // Copyright (C) 2000-2002, 2006, 2011-2012 The University of Melbourne.
-// Copyright (C) 2015-2016, 2018-2019 The Mercury team.
+// Copyright (C) 2015-2016, 2018-2019, 2023 The Mercury team.
  // This file is distributed under the terms specified in COPYING.LIB.

  // mercury_string.c - string handling

  #include "mercury_imp.h"
  #include "mercury_string.h"
+#include "mercury_windows.h"

  #ifdef _MSC_VER
      // Disable warnings about using _vsnprintf being deprecated.
@@ -574,3 +575,39 @@ MR_utf8_find_ill_formed_char(const MR_String s)
          }
      }
  }
+
+#if defined(MR_WIN32)
+wchar_t *
+MR_utf8_to_wide(const char *s)
+{
+    int     wslen;
+    wchar_t *ws;
+
+    wslen = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
+    if (wslen == 0) {
+        MR_fatal_error("ML_utf8_to_wide: MultiByteToWideChar failed");
+    }
+    ws = MR_GC_NEW_ARRAY(wchar_t, wslen);
+    if (0 == MultiByteToWideChar(CP_UTF8, 0, s, -1, ws, wslen)) {
+        MR_fatal_error("ML_utf8_to_wide: MultiByteToWideChar failed");
+    }
+    return ws;
+}
+
+char *
+MR_wide_to_utf8(const wchar_t *ws, MR_AllocSiteInfoPtr alloc_id)
+{
+    char    *s;
+    int     bytes;
+
+    bytes = WideCharToMultiByte(CP_UTF8, 0, ws, -1, NULL, 0, NULL, NULL);
+    if (bytes == 0) {
+        MR_fatal_error("ML_wide_to_utf8: WideCharToMultiByte failed");
+    }
+    MR_allocate_aligned_string_msg(s, bytes, alloc_id);
+    if (0 == WideCharToMultiByte(CP_UTF8, 0, ws, -1, s, bytes, NULL, NULL)) {
+        MR_fatal_error("ML_wide_to_utf8: WideCharToMultiByte failed");
+    }
+    return s;
+}
+#endif // MR_WIN32
diff --git a/runtime/mercury_string.h b/runtime/mercury_string.h
index 008cd83..1b28f3a 100644
--- a/runtime/mercury_string.h
+++ b/runtime/mercury_string.h
@@ -1,7 +1,7 @@
  // vim: ts=4 sw=4 expandtab ft=c

  // Copyright (C) 1995-2005, 2007, 2011-2012 The University of Melbourne.
-// Copyright (C) 2015-2016, 2018 The Mercury team.
+// Copyright (C) 2015-2016, 2018-2019, 2021, 2023 The Mercury team.
  // This file is distributed under the terms specified in COPYING.LIB.

  // mercury_string.h - string handling
@@ -14,6 +14,9 @@
  #include <string.h>             // for strcmp() etc.
  #include <stdarg.h>
  #include <stdio.h>
+#if defined(MR_WIN32)
+   #include <wchar.h>
+#endif

  // On Windows, snprintf/vsnprintf may be synonyms for _snprintf/_vsnprintf and
  // thus not conform to the C99 specification. Since it is next to impossible to
@@ -505,4 +508,12 @@ extern MR_bool          MR_utf8_verify(const MR_String s);

  extern MR_Integer       MR_utf8_find_ill_formed_char(const MR_String s);

+// Accessing Unicode file names on Windows requires that we use the functions
+// taking wide character strings. The following functions handle the
+// conversions.
+#if defined(MR_WIN32)
+extern wchar_t          *MR_utf8_to_wide(const char *s);
+extern char             *MR_wide_to_utf8(const wchar_t *ws,
+#endif
+
  #endif // not MERCURY_STRING_H


More information about the reviews mailing list