args_init_from_string(const char *command)
{
struct args *args;
- const char *pos = command;
- char *argbuf = x_malloc(strlen(command) + 1);
- char *argpos = argbuf;
- args = args_init(0, NULL);
- argpos = argbuf;
- char quoting = '\0';
-
- while (1) {
- switch (*pos) {
- case '\\':
- pos++;
- if (*pos == '\0')
- continue;
- break;
+ char *p = x_strdup(command);
+ char *q = p;
+ char *word, *saveptr = NULL;
- case '\"': case '\'':
- if (quoting != '\0') {
- if (quoting == *pos) {
- quoting = '\0';
- pos++;
- continue;
- } else
- break;
- } else {
- quoting = *pos;
- pos++;
- continue;
- }
- case '\n': case '\t': case ' ':
- if (quoting)
- break;
- /* Fall through */
- case '\0':
- /* end of token */
- *argpos = '\0';
- if (argbuf[0] != '\0')
- args_add(args, argbuf);
- argpos = argbuf;
- if (*pos == '\0')
- goto out;
- else {
- pos++;
- continue;
- }
- }
- *argpos = *pos;
- pos++;
- argpos++;
+ args = args_init(0, NULL);
+ while ((word = strtok_r(q, " \t\r\n", &saveptr))) {
+ args_add(args, word);
+ q = NULL;
}
-out:
- free(argbuf);
+
+ free(p);
return args;
}
return args_init(args->argc, args->argv);
}
-/* Insert all arguments in src into dest at position index.
- * If replace is true, the element at dest->argv[index] is replaced
- * with the contents of src and everything past it is shifted.
- * Otherwise, dest->argv[index] is also shifted.
- *
- * src is consumed by this operation and should not be freed or used
- * again by the caller */
-void
-args_insert(struct args *dest, int index, struct args *src, bool replace)
-{
- int offset;
- int j;
-
- /* Adjustments made if we are replacing or shifting the element
- * currently at dest->argv[index] */
- offset = replace ? 1 : 0;
-
- if (replace)
- free(dest->argv[index]);
-
- if (src->argc == 0) {
- if (replace) {
- /* Have to shift everything down by 1 since
- * we replaced with an empty list */
- for (j = index; j < dest->argc; j++)
- dest->argv[j] = dest->argv[j + 1];
- dest->argc--;
- }
- args_free(src);
- return;
- }
-
- if (src->argc == 1 && replace) {
- /* Trivial case; replace with 1 element */
- dest->argv[index] = src->argv[0];
- src->argc = 0;
- args_free(src);
- return;
- }
-
- dest->argv = (char**)x_realloc(dest->argv,
- (src->argc + dest->argc + 1 - offset) *
- sizeof(char *));
-
- /* Shift arguments over */
- for (j = dest->argc; j >= index + offset; j--)
- dest->argv[j + src->argc - offset] = dest->argv[j];
-
- /* Copy the new arguments into place */
- for (j = 0; j < src->argc; j++)
- dest->argv[j + index] = src->argv[j];
-
- dest->argc += src->argc - offset;
- src->argc = 0;
- args_free(src);
-}
-
void
args_free(struct args *args)
{
goto out;
}
- if (str_startswith(argv[i], "@")) {
- char *argpath = argv[i] + 1;
- struct args *file_args;
- char *argdata;
-
- if (!(argdata = read_text_file(argpath, 0))) {
- cc_log("Coudln't read arg file %s", argpath);
- stats_update(STATS_ARGS);
- result = false;
- goto out;
- }
-
- file_args = args_init_from_string(argdata);
- free(argdata);
-
- args_insert(orig_args, i, file_args, true);
-
- argc = orig_args->argc;
- argv = orig_args->argv;
- i--;
- continue;
- }
-
/* These are always too hard. */
if (compopt_too_hard(argv[i])
+ || str_startswith(argv[i], "@")
|| str_startswith(argv[i], "-fdump-")) {
cc_log("Compiler option %s is unsupported", argv[i]);
stats_update(STATS_UNSUPPORTED);
void args_add(struct args *args, const char *s);
void args_add_prefix(struct args *args, const char *s);
void args_extend(struct args *args, struct args *to_append);
-void args_insert(struct args *dest, int index, struct args *src, bool replace);
void args_pop(struct args *args, int n);
void args_set(struct args *args, int index, const char *value);
void args_strip(struct args *args, const char *prefix);
TEST(args_init_from_string)
{
- struct args *args = args_init_from_string("first sec\\\tond\tthi\\\\rd\nfourth \tfif\\ th \"si'x\\\" th\" 'seve\nth'\\");
+ struct args *args = args_init_from_string("first second\tthird\nfourth");
CHECK(args);
- CHECK_INT_EQ(7, args->argc);
+ CHECK_INT_EQ(4, args->argc);
CHECK_STR_EQ("first", args->argv[0]);
- CHECK_STR_EQ("sec\tond", args->argv[1]);
- CHECK_STR_EQ("thi\\rd", args->argv[2]);
+ CHECK_STR_EQ("second", args->argv[1]);
+ CHECK_STR_EQ("third", args->argv[2]);
CHECK_STR_EQ("fourth", args->argv[3]);
- CHECK_STR_EQ("fif th", args->argv[4]);
- CHECK_STR_EQ("si'x\" th", args->argv[5]);
- CHECK_STR_EQ("seve\nth", args->argv[6]);
- CHECK(!args->argv[7]);
+ CHECK(!args->argv[4]);
args_free(args);
}
args_free(args);
}
-TEST(args_insert)
-{
- struct args *args = args_init_from_string("first second third fourth fifth");
-
- struct args *src1 = args_init_from_string("alpha beta gamma");
- struct args *src2 = args_init_from_string("one");
- struct args *src3 = args_init_from_string("");
- struct args *src4 = args_init_from_string("alpha beta gamma");
- struct args *src5 = args_init_from_string("one");
- struct args *src6 = args_init_from_string("");
-
- args_insert(args, 2, src1, true);
- CHECK_STR_EQ(args_to_string(args),
- "first second alpha beta gamma fourth fifth");
- CHECK_INT_EQ(7, args->argc);
- args_insert(args, 2, src2, true);
- CHECK_STR_EQ(args_to_string(args),
- "first second one beta gamma fourth fifth");
- CHECK_INT_EQ(7, args->argc);
- args_insert(args, 2, src3, true);
- CHECK_STR_EQ(args_to_string(args),
- "first second beta gamma fourth fifth");
- CHECK_INT_EQ(6, args->argc);
-
- args_insert(args, 1, src4, false);
- CHECK_STR_EQ(args_to_string(args),
- "first alpha beta gamma second beta gamma fourth fifth");
- CHECK_INT_EQ(9, args->argc);
- args_insert(args, 1, src5, false);
- CHECK_STR_EQ(args_to_string(args),
- "first one alpha beta gamma second beta gamma fourth fifth");
- CHECK_INT_EQ(10, args->argc);
- args_insert(args, 1, src6, false);
- CHECK_STR_EQ(args_to_string(args),
- "first one alpha beta gamma second beta gamma fourth fifth");
- CHECK_INT_EQ(10, args->argc);
-
- args_free(args);
-}
-
TEST_SUITE_END