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
| 1132 | * the original narrow argv). The returned block lives for the whole process (argv must |
| 1133 | * stay valid until exit), so it is intentionally never freed. */ |
| 1134 | static char **cbm_win_utf8_argv(int *out_argc) { |
| 1135 | int wargc = 0; |
| 1136 | LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &wargc); |
| 1137 | if (!wargv) { |
| 1138 | return NULL; |
| 1139 | } |
| 1140 | if (wargc <= 0) { |
| 1141 | LocalFree(wargv); |
| 1142 | return NULL; |
| 1143 | } |
| 1144 | char **u8argv = (char **)calloc((size_t)wargc + 1, sizeof(char *)); |
| 1145 | if (!u8argv) { |
| 1146 | LocalFree(wargv); |
| 1147 | return NULL; |
| 1148 | } |
| 1149 | for (int i = 0; i < wargc; i++) { |
| 1150 | u8argv[i] = cbm_wide_to_utf8(wargv[i]); |
| 1151 | if (!u8argv[i]) { |
| 1152 | for (int j = 0; j < i; j++) { |
| 1153 | free(u8argv[j]); |
| 1154 | } |
| 1155 | free(u8argv); |
| 1156 | LocalFree(wargv); |
| 1157 | return NULL; |
| 1158 | } |
| 1159 | } |
| 1160 | LocalFree(wargv); |
| 1161 | *out_argc = wargc; |
| 1162 | return u8argv; /* NULL-terminated (calloc'd wargc+1) */ |
| 1163 | } |
| 1164 | #endif /* _WIN32 */ |
| 1165 | |
| 1166 | static bool main_resolve_executable(const char *argv0, char out[MAIN_PATH_CAP]) { |
no test coverage detected