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 */