17a1c0d96SNathan Whitehorn /*
2*a96ef450SBaptiste Daroussin * $Id: argv.c,v 1.13 2020/03/26 02:55:37 tom Exp $
37a1c0d96SNathan Whitehorn *
47a1c0d96SNathan Whitehorn * argv - Reusable functions for argv-parsing.
57a1c0d96SNathan Whitehorn *
6*a96ef450SBaptiste Daroussin * Copyright 2011-2018,2020 Thomas E. Dickey
77a1c0d96SNathan Whitehorn *
87a1c0d96SNathan Whitehorn * This program is free software; you can redistribute it and/or modify
97a1c0d96SNathan Whitehorn * it under the terms of the GNU Lesser General Public License, version 2.1
107a1c0d96SNathan Whitehorn * as published by the Free Software Foundation.
117a1c0d96SNathan Whitehorn *
127a1c0d96SNathan Whitehorn * This program is distributed in the hope that it will be useful, but
137a1c0d96SNathan Whitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of
147a1c0d96SNathan Whitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
157a1c0d96SNathan Whitehorn * Lesser General Public License for more details.
167a1c0d96SNathan Whitehorn *
177a1c0d96SNathan Whitehorn * You should have received a copy of the GNU Lesser General Public
187a1c0d96SNathan Whitehorn * License along with this program; if not, write to
197a1c0d96SNathan Whitehorn * Free Software Foundation, Inc.
207a1c0d96SNathan Whitehorn * 51 Franklin St., Fifth Floor
217a1c0d96SNathan Whitehorn * Boston, MA 02110, USA.
227a1c0d96SNathan Whitehorn */
237a1c0d96SNathan Whitehorn
247a1c0d96SNathan Whitehorn #include <dialog.h>
257a1c0d96SNathan Whitehorn #include <string.h>
267a1c0d96SNathan Whitehorn
277a1c0d96SNathan Whitehorn /*
287a1c0d96SNathan Whitehorn * Convert a string to an argv[], returning a char** index (which must be
297a1c0d96SNathan Whitehorn * freed by the caller). The string is modified (replacing gaps between
307a1c0d96SNathan Whitehorn * tokens with nulls).
317a1c0d96SNathan Whitehorn */
327a1c0d96SNathan Whitehorn char **
dlg_string_to_argv(char * blob)337a1c0d96SNathan Whitehorn dlg_string_to_argv(char *blob)
347a1c0d96SNathan Whitehorn {
35f4f33ea0SBaptiste Daroussin size_t n, k;
367a1c0d96SNathan Whitehorn int pass;
377a1c0d96SNathan Whitehorn size_t length = strlen(blob);
387a1c0d96SNathan Whitehorn char **result = 0;
397a1c0d96SNathan Whitehorn
40f4f33ea0SBaptiste Daroussin #ifdef HAVE_DLG_TRACE
41f4f33ea0SBaptiste Daroussin if (dialog_state.trace_output) {
42f4f33ea0SBaptiste Daroussin DLG_TRACE(("# dlg_string_to_argv:\n"));
43f4f33ea0SBaptiste Daroussin DLG_TRACE(("# given:\n"));
44f4f33ea0SBaptiste Daroussin for (n = k = 0; n < length; ++n) {
45f4f33ea0SBaptiste Daroussin if (blob[n] == '\n') {
46f4f33ea0SBaptiste Daroussin DLG_TRACE(("#%s\t%.*s\\n\n",
47f4f33ea0SBaptiste Daroussin k ? "+" : "",
48f4f33ea0SBaptiste Daroussin (int) (n - k), blob + k));
49f4f33ea0SBaptiste Daroussin k = n + 1;
50f4f33ea0SBaptiste Daroussin }
51f4f33ea0SBaptiste Daroussin }
52f4f33ea0SBaptiste Daroussin if (n > k) {
53f4f33ea0SBaptiste Daroussin DLG_TRACE(("#%s\t%.*s\n",
54f4f33ea0SBaptiste Daroussin k ? "+" : "",
55f4f33ea0SBaptiste Daroussin (int) (n - k), blob + k));
56f4f33ea0SBaptiste Daroussin }
57f4f33ea0SBaptiste Daroussin DLG_TRACE(("# result:\n"));
58f4f33ea0SBaptiste Daroussin }
59f4f33ea0SBaptiste Daroussin #endif
607a1c0d96SNathan Whitehorn for (pass = 0; pass < 2; ++pass) {
617a1c0d96SNathan Whitehorn bool inparm = FALSE;
627a1c0d96SNathan Whitehorn bool quoted = FALSE;
637a1c0d96SNathan Whitehorn char *param = blob;
647a1c0d96SNathan Whitehorn size_t count = 0;
657a1c0d96SNathan Whitehorn
667a1c0d96SNathan Whitehorn for (n = 0; n < length; ++n) {
67*a96ef450SBaptiste Daroussin if (quoted && blob[n] == '"') {
687a1c0d96SNathan Whitehorn quoted = FALSE;
697a1c0d96SNathan Whitehorn } else if (blob[n] == '"') {
707a1c0d96SNathan Whitehorn quoted = TRUE;
717a1c0d96SNathan Whitehorn if (!inparm) {
72*a96ef450SBaptiste Daroussin if (pass) {
737a1c0d96SNathan Whitehorn result[count] = param;
74*a96ef450SBaptiste Daroussin }
757a1c0d96SNathan Whitehorn ++count;
767a1c0d96SNathan Whitehorn inparm = TRUE;
777a1c0d96SNathan Whitehorn }
787a1c0d96SNathan Whitehorn } else if (!quoted && isspace(UCH(blob[n]))) {
79f4f33ea0SBaptiste Daroussin if (inparm) {
807a1c0d96SNathan Whitehorn if (pass) {
81*a96ef450SBaptiste Daroussin *param = '\0';
827a1c0d96SNathan Whitehorn }
83*a96ef450SBaptiste Daroussin ++param;
84f4f33ea0SBaptiste Daroussin inparm = FALSE;
85f4f33ea0SBaptiste Daroussin }
867a1c0d96SNathan Whitehorn } else {
87f4f33ea0SBaptiste Daroussin if (blob[n] == '\\') {
88*a96ef450SBaptiste Daroussin size_t n1 = (n + 1);
89*a96ef450SBaptiste Daroussin bool ignore = FALSE;
90*a96ef450SBaptiste Daroussin if (n1 == length) {
91f4f33ea0SBaptiste Daroussin break; /* The string is terminated by a backslash */
92*a96ef450SBaptiste Daroussin } else if ((blob[n1] == '\\') ||
93*a96ef450SBaptiste Daroussin (blob[n1] == '"') ||
94*a96ef450SBaptiste Daroussin (ignore = (blob[n1] == '\n'))) {
95f4f33ea0SBaptiste Daroussin /* eat the backslash */
96f4f33ea0SBaptiste Daroussin if (pass) {
97f4f33ea0SBaptiste Daroussin --length;
98f4f33ea0SBaptiste Daroussin for (k = n; k < length; ++k)
99f4f33ea0SBaptiste Daroussin blob[k] = blob[k + 1];
100f4f33ea0SBaptiste Daroussin blob[length] = '\0';
101f4f33ea0SBaptiste Daroussin } else {
102*a96ef450SBaptiste Daroussin ++param; /* pretend I ate it */
103*a96ef450SBaptiste Daroussin }
104*a96ef450SBaptiste Daroussin if (ignore)
105f4f33ea0SBaptiste Daroussin continue;
106f4f33ea0SBaptiste Daroussin }
107f4f33ea0SBaptiste Daroussin }
1087a1c0d96SNathan Whitehorn if (!inparm) {
109*a96ef450SBaptiste Daroussin if (pass) {
1107a1c0d96SNathan Whitehorn result[count] = param;
111*a96ef450SBaptiste Daroussin }
1127a1c0d96SNathan Whitehorn ++count;
1137a1c0d96SNathan Whitehorn inparm = TRUE;
1147a1c0d96SNathan Whitehorn }
1157a1c0d96SNathan Whitehorn if (pass) {
116*a96ef450SBaptiste Daroussin *param = blob[n];
1177a1c0d96SNathan Whitehorn }
118*a96ef450SBaptiste Daroussin ++param;
1197a1c0d96SNathan Whitehorn }
1207a1c0d96SNathan Whitehorn }
1217a1c0d96SNathan Whitehorn
122*a96ef450SBaptiste Daroussin if (pass) {
123*a96ef450SBaptiste Daroussin *param = '\0';
124*a96ef450SBaptiste Daroussin } else {
1257a1c0d96SNathan Whitehorn if (count) {
1267a1c0d96SNathan Whitehorn result = dlg_calloc(char *, count + 1);
1277a1c0d96SNathan Whitehorn assert_ptr(result, "string_to_argv");
1287a1c0d96SNathan Whitehorn } else {
1297a1c0d96SNathan Whitehorn break; /* no tokens found */
1307a1c0d96SNathan Whitehorn }
1317a1c0d96SNathan Whitehorn }
1327a1c0d96SNathan Whitehorn }
133f4f33ea0SBaptiste Daroussin #ifdef HAVE_DLG_TRACE
134f4f33ea0SBaptiste Daroussin if (result != 0) {
135f4f33ea0SBaptiste Daroussin for (n = 0; result[n] != 0; ++n) {
136f4f33ea0SBaptiste Daroussin DLG_TRACE(("#\targv[%d] = %s\n", (int) n, result[n]));
137f4f33ea0SBaptiste Daroussin }
138f4f33ea0SBaptiste Daroussin }
139f4f33ea0SBaptiste Daroussin #endif
1407a1c0d96SNathan Whitehorn return result;
1417a1c0d96SNathan Whitehorn }
1427a1c0d96SNathan Whitehorn
1437a1c0d96SNathan Whitehorn /*
1447a1c0d96SNathan Whitehorn * Count the entries in an argv list.
1457a1c0d96SNathan Whitehorn */
1467a1c0d96SNathan Whitehorn int
dlg_count_argv(char ** argv)1477a1c0d96SNathan Whitehorn dlg_count_argv(char **argv)
1487a1c0d96SNathan Whitehorn {
1497a1c0d96SNathan Whitehorn int result = 0;
1507a1c0d96SNathan Whitehorn
1517a1c0d96SNathan Whitehorn if (argv != 0) {
1527a1c0d96SNathan Whitehorn while (argv[result] != 0)
1537a1c0d96SNathan Whitehorn ++result;
1547a1c0d96SNathan Whitehorn }
1557a1c0d96SNathan Whitehorn return result;
1567a1c0d96SNathan Whitehorn }
1577a1c0d96SNathan Whitehorn
1587a1c0d96SNathan Whitehorn int
dlg_eat_argv(int * argcp,char *** argvp,int start,int count)1597a1c0d96SNathan Whitehorn dlg_eat_argv(int *argcp, char ***argvp, int start, int count)
1607a1c0d96SNathan Whitehorn {
1617a1c0d96SNathan Whitehorn int k;
1627a1c0d96SNathan Whitehorn
1637a1c0d96SNathan Whitehorn *argcp -= count;
1647a1c0d96SNathan Whitehorn for (k = start; k <= *argcp; k++)
1657a1c0d96SNathan Whitehorn (*argvp)[k] = (*argvp)[k + count];
1667a1c0d96SNathan Whitehorn (*argvp)[*argcp] = 0;
1677a1c0d96SNathan Whitehorn return TRUE;
1687a1c0d96SNathan Whitehorn }
169