1 // Copyright (C) 2002 Andrew Tridgell
2 // Copyright (C) 2009-2016 Joel Rosdahl
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
21 args_init(int init_argc, char **init_args)
23 struct args *args = (struct args *)x_malloc(sizeof(struct args));
25 args->argv = (char **)x_malloc(sizeof(char *));
27 for (int i = 0; i < init_argc; i++) {
28 args_add(args, init_args[i]);
34 args_init_from_string(const char *command)
36 char *p = x_strdup(command);
38 char *word, *saveptr = NULL;
39 struct args *args = args_init(0, NULL);
40 while ((word = strtok_r(q, " \t\r\n", &saveptr))) {
50 args_init_from_gcc_atfile(const char *filename)
53 if (!(argtext = read_text_file(filename, 0))) {
57 struct args *args = args_init(0, NULL);
59 char *argbuf = x_malloc(strlen(argtext) + 1);
60 char *argpos = argbuf;
62 // Used to track quoting state; if \0, we are not inside quotes. Otherwise
63 // stores the quoting character that started it, for matching the end quote.
77 if (quoting != '\0') {
78 if (quoting == *pos) {
103 if (argbuf[0] != '\0') {
104 args_add(args, argbuf);
127 args_copy(struct args *args)
129 return args_init(args->argc, args->argv);
132 // Insert all arguments in src into dest at position index. If replace is true,
133 // the element at dest->argv[index] is replaced with the contents of src and
134 // everything past it is shifted. Otherwise, dest->argv[index] is also shifted.
136 // src is consumed by this operation and should not be freed or used again by
139 args_insert(struct args *dest, int index, struct args *src, bool replace)
141 // Adjustments made if we are replacing or shifting the element currently at
142 // dest->argv[index].
143 int offset = replace ? 1 : 0;
146 free(dest->argv[index]);
149 if (src->argc == 0) {
151 // Have to shift everything down by 1 since we replaced with an empty
153 for (int i = index; i < dest->argc; i++) {
154 dest->argv[i] = dest->argv[i + 1];
162 if (src->argc == 1 && replace) {
163 // Trivial case; replace with 1 element.
164 dest->argv[index] = src->argv[0];
170 dest->argv = (char **)x_realloc(
172 (src->argc + dest->argc + 1 - offset) *
175 // Shift arguments over.
176 for (int i = dest->argc; i >= index + offset; i--) {
177 dest->argv[i + src->argc - offset] = dest->argv[i];
180 // Copy the new arguments into place.
181 for (int i = 0; i < src->argc; i++) {
182 dest->argv[i + index] = src->argv[i];
185 dest->argc += src->argc - offset;
191 args_free(struct args *args)
196 for (int i = 0; i < args->argc; ++i) {
206 args_add(struct args *args, const char *s)
208 args->argv = (char **)x_realloc(args->argv,
209 (args->argc + 2) * sizeof(char *));
210 args->argv[args->argc] = x_strdup(s);
212 args->argv[args->argc] = NULL;
215 // Add all arguments in to_append to args.
217 args_extend(struct args *args, struct args *to_append)
219 for (int i = 0; i < to_append->argc; i++) {
220 args_add(args, to_append->argv[i]);
224 // Pop the last element off the args list.
226 args_pop(struct args *args, int n)
230 free(args->argv[args->argc]);
231 args->argv[args->argc] = NULL;
235 // Set argument at given index.
237 args_set(struct args *args, int index, const char *value)
239 assert(index < args->argc);
240 free(args->argv[index]);
241 args->argv[index] = x_strdup(value);
244 // Remove the first element of the argument list.
246 args_remove_first(struct args *args)
249 memmove(&args->argv[0], &args->argv[1], args->argc * sizeof(args->argv[0]));
253 // Add an argument into the front of the argument list.
255 args_add_prefix(struct args *args, const char *s)
257 args->argv = (char **)x_realloc(args->argv,
258 (args->argc + 2) * sizeof(char *));
259 memmove(&args->argv[1], &args->argv[0],
260 (args->argc+1) * sizeof(args->argv[0]));
261 args->argv[0] = x_strdup(s);
265 // Strip any arguments beginning with the specified prefix.
267 args_strip(struct args *args, const char *prefix)
269 for (int i = 0; i < args->argc; ) {
270 if (str_startswith(args->argv[i], prefix)) {
272 memmove(&args->argv[i],
274 (args->argc - i) * sizeof(args->argv[i]));
282 // Format args to a space-separated string. Does not quote spaces. Caller
285 args_to_string(struct args *args)
288 for (char **p = args->argv; *p; p++) {
289 size += strlen(*p) + 1;
292 char *result = x_malloc(size + 1);
294 for (char **p = args->argv; *p; p++) {
295 pos += sprintf(&result[pos], "%s ", *p);
297 result[pos - 1] = '\0';
301 // Returns true if args1 equals args2, else false.
303 args_equal(struct args *args1, struct args *args2)
305 if (args1->argc != args2->argc) {
308 for (int i = 0; i < args1->argc; i++) {
309 if (!str_eq(args1->argv[i], args2->argv[i])) {