|
1 /* |
|
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 |
|
27 /* |
|
28 * Converts a single string command line to the traditional argc, argv. |
|
29 * There are rules which govern the breaking of the the arguments, and |
|
30 * these rules are embodied in the regression tests below, and duplicated |
|
31 * in the jdk regression tests. |
|
32 */ |
|
33 |
|
34 #ifndef IDE_STANDALONE |
|
35 #include "java.h" |
|
36 #include "jli_util.h" |
|
37 #else /* IDE_STANDALONE */ |
|
38 // The defines we need for stand alone testing |
|
39 #include <stdio.h> |
|
40 #include <stdlib.h> |
|
41 #include <Windows.h> |
|
42 #define JNI_TRUE TRUE |
|
43 #define JNI_FALSE FALSE |
|
44 #define JLI_MemRealloc realloc |
|
45 #define JLI_StringDup _strdup |
|
46 #define JLI_MemFree free |
|
47 #define jboolean boolean |
|
48 typedef struct { |
|
49 char* arg; |
|
50 boolean has_wildcard; |
|
51 } StdArg ; |
|
52 #endif |
|
53 static StdArg *stdargs; |
|
54 static int stdargc; |
|
55 |
|
56 static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) { |
|
57 |
|
58 char* src = cmdline; |
|
59 char* dest = arg; |
|
60 jboolean separator = JNI_FALSE; |
|
61 int quotes = 0; |
|
62 int slashes = 0; |
|
63 |
|
64 char prev = 0; |
|
65 char ch = 0; |
|
66 int i; |
|
67 jboolean done = JNI_FALSE; |
|
68 |
|
69 *wildcard = JNI_FALSE; |
|
70 while ((ch = *src) != 0 && !done) { |
|
71 switch (ch) { |
|
72 case '"': |
|
73 if (separator) { |
|
74 done = JNI_TRUE; |
|
75 break; |
|
76 } |
|
77 if (prev == '\\') { |
|
78 for (i = 1; i < slashes; i += 2) { |
|
79 *dest++ = prev; |
|
80 } |
|
81 if (slashes % 2 == 1) { |
|
82 *dest++ = ch; |
|
83 } else { |
|
84 quotes++; |
|
85 } |
|
86 } else if (prev == '"' && quotes % 2 == 0) { |
|
87 quotes++; |
|
88 *dest++ = ch; // emit every other consecutive quote |
|
89 } else if (quotes == 0) { |
|
90 quotes++; // starting quote |
|
91 } else { |
|
92 quotes--; // matching quote |
|
93 } |
|
94 slashes = 0; |
|
95 break; |
|
96 |
|
97 case '\\': |
|
98 slashes++; |
|
99 if (separator) { |
|
100 done = JNI_TRUE; |
|
101 separator = JNI_FALSE; |
|
102 } |
|
103 break; |
|
104 |
|
105 case ' ': |
|
106 case '\t': |
|
107 if (quotes % 2 == 1) { |
|
108 *dest++ = ch; |
|
109 } else { |
|
110 separator = JNI_TRUE; |
|
111 } |
|
112 slashes = 0; |
|
113 break; |
|
114 |
|
115 case '*': |
|
116 case '?': |
|
117 if (separator) { |
|
118 done = JNI_TRUE; |
|
119 separator = JNI_FALSE; |
|
120 break; |
|
121 } |
|
122 if (quotes % 2 == 0) { |
|
123 *wildcard = JNI_TRUE; |
|
124 } |
|
125 if (prev == '\\') { |
|
126 *dest++ = prev; |
|
127 } |
|
128 *dest++ = ch; |
|
129 break; |
|
130 |
|
131 default: |
|
132 if (prev == '\\') { |
|
133 for (i = 0 ; i < slashes ; i++) { |
|
134 *dest++ = prev; |
|
135 } |
|
136 *dest++ = ch; |
|
137 } else if (separator) { |
|
138 done = JNI_TRUE; |
|
139 } else { |
|
140 *dest++ = ch; |
|
141 } |
|
142 slashes = 0; |
|
143 } |
|
144 |
|
145 if (!done) { |
|
146 prev = ch; |
|
147 src++; |
|
148 } |
|
149 } |
|
150 if (prev == '\\') { |
|
151 for (i = 0; i < slashes; i++) { |
|
152 *dest++ = prev; |
|
153 } |
|
154 } |
|
155 *dest = 0; |
|
156 return done ? src : NULL; |
|
157 } |
|
158 |
|
159 int JLI_GetStdArgc() { |
|
160 return stdargc; |
|
161 } |
|
162 |
|
163 StdArg* JLI_GetStdArgs() { |
|
164 return stdargs; |
|
165 } |
|
166 |
|
167 void JLI_CmdToArgs(char* cmdline) { |
|
168 int nargs = 0; |
|
169 StdArg* argv = NULL; |
|
170 jboolean wildcard = JNI_FALSE; |
|
171 char* src = cmdline; |
|
172 |
|
173 // allocate arg buffer with sufficient space to receive the largest arg |
|
174 char* arg = JLI_StringDup(cmdline); |
|
175 |
|
176 do { |
|
177 src = next_arg(src, arg, &wildcard); |
|
178 // resize to accommodate another Arg |
|
179 argv = (StdArg*) JLI_MemRealloc(argv, (nargs+1) * sizeof(StdArg)); |
|
180 argv[nargs].arg = JLI_StringDup(arg); |
|
181 argv[nargs].has_wildcard = wildcard; |
|
182 |
|
183 nargs++; |
|
184 } while (src != NULL); |
|
185 |
|
186 stdargc = nargs; |
|
187 stdargs = argv; |
|
188 } |
|
189 |
|
190 #ifdef IDE_STANDALONE |
|
191 void doexit(int rv) { |
|
192 printf("Hit any key to quit\n"); |
|
193 int c = getchar(); |
|
194 exit(rv); |
|
195 } |
|
196 |
|
197 void doabort() { |
|
198 doexit(1); |
|
199 } |
|
200 |
|
201 class Vector { |
|
202 public: |
|
203 char* cmdline; |
|
204 int argc; |
|
205 char* argv[10]; |
|
206 boolean wildcard[10]; |
|
207 boolean enabled; |
|
208 |
|
209 Vector(){} |
|
210 // Initialize our test vector with the program name, argv[0] |
|
211 // and the single string command line. |
|
212 Vector(char* pname, char* cline) { |
|
213 argv[0] = pname; |
|
214 wildcard[0] = FALSE; |
|
215 cmdline = cline; |
|
216 argc = 1; |
|
217 enabled = TRUE; |
|
218 } |
|
219 |
|
220 // add our expected strings, the program name has already been |
|
221 // added so ignore that |
|
222 void add(char* arg, boolean w) { |
|
223 argv[argc] = arg; |
|
224 wildcard[argc] = w; |
|
225 argc++; |
|
226 } |
|
227 |
|
228 void disable() { |
|
229 enabled = FALSE; |
|
230 } |
|
231 |
|
232 // validate the returned arguments with the expected arguments, using the |
|
233 // new CmdToArgs method. |
|
234 bool check() { |
|
235 // "pgmname" rest of cmdline ie. pgmname + 2 double quotes + space + cmdline from windows |
|
236 char* cptr = (char*) malloc(strlen(argv[0]) + sizeof(char) * 3 + strlen(cmdline) + 1); |
|
237 _snprintf(cptr, MAX_PATH, "\"%s\" %s", argv[0], cmdline); |
|
238 JLI_CmdToArgs(cptr); |
|
239 free(cptr); |
|
240 StdArg *kargv = JLI_GetStdArgs(); |
|
241 int kargc = JLI_GetStdArgc(); |
|
242 bool retval = true; |
|
243 printf("\n===========================\n"); |
|
244 printf("cmdline=%s\n", cmdline); |
|
245 if (argc != kargc) { |
|
246 printf("*** argument count does not match\n"); |
|
247 printme(); |
|
248 printtest(kargc, kargv); |
|
249 doabort(); |
|
250 } |
|
251 for (int i = 0 ; i < argc && retval == true ; i++) { |
|
252 if (strcmp(argv[i], kargv[i].arg) != 0) { |
|
253 printf("*** argument at [%d] don't match\n got: %s\n exp: %s\n", |
|
254 i, kargv[i].arg, argv[i]); |
|
255 doabort(); |
|
256 } |
|
257 } |
|
258 for (int i = 0 ; i < argc && retval == true ; i++) { |
|
259 if (wildcard[i] != kargv[i].has_wildcard) { |
|
260 printf("*** expansion flag at [%d] doesn't match\n got: %d\n exp: %d\n", |
|
261 i, kargv[i].has_wildcard, wildcard[i]); |
|
262 doabort(); |
|
263 } |
|
264 } |
|
265 for (int i = 0 ; i < kargc ; i++) { |
|
266 printf("k[%d]=%s\n", i, kargv[i].arg); |
|
267 printf(" [%d]=%s\n", i, argv[i]); |
|
268 } |
|
269 return retval; |
|
270 } |
|
271 void printtest(int kargc, StdArg* kargv) { |
|
272 for (int i = 0 ; i < kargc ; i++) { |
|
273 printf("k[%d]=%s\n", i, kargv[i].arg); |
|
274 } |
|
275 } |
|
276 void printme() { |
|
277 for (int i = 0 ; i < argc ; i++) { |
|
278 printf(" [%d]=%s\n", i, argv[i]); |
|
279 } |
|
280 } |
|
281 }; |
|
282 |
|
283 void dotest(Vector** vectors) { |
|
284 Vector* v = vectors[0]; |
|
285 for (int i = 0 ; v != NULL;) { |
|
286 if (v->enabled) { |
|
287 v->check(); |
|
288 } |
|
289 v = vectors[++i]; |
|
290 } |
|
291 } |
|
292 |
|
293 #define MAXV 128 |
|
294 int main(int argc, char* argv[]) { |
|
295 |
|
296 int n; |
|
297 for (n=1; n < argc; n++) { |
|
298 printf("%d %s\n", n, argv[n]); |
|
299 } |
|
300 if (n > 1) { |
|
301 JLI_CmdToArgs(GetCommandLine()); |
|
302 for (n = 0; n < stdargc; n++) { |
|
303 printf(" [%d]=%s\n", n, stdargs[n].arg); |
|
304 printf(" [%d]=%s\n", n, stdargs[n].has_wildcard ? "TRUE" : "FALSE"); |
|
305 } |
|
306 doexit(0); |
|
307 } |
|
308 |
|
309 Vector *vectors[MAXV]; |
|
310 |
|
311 memset(vectors, 0, sizeof(vectors)); |
|
312 int i = 0; |
|
313 Vector* v = new Vector(argv[0], "abcd"); |
|
314 v->add("abcd", FALSE); |
|
315 // v->disable(); |
|
316 vectors[i++] = v; |
|
317 |
|
318 |
|
319 v = new Vector(argv[0], "\"a b c d\""); |
|
320 v->add("a b c d", FALSE); |
|
321 // v->disable(); |
|
322 vectors[i++] = v; |
|
323 |
|
324 |
|
325 v = new Vector(argv[0], "a\"b c d\"e"); |
|
326 v->add("ab c de", FALSE); |
|
327 // v->disable(); |
|
328 vectors[i++] = v; |
|
329 |
|
330 |
|
331 v = new Vector(argv[0], "ab\\\"cd"); |
|
332 v->add("ab\"cd", FALSE); |
|
333 // v->disable(); |
|
334 vectors[i++] = v; |
|
335 |
|
336 |
|
337 v = new Vector(argv[0], "\"a b c d\\\\\""); |
|
338 v->add("a b c d\\", FALSE); |
|
339 // v->disable(); |
|
340 vectors[i++] = v; |
|
341 |
|
342 |
|
343 v = new Vector(argv[0], "ab\\\\\\\"cd"); |
|
344 v->add("ab\\\"cd", FALSE); |
|
345 // v->disable(); |
|
346 vectors[i++] = v; |
|
347 |
|
348 |
|
349 // Windows tests |
|
350 v = new Vector(argv[0], "a\\\\\\c"); |
|
351 v->add("a\\\\\\c", FALSE); |
|
352 // v->disable(); |
|
353 vectors[i++] = v; |
|
354 |
|
355 |
|
356 v = new Vector(argv[0], "\"a\\\\\\d\""); |
|
357 v->add("a\\\\\\d", FALSE); |
|
358 // v->disable(); |
|
359 vectors[i++] = v; |
|
360 |
|
361 |
|
362 v = new Vector(argv[0], "\"a b c\" d e"); |
|
363 v->add("a b c", FALSE); |
|
364 v->add("d", FALSE); |
|
365 v->add("e", FALSE); |
|
366 // v->disable(); |
|
367 vectors[i++] = v; |
|
368 |
|
369 |
|
370 v = new Vector(argv[0], "\"ab\\\"c\" \"\\\\\" d"); |
|
371 v->add("ab\"c", FALSE); |
|
372 v->add("\\", FALSE); |
|
373 v->add("d", FALSE); |
|
374 // v->disable(); |
|
375 vectors[i++] = v; |
|
376 |
|
377 |
|
378 v = new Vector(argv[0], "a\\\\\\c d\"e f\"g h"); |
|
379 v->add("a\\\\\\c", FALSE); |
|
380 v->add("de fg", FALSE); |
|
381 v->add("h", FALSE); |
|
382 // v->disable(); |
|
383 vectors[i++] = v; |
|
384 |
|
385 |
|
386 v = new Vector(argv[0], "a\\\\\\\"b c d"); |
|
387 v->add("a\\\"b", FALSE); // XXX "a\\\\\\\"b" |
|
388 v->add("c", FALSE); |
|
389 v->add("d", FALSE); |
|
390 // v->disable(); |
|
391 vectors[i++] = v; |
|
392 |
|
393 |
|
394 v = new Vector(argv[0], "a\\\\\\\\\"g c\" d e"); // XXX "a\\\\\\\\\"b c\" d e" |
|
395 v->add("a\\\\\g c", FALSE); // XXX "a\\\\\\\\\"b c" |
|
396 v->add("d", FALSE); |
|
397 v->add("e", FALSE); |
|
398 // v->disable(); |
|
399 vectors[i++] = v; |
|
400 |
|
401 |
|
402 // Additional tests |
|
403 v = new Vector(argv[0], "\"a b c\"\""); |
|
404 v->add("a b c\"", FALSE); |
|
405 // v->disable(); |
|
406 vectors[i++] = v; |
|
407 |
|
408 |
|
409 v = new Vector(argv[0], "\"\"a b c\"\""); |
|
410 v->add("a", FALSE); |
|
411 v->add("b", FALSE); |
|
412 v->add("c", FALSE); |
|
413 // v->disable(); |
|
414 vectors[i++] = v; |
|
415 |
|
416 |
|
417 v = new Vector(argv[0], "\"\"\"a b c\"\"\""); |
|
418 v->add("\"a b c\"", FALSE); |
|
419 // v->disable(); |
|
420 vectors[i++] = v; |
|
421 |
|
422 |
|
423 v = new Vector(argv[0], "\"\"\"\"a b c\"\"\"\""); |
|
424 v->add("\"a", FALSE); |
|
425 v->add("b", FALSE); |
|
426 v->add("c\"", FALSE); |
|
427 // v->disable(); |
|
428 vectors[i++] = v; |
|
429 |
|
430 |
|
431 v = new Vector(argv[0], "\"\"\"\"\"a b c\"\"\"\"\""); |
|
432 v->add("\"\"a b c\"\"", FALSE); |
|
433 // v->disable(); |
|
434 vectors[i++] = v; |
|
435 |
|
436 |
|
437 v = new Vector(argv[0], "\"C:\\TEST A\\\\\""); |
|
438 v->add("C:\\TEST A\\", FALSE); |
|
439 // v->disable(); |
|
440 vectors[i++] = v; |
|
441 |
|
442 |
|
443 v = new Vector(argv[0], "\"\"C:\\TEST A\\\\\"\""); |
|
444 v->add("C:\\TEST", FALSE); |
|
445 v->add("A\\", FALSE); |
|
446 // v->disable(); |
|
447 vectors[i++] = v; |
|
448 |
|
449 |
|
450 // test if a wildcard is present |
|
451 v = new Vector(argv[0], "abc*def"); |
|
452 v->add("abc*def", TRUE); |
|
453 // v->disable(); |
|
454 vectors[i++] = v; |
|
455 |
|
456 |
|
457 v = new Vector(argv[0], "\"abc*def\""); |
|
458 v->add("abc*def", FALSE); |
|
459 // v->disable(); |
|
460 vectors[i++] = v; |
|
461 |
|
462 |
|
463 v = new Vector(argv[0], "*.abc"); |
|
464 v->add("*.abc", TRUE); |
|
465 // v->disable(); |
|
466 vectors[i++] = v; |
|
467 |
|
468 |
|
469 v = new Vector(argv[0], "\"*.abc\""); |
|
470 v->add("*.abc", FALSE); |
|
471 // v->disable(); |
|
472 vectors[i++] = v; |
|
473 |
|
474 |
|
475 v = new Vector(argv[0], "x.???"); |
|
476 v->add("x.???", TRUE); |
|
477 // v->disable(); |
|
478 vectors[i++] = v; |
|
479 |
|
480 |
|
481 v = new Vector(argv[0], "\"x.???\""); |
|
482 v->add("x.???", FALSE); |
|
483 // v->disable(); |
|
484 vectors[i++] = v; |
|
485 |
|
486 |
|
487 v = new Vector(argv[0], "Debug\\*"); |
|
488 v->add("Debug\\*", TRUE); |
|
489 // v->disable(); |
|
490 vectors[i++] = v; |
|
491 |
|
492 |
|
493 v = new Vector(argv[0], "Debug\\f?a"); |
|
494 v->add("Debug\\f?a", TRUE); |
|
495 // v->disable(); |
|
496 vectors[i++] = v; |
|
497 |
|
498 |
|
499 v = new Vector(argv[0], "Debug\\?a.java"); |
|
500 v->add("Debug\\?a.java", TRUE); |
|
501 // v->disable(); |
|
502 vectors[i++] = v; |
|
503 |
|
504 |
|
505 v = new Vector(argv[0], "foo *.noexts"); |
|
506 v->add("foo", FALSE); |
|
507 v->add("*.noexts", TRUE); |
|
508 // v->disable(); |
|
509 vectors[i++] = v; |
|
510 |
|
511 |
|
512 v = new Vector(argv[0], "X\\Y\\Z"); |
|
513 v->add("X\\Y\\Z", FALSE); |
|
514 // v->disable(); |
|
515 vectors[i++] = v; |
|
516 |
|
517 |
|
518 v = new Vector(argv[0], "\\X\\Y\\Z"); |
|
519 v->add("\\X\\Y\\Z", FALSE); |
|
520 // v->disable(); |
|
521 vectors[i++] = v; |
|
522 |
|
523 |
|
524 v = new Vector(argv[0], "a b"); |
|
525 v->add("a", FALSE); |
|
526 v->add("b", FALSE); |
|
527 // v->disable(); |
|
528 vectors[i++] = v; |
|
529 |
|
530 |
|
531 v = new Vector(argv[0], "a\tb"); |
|
532 v->add("a", FALSE); |
|
533 v->add("b", FALSE); |
|
534 // v->disable(); |
|
535 vectors[i++] = v; |
|
536 |
|
537 |
|
538 v = new Vector(argv[0], "a \t b"); |
|
539 v->add("a", FALSE); |
|
540 v->add("b", FALSE); |
|
541 // v->disable(); |
|
542 vectors[i++] = v; |
|
543 |
|
544 v = new Vector(argv[0], "*\\"); |
|
545 v->add("*\\", TRUE); |
|
546 // v->disable(); |
|
547 vectors[i++] = v; |
|
548 |
|
549 v = new Vector(argv[0], "*/"); |
|
550 v->add("*/", TRUE); |
|
551 // v->disable(); |
|
552 vectors[i++] = v; |
|
553 |
|
554 v = new Vector(argv[0], ".\\*"); |
|
555 v->add(".\\*", TRUE); |
|
556 // v->disable(); |
|
557 vectors[i++] = v; |
|
558 |
|
559 v = new Vector(argv[0], "./*"); |
|
560 v->add("./*", TRUE); |
|
561 // v->disable(); |
|
562 vectors[i++] = v; |
|
563 |
|
564 v = new Vector(argv[0], ".\\*"); |
|
565 v->add(".\\*", TRUE); |
|
566 // v->disable(); |
|
567 vectors[i++] = v; |
|
568 |
|
569 v = new Vector(argv[0], ".//*"); |
|
570 v->add(".//*", TRUE); |
|
571 // v->disable(); |
|
572 vectors[i++] = v; |
|
573 |
|
574 v = new Vector(argv[0], "..\\..\\*"); |
|
575 v->add("..\\..\\*", TRUE); |
|
576 // v->disable(); |
|
577 vectors[i++] = v; |
|
578 |
|
579 v = new Vector(argv[0], "../../*"); |
|
580 v->add("../../*", TRUE); |
|
581 // v->disable(); |
|
582 vectors[i++] = v; |
|
583 |
|
584 v = new Vector(argv[0], "..\\..\\"); |
|
585 v->add("..\\..\\", FALSE); |
|
586 // v->disable(); |
|
587 vectors[i++] = v; |
|
588 |
|
589 v = new Vector(argv[0], "../../"); |
|
590 v->add("../../", FALSE); |
|
591 // v->disable(); |
|
592 vectors[i++] = v; |
|
593 |
|
594 dotest(vectors); |
|
595 printf("All tests pass [%d]\n", i); |
|
596 doexit(0); |
|
597 } |
|
598 #endif /* IDE_STANDALONE */ |