2 * Copyright (C) 2002 Andrew Tridgell
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 3 of the License, or (at your option)
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51
16 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 args_init(int init_argc, char **init_args)
26 args = (struct args *)x_malloc(sizeof(struct args));
28 args->argv = (char **)x_malloc(sizeof(char *));
30 for (i = 0; i < init_argc; i++) {
31 args_add(args, init_args[i]);
37 args_init_from_string(const char *command)
40 char *p = x_strdup(command);
42 char *word, *saveptr = NULL;
44 args = args_init(0, NULL);
45 while ((word = strtok_r(q, " \t\r\n", &saveptr))) {
55 args_init_from_gcc_atfile(const char *filename)
58 char *pos, *argtext, *argpos, *argbuf;
61 /* Used to track quoting state; if \0, we are not inside quotes. Otherwise
62 * stores the quoting character that started it, for matching the end
66 if (!(argtext = read_text_file(filename, 0)))
69 args = args_init(0, NULL);
71 argbuf = x_malloc(strlen(argtext) + 1);
85 if (quoting != '\0') {
86 if (quoting == *pos) {
111 if (argbuf[0] != '\0')
112 args_add(args, argbuf);
134 args_copy(struct args *args)
136 return args_init(args->argc, args->argv);
139 /* Insert all arguments in src into dest at position index.
140 * If replace is true, the element at dest->argv[index] is replaced
141 * with the contents of src and everything past it is shifted.
142 * Otherwise, dest->argv[index] is also shifted.
144 * src is consumed by this operation and should not be freed or used
145 * again by the caller */
147 args_insert(struct args *dest, int index, struct args *src, bool replace)
152 /* Adjustments made if we are replacing or shifting the element
153 * currently at dest->argv[index] */
154 offset = replace ? 1 : 0;
157 free(dest->argv[index]);
160 if (src->argc == 0) {
162 /* Have to shift everything down by 1 since
163 * we replaced with an empty list */
164 for (i = index; i < dest->argc; i++) {
165 dest->argv[i] = dest->argv[i + 1];
173 if (src->argc == 1 && replace) {
174 /* Trivial case; replace with 1 element */
175 dest->argv[index] = src->argv[0];
181 dest->argv = (char **)x_realloc(
183 (src->argc + dest->argc + 1 - offset) *
186 /* Shift arguments over */
187 for (i = dest->argc; i >= index + offset; i--) {
188 dest->argv[i + src->argc - offset] = dest->argv[i];
191 /* Copy the new arguments into place */
192 for (i = 0; i < src->argc; i++) {
193 dest->argv[i + index] = src->argv[i];
196 dest->argc += src->argc - offset;
202 args_free(struct args *args)
208 for (i = 0; i < args->argc; ++i) {
218 args_add(struct args *args, const char *s)
220 args->argv = (char **)x_realloc(args->argv,
221 (args->argc + 2) * sizeof(char *));
222 args->argv[args->argc] = x_strdup(s);
224 args->argv[args->argc] = NULL;
227 /* Add all arguments in to_append to args. */
229 args_extend(struct args *args, struct args *to_append)
232 for (i = 0; i < to_append->argc; i++) {
233 args_add(args, to_append->argv[i]);
237 /* pop the last element off the args list */
239 args_pop(struct args *args, int n)
243 free(args->argv[args->argc]);
244 args->argv[args->argc] = NULL;
248 /* set argument at given index */
250 args_set(struct args *args, int index, const char *value)
252 assert(index < args->argc);
253 free(args->argv[index]);
254 args->argv[index] = x_strdup(value);
257 /* remove the first element of the argument list */
259 args_remove_first(struct args *args)
262 memmove(&args->argv[0], &args->argv[1], args->argc * sizeof(args->argv[0]));
266 /* add an argument into the front of the argument list */
268 args_add_prefix(struct args *args, const char *s)
270 args->argv = (char **)x_realloc(args->argv,
271 (args->argc + 2) * sizeof(char *));
272 memmove(&args->argv[1], &args->argv[0],
273 (args->argc+1) * sizeof(args->argv[0]));
274 args->argv[0] = x_strdup(s);
278 /* strip any arguments beginning with the specified prefix */
280 args_strip(struct args *args, const char *prefix)
283 for (i = 0; i < args->argc; ) {
284 if (str_startswith(args->argv[i], prefix)) {
286 memmove(&args->argv[i],
288 (args->argc - i) * sizeof(args->argv[i]));
297 * Format args to a space-separated string. Does not quote spaces. Caller
301 args_to_string(struct args *args)
307 for (p = args->argv; *p; p++) {
308 size += strlen(*p) + 1;
310 result = x_malloc(size + 1);
312 for (p = args->argv; *p; p++) {
313 pos += sprintf(&result[pos], "%s ", *p);
315 result[pos - 1] = '\0';
319 /* Returns true if args1 equals args2, else false. */
321 args_equal(struct args *args1, struct args *args2)
324 if (args1->argc != args2->argc) {
327 for (i = 0; i < args1->argc; i++) {
328 if (!str_eq(args1->argv[i], args2->argv[i])) {