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, &quoted);
34 		*word || quoted;
35 		word = lub_string_nextword(word + len, &len, &offset, &quoted)) {
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