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