15382d832SPeter Avalos /*
2*a8e38dc0SAntonio Huete Jimenez * $Id: argv.c,v 1.14 2022/04/03 22:38:16 tom Exp $
35382d832SPeter Avalos *
45382d832SPeter Avalos * argv - Reusable functions for argv-parsing.
55382d832SPeter Avalos *
6*a8e38dc0SAntonio Huete Jimenez * Copyright 2011-2020,2022 Thomas E. Dickey
75382d832SPeter Avalos *
85382d832SPeter Avalos * This program is free software; you can redistribute it and/or modify
95382d832SPeter Avalos * it under the terms of the GNU Lesser General Public License, version 2.1
105382d832SPeter Avalos * as published by the Free Software Foundation.
115382d832SPeter Avalos *
125382d832SPeter Avalos * This program is distributed in the hope that it will be useful, but
135382d832SPeter Avalos * WITHOUT ANY WARRANTY; without even the implied warranty of
145382d832SPeter Avalos * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
155382d832SPeter Avalos * Lesser General Public License for more details.
165382d832SPeter Avalos *
175382d832SPeter Avalos * You should have received a copy of the GNU Lesser General Public
185382d832SPeter Avalos * License along with this program; if not, write to
195382d832SPeter Avalos * Free Software Foundation, Inc.
205382d832SPeter Avalos * 51 Franklin St., Fifth Floor
215382d832SPeter Avalos * Boston, MA 02110, USA.
225382d832SPeter Avalos */
235382d832SPeter Avalos
24*a8e38dc0SAntonio Huete Jimenez #include <dlg_internals.h>
255382d832SPeter Avalos
265382d832SPeter Avalos /*
275382d832SPeter Avalos * Convert a string to an argv[], returning a char** index (which must be
285382d832SPeter Avalos * freed by the caller). The string is modified (replacing gaps between
295382d832SPeter Avalos * tokens with nulls).
305382d832SPeter Avalos */
315382d832SPeter Avalos char **
dlg_string_to_argv(char * blob)325382d832SPeter Avalos dlg_string_to_argv(char *blob)
335382d832SPeter Avalos {
345940c9abSDaniel Fojt size_t n, k;
355382d832SPeter Avalos int pass;
365382d832SPeter Avalos size_t length = strlen(blob);
375382d832SPeter Avalos char **result = 0;
385382d832SPeter Avalos
395940c9abSDaniel Fojt #ifdef HAVE_DLG_TRACE
405940c9abSDaniel Fojt if (dialog_state.trace_output) {
415940c9abSDaniel Fojt DLG_TRACE(("# dlg_string_to_argv:\n"));
425940c9abSDaniel Fojt DLG_TRACE(("# given:\n"));
435940c9abSDaniel Fojt for (n = k = 0; n < length; ++n) {
445940c9abSDaniel Fojt if (blob[n] == '\n') {
455940c9abSDaniel Fojt DLG_TRACE(("#%s\t%.*s\\n\n",
465940c9abSDaniel Fojt k ? "+" : "",
475940c9abSDaniel Fojt (int) (n - k), blob + k));
485940c9abSDaniel Fojt k = n + 1;
495940c9abSDaniel Fojt }
505940c9abSDaniel Fojt }
515940c9abSDaniel Fojt if (n > k) {
525940c9abSDaniel Fojt DLG_TRACE(("#%s\t%.*s\n",
535940c9abSDaniel Fojt k ? "+" : "",
545940c9abSDaniel Fojt (int) (n - k), blob + k));
555940c9abSDaniel Fojt }
565940c9abSDaniel Fojt DLG_TRACE(("# result:\n"));
575940c9abSDaniel Fojt }
585940c9abSDaniel Fojt #endif
595382d832SPeter Avalos for (pass = 0; pass < 2; ++pass) {
605382d832SPeter Avalos bool inparm = FALSE;
615382d832SPeter Avalos bool quoted = FALSE;
625382d832SPeter Avalos char *param = blob;
635382d832SPeter Avalos size_t count = 0;
645382d832SPeter Avalos
655382d832SPeter Avalos for (n = 0; n < length; ++n) {
665382d832SPeter Avalos if (quoted && blob[n] == '"') {
675382d832SPeter Avalos quoted = FALSE;
685382d832SPeter Avalos } else if (blob[n] == '"') {
695382d832SPeter Avalos quoted = TRUE;
705382d832SPeter Avalos if (!inparm) {
715940c9abSDaniel Fojt if (pass) {
725382d832SPeter Avalos result[count] = param;
735940c9abSDaniel Fojt }
745382d832SPeter Avalos ++count;
755382d832SPeter Avalos inparm = TRUE;
765382d832SPeter Avalos }
775382d832SPeter Avalos } else if (!quoted && isspace(UCH(blob[n]))) {
781ef6786aSJohn Marino if (inparm) {
795382d832SPeter Avalos if (pass) {
805940c9abSDaniel Fojt *param = '\0';
815382d832SPeter Avalos }
825940c9abSDaniel Fojt ++param;
831ef6786aSJohn Marino inparm = FALSE;
841ef6786aSJohn Marino }
855382d832SPeter Avalos } else {
865940c9abSDaniel Fojt if (blob[n] == '\\') {
875940c9abSDaniel Fojt size_t n1 = (n + 1);
885940c9abSDaniel Fojt bool ignore = FALSE;
895940c9abSDaniel Fojt if (n1 == length) {
905940c9abSDaniel Fojt break; /* The string is terminated by a backslash */
915940c9abSDaniel Fojt } else if ((blob[n1] == '\\') ||
925940c9abSDaniel Fojt (blob[n1] == '"') ||
935940c9abSDaniel Fojt (ignore = (blob[n1] == '\n'))) {
945940c9abSDaniel Fojt /* eat the backslash */
955940c9abSDaniel Fojt if (pass) {
965940c9abSDaniel Fojt --length;
975940c9abSDaniel Fojt for (k = n; k < length; ++k)
985940c9abSDaniel Fojt blob[k] = blob[k + 1];
995940c9abSDaniel Fojt blob[length] = '\0';
1005940c9abSDaniel Fojt } else {
1015940c9abSDaniel Fojt ++param; /* pretend I ate it */
1025940c9abSDaniel Fojt }
1035940c9abSDaniel Fojt if (ignore)
1045940c9abSDaniel Fojt continue;
1055940c9abSDaniel Fojt }
1065940c9abSDaniel Fojt }
1075382d832SPeter Avalos if (!inparm) {
1085940c9abSDaniel Fojt if (pass) {
1095382d832SPeter Avalos result[count] = param;
1105940c9abSDaniel Fojt }
1115382d832SPeter Avalos ++count;
1125382d832SPeter Avalos inparm = TRUE;
1135382d832SPeter Avalos }
1145382d832SPeter Avalos if (pass) {
1155940c9abSDaniel Fojt *param = blob[n];
1165382d832SPeter Avalos }
1175940c9abSDaniel Fojt ++param;
1185382d832SPeter Avalos }
1195382d832SPeter Avalos }
1205382d832SPeter Avalos
1215940c9abSDaniel Fojt if (pass) {
1225940c9abSDaniel Fojt *param = '\0';
1235940c9abSDaniel Fojt } else {
1245382d832SPeter Avalos if (count) {
1255382d832SPeter Avalos result = dlg_calloc(char *, count + 1);
1265382d832SPeter Avalos assert_ptr(result, "string_to_argv");
1275382d832SPeter Avalos } else {
1285382d832SPeter Avalos break; /* no tokens found */
1295382d832SPeter Avalos }
1305382d832SPeter Avalos }
1315382d832SPeter Avalos }
1321ef6786aSJohn Marino #ifdef HAVE_DLG_TRACE
1331ef6786aSJohn Marino if (result != 0) {
1341ef6786aSJohn Marino for (n = 0; result[n] != 0; ++n) {
1351ef6786aSJohn Marino DLG_TRACE(("#\targv[%d] = %s\n", (int) n, result[n]));
1361ef6786aSJohn Marino }
1371ef6786aSJohn Marino }
1381ef6786aSJohn Marino #endif
1395382d832SPeter Avalos return result;
1405382d832SPeter Avalos }
1415382d832SPeter Avalos
1425382d832SPeter Avalos /*
1435382d832SPeter Avalos * Count the entries in an argv list.
1445382d832SPeter Avalos */
1455382d832SPeter Avalos int
dlg_count_argv(char ** argv)1465382d832SPeter Avalos dlg_count_argv(char **argv)
1475382d832SPeter Avalos {
1485382d832SPeter Avalos int result = 0;
1495382d832SPeter Avalos
1505382d832SPeter Avalos if (argv != 0) {
1515382d832SPeter Avalos while (argv[result] != 0)
1525382d832SPeter Avalos ++result;
1535382d832SPeter Avalos }
1545382d832SPeter Avalos return result;
1555382d832SPeter Avalos }
1565382d832SPeter Avalos
1575382d832SPeter Avalos int
dlg_eat_argv(int * argcp,char *** argvp,int start,int count)1585382d832SPeter Avalos dlg_eat_argv(int *argcp, char ***argvp, int start, int count)
1595382d832SPeter Avalos {
1605382d832SPeter Avalos int k;
1615382d832SPeter Avalos
1625382d832SPeter Avalos *argcp -= count;
1635382d832SPeter Avalos for (k = start; k <= *argcp; k++)
1645382d832SPeter Avalos (*argvp)[k] = (*argvp)[k + count];
1655382d832SPeter Avalos (*argvp)[*argcp] = 0;
1665382d832SPeter Avalos return TRUE;
1675382d832SPeter Avalos }
168