Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/CommandLineParser.java
38867 views
1
/*
2
* Copyright (c) 2010, 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
package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
26
27
import java.util.*;
28
/*
29
* @author jrose
30
*/
31
public class CommandLineParser {
32
33
public CommandLineParser(String optionString) {
34
setOptionMap(optionString);
35
}
36
TreeMap<String, String[]> optionMap;
37
38
public void setOptionMap(String options) {
39
// Convert options string into optLines dictionary.
40
TreeMap<String, String[]> optmap = new TreeMap<String, String[]>();
41
loadOptmap:
42
for (String optline : options.split("\n")) {
43
String[] words = optline.split("\\p{Space}+");
44
if (words.length == 0) {
45
continue loadOptmap;
46
}
47
String opt = words[0];
48
words[0] = ""; // initial word is not a spec
49
if (opt.length() == 0 && words.length >= 1) {
50
opt = words[1]; // initial "word" is empty due to leading ' '
51
words[1] = "";
52
}
53
if (opt.length() == 0) {
54
continue loadOptmap;
55
}
56
String[] prevWords = optmap.put(opt, words);
57
if (prevWords != null) {
58
throw new RuntimeException("duplicate option: "
59
+ optline.trim());
60
}
61
}
62
optionMap = optmap;
63
}
64
65
public String getOptionMap() {
66
TreeMap<String, String[]> optmap = optionMap;
67
StringBuffer sb = new StringBuffer();
68
for (String opt : optmap.keySet()) {
69
sb.append(opt);
70
for (String spec : optmap.get(opt)) {
71
sb.append(' ').append(spec);
72
}
73
sb.append('\n');
74
}
75
return sb.toString();
76
}
77
78
/**
79
* Remove a set of command-line options from args,
80
* storing them in the properties map in a canonicalized form.
81
*/
82
public String parse(List<String> args, Map<String, String> properties) {
83
//System.out.println(args+" // "+properties);
84
85
String resultString = null;
86
TreeMap<String, String[]> optmap = optionMap;
87
88
// State machine for parsing a command line.
89
ListIterator<String> argp = args.listIterator();
90
ListIterator<String> pbp = new ArrayList<String>().listIterator();
91
doArgs:
92
for (;;) {
93
// One trip through this loop per argument.
94
// Multiple trips per option only if several options per argument.
95
String arg;
96
if (pbp.hasPrevious()) {
97
arg = pbp.previous();
98
pbp.remove();
99
} else if (argp.hasNext()) {
100
arg = argp.next();
101
} else {
102
// No more arguments at all.
103
break doArgs;
104
}
105
tryOpt:
106
for (int optlen = arg.length();; optlen--) {
107
// One time through this loop for each matching arg prefix.
108
String opt;
109
// Match some prefix of the argument to a key in optmap.
110
findOpt:
111
for (;;) {
112
opt = arg.substring(0, optlen);
113
if (optmap.containsKey(opt)) {
114
break findOpt;
115
}
116
if (optlen == 0) {
117
break tryOpt;
118
}
119
// Decide on a smaller prefix to search for.
120
SortedMap<String, String[]> pfxmap = optmap.headMap(opt);
121
// pfxmap.lastKey is no shorter than any prefix in optmap.
122
int len = pfxmap.isEmpty() ? 0 : pfxmap.lastKey().length();
123
optlen = Math.min(len, optlen - 1);
124
opt = arg.substring(0, optlen);
125
// (Note: We could cut opt down to its common prefix with
126
// pfxmap.lastKey, but that wouldn't save many cycles.)
127
}
128
opt = opt.intern();
129
assert (arg.startsWith(opt));
130
assert (opt.length() == optlen);
131
String val = arg.substring(optlen); // arg == opt+val
132
133
// Execute the option processing specs for this opt.
134
// If no actions are taken, then look for a shorter prefix.
135
boolean didAction = false;
136
boolean isError = false;
137
138
int pbpMark = pbp.nextIndex(); // in case of backtracking
139
String[] specs = optmap.get(opt);
140
eachSpec:
141
for (String spec : specs) {
142
if (spec.length() == 0) {
143
continue eachSpec;
144
}
145
if (spec.startsWith("#")) {
146
break eachSpec;
147
}
148
int sidx = 0;
149
char specop = spec.charAt(sidx++);
150
151
// Deal with '+'/'*' prefixes (spec conditions).
152
boolean ok;
153
switch (specop) {
154
case '+':
155
// + means we want an non-empty val suffix.
156
ok = (val.length() != 0);
157
specop = spec.charAt(sidx++);
158
break;
159
case '*':
160
// * means we accept empty or non-empty
161
ok = true;
162
specop = spec.charAt(sidx++);
163
break;
164
default:
165
// No condition prefix means we require an exact
166
// match, as indicated by an empty val suffix.
167
ok = (val.length() == 0);
168
break;
169
}
170
if (!ok) {
171
continue eachSpec;
172
}
173
174
String specarg = spec.substring(sidx);
175
switch (specop) {
176
case '.': // terminate the option sequence
177
resultString = (specarg.length() != 0) ? specarg.intern() : opt;
178
break doArgs;
179
case '?': // abort the option sequence
180
resultString = (specarg.length() != 0) ? specarg.intern() : arg;
181
isError = true;
182
break eachSpec;
183
case '@': // change the effective opt name
184
opt = specarg.intern();
185
break;
186
case '>': // shift remaining arg val to next arg
187
pbp.add(specarg + val); // push a new argument
188
val = "";
189
break;
190
case '!': // negation option
191
String negopt = (specarg.length() != 0) ? specarg.intern() : opt;
192
properties.remove(negopt);
193
properties.put(negopt, null); // leave placeholder
194
didAction = true;
195
break;
196
case '$': // normal "boolean" option
197
String boolval;
198
if (specarg.length() != 0) {
199
// If there is a given spec token, store it.
200
boolval = specarg;
201
} else {
202
String old = properties.get(opt);
203
if (old == null || old.length() == 0) {
204
boolval = "1";
205
} else {
206
// Increment any previous value as a numeral.
207
boolval = "" + (1 + Integer.parseInt(old));
208
}
209
}
210
properties.put(opt, boolval);
211
didAction = true;
212
break;
213
case '=': // "string" option
214
case '&': // "collection" option
215
// Read an option.
216
boolean append = (specop == '&');
217
String strval;
218
if (pbp.hasPrevious()) {
219
strval = pbp.previous();
220
pbp.remove();
221
} else if (argp.hasNext()) {
222
strval = argp.next();
223
} else {
224
resultString = arg + " ?";
225
isError = true;
226
break eachSpec;
227
}
228
if (append) {
229
String old = properties.get(opt);
230
if (old != null) {
231
// Append new val to old with embedded delim.
232
String delim = specarg;
233
if (delim.length() == 0) {
234
delim = " ";
235
}
236
strval = old + specarg + strval;
237
}
238
}
239
properties.put(opt, strval);
240
didAction = true;
241
break;
242
default:
243
throw new RuntimeException("bad spec for "
244
+ opt + ": " + spec);
245
}
246
}
247
248
// Done processing specs.
249
if (didAction && !isError) {
250
continue doArgs;
251
}
252
253
// The specs should have done something, but did not.
254
while (pbp.nextIndex() > pbpMark) {
255
// Remove anything pushed during these specs.
256
pbp.previous();
257
pbp.remove();
258
}
259
260
if (isError) {
261
throw new IllegalArgumentException(resultString);
262
}
263
264
if (optlen == 0) {
265
// We cannot try a shorter matching option.
266
break tryOpt;
267
}
268
}
269
270
// If we come here, there was no matching option.
271
// So, push back the argument, and return to caller.
272
pbp.add(arg);
273
break doArgs;
274
}
275
// Report number of arguments consumed.
276
args.subList(0, argp.nextIndex()).clear();
277
// Report any unconsumed partial argument.
278
while (pbp.hasPrevious()) {
279
args.add(0, pbp.previous());
280
}
281
//System.out.println(args+" // "+properties+" -> "+resultString);
282
return resultString;
283
}
284
}
285
286