This was sent in error, please ignore. Patch isn't quite ready yet. Andrew
> -----Original Message----- > From: Boie, Andrew P > Sent: Monday, July 30, 2012 3:38 PM > To: ccache@lists.samba.org > Cc: Boie, Andrew P > Subject: [PATCH v2] add support for '@' parameters > > From: "Boie, Andrew P" <andrew.p.b...@intel.com> > > These indicate to the compiler that additional command line options > should be read from a text file. If encountered, read the file, > tokenize any arguments, and if any are found, do an in-place replacement > of the '@' parameter with the arguments within the file. > > args_insert() added to insert a set of arguments into a position within > another set of arguments. > > args_init_from_string() has been improved so that any character may be > included by prefixing that character with a backslash, and support for > quoted arguments which pass special characters within the quotation marks > unmodified. > > Signed-off-by: Andrew Boie <andrew.p.b...@intel.com> > --- > args.c | 108 > +++++++++++++++++++++++++++++++++++++++++++++++++----- > ccache.c | 25 ++++++++++++- > ccache.h | 1 + > test/test_args.c | 47 +++++++++++++++++++++--- > 4 files changed, 166 insertions(+), 15 deletions(-) > > diff --git a/args.c b/args.c > index 13a3d37..ee84951 100644 > --- a/args.c > +++ b/args.c > @@ -37,17 +37,57 @@ struct args * > args_init_from_string(const char *command) > { > struct args *args; > - char *p = x_strdup(command); > - char *q = p; > - char *word, *saveptr = NULL; > - > + const char *pos = command; > + char *argbuf = x_malloc(strlen(command) + 1); > + char *argpos = argbuf; > args = args_init(0, NULL); > - while ((word = strtok_r(q, " \t\r\n", &saveptr))) { > - args_add(args, word); > - q = NULL; > - } > + argpos = argbuf; > + char quoting = '\0'; > + > + while (1) { > + switch (*pos) { > + case '\\': > + pos++; > + if (*pos == '\0') > + continue; > + break; > > - free(p); > + 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++; > + } > +out: > + free(argbuf); > return args; > } > > @@ -57,6 +97,56 @@ args_copy(struct args *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. > + * > + * This operation modifies dest but leaves src untouched. */ > +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]; > + } > + return; > + } > + > + if (src->argc == 1 && replace) { > + /* Trivial case; replace with 1 element */ > + dest->argv[index] = x_strdup(src->argv[0]); > + 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] = x_strdup(src->argv[j]); > + > + dest->argc += src->argc - offset; > +} > + > void > args_free(struct args *args) > { > diff --git a/ccache.c b/ccache.c > index 8e36bdd..a3d27ab 100644 > --- a/ccache.c > +++ b/ccache.c > @@ -1445,9 +1445,32 @@ cc_process_args(struct args *orig_args, struct args > **preprocessor_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); > + > + args_free(file_args); > + 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); > diff --git a/ccache.h b/ccache.h > index 7e25883..ed04c04 100644 > --- a/ccache.h > +++ b/ccache.h > @@ -75,6 +75,7 @@ void args_free(struct args *args); > 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); > diff --git a/test/test_args.c b/test/test_args.c > index 50608fc..3a595be 100644 > --- a/test/test_args.c > +++ b/test/test_args.c > @@ -48,14 +48,17 @@ TEST(args_init_populated) > > TEST(args_init_from_string) > { > - struct args *args = args_init_from_string("first > second\tthird\nfourth"); > + struct args *args = args_init_from_string("first > sec\\\tond\tthi\\\\rd\nfourth \tfif\\ th \"si'x\\\" th\" 'seve\nth'\\"); > CHECK(args); > - CHECK_INT_EQ(4, args->argc); > + CHECK_INT_EQ(7, args->argc); > CHECK_STR_EQ("first", args->argv[0]); > - CHECK_STR_EQ("second", args->argv[1]); > - CHECK_STR_EQ("third", args->argv[2]); > + CHECK_STR_EQ("sec\tond", args->argv[1]); > + CHECK_STR_EQ("thi\\rd", args->argv[2]); > CHECK_STR_EQ("fourth", args->argv[3]); > - CHECK(!args->argv[4]); > + 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]); > args_free(args); > } > > @@ -144,4 +147,38 @@ TEST(args_to_string) > 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(""); > + > + args_insert(args, 2, src1, true); > + CHECK_STR_EQ(args_to_string(args), > + "first second alpha beta gamma fourth fifth"); > + args_insert(args, 2, src2, true); > + CHECK_STR_EQ(args_to_string(args), > + "first second one beta gamma fourth fifth"); > + args_insert(args, 2, src3, true); > + CHECK_STR_EQ(args_to_string(args), > + "first second beta gamma fourth fifth"); > + > + args_insert(args, 1, src1, false); > + CHECK_STR_EQ(args_to_string(args), > + "first alpha beta gamma second beta gamma fourth fifth"); > + args_insert(args, 1, src2, false); > + CHECK_STR_EQ(args_to_string(args), > + "first one alpha beta gamma second beta gamma fourth > fifth"); > + args_insert(args, 1, src3, false); > + CHECK_STR_EQ(args_to_string(args), > + "first one alpha beta gamma second beta gamma fourth > fifth"); > + > + args_free(args); > + args_free(src1); > + args_free(src2); > + args_free(src3); > +} > + > TEST_SUITE_END > -- > 1.7.9.5 _______________________________________________ ccache mailing list ccache@lists.samba.org https://lists.samba.org/mailman/listinfo/ccache