return path;
}
+#ifdef _WIN32
+ if (path[0] == '/')
+ path++; /* skip leading slash */
+#endif
+
/* x_realpath only works for existing paths, so if path doesn't exist, try
* dirname(path) and assemble the path afterwards. We only bother to try
* canonicalizing one of these two paths since a compiler path argument
PROCESS_INFORMATION pi;
STARTUPINFO si;
DWORD exitcode;
+ bool cmd = false;
char *sh = NULL;
char *win32args;
char *path;
int pipefd[2];
#endif
+#ifdef _WIN32
+ /* trim leading space */
+ while (isspace(*command))
+ command++;
+ /* add "echo" command */
+ if (str_startswith(command, "echo")) {
+ command = format("cmd.exe /c \"%s\"", command);
+ cmd = true;
+ } else if (str_startswith(command, "%compiler%") && str_eq(compiler, "echo")) {
+ command = format("cmd.exe /c \"%s%s\"", compiler, command + 10);
+ cmd = true;
+ } else {
+ command = x_strdup(command);
+ }
+#endif
struct args *args = args_init_from_string(command);
int i;
for (i = 0; i < args->argc; i++) {
si.hStdError = pipe_out[1];
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.dwFlags = STARTF_USESTDHANDLES;
- win32args = win32argvtos(sh, args->argv);
+ if (!cmd)
+ win32args = win32argvtos(sh, args->argv);
+ else
+ win32args = (char *) command; /* quoted */
ret = CreateProcess(path, win32args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi);
CloseHandle(pipe_out[1]);
args_free(args);
free(win32args);
+ if (cmd)
+ free((char *) command); /* original argument was replaced above */
if (ret == 0) {
stats_update(STATS_COMPCHECK);
return false;
CHECK_STR_EQ("fourth", args->argv[3]);
CHECK_STR_EQ("fif th", args->argv[4]);
CHECK_STR_EQ("si'x\" th", args->argv[5]);
+#ifndef _WIN32
CHECK_STR_EQ("seve\nth", args->argv[6]);
+#else
+ CHECK_STR_EQ("seve\r\nth", args->argv[6]);
+#endif
CHECK(!args->argv[7]);
args_free(args);
}
extern struct conf *conf;
+static char *
+get_root(void)
+{
+#ifndef _WIN32
+ return x_strdup("/");
+#else
+ char volume[4]; /* "C:\" */
+ GetVolumePathName(get_cwd(), volume, sizeof(volume));
+ return x_strdup(volume);
+#endif
+}
+
+static char *
+get_posix_path(char *path)
+{
+#ifndef _WIN32
+ return x_strdup(path);
+#else
+ char *posix;
+ char *p;
+
+ /* / escape volume */
+ if (path[0] >= 'A' && path[0] <= 'Z' && path[1] == ':')
+ posix = format("/%s", path);
+ else
+ posix = x_strdup(path);
+ /* convert slashes */
+ for (p = posix; *p; p++) {
+ if (*p == '\\')
+ *p = '/';
+ }
+ return posix;
+#endif
+}
+
TEST_SUITE(argument_processing)
TEST(dash_E_should_result_in_called_for_preprocessing)
create_file("foo.c", "");
free(conf->base_dir);
- conf->base_dir = x_strdup("/");
+ conf->base_dir = get_root();
current_working_dir = get_cwd();
arg_string = format("cc --sysroot=%s/foo -c foo.c", current_working_dir);
orig = args_init_from_string(arg_string);
create_file("foo.c", "");
free(conf->base_dir);
- conf->base_dir = x_strdup("/");
+ conf->base_dir = get_root();
current_working_dir = get_cwd();
arg_string = format("cc -isystem %s/foo -c foo.c", current_working_dir);
orig = args_init_from_string(arg_string);
TEST(isystem_flag_with_concat_arg_should_be_rewritten_if_basedir_is_used)
{
extern char *current_working_dir;
+ char *cwd;
char *arg_string;
struct args *orig;
struct args *act_cpp = NULL, *act_cc = NULL;
create_file("foo.c", "");
free(conf->base_dir);
- conf->base_dir = x_strdup("/");
+ conf->base_dir = x_strdup("/"); /* posix */
current_working_dir = get_cwd();
- arg_string = format("cc -isystem%s/foo -c foo.c", current_working_dir);
+ /* windows path don't work concatenated */
+ cwd = get_posix_path(current_working_dir);
+ arg_string = format("cc -isystem%s/foo -c foo.c", cwd);
orig = args_init_from_string(arg_string);
free(arg_string);
CHECK_STR_EQ("-isystem", act_cpp->argv[1]);
CHECK_STR_EQ("./foo", act_cpp->argv[2]);
+ free(cwd);
args_free(orig);
args_free(act_cpp);
args_free(act_cc);
CHECK_STR_EQ("rabbit", user);
create_file(
"ccache.conf",
+#ifndef _WIN32
"base_dir = /$USER/foo/${USER} \n"
+#else
+ "base_dir = C:/$USER/foo/${USER}\n"
+#endif
"cache_dir=\n"
"cache_dir = $USER$/${USER}/.ccache\n"
"\n"
CHECK(conf_read(conf, "ccache.conf", &errmsg));
CHECK(!errmsg);
+#ifndef _WIN32
CHECK_STR_EQ_FREE1(format("/%s/foo/%s", user, user), conf->base_dir);
+#else
+ CHECK_STR_EQ_FREE1(format("C:/%s/foo/%s", user, user), conf->base_dir);
+#endif
CHECK_STR_EQ_FREE1(format("%s$/%s/.ccache", user, user), conf->cache_dir);
CHECK_INT_EQ(4, conf->cache_dir_levels);
CHECK_STR_EQ("foo", conf->compiler);
struct mdfour h1, h2;
hash_start(&h1);
hash_start(&h2);
+#ifndef _WIN32
create_file("stderr.sh", "#!/bin/sh\necho foo >&2\n");
chmod("stderr.sh", 0555);
CHECK(hash_command_output(&h1, "echo foo", "not used"));
CHECK(hash_command_output(&h2, "./stderr.sh", "not used"));
+#else
+ create_file("stderr.bat", "@echo off\r\necho foo>&2\r\n");
+ CHECK(hash_command_output(&h1, "echo foo", "not used"));
+ CHECK(hash_command_output(&h2, "stderr.bat", "not used"));
+#endif
CHECK(hash_equal(&h1, &h2));
}
struct mdfour h1, h2;
hash_start(&h1);
hash_start(&h2);
+#ifndef _WIN32
create_file("foo.sh", "#!/bin/sh\necho foo\necho bar\n");
chmod("foo.sh", 0555);
CHECK(hash_multicommand_output(&h2, "echo foo; echo bar", "not used"));
CHECK(hash_multicommand_output(&h1, "./foo.sh", "not used"));
+#else
+ create_file("foo.bat", "@echo off\r\necho foo\r\necho bar\r\n");
+ CHECK(hash_multicommand_output(&h2, "echo foo; echo bar", "not used"));
+ CHECK(hash_multicommand_output(&h1, "foo.bat", "not used"));
+#endif
CHECK(hash_equal(&h1, &h2));
}
#if HAVE_REALPATH
p = realpath(path, ret);
#elif defined(_WIN32)
+ if (path[0] == '/')
+ path++; /* skip leading slash */
path_handle = CreateFile(
path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
}
#ifdef _WIN32
+ // Paths can be escaped by a slash for use with -isystem
+ if (from[0] == '/')
+ from++;
+ if (to[0] == '/')
+ to++;
// Both paths are absolute, drop the drive letters
assert(from[0] == to[0]); // Assume the same drive letter
from += 2;