aoqi@0: /* aoqi@0: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: import java.io.File; aoqi@0: import java.io.IOException; aoqi@0: import java.io.PrintWriter; aoqi@0: import java.util.Enumeration; aoqi@0: import java.util.Hashtable; aoqi@0: import java.util.Iterator; aoqi@0: import java.util.List; aoqi@0: import java.util.Stack; aoqi@0: import java.util.TreeSet; aoqi@0: import java.util.Vector; aoqi@0: aoqi@0: abstract class HsArgHandler extends ArgHandler { aoqi@0: static final int STRING = 1; aoqi@0: static final int VECTOR = 2; aoqi@0: static final int HASH = 3; aoqi@0: aoqi@0: boolean nextNotKey(ArgIterator it) { aoqi@0: if (it.next()) { aoqi@0: String s = it.get(); aoqi@0: return (s.length() == 0) || (s.charAt(0) != '-'); aoqi@0: } else { aoqi@0: return false; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void empty(String key, String message) { aoqi@0: if (key != null) { aoqi@0: System.err.println("** Error: empty " + key); aoqi@0: } aoqi@0: if (message != null) { aoqi@0: System.err.println(message); aoqi@0: } aoqi@0: WinGammaPlatform.usage(); aoqi@0: } aoqi@0: aoqi@0: static String getCfg(String val) { aoqi@0: int under = val.indexOf('_'); aoqi@0: int len = val.length(); aoqi@0: if (under != -1 && under < len - 1) { aoqi@0: return val.substring(under+1, len); aoqi@0: } else { aoqi@0: return null; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: class ArgRuleSpecific extends ArgRule { aoqi@0: ArgRuleSpecific(String arg, ArgHandler handler) { aoqi@0: super(arg, handler); aoqi@0: } aoqi@0: aoqi@0: boolean match(String rulePattern, String arg) { aoqi@0: return rulePattern.startsWith(arg); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: class SpecificHsArgHandler extends HsArgHandler { aoqi@0: aoqi@0: String message, argKey, valKey; aoqi@0: int type; aoqi@0: aoqi@0: public void handle(ArgIterator it) { aoqi@0: String cfg = getCfg(it.get()); aoqi@0: if (nextNotKey(it)) { aoqi@0: String val = it.get(); aoqi@0: switch (type) { aoqi@0: case VECTOR: aoqi@0: BuildConfig.addFieldVector(cfg, valKey, val); aoqi@0: break; aoqi@0: case HASH: aoqi@0: BuildConfig.putFieldHash(cfg, valKey, val, "1"); aoqi@0: break; aoqi@0: case STRING: aoqi@0: BuildConfig.putField(cfg, valKey, val); aoqi@0: break; aoqi@0: default: aoqi@0: empty(valKey, "Unknown type: "+type); aoqi@0: } aoqi@0: it.next(); aoqi@0: aoqi@0: } else { aoqi@0: empty(argKey, message); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: SpecificHsArgHandler(String argKey, String valKey, String message, int type) { aoqi@0: this.argKey = argKey; aoqi@0: this.valKey = valKey; aoqi@0: this.message = message; aoqi@0: this.type = type; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: class HsArgRule extends ArgRuleSpecific { aoqi@0: aoqi@0: HsArgRule(String argKey, String valKey, String message, int type) { aoqi@0: super(argKey, new SpecificHsArgHandler(argKey, valKey, message, type)); aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: public abstract class WinGammaPlatform { aoqi@0: aoqi@0: public boolean fileNameStringEquality(String s1, String s2) { aoqi@0: return s1.equalsIgnoreCase(s2); aoqi@0: } aoqi@0: aoqi@0: static void usage() throws IllegalArgumentException { aoqi@0: System.err.println("WinGammaPlatform platform-specific options:"); aoqi@0: System.err.println(" -sourceBase "); aoqi@0: System.err.println(" -projectFileName "); aoqi@0: System.err.println(" If any of the above are specified, "+ aoqi@0: "they must all be."); aoqi@0: System.err.println(" Note: if '-altRelativeInclude' option below " + aoqi@0: "is used, then the '-relativeAltSrcInclude' " + aoqi@0: "option must be used to specify the alternate " + aoqi@0: "source dir, e.g., 'src\\closed'"); aoqi@0: System.err.println(" Additional, optional arguments, which can be " + aoqi@0: "specified multiple times:"); aoqi@0: System.err.println(" -absoluteInclude "); aoqi@0: System.err.println(" -altRelativeInclude "); aoqi@0: System.err.println(" -relativeInclude "); aoqi@0: System.err.println(" -define "); aoqi@0: System.err.println(" -startAt "); aoqi@0: System.err.println(" -additionalFile "); aoqi@0: System.err.println(" -additionalGeneratedFile " + aoqi@0: ""); aoqi@0: throw new IllegalArgumentException(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: public void addPerFileLine(Hashtable table, aoqi@0: String fileName, aoqi@0: String line) { aoqi@0: Vector v = (Vector) table.get(fileName); aoqi@0: if (v != null) { aoqi@0: v.add(line); aoqi@0: } else { aoqi@0: v = new Vector(); aoqi@0: v.add(line); aoqi@0: table.put(fileName, v); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected static class PerFileCondData { aoqi@0: public String releaseString; aoqi@0: public String debugString; aoqi@0: } aoqi@0: aoqi@0: protected void addConditionalPerFileLine(Hashtable table, aoqi@0: String fileName, aoqi@0: String releaseLine, aoqi@0: String debugLine) { aoqi@0: PerFileCondData data = new PerFileCondData(); aoqi@0: data.releaseString = releaseLine; aoqi@0: data.debugString = debugLine; aoqi@0: Vector v = (Vector) table.get(fileName); aoqi@0: if (v != null) { aoqi@0: v.add(data); aoqi@0: } else { aoqi@0: v = new Vector(); aoqi@0: v.add(data); aoqi@0: table.put(fileName, v); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: protected static class PrelinkCommandData { aoqi@0: String description; aoqi@0: String commands; aoqi@0: } aoqi@0: aoqi@0: protected void addPrelinkCommand(Hashtable table, aoqi@0: String build, aoqi@0: String description, aoqi@0: String commands) { aoqi@0: PrelinkCommandData data = new PrelinkCommandData(); aoqi@0: data.description = description; aoqi@0: data.commands = commands; aoqi@0: table.put(build, data); aoqi@0: } aoqi@0: aoqi@0: public boolean findString(Vector v, String s) { aoqi@0: for (Iterator iter = v.iterator(); iter.hasNext(); ) { aoqi@0: if (((String) iter.next()).equals(s)) { aoqi@0: return true; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: String getProjectName(String fullPath, String extension) aoqi@0: throws IllegalArgumentException, IOException { aoqi@0: File file = new File(fullPath).getCanonicalFile(); aoqi@0: fullPath = file.getCanonicalPath(); aoqi@0: String parent = file.getParent(); aoqi@0: aoqi@0: if (!fullPath.endsWith(extension)) { aoqi@0: throw new IllegalArgumentException("project file name \"" + aoqi@0: fullPath + aoqi@0: "\" does not end in "+extension); aoqi@0: } aoqi@0: aoqi@0: if ((parent != null) && aoqi@0: (!fullPath.startsWith(parent))) { aoqi@0: throw new RuntimeException( aoqi@0: "Internal error: parent of file name \"" + parent + aoqi@0: "\" does not match file name \"" + fullPath + "\"" aoqi@0: ); aoqi@0: } aoqi@0: aoqi@0: int len = parent.length(); aoqi@0: if (!parent.endsWith(Util.sep)) { aoqi@0: len += Util.sep.length(); aoqi@0: } aoqi@0: aoqi@0: int end = fullPath.length() - extension.length(); aoqi@0: aoqi@0: if (len == end) { aoqi@0: throw new RuntimeException( aoqi@0: "Internal error: file name was empty" aoqi@0: ); aoqi@0: } aoqi@0: aoqi@0: return fullPath.substring(len, end); aoqi@0: } aoqi@0: aoqi@0: protected abstract String getProjectExt(); aoqi@0: aoqi@0: public void createVcproj(String[] args) aoqi@0: throws IllegalArgumentException, IOException { aoqi@0: aoqi@0: parseArguments(args); aoqi@0: aoqi@0: String projectFileName = BuildConfig.getFieldString(null, "ProjectFileName"); aoqi@0: String ext = getProjectExt(); aoqi@0: aoqi@0: String projectName = getProjectName(projectFileName, ext); aoqi@0: aoqi@0: writeProjectFile(projectFileName, projectName, createAllConfigs(BuildConfig.getFieldString(null, "PlatformName"))); aoqi@0: } aoqi@0: aoqi@0: protected void writePrologue(String[] args) { aoqi@0: System.err.println("WinGammaPlatform platform-specific arguments:"); aoqi@0: for (int i = 0; i < args.length; i++) { aoqi@0: System.err.print(args[i] + " "); aoqi@0: } aoqi@0: System.err.println(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void parseArguments(String[] args) { aoqi@0: new ArgsParser(args, aoqi@0: new ArgRule[] aoqi@0: { aoqi@0: new ArgRule("-sourceBase", aoqi@0: new HsArgHandler() { aoqi@0: public void handle(ArgIterator it) { aoqi@0: String cfg = getCfg(it.get()); aoqi@0: if (nextNotKey(it)) { aoqi@0: String sb = (String) it.get(); aoqi@0: if (sb.endsWith(Util.sep)) { aoqi@0: sb = sb.substring(0, sb.length() - 1); aoqi@0: } aoqi@0: BuildConfig.putField(cfg, "SourceBase", sb); aoqi@0: it.next(); aoqi@0: } else { aoqi@0: empty("-sourceBase", null); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-buildBase", aoqi@0: "BuildBase", aoqi@0: " (Did you set the HotSpotBuildSpace environment variable?)", aoqi@0: HsArgHandler.STRING aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-buildSpace", aoqi@0: "BuildSpace", aoqi@0: null, aoqi@0: HsArgHandler.STRING aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-platformName", aoqi@0: "PlatformName", aoqi@0: null, aoqi@0: HsArgHandler.STRING aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-projectFileName", aoqi@0: "ProjectFileName", aoqi@0: null, aoqi@0: HsArgHandler.STRING aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-jdkTargetRoot", aoqi@0: "JdkTargetRoot", aoqi@0: " (Did you set the HotSpotJDKDist environment variable?)", aoqi@0: HsArgHandler.STRING aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-compiler", aoqi@0: "CompilerVersion", aoqi@0: " (Did you set the VcVersion correctly?)", aoqi@0: HsArgHandler.STRING aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-absoluteInclude", aoqi@0: "AbsoluteInclude", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-altRelativeInclude", aoqi@0: "AltRelativeInclude", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-relativeInclude", aoqi@0: "RelativeInclude", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-absoluteSrcInclude", aoqi@0: "AbsoluteSrcInclude", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-relativeAltSrcInclude", aoqi@0: "RelativeAltSrcInclude", aoqi@0: null, aoqi@0: HsArgHandler.STRING aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-relativeSrcInclude", aoqi@0: "RelativeSrcInclude", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-define", aoqi@0: "Define", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-useToGeneratePch", aoqi@0: "UseToGeneratePch", aoqi@0: null, aoqi@0: HsArgHandler.STRING aoqi@0: ), aoqi@0: aoqi@0: new ArgRuleSpecific("-perFileLine", aoqi@0: new HsArgHandler() { aoqi@0: public void handle(ArgIterator it) { aoqi@0: String cfg = getCfg(it.get()); aoqi@0: if (nextNotKey(it)) { aoqi@0: String fileName = it.get(); aoqi@0: if (nextNotKey(it)) { aoqi@0: String line = it.get(); aoqi@0: BuildConfig.putFieldHash(cfg, "PerFileLine", fileName, line); aoqi@0: it.next(); aoqi@0: return; aoqi@0: } aoqi@0: } aoqi@0: empty(null, "** Error: wrong number of args to -perFileLine"); aoqi@0: } aoqi@0: } aoqi@0: ), aoqi@0: aoqi@0: new ArgRuleSpecific("-conditionalPerFileLine", aoqi@0: new HsArgHandler() { aoqi@0: public void handle(ArgIterator it) { aoqi@0: String cfg = getCfg(it.get()); aoqi@0: if (nextNotKey(it)) { aoqi@0: String fileName = it.get(); aoqi@0: if (nextNotKey(it)) { aoqi@0: String productLine = it.get(); aoqi@0: if (nextNotKey(it)) { aoqi@0: String debugLine = it.get(); aoqi@0: BuildConfig.putFieldHash(cfg+"_debug", "CondPerFileLine", aoqi@0: fileName, debugLine); aoqi@0: BuildConfig.putFieldHash(cfg+"_product", "CondPerFileLine", aoqi@0: fileName, productLine); aoqi@0: it.next(); aoqi@0: return; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: empty(null, "** Error: wrong number of args to -conditionalPerFileLine"); aoqi@0: } aoqi@0: } aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-disablePch", aoqi@0: "DisablePch", aoqi@0: null, aoqi@0: HsArgHandler.HASH aoqi@0: ), aoqi@0: aoqi@0: new ArgRule("-startAt", aoqi@0: new HsArgHandler() { aoqi@0: public void handle(ArgIterator it) { aoqi@0: if (BuildConfig.getField(null, "StartAt") != null) { aoqi@0: empty(null, "** Error: multiple -startAt"); aoqi@0: } aoqi@0: if (nextNotKey(it)) { aoqi@0: BuildConfig.putField(null, "StartAt", it.get()); aoqi@0: it.next(); aoqi@0: } else { aoqi@0: empty("-startAt", null); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-ignoreFile", aoqi@0: "IgnoreFile", aoqi@0: null, aoqi@0: HsArgHandler.HASH aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-ignorePath", aoqi@0: "IgnorePath", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-hidePath", aoqi@0: "HidePath", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new HsArgRule("-additionalFile", aoqi@0: "AdditionalFile", aoqi@0: null, aoqi@0: HsArgHandler.VECTOR aoqi@0: ), aoqi@0: aoqi@0: new ArgRuleSpecific("-additionalGeneratedFile", aoqi@0: new HsArgHandler() { aoqi@0: public void handle(ArgIterator it) { aoqi@0: String cfg = getCfg(it.get()); aoqi@0: if (nextNotKey(it)) { aoqi@0: String dir = it.get(); aoqi@0: if (nextNotKey(it)) { aoqi@0: String fileName = it.get(); aoqi@0: BuildConfig.putFieldHash(cfg, "AdditionalGeneratedFile", aoqi@0: Util.normalize(dir + Util.sep + fileName), aoqi@0: fileName); aoqi@0: it.next(); aoqi@0: return; aoqi@0: } aoqi@0: } aoqi@0: empty(null, "** Error: wrong number of args to -additionalGeneratedFile"); aoqi@0: } aoqi@0: } aoqi@0: ), aoqi@0: aoqi@0: new ArgRule("-prelink", aoqi@0: new HsArgHandler() { aoqi@0: public void handle(ArgIterator it) { aoqi@0: if (nextNotKey(it)) { aoqi@0: if (nextNotKey(it)) { aoqi@0: String description = it.get(); aoqi@0: if (nextNotKey(it)) { aoqi@0: String command = it.get(); aoqi@0: BuildConfig.putField(null, "PrelinkDescription", description); aoqi@0: BuildConfig.putField(null, "PrelinkCommand", command); aoqi@0: it.next(); aoqi@0: return; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: empty(null, "** Error: wrong number of args to -prelink"); aoqi@0: } aoqi@0: } aoqi@0: ), aoqi@0: aoqi@0: new ArgRule("-postbuild", aoqi@0: new HsArgHandler() { aoqi@0: public void handle(ArgIterator it) { aoqi@0: if (nextNotKey(it)) { aoqi@0: if (nextNotKey(it)) { aoqi@0: String description = it.get(); aoqi@0: if (nextNotKey(it)) { aoqi@0: String command = it.get(); aoqi@0: BuildConfig.putField(null, "PostbuildDescription", description); aoqi@0: BuildConfig.putField(null, "PostbuildCommand", command); aoqi@0: it.next(); aoqi@0: return; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: empty(null, "** Error: wrong number of args to -postbuild"); aoqi@0: } aoqi@0: } aoqi@0: ), aoqi@0: }, aoqi@0: new ArgHandler() { aoqi@0: public void handle(ArgIterator it) { aoqi@0: aoqi@0: throw new RuntimeException("Arg Parser: unrecognized option "+it.get()); aoqi@0: } aoqi@0: } aoqi@0: ); aoqi@0: if (BuildConfig.getField(null, "SourceBase") == null || aoqi@0: BuildConfig.getField(null, "BuildBase") == null || aoqi@0: BuildConfig.getField(null, "ProjectFileName") == null || aoqi@0: BuildConfig.getField(null, "CompilerVersion") == null) { aoqi@0: usage(); aoqi@0: } aoqi@0: aoqi@0: if (BuildConfig.getField(null, "UseToGeneratePch") == null) { aoqi@0: throw new RuntimeException("ERROR: need to specify one file to compute PCH, with -useToGeneratePch flag"); aoqi@0: } aoqi@0: aoqi@0: BuildConfig.putField(null, "PlatformObject", this); aoqi@0: } aoqi@0: aoqi@0: Vector createAllConfigs(String platform) { aoqi@0: Vector allConfigs = new Vector(); aoqi@0: aoqi@0: allConfigs.add(new C1DebugConfig()); aoqi@0: allConfigs.add(new C1FastDebugConfig()); aoqi@0: allConfigs.add(new C1ProductConfig()); aoqi@0: aoqi@0: allConfigs.add(new C2DebugConfig()); aoqi@0: allConfigs.add(new C2FastDebugConfig()); aoqi@0: allConfigs.add(new C2ProductConfig()); aoqi@0: aoqi@0: allConfigs.add(new TieredDebugConfig()); aoqi@0: allConfigs.add(new TieredFastDebugConfig()); aoqi@0: allConfigs.add(new TieredProductConfig()); aoqi@0: aoqi@0: return allConfigs; aoqi@0: } aoqi@0: aoqi@0: PrintWriter printWriter; aoqi@0: aoqi@0: public void writeProjectFile(String projectFileName, String projectName, aoqi@0: Vector allConfigs) throws IOException { aoqi@0: throw new RuntimeException("use compiler version specific version"); aoqi@0: } aoqi@0: aoqi@0: int indent; aoqi@0: private Stack tagStack = new Stack(); aoqi@0: aoqi@0: private void startTagPrim(String name, String[] attrs, boolean close) { aoqi@0: startTagPrim(name, attrs, close, true); aoqi@0: } aoqi@0: aoqi@0: private void startTagPrim(String name, String[] attrs, boolean close, aoqi@0: boolean newline) { aoqi@0: doIndent(); aoqi@0: printWriter.print("<" + name); aoqi@0: indent++; aoqi@0: aoqi@0: if (attrs != null && attrs.length > 0) { aoqi@0: for (int i = 0; i < attrs.length; i += 2) { aoqi@0: printWriter.print(" " + attrs[i] + "=\"" + attrs[i + 1] + "\""); aoqi@0: if (i < attrs.length - 2) { aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (close) { aoqi@0: indent--; aoqi@0: printWriter.print(" />"); aoqi@0: } else { aoqi@0: // TODO push tag name, and change endTag to pop and print. aoqi@0: tagStack.push(name); aoqi@0: printWriter.print(">"); aoqi@0: } aoqi@0: if (newline) { aoqi@0: printWriter.println(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void startTag(String name, String... attrs) { aoqi@0: startTagPrim(name, attrs, false); aoqi@0: } aoqi@0: aoqi@0: void startTagV(String name, Vector attrs) { aoqi@0: String s[] = new String[attrs.size()]; aoqi@0: for (int i = 0; i < attrs.size(); i++) { aoqi@0: s[i] = (String) attrs.elementAt(i); aoqi@0: } aoqi@0: startTagPrim(name, s, false); aoqi@0: } aoqi@0: aoqi@0: void endTag() { aoqi@0: String name = tagStack.pop(); aoqi@0: indent--; aoqi@0: doIndent(); aoqi@0: printWriter.println(""); aoqi@0: } aoqi@0: aoqi@0: private void endTagNoIndent() { aoqi@0: String name = tagStack.pop(); aoqi@0: indent--; aoqi@0: printWriter.println(""); aoqi@0: } aoqi@0: aoqi@0: void tag(String name, String... attrs) { aoqi@0: startTagPrim(name, attrs, true); aoqi@0: } aoqi@0: aoqi@0: void tagData(String name, String data) { aoqi@0: startTagPrim(name, null, false, false); aoqi@0: printWriter.print(data); aoqi@0: endTagNoIndent(); aoqi@0: } aoqi@0: aoqi@0: void tagData(String name, String data, String... attrs) { aoqi@0: startTagPrim(name, attrs, false, false); aoqi@0: printWriter.print(data); aoqi@0: endTagNoIndent(); aoqi@0: } aoqi@0: aoqi@0: void tagV(String name, Vector attrs) { aoqi@0: String s[] = new String[attrs.size()]; aoqi@0: for (int i = 0; i < attrs.size(); i++) { aoqi@0: s[i] = (String) attrs.elementAt(i); aoqi@0: } aoqi@0: startTagPrim(name, s, true); aoqi@0: } aoqi@0: aoqi@0: void doIndent() { aoqi@0: for (int i = 0; i < indent; i++) { aoqi@0: printWriter.print(" "); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: }