1 /*
2 * argv.c
3 */
4 #include "private.h"
5 #include "lub/string.h"
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <assert.h>
10 #include <ctype.h>
11
12 /*--------------------------------------------------------- */
lub_argv_init(lub_argv_t * this,const char * line,size_t offset)13 static void lub_argv_init(lub_argv_t * this, const char *line, size_t offset)
14 {
15 size_t len;
16 const char *word;
17 lub_arg_t *arg;
18 size_t quoted;
19
20 this->argv = NULL;
21 this->argc = 0;
22 if (!line)
23 return;
24 /* first of all count the words in the line */
25 this->argc = lub_string_wordcount(line);
26 if (0 == this->argc)
27 return;
28 /* allocate space to hold the vector */
29 arg = this->argv = malloc(sizeof(lub_arg_t) * this->argc);
30 assert(arg);
31
32 /* then fill out the array with the words */
33 for (word = lub_string_nextword(line, &len, &offset, "ed);
34 *word || quoted;
35 word = lub_string_nextword(word + len, &len, &offset, "ed)) {
36 (*arg).arg = lub_string_ndecode(word, len);
37 (*arg).offset = offset;
38 (*arg).quoted = quoted ? BOOL_TRUE : BOOL_FALSE;
39
40 offset += len;
41
42 if (quoted) {
43 len += quoted - 1; /* account for terminating quotation mark */
44 offset += quoted; /* account for quotation marks */
45 }
46 arg++;
47 }
48 }
49
50 /*--------------------------------------------------------- */
lub_argv_new(const char * line,size_t offset)51 lub_argv_t *lub_argv_new(const char *line, size_t offset)
52 {
53 lub_argv_t *this;
54
55 this = malloc(sizeof(lub_argv_t));
56 if (this)
57 lub_argv_init(this, line, offset);
58
59 return this;
60 }
61
62 /*--------------------------------------------------------- */
lub_argv_add(lub_argv_t * this,const char * text)63 void lub_argv_add(lub_argv_t * this, const char *text)
64 {
65 lub_arg_t * arg;
66
67 if (!text)
68 return;
69
70 /* allocate space to hold the vector */
71 arg = realloc(this->argv, sizeof(lub_arg_t) * (this->argc + 1));
72 assert(arg);
73 this->argv = arg;
74 (this->argv[this->argc++]).arg = strdup(text);
75 }
76
77 /*--------------------------------------------------------- */
lub_argv_fini(lub_argv_t * this)78 static void lub_argv_fini(lub_argv_t * this)
79 {
80 unsigned i;
81
82 for (i = 0; i < this->argc; i++)
83 free(this->argv[i].arg);
84 free(this->argv);
85 this->argv = NULL;
86 }
87
88 /*--------------------------------------------------------- */
lub_argv_delete(lub_argv_t * this)89 void lub_argv_delete(lub_argv_t * this)
90 {
91 lub_argv_fini(this);
92 free(this);
93 }
94
95 /*--------------------------------------------------------- */
lub_argv__get_line(const lub_argv_t * this)96 char *lub_argv__get_line(const lub_argv_t * this)
97 {
98 int space = 0;
99 const char *p;
100 unsigned i;
101 char *line = NULL;
102
103 for (i = 0; i < this->argc; i++) {
104 if (i != 0)
105 lub_string_cat(&line, " ");
106 space = 0;
107 /* Search for spaces */
108 for (p = this->argv[i].arg; *p; p++) {
109 if (isspace(*p)) {
110 space = 1;
111 break;
112 }
113 }
114 if (space)
115 lub_string_cat(&line, "\"");
116 lub_string_cat(&line, this->argv[i].arg);
117 if (space)
118 lub_string_cat(&line, "\"");
119 }
120
121 return line;
122 }
123
124 /*--------------------------------------------------------- */
lub_argv__get_argv(const lub_argv_t * this,const char * argv0)125 char **lub_argv__get_argv(const lub_argv_t * this, const char *argv0)
126 {
127 char **result = NULL;
128 unsigned i;
129 unsigned a = 0;
130
131 if (argv0)
132 a = 1;
133
134 result = malloc(sizeof(char *) * (this->argc + 1 + a));
135
136 if (argv0)
137 result[0] = strdup(argv0);
138 for (i = 0; i < this->argc; i++)
139 result[i + a] = strdup(this->argv[i].arg);
140 result[i + a] = NULL;
141
142 return result;
143 }
144
145 /*--------------------------------------------------------- */
lub_argv__free_argv(char ** argv)146 void lub_argv__free_argv(char **argv)
147 {
148 unsigned i;
149
150 if (!argv)
151 return;
152
153 for (i = 0; argv[i]; i++)
154 free(argv[i]);
155 free(argv);
156 }
157
158 /*--------------------------------------------------------- */
lub_argv__get_arg(const lub_argv_t * this,unsigned int index)159 const char *lub_argv__get_arg(const lub_argv_t *this, unsigned int index)
160 {
161 const char *result = NULL;
162
163 if (!this)
164 return NULL;
165 if (this->argc > index)
166 result = this->argv[index].arg;
167
168 return result;
169 }
170
171 /*--------------------------------------------------------- */
lub_argv__get_count(const lub_argv_t * this)172 unsigned lub_argv__get_count(const lub_argv_t * this)
173 {
174 return this->argc;
175 }
176
177 /*--------------------------------------------------------- */
lub_argv__get_offset(const lub_argv_t * this,unsigned index)178 size_t lub_argv__get_offset(const lub_argv_t * this, unsigned index)
179 {
180 size_t result = 0;
181
182 if (this->argc > index)
183 result = this->argv[index].offset;
184
185 return result;
186 }
187
188 /*--------------------------------------------------------- */
lub_argv__get_quoted(const lub_argv_t * this,unsigned index)189 bool_t lub_argv__get_quoted(const lub_argv_t * this, unsigned index)
190 {
191 bool_t result = BOOL_FALSE;
192
193 if (this->argc > index)
194 result = this->argv[index].quoted;
195
196 return result;
197 }
198
199 /*--------------------------------------------------------- */
200