5269N/A/*
5668N/A * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
5269N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5269N/A *
5269N/A * This code is free software; you can redistribute it and/or modify it
5269N/A * under the terms of the GNU General Public License version 2 only, as
5269N/A * published by the Free Software Foundation. Oracle designates this
5269N/A * particular file as subject to the "Classpath" exception as provided
5269N/A * by Oracle in the LICENSE file that accompanied this code.
5269N/A *
5269N/A * This code is distributed in the hope that it will be useful, but WITHOUT
5269N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5269N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
5269N/A * version 2 for more details (a copy is included in the LICENSE file that
5269N/A * accompanied this code).
5269N/A *
5269N/A * You should have received a copy of the GNU General Public License version
5269N/A * 2 along with this work; if not, write to the Free Software Foundation,
5269N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5269N/A *
5269N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
5269N/A * or visit www.oracle.com if you need additional information or have any
5269N/A * questions.
5269N/A */
5269N/A
5269N/A
5269N/A/*
5269N/A * Converts a single string command line to the traditional argc, argv.
5269N/A * There are rules which govern the breaking of the the arguments, and
5269N/A * these rules are embodied in the regression tests below, and duplicated
5269N/A * in the jdk regression tests.
5269N/A */
5269N/A
5269N/A#ifndef IDE_STANDALONE
5269N/A#include "java.h"
5269N/A#include "jli_util.h"
5269N/A#else /* IDE_STANDALONE */
5269N/A// The defines we need for stand alone testing
5269N/A#include <stdio.h>
5269N/A#include <stdlib.h>
5269N/A#include <Windows.h>
5269N/A#define JNI_TRUE TRUE
5269N/A#define JNI_FALSE FALSE
5269N/A#define JLI_MemRealloc realloc
5269N/A#define JLI_StringDup _strdup
5269N/A#define JLI_MemFree free
5269N/A#define jboolean boolean
5269N/Atypedef struct {
5269N/A char* arg;
5269N/A boolean has_wildcard;
5269N/A} StdArg ;
5269N/A#endif
5269N/Astatic StdArg *stdargs;
5269N/Astatic int stdargc;
5269N/A
5269N/Astatic char* next_arg(char* cmdline, char* arg, jboolean* wildcard) {
5269N/A
5269N/A char* src = cmdline;
5269N/A char* dest = arg;
5269N/A jboolean separator = JNI_FALSE;
5269N/A int quotes = 0;
5269N/A int slashes = 0;
5269N/A
5269N/A char prev = 0;
5269N/A char ch = 0;
5269N/A int i;
5269N/A jboolean done = JNI_FALSE;
5269N/A
5269N/A *wildcard = JNI_FALSE;
5269N/A while ((ch = *src) != 0 && !done) {
5269N/A switch (ch) {
5269N/A case '"':
5269N/A if (separator) {
5269N/A done = JNI_TRUE;
5269N/A break;
5269N/A }
5269N/A if (prev == '\\') {
5269N/A for (i = 1; i < slashes; i += 2) {
5269N/A *dest++ = prev;
5269N/A }
5269N/A if (slashes % 2 == 1) {
5269N/A *dest++ = ch;
5269N/A } else {
5269N/A quotes++;
5269N/A }
5269N/A } else if (prev == '"' && quotes % 2 == 0) {
5269N/A quotes++;
5269N/A *dest++ = ch; // emit every other consecutive quote
5269N/A } else if (quotes == 0) {
5269N/A quotes++; // starting quote
5269N/A } else {
5269N/A quotes--; // matching quote
5269N/A }
5269N/A slashes = 0;
5269N/A break;
5269N/A
5269N/A case '\\':
5269N/A slashes++;
5269N/A if (separator) {
5269N/A done = JNI_TRUE;
5269N/A separator = JNI_FALSE;
5269N/A }
5269N/A break;
5269N/A
5269N/A case ' ':
5269N/A case '\t':
5668N/A if (prev == '\\') {
5668N/A for (i = 0 ; i < slashes; i++) {
5668N/A *dest++ = prev;
5668N/A }
5668N/A }
5269N/A if (quotes % 2 == 1) {
5269N/A *dest++ = ch;
5269N/A } else {
5269N/A separator = JNI_TRUE;
5269N/A }
5269N/A slashes = 0;
5269N/A break;
5269N/A
5269N/A case '*':
5269N/A case '?':
5269N/A if (separator) {
5269N/A done = JNI_TRUE;
5269N/A separator = JNI_FALSE;
5269N/A break;
5269N/A }
5269N/A if (quotes % 2 == 0) {
5269N/A *wildcard = JNI_TRUE;
5269N/A }
5269N/A if (prev == '\\') {
6109N/A for (i = 0 ; i < slashes ; i++) {
6109N/A *dest++ = prev;
6109N/A }
5269N/A }
5269N/A *dest++ = ch;
5269N/A break;
5269N/A
5269N/A default:
5269N/A if (prev == '\\') {
5269N/A for (i = 0 ; i < slashes ; i++) {
5269N/A *dest++ = prev;
5269N/A }
5269N/A *dest++ = ch;
5269N/A } else if (separator) {
5269N/A done = JNI_TRUE;
5269N/A } else {
5269N/A *dest++ = ch;
5269N/A }
5269N/A slashes = 0;
5269N/A }
5269N/A
5269N/A if (!done) {
5269N/A prev = ch;
5269N/A src++;
5269N/A }
5269N/A }
5269N/A if (prev == '\\') {
5269N/A for (i = 0; i < slashes; i++) {
5269N/A *dest++ = prev;
5269N/A }
5269N/A }
5269N/A *dest = 0;
5269N/A return done ? src : NULL;
5269N/A}
5269N/A
5269N/Aint JLI_GetStdArgc() {
5269N/A return stdargc;
5269N/A}
5269N/A
5269N/AStdArg* JLI_GetStdArgs() {
5269N/A return stdargs;
5269N/A}
5269N/A
5269N/Avoid JLI_CmdToArgs(char* cmdline) {
5269N/A int nargs = 0;
5269N/A StdArg* argv = NULL;
5269N/A jboolean wildcard = JNI_FALSE;
5269N/A char* src = cmdline;
5269N/A
5269N/A // allocate arg buffer with sufficient space to receive the largest arg
5269N/A char* arg = JLI_StringDup(cmdline);
5269N/A
5269N/A do {
5269N/A src = next_arg(src, arg, &wildcard);
5269N/A // resize to accommodate another Arg
5269N/A argv = (StdArg*) JLI_MemRealloc(argv, (nargs+1) * sizeof(StdArg));
5269N/A argv[nargs].arg = JLI_StringDup(arg);
5269N/A argv[nargs].has_wildcard = wildcard;
6109N/A *arg = NULL;
5269N/A nargs++;
5269N/A } while (src != NULL);
5269N/A
5269N/A stdargc = nargs;
5269N/A stdargs = argv;
5269N/A}
5269N/A
5269N/A#ifdef IDE_STANDALONE
5269N/Avoid doexit(int rv) {
5269N/A printf("Hit any key to quit\n");
5269N/A int c = getchar();
5269N/A exit(rv);
5269N/A}
5269N/A
5269N/Avoid doabort() {
5269N/A doexit(1);
5269N/A}
5269N/A
5269N/Aclass Vector {
5269N/Apublic:
5269N/A char* cmdline;
5269N/A int argc;
5269N/A char* argv[10];
5269N/A boolean wildcard[10];
5269N/A boolean enabled;
5269N/A
5269N/A Vector(){}
5269N/A // Initialize our test vector with the program name, argv[0]
5269N/A // and the single string command line.
5269N/A Vector(char* pname, char* cline) {
5269N/A argv[0] = pname;
5269N/A wildcard[0] = FALSE;
5269N/A cmdline = cline;
5269N/A argc = 1;
5269N/A enabled = TRUE;
5269N/A }
5269N/A
5269N/A // add our expected strings, the program name has already been
5269N/A // added so ignore that
5269N/A void add(char* arg, boolean w) {
5269N/A argv[argc] = arg;
5269N/A wildcard[argc] = w;
5269N/A argc++;
5269N/A }
5269N/A
5269N/A void disable() {
5269N/A enabled = FALSE;
5269N/A }
5269N/A
5269N/A // validate the returned arguments with the expected arguments, using the
5269N/A // new CmdToArgs method.
5269N/A bool check() {
5269N/A // "pgmname" rest of cmdline ie. pgmname + 2 double quotes + space + cmdline from windows
5269N/A char* cptr = (char*) malloc(strlen(argv[0]) + sizeof(char) * 3 + strlen(cmdline) + 1);
5269N/A _snprintf(cptr, MAX_PATH, "\"%s\" %s", argv[0], cmdline);
5269N/A JLI_CmdToArgs(cptr);
5269N/A free(cptr);
5269N/A StdArg *kargv = JLI_GetStdArgs();
5269N/A int kargc = JLI_GetStdArgc();
5269N/A bool retval = true;
5269N/A printf("\n===========================\n");
5269N/A printf("cmdline=%s\n", cmdline);
5269N/A if (argc != kargc) {
5269N/A printf("*** argument count does not match\n");
5269N/A printme();
5269N/A printtest(kargc, kargv);
5269N/A doabort();
5269N/A }
5269N/A for (int i = 0 ; i < argc && retval == true ; i++) {
5269N/A if (strcmp(argv[i], kargv[i].arg) != 0) {
5269N/A printf("*** argument at [%d] don't match\n got: %s\n exp: %s\n",
5269N/A i, kargv[i].arg, argv[i]);
5269N/A doabort();
5269N/A }
5269N/A }
5269N/A for (int i = 0 ; i < argc && retval == true ; i++) {
5269N/A if (wildcard[i] != kargv[i].has_wildcard) {
5269N/A printf("*** expansion flag at [%d] doesn't match\n got: %d\n exp: %d\n",
5269N/A i, kargv[i].has_wildcard, wildcard[i]);
5269N/A doabort();
5269N/A }
5269N/A }
5269N/A for (int i = 0 ; i < kargc ; i++) {
5269N/A printf("k[%d]=%s\n", i, kargv[i].arg);
5269N/A printf(" [%d]=%s\n", i, argv[i]);
5269N/A }
5269N/A return retval;
5269N/A }
5269N/A void printtest(int kargc, StdArg* kargv) {
5269N/A for (int i = 0 ; i < kargc ; i++) {
5269N/A printf("k[%d]=%s\n", i, kargv[i].arg);
5269N/A }
5269N/A }
5269N/A void printme() {
5269N/A for (int i = 0 ; i < argc ; i++) {
5269N/A printf(" [%d]=%s\n", i, argv[i]);
5269N/A }
5269N/A }
5269N/A};
5269N/A
5269N/Avoid dotest(Vector** vectors) {
5269N/A Vector* v = vectors[0];
5269N/A for (int i = 0 ; v != NULL;) {
5269N/A if (v->enabled) {
5269N/A v->check();
5269N/A }
5269N/A v = vectors[++i];
5269N/A }
5269N/A}
5269N/A
5269N/A#define MAXV 128
5269N/Aint main(int argc, char* argv[]) {
5269N/A
5269N/A int n;
5269N/A for (n=1; n < argc; n++) {
5269N/A printf("%d %s\n", n, argv[n]);
5269N/A }
5269N/A if (n > 1) {
5269N/A JLI_CmdToArgs(GetCommandLine());
5269N/A for (n = 0; n < stdargc; n++) {
5269N/A printf(" [%d]=%s\n", n, stdargs[n].arg);
5269N/A printf(" [%d]=%s\n", n, stdargs[n].has_wildcard ? "TRUE" : "FALSE");
5269N/A }
5269N/A doexit(0);
5269N/A }
5269N/A
5269N/A Vector *vectors[MAXV];
5269N/A
5269N/A memset(vectors, 0, sizeof(vectors));
5269N/A int i = 0;
5269N/A Vector* v = new Vector(argv[0], "abcd");
5269N/A v->add("abcd", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"a b c d\"");
5269N/A v->add("a b c d", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "a\"b c d\"e");
5269N/A v->add("ab c de", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "ab\\\"cd");
5269N/A v->add("ab\"cd", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"a b c d\\\\\"");
5269N/A v->add("a b c d\\", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "ab\\\\\\\"cd");
5269N/A v->add("ab\\\"cd", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A // Windows tests
5269N/A v = new Vector(argv[0], "a\\\\\\c");
5269N/A v->add("a\\\\\\c", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"a\\\\\\d\"");
5269N/A v->add("a\\\\\\d", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"a b c\" d e");
5269N/A v->add("a b c", FALSE);
5269N/A v->add("d", FALSE);
5269N/A v->add("e", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"ab\\\"c\" \"\\\\\" d");
5269N/A v->add("ab\"c", FALSE);
5269N/A v->add("\\", FALSE);
5269N/A v->add("d", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "a\\\\\\c d\"e f\"g h");
5269N/A v->add("a\\\\\\c", FALSE);
5269N/A v->add("de fg", FALSE);
5269N/A v->add("h", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "a\\\\\\\"b c d");
5269N/A v->add("a\\\"b", FALSE); // XXX "a\\\\\\\"b"
5269N/A v->add("c", FALSE);
5269N/A v->add("d", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "a\\\\\\\\\"g c\" d e"); // XXX "a\\\\\\\\\"b c\" d e"
5269N/A v->add("a\\\\\g c", FALSE); // XXX "a\\\\\\\\\"b c"
5269N/A v->add("d", FALSE);
5269N/A v->add("e", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A // Additional tests
5269N/A v = new Vector(argv[0], "\"a b c\"\"");
5269N/A v->add("a b c\"", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"\"a b c\"\"");
5269N/A v->add("a", FALSE);
5269N/A v->add("b", FALSE);
5269N/A v->add("c", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"\"\"a b c\"\"\"");
5269N/A v->add("\"a b c\"", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"\"\"\"a b c\"\"\"\"");
5269N/A v->add("\"a", FALSE);
5269N/A v->add("b", FALSE);
5269N/A v->add("c\"", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"\"\"\"\"a b c\"\"\"\"\"");
5269N/A v->add("\"\"a b c\"\"", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"C:\\TEST A\\\\\"");
5269N/A v->add("C:\\TEST A\\", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"\"C:\\TEST A\\\\\"\"");
5269N/A v->add("C:\\TEST", FALSE);
5269N/A v->add("A\\", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A // test if a wildcard is present
5269N/A v = new Vector(argv[0], "abc*def");
5269N/A v->add("abc*def", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"abc*def\"");
5269N/A v->add("abc*def", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "*.abc");
5269N/A v->add("*.abc", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"*.abc\"");
5269N/A v->add("*.abc", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "x.???");
5269N/A v->add("x.???", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\"x.???\"");
5269N/A v->add("x.???", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "Debug\\*");
5269N/A v->add("Debug\\*", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "Debug\\f?a");
5269N/A v->add("Debug\\f?a", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "Debug\\?a.java");
5269N/A v->add("Debug\\?a.java", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "foo *.noexts");
5269N/A v->add("foo", FALSE);
5269N/A v->add("*.noexts", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "X\\Y\\Z");
5269N/A v->add("X\\Y\\Z", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "\\X\\Y\\Z");
5269N/A v->add("\\X\\Y\\Z", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "a b");
5269N/A v->add("a", FALSE);
5269N/A v->add("b", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "a\tb");
5269N/A v->add("a", FALSE);
5269N/A v->add("b", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A
5269N/A v = new Vector(argv[0], "a \t b");
5269N/A v->add("a", FALSE);
5269N/A v->add("b", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], "*\\");
5269N/A v->add("*\\", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], "*/");
5269N/A v->add("*/", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], ".\\*");
5269N/A v->add(".\\*", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], "./*");
5269N/A v->add("./*", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], ".\\*");
5269N/A v->add(".\\*", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], ".//*");
5269N/A v->add(".//*", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], "..\\..\\*");
5269N/A v->add("..\\..\\*", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], "../../*");
5269N/A v->add("../../*", TRUE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], "..\\..\\");
5269N/A v->add("..\\..\\", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5269N/A v = new Vector(argv[0], "../../");
5269N/A v->add("../../", FALSE);
5269N/A // v->disable();
5269N/A vectors[i++] = v;
5269N/A
5668N/A v= new Vector(argv[0], "a b\\\\ d");
5668N/A v->add("a", FALSE);
5668N/A v->add("b\\\\", FALSE);
5668N/A v->add("d", FALSE);
5668N/A vectors[i++] = v;
5668N/A
6109N/A v= new Vector(argv[0], "\\\\?");
6109N/A v->add("\\\\?", TRUE);
6109N/A vectors[i++] = v;
6109N/A
6109N/A v= new Vector(argv[0], "\\\\*");
6109N/A v->add("\\\\*", TRUE);
6109N/A vectors[i++] = v;
6109N/A
5269N/A dotest(vectors);
5269N/A printf("All tests pass [%d]\n", i);
5269N/A doexit(0);
5269N/A}
5269N/A#endif /* IDE_STANDALONE */