jdk/src/windows/bin/cmdtoargs.c
changeset 13410 e667545511c7
child 15523 cc0ee864bfb5
equal deleted inserted replaced
13409:fe3ab27ef1a6 13410:e667545511c7
       
     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 */