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);
204 if (p[0] ==
'/' && p[1] ==
'/') {
205 for (
i = 2; p[
i] && p[
i] !=
'/';
i++)
208 for (
i++; p[
i] && p[
i] !=
'/';
i++)
210 }
else if (isalpha(p[0]) && p[1] ==
':') {
225 int pb = !path[
i] || path[
i] ==
'/';
239 for (
i = tail + 1;;
i++) {
246 rest = path + tail + 1;
248 for (
i = 0;
i < updirs;
i++, q += 3)
257 if (!strcmp(
deps[
i], path)) {
280 char *args[] = { (
char *)prog,
"-u", (
char *)
root,
NULL };
292 dup2(fds[1], STDOUT_FILENO);
302 if (n < 0 && errno == EINTR)
306 if (
len + n <
sizeof(buf)) {
307 memcpy(buf +
len,
tmp, n);
312 if (waitpid(pid, &st, 0) < 0)
313 die(
"waitpid failed");
314 if (!WIFEXITED(st) || WEXITSTATUS(st) || !
len)
317 len = strcspn(buf,
"\r\n");
318 while (
len && buf[
len - 1] ==
'/')
334 for (
char *q =
root; *q; q++)
359 strcat(
out, path +
r);
367 char *own =
NULL, *rel;
370 p = own = recode(p, out_cp, CP_UTF8);
373 for (
char *q = p; *q; q++)
417static void feed(
const char *buf,
size_t n)
419 for (
size_t i = 0;
i < n;
i++) {
420 if (buf[
i] ==
'\n') {
448 DWORD
size = GetCurrentDirectoryW(0,
NULL);
450 if (!GetCurrentDirectoryW(
size, wcwd))
451 die(
"GetCurrentDirectory failed");
452 cwd = wide_to_mb(wcwd, CP_UTF8);
457 die(
"getcwd failed");
459 for (
char *q =
cwd; *q; q++)
473static wchar_t *cmdline_tail(
void)
475 wchar_t *
p = GetCommandLineW();
478 while (*p && *p !=
L'"')
483 while (*p && *p !=
L' ' && *p !=
L'\t')
486 while (*p ==
L' ' || *p ==
L'\t')
493static char **split_cmdline(
const wchar_t *p,
int *argc)
495 wchar_t *buf =
xrealloc(
NULL, (wcslen(p) + 1) *
sizeof(*buf));
503 while (*p ==
L' ' || *p ==
L'\t')
509 while (*p ==
L'\\') {
514 for (
size_t i = 0;
i < bs / 2;
i++)
518 }
else if (quoted && p[1] ==
L'"') {
527 for (
size_t i = 0;
i < bs;
i++)
529 if (!*p || (!quoted && (*p ==
L' ' || *p ==
L'\t')))
534 argv =
xrealloc(argv, (n + 2) *
sizeof(*argv));
535 argv[n++] = wide_to_mb(buf, CP_UTF8);
544static int run(
wchar_t *cmdline,
int want_pipe)
547 SECURITY_ATTRIBUTES sa = {
sizeof(sa),
NULL, TRUE };
548 STARTUPINFOW si = { .cb =
sizeof(si) };
549 PROCESS_INFORMATION pi;
552 si.dwFlags = STARTF_USESTDHANDLES;
553 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
554 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
555 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
556 SetHandleInformation(si.hStdInput, HANDLE_FLAG_INHERIT, 1);
557 SetHandleInformation(si.hStdOutput, HANDLE_FLAG_INHERIT, 1);
558 SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, 1);
561 if (!CreatePipe(&rd, &wr, &sa, 0))
562 die(
"CreatePipe failed");
563 SetHandleInformation(rd, HANDLE_FLAG_INHERIT, 0);
566 SetEnvironmentVariableA(
"VSLANG",
"1033");
571 die(
"cannot execute compiler");
572 CloseHandle(pi.hThread);
578 while (ReadFile(rd, buf,
sizeof(buf), &n,
NULL) && n > 0)
585 GetExitCodeProcess(pi.hProcess, &
code);
586 CloseHandle(pi.hProcess);
592static int run(
char **args)
600 setenv(
"VSLANG",
"1033", 1);
603 wslenv = getenv(
"WSLENV");
604 if (wslenv && *wslenv) {
605 char *e =
xrealloc(
NULL, strlen(wslenv) +
sizeof(
":VSLANG"));
607 strcat(e,
":VSLANG");
608 setenv(
"WSLENV", e, 1);
611 setenv(
"WSLENV",
"VSLANG", 1);
617 dup2(fds[1], STDOUT_FILENO);
620 execvp(args[0], args);
627 ssize_t n =
read(fds[0], buf,
sizeof(buf));
628 if (n < 0 && errno == EINTR)
637 if (waitpid(pid, &st, 0) < 0)
638 die(
"waitpid failed");
639 return WIFEXITED(st) ? WEXITSTATUS(st) : 128 + WTERMSIG(st);
648 if (*
s ==
' ' || *
s ==
'#')
664 memcpy(path,
obj,
len + 1);
665 if (
len > 2 && !strcmp(path +
len - 2,
".o"))
667 strcpy(path +
len,
".d");
670 fprintf(stderr,
"mscl: cannot map %s to a host path, "
671 "wslpath or cygpath is required\n",
unmapped);
676 memcpy(
tmp, path,
len + 2);
677 strcpy(
tmp +
len + 2,
".tmp");
699 fprintf(stderr,
"mscl: cannot write %s\n", path);
705 int show_includes = 0;
709 argv = split_cmdline(GetCommandLineW(), &argc);
710 out_cp = GetConsoleOutputCP();
716 fprintf(stderr,
"usage: mscl <compiler> <arguments...>\n");
720 for (
int i = 2;
i < argc;
i++) {
721 const char *
arg = argv[
i];
722 if (!strcmp(
arg,
"-showIncludes") || !strcmp(
arg,
"/showIncludes"))
724 else if (!strncmp(
arg,
"-Fo", 3) || !strncmp(
arg,
"/Fo", 3))
731 src = recode(
src, CP_UTF8, out_cp);
740 wchar_t *cmdline = cmdline_tail();
742 return run(cmdline, 0);
744 status =
run(cmdline, 1);
746 if (!show_includes) {
747 execvp(argv[1], argv + 1);
752 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)
static double cb(void *priv, double x, double y)
#define WaitForSingleObject(a, b)