Skip to content

Commit 0413eba

Browse files
[GR-55690] [GR-55692] [GR-55693] Misc fixes for espresso launchers.
PullRequest: graal/18363
2 parents d60e894 + 78b9770 commit 0413eba

File tree

5 files changed

+273
-120
lines changed

5 files changed

+273
-120
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright (c) 2024, 2024, 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package com.oracle.truffle.espresso.launcher;
24+
25+
import static com.oracle.truffle.espresso.launcher.ArgFileParser.State.FIND_NEXT;
26+
import static com.oracle.truffle.espresso.launcher.ArgFileParser.State.IN_COMMENT;
27+
import static com.oracle.truffle.espresso.launcher.ArgFileParser.State.IN_ESCAPE;
28+
import static com.oracle.truffle.espresso.launcher.ArgFileParser.State.IN_QUOTE;
29+
import static com.oracle.truffle.espresso.launcher.ArgFileParser.State.IN_TOKEN;
30+
import static com.oracle.truffle.espresso.launcher.ArgFileParser.State.SKIP_LEAD_WS;
31+
32+
import java.io.IOException;
33+
import java.io.Reader;
34+
import java.util.function.Consumer;
35+
36+
/**
37+
* Parse {@code @arg-files} as handled by libjli. See libjli/args.c.
38+
*/
39+
public final class ArgFileParser {
40+
private final Reader reader;
41+
42+
protected enum State {
43+
FIND_NEXT,
44+
IN_COMMENT,
45+
IN_QUOTE,
46+
IN_ESCAPE,
47+
SKIP_LEAD_WS,
48+
IN_TOKEN
49+
}
50+
51+
public ArgFileParser(Reader reader) {
52+
this.reader = reader;
53+
}
54+
55+
public void parse(Consumer<String> argConsumer) throws IOException {
56+
String token;
57+
while ((token = nextToken()) != null) {
58+
argConsumer.accept(token);
59+
}
60+
}
61+
62+
@SuppressWarnings("fallthrough")
63+
private String nextToken() throws IOException {
64+
State state = FIND_NEXT;
65+
int currentQuoteChar = -1;
66+
int ch;
67+
StringBuilder sb = new StringBuilder();
68+
charloop: while ((ch = reader.read()) >= 0) {
69+
// Skip white space characters
70+
if (state == FIND_NEXT || state == SKIP_LEAD_WS) {
71+
while (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f') {
72+
ch = reader.read();
73+
if (ch < 0) {
74+
break charloop;
75+
}
76+
}
77+
state = (state == FIND_NEXT) ? IN_TOKEN : IN_QUOTE;
78+
// Deal with escape sequences
79+
} else if (state == IN_ESCAPE) {
80+
// concatenation directive
81+
if (ch == '\n' || ch == '\r') {
82+
state = SKIP_LEAD_WS;
83+
} else {
84+
// escaped character
85+
switch (ch) {
86+
case 'n':
87+
sb.append('\n');
88+
break;
89+
case 'r':
90+
sb.append('\r');
91+
break;
92+
case 't':
93+
sb.append('\t');
94+
break;
95+
case 'f':
96+
sb.append('\f');
97+
break;
98+
default:
99+
sb.append((char) ch);
100+
break;
101+
}
102+
state = IN_QUOTE;
103+
}
104+
continue;
105+
// ignore comment to EOL
106+
} else if (state == IN_COMMENT) {
107+
while (ch != '\n' && ch != '\r') {
108+
ch = reader.read();
109+
if (ch < 0) {
110+
break charloop;
111+
}
112+
}
113+
state = FIND_NEXT;
114+
continue;
115+
}
116+
117+
assert (state != IN_ESCAPE);
118+
assert (state != FIND_NEXT);
119+
assert (state != SKIP_LEAD_WS);
120+
assert (state != IN_COMMENT);
121+
122+
switch (ch) {
123+
case ' ':
124+
case '\t':
125+
case '\f':
126+
if (state == IN_QUOTE) {
127+
sb.append((char) ch);
128+
continue;
129+
}
130+
// fallthrough
131+
case '\n':
132+
case '\r':
133+
return sb.toString();
134+
case '#':
135+
if (state == IN_QUOTE) {
136+
sb.append((char) ch);
137+
continue;
138+
}
139+
state = IN_COMMENT;
140+
break;
141+
case '\\':
142+
if (state != IN_QUOTE) {
143+
sb.append((char) ch);
144+
continue;
145+
}
146+
state = IN_ESCAPE;
147+
break;
148+
case '\'':
149+
case '"':
150+
if (state == IN_QUOTE && currentQuoteChar != ch) {
151+
// not matching quote
152+
sb.append((char) ch);
153+
continue;
154+
}
155+
// anchor after quote character
156+
if (state == IN_TOKEN) {
157+
currentQuoteChar = ch;
158+
state = IN_QUOTE;
159+
} else {
160+
state = IN_TOKEN;
161+
}
162+
break;
163+
default:
164+
sb.append((char) ch);
165+
break;
166+
}
167+
}
168+
if (sb.isEmpty()) {
169+
return null;
170+
}
171+
return sb.toString();
172+
}
173+
}

espresso/src/com.oracle.truffle.espresso.launcher/src/com/oracle/truffle/espresso/launcher/EspressoLauncher.java

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@
2222
*/
2323
package com.oracle.truffle.espresso.launcher;
2424

25+
import java.io.BufferedReader;
2526
import java.io.File;
2627
import java.io.IOException;
28+
import java.nio.file.Files;
29+
import java.nio.file.Path;
30+
import java.nio.file.Paths;
2731
import java.util.ArrayList;
2832
import java.util.HashMap;
2933
import java.util.List;
@@ -176,7 +180,9 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
176180
ArrayList<String> unrecognized = new ArrayList<>();
177181
boolean isRelaxStaticObjectSafetyChecksSet = false;
178182

179-
Arguments args = new Arguments(arguments);
183+
List<String> expandedArguments = expandAtFiles(arguments);
184+
185+
Arguments args = new Arguments(expandedArguments);
180186
while (args.next()) {
181187
String arg = args.getKey();
182188
switch (arg) {
@@ -347,7 +353,7 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
347353

348354
mainClassName = getMainClassName(jarFileName);
349355
}
350-
buildJvmArgs(arguments, args.getNumberOfProcessedArgs());
356+
buildJvmArgs(expandedArguments, args.getNumberOfProcessedArgs());
351357
args.pushLeftoversArgs();
352358
break;
353359
}
@@ -361,14 +367,12 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
361367
if (classpath == null) {
362368
// (3) the environment variable CLASSPATH
363369
classpath = System.getenv("CLASSPATH");
364-
if (classpath == null) {
365-
// (4) the current working directory only
366-
classpath = ".";
367-
}
368370
}
369371
}
370372

371-
espressoOptions.put("java.Classpath", classpath);
373+
if (classpath != null) {
374+
espressoOptions.put("java.Classpath", classpath);
375+
}
372376

373377
if (!isRelaxStaticObjectSafetyChecksSet) {
374378
// Since Espresso has a verifier, the Static Object Model does not need to perform shape
@@ -380,6 +384,32 @@ protected List<String> preprocessArguments(List<String> arguments, Map<String, S
380384
return unrecognized;
381385
}
382386

387+
private List<String> expandAtFiles(List<String> arguments) {
388+
List<String> expanded = null;
389+
for (int i = 0; i < arguments.size(); i++) {
390+
String arg = arguments.get(i);
391+
if (arg.startsWith("@")) {
392+
if (expanded == null) {
393+
expanded = new ArrayList<>(arguments.subList(0, i));
394+
}
395+
parseArgFile(arg.substring(1, arg.length()), expanded);
396+
} else if (expanded != null) {
397+
expanded.add(arg);
398+
}
399+
}
400+
return expanded == null ? arguments : expanded;
401+
}
402+
403+
private void parseArgFile(String pathArg, List<String> expanded) {
404+
Path argFilePath = Paths.get(pathArg);
405+
try {
406+
BufferedReader reader = Files.newBufferedReader(argFilePath);
407+
new ArgFileParser(reader).parse(expanded::add);
408+
} catch (IOException e) {
409+
throw abort(new RuntimeException("Cannot open @argfile", e), 1);
410+
}
411+
}
412+
383413
private void handleXXArg(String fullArg, ArrayList<String> unrecognized) {
384414
String arg = fullArg.substring("-XX:".length());
385415
String name;

espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/Arguments.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ public static int setupContext(Context.Builder builder, JNIJavaVMInitArgs args)
174174
} else if (optionString.startsWith("--enable-native-access=")) {
175175
handler.enableNativeAccess(optionString.substring("--enable-native-access=".length()));
176176
} else if (optionString.startsWith("--module-path=")) {
177-
builder.option(JAVA_PROPS + "jdk.module.path", optionString.substring("--module-path=".length()));
177+
builder.option("java.ModulePath", optionString.substring("--module-path=".length()));
178178
} else if (optionString.startsWith("--upgrade-module-path=")) {
179179
builder.option(JAVA_PROPS + "jdk.module.upgrade.path", optionString.substring("--upgrade-module-path=".length()));
180180
} else if (optionString.startsWith("--limit-modules=")) {

0 commit comments

Comments
 (0)