[ccache] [PATCH v2] add support for '@' parameters

Boie, Andrew P andrew.p.boie at intel.com
Mon Jul 30 16:38:41 MDT 2012


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 at lists.samba.org
> Cc: Boie, Andrew P
> Subject: [PATCH v2] add support for '@' parameters
> 
> From: "Boie, Andrew P" <andrew.p.boie at 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.boie at 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



More information about the ccache mailing list