On Windows the CRT hands main() an argv encoded in the active ANSI code page, so a * non-ASCII CLI argument (e.g. a repo path like café_日本語_repo) is mangled before the * program ever sees it — the documented `cli index_repository " "` then fails with * "repo_path is required" (#423/#20). Rebuild argv from the wide command line * (GetCommandLineW → CommandLineToArgvW) and convert each elem
| 1323 | * the original narrow argv). The returned block lives for the whole process (argv must |
| 1324 | * stay valid until exit), so it is intentionally never freed. */ |
| 1325 | static char **cbm_win_utf8_argv(int *out_argc) { |
| 1326 | int wargc = 0; |
| 1327 | LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &wargc); |
| 1328 | if (!wargv) { |
| 1329 | return NULL; |
| 1330 | } |
| 1331 | if (wargc <= 0) { |
| 1332 | LocalFree(wargv); |
| 1333 | return NULL; |
| 1334 | } |
| 1335 | char **u8argv = (char **)calloc((size_t)wargc + 1, sizeof(char *)); |
| 1336 | if (!u8argv) { |
| 1337 | LocalFree(wargv); |
| 1338 | return NULL; |
| 1339 | } |
| 1340 | for (int i = 0; i < wargc; i++) { |
| 1341 | u8argv[i] = cbm_wide_to_utf8(wargv[i]); |
| 1342 | if (!u8argv[i]) { |
| 1343 | for (int j = 0; j < i; j++) { |
| 1344 | free(u8argv[j]); |
| 1345 | } |
| 1346 | free(u8argv); |
| 1347 | LocalFree(wargv); |
| 1348 | return NULL; |
| 1349 | } |
| 1350 | } |
| 1351 | LocalFree(wargv); |
| 1352 | *out_argc = wargc; |
| 1353 | return u8argv; /* NULL-terminated (calloc'd wargc+1) */ |
| 1354 | } |
| 1355 | #endif /* _WIN32 */ |
| 1356 | |
| 1357 | static bool main_resolve_executable(const char *argv0, char out[MAIN_PATH_CAP]) { |
no test coverage detected