diff --git a/src/org/openjdk/asmtools/Main.java b/src/org/openjdk/asmtools/Main.java index 441b691..c0f3650 100644 --- a/src/org/openjdk/asmtools/Main.java +++ b/src/org/openjdk/asmtools/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ public class Main { public static final String DUAL_LOG_SWITCH ="-dls"; /** - * Parses the first argument and deligates execution to an appropriate tool + * Parses the first argument and delegates execution to an appropriate tool * * @param args - command line arguments */ diff --git a/src/org/openjdk/asmtools/jasm/BootstrapMethodData.java b/src/org/openjdk/asmtools/jasm/BootstrapMethodData.java index b303680..67d9777 100644 --- a/src/org/openjdk/asmtools/jasm/BootstrapMethodData.java +++ b/src/org/openjdk/asmtools/jasm/BootstrapMethodData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Objects; +import java.util.stream.Collectors; class BootstrapMethodData extends Indexer implements DataWriter { @@ -37,33 +38,32 @@ public BootstrapMethodData(ConstCell bsmHandle, ArrayList> argument this.arguments = arguments; } - // placeholder - bootstrap_method_attr_index + // methodAttrIndex - bootstrap_method_attr_index // The value of the bootstrap_method_attr_index item must be a valid index into the bootstrap_methods array // of the bootstrap method table of this class file (§4.7.23). - protected BootstrapMethodData clone(int placeholder) { - BootstrapMethodData instance = new BootstrapMethodData(this.bootstrapMethodHandle, arguments); - instance.cpIndex = placeholder; - return instance; - } - - // placeholder - bootstrap_method_attr_index - // The value of the bootstrap_method_attr_index item must be a valid index into the bootstrap_methods array - // of the bootstrap method table of this class file (§4.7.23). - public BootstrapMethodData(int placeholder) { + public BootstrapMethodData(int methodAttrIndex) { super(); this.bootstrapMethodHandle = null; this.arguments = null; - this.cpIndex = placeholder; + super.cpIndex = methodAttrIndex; } public int getLength() { return 4 + arguments.size() * 2; } - public boolean isPlaceholder() { + public boolean hasMethodAttrIndex() { return super.isSet(); } + public void setMethodAttrIndex(int methodAttrIndex) { + super.cpIndex = methodAttrIndex; + } + + public int getMethodAttrIndex() { + return super.cpIndex; + + } public void write(CheckedDataOutputStream out) throws IOException { out.writeShort(bootstrapMethodHandle.cpIndex); out.writeShort(arguments.size()); @@ -73,6 +73,14 @@ public void write(CheckedDataOutputStream out) throws IOException { } } + @Override + public String toString() { + return String.format("{MethodHandle:%s Arguments:%s}", + bootstrapMethodHandle == null || bootstrapMethodHandle.cpIndex == NotSet ? " n/a" : " #" + bootstrapMethodHandle.cpIndex, + arguments == null || arguments.isEmpty() ? "{}" : + "{ " + arguments.stream().map(a -> String.format("#%d", a.cpIndex)).collect(Collectors.joining(", ")) + " }"); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -80,7 +88,7 @@ public boolean equals(Object o) { BootstrapMethodData that = (BootstrapMethodData) o; if (!Objects.equals(bootstrapMethodHandle, that.bootstrapMethodHandle)) return false; - return Objects.equals(arguments, that.arguments); + return this.cpIndex == that.cpIndex & Objects.equals(arguments, that.arguments); } @Override diff --git a/src/org/openjdk/asmtools/jasm/ClassData.java b/src/org/openjdk/asmtools/jasm/ClassData.java index e05797d..04cb70a 100644 --- a/src/org/openjdk/asmtools/jasm/ClassData.java +++ b/src/org/openjdk/asmtools/jasm/ClassData.java @@ -28,14 +28,16 @@ import org.openjdk.asmtools.common.structure.EModifier; import java.io.*; -import java.nio.file.FileSystems; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import static org.openjdk.asmtools.common.structure.ClassFileContext.INNER_CLASS; import static org.openjdk.asmtools.jasm.ClassFileConst.ConstType; import static org.openjdk.asmtools.jasm.ClassFileConst.ConstType.CONSTANT_DYNAMIC; import static org.openjdk.asmtools.jasm.ClassFileConst.ConstType.CONSTANT_INVOKEDYNAMIC; import static org.openjdk.asmtools.jasm.ClassFileConst.JAVA_MAGIC; +import static org.openjdk.asmtools.jasm.Indexer.NotSet; /** * ClassData @@ -148,73 +150,85 @@ public final boolean isAbstract() { /* * After a constant pool has been explicitly declared, - * this method links the Constant_InvokeDynamic Constant_Dynamic + * this method links the Constant_InvokeDynamic|Constant_Dynamic * constants with any bootstrap methods that they index in the * Bootstrap Methods Attribute */ protected void relinkBootstrapMethods() { - if (bootstrapMethodsAttr == null) { - return; - } - - environment.traceln("relinkBootstrapMethods"); - - for (ConstCell cell : pool) { - ConstValue ref = null; - if (cell != null) { - ref = cell.ref; - } - if (ref != null - && (ref.tag == CONSTANT_INVOKEDYNAMIC || ref.tag == CONSTANT_DYNAMIC)) { - // Find only the Constant - ConstantPool.ConstValue_BootstrapMethod refval = (ConstantPool.ConstValue_BootstrapMethod) ref; - BootstrapMethodData bsmdata = refval.bsmData(); - // only care about BSM Data that were placeholders - if (bsmdata != null && bsmdata.isPlaceholder()) { + if (bootstrapMethodsAttr != null) { + ArrayList> cells = pool.getPoolValuesByRefType(CONSTANT_INVOKEDYNAMIC, CONSTANT_DYNAMIC); + environment.traceln("relinkBSMs: %d items", cells.size()); + for (ConstCell cell : cells) { + ConstantPool.ConstValue_BootstrapMethod refVal = (ConstantPool.ConstValue_BootstrapMethod) cell.ref; + BootstrapMethodData bsmData = refVal.bsmData(); + if (refVal.isSet() & refVal.value.ref == null) { + ConstCell c = pool.getCell(((ConstCell) refVal.value).cpIndex); + refVal.setValue(c); + } + if (bsmData != null && bsmData.hasMethodAttrIndex()) { // find the real BSM Data at the index - int bsmindex = bsmdata.cpIndex; - if (bsmindex < 0 || bsmindex > bootstrapMethodsAttr.size()) { - // bad BSM index -- - // give a warning, but place the index in the arg anyway - environment.traceln("Warning: (ClassData.relinkBootstrapMethods()): Bad bootstrapMethods index: " + bsmindex); - // env.error("const.bsmindex", bsmindex); - bsmdata.cpIndex = bsmindex; + int methodAttrIndex = bsmData.getMethodAttrIndex(); + if (methodAttrIndex < 0 || methodAttrIndex > bootstrapMethodsAttr.size()) { + // bad BSM index - give a warning, but place the index in the arg anyway + environment.warning("warn.bootstrapmethod.attr.bad", methodAttrIndex); + bsmData.setMethodAttrIndex(methodAttrIndex); } else { // make the IndyPairs BSM Data point to the one from the attribute - refval.setBsmData(bootstrapMethodsAttr.get(bsmindex)); + refVal.setBsmData(bootstrapMethodsAttr.get(methodAttrIndex), methodAttrIndex); } } } } } - protected void numberBootstrapMethods() { - environment.traceln("Numbering Bootstrap Methods"); - if (bootstrapMethodsAttr == null) { - return; - } - boolean duplicateExists = false; - // remove duplicates in BootstrapMethod_Attribute if found - // Fix 7902888: Excess entries in BootstrapMethods with the same bsm, bsmKind, bsmArgs - ArrayList> list = this.getPool().getPoolCellsByType(CONSTANT_DYNAMIC, CONSTANT_INVOKEDYNAMIC); - BootstrapMethodData[] bsmAttributes = new BootstrapMethodData[list.size()]; - HashMap bsmHashMap = new HashMap<>(); - int index = 0; - // - for (int i = 0; i < list.size(); i++) { - ConstantPool.ConstValue_BootstrapMethod cell = (ConstantPool.ConstValue_BootstrapMethod) list.get(i).ref; - BootstrapMethodData bsmData = ((ConstantPool.ConstValue_BootstrapMethod) list.get(i).ref).bsmData(); - if (bsmHashMap.keySet().contains(bsmData)) { - duplicateExists = true; - cell.setBsmData(bsmAttributes[bsmHashMap.get(bsmData)]); - } else { - bsmAttributes[i] = bsmData.clone(index++); - cell.setBsmData(bsmAttributes[i]); - bsmHashMap.put(bsmData, i); + /** + * Finds first BSM data element by value in a collection + */ + private > int getFirstIndex(T collection, BootstrapMethodData bsmData) { + if (!collection.isEmpty()) { + BootstrapMethodData[] array = collection.toArray(BootstrapMethodData[]::new); + for (int i = 0; i < array.length; i++) { + if (bsmData.equalsByValue(array[i])) { + return i; + } } } - if( duplicateExists ) { - bootstrapMethodsAttr.replaceAll(Arrays.stream(bsmAttributes).filter(i -> i != null).toList()); + return NotSet; + } + + /** + * Relinks BSM data (BootstrapMethod Attribute) and Constant Pool Constant_InvokeDynamic|Constant_Dynamic entries if + * at least one CP cell has undefined method attribute index also the method removes duplicates in BootstrapMethod + * Attribute if found + */ + private void uniquifyBootstrapMethods() { + if (bootstrapMethodsAttr != null) { + int index = 0; + final List cpBsmList = this.getPool(). + getPoolCellsByType(CONSTANT_DYNAMIC, CONSTANT_INVOKEDYNAMIC). + stream().map(item -> ((ConstantPool.ConstValue_BootstrapMethod) item.ref). + bsmData()).toList(); + if (cpBsmList.stream().anyMatch(item -> !item.hasMethodAttrIndex())) { + environment.traceln("numberBSM: %d items", cpBsmList.size()); + // remove duplicates in BootstrapMethod_Attribute if found + // Fix 7902888: Excess entries in BootstrapMethods with the same bsm, bsmKind, bsmArgs + final ArrayList newBsmList = new ArrayList<>(cpBsmList.size()); + for (int i = 0; i < cpBsmList.size(); i++) { + BootstrapMethodData bsmData = cpBsmList.get(i); + int cachedIndex = getFirstIndex(newBsmList, bsmData); + if (cachedIndex != NotSet) { + bsmData.setMethodAttrIndex(cachedIndex); + } else { + if (getFirstIndex(this.bootstrapMethodsAttr, bsmData) == NotSet) { + environment.warning("warn.bootstrapmethod.attr.expected", bsmData.toString()); + } else { + bsmData.setMethodAttrIndex(index++); + } + newBsmList.add(bsmData); + } + } + bootstrapMethodsAttr.replaceAll(newBsmList); + } } } @@ -308,11 +322,11 @@ public void addInnerClass(int access, ConstCell name, ConstCell innerClass, Cons } public void addBootstrapMethod(BootstrapMethodData bsmData) { - environment.traceln("addBootstrapMethod"); if (bootstrapMethodsAttr == null) { bootstrapMethodsAttr = new DataVectorAttr<>(pool, EAttribute.ATT_BootstrapMethods); } bootstrapMethodsAttr.add(bsmData); + environment.traceln("addBootstrapMethod: " + bsmData.toString()); } public void addNestHost(ConstCell hostClass) { @@ -345,9 +359,9 @@ public void endClass() { pool.checkGlobals(); pool.fixIndexesInPool(); itemizeAttributes(new DataVectorAttr<>(pool, EAttribute.ATT_ConstantValue). - addAll(fields.stream().map(f->f.getInitialValue())), + addAll(fields.stream().map(f -> f.getInitialValue())), annotAttrInv, annotAttrVis); - numberBootstrapMethods(); + uniquifyBootstrapMethods(); try { ConstantPool.ConstValue_Class this_class_value = (ConstantPool.ConstValue_Class) this_class.ref; ConstantPool.ConstValue_UTF8 this_class_name = this_class_value.value.ref; diff --git a/src/org/openjdk/asmtools/jasm/ConstValue.java b/src/org/openjdk/asmtools/jasm/ConstValue.java index ca87fe9..b8b244a 100644 --- a/src/org/openjdk/asmtools/jasm/ConstValue.java +++ b/src/org/openjdk/asmtools/jasm/ConstValue.java @@ -44,6 +44,11 @@ public int size() { public boolean isSet() { return value != null; } + public ConstValue setValue(T value) { + this.value = value; + return this; + } + @Override public int hashCode() { int result = value != null ? value.hashCode() : 0; diff --git a/src/org/openjdk/asmtools/jasm/ConstantPool.java b/src/org/openjdk/asmtools/jasm/ConstantPool.java index b798932..e9e41e5 100644 --- a/src/org/openjdk/asmtools/jasm/ConstantPool.java +++ b/src/org/openjdk/asmtools/jasm/ConstantPool.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.util.*; +import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; @@ -173,10 +174,9 @@ private boolean handleIndexCell(ConstCell refCell) { * and the second pass, which links references to existing constants. */ public void fixRefsInPool() { - // used to fix CP refs when a constant pool is constructed by refs alone. - environment.traceln("Fixing CP for explicit Constant Entries."); - // simply iterate through the pool. - environment.traceln("fixRefsInPool %d items", pool.size()); + // Simply iterating through the pool the method is used to fix CP refs + // when a constant pool is constructed by refs alone. + environment.traceln("fixRefsInPool: Fixing CP for %d explicit Constant Entries", pool.size()); for (ConstCell item : pool) { checkAndFixCPRef(item); } @@ -186,10 +186,9 @@ public void fixRefsInPool() { * Fix Indexes in constant pool. */ public void fixIndexesInPool() { - // used to fix CP Indexes when a constant pool is constructed by values alone. - environment.traceln("Fixing CP for explicit Constant Entries."); - // simply iterate through the pool. - environment.traceln("fixIndexesInPool %d items", pool.size()); + // Simply iterate through the pool the method is used to fix CP Indexes + // when a constant pool is constructed by values alone. + environment.traceln("fixIndexesInPool: Fixing CP for %d explicit Constant Entries.", pool.size()); for (ConstCell item : pool) { checkAndFixCPIndexes(item); } @@ -214,7 +213,6 @@ protected void checkGlobals() { /* * Helper function for "fixRefsInPool" - * * Does recursive checking of references, using a locally-defined visitor. */ private void checkAndFixCPRef(ConstCell item) { @@ -308,8 +306,8 @@ public void setCell(int cpx, ConstCell cell) { return; } if (cell.isSet() && (cell.cpIndex != cpx)) { - environment.traceln("setCell: new ConstCell"); cell = new ConstCell(value); + environment.traceln("setCell: new ConstCell %s", cell.toString()); } } cpool_set(cpx, cell, sz); @@ -493,6 +491,11 @@ public ArrayList> getPoolCellsByType(ClassFileConst.ConstType... t return pool.stream().filter(c->c.getType().oneOf(types)).collect(Collectors.toCollection(ArrayList::new)); } + public ArrayList> getPoolValuesByRefType(ClassFileConst.ConstType... types) { + return pool.stream().filter(c->c.ref != null && c.getType().oneOf(types)). + collect(Collectors.toCollection(ArrayList::new)); + } + public enum ReferenceRank { LDC(0), // 0 - highest - ref from ldc ANY(1), // 1 - any ref @@ -878,6 +881,11 @@ public BootstrapMethodData bsmData() { return bsmData; } + public void setBsmData(BootstrapMethodData bsmData, int methodAttrIndex) { + this.bsmData = bsmData; + this.bsmData.cpIndex = methodAttrIndex; + } + public void setBsmData(BootstrapMethodData bsmData) { this.bsmData = bsmData; } @@ -927,7 +935,7 @@ public void write(CheckedDataOutputStream out) throws IOException { /** * The CONSTANT_Dynamic (17) structure is used to represent a dynamically-computed constant, an arbitrary value - * that is produced by invocation of a bootstrap method in the course of an ldc instruction, among others. + * that is produced by invocation of a bootstrap method in the course of a ldc instruction, among others. * The auxiliary type specified by the structure constrains the type of the dynamically-computed constant. */ static public class ConstValue_Dynamic extends ConstValue_BootstrapMethod { diff --git a/src/org/openjdk/asmtools/jasm/DataVectorAttr.java b/src/org/openjdk/asmtools/jasm/DataVectorAttr.java index b3d6e29..e5f4107 100644 --- a/src/org/openjdk/asmtools/jasm/DataVectorAttr.java +++ b/src/org/openjdk/asmtools/jasm/DataVectorAttr.java @@ -35,7 +35,7 @@ * InnerClasses, BootstrapMethods, LineNumberTable, Runtime(In)Visible(Type|Parameter)Annotations, * LocalVariableTable, StackMapTable */ -class DataVectorAttr extends AttrData implements Iterable { +class DataVectorAttr extends AttrData implements Collection { private ArrayList elements; private boolean byteIndex; @@ -72,9 +72,39 @@ public T get(int index) { return elements.get(index); } - public void add(T element) { - if (element != null) - elements.add(element); + @Override + public boolean add(T element) { + return elements.add(element); + } + + @Override + public boolean remove(Object o) { + return elements.remove(o); + } + + @Override + public boolean containsAll(Collection c) { + return elements.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + return elements.addAll(c); + } + + @Override + public boolean removeAll(Collection c) { + return elements.removeAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return elements.retainAll(c); + } + + @Override + public void clear() { + elements.clear(); } public DataVectorAttr addAll(Stream s) { @@ -82,12 +112,22 @@ public DataVectorAttr addAll(Stream s) { return this; } - public void put(int i, T element) { - elements.set(i, element); + public T set(int i, T element) { + return elements.set(i, element); } public int size() { return elements.size(); } + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + public void replaceAll(Collection collection) { elements.clear(); elements.addAll(collection); @@ -102,6 +142,18 @@ public Iterator iterator() { return elements.iterator(); } + @Override + public Object[] toArray() { + return elements.toArray(); + } + + @Override + public V[] toArray(V[] a) { + return elements.toArray(a); + } + + public Stream stream() { return elements.stream(); }; + @Override public int attrLength() { // calculate overall size @@ -123,5 +175,4 @@ public void write(CheckedDataOutputStream out) throws IOException { elem.write(out); } } - } diff --git a/src/org/openjdk/asmtools/jasm/Main.java b/src/org/openjdk/asmtools/jasm/Main.java index 880cba0..47ea892 100644 --- a/src/org/openjdk/asmtools/jasm/Main.java +++ b/src/org/openjdk/asmtools/jasm/Main.java @@ -27,6 +27,8 @@ import org.openjdk.asmtools.common.ToolInput; import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; import java.net.URISyntaxException; import java.util.Optional; import java.util.regex.PatternSyntaxException; @@ -86,12 +88,40 @@ public Main(ToolOutput toolOutput, ToolOutput.DualStreamToolOutput log, ToolInpu parseArgs(new String[0]); } + /** + * Deprecated method to support external tools having it + * + * @param ref A stream to which to write reference output + * @param toolName the tool's name (ignored) + */ + @Deprecated + public Main(PrintWriter ref, String toolName) { + super(new ToolOutput.PrintWriterOutput(ref)); + } + + /** + * Deprecated method to support external tools having it + * + * @param out A stream to which to write reference output + * @param toolName the tool's name (ignored) + */ + @Deprecated + public Main(PrintStream out, String toolName) { + this(new PrintWriter(out), toolName); + } + // jasm entry point public static void main(String... argv) { Main compiler = new Main(new ToolOutput.EscapedPrintStreamOutput(System.out), new ToolOutput.SingleDualOutputStreamOutput(), argv); System.exit(compiler.compile()); } + // Run jasm compiler with args + public synchronized boolean compile(String... argv) { + parseArgs(argv); + return this.compile() == OK; + } + // Run jasm compiler when args already parsed public synchronized int compile() { // compile all input files diff --git a/src/org/openjdk/asmtools/jasm/MethodData.java b/src/org/openjdk/asmtools/jasm/MethodData.java index 9232170..ff3943a 100644 --- a/src/org/openjdk/asmtools/jasm/MethodData.java +++ b/src/org/openjdk/asmtools/jasm/MethodData.java @@ -160,7 +160,7 @@ public void addMethodParameter(int totalParams, int paramNum, ConstCell name, methodParameters.add(new MethodParameterData(0, null)); } } - methodParameters.put(paramNum, new MethodParameterData(access, name)); + methodParameters.set(paramNum, new MethodParameterData(access, name)); } public CodeAttr startCode(int paramCount, Indexer max_stack, Indexer max_locals) { @@ -208,4 +208,3 @@ public void write(CheckedDataOutputStream out) throws IOException, Parser.Compil getAttrVector().write(out); } } // end MethodData - diff --git a/src/org/openjdk/asmtools/jasm/Parser.java b/src/org/openjdk/asmtools/jasm/Parser.java index 0dc314b..f2baf72 100644 --- a/src/org/openjdk/asmtools/jasm/Parser.java +++ b/src/org/openjdk/asmtools/jasm/Parser.java @@ -557,7 +557,7 @@ Indexer parseUInt(int size) throws SyntaxError, IOException { /** * Parse constant declaration */ - private void parseConstDef() throws IOException { + private void parseConstDef() { for (; ; ) { if (scanner.token == Token.CPINDEX) { int cpx = scanner.intValue; diff --git a/src/org/openjdk/asmtools/jasm/i18n.properties b/src/org/openjdk/asmtools/jasm/i18n.properties index 1d98005..bf2b2d1 100644 --- a/src/org/openjdk/asmtools/jasm/i18n.properties +++ b/src/org/openjdk/asmtools/jasm/i18n.properties @@ -171,6 +171,9 @@ err.itemtype.expected=StackMap item type expected instead of {0} err.version.expected=class file version expected err.invalid.innerclass=Invalid declaration of Inner Class err.invalid.bootstrapmethod=Invalid declaration of BootstrapMethod Entry +warn.bootstrapmethod.attr.bad=Bad bootstrap method attribute index {0} +warn.bootstrapmethod.attr.expected=Invoke dynamic \"{0}\" has undefined method attribute index + err.invalid.paramnum=Invalid Parameter Number: {0} err.duplicate.paramnum=Duplicate Parameter Number: {0} err.paramname.constnum.invaltype=ParameterName CPX at {0} is not a ConstantString @@ -220,4 +223,4 @@ err.cpindex.notfound=Constant Pool index {0} is not found # Common errors err.obj.is.null=Fatal Error: Object reference \"{0}\" is null -err.invalid.type=Invalid type of Constant Pool Constant {0} \ No newline at end of file +err.invalid.type=Invalid type of Constant Pool Constant {0} diff --git a/src/org/openjdk/asmtools/jcoder/Main.java b/src/org/openjdk/asmtools/jcoder/Main.java index e5be573..dd8e4f4 100644 --- a/src/org/openjdk/asmtools/jcoder/Main.java +++ b/src/org/openjdk/asmtools/jcoder/Main.java @@ -26,6 +26,8 @@ import org.openjdk.asmtools.common.ToolOutput; import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; import java.net.URISyntaxException; import java.util.HashMap; import java.util.regex.PatternSyntaxException; @@ -72,6 +74,28 @@ public Main(ToolOutput toolOutput, ToolOutput.DualStreamToolOutput log, ToolInpu parseArgs(new String[0]); } + /** + * Deprecated method to support external tools having it + * + * @param ref A stream to which to write reference output + * @param toolName the tool's name (ignored) + */ + @Deprecated + public Main(PrintWriter ref, String toolName) { + super(new ToolOutput.PrintWriterOutput(ref)); + } + + /** + * Deprecated method to support external tools having it + * + * @param out A stream to which to write reference output + * @param toolName the tool's name (ignored) + */ + @Deprecated + public Main(PrintStream out, String toolName) { + this(new PrintWriter(out), toolName); + } + // jcoder entry point public static void main(String... argv) { Main compiler = new Main(new ToolOutput.EscapedPrintStreamOutput(System.out), argv); @@ -90,6 +114,12 @@ public void usage() { environment.info("info.opt.version"); } + // Run jcoder compiler with args + public synchronized boolean compile(String... argv) { + parseArgs(argv); + return this.compile() == OK; + } + // Run jcoder compiler when args already parsed public synchronized int compile() { macros.put("VERSION", "3;45");