1 /* 2 * Copyright (c) 2012, 2013, 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 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 int copyCh(USHORT ch, char* dest) { 57 if (HIBYTE(ch) == 0) { 58 *dest = (char)ch; 59 return 1; 60 } else { 61 *((USHORT *)dest) = ch; 62 return 2; 63 } 64 } 65 66 static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) { 67 68 char* src = cmdline; 69 char* dest = arg; 70 jboolean separator = JNI_FALSE; 71 int quotes = 0; 72 int slashes = 0; 73 74 // "prev"/"ch" may contain either a single byte, or a double byte 75 // character encoded in CP_ACP. 76 USHORT prev = 0; 77 USHORT ch = 0; 78 int i; 79 jboolean done = JNI_FALSE; 80 int charLength; 81 82 *wildcard = JNI_FALSE; 83 while (!done) { 84 charLength = CharNextExA(CP_ACP, src, 0) - src; 85 if (charLength == 0) { 86 break; 87 } else if (charLength == 1) { 88 ch = (USHORT)(UCHAR)src[0]; 89 } else { 90 ch = ((USHORT *)src)[0]; 91 } 92 93 switch (ch) { 94 case L'"': 95 if (separator) { 96 done = JNI_TRUE; 97 break; 98 } 99 if (prev == L'\\') { 100 for (i = 1; i < slashes; i += 2) { 101 dest += copyCh(prev, dest); 102 } 103 if (slashes % 2 == 1) { 104 dest += copyCh(ch, dest); 105 } else { 106 quotes++; 107 } 108 } else if (prev == L'"' && quotes % 2 == 0) { 109 quotes++; 110 dest += copyCh(ch, dest); // emit every other consecutive quote 111 } else if (quotes == 0) { 112 quotes++; // starting quote 113 } else { 114 quotes--; // matching quote 115 } 116 slashes = 0; 117 break; 118 119 case L'\\': 120 slashes++; 121 if (separator) { 122 done = JNI_TRUE; 123 separator = JNI_FALSE; 124 } 125 break; 126 127 case L' ': 128 case L'\t': 129 if (prev == L'\\') { 130 for (i = 0 ; i < slashes; i++) { 131 dest += copyCh(prev, dest); 132 } 133 } 134 if (quotes % 2 == 1) { 135 dest += copyCh(ch, dest); 136 } else { 137 separator = JNI_TRUE; 138 } 139 slashes = 0; 140 break; 141 142 case L'*': 143 case L'?': 144 if (separator) { 145 done = JNI_TRUE; 146 separator = JNI_FALSE; 147 break; 148 } 149 if (quotes % 2 == 0) { 150 *wildcard = JNI_TRUE; 151 } 152 if (prev == L'\\') { 153 for (i = 0 ; i < slashes ; i++) { 154 dest += copyCh(prev, dest); 155 } 156 } 157 dest += copyCh(ch, dest); 158 break; 159 160 default: 161 if (prev == L'\\') { 162 for (i = 0 ; i < slashes ; i++) { 163 dest += copyCh(prev, dest); 164 } 165 dest += copyCh(ch, dest); 166 } else if (separator) { 167 done = JNI_TRUE; 168 } else { 169 dest += copyCh(ch, dest); 170 } 171 slashes = 0; 172 } 173 174 if (!done) { 175 prev = ch; 176 src += charLength; 177 } 178 } 179 if (prev == L'\\') { 180 for (i = 0; i < slashes; i++) { 181 dest += copyCh(prev, dest); 182 } 183 } 184 *dest = 0; 185 return done ? src : NULL; 186 } 187 188 int JLI_GetStdArgc() { 189 return stdargc; 190 } 191 192 StdArg* JLI_GetStdArgs() { 193 return stdargs; 194 } 195 196 void JLI_CmdToArgs(char* cmdline) { 197 int nargs = 0; 198 StdArg* argv = NULL; 199 jboolean wildcard = JNI_FALSE; 200 char* src = cmdline; 201 202 // allocate arg buffer with sufficient space to receive the largest arg 203 char* arg = JLI_StringDup(cmdline); 204 205 do { 206 src = next_arg(src, arg, &wildcard); 207 // resize to accommodate another Arg 208 argv = (StdArg*) JLI_MemRealloc(argv, (nargs+1) * sizeof(StdArg)); 209 argv[nargs].arg = JLI_StringDup(arg); 210 argv[nargs].has_wildcard = wildcard; 211 *arg = NULL; 212 nargs++; 213 } while (src != NULL); 214 215 stdargc = nargs; 216 stdargs = argv; 217 } 218 219 #ifdef IDE_STANDALONE 220 void doexit(int rv) { 221 printf("Hit any key to quit\n"); 222 int c = getchar(); 223 exit(rv); 224 } 225 226 void doabort() { 227 doexit(1); 228 } 229 230 class Vector { 231 public: 232 char* cmdline; 233 int argc; 234 char* argv[10]; 235 boolean wildcard[10]; 236 boolean enabled; 237 238 Vector(){} 239 // Initialize our test vector with the program name, argv[0] 240 // and the single string command line. 241 Vector(char* pname, char* cline) { 242 argv[0] = pname; 243 wildcard[0] = FALSE; 244 cmdline = cline; 245 argc = 1; 246 enabled = TRUE; 247 } 248 249 // add our expected strings, the program name has already been 250 // added so ignore that 251 void add(char* arg, boolean w) { 252 argv[argc] = arg; 253 wildcard[argc] = w; 254 argc++; 255 } 256 257 void disable() { 258 enabled = FALSE; 259 } 260 261 // validate the returned arguments with the expected arguments, using the 262 // new CmdToArgs method. 263 bool check() { 264 // "pgmname" rest of cmdline ie. pgmname + 2 double quotes + space + cmdline from windows 265 char* cptr = (char*) malloc(strlen(argv[0]) + sizeof(char) * 3 + strlen(cmdline) + 1); 266 _snprintf(cptr, MAX_PATH, "\"%s\" %s", argv[0], cmdline); 267 JLI_CmdToArgs(cptr); 268 free(cptr); 269 StdArg *kargv = JLI_GetStdArgs(); 270 int kargc = JLI_GetStdArgc(); 271 bool retval = true; 272 printf("\n===========================\n"); 273 printf("cmdline=%s\n", cmdline); 274 if (argc != kargc) { 275 printf("*** argument count does not match\n"); 276 printme(); 277 printtest(kargc, kargv); 278 doabort(); 279 } 280 for (int i = 0 ; i < argc && retval == true ; i++) { 281 if (strcmp(argv[i], kargv[i].arg) != 0) { 282 printf("*** argument at [%d] don't match\n got: %s\n exp: %s\n", 283 i, kargv[i].arg, argv[i]); 284 doabort(); 285 } 286 } 287 for (int i = 0 ; i < argc && retval == true ; i++) { 288 if (wildcard[i] != kargv[i].has_wildcard) { 289 printf("*** expansion flag at [%d] doesn't match\n got: %d\n exp: %d\n", 290 i, kargv[i].has_wildcard, wildcard[i]); 291 doabort(); 292 } 293 } 294 for (int i = 0 ; i < kargc ; i++) { 295 printf("k[%d]=%s\n", i, kargv[i].arg); 296 printf(" [%d]=%s\n", i, argv[i]); 297 } 298 return retval; 299 } 300 void printtest(int kargc, StdArg* kargv) { 301 for (int i = 0 ; i < kargc ; i++) { 302 printf("k[%d]=%s\n", i, kargv[i].arg); 303 } 304 } 305 void printme() { 306 for (int i = 0 ; i < argc ; i++) { 307 printf(" [%d]=%s\n", i, argv[i]); 308 } 309 } 310 }; 311 312 void dotest(Vector** vectors) { 313 Vector* v = vectors[0]; 314 for (int i = 0 ; v != NULL;) { 315 if (v->enabled) { 316 v->check(); 317 } 318 v = vectors[++i]; 319 } 320 } 321 322 #define MAXV 128 323 int main(int argc, char* argv[]) { 324 325 int n; 326 for (n=1; n < argc; n++) { 327 printf("%d %s\n", n, argv[n]); 328 } 329 if (n > 1) { 330 JLI_CmdToArgs(GetCommandLine()); 331 for (n = 0; n < stdargc; n++) { 332 printf(" [%d]=%s\n", n, stdargs[n].arg); 333 printf(" [%d]=%s\n", n, stdargs[n].has_wildcard ? "TRUE" : "FALSE"); 334 } 335 doexit(0); 336 } 337 338 Vector *vectors[MAXV]; 339 340 memset(vectors, 0, sizeof(vectors)); 341 int i = 0; 342 Vector* v = new Vector(argv[0], "abcd"); 343 v->add("abcd", FALSE); 344 // v->disable(); 345 vectors[i++] = v; 346 347 348 v = new Vector(argv[0], "\"a b c d\""); 349 v->add("a b c d", FALSE); 350 // v->disable(); 351 vectors[i++] = v; 352 353 354 v = new Vector(argv[0], "a\"b c d\"e"); 355 v->add("ab c de", FALSE); 356 // v->disable(); 357 vectors[i++] = v; 358 359 360 v = new Vector(argv[0], "ab\\\"cd"); 361 v->add("ab\"cd", FALSE); 362 // v->disable(); 363 vectors[i++] = v; 364 365 366 v = new Vector(argv[0], "\"a b c d\\\\\""); 367 v->add("a b c d\\", FALSE); 368 // v->disable(); 369 vectors[i++] = v; 370 371 372 v = new Vector(argv[0], "ab\\\\\\\"cd"); 373 v->add("ab\\\"cd", FALSE); 374 // v->disable(); 375 vectors[i++] = v; 376 377 378 // Windows tests 379 v = new Vector(argv[0], "a\\\\\\c"); 380 v->add("a\\\\\\c", FALSE); 381 // v->disable(); 382 vectors[i++] = v; 383 384 385 v = new Vector(argv[0], "\"a\\\\\\d\""); 386 v->add("a\\\\\\d", FALSE); 387 // v->disable(); 388 vectors[i++] = v; 389 390 391 v = new Vector(argv[0], "\"a b c\" d e"); 392 v->add("a b c", FALSE); 393 v->add("d", FALSE); 394 v->add("e", FALSE); 395 // v->disable(); 396 vectors[i++] = v; 397 398 399 v = new Vector(argv[0], "\"ab\\\"c\" \"\\\\\" d"); 400 v->add("ab\"c", FALSE); 401 v->add("\\", FALSE); 402 v->add("d", FALSE); 403 // v->disable(); 404 vectors[i++] = v; 405 406 407 v = new Vector(argv[0], "a\\\\\\c d\"e f\"g h"); 408 v->add("a\\\\\\c", FALSE); 409 v->add("de fg", FALSE); 410 v->add("h", FALSE); 411 // v->disable(); 412 vectors[i++] = v; 413 414 415 v = new Vector(argv[0], "a\\\\\\\"b c d"); 416 v->add("a\\\"b", FALSE); // XXX "a\\\\\\\"b" 417 v->add("c", FALSE); 418 v->add("d", FALSE); 419 // v->disable(); 420 vectors[i++] = v; 421 422 423 v = new Vector(argv[0], "a\\\\\\\\\"g c\" d e"); // XXX "a\\\\\\\\\"b c\" d e" 424 v->add("a\\\\\g c", FALSE); // XXX "a\\\\\\\\\"b c" 425 v->add("d", FALSE); 426 v->add("e", FALSE); 427 // v->disable(); 428 vectors[i++] = v; 429 430 431 // Additional tests 432 v = new Vector(argv[0], "\"a b c\"\""); 433 v->add("a b c\"", FALSE); 434 // v->disable(); 435 vectors[i++] = v; 436 437 438 v = new Vector(argv[0], "\"\"a b c\"\""); 439 v->add("a", FALSE); 440 v->add("b", FALSE); 441 v->add("c", FALSE); 442 // v->disable(); 443 vectors[i++] = v; 444 445 446 v = new Vector(argv[0], "\"\"\"a b c\"\"\""); 447 v->add("\"a b c\"", FALSE); 448 // v->disable(); 449 vectors[i++] = v; 450 451 452 v = new Vector(argv[0], "\"\"\"\"a b c\"\"\"\""); 453 v->add("\"a", FALSE); 454 v->add("b", FALSE); 455 v->add("c\"", FALSE); 456 // v->disable(); 457 vectors[i++] = v; 458 459 460 v = new Vector(argv[0], "\"\"\"\"\"a b c\"\"\"\"\""); 461 v->add("\"\"a b c\"\"", FALSE); 462 // v->disable(); 463 vectors[i++] = v; 464 465 466 v = new Vector(argv[0], "\"C:\\TEST A\\\\\""); 467 v->add("C:\\TEST A\\", FALSE); 468 // v->disable(); 469 vectors[i++] = v; 470 471 472 v = new Vector(argv[0], "\"\"C:\\TEST A\\\\\"\""); 473 v->add("C:\\TEST", FALSE); 474 v->add("A\\", FALSE); 475 // v->disable(); 476 vectors[i++] = v; 477 478 479 // test if a wildcard is present 480 v = new Vector(argv[0], "abc*def"); 481 v->add("abc*def", TRUE); 482 // v->disable(); 483 vectors[i++] = v; 484 485 486 v = new Vector(argv[0], "\"abc*def\""); 487 v->add("abc*def", FALSE); 488 // v->disable(); 489 vectors[i++] = v; 490 491 492 v = new Vector(argv[0], "*.abc"); 493 v->add("*.abc", TRUE); 494 // v->disable(); 495 vectors[i++] = v; 496 497 498 v = new Vector(argv[0], "\"*.abc\""); 499 v->add("*.abc", FALSE); 500 // v->disable(); 501 vectors[i++] = v; 502 503 504 v = new Vector(argv[0], "x.???"); 505 v->add("x.???", TRUE); 506 // v->disable(); 507 vectors[i++] = v; 508 509 510 v = new Vector(argv[0], "\"x.???\""); 511 v->add("x.???", FALSE); 512 // v->disable(); 513 vectors[i++] = v; 514 515 516 v = new Vector(argv[0], "Debug\\*"); 517 v->add("Debug\\*", TRUE); 518 // v->disable(); 519 vectors[i++] = v; 520 521 522 v = new Vector(argv[0], "Debug\\f?a"); 523 v->add("Debug\\f?a", TRUE); 524 // v->disable(); 525 vectors[i++] = v; 526 527 528 v = new Vector(argv[0], "Debug\\?a.java"); 529 v->add("Debug\\?a.java", TRUE); 530 // v->disable(); 531 vectors[i++] = v; 532 533 534 v = new Vector(argv[0], "foo *.noexts"); 535 v->add("foo", FALSE); 536 v->add("*.noexts", TRUE); 537 // v->disable(); 538 vectors[i++] = v; 539 540 541 v = new Vector(argv[0], "X\\Y\\Z"); 542 v->add("X\\Y\\Z", FALSE); 543 // v->disable(); 544 vectors[i++] = v; 545 546 547 v = new Vector(argv[0], "\\X\\Y\\Z"); 548 v->add("\\X\\Y\\Z", FALSE); 549 // v->disable(); 550 vectors[i++] = v; 551 552 553 v = new Vector(argv[0], "a b"); 554 v->add("a", FALSE); 555 v->add("b", FALSE); 556 // v->disable(); 557 vectors[i++] = v; 558 559 560 v = new Vector(argv[0], "a\tb"); 561 v->add("a", FALSE); 562 v->add("b", FALSE); 563 // v->disable(); 564 vectors[i++] = v; 565 566 567 v = new Vector(argv[0], "a \t b"); 568 v->add("a", FALSE); 569 v->add("b", FALSE); 570 // v->disable(); 571 vectors[i++] = v; 572 573 v = new Vector(argv[0], "*\\"); 574 v->add("*\\", TRUE); 575 // v->disable(); 576 vectors[i++] = v; 577 578 v = new Vector(argv[0], "*/"); 579 v->add("*/", TRUE); 580 // v->disable(); 581 vectors[i++] = v; 582 583 v = new Vector(argv[0], ".\\*"); 584 v->add(".\\*", TRUE); 585 // v->disable(); 586 vectors[i++] = v; 587 588 v = new Vector(argv[0], "./*"); 589 v->add("./*", TRUE); 590 // v->disable(); 591 vectors[i++] = v; 592 593 v = new Vector(argv[0], ".\\*"); 594 v->add(".\\*", TRUE); 595 // v->disable(); 596 vectors[i++] = v; 597 598 v = new Vector(argv[0], ".//*"); 599 v->add(".//*", TRUE); 600 // v->disable(); 601 vectors[i++] = v; 602 603 v = new Vector(argv[0], "..\\..\\*"); 604 v->add("..\\..\\*", TRUE); 605 // v->disable(); 606 vectors[i++] = v; 607 608 v = new Vector(argv[0], "../../*"); 609 v->add("../../*", TRUE); 610 // v->disable(); 611 vectors[i++] = v; 612 613 v = new Vector(argv[0], "..\\..\\"); 614 v->add("..\\..\\", FALSE); 615 // v->disable(); 616 vectors[i++] = v; 617 618 v = new Vector(argv[0], "../../"); 619 v->add("../../", FALSE); 620 // v->disable(); 621 vectors[i++] = v; 622 623 v= new Vector(argv[0], "a b\\\\ d"); 624 v->add("a", FALSE); 625 v->add("b\\\\", FALSE); 626 v->add("d", FALSE); 627 vectors[i++] = v; 628 629 v= new Vector(argv[0], "\\\\?"); 630 v->add("\\\\?", TRUE); 631 vectors[i++] = v; 632 633 v= new Vector(argv[0], "\\\\*"); 634 v->add("\\\\*", TRUE); 635 vectors[i++] = v; 636 637 dotest(vectors); 638 printf("All tests pass [%d]\n", i); 639 doexit(0); 640 } 641 #endif /* IDE_STANDALONE */