From 3d553eda60e1c5657b195154d2d6623e3c50ba70 Mon Sep 17 00:00:00 2001 From: npwoods Date: Mon, 18 Sep 2017 20:28:53 -0400 Subject: Attempted to sanitize/rationalize how we access UTF-8 command line arguments (#2532) Specifically, this creates a call osd_get_command_line() that returns UTF-8 command line arguments as std::vector. On non-Windows platforms, this does nothing more than build the vector. On Windows, this invokes GetCommandLineW() and CommandLineToArgvW(). This also attempts to unwind usage of wmain()/_tmain() on Windows, which is not standard. Related to this, this fixes a bug in Imgtool; specifically, non-7 bit ASCII was not being handled correctly in Windows. This is really an admission that the way that Windows handles Unicode and command line arguments sucks, and it is my belief that having a wmain() or _tmain() declaration specific for Windows is a worse solution. C'est la vie. I'm very open to the idea that src/osd/osdcore.[cpp|h] is not the best place to do this. Let me know if I should move it. --- scripts/src/main.lua | 5 ----- scripts/src/osd/sdl.lua | 8 ------- scripts/src/osd/sdl_cfg.lua | 1 - scripts/src/osd/windows.lua | 3 --- scripts/src/osd/windows_cfg.lua | 3 +-- src/osd/osdcore.cpp | 48 +++++++++++++++++++++++++++++++++++++++++ src/osd/osdcore.h | 4 ++++ src/osd/sdl/sdlmain.cpp | 8 +------ src/osd/windows/main.cpp | 24 +-------------------- src/osd/windows/winmain.cpp | 6 ++++-- src/tools/imgtool/main.cpp | 6 ++++++ 11 files changed, 65 insertions(+), 51 deletions(-) diff --git a/scripts/src/main.lua b/scripts/src/main.lua index ebad23b0c98..5e189aa3ef1 100644 --- a/scripts/src/main.lua +++ b/scripts/src/main.lua @@ -68,11 +68,6 @@ end } end - configuration { "vs*" } - flags { - "Unicode", - } - configuration { "winstore*" } -- Windows Required Files files { diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua index f310a11360c..be1f27e9319 100644 --- a/scripts/src/osd/sdl.lua +++ b/scripts/src/osd/sdl.lua @@ -94,14 +94,6 @@ function maintargetosdoptions(_target,_subtarget) links { "psapi", } - configuration { "mingw*" } - linkoptions{ - "-municode", - } - configuration { "vs*" } - flags { - "Unicode", - } configuration {} elseif _OPTIONS["targetos"]=="haiku" then links { diff --git a/scripts/src/osd/sdl_cfg.lua b/scripts/src/osd/sdl_cfg.lua index e606e5ad1ea..7e74e43f911 100644 --- a/scripts/src/osd/sdl_cfg.lua +++ b/scripts/src/osd/sdl_cfg.lua @@ -107,7 +107,6 @@ if _OPTIONS["targetos"]=="windows" then defines { "UNICODE", "_UNICODE", - "main=utf8_main", "_WIN32_WINNT=0x0501", "WIN32_LEAN_AND_MEAN", "NOMINMAX", diff --git a/scripts/src/osd/windows.lua b/scripts/src/osd/windows.lua index f0e301e79e1..00432b75a8e 100644 --- a/scripts/src/osd/windows.lua +++ b/scripts/src/osd/windows.lua @@ -16,9 +16,6 @@ function maintargetosdoptions(_target,_subtarget) osdmodulestargetconf() configuration { "mingw*" } - linkoptions { - "-municode", - } links { "mingw32", } diff --git a/scripts/src/osd/windows_cfg.lua b/scripts/src/osd/windows_cfg.lua index 1baa45f4255..73598da6760 100644 --- a/scripts/src/osd/windows_cfg.lua +++ b/scripts/src/osd/windows_cfg.lua @@ -10,8 +10,7 @@ defines { configuration { "mingw* or vs*" } defines { "UNICODE", - "_UNICODE", - "main=utf8_main", + "_UNICODE" } configuration { "vs*" } diff --git a/src/osd/osdcore.cpp b/src/osd/osdcore.cpp index 58bb1157674..4da081e2111 100644 --- a/src/osd/osdcore.cpp +++ b/src/osd/osdcore.cpp @@ -8,6 +8,14 @@ #if defined(SDLMAME_ANDROID) #include #endif + +#ifdef _WIN32 +#include +#include +#include +#include "strconv.h" +#endif + static const int MAXSTACK = 10; static osd_output *m_stack[MAXSTACK]; static int m_ptr = -1; @@ -194,3 +202,43 @@ void osd_sleep(osd_ticks_t duration) { std::this_thread::sleep_for(std::chrono::high_resolution_clock::duration(duration)); } + + +//============================================================ +// osd_get_command_line - returns command line arguments +// in an std::vector in UTF-8 +// +// The real purpose of this call is to hide details necessary +// on Windows (provided that one wants to avoid using wmain) +//============================================================ + +std::vector osd_get_command_line(int argc, char *argv[]) +{ + std::vector results; +#ifdef WIN32 + { + // Get the command line from Windows + int count; + LPWSTR *wide_args = CommandLineToArgvW(GetCommandLineW(), &count); + + // Convert the returned command line arguments to UTF8 std::vector + results.reserve(count); + for (int i = 0; i < count; i++) + { + std::string arg = osd::text::from_wstring(wide_args[i]); + results.push_back(std::move(arg)); + } + + LocalFree(wide_args); + } +#else // !WIN32 + { + // for non Windows platforms, we are assuming that arguments are + // already UTF-8; we just need to convert to std::vector + results.reserve(argc); + for (int i = 0; i < argc; i++) + results.emplace_back(argv[i]); + } +#endif // WIN32 + return results; +} diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h index c22bfd03800..2bfc7cb5950 100644 --- a/src/osd/osdcore.h +++ b/src/osd/osdcore.h @@ -26,6 +26,7 @@ #include #include #include +#include /*************************************************************************** @@ -883,6 +884,9 @@ void CLIB_DECL osd_printf_info(const char *format, ...) ATTR_PRINTF(1,2); void CLIB_DECL osd_printf_verbose(const char *format, ...) ATTR_PRINTF(1,2); void CLIB_DECL osd_printf_debug(const char *format, ...) ATTR_PRINTF(1,2); +// returns command line arguments as an std::vector in UTF-8 +std::vector osd_get_command_line(int argc, char *argv[]); + /* discourage the use of printf directly */ /* sadly, can't do this because of the ATTR_PRINTF under GCC */ /* diff --git a/src/osd/sdl/sdlmain.cpp b/src/osd/sdl/sdlmain.cpp index 3f4b3815359..4fa78bbed38 100644 --- a/src/osd/sdl/sdlmain.cpp +++ b/src/osd/sdl/sdlmain.cpp @@ -183,15 +183,9 @@ sdl_options::sdl_options() extern "C" DECLSPEC void SDLCALL SDL_SetModuleHandle(void *hInst); #endif -// translated to utf8_main -#if defined(SDLMAME_WIN32) -int main(std::vector &args) -{ -#else int main(int argc, char** argv) { - std::vector args(argv, argv+argc); -#endif + std::vector args = osd_get_command_line(argc, argv); int res = 0; // disable I/O buffering diff --git a/src/osd/windows/main.cpp b/src/osd/windows/main.cpp index e87fa24e57c..efe2ad68d72 100644 --- a/src/osd/windows/main.cpp +++ b/src/osd/windows/main.cpp @@ -18,29 +18,7 @@ #include "strconv.h" -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - -extern int utf8_main(std::vector &args); -//============================================================ -// main -//============================================================ - -#ifdef UNICODE -extern "C" int _tmain(int argc, TCHAR **argv) -{ - int i; - std::vector argv_vectors(argc); - - // convert arguments to UTF-8 - for (i = 0; i < argc; i++) - argv_vectors[i] = osd::text::from_tstring(argv[i]); - - // run utf8_main - return utf8_main(argv_vectors); -} -#endif - -#else +#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #include "winmain.h" diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp index 805a769d1b8..b1702f7fac3 100644 --- a/src/osd/windows/winmain.cpp +++ b/src/osd/windows/winmain.cpp @@ -273,11 +273,13 @@ const options_entry windows_options::s_option_entries[] = #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) //============================================================ -// utf8_main +// main //============================================================ -int main(std::vector &args) +int main(int argc, char *argv[]) { + std::vector args = osd_get_command_line(argc, argv); + // use small output buffers on non-TTYs (i.e. pipes) if (!isatty(fileno(stdout))) setvbuf(stdout, (char *) nullptr, _IOFBF, 64); diff --git a/src/tools/imgtool/main.cpp b/src/tools/imgtool/main.cpp index 9559b687c9d..516c4f49e4e 100644 --- a/src/tools/imgtool/main.cpp +++ b/src/tools/imgtool/main.cpp @@ -864,6 +864,12 @@ int main(int argc, char *argv[]) return -1; #endif // MAME_DEBUG + // convert arguments to UTF-8 + std::vector args = osd_get_command_line(argc, argv); + argv = (char **)alloca(sizeof(char *) * args.size()); + for (i = 0; i < args.size(); i++) + argv[i] = (char *)args[i].c_str(); + util::stream_format(std::wcout, L"\n"); if (argc > 1) -- cgit v1.2.3-70-g09d2