From 5ffb56b494923a8efeb818f432210f88f63b21e0 Mon Sep 17 00:00:00 2001 From: John Soklaski Date: Tue, 1 Aug 2017 23:42:07 -0600 Subject: [PATCH] Support Unicode reading/writing unicode paths on Windows --- setup.py | 2 +- src/ccc.cpp | 35 ++++++++++++++++++++++++++++++++--- src/ccc.h | 2 +- src/compiler.cpp | 9 +++++---- src/module.cpp | 4 ++-- src/pythonlib.cpp | 4 ++-- src/util.h | 16 ++++++++++++++++ 7 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 src/util.h diff --git a/setup.py b/setup.py index 973b826..593dc41 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ extra_link_args = ["-lstdc++fs"] setup(name="ccscript", - version="1.338", + version="1.339", description="ccscript", url="http://starmen.net/pkhack/ccscript", ext_modules=[ diff --git a/src/ccc.cpp b/src/ccc.cpp index 322e4ed..478744f 100644 --- a/src/ccc.cpp +++ b/src/ccc.cpp @@ -5,13 +5,17 @@ #include #include #include +#include +#include #include #include namespace fs = std::experimental::filesystem::v1; +#include "ccc.h" #include "compiler.h" #include "module.h" +#include "util.h" using std::vector; using std::string; @@ -32,7 +36,7 @@ string getbasepath(const char* p) void printversion() { - cout << "ccc version 1.337 Duck Tape Edition" << endl; + cout << "ccc version 1.339 Duck Tape Edition" << endl; } void printusage() @@ -64,9 +68,34 @@ void printusage() << " put the resulting compiled text at $F20000 in the ROM Earthbound.smc" << endl; } -int main(int argc, char* argv[]) +#ifdef _WIN32 +int wmain(int argc, wchar_t* argv[]) { + std::wstring_convert, wchar_t> converter; + // Convert the utf-16 args to utf-8 + std::vector utf8Args; + for(int i = 0; i < argc; ++i) { + auto utf8Arg = converter.to_bytes(argv[i]); + utf8Args.push_back(utf8Arg); + } + + // Expose the std::strings as a vector of const char*s + std::vector utf8Argv; + std::transform(utf8Args.begin(), utf8Args.end(), std::back_inserter(utf8Argv), + [](const std::string& s){ return s.c_str(); } ); + + return run(argc, utf8Argv.data()); +} +#else +int main(int argc, const char* argv[]) +{ + return run(argc, argv); +} +#endif + +int run(int argc, const char* argv[]) +{ // // Get the default libs path // @@ -269,7 +298,7 @@ int main(int argc, char* argv[]) if(!summaryfile.empty()) { std::fstream file; - file.open(summaryfile.c_str(), std::ios_base::out|std::ios_base::trunc); + file.open(ConvertToNativeString(summaryfile), std::ios_base::out|std::ios_base::trunc); if(file.fail()) { std::cerr << "Couldn't open " << summaryfile << " to write summary file." << std::endl; diff --git a/src/ccc.h b/src/ccc.h index 3556e31..7e513e7 100644 --- a/src/ccc.h +++ b/src/ccc.h @@ -1 +1 @@ -int main(int argc, char* argv[]); +int run(int argc, const char* argv[]); \ No newline at end of file diff --git a/src/compiler.cpp b/src/compiler.cpp index 1125c08..df1121d 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -20,6 +20,7 @@ namespace fs = std::experimental::filesystem::v1; #include "module.h" #include "symboltable.h" #include "exception.h" +#include "util.h" using namespace std; @@ -60,7 +61,7 @@ Compiler::Compiler(const string& romfile, unsigned int adr, unsigned int endadr) nostdlibs = false; // Open the file - ifstream file(filename.c_str(), ifstream::binary); + ifstream file(ConvertToNativeString(filename), ifstream::binary); if(file.fail()) { Error("failed to open file " + filename + " for reading."); @@ -130,7 +131,7 @@ Compiler::~Compiler() void Compiler::WriteOutput() { if(failed) return; - ofstream file(filename.c_str(), ofstream::binary); + ofstream file(ConvertToNativeString(filename), ofstream::binary); if(file.fail()) { Error("failed to open file " + filename + " for writing."); @@ -576,7 +577,7 @@ void Compiler::DoDelayedWrites() */ void Compiler::WriteResetInfo(const std::string &filename) { - ofstream file(filename.c_str()); + ofstream file(ConvertToNativeString(filename)); if(file.fail()) throw Exception("couldn't create info file '" + filename + "'"); @@ -621,7 +622,7 @@ void Compiler::WriteResetInfo(const std::string &filename) void Compiler::ApplyResetInfo(const std::string& filename) { - ifstream file(filename.c_str()); + ifstream file(ConvertToNativeString(filename)); if(file.fail()) return; diff --git a/src/module.cpp b/src/module.cpp index 2f62866..eba305b 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -16,6 +16,7 @@ #include "symboltable.h" #include "bytechunk.h" #include "exception.h" +#include "util.h" using namespace std; @@ -68,9 +69,8 @@ void Module::Load(const string& filename) failed = true; return; } - ifstream in(filename.c_str()); - + ifstream in(ConvertToNativeString(filename)); if(in.fail()) { parent->Error("couldn't open " + filename); diff --git a/src/pythonlib.cpp b/src/pythonlib.cpp index 57fd936..1deaf20 100644 --- a/src/pythonlib.cpp +++ b/src/pythonlib.cpp @@ -19,7 +19,7 @@ static PyObject* ccc(PyObject* self, PyObject* args) { return nullptr; } - std::vector argv; + std::vector argv; argv.reserve(argc+1); argv.push_back(CCC_BASENAME); for (int i = 0; i < argc; ++i) { @@ -39,7 +39,7 @@ static PyObject* ccc(PyObject* self, PyObject* args) { std::stringstream buffer; std::streambuf* old_cout = std::cout.rdbuf(buffer.rdbuf()); std::streambuf* old_cerr = std::cerr.rdbuf(buffer.rdbuf()); - int return_value = main(argc + 1, &argv[0]); + int return_value = run(argc + 1, argv.data()); std::cout.rdbuf(old_cout); std::cerr.rdbuf(old_cerr); diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..924051d --- /dev/null +++ b/src/util.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +#ifdef _WIN32 +inline std::wstring ConvertToNativeString(const std::string str) { + std::wstring_convert> converter; + std::wstring wstr = converter.from_bytes(str); + return wstr; +} +#else +inline std::string ConvertToNativeString(const std::string str) { + return str; +} +#endif \ No newline at end of file