Skip to content

Commit f3a4212

Browse files
authored
Back to wide strings on Windows + magic encantations (#22)
The main fix here is the switch to `wmain` from `main` on Windows. The difference is that we're now passed parameters encoded as Unicode wide strings, which makes them actually keep the correct characters as specified on the application's command line by the caller. Also, in order to properly output wide strings to output streams, applications need to set the correct mode for the output stream's file handle (see `platform_setup`)
1 parent c1bf985 commit f3a4212

File tree

12 files changed

+116
-52
lines changed

12 files changed

+116
-52
lines changed

prepare-release.sh

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ MY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
66
source common.sh
77

88
WORK_DIR="${MY_DIR}/prep"
9-
ARTIFACT_TARBALL="${DIST_PACKAGE_NAME_BASE}.tar.bz2"
10-
ARTIFACTS_DIR="${WORK_DIR}/artifacts"
9+
ARTIFACTS_DIR="${WORK_DIR}"
1110

1211
ARTIFACT_ZIP="${1}"
1312
XA_TAG_COMPONENT="${2}"
@@ -38,12 +37,6 @@ function prepare()
3837
echo Unpacking artifact ZIP
3938
unzip "${ARTIFACT_ZIP}"
4039

41-
if [ ! -f "${ARTIFACT_TARBALL}" ]; then
42-
die Build artifact tarball $(pwd)/${ARTIFACT_TARBALL} not found
43-
fi
44-
45-
echo Unpacking binaries tarball
46-
tar xf "${ARTIFACT_TARBALL}"
4740
if [ ! -d "${ARTIFACTS_DIR}" ]; then
4841
die Artifacts directory ${ARTIFACTS_DIR} does not exist
4942
fi

src/gas/command_line.cc

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <vector>
66

77
#include "command_line.hh"
8-
#include "exceptions.hh"
98
#include "platform.hh"
109

1110
using namespace xamarin::android::gas;
@@ -34,7 +33,8 @@ bool CommandLine::parse (std::span<const CommandLineOption> options, std::vector
3433
if (last_opt.has_value ()) {
3534
option_cb (last_opt.value (), option);
3635
} else {
37-
throw invalid_argument_error { "Option '" + option + "' requires an argument." };
36+
STDERR << "Option '" << option << "' requires an argument.";
37+
return false;
3838
}
3939

4040
next_arg_is_value = false;
@@ -83,7 +83,7 @@ bool CommandLine::parse (std::span<const CommandLineOption> options, std::vector
8383
auto match = std::find_if (options.begin (), options.end (), matching_option);
8484
#endif
8585
if (match == options.end ()) {
86-
STDERR << "Uncrecognized option '" << option << "'\n";
86+
STDERR << "Unrecognized option '" << option << Constants::newline;
8787
continue;
8888
}
8989

@@ -98,11 +98,8 @@ bool CommandLine::parse (std::span<const CommandLineOption> options, std::vector
9898
}
9999

100100
if (last_opt.has_value ()) {
101-
platform::string message { "Option '" };
102-
message
103-
.append (last_opt.value ().name)
104-
.append ("' requires an argument.");
105-
throw invalid_operation_error {message};
101+
STDERR << "Option '" << last_opt.value().name << "' requires an argument." << std::endl;
102+
return false;
106103
}
107104

108105
return true;

src/gas/command_line.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ namespace xamarin::android::gas
113113

114114
#define CLISTR(_str_lit_) PSTR((_str_lit_))
115115

116-
#if !defined (_WIN32)
117-
#define CLIPARAM(_str_lit_) std::string_view { _str_lit_ }
116+
#if defined (_WIN32)
117+
#define CLIPARAM(_str_lit_) std::wstring_view { L ## _str_lit_ }
118118
#else
119119
#define CLIPARAM(_str_lit_) std::string_view { _str_lit_ }
120120
#endif

src/gas/gas.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ int Gas::usage (bool is_error, platform::string const message)
5858
return is_error ? 1 : 0;
5959
}
6060

61-
std::vector<platform::string> Gas::get_command_line (int &argc, char **&argv)
61+
std::vector<platform::string> Gas::get_command_line (int argc, argv_char **argv)
6262
{
6363
std::vector<platform::string> ret;
6464

@@ -173,11 +173,11 @@ int Gas::run (std::vector<platform::string> args)
173173
ld_path /= ld_name;
174174
auto ld = std::make_unique<Process> (ld_path);
175175
ld->append_program_argument (PSTR("-o"));
176-
ld->append_program_argument (_gas_output_file.empty () ? platform::string (Constants::default_output_name) : _gas_output_file.string ());
176+
ld->append_program_argument (_gas_output_file.empty () ? platform::string (Constants::default_output_name) : _gas_output_file.native ());
177177
ld->append_program_argument (PSTR("--relocatable"));
178178

179179
for (fs::path const& output : output_files) {
180-
ld->append_program_argument (output.string ());
180+
ld->append_program_argument (output.native ());
181181
}
182182

183183
return ld->run ();

src/gas/gas.hh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ namespace xamarin::android::gas
108108
~Gas ()
109109
{}
110110

111-
std::vector<platform::string> get_command_line (int &argc, char **&argv);
111+
void dump_command_line_args (int argc, argv_char **argv);
112+
static void platform_setup ();
113+
std::vector<platform::string> get_command_line (int argc, argv_char **argv);
112114

113115
int run (std::vector<platform::string> args);
114116

src/gas/gas.posix.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010

1111
using namespace xamarin::android::gas;
1212

13+
void Gas::dump_command_line_args ([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
14+
{}
15+
16+
void Gas::platform_setup()
17+
{}
18+
1319
void Gas::determine_program_dir (std::vector<platform::string> args)
1420
{
1521
fs::path program_path { args[0] };

src/gas/gas.windows.cc

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,79 @@
22
#include <windows.h>
33
#include <shlwapi.h>
44

5+
#include <cstdio>
6+
#include <clocale>
57
#include <cstring>
68
#include <iostream>
79
#include <vector>
10+
#include <io.h>
11+
#include <fcntl.h>
812

913
#include "exceptions.hh"
1014
#include "gas.hh"
1115
#include "platform.hh"
1216

1317
using namespace xamarin::android::gas;
1418

19+
namespace {
20+
void log_cp_info(std::wstring label, UINT cp)
21+
{
22+
std::wcout << L" " << label << L" code page:" << std::endl;
23+
std::wcout << L" ID: " << cp << std::endl;
24+
25+
CPINFOEX cpinfo;
26+
BOOL result = GetCPInfoEx(cp, 0, &cpinfo);
27+
if (!result) {
28+
std::wcout << L" failed to obtain more information about the code page" << std::endl;
29+
return;
30+
}
31+
32+
std::wcout
33+
<< L" Maximum character size: " << cpinfo.MaxCharSize << std::endl
34+
<< L" Localized name: " << cpinfo.CodePageName << std::endl;
35+
}
36+
37+
void log_cli_arg(int index, const wchar_t* arg)
38+
{
39+
std::wcout << L" [" << index << L"] " << std::endl;
40+
std::wcout << std::endl;
41+
std::wstring ws(arg);
42+
std::wcout << L" As C string (direct): " << ws << std::endl;
43+
std::wcout << L" As hex bytes: " << std::hex << std::setw(4) << std::setfill(L'0');
44+
45+
const wchar_t* p = arg;
46+
while (p != nullptr && *p != 0) {
47+
auto ch = static_cast<uint16_t>(*p);
48+
std::wcout << ch << " ";
49+
p++;
50+
}
51+
std::wcout << std::endl;
52+
}
53+
}
54+
55+
void Gas::dump_command_line_args (int argc, wchar_t **argv)
56+
{
57+
std::wcout << L"Active code pages information" << std::endl;
58+
log_cp_info(L"OS", GetACP());
59+
std::wcout << std::endl;
60+
log_cp_info(L"OEM", GetOEMCP());
61+
std::wcout << std::endl;
62+
63+
std::wcout << L"Command line arguments (" << argc << "):" << std::endl;
64+
for (int i = 0; i < argc; i++) {
65+
log_cli_arg(i, argv[i]);
66+
}
67+
std::wcout << L"================================" << std::endl << std::endl;
68+
}
69+
70+
void Gas::platform_setup()
71+
{
72+
// Windows needs that magic to make stdout work with wchar_t and friends
73+
constexpr char cp_utf16le[] = ".1200"; // UTF-16 little-endian locale.
74+
setlocale(LC_ALL, cp_utf16le);
75+
_setmode(_fileno(stdout), _O_WTEXT);
76+
}
77+
1578
void Gas::determine_program_dir (std::vector<platform::string> args)
1679
{
1780
TCHAR buffer[MAX_PATH + 1]{};

src/gas/llvm_mc_runner.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ std::unordered_map<LlvmMcArgument, bool> LlvmMcRunner::known_options {
2626
int LlvmMcRunner::run (fs::path const& executable_path)
2727
{
2828
if (!fs::exists (executable_path)) {
29-
STDERR << "Executable '" << executable_path.string () << "' does not exist." << Constants::newline;
29+
STDERR << "Executable '" << executable_path.native () << "' does not exist." << Constants::newline;
3030
return Constants::wrapper_exec_failed_error_code;
3131
}
3232

@@ -59,8 +59,8 @@ int LlvmMcRunner::run (fs::path const& executable_path)
5959
process->append_program_argument (PSTR("-o"), opt->second);
6060
}
6161

62-
platform::string input_file { PSTR("\"") + input_file_path.make_preferred ().string () + PSTR("\"") };
63-
process->append_program_argument (input_file_path.make_preferred ().string ());
62+
platform::string input_file { PSTR("\"") + input_file_path.make_preferred ().native () + PSTR("\"") };
63+
process->append_program_argument (input_file_path.make_preferred ().native ());
6464

6565
return process->run ();
6666
}

src/gas/llvm_mc_runner.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ namespace xamarin::android::gas
6868

6969
void set_output_file_path (fs::path const& file_path)
7070
{
71-
set_option (LlvmMcArgument::Output, file_path.string ());
71+
set_option (LlvmMcArgument::Output, file_path.native ());
7272
}
7373

7474
void add_include_path (fs::path const& include_path)
@@ -77,7 +77,7 @@ namespace xamarin::android::gas
7777
return;
7878
}
7979

80-
set_option (LlvmMcArgument::IncludeDir, include_path.string ());
80+
set_option (LlvmMcArgument::IncludeDir, include_path.native ());
8181
}
8282

8383
void generate_debug_info ()

src/gas/main.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
// SPDX-License-Identifier: MIT
2-
#include <iostream>
32
#include <vector>
43

54
#include "gas.hh"
65
#include "platform.hh"
76

7+
#if defined(_WIN32)
8+
int wmain (int argc, wchar_t **argv)
9+
#else
810
int main (int argc, char **argv)
11+
#endif
912
{
13+
xamarin::android::gas::Gas::platform_setup ();
1014
xamarin::android::gas::Gas app;
1115

1216
std::vector<platform::string> args = app.get_command_line (argc, argv);

0 commit comments

Comments
 (0)