1 /* 2 * Copyright (c) 2012, 2015, 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 ptrdiff_t 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 = '\0'; 212 nargs++; 213 } while (src != NULL); 214 215 JLI_MemFree(arg); 216 217 stdargc = nargs; 218 stdargs = argv; 219 } 220 221 #ifdef IDE_STANDALONE 222 void doexit(int rv) { 223 printf("Hit any key to quit\n"); 224 int c = getchar(); 225 exit(rv); 226 } 227 228 void doabort() { 229 doexit(1); 230 } 231 232 class Vector { 233 public: 234 char* cmdline; 235 int argc; 236 char* argv[10]; 237 boolean wildcard[10]; 238 boolean enabled; 239 240 Vector(){} 241 // Initialize our test vector with the program name, argv[0] 242 // and the single string command line. 243 Vector(char* pname, char* cline) { 244 argv[0] = pname; 245 wildcard[0] = FALSE; 246 cmdline = cline; 247 argc = 1; 248 enabled = TRUE; 249 } 250 251 // add our expected strings, the program name has already been 252 // added so ignore that 253 void add(char* arg, boolean w) { 254 argv[argc] = arg; 255 wildcard[argc] = w; 256 argc++; 257 } 258 259 void disable() { 260 enabled = FALSE; 261 } 262 263 // validate the returned arguments with the expected arguments, using the 264 // new CmdToArgs method. 265 bool check() { 266 // "pgmname" rest of cmdline ie. pgmname + 2 double quotes + space + cmdline from windows 267 char* cptr = (char*) malloc(strlen(argv[0]) + sizeof(char) * 3 + strlen(cmdline) + 1); 268 _snprintf(cptr, MAX_PATH, "\"%s\" %s", argv[0], cmdline); 269 JLI_CmdToArgs(cptr); 270 free(cptr); 271 StdArg *kargv = JLI_GetStdArgs(); 272 int kargc = JLI_GetStdArgc(); 273 bool retval = true; 274 printf("\n===========================\n"); 275 printf("cmdline=%s\n", cmdline); 276 if (argc != kargc) { 277 printf("*** argument count does not match\n"); 278 printme(); 279 printtest(kargc, kargv); 280 doabort(); 281 } 282 for (int i = 0 ; i < argc && retval == true ; i++) { 283 if (strcmp(argv[i], kargv[i].arg) != 0) { 284 printf("*** argument at [%d] don't match\n got: %s\n exp: %s\n", 285 i, kargv[i].arg, argv[i]); 286 doabort(); 287 } 288 } 289 for (int i = 0 ; i < argc && retval == true ; i++) { 290 if (wildcard[i] != kargv[i].has_wildcard) { 291 printf("*** expansion flag at [%d] doesn't match\n got: %d\n exp: %d\n", 292 i, kargv[i].has_wildcard, wildcard[i]); 293 doabort(); 294 } 295 } 296 for (int i = 0 ; i < kargc ; i++) { 297 printf("k[%d]=%s\n", i, kargv[i].arg); 298 printf(" [%d]=%s\n", i, argv[i]); 299 } 300 return retval; 301 } 302 void printtest(int kargc, StdArg* kargv) { 303 for (int i = 0 ; i < kargc ; i++) { 304 printf("k[%d]=%s\n", i, kargv[i].arg); 305 } 306 } 307 void printme() { 308 for (int i = 0 ; i < argc ; i++) { 309 printf(" [%d]=%s\n", i, argv[i]); 310 } 311 } 312 }; 313 314 void dotest(Vector** vectors) { 315 Vector* v = vectors[0]; 316 for (int i = 0 ; v != NULL;) { 317 if (v->enabled) { 318 v->check(); 319 } 320 v = vectors[++i]; 321 } 322 } 323 324 #define MAXV 128 325 int main(int argc, char* argv[]) { 326 327 int n; 328 for (n=1; n < argc; n++) { 329 printf("%d %s\n", n, argv[n]); 330 } 331 if (n > 1) { 332 JLI_CmdToArgs(GetCommandLine()); 333 for (n = 0; n < stdargc; n++) { 334 printf(" [%d]=%s\n", n, stdargs[n].arg); 335 printf(" [%d]=%s\n", n, stdargs[n].has_wildcard ? "TRUE" : "FALSE"); 336 } 337 doexit(0); 338 } 339 340 Vector *vectors[MAXV]; 341 342 memset(vectors, 0, sizeof(vectors)); 343 int i = 0; 344 Vector* v = new Vector(argv[0], "abcd"); 345 v->add("abcd", FALSE); 346 // v->disable(); 347 vectors[i++] = v; 348 349 350 v = new Vector(argv[0], "\"a b c d\""); 351 v->add("a b c d", FALSE); 352 // v->disable(); 353 vectors[i++] = v; 354 355 356 v = new Vector(argv[0], "a\"b c d\"e"); 357 v->add("ab c de", FALSE); 358 // v->disable(); 359 vectors[i++] = v; 360 361 362 v = new Vector(argv[0], "ab\\\"cd"); 363 v->add("ab\"cd", FALSE); 364 // v->disable(); 365 vectors[i++] = v; 366 367 368 v = new Vector(argv[0], "\"a b c d\\\\\""); 369 v->add("a b c d\\", FALSE); 370 // v->disable(); 371 vectors[i++] = v; 372 373 374 v = new Vector(argv[0], "ab\\\\\\\"cd"); 375 v->add("ab\\\"cd", FALSE); 376 // v->disable(); 377 vectors[i++] = v; 378 379 380 // Windows tests 381 v = new Vector(argv[0], "a\\\\\\c"); 382 v->add("a\\\\\\c", FALSE); 383 // v->disable(); 384 vectors[i++] = v; 385 386 387 v = new Vector(argv[0], "\"a\\\\\\d\""); 388 v->add("a\\\\\\d", FALSE); 389 // v->disable(); 390 vectors[i++] = v; 391 392 393 v = new Vector(argv[0], "\"a b c\" d e"); 394 v->add("a b c", FALSE); 395 v->add("d", FALSE); 396 v->add("e", FALSE); 397 // v->disable(); 398 vectors[i++] = v; 399 400 401 v = new Vector(argv[0], "\"ab\\\"c\" \"\\\\\" d"); 402 v->add("ab\"c", FALSE); 403 v->add("\\", FALSE); 404 v->add("d", FALSE); 405 // v->disable(); 406 vectors[i++] = v; 407 408 409 v = new Vector(argv[0], "a\\\\\\c d\"e f\"g h"); 410 v->add("a\\\\\\c", FALSE); 411 v->add("de fg", FALSE); 412 v->add("h", FALSE); 413 // v->disable(); 414 vectors[i++] = v; 415 416 417 v = new Vector(argv[0], "a\\\\\\\"b c d"); 418 v->add("a\\\"b", FALSE); // XXX "a\\\\\\\"b" 419 v->add("c", FALSE); 420 v->add("d", FALSE); 421 // v->disable(); 422 vectors[i++] = v; 423 424 425 v = new Vector(argv[0], "a\\\\\\\\\"g c\" d e"); // XXX "a\\\\\\\\\"b c\" d e" 426 v->add("a\\\\\g c", FALSE); // XXX "a\\\\\\\\\"b c" 427 v->add("d", FALSE); 428 v->add("e", FALSE); 429 // v->disable(); 430 vectors[i++] = v; 431 432 433 // Additional tests 434 v = new Vector(argv[0], "\"a b c\"\""); 435 v->add("a b c\"", FALSE); 436 // v->disable(); 437 vectors[i++] = v; 438 439 440 v = new Vector(argv[0], "\"\"a b c\"\""); 441 v->add("a", FALSE); 442 v->add("b", FALSE); 443 v->add("c", FALSE); 444 // v->disable(); 445 vectors[i++] = v; 446 447 448 v = new Vector(argv[0], "\"\"\"a b c\"\"\""); 449 v->add("\"a b c\"", FALSE); 450 // v->disable(); 451 vectors[i++] = v; 452 453 454 v = new Vector(argv[0], "\"\"\"\"a b c\"\"\"\""); 455 v->add("\"a", FALSE); 456 v->add("b", FALSE); 457 v->add("c\"", FALSE); 458 // v->disable(); 459 vectors[i++] = v; 460 461 462 v = new Vector(argv[0], "\"\"\"\"\"a b c\"\"\"\"\""); 463 v->add("\"\"a b c\"\"", FALSE); 464 // v->disable(); 465 vectors[i++] = v; 466 467 468 v = new Vector(argv[0], "\"C:\\TEST A\\\\\""); 469 v->add("C:\\TEST A\\", FALSE); 470 // v->disable(); 471 vectors[i++] = v; 472 473 474 v = new Vector(argv[0], "\"\"C:\\TEST A\\\\\"\""); 475 v->add("C:\\TEST", FALSE); 476 v->add("A\\", FALSE); 477 // v->disable(); 478 vectors[i++] = v; 479 480 481 // test if a wildcard is present 482 v = new Vector(argv[0], "abc*def"); 483 v->add("abc*def", TRUE); 484 // v->disable(); 485 vectors[i++] = v; 486 487 488 v = new Vector(argv[0], "\"abc*def\""); 489 v->add("abc*def", FALSE); 490 // v->disable(); 491 vectors[i++] = v; 492 493 494 v = new Vector(argv[0], "*.abc"); 495 v->add("*.abc", TRUE); 496 // v->disable(); 497 vectors[i++] = v; 498 499 500 v = new Vector(argv[0], "\"*.abc\""); 501 v->add("*.abc", FALSE); 502 // v->disable(); 503 vectors[i++] = v; 504 505 506 v = new Vector(argv[0], "x.???"); 507 v->add("x.???", TRUE); 508 // v->disable(); 509 vectors[i++] = v; 510 511 512 v = new Vector(argv[0], "\"x.???\""); 513 v->add("x.???", FALSE); 514 // v->disable(); 515 vectors[i++] = v; 516 517 518 v = new Vector(argv[0], "Debug\\*"); 519 v->add("Debug\\*", TRUE); 520 // v->disable(); 521 vectors[i++] = v; 522 523 524 v = new Vector(argv[0], "Debug\\f?a"); 525 v->add("Debug\\f?a", TRUE); 526 // v->disable(); 527 vectors[i++] = v; 528 529 530 v = new Vector(argv[0], "Debug\\?a.java"); 531 v->add("Debug\\?a.java", TRUE); 532 // v->disable(); 533 vectors[i++] = v; 534 535 536 v = new Vector(argv[0], "foo *.noexts"); 537 v->add("foo", FALSE); 538 v->add("*.noexts", TRUE); 539 // v->disable(); 540 vectors[i++] = v; 541 542 543 v = new Vector(argv[0], "X\\Y\\Z"); 544 v->add("X\\Y\\Z", FALSE); 545 // v->disable(); 546 vectors[i++] = v; 547 548 549 v = new Vector(argv[0], "\\X\\Y\\Z"); 550 v->add("\\X\\Y\\Z", FALSE); 551 // v->disable(); 552 vectors[i++] = v; 553 554 555 v = new Vector(argv[0], "a b"); 556 v->add("a", FALSE); 557 v->add("b", FALSE); 558 // v->disable(); 559 vectors[i++] = v; 560 561 562 v = new Vector(argv[0], "a\tb"); 563 v->add("a", FALSE); 564 v->add("b", FALSE); 565 // v->disable(); 566 vectors[i++] = v; 567 568 569 v = new Vector(argv[0], "a \t b"); 570 v->add("a", FALSE); 571 v->add("b", FALSE); 572 // v->disable(); 573 vectors[i++] = v; 574 575 v = new Vector(argv[0], "*\\"); 576 v->add("*\\", TRUE); 577 // v->disable(); 578 vectors[i++] = v; 579 580 v = new Vector(argv[0], "*/"); 581 v->add("*/", TRUE); 582 // v->disable(); 583 vectors[i++] = v; 584 585 v = new Vector(argv[0], ".\\*"); 586 v->add(".\\*", TRUE); 587 // v->disable(); 588 vectors[i++] = v; 589 590 v = new Vector(argv[0], "./*"); 591 v->add("./*", TRUE); 592 // v->disable(); 593 vectors[i++] = v; 594 595 v = new Vector(argv[0], ".\\*"); 596 v->add(".\\*", TRUE); 597 // v->disable(); 598 vectors[i++] = v; 599 600 v = new Vector(argv[0], ".//*"); 601 v->add(".//*", TRUE); 602 // v->disable(); 603 vectors[i++] = v; 604 605 v = new Vector(argv[0], "..\\..\\*"); 606 v->add("..\\..\\*", TRUE); 607 // v->disable(); 608 vectors[i++] = v; 609 610 v = new Vector(argv[0], "../../*"); 611 v->add("../../*", TRUE); 612 // v->disable(); 613 vectors[i++] = v; 614 615 v = new Vector(argv[0], "..\\..\\"); 616 v->add("..\\..\\", FALSE); 617 // v->disable(); 618 vectors[i++] = v; 619 620 v = new Vector(argv[0], "../../"); 621 v->add("../../", FALSE); 622 // v->disable(); 623 vectors[i++] = v; 624 625 v= new Vector(argv[0], "a b\\\\ d"); 626 v->add("a", FALSE); 627 v->add("b\\\\", FALSE); 628 v->add("d", FALSE); 629 vectors[i++] = v; 630 631 v= new Vector(argv[0], "\\\\?"); 632 v->add("\\\\?", TRUE); 633 vectors[i++] = v; 634 635 v= new Vector(argv[0], "\\\\*"); 636 v->add("\\\\*", TRUE); 637 vectors[i++] = v; 638 639 dotest(vectors); 640 printf("All tests pass [%d]\n", i); 641 doexit(0); 642 } 643 #endif /* IDE_STANDALONE */