47#define WIN32_LEAN_AND_MEAN
55#define INC_PREFIX "Note: including file:"
57static const char *
obj;
58static const char *
src;
68static void die(
const char *msg)
70 fprintf(stderr,
"mscl: %s\n", msg);
76 ptr = realloc(ptr,
size);
84 size_t size = strlen(
s) + 1;
93static wchar_t *mb_to_wide(
const char *
s, UINT cp)
95 int n = MultiByteToWideChar(cp, 0,
s, -1,
NULL, 0);
100 MultiByteToWideChar(cp, 0,
s, -1,
w, n);
104static char *wide_to_mb(
const wchar_t *
w, UINT cp)
106 int n = WideCharToMultiByte(cp, 0,
w, -1,
NULL, 0,
NULL,
NULL);
111 WideCharToMultiByte(cp, 0,
w, -1,
s, n,
NULL,
NULL);
115static char *recode(
const char *
s, UINT
from, UINT
to)
117 wchar_t *
w = mb_to_wide(
s,
from);
118 char *
out = wide_to_mb(
w,
to);
123static FILE *
open_wb(
const char *path)
125 wchar_t *
w = mb_to_wide(path, CP_UTF8);
126 FILE *
f = _wfopen(
w,
L"wb");
133 wchar_t *
w = mb_to_wide(path, CP_UTF8);
134 int ret = _wremove(
w);
141 wchar_t *wfrom = mb_to_wide(
from, CP_UTF8), *wto = mb_to_wide(
to, CP_UTF8);
142 int ret = !MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING);
152 return fopen(path,
"wb");
169 for (
const char *q = p; *q; q++)
170 if (*q ==
'/' || *q ==
'\\')
177 static const char *
const exts[] = {
178 ".c",
".cc",
".cpp",
".cxx",
".m",
".mm",
".s",
".S",
".asm"
184 if (!strcmp(dot, exts[
i]))
192 return tolower(
a) == tolower(
b);
206 if (path[
i] !=
'/' || !path[
i + 1])
214 if (!strcmp(
deps[
i], path)) {
235 if (p[0] ==
'/' && p[1] ==
'/') {
236 for (
i = 2; p[
i] && p[
i] !=
'/';
i++)
239 for (
i++; p[
i] && p[
i] !=
'/';
i++)
241 }
else if (isalpha(p[0]) && p[1] ==
':') {
255 char *args[] = { (
char *)prog,
"-u", (
char *)
root,
NULL };
267 dup2(fds[1], STDOUT_FILENO);
277 if (n < 0 && errno == EINTR)
281 if (
len + n <
sizeof(buf)) {
282 memcpy(buf +
len,
tmp, n);
287 if (waitpid(pid, &st, 0) < 0)
288 die(
"waitpid failed");
289 if (!WIFEXITED(st) || WEXITSTATUS(st) || !
len)
292 len = strcspn(buf,
"\r\n");
293 while (
len && buf[
len - 1] ==
'/')
309 for (
char *q =
root; *q; q++)
334 strcat(
out, path +
r);
342 char *own =
NULL, *rel;
345 p = own = recode(p, out_cp, CP_UTF8);
348 for (
char *q = p; *q; q++)
392static void feed(
const char *buf,
size_t n)
394 for (
size_t i = 0;
i < n;
i++) {
395 if (buf[
i] ==
'\n') {
423 DWORD
size = GetCurrentDirectoryW(0,
NULL);
425 if (!GetCurrentDirectoryW(
size, wcwd))
426 die(
"GetCurrentDirectory failed");
427 cwd = wide_to_mb(wcwd, CP_UTF8);
432 die(
"getcwd failed");
434 for (
char *q =
cwd; *q; q++)
448static wchar_t *cmdline_tail(
void)
450 wchar_t *
p = GetCommandLineW();
453 while (*p && *p !=
L'"')
458 while (*p && *p !=
L' ' && *p !=
L'\t')
461 while (*p ==
L' ' || *p ==
L'\t')
468static char **split_cmdline(
const wchar_t *p,
int *argc)
470 wchar_t *buf =
xrealloc(
NULL, (wcslen(p) + 1) *
sizeof(*buf));
478 while (*p ==
L' ' || *p ==
L'\t')
484 while (*p ==
L'\\') {
489 for (
size_t i = 0;
i < bs / 2;
i++)
493 }
else if (quoted && p[1] ==
L'"') {
502 for (
size_t i = 0;
i < bs;
i++)
504 if (!*p || (!quoted && (*p ==
L' ' || *p ==
L'\t')))
509 argv =
xrealloc(argv, (n + 2) *
sizeof(*argv));
510 argv[n++] = wide_to_mb(buf, CP_UTF8);
519static int run(
wchar_t *cmdline,
int want_pipe)
522 SECURITY_ATTRIBUTES sa = {
sizeof(sa),
NULL, TRUE };
523 STARTUPINFOW si = { .cb =
sizeof(si) };
524 PROCESS_INFORMATION pi;
527 si.dwFlags = STARTF_USESTDHANDLES;
528 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
529 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
530 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
531 SetHandleInformation(si.hStdInput, HANDLE_FLAG_INHERIT, 1);
532 SetHandleInformation(si.hStdOutput, HANDLE_FLAG_INHERIT, 1);
533 SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, 1);
536 if (!CreatePipe(&rd, &wr, &sa, 0))
537 die(
"CreatePipe failed");
538 SetHandleInformation(rd, HANDLE_FLAG_INHERIT, 0);
541 SetEnvironmentVariableA(
"VSLANG",
"1033");
546 die(
"cannot execute compiler");
547 CloseHandle(pi.hThread);
553 while (ReadFile(rd, buf,
sizeof(buf), &n,
NULL) && n > 0)
560 GetExitCodeProcess(pi.hProcess, &
code);
561 CloseHandle(pi.hProcess);
567static int run(
char **args)
575 setenv(
"VSLANG",
"1033", 1);
578 wslenv = getenv(
"WSLENV");
579 if (wslenv && *wslenv) {
580 char *e =
xrealloc(
NULL, strlen(wslenv) +
sizeof(
":VSLANG"));
582 strcat(e,
":VSLANG");
583 setenv(
"WSLENV", e, 1);
586 setenv(
"WSLENV",
"VSLANG", 1);
592 dup2(fds[1], STDOUT_FILENO);
595 execvp(args[0], args);
602 ssize_t n =
read(fds[0], buf,
sizeof(buf));
603 if (n < 0 && errno == EINTR)
612 if (waitpid(pid, &st, 0) < 0)
613 die(
"waitpid failed");
614 return WIFEXITED(st) ? WEXITSTATUS(st) : 128 + WTERMSIG(st);
623 if (*
s ==
' ' || *
s ==
'#')
639 memcpy(path,
obj,
len + 1);
640 if (
len > 2 && !strcmp(path +
len - 2,
".o"))
642 strcpy(path +
len,
".d");
645 fprintf(stderr,
"mscl: cannot map %s to a host path, "
646 "wslpath or cygpath is required\n",
unmapped);
651 memcpy(
tmp, path,
len + 2);
652 strcpy(
tmp +
len + 2,
".tmp");
674 fprintf(stderr,
"mscl: cannot write %s\n", path);
680 int show_includes = 0;
684 argv = split_cmdline(GetCommandLineW(), &argc);
685 out_cp = GetConsoleOutputCP();
691 fprintf(stderr,
"usage: mscl <compiler> <arguments...>\n");
695 for (
int i = 2;
i < argc;
i++) {
696 const char *
arg = argv[
i];
697 if (!strcmp(
arg,
"-showIncludes") || !strcmp(
arg,
"/showIncludes"))
699 else if (!strncmp(
arg,
"-Fo", 3) || !strncmp(
arg,
"/Fo", 3))
706 src = recode(
src, CP_UTF8, out_cp);
715 wchar_t *cmdline = cmdline_tail();
717 return run(cmdline, 0);
719 status =
run(cmdline, 1);
721 if (!show_includes) {
722 execvp(argv[1], argv + 1);
727 status =
run(argv + 1);
static av_cold void close(AVCodecParserContext *s)
static uint32_t BS_FUNC read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
#define i(width, name, range_min, range_max)
Utility Preprocessor macros.
static void feed(const char *buf, size_t n)
static const char * file_basename(const char *p)
static void fput_escaped(const char *s, FILE *f)
static int unlink_file(const char *path)
static int replace_file(const char *from, const char *to)
static char * make_relative(const char *path)
static void * xrealloc(void *ptr, size_t size)
static void add_dep(char *path)
static void die(const char *msg)
static struct @247131355217247325142334070304237061366312316121 * roots
static size_t root_len(const char *p)
static int is_source(const char *arg)
static const char * unmapped
static void init_deps(void)
static char * path_helper(const char *prog, const char *root)
static FILE * open_wb(const char *path)
static void feed_flush(void)
static void process_line(char *line)
static void add_include(char *p)
static int write_depfile(void)
static int chr_eq(char a, char b)
static char * host_path(const char *path)
static char * xstrdup(const char *s)
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
#define FF_ARRAY_ELEMS(a)
#define WaitForSingleObject(a, b)