00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 #include "ansidecl.h"
00029 #include "libiberty.h"
00030 #include "safe-ctype.h"
00031
00032
00033
00034 #include <stddef.h>
00035 #include <string.h>
00036 #include <stdlib.h>
00037 #include <stdio.h>
00038
00039 #ifndef NULL
00040 #define NULL 0
00041 #endif
00042
00043 #ifndef EOS
00044 #define EOS '\0'
00045 #endif
00046
00047 #define INITIAL_MAXARGC 8
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 char **
00065 dupargv (char **argv)
00066 {
00067 int argc;
00068 char **copy;
00069
00070 if (argv == NULL)
00071 return NULL;
00072
00073
00074 for (argc = 0; argv[argc] != NULL; argc++);
00075 copy = (char **) malloc ((argc + 1) * sizeof (char *));
00076 if (copy == NULL)
00077 return NULL;
00078
00079
00080 for (argc = 0; argv[argc] != NULL; argc++)
00081 {
00082 int len = strlen (argv[argc]);
00083 copy[argc] = (char *) malloc (len + 1);
00084 if (copy[argc] == NULL)
00085 {
00086 freeargv (copy);
00087 return NULL;
00088 }
00089 strcpy (copy[argc], argv[argc]);
00090 }
00091 copy[argc] = NULL;
00092 return copy;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 void freeargv (char **vector)
00109 {
00110 register char **scan;
00111
00112 if (vector != NULL)
00113 {
00114 for (scan = vector; *scan != NULL; scan++)
00115 {
00116 free (*scan);
00117 }
00118 free (vector);
00119 }
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 char **buildargv (const char *input)
00163 {
00164 char *arg;
00165 char *copybuf;
00166 int squote = 0;
00167 int dquote = 0;
00168 int bsquote = 0;
00169 int argc = 0;
00170 int maxargc = 0;
00171 char **argv = NULL;
00172 char **nargv;
00173
00174 if (input != NULL)
00175 {
00176 copybuf = (char *) alloca (strlen (input) + 1);
00177
00178
00179 do
00180 {
00181
00182 while (ISBLANK (*input))
00183 {
00184 input++;
00185 }
00186 if ((maxargc == 0) || (argc >= (maxargc - 1)))
00187 {
00188
00189 if (argv == NULL)
00190 {
00191 maxargc = INITIAL_MAXARGC;
00192 nargv = (char **) malloc (maxargc * sizeof (char *));
00193 }
00194 else
00195 {
00196 maxargc *= 2;
00197 nargv = (char **) realloc (argv, maxargc * sizeof (char *));
00198 }
00199 if (nargv == NULL)
00200 {
00201 if (argv != NULL)
00202 {
00203 freeargv (argv);
00204 argv = NULL;
00205 }
00206 break;
00207 }
00208 argv = nargv;
00209 argv[argc] = NULL;
00210 }
00211
00212 arg = copybuf;
00213 while (*input != EOS)
00214 {
00215 if (ISSPACE (*input) && !squote && !dquote && !bsquote)
00216 {
00217 break;
00218 }
00219 else
00220 {
00221 if (bsquote)
00222 {
00223 bsquote = 0;
00224 *arg++ = *input;
00225 }
00226 else if (*input == '\\')
00227 {
00228 bsquote = 1;
00229 }
00230 else if (squote)
00231 {
00232 if (*input == '\'')
00233 {
00234 squote = 0;
00235 }
00236 else
00237 {
00238 *arg++ = *input;
00239 }
00240 }
00241 else if (dquote)
00242 {
00243 if (*input == '"')
00244 {
00245 dquote = 0;
00246 }
00247 else
00248 {
00249 *arg++ = *input;
00250 }
00251 }
00252 else
00253 {
00254 if (*input == '\'')
00255 {
00256 squote = 1;
00257 }
00258 else if (*input == '"')
00259 {
00260 dquote = 1;
00261 }
00262 else
00263 {
00264 *arg++ = *input;
00265 }
00266 }
00267 input++;
00268 }
00269 }
00270 *arg = EOS;
00271 argv[argc] = strdup (copybuf);
00272 if (argv[argc] == NULL)
00273 {
00274 freeargv (argv);
00275 argv = NULL;
00276 break;
00277 }
00278 argc++;
00279 argv[argc] = NULL;
00280
00281 while (ISSPACE (*input))
00282 {
00283 input++;
00284 }
00285 }
00286 while (*input != EOS);
00287 }
00288 return (argv);
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 void
00315 expandargv (argcp, argvp)
00316 int *argcp;
00317 char ***argvp;
00318 {
00319
00320 int i = 0;
00321
00322 int argv_dynamic = 0;
00323
00324
00325 while (++i < *argcp)
00326 {
00327
00328 const char *filename;
00329
00330 FILE *f;
00331
00332
00333 long pos;
00334
00335
00336 size_t len;
00337
00338
00339 char *buffer;
00340
00341
00342 char **file_argv;
00343
00344 size_t file_argc;
00345
00346 filename = (*argvp)[i];
00347 if (filename[0] != '@')
00348 continue;
00349
00350 f = fopen (++filename, "r");
00351 if (!f)
00352 continue;
00353 if (fseek (f, 0L, SEEK_END) == -1)
00354 goto error;
00355 pos = ftell (f);
00356 if (pos == -1)
00357 goto error;
00358 if (fseek (f, 0L, SEEK_SET) == -1)
00359 goto error;
00360 buffer = (char *) xmalloc (pos * sizeof (char) + 1);
00361 len = fread (buffer, sizeof (char), pos, f);
00362 if (len != (size_t) pos
00363
00364
00365
00366 && ferror (f))
00367 goto error;
00368
00369 buffer[len] = '\0';
00370
00371 file_argv = buildargv (buffer);
00372
00373 if (!argv_dynamic)
00374 {
00375 *argvp = dupargv (*argvp);
00376 if (!*argvp)
00377 {
00378 fputs ("\nout of memory\n", stderr);
00379 xexit (1);
00380 }
00381 }
00382
00383 file_argc = 0;
00384 while (file_argv[file_argc] && *file_argv[file_argc])
00385 ++file_argc;
00386
00387
00388 *argvp = ((char **)
00389 xrealloc (*argvp,
00390 (*argcp + file_argc + 1) * sizeof (char *)));
00391 memmove (*argvp + i + file_argc, *argvp + i + 1,
00392 (*argcp - i) * sizeof (char *));
00393 memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
00394
00395
00396 *argcp += file_argc - 1;
00397
00398
00399
00400 free (file_argv);
00401 free (buffer);
00402
00403
00404 --i;
00405 error:
00406
00407 fclose (f);
00408 }
00409 }
00410
00411 #ifdef MAIN
00412
00413
00414
00415 static const char *const tests[] =
00416 {
00417 "a simple command line",
00418 "arg 'foo' is single quoted",
00419 "arg \"bar\" is double quoted",
00420 "arg \"foo bar\" has embedded whitespace",
00421 "arg 'Jack said \\'hi\\'' has single quotes",
00422 "arg 'Jack said \\\"hi\\\"' has double quotes",
00423 "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9",
00424
00425
00426 "trailing-whitespace ",
00427
00428 "",
00429 NULL
00430 };
00431
00432 int
00433 main (void)
00434 {
00435 char **argv;
00436 const char *const *test;
00437 char **targs;
00438
00439 for (test = tests; *test != NULL; test++)
00440 {
00441 printf ("buildargv(\"%s\")\n", *test);
00442 if ((argv = buildargv (*test)) == NULL)
00443 {
00444 printf ("failed!\n\n");
00445 }
00446 else
00447 {
00448 for (targs = argv; *targs != NULL; targs++)
00449 {
00450 printf ("\t\"%s\"\n", *targs);
00451 }
00452 printf ("\n");
00453 }
00454 freeargv (argv);
00455 }
00456
00457 return 0;
00458 }
00459
00460 #endif