From 654ec26168ba5e6a5a177d0b581c12d18bdd53c8 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Mon, 27 Mar 2023 16:02:41 -0700 Subject: [PATCH] tex tool updates for some POSIX like support (#333) --- Texassemble/Texassemble_Desktop_2019.vcxproj | 6 + Texassemble/Texassemble_Desktop_2022.vcxproj | 6 + Texassemble/texassemble.cpp | 105 +++++++++++++---- Texconv/Texconv_Desktop_2019.vcxproj | 6 + Texconv/Texconv_Desktop_2022.vcxproj | 6 + Texconv/texconv.cpp | 112 ++++++++++++++----- Texdiag/texdiag.cpp | 105 +++++++++++++---- Texdiag/texdiag_Desktop_2019.vcxproj | 6 + Texdiag/texdiag_Desktop_2022.vcxproj | 6 + 9 files changed, 284 insertions(+), 74 deletions(-) diff --git a/Texassemble/Texassemble_Desktop_2019.vcxproj b/Texassemble/Texassemble_Desktop_2019.vcxproj index c2ea6253..c87cfe1e 100644 --- a/Texassemble/Texassemble_Desktop_2019.vcxproj +++ b/Texassemble/Texassemble_Desktop_2019.vcxproj @@ -140,6 +140,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -163,6 +164,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -186,6 +188,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -211,6 +214,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -236,6 +240,7 @@ /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -261,6 +266,7 @@ /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) diff --git a/Texassemble/Texassemble_Desktop_2022.vcxproj b/Texassemble/Texassemble_Desktop_2022.vcxproj index 4d463a0c..a9c47db8 100644 --- a/Texassemble/Texassemble_Desktop_2022.vcxproj +++ b/Texassemble/Texassemble_Desktop_2022.vcxproj @@ -140,6 +140,7 @@ true /Zc:__cplusplus %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -164,6 +165,7 @@ true /Zc:__cplusplus %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -188,6 +190,7 @@ true /Zc:__cplusplus %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -214,6 +217,7 @@ true /Zc:__cplusplus %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -240,6 +244,7 @@ /Zc:__cplusplus %(AdditionalOptions) Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -266,6 +271,7 @@ /Zc:__cplusplus %(AdditionalOptions) Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) diff --git a/Texassemble/texassemble.cpp b/Texassemble/texassemble.cpp index 6b543e94..49dc12a4 100644 --- a/Texassemble/texassemble.cpp +++ b/Texassemble/texassemble.cpp @@ -20,6 +20,10 @@ #define NOHELP #pragma warning(pop) +#if __cplusplus < 201703L +#error Requires C++17 (and /Zc:__cplusplus with MSVC) +#endif + #include #include #include @@ -28,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -521,12 +526,14 @@ namespace } else { + std::filesystem::path path(fname + 1); + auto& npath = path.make_preferred(); if (wcspbrk(fname, L"?*") != nullptr) { std::list removeFiles; - SearchForFiles(&fname[1], removeFiles, false); + SearchForFiles(npath.c_str(), removeFiles, false); - for (auto it : removeFiles) + for (auto& it : removeFiles) { _wcslwr_s(it.szSrc); excludes.insert(it.szSrc); @@ -534,7 +541,7 @@ namespace } else { - std::wstring name = (fname + 1); + std::wstring name = npath.c_str(); std::transform(name.begin(), name.end(), name.begin(), towlower); excludes.insert(name); } @@ -542,12 +549,14 @@ namespace } else if (wcspbrk(fname, L"?*") != nullptr) { - SearchForFiles(fname, flist, false); + std::filesystem::path path(fname); + SearchForFiles(path.make_preferred().c_str(), flist, false); } else { SConversion conv = {}; - wcscpy_s(conv.szSrc, MAX_PATH, fname); + std::filesystem::path path(fname); + wcscpy_s(conv.szSrc, path.make_preferred().c_str()); flist.push_back(conv); } @@ -673,7 +682,7 @@ namespace wprintf(L"\n"); } - void PrintLogo() + void PrintLogo(bool versionOnly) { wchar_t version[32] = {}; @@ -701,12 +710,19 @@ namespace swprintf_s(version, L"%03d (library)", DIRECTX_TEX_VERSION); } - wprintf(L"Microsoft (R) DirectX Texture Assembler [DirectXTex] Version %ls\n", version); - wprintf(L"Copyright (C) Microsoft Corp.\n"); - #ifdef _DEBUG - wprintf(L"*** Debug build ***\n"); - #endif - wprintf(L"\n"); + if (versionOnly) + { + wprintf(L"texassemble version %ls\n", version); + } + else + { + wprintf(L"Microsoft (R) DirectX Texture Assembler [DirectXTex] Version %ls\n", version); + wprintf(L"Copyright (C) Microsoft Corp.\n"); + #ifdef _DEBUG + wprintf(L"*** Debug build ***\n"); + #endif + wprintf(L"\n"); + } } const wchar_t* GetErrorDesc(HRESULT hr) @@ -740,10 +756,10 @@ namespace void PrintUsage() { - PrintLogo(); + PrintLogo(false); static const wchar_t* const s_usage = - L"Usage: texassemble \n" + L"Usage: texassemble [--] \n" L"\n" L" cube create cubemap\n" L" volume create volume map\n" @@ -789,7 +805,9 @@ namespace L" -swizzle Select channels for merge (defaults to rgbB)\n" L"\n" L" (cube, volume, array, cubearray, merge only)\n" - L" -stripmips Use only base image from input dds files\n"; + L" -stripmips Use only base image from input dds files\n" + L"\n" + L" '-- ' is needed if any input filepath starts with the '-' or '/' character\n"; wprintf(L"%ls", s_usage); @@ -1009,6 +1027,20 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) return 0; } + if (('-' == argv[1][0]) && ('-' == argv[1][1])) + { + if (!_wcsicmp(argv[1], L"--version")) + { + PrintLogo(true); + return 0; + } + else if (!_wcsicmp(argv[1], L"--help")) + { + PrintUsage(); + return 0; + } + } + const uint32_t dwCommand = LookupByName(argv[1], g_pCommands); switch (dwCommand) { @@ -1041,12 +1073,38 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) uint32_t dwOptions = 0; std::list conversion; + bool allowOpts = true; for (int iArg = 2; iArg < argc; iArg++) { PWSTR pArg = argv[iArg]; - if (('-' == pArg[0]) || ('/' == pArg[0])) + if (allowOpts + && ('-' == pArg[0]) && ('-' == pArg[1])) + { + if (pArg[2] == 0) + { + // "-- " is the POSIX standard for "end of options" marking to escape the '-' and '/' characters at the start of filepaths. + allowOpts = false; + } + else if (!_wcsicmp(pArg, L"--version")) + { + PrintLogo(true); + return 0; + } + else if (!_wcsicmp(pArg, L"--help")) + { + PrintUsage(); + return 0; + } + else + { + wprintf(L"Unknown option: %ls\n", pArg); + return 1; + } + } + else if (allowOpts + && (('-' == pArg[0]) || ('/' == pArg[0]))) { pArg++; PWSTR pValue; @@ -1156,7 +1214,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) case OPT_OUTPUTFILE: { - wcscpy_s(szOutputFile, MAX_PATH, pValue); + std::filesystem::path path(pValue); + wcscpy_s(szOutputFile, path.make_preferred().c_str()); wchar_t ext[_MAX_EXT] = {}; _wsplitpath_s(szOutputFile, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT); @@ -1207,7 +1266,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) case OPT_FILELIST: { - std::wifstream inFile(pValue); + std::filesystem::path path(pValue); + std::wifstream inFile(path.make_preferred().c_str()); if (!inFile) { wprintf(L"Error opening -flist file %ls\n", pValue); @@ -1284,7 +1344,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) else if (wcspbrk(pArg, L"?*") != nullptr) { const size_t count = conversion.size(); - SearchForFiles(pArg, conversion, (dwOptions & (1 << OPT_RECURSIVE)) != 0); + std::filesystem::path path(pArg); + SearchForFiles(path.make_preferred().c_str(), conversion, (dwOptions & (1 << OPT_RECURSIVE)) != 0); if (conversion.size() <= count) { wprintf(L"No matching files found for %ls\n", pArg); @@ -1294,8 +1355,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) else { SConversion conv = {}; - wcscpy_s(conv.szSrc, MAX_PATH, pArg); - + std::filesystem::path path(pArg); + wcscpy_s(conv.szSrc, path.make_preferred().c_str()); conversion.push_back(conv); } } @@ -1307,7 +1368,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) } if (~dwOptions & (1 << OPT_NOLOGO)) - PrintLogo(); + PrintLogo(false); switch (dwCommand) { diff --git a/Texconv/Texconv_Desktop_2019.vcxproj b/Texconv/Texconv_Desktop_2019.vcxproj index 6063c056..62461a7c 100644 --- a/Texconv/Texconv_Desktop_2019.vcxproj +++ b/Texconv/Texconv_Desktop_2019.vcxproj @@ -141,6 +141,7 @@ true true 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -165,6 +166,7 @@ true true 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -189,6 +191,7 @@ true true 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -215,6 +218,7 @@ true true 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -241,6 +245,7 @@ true Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -267,6 +272,7 @@ true Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) diff --git a/Texconv/Texconv_Desktop_2022.vcxproj b/Texconv/Texconv_Desktop_2022.vcxproj index 0faf9e78..a2c113bf 100644 --- a/Texconv/Texconv_Desktop_2022.vcxproj +++ b/Texconv/Texconv_Desktop_2022.vcxproj @@ -141,6 +141,7 @@ true true 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -166,6 +167,7 @@ true true 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -191,6 +193,7 @@ true true 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -218,6 +221,7 @@ true true 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -245,6 +249,7 @@ true Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -272,6 +277,7 @@ true Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) diff --git a/Texconv/texconv.cpp b/Texconv/texconv.cpp index fc57a202..ec87fcb0 100644 --- a/Texconv/texconv.cpp +++ b/Texconv/texconv.cpp @@ -21,6 +21,10 @@ #include +#if __cplusplus < 201703L +#error Requires C++17 (and /Zc:__cplusplus with MSVC) +#endif + #include #include #include @@ -29,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -602,8 +607,8 @@ namespace { wchar_t subdir[MAX_PATH] = {}; auto subfolder = (folder) - ? (std::wstring(folder) + std::wstring(findData.cFileName) + L"\\") - : (std::wstring(findData.cFileName) + L"\\"); + ? (std::wstring(folder) + std::wstring(findData.cFileName) + std::filesystem::path::preferred_separator) + : (std::wstring(findData.cFileName) + std::filesystem::path::preferred_separator); { wchar_t drive[_MAX_DRIVE] = {}; wchar_t dir[_MAX_DIR] = {}; @@ -647,12 +652,14 @@ namespace } else { + std::filesystem::path path(fname + 1); + auto& npath = path.make_preferred(); if (wcspbrk(fname, L"?*") != nullptr) { std::list removeFiles; - SearchForFiles(&fname[1], removeFiles, false, nullptr); + SearchForFiles(npath.c_str(), removeFiles, false, nullptr); - for (auto it : removeFiles) + for (auto& it : removeFiles) { _wcslwr_s(it.szSrc); excludes.insert(it.szSrc); @@ -660,7 +667,7 @@ namespace } else { - std::wstring name = (fname + 1); + std::wstring name = npath.c_str(); std::transform(name.begin(), name.end(), name.begin(), towlower); excludes.insert(name); } @@ -668,12 +675,14 @@ namespace } else if (wcspbrk(fname, L"?*") != nullptr) { - SearchForFiles(fname, flist, false, nullptr); + std::filesystem::path path(fname); + SearchForFiles(path.make_preferred().c_str(), flist, false, nullptr); } else { SConversion conv = {}; - wcscpy_s(conv.szSrc, MAX_PATH, fname); + std::filesystem::path path(fname); + wcscpy_s(conv.szSrc, path.make_preferred().c_str()); flist.push_back(conv); } @@ -810,7 +819,7 @@ namespace wprintf(L"\n"); } - void PrintLogo() + void PrintLogo(bool versionOnly) { wchar_t version[32] = {}; @@ -838,12 +847,19 @@ namespace swprintf_s(version, L"%03d (library)", DIRECTX_TEX_VERSION); } - wprintf(L"Microsoft (R) DirectX Texture Converter [DirectXTex] Version %ls\n", version); - wprintf(L"Copyright (C) Microsoft Corp.\n"); - #ifdef _DEBUG - wprintf(L"*** Debug build ***\n"); - #endif - wprintf(L"\n"); + if (versionOnly) + { + wprintf(L"texconv version %ls\n", version); + } + else + { + wprintf(L"Microsoft (R) DirectX Texture Converter [DirectXTex] Version %ls\n", version); + wprintf(L"Copyright (C) Microsoft Corp.\n"); + #ifdef _DEBUG + wprintf(L"*** Debug build ***\n"); + #endif + wprintf(L"\n"); + } } _Success_(return) @@ -874,10 +890,10 @@ namespace void PrintUsage() { - PrintLogo(); + PrintLogo(false); static const wchar_t* const s_usage = - L"Usage: texconv \n" + L"Usage: texconv [--] \n" L"\n" L" -r wildcard filename search is recursive\n" L" -r:flatten flatten the directory structure (default)\n" @@ -943,9 +959,9 @@ namespace L" -nologo suppress copyright message\n" L" -timing Display elapsed processing time\n" L"\n" -#ifdef _OPENMP + #ifdef _OPENMP L" -singleproc Do not use multi-threaded compression\n" -#endif + #endif L" -gpu Select GPU for DirectCompute-based codecs (0 is default)\n" L" -nogpu Do not use DirectCompute-based codecs\n" L"\n" @@ -962,7 +978,9 @@ namespace L" -x2bias Enable *2 - 1 conversion cases for unorm/pos-only-float\n" L" -inverty Invert Y (i.e. green) channel values\n" L" -reconstructz Rebuild Z (blue) channel assuming X/Y are normals\n" - L" -swizzle Swizzle image channels using HLSL-style mask\n"; + L" -swizzle Swizzle image channels using HLSL-style mask\n" + L"\n" + L" '-- ' is needed if any input filepath starts with the '-' or '/' character\n"; wprintf(L"%ls", s_usage); @@ -1415,12 +1433,38 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) // Process command line uint64_t dwOptions = 0; std::list conversion; + bool allowOpts = true; for (int iArg = 1; iArg < argc; iArg++) { PWSTR pArg = argv[iArg]; - if (('-' == pArg[0]) || ('/' == pArg[0])) + if (allowOpts + && ('-' == pArg[0]) && ('-' == pArg[1])) + { + if (pArg[2] == 0) + { + // "-- " is the POSIX standard for "end of options" marking to escape the '-' and '/' characters at the start of filepaths. + allowOpts = false; + } + else if (!_wcsicmp(pArg,L"--version")) + { + PrintLogo(true); + return 0; + } + else if (!_wcsicmp(pArg, L"--help")) + { + PrintUsage(); + return 0; + } + else + { + wprintf(L"Unknown option: %ls\n", pArg); + return 1; + } + } + else if (allowOpts + && (('-' == pArg[0]) || ('/' == pArg[0]))) { pArg++; PWSTR pValue; @@ -1579,7 +1623,10 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) break; case OPT_OUTPUTDIR: - wcscpy_s(szOutputDir, MAX_PATH, pValue); + { + std::filesystem::path path(pValue); + wcscpy_s(szOutputDir, path.make_preferred().c_str()); + } break; case OPT_FILETYPE: @@ -1875,7 +1922,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) case OPT_FILELIST: { - std::wifstream inFile(pValue); + std::filesystem::path path(pValue); + std::wifstream inFile(path.make_preferred().c_str()); if (!inFile) { wprintf(L"Error opening -flist file %ls\n", pValue); @@ -1934,7 +1982,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) else if (wcspbrk(pArg, L"?*") != nullptr) { const size_t count = conversion.size(); - SearchForFiles(pArg, conversion, (dwOptions & (uint64_t(1) << OPT_RECURSIVE)) != 0, nullptr); + std::filesystem::path path(pArg); + SearchForFiles(path.make_preferred().c_str(), conversion, (dwOptions & (uint64_t(1) << OPT_RECURSIVE)) != 0, nullptr); if (conversion.size() <= count) { wprintf(L"No matching files found for %ls\n", pArg); @@ -1944,8 +1993,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) else { SConversion conv = {}; - wcscpy_s(conv.szSrc, MAX_PATH, pArg); - + std::filesystem::path path(pArg); + wcscpy_s(conv.szSrc, path.make_preferred().c_str()); conversion.push_back(conv); } } @@ -1957,11 +2006,14 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) } if (~dwOptions & (uint64_t(1) << OPT_NOLOGO)) - PrintLogo(); + PrintLogo(false); // Work out out filename prefix and suffix - if (szOutputDir[0] && (L'\\' != szOutputDir[wcslen(szOutputDir) - 1])) - wcscat_s(szOutputDir, MAX_PATH, L"\\"); + if (szOutputDir[0] && (std::filesystem::path::preferred_separator != szOutputDir[wcslen(szOutputDir) - 1])) + { + wchar_t pSeparator[2] = { std::filesystem::path::preferred_separator, 0 }; + wcscat_s(szOutputDir, MAX_PATH, pSeparator); + } auto fileTypeName = LookupByValue(FileType, g_pSaveFileTypes); @@ -3568,13 +3620,13 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) if (*szPrefix) wcscat_s(szDest, szPrefix); - pchSlash = wcsrchr(pConv->szSrc, L'\\'); + pchSlash = wcsrchr(pConv->szSrc, std::filesystem::path::preferred_separator); if (pchSlash) wcscat_s(szDest, pchSlash + 1); else wcscat_s(szDest, pConv->szSrc); - pchSlash = wcsrchr(szDest, '\\'); + pchSlash = wcsrchr(szDest, std::filesystem::path::preferred_separator); pchDot = wcsrchr(szDest, '.'); if (pchDot > pchSlash) diff --git a/Texdiag/texdiag.cpp b/Texdiag/texdiag.cpp index 0b7f480d..5a4cc1b2 100644 --- a/Texdiag/texdiag.cpp +++ b/Texdiag/texdiag.cpp @@ -20,6 +20,10 @@ #define NOHELP #pragma warning(pop) +#if __cplusplus < 201703L +#error Requires C++17 (and /Zc:__cplusplus with MSVC) +#endif + #include #include #include @@ -28,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -511,12 +516,14 @@ namespace } else { + std::filesystem::path path(fname + 1); + auto& npath = path.make_preferred(); if (wcspbrk(fname, L"?*") != nullptr) { std::list removeFiles; - SearchForFiles(&fname[1], removeFiles, false); + SearchForFiles(npath.c_str(), removeFiles, false); - for (auto it : removeFiles) + for (auto& it : removeFiles) { _wcslwr_s(it.szSrc); excludes.insert(it.szSrc); @@ -524,7 +531,7 @@ namespace } else { - std::wstring name = (fname + 1); + std::wstring name = npath.c_str(); std::transform(name.begin(), name.end(), name.begin(), towlower); excludes.insert(name); } @@ -532,12 +539,14 @@ namespace } else if (wcspbrk(fname, L"?*") != nullptr) { - SearchForFiles(fname, flist, false); + std::filesystem::path path(fname); + SearchForFiles(path.make_preferred().c_str(), flist, false); } else { SConversion conv = {}; - wcscpy_s(conv.szSrc, MAX_PATH, fname); + std::filesystem::path path(fname); + wcscpy_s(conv.szSrc, path.make_preferred().c_str()); flist.push_back(conv); } @@ -615,7 +624,7 @@ namespace wprintf(L"\n"); } - void PrintLogo() + void PrintLogo(bool versionOnly) { wchar_t version[32] = {}; @@ -643,20 +652,27 @@ namespace swprintf_s(version, L"%03d (library)", DIRECTX_TEX_VERSION); } - wprintf(L"Microsoft (R) DirectX Texture Diagnostic Tool [DirectXTex] Version %ls\n", version); - wprintf(L"Copyright (C) Microsoft Corp.\n"); - #ifdef _DEBUG - wprintf(L"*** Debug build ***\n"); - #endif - wprintf(L"\n"); + if (versionOnly) + { + wprintf(L"texdiag version %ls\n", version); + } + else + { + wprintf(L"Microsoft (R) DirectX Texture Diagnostic Tool [DirectXTex] Version %ls\n", version); + wprintf(L"Copyright (C) Microsoft Corp.\n"); + #ifdef _DEBUG + wprintf(L"*** Debug build ***\n"); + #endif + wprintf(L"\n"); + } } void PrintUsage() { - PrintLogo(); + PrintLogo(false); static const wchar_t* const s_usage = - L"Usage: texdiag \n" + L"Usage: texdiag [--] \n" L"\n" L" info Output image metadata\n" L" analyze Analyze and summarize image information\n" @@ -690,7 +706,9 @@ namespace L" -ft output file type\n" L"\n" L" -nologo suppress copyright message\n" - L" -flist use text file with a list of input files (one per line)\n"; + L" -flist use text file with a list of input files (one per line)\n" + L"\n" + L" '-- ' is needed if any input filepath starts with the '-' or '/' character\n"; wprintf(L"%ls", s_usage); @@ -3262,6 +3280,20 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) return 0; } + if (('-' == argv[1][0]) && ('-' == argv[1][1])) + { + if (!_wcsicmp(argv[1], L"--version")) + { + PrintLogo(true); + return 0; + } + else if (!_wcsicmp(argv[1], L"--help")) + { + PrintUsage(); + return 0; + } + } + const uint32_t dwCommand = LookupByName(argv[1], g_pCommands); switch (dwCommand) { @@ -3280,12 +3312,38 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) uint32_t dwOptions = 0; std::list conversion; + bool allowOpts = true; for (int iArg = 2; iArg < argc; iArg++) { PWSTR pArg = argv[iArg]; - if (('-' == pArg[0]) || ('/' == pArg[0])) + if (allowOpts + && ('-' == pArg[0]) && ('-' == pArg[1])) + { + if (pArg[2] == 0) + { + // "-- " is the POSIX standard for "end of options" marking to escape the '-' and '/' characters at the start of filepaths. + allowOpts = false; + } + else if (!_wcsicmp(pArg, L"--version")) + { + PrintLogo(true); + return 0; + } + else if (!_wcsicmp(pArg, L"--help")) + { + PrintUsage(); + return 0; + } + else + { + wprintf(L"Unknown option: %ls\n", pArg); + return 1; + } + } + else if (allowOpts + && (('-' == pArg[0]) || ('/' == pArg[0]))) { pArg++; PWSTR pValue; @@ -3374,7 +3432,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) } else { - wcscpy_s(szOutputFile, MAX_PATH, pValue); + std::filesystem::path path(pValue); + wcscpy_s(szOutputFile, path.make_preferred().c_str()); wchar_t ext[_MAX_EXT] = {}; _wsplitpath_s(szOutputFile, nullptr, 0, nullptr, 0, nullptr, 0, ext, _MAX_EXT); @@ -3451,7 +3510,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) case OPT_FILELIST: { - std::wifstream inFile(pValue); + std::filesystem::path path(pValue); + std::wifstream inFile(path.make_preferred().c_str()); if (!inFile) { wprintf(L"Error opening -flist file %ls\n", pValue); @@ -3471,7 +3531,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) else if (wcspbrk(pArg, L"?*") != nullptr) { const size_t count = conversion.size(); - SearchForFiles(pArg, conversion, (dwOptions & (1 << OPT_RECURSIVE)) != 0); + std::filesystem::path path(pArg); + SearchForFiles(path.make_preferred().c_str(), conversion, (dwOptions & (1 << OPT_RECURSIVE)) != 0); if (conversion.size() <= count) { wprintf(L"No matching files found for %ls\n", pArg); @@ -3481,8 +3542,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) else { SConversion conv = {}; - wcscpy_s(conv.szSrc, MAX_PATH, pArg); - + std::filesystem::path path(pArg); + wcscpy_s(conv.szSrc, path.make_preferred().c_str()); conversion.push_back(conv); } } @@ -3494,7 +3555,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[]) } if (~dwOptions & (1 << OPT_NOLOGO)) - PrintLogo(); + PrintLogo(false); switch (dwCommand) { diff --git a/Texdiag/texdiag_Desktop_2019.vcxproj b/Texdiag/texdiag_Desktop_2019.vcxproj index 5bcb5453..c0ec13ad 100644 --- a/Texdiag/texdiag_Desktop_2019.vcxproj +++ b/Texdiag/texdiag_Desktop_2019.vcxproj @@ -140,6 +140,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -163,6 +164,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -186,6 +188,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -211,6 +214,7 @@ true /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -236,6 +240,7 @@ /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -261,6 +266,7 @@ /Zc:__cplusplus /ZH:SHA_256 %(AdditionalOptions) Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) diff --git a/Texdiag/texdiag_Desktop_2022.vcxproj b/Texdiag/texdiag_Desktop_2022.vcxproj index a618e168..49d19ea7 100644 --- a/Texdiag/texdiag_Desktop_2022.vcxproj +++ b/Texdiag/texdiag_Desktop_2022.vcxproj @@ -140,6 +140,7 @@ true /Zc:__cplusplus %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -164,6 +165,7 @@ true /Zc:__cplusplus %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -188,6 +190,7 @@ true /Zc:__cplusplus %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -214,6 +217,7 @@ true /Zc:__cplusplus %(AdditionalOptions) 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -240,6 +244,7 @@ /Zc:__cplusplus %(AdditionalOptions) Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies) @@ -266,6 +271,7 @@ /Zc:__cplusplus %(AdditionalOptions) Guard 26812 + stdcpp17 ole32.lib;windowscodecs.lib;uuid.lib;version.lib;%(AdditionalDependencies)