Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/dialog/argv.c
39481 views
1
/*
2
* $Id: argv.c,v 1.13 2020/03/26 02:55:37 tom Exp $
3
*
4
* argv - Reusable functions for argv-parsing.
5
*
6
* Copyright 2011-2018,2020 Thomas E. Dickey
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU Lesser General Public License, version 2.1
10
* as published by the Free Software Foundation.
11
*
12
* This program is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this program; if not, write to
19
* Free Software Foundation, Inc.
20
* 51 Franklin St., Fifth Floor
21
* Boston, MA 02110, USA.
22
*/
23
24
#include <dialog.h>
25
#include <string.h>
26
27
/*
28
* Convert a string to an argv[], returning a char** index (which must be
29
* freed by the caller). The string is modified (replacing gaps between
30
* tokens with nulls).
31
*/
32
char **
33
dlg_string_to_argv(char *blob)
34
{
35
size_t n, k;
36
int pass;
37
size_t length = strlen(blob);
38
char **result = 0;
39
40
#ifdef HAVE_DLG_TRACE
41
if (dialog_state.trace_output) {
42
DLG_TRACE(("# dlg_string_to_argv:\n"));
43
DLG_TRACE(("# given:\n"));
44
for (n = k = 0; n < length; ++n) {
45
if (blob[n] == '\n') {
46
DLG_TRACE(("#%s\t%.*s\\n\n",
47
k ? "+" : "",
48
(int) (n - k), blob + k));
49
k = n + 1;
50
}
51
}
52
if (n > k) {
53
DLG_TRACE(("#%s\t%.*s\n",
54
k ? "+" : "",
55
(int) (n - k), blob + k));
56
}
57
DLG_TRACE(("# result:\n"));
58
}
59
#endif
60
for (pass = 0; pass < 2; ++pass) {
61
bool inparm = FALSE;
62
bool quoted = FALSE;
63
char *param = blob;
64
size_t count = 0;
65
66
for (n = 0; n < length; ++n) {
67
if (quoted && blob[n] == '"') {
68
quoted = FALSE;
69
} else if (blob[n] == '"') {
70
quoted = TRUE;
71
if (!inparm) {
72
if (pass) {
73
result[count] = param;
74
}
75
++count;
76
inparm = TRUE;
77
}
78
} else if (!quoted && isspace(UCH(blob[n]))) {
79
if (inparm) {
80
if (pass) {
81
*param = '\0';
82
}
83
++param;
84
inparm = FALSE;
85
}
86
} else {
87
if (blob[n] == '\\') {
88
size_t n1 = (n + 1);
89
bool ignore = FALSE;
90
if (n1 == length) {
91
break; /* The string is terminated by a backslash */
92
} else if ((blob[n1] == '\\') ||
93
(blob[n1] == '"') ||
94
(ignore = (blob[n1] == '\n'))) {
95
/* eat the backslash */
96
if (pass) {
97
--length;
98
for (k = n; k < length; ++k)
99
blob[k] = blob[k + 1];
100
blob[length] = '\0';
101
} else {
102
++param; /* pretend I ate it */
103
}
104
if (ignore)
105
continue;
106
}
107
}
108
if (!inparm) {
109
if (pass) {
110
result[count] = param;
111
}
112
++count;
113
inparm = TRUE;
114
}
115
if (pass) {
116
*param = blob[n];
117
}
118
++param;
119
}
120
}
121
122
if (pass) {
123
*param = '\0';
124
} else {
125
if (count) {
126
result = dlg_calloc(char *, count + 1);
127
assert_ptr(result, "string_to_argv");
128
} else {
129
break; /* no tokens found */
130
}
131
}
132
}
133
#ifdef HAVE_DLG_TRACE
134
if (result != 0) {
135
for (n = 0; result[n] != 0; ++n) {
136
DLG_TRACE(("#\targv[%d] = %s\n", (int) n, result[n]));
137
}
138
}
139
#endif
140
return result;
141
}
142
143
/*
144
* Count the entries in an argv list.
145
*/
146
int
147
dlg_count_argv(char **argv)
148
{
149
int result = 0;
150
151
if (argv != 0) {
152
while (argv[result] != 0)
153
++result;
154
}
155
return result;
156
}
157
158
int
159
dlg_eat_argv(int *argcp, char ***argvp, int start, int count)
160
{
161
int k;
162
163
*argcp -= count;
164
for (k = start; k <= *argcp; k++)
165
(*argvp)[k] = (*argvp)[k + count];
166
(*argvp)[*argcp] = 0;
167
return TRUE;
168
}
169
170