Path: blob/master/sourcetools/j9constantpool/com/ibm/oti/VMCPTool/PrimaryItem.java
6004 views
/*******************************************************************************1* Copyright (c) 2004, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/21package com.ibm.oti.VMCPTool;2223import java.io.PrintWriter;24import java.util.ArrayList;25import java.util.List;26import java.util.Set;27import java.util.StringTokenizer;28import java.util.regex.Matcher;29import java.util.regex.Pattern;3031import org.w3c.dom.Element;32import org.w3c.dom.Node;33import org.w3c.dom.NodeList;3435public abstract class PrimaryItem {36protected final Alias primary;37private final Alias[] aliases;3839protected abstract String cMacroName();4041protected PrimaryItem(Element e, String nodeName, Alias.Factory factory) {42primary = factory.alias(e, null);43aliases = aliases(e, nodeName, primary, factory);44}4546private static String[] attribute(Element e, String name) {47StringTokenizer tok = new StringTokenizer(e.getAttribute(name), ",");48if (tok.hasMoreTokens()) {49String[] attributes = new String[tok.countTokens()];50for (int i = 0; tok.hasMoreTokens(); ++i) {51attributes[i] = tok.nextToken();52}53return attributes;54} else {55return null;56}57}5859protected static VersionRange[] versions(Element e, Alias proto) {60VersionRange[] ranges;61String[] versions = attribute(e, "versions");6263if (versions != null) {64int length = versions.length;6566ranges = new VersionRange[length];6768for (int i = 0; i < length; ++i) {69ranges[i] = VersionRange.parse(versions[i]);70}71} else if (proto != null) {72ranges = proto.versions;73} else {74ranges = VersionRange.ALL;75}7677return ranges;78}7980private static final String[] NO_FLAGS = new String[0];8182protected static String[] flags(Element e, Alias proto) {83String[] flags = attribute(e, "flags");84if (flags == null) {85flags = proto != null ? proto.flags : NO_FLAGS;86}87return flags;88}8990protected static String attribute(Element e, String name, String ifAbsent) {91return e.hasAttribute(name) ? e.getAttribute(name) : ifAbsent;92}9394protected static final class VersionRange {9596protected static final VersionRange[] ALL = new VersionRange[] { new VersionRange(0, Integer.MAX_VALUE) };9798protected static final VersionRange[] NONE = new VersionRange[] { new VersionRange(0, -1) };99100private static final Pattern PATTERN = Pattern.compile("(\\d+)(-(\\d*))?");101102protected static VersionRange parse(String rangeText) {103Matcher matcher = PATTERN.matcher(rangeText);104105if (matcher.matches()) {106try {107int min = Integer.parseInt(matcher.group(1));108String maxText = matcher.group(3);109int max;110111if (maxText == null) {112max = min;113} else if (maxText.isEmpty()) {114max = Integer.MAX_VALUE;115} else {116max = Integer.parseInt(maxText);117}118119return new VersionRange(min, max);120} catch (NumberFormatException e) {121// throw IllegalArgumentException below122}123}124125throw new IllegalArgumentException();126}127128private final int min;129130private final int max;131132private VersionRange(int min, int max) {133super();134this.min = min;135this.max = max;136}137138protected boolean includes(int version) {139return min <= version && version <= max;140}141142}143144protected static class Alias {145146static interface Factory {147Alias alias(Element e, Alias proto);148}149150final VersionRange[] versions;151final String[] flags;152153Alias(VersionRange[] versions, String[] flags) {154this.versions = versions;155this.flags = flags;156}157158protected boolean isIncluded() {159return false;160}161162void writeSecondaryItems(ConstantPoolStream ds) {163// do nothing164}165166void write(ConstantPoolStream ds) {167ds.writeInt(0);168ds.writeInt(0);169}170171private boolean matchesVersion(int version) {172for (VersionRange range : this.versions) {173if (range.includes(version)) {174return true;175}176}177return false;178}179180private boolean hasFlag(Set<String> flags) {181for (String s : this.flags) {182if (s.startsWith("!")) {183// remove starting !184String actualFlag = s.substring(1);185if (flags.contains(actualFlag)) {186return false;187} else {188return true;189}190} else if (flags.contains(s)) {191return true;192}193}194return false;195}196}197198protected static class AliasWithClass extends Alias {199final ClassRef classRef;200private boolean classIncluded;201202AliasWithClass(VersionRange[] versions, String[] flags, ClassRef classRef) {203super(versions, flags);204this.classRef = classRef;205}206207boolean checkClassForWriteSecondary(ConstantPoolStream ds) {208if (!classIncluded) {209super.writeSecondaryItems(ds);210}211return classIncluded;212}213214boolean checkClassForWrite(ConstantPoolStream ds) {215classIncluded = classRef.alias(ds).isIncluded();216if (!classIncluded) {217super.write(ds);218}219return classIncluded;220}221}222223private static Alias[] aliases(Element e, String nodeName, Alias proto, Alias.Factory factory) {224NodeList nodes = e.getChildNodes();225List<Alias> list = new ArrayList<>();226for (int i = 0; i < nodes.getLength(); i++) {227Node node = nodes.item(i);228if (node.getNodeType() == Node.ELEMENT_NODE && nodeName.equals(node.getNodeName())) {229list.add(factory.alias((Element) node, proto));230}231}232return list.toArray(new Alias[list.size()]);233}234235Alias alias(int version, Set<String> flags) {236// Look for an alias that explicitly supports the version and a flag.237for (Alias alias : aliases) {238if (alias.matchesVersion(version) && alias.hasFlag(flags)) {239return alias;240}241}242243// Look for an alias that explicitly supports either the version or a flag.244for (Alias alias : aliases) {245// Check if the alias explicitly supports the version and has no flags.246if (alias.matchesVersion(version) && alias.flags.length == 0) {247// Check that the primary alias supports a flag.248if (primary.hasFlag(flags) || primary.flags.length == 0) {249return alias;250}251}252// Check if the alias implicitly supports the version and has a flag.253if (alias.versions.length == 0 && alias.hasFlag(flags)) {254// Check that the primary alias supports the version.255if (primary.matchesVersion(version) || primary.versions.length == 0) {256return alias;257}258}259}260261// Check that the primary alias supports the version and flags.262if (primary.matchesVersion(version) || primary.versions.length == 0) {263if (primary.hasFlag(flags) || primary.flags.length == 0) {264// Look for an alias that implicitly supports the version and flags.265for (Alias alias : aliases) {266if (alias.versions.length == 0 && alias.flags.length == 0) {267return alias;268}269}270271return primary;272}273}274275// This item is not applicable to the current configuration.276return null;277}278279Alias alias(ConstantPoolStream ds) {280return alias(ds.version, ds.flags);281}282283public void write(ConstantPoolStream ds) {284alias(ds).write(ds);285}286287public void writeSecondaryItems(ConstantPoolStream ds) {288alias(ds).writeSecondaryItems(ds);289}290291public void writeMacros(ConstantPool pool, PrintWriter out) {292out.println();293out.println("#define J9VMCONSTANTPOOL_" + cMacroName() + " " + pool.getIndex(this));294}295296public String commentText() {297return getClass().getName();298}299300}301302303