"Fossies" - the Fresh Open Source Software Archive 
Member "global-6.6.5/libutil/args.c" (3 Sep 2020, 7009 Bytes) of package /linux/misc/global-6.6.5.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "args.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
6.6.4_vs_6.6.5.
1 /*
2 * Copyright (c) 2010, 2014, 2020 Tama Communications Corporation
3 *
4 * This file is part of GNU GLOBAL.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <ctype.h>
24 #include <stdio.h>
25 #include "getopt.h"
26 #include "checkalloc.h"
27 #include "die.h"
28 #include "env.h"
29 #include "locatestring.h"
30 #include "strbuf.h"
31 #include "test.h"
32 #include "gpathop.h"
33 #include "args.h"
34 #if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(__DJGPP__)
35 #include "path.h"
36 #endif
37
38 #define ARGS_NOP 0
39 #define ARGS_ARGS 1
40 #define ARGS_FILELIST 2
41 #define ARGS_GFIND 3
42 #define ARGS_BOTH 4
43
44 static int type;
45 static char *const *argslist;
46 static FILE *ip;
47 static GFIND *gp;
48
49 /**
50 * args_open:
51 *
52 * @param[in] args args array
53 */
54 void
55 args_open(char *const *argv)
56 {
57 type = ARGS_ARGS;
58 argslist = argv;
59 }
60 /**
61 * args_open_filelist: args_open like interface for handling output of find(1).
62 *
63 * @param[in] filename file including list of file names.
64 * When "-" is specified, read from standard input.
65 */
66 void
67 args_open_filelist(const char *filename)
68 {
69 type = ARGS_FILELIST;
70 if (!strcmp(filename, "-")) {
71 ip = stdin;
72 } else {
73 ip = fopen(filename, "r");
74 if (ip == NULL)
75 die("cannot open '%s'.", filename);
76 }
77 }
78 /**
79 * args_open_both: args_open like interface for argument and file list.
80 *
81 * @param[in] args args array
82 * @param[in] filename file including list of file names.
83 * When "-" is specified, read from standard input.
84 */
85 void
86 args_open_both(char *const *argv, const char *filename)
87 {
88 type = ARGS_BOTH;
89 argslist = argv;
90 if (!strcmp(filename, "-")) {
91 ip = stdin;
92 } else {
93 ip = fopen(filename, "r");
94 if (ip == NULL)
95 die("cannot open '%s'.", filename);
96 }
97 }
98 /**
99 * args_open_gfind: args_open like interface for handling output of gfind.
100 *
101 * @param[in] agp GFIND descriptor
102 */
103 void
104 args_open_gfind(GFIND *agp)
105 {
106 type = ARGS_GFIND;
107 gp = agp;
108 }
109 void
110 args_open_nop(void)
111 {
112 type = ARGS_NOP;
113 }
114 /**
115 * args_read: read path From args.
116 *
117 * @return path (NULL: end of argument)
118 */
119 const char *
120 args_read(void)
121 {
122 const char *p;
123 STATIC_STRBUF(sb);
124
125 strbuf_clear(sb);
126 switch (type) {
127 case ARGS_NOP:
128 p = NULL;
129 break;
130 case ARGS_ARGS:
131 p = *argslist++;
132 break;
133 case ARGS_FILELIST:
134 p = strbuf_fgets(sb, ip, STRBUF_NOCRLF);
135 break;
136 case ARGS_GFIND:
137 p = gfind_read(gp);
138 break;
139 case ARGS_BOTH:
140 if (*argslist != NULL)
141 p = *argslist++;
142 else
143 p = strbuf_fgets(sb, ip, STRBUF_NOCRLF);
144 break;
145 default:
146 die("args_read: invalid type.");
147 }
148 return p;
149 }
150 /**
151 * args_close: close args.
152 */
153 void
154 args_close(void)
155 {
156 switch (type) {
157 case ARGS_NOP:
158 case ARGS_ARGS:
159 break;
160 case ARGS_FILELIST:
161 case ARGS_BOTH:
162 if (ip != NULL && ip != stdin)
163 fclose(ip);
164 ip = NULL;
165 break;
166 case ARGS_GFIND:
167 if (gp != NULL)
168 gfind_close(gp);
169 gp = NULL;
170 break;
171 default:
172 die("something wrong.");
173 }
174 }
175 /**
176 * preparse_options
177 *
178 * @param[in] argc main()'s argc integer
179 * @param[in] argv main()'s argv string array
180 *
181 * Setup the "GTAGSCONF" and "GTAGSLABEL" environment variables
182 * according to the --gtagsconf and --gtagslabel options.
183 * Additionally changes directory acording to the --directory.
184 */
185 int
186 preparse_options(int argc, char *const *argv)
187 {
188 int optchar;
189 int option_index = 0;
190 char *confpath = NULL;
191 char *label = NULL;
192 char *dir = NULL;
193 extern const char *short_options;
194 extern struct option const long_options[];
195
196 /*
197 * restart scanning of the same argv by setting optind = 1.
198 */
199 optind = 1;
200 while ((optchar = getopt_long(argc, argv, short_options, long_options, &option_index)) != EOF) {
201 switch (optchar) {
202 case 'C':
203 dir = optarg;
204 break;
205 case OPT_GTAGSCONF:
206 confpath = optarg;
207 break;
208 case OPT_GTAGSLABEL:
209 label = optarg;
210 break;
211 case '?':
212 return -1;
213 default:
214 break;
215 }
216 }
217 /*
218 * Change the directory before doing all the work including parameter analysis.
219 */
220 if (dir)
221 if (chdir(dir) < 0)
222 die("cannot change directory to '%s'.", dir);
223 if (confpath) {
224 char real[MAXPATHLEN];
225
226 if (!test("f", confpath))
227 die("--gtagsconf file not found.");
228 if (!realpath(confpath, real))
229 die("cannot get absolute path of --gtagsconf file.");
230 set_env("GTAGSCONF", real);
231 }
232 if (label)
233 set_env("GTAGSLABEL", label);
234 /*
235 * restart scanning of the same argv by setting optind = 1.
236 * This is needed for the calling of getopt() in main().
237 */
238 optind = 1;
239 return 0;
240 }
241 /**
242 * prepend_options: creates a new argv main() array, by prepending (space separated)
243 * options and arguments from the string argument options.
244 *
245 * @param[in,out] argc pointer to main()'s argc integer
246 * @param[in] argv main()'s argv string array
247 * @param[in] options string
248 * @return The new argv array.
249 *
250 * The program's name is copied back into: returned[0] (argv[0]).
251 */
252 char **
253 prepend_options(int *argc, char *const *argv, const char *options)
254 {
255 STRBUF *sb = strbuf_open(0);
256 const char *p, *opt = check_strdup(options);
257 int count = 1;
258 int quote = 0;
259 const char **newargv;
260 int i = 0, j = 1;
261
262 for (p = opt; *p && isspace(*p); p++)
263 ;
264 for (; *p; p++) {
265 int c = *p;
266
267 if (quote) {
268 if (quote == c)
269 quote = 0;
270 else
271 strbuf_putc(sb, c);
272 } else if (c == '\\') {
273 if (*(p + 1))
274 strbuf_putc(sb, *++p);
275 } else if (c == '\'' || c == '"') {
276 quote = c;
277 } else if (isspace(c)) {
278 strbuf_putc(sb, '\0');
279 count++;
280 while (*p && isspace(*p))
281 p++;
282 p--;
283 } else {
284 strbuf_putc(sb, *p);
285 }
286 }
287 newargv = (const char **)check_malloc(sizeof(char *) * (*argc + count + 1));
288 newargv[i++] = argv[0];
289 p = strbuf_value(sb);
290 while (count--) {
291 newargv[i++] = p;
292 p += strlen(p) + 1;
293 }
294 while (j < *argc)
295 newargv[i++] = argv[j++];
296 newargv[i] = NULL;
297 *argc = i;
298 #ifdef DEBUG
299 for (i = 0; i < *argc; i++)
300 fprintf(stderr, "newargv[%d] = '%s'\n", i, newargv[i]);
301 #endif
302 /* doesn't close string buffer. */
303
304 return (char **)newargv;
305 }
306 /**
307 * serialize_options
308 */
309 char *
310 serialize_options(int argc, char *const *argv)
311 {
312 STRBUF *sb = strbuf_open(0);
313 char *string = NULL;
314 char *p = NULL;
315 int i;
316 for (i = 0; i < argc; i++) {
317 if (i > 0)
318 strbuf_putc(sb, ' ');
319 for (p = argv[i]; *p; p++) {
320 /* quote spaces using url encoding */
321 if (*p == ' ')
322 strbuf_puts(sb, "%20");
323 else
324 strbuf_putc(sb, *p);
325 }
326 }
327 string = check_strdup(strbuf_value(sb));
328 strbuf_close(sb);
329 return string;
330 }