Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/sourcetools/j9constantpool/com/ibm/oti/VMCPTool/PrimaryItem.java
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2004, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
package com.ibm.oti.VMCPTool;
23
24
import java.io.PrintWriter;
25
import java.util.ArrayList;
26
import java.util.List;
27
import java.util.Set;
28
import java.util.StringTokenizer;
29
import java.util.regex.Matcher;
30
import java.util.regex.Pattern;
31
32
import org.w3c.dom.Element;
33
import org.w3c.dom.Node;
34
import org.w3c.dom.NodeList;
35
36
public abstract class PrimaryItem {
37
protected final Alias primary;
38
private final Alias[] aliases;
39
40
protected abstract String cMacroName();
41
42
protected PrimaryItem(Element e, String nodeName, Alias.Factory factory) {
43
primary = factory.alias(e, null);
44
aliases = aliases(e, nodeName, primary, factory);
45
}
46
47
private static String[] attribute(Element e, String name) {
48
StringTokenizer tok = new StringTokenizer(e.getAttribute(name), ",");
49
if (tok.hasMoreTokens()) {
50
String[] attributes = new String[tok.countTokens()];
51
for (int i = 0; tok.hasMoreTokens(); ++i) {
52
attributes[i] = tok.nextToken();
53
}
54
return attributes;
55
} else {
56
return null;
57
}
58
}
59
60
protected static VersionRange[] versions(Element e, Alias proto) {
61
VersionRange[] ranges;
62
String[] versions = attribute(e, "versions");
63
64
if (versions != null) {
65
int length = versions.length;
66
67
ranges = new VersionRange[length];
68
69
for (int i = 0; i < length; ++i) {
70
ranges[i] = VersionRange.parse(versions[i]);
71
}
72
} else if (proto != null) {
73
ranges = proto.versions;
74
} else {
75
ranges = VersionRange.ALL;
76
}
77
78
return ranges;
79
}
80
81
private static final String[] NO_FLAGS = new String[0];
82
83
protected static String[] flags(Element e, Alias proto) {
84
String[] flags = attribute(e, "flags");
85
if (flags == null) {
86
flags = proto != null ? proto.flags : NO_FLAGS;
87
}
88
return flags;
89
}
90
91
protected static String attribute(Element e, String name, String ifAbsent) {
92
return e.hasAttribute(name) ? e.getAttribute(name) : ifAbsent;
93
}
94
95
protected static final class VersionRange {
96
97
protected static final VersionRange[] ALL = new VersionRange[] { new VersionRange(0, Integer.MAX_VALUE) };
98
99
protected static final VersionRange[] NONE = new VersionRange[] { new VersionRange(0, -1) };
100
101
private static final Pattern PATTERN = Pattern.compile("(\\d+)(-(\\d*))?");
102
103
protected static VersionRange parse(String rangeText) {
104
Matcher matcher = PATTERN.matcher(rangeText);
105
106
if (matcher.matches()) {
107
try {
108
int min = Integer.parseInt(matcher.group(1));
109
String maxText = matcher.group(3);
110
int max;
111
112
if (maxText == null) {
113
max = min;
114
} else if (maxText.isEmpty()) {
115
max = Integer.MAX_VALUE;
116
} else {
117
max = Integer.parseInt(maxText);
118
}
119
120
return new VersionRange(min, max);
121
} catch (NumberFormatException e) {
122
// throw IllegalArgumentException below
123
}
124
}
125
126
throw new IllegalArgumentException();
127
}
128
129
private final int min;
130
131
private final int max;
132
133
private VersionRange(int min, int max) {
134
super();
135
this.min = min;
136
this.max = max;
137
}
138
139
protected boolean includes(int version) {
140
return min <= version && version <= max;
141
}
142
143
}
144
145
protected static class Alias {
146
147
static interface Factory {
148
Alias alias(Element e, Alias proto);
149
}
150
151
final VersionRange[] versions;
152
final String[] flags;
153
154
Alias(VersionRange[] versions, String[] flags) {
155
this.versions = versions;
156
this.flags = flags;
157
}
158
159
protected boolean isIncluded() {
160
return false;
161
}
162
163
void writeSecondaryItems(ConstantPoolStream ds) {
164
// do nothing
165
}
166
167
void write(ConstantPoolStream ds) {
168
ds.writeInt(0);
169
ds.writeInt(0);
170
}
171
172
private boolean matchesVersion(int version) {
173
for (VersionRange range : this.versions) {
174
if (range.includes(version)) {
175
return true;
176
}
177
}
178
return false;
179
}
180
181
private boolean hasFlag(Set<String> flags) {
182
for (String s : this.flags) {
183
if (s.startsWith("!")) {
184
// remove starting !
185
String actualFlag = s.substring(1);
186
if (flags.contains(actualFlag)) {
187
return false;
188
} else {
189
return true;
190
}
191
} else if (flags.contains(s)) {
192
return true;
193
}
194
}
195
return false;
196
}
197
}
198
199
protected static class AliasWithClass extends Alias {
200
final ClassRef classRef;
201
private boolean classIncluded;
202
203
AliasWithClass(VersionRange[] versions, String[] flags, ClassRef classRef) {
204
super(versions, flags);
205
this.classRef = classRef;
206
}
207
208
boolean checkClassForWriteSecondary(ConstantPoolStream ds) {
209
if (!classIncluded) {
210
super.writeSecondaryItems(ds);
211
}
212
return classIncluded;
213
}
214
215
boolean checkClassForWrite(ConstantPoolStream ds) {
216
classIncluded = classRef.alias(ds).isIncluded();
217
if (!classIncluded) {
218
super.write(ds);
219
}
220
return classIncluded;
221
}
222
}
223
224
private static Alias[] aliases(Element e, String nodeName, Alias proto, Alias.Factory factory) {
225
NodeList nodes = e.getChildNodes();
226
List<Alias> list = new ArrayList<>();
227
for (int i = 0; i < nodes.getLength(); i++) {
228
Node node = nodes.item(i);
229
if (node.getNodeType() == Node.ELEMENT_NODE && nodeName.equals(node.getNodeName())) {
230
list.add(factory.alias((Element) node, proto));
231
}
232
}
233
return list.toArray(new Alias[list.size()]);
234
}
235
236
Alias alias(int version, Set<String> flags) {
237
// Look for an alias that explicitly supports the version and a flag.
238
for (Alias alias : aliases) {
239
if (alias.matchesVersion(version) && alias.hasFlag(flags)) {
240
return alias;
241
}
242
}
243
244
// Look for an alias that explicitly supports either the version or a flag.
245
for (Alias alias : aliases) {
246
// Check if the alias explicitly supports the version and has no flags.
247
if (alias.matchesVersion(version) && alias.flags.length == 0) {
248
// Check that the primary alias supports a flag.
249
if (primary.hasFlag(flags) || primary.flags.length == 0) {
250
return alias;
251
}
252
}
253
// Check if the alias implicitly supports the version and has a flag.
254
if (alias.versions.length == 0 && alias.hasFlag(flags)) {
255
// Check that the primary alias supports the version.
256
if (primary.matchesVersion(version) || primary.versions.length == 0) {
257
return alias;
258
}
259
}
260
}
261
262
// Check that the primary alias supports the version and flags.
263
if (primary.matchesVersion(version) || primary.versions.length == 0) {
264
if (primary.hasFlag(flags) || primary.flags.length == 0) {
265
// Look for an alias that implicitly supports the version and flags.
266
for (Alias alias : aliases) {
267
if (alias.versions.length == 0 && alias.flags.length == 0) {
268
return alias;
269
}
270
}
271
272
return primary;
273
}
274
}
275
276
// This item is not applicable to the current configuration.
277
return null;
278
}
279
280
Alias alias(ConstantPoolStream ds) {
281
return alias(ds.version, ds.flags);
282
}
283
284
public void write(ConstantPoolStream ds) {
285
alias(ds).write(ds);
286
}
287
288
public void writeSecondaryItems(ConstantPoolStream ds) {
289
alias(ds).writeSecondaryItems(ds);
290
}
291
292
public void writeMacros(ConstantPool pool, PrintWriter out) {
293
out.println();
294
out.println("#define J9VMCONSTANTPOOL_" + cMacroName() + " " + pool.getIndex(this));
295
}
296
297
public String commentText() {
298
return getClass().getName();
299
}
300
301
}
302
303