make/hotspot/src/classes/build/tools/projectcreator/WinGammaPlatform.java
changeset 47216 71c04702a3d5
parent 38247 6ff550a6307e
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1999, 2016, 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 package build.tools.projectcreator;
       
    26 
       
    27 import java.io.File;
       
    28 import java.io.IOException;
       
    29 import java.io.PrintWriter;
       
    30 import java.util.Hashtable;
       
    31 import java.util.Iterator;
       
    32 import java.util.Stack;
       
    33 import java.util.Vector;
       
    34 
       
    35 abstract class HsArgHandler extends ArgHandler {
       
    36     static final int STRING = 1;
       
    37     static final int VECTOR = 2;
       
    38     static final int HASH   = 3;
       
    39 
       
    40     boolean nextNotKey(ArgIterator it) {
       
    41         if (it.next()) {
       
    42             String s = it.get();
       
    43             return (s.length() == 0) || (s.charAt(0) != '-');
       
    44         } else {
       
    45             return false;
       
    46         }
       
    47     }
       
    48 
       
    49     void empty(String key, String message) {
       
    50         if (key != null) {
       
    51             System.err.println("** Error: empty " + key);
       
    52         }
       
    53         if (message != null) {
       
    54             System.err.println(message);
       
    55         }
       
    56         WinGammaPlatform.usage();
       
    57     }
       
    58 
       
    59     static String getCfg(String val) {
       
    60         int under = val.indexOf('_');
       
    61         int len = val.length();
       
    62         if (under != -1 && under < len - 1) {
       
    63             return val.substring(under+1, len);
       
    64         } else {
       
    65             return null;
       
    66         }
       
    67     }
       
    68 }
       
    69 
       
    70 class ArgRuleSpecific extends ArgRule {
       
    71     ArgRuleSpecific(String arg, ArgHandler handler) {
       
    72         super(arg, handler);
       
    73     }
       
    74 
       
    75     boolean match(String rulePattern, String arg) {
       
    76         return rulePattern.startsWith(arg);
       
    77     }
       
    78 }
       
    79 
       
    80 
       
    81 class SpecificHsArgHandler extends HsArgHandler {
       
    82 
       
    83     String message, argKey, valKey;
       
    84     int type;
       
    85 
       
    86     public void handle(ArgIterator it) {
       
    87         String cfg = getCfg(it.get());
       
    88         if (nextNotKey(it)) {
       
    89             String val = it.get();
       
    90             switch (type) {
       
    91             case VECTOR:
       
    92                 BuildConfig.addFieldVector(cfg, valKey, val);
       
    93                 break;
       
    94             case HASH:
       
    95                 BuildConfig.putFieldHash(cfg, valKey, val, "1");
       
    96                 break;
       
    97             case STRING:
       
    98                 BuildConfig.putField(cfg, valKey, val);
       
    99                 break;
       
   100             default:
       
   101                 empty(valKey, "Unknown type: "+type);
       
   102             }
       
   103             it.next();
       
   104 
       
   105         } else {
       
   106             empty(argKey, message);
       
   107         }
       
   108     }
       
   109 
       
   110     SpecificHsArgHandler(String argKey, String valKey, String message, int type) {
       
   111         this.argKey = argKey;
       
   112         this.valKey = valKey;
       
   113         this.message = message;
       
   114         this.type = type;
       
   115     }
       
   116 }
       
   117 
       
   118 
       
   119 class HsArgRule extends ArgRuleSpecific {
       
   120 
       
   121     HsArgRule(String argKey, String valKey, String message, int type) {
       
   122         super(argKey, new SpecificHsArgHandler(argKey, valKey, message, type));
       
   123     }
       
   124 
       
   125 }
       
   126 
       
   127 public abstract class WinGammaPlatform {
       
   128 
       
   129     public boolean fileNameStringEquality(String s1, String s2) {
       
   130         return s1.equalsIgnoreCase(s2);
       
   131     }
       
   132 
       
   133     static void usage() throws IllegalArgumentException {
       
   134         System.err.println("WinGammaPlatform platform-specific options:");
       
   135         System.err.println("  -sourceBase <path to directory (workspace) " +
       
   136                            "containing source files; no trailing slash>");
       
   137         System.err.println("  -projectFileName <full pathname to which project file " +
       
   138                            "will be written; all parent directories must " +
       
   139                            "already exist>");
       
   140         System.err.println("  If any of the above are specified, "+
       
   141                            "they must all be.");
       
   142         System.err.println("  Note: if '-altRelativeInclude' option below " +
       
   143                            "is used, then the '-relativeAltSrcInclude' " +
       
   144                            "option must be used to specify the alternate " +
       
   145                            "source dir, e.g., 'src\\closed'");
       
   146         System.err.println("  Additional, optional arguments, which can be " +
       
   147                            "specified multiple times:");
       
   148         System.err.println("    -absoluteInclude <string containing absolute " +
       
   149                            "path to include directory>");
       
   150         System.err.println("    -altRelativeInclude <string containing " +
       
   151                            "alternate include directory relative to " +
       
   152                            "-sourceBase>");
       
   153         System.err.println("    -relativeInclude <string containing include " +
       
   154                            "directory relative to -sourceBase>");
       
   155         System.err.println("    -define <preprocessor flag to be #defined " +
       
   156                            "(note: doesn't yet support " +
       
   157                            "#define (flag) (value))>");
       
   158         System.err.println("    -startAt <subdir of sourceBase>");
       
   159         System.err.println("    -additionalFile <file not in database but " +
       
   160                            "which should show up in project file>");
       
   161         System.err.println("    -additionalGeneratedFile <absolute path to " +
       
   162                            "directory containing file; no trailing slash> " +
       
   163                            "<name of file generated later in the build process>");
       
   164         throw new IllegalArgumentException();
       
   165     }
       
   166 
       
   167 
       
   168     public void addPerFileLine(Hashtable table,
       
   169                                String fileName,
       
   170                                String line) {
       
   171         Vector v = (Vector) table.get(fileName);
       
   172         if (v != null) {
       
   173             v.add(line);
       
   174         } else {
       
   175             v = new Vector();
       
   176             v.add(line);
       
   177             table.put(fileName, v);
       
   178         }
       
   179     }
       
   180 
       
   181     protected static class PerFileCondData {
       
   182         public String releaseString;
       
   183         public String debugString;
       
   184     }
       
   185 
       
   186     protected void addConditionalPerFileLine(Hashtable table,
       
   187                                            String fileName,
       
   188                                            String releaseLine,
       
   189                                            String debugLine) {
       
   190         PerFileCondData data = new PerFileCondData();
       
   191         data.releaseString = releaseLine;
       
   192         data.debugString = debugLine;
       
   193         Vector v = (Vector) table.get(fileName);
       
   194         if (v != null) {
       
   195             v.add(data);
       
   196         } else {
       
   197             v = new Vector();
       
   198             v.add(data);
       
   199             table.put(fileName, v);
       
   200         }
       
   201     }
       
   202 
       
   203     protected static class PrelinkCommandData {
       
   204       String description;
       
   205       String commands;
       
   206     }
       
   207 
       
   208     protected void addPrelinkCommand(Hashtable table,
       
   209                                      String build,
       
   210                                      String description,
       
   211                                      String commands) {
       
   212       PrelinkCommandData data = new PrelinkCommandData();
       
   213       data.description = description;
       
   214       data.commands = commands;
       
   215       table.put(build, data);
       
   216     }
       
   217 
       
   218     public boolean findString(Vector v, String s) {
       
   219         for (Iterator iter = v.iterator(); iter.hasNext(); ) {
       
   220             if (((String) iter.next()).equals(s)) {
       
   221                 return true;
       
   222             }
       
   223         }
       
   224 
       
   225         return false;
       
   226     }
       
   227 
       
   228      String getProjectName(String fullPath, String extension)
       
   229         throws IllegalArgumentException, IOException {
       
   230         File file = new File(fullPath).getCanonicalFile();
       
   231         fullPath = file.getCanonicalPath();
       
   232         String parent = file.getParent();
       
   233 
       
   234         if (!fullPath.endsWith(extension)) {
       
   235             throw new IllegalArgumentException("project file name \"" +
       
   236                                                fullPath +
       
   237                                                "\" does not end in "+extension);
       
   238         }
       
   239 
       
   240         if ((parent != null) &&
       
   241             (!fullPath.startsWith(parent))) {
       
   242             throw new RuntimeException(
       
   243                 "Internal error: parent of file name \"" + parent +
       
   244                 "\" does not match file name \"" + fullPath + "\""
       
   245             );
       
   246         }
       
   247 
       
   248         int len = parent.length();
       
   249         if (!parent.endsWith(Util.sep)) {
       
   250             len += Util.sep.length();
       
   251         }
       
   252 
       
   253         int end = fullPath.length() - extension.length();
       
   254 
       
   255         if (len == end) {
       
   256             throw new RuntimeException(
       
   257                 "Internal error: file name was empty"
       
   258             );
       
   259         }
       
   260 
       
   261         return fullPath.substring(len, end);
       
   262     }
       
   263 
       
   264     protected abstract String getProjectExt();
       
   265 
       
   266     public void createVcproj(String[] args)
       
   267         throws IllegalArgumentException, IOException {
       
   268 
       
   269         parseArguments(args);
       
   270 
       
   271         String projectFileName = BuildConfig.getFieldString(null, "ProjectFileName");
       
   272         String ext = getProjectExt();
       
   273 
       
   274         String projectName = getProjectName(projectFileName, ext);
       
   275 
       
   276         writeProjectFile(projectFileName, projectName, createAllConfigs(BuildConfig.getFieldString(null, "PlatformName")));
       
   277     }
       
   278 
       
   279     protected void writePrologue(String[] args) {
       
   280         System.err.println("WinGammaPlatform platform-specific arguments:");
       
   281         for (int i = 0; i < args.length; i++) {
       
   282             System.err.print(args[i] + " ");
       
   283         }
       
   284         System.err.println();
       
   285     }
       
   286 
       
   287 
       
   288     void parseArguments(String[] args) {
       
   289         new ArgsParser(args,
       
   290                        new ArgRule[]
       
   291             {
       
   292                 new ArgRule("-sourceBase",
       
   293                             new HsArgHandler() {
       
   294                                 public void handle(ArgIterator it) {
       
   295                                    String cfg = getCfg(it.get());
       
   296                                    if (nextNotKey(it)) {
       
   297                                       String sb = (String) it.get();
       
   298                                       if (sb.endsWith(Util.sep)) {
       
   299                                          sb = sb.substring(0, sb.length() - 1);
       
   300                                       }
       
   301                                       BuildConfig.putField(cfg, "SourceBase", sb);
       
   302                                       it.next();
       
   303                                    } else {
       
   304                                       empty("-sourceBase", null);
       
   305                                    }
       
   306                                 }
       
   307                             }
       
   308                             ),
       
   309 
       
   310                 new HsArgRule("-buildBase",
       
   311                               "BuildBase",
       
   312                               "   (Did you set the HotSpotBuildSpace environment variable?)",
       
   313                               HsArgHandler.STRING
       
   314                               ),
       
   315 
       
   316                new HsArgRule("-buildSpace",
       
   317                               "BuildSpace",
       
   318                               null,
       
   319                               HsArgHandler.STRING
       
   320                               ),
       
   321 
       
   322                new HsArgRule("-makeBinary",
       
   323                               "MakeBinary",
       
   324                               null,
       
   325                               HsArgHandler.STRING
       
   326                               ),
       
   327 
       
   328                new HsArgRule("-makeOutput",
       
   329                               "MakeOutput",
       
   330                               null,
       
   331                               HsArgHandler.STRING
       
   332                               ),
       
   333 
       
   334               new HsArgRule("-platformName",
       
   335                               "PlatformName",
       
   336                               null,
       
   337                               HsArgHandler.STRING
       
   338                               ),
       
   339 
       
   340               new HsArgRule("-projectFileName",
       
   341                               "ProjectFileName",
       
   342                               null,
       
   343                               HsArgHandler.STRING
       
   344                               ),
       
   345 
       
   346                 new HsArgRule("-jdkTargetRoot",
       
   347                               "JdkTargetRoot",
       
   348                               "   (Did you set the HotSpotJDKDist environment variable?)",
       
   349                               HsArgHandler.STRING
       
   350                               ),
       
   351 
       
   352                 new HsArgRule("-compiler",
       
   353                               "CompilerVersion",
       
   354                               "   (Did you set the VcVersion correctly?)",
       
   355                               HsArgHandler.STRING
       
   356                               ),
       
   357 
       
   358                 new HsArgRule("-absoluteInclude",
       
   359                               "AbsoluteInclude",
       
   360                               null,
       
   361                               HsArgHandler.VECTOR
       
   362                               ),
       
   363 
       
   364                 new HsArgRule("-altRelativeInclude",
       
   365                               "AltRelativeInclude",
       
   366                               null,
       
   367                               HsArgHandler.VECTOR
       
   368                               ),
       
   369 
       
   370                 new HsArgRule("-relativeInclude",
       
   371                               "RelativeInclude",
       
   372                               null,
       
   373                               HsArgHandler.VECTOR
       
   374                               ),
       
   375 
       
   376                 new HsArgRule("-absoluteSrcInclude",
       
   377                               "AbsoluteSrcInclude",
       
   378                               null,
       
   379                               HsArgHandler.VECTOR
       
   380                               ),
       
   381 
       
   382                 new HsArgRule("-relativeAltSrcInclude",
       
   383                               "RelativeAltSrcInclude",
       
   384                               null,
       
   385                               HsArgHandler.STRING
       
   386                               ),
       
   387 
       
   388                 new HsArgRule("-relativeSrcInclude",
       
   389                               "RelativeSrcInclude",
       
   390                               null,
       
   391                               HsArgHandler.VECTOR
       
   392                               ),
       
   393 
       
   394                 new HsArgRule("-define",
       
   395                               "Define",
       
   396                               null,
       
   397                               HsArgHandler.VECTOR
       
   398                               ),
       
   399 
       
   400                 new HsArgRule("-useToGeneratePch",
       
   401                               "UseToGeneratePch",
       
   402                               null,
       
   403                               HsArgHandler.STRING
       
   404                               ),
       
   405 
       
   406                 new ArgRuleSpecific("-perFileLine",
       
   407                             new HsArgHandler() {
       
   408                                 public void handle(ArgIterator it) {
       
   409                                     String cfg = getCfg(it.get());
       
   410                                     if (nextNotKey(it)) {
       
   411                                         String fileName = it.get();
       
   412                                         if (nextNotKey(it)) {
       
   413                                             String line = it.get();
       
   414                                             BuildConfig.putFieldHash(cfg, "PerFileLine", fileName, line);
       
   415                                             it.next();
       
   416                                             return;
       
   417                                         }
       
   418                                     }
       
   419                                     empty(null, "** Error: wrong number of args to -perFileLine");
       
   420                                 }
       
   421                             }
       
   422                             ),
       
   423 
       
   424                 new ArgRuleSpecific("-conditionalPerFileLine",
       
   425                             new HsArgHandler() {
       
   426                                 public void handle(ArgIterator it) {
       
   427                                     String cfg = getCfg(it.get());
       
   428                                     if (nextNotKey(it)) {
       
   429                                         String fileName = it.get();
       
   430                                         if (nextNotKey(it)) {
       
   431                                             String productLine = it.get();
       
   432                                             if (nextNotKey(it)) {
       
   433                                                 String debugLine = it.get();
       
   434                                                 BuildConfig.putFieldHash(cfg+"_debug", "CondPerFileLine",
       
   435                                                                          fileName, debugLine);
       
   436                                                 BuildConfig.putFieldHash(cfg+"_product", "CondPerFileLine",
       
   437                                                                          fileName, productLine);
       
   438                                                 it.next();
       
   439                                                 return;
       
   440                                             }
       
   441                                         }
       
   442                                     }
       
   443 
       
   444                                     empty(null, "** Error: wrong number of args to -conditionalPerFileLine");
       
   445                                 }
       
   446                             }
       
   447                             ),
       
   448 
       
   449                 new HsArgRule("-disablePch",
       
   450                               "DisablePch",
       
   451                               null,
       
   452                               HsArgHandler.HASH
       
   453                               ),
       
   454 
       
   455                 new ArgRule("-startAt",
       
   456                             new HsArgHandler() {
       
   457                                 public void handle(ArgIterator it) {
       
   458                                     if (BuildConfig.getField(null, "StartAt") != null) {
       
   459                                         empty(null, "** Error: multiple -startAt");
       
   460                                     }
       
   461                                     if (nextNotKey(it)) {
       
   462                                         BuildConfig.putField(null, "StartAt", it.get());
       
   463                                         it.next();
       
   464                                     } else {
       
   465                                         empty("-startAt", null);
       
   466                                     }
       
   467                                 }
       
   468                             }
       
   469                             ),
       
   470 
       
   471                 new HsArgRule("-ignoreFile",
       
   472                                       "IgnoreFile",
       
   473                                       null,
       
   474                                       HsArgHandler.HASH
       
   475                                       ),
       
   476 
       
   477                 new HsArgRule("-ignorePath",
       
   478                               "IgnorePath",
       
   479                               null,
       
   480                               HsArgHandler.VECTOR
       
   481                               ),
       
   482 
       
   483                 new HsArgRule("-hidePath",
       
   484                       "HidePath",
       
   485                       null,
       
   486                       HsArgHandler.VECTOR
       
   487                       ),
       
   488 
       
   489                 new HsArgRule("-additionalFile",
       
   490                               "AdditionalFile",
       
   491                               null,
       
   492                               HsArgHandler.VECTOR
       
   493                               ),
       
   494 
       
   495                 new ArgRuleSpecific("-additionalGeneratedFile",
       
   496                             new HsArgHandler() {
       
   497                                 public void handle(ArgIterator it) {
       
   498                                     String cfg = getCfg(it.get());
       
   499                                     if (nextNotKey(it)) {
       
   500                                         String dir = it.get();
       
   501                                         if (nextNotKey(it)) {
       
   502                                             String fileName = it.get();
       
   503                                             BuildConfig.putFieldHash(cfg, "AdditionalGeneratedFile",
       
   504                                                                      Util.normalize(dir + Util.sep + fileName),
       
   505                                                                      fileName);
       
   506                                             it.next();
       
   507                                             return;
       
   508                                         }
       
   509                                     }
       
   510                                     empty(null, "** Error: wrong number of args to -additionalGeneratedFile");
       
   511                                 }
       
   512                             }
       
   513                             ),
       
   514 
       
   515                 new ArgRule("-prelink",
       
   516                             new HsArgHandler() {
       
   517                                 public void handle(ArgIterator it) {
       
   518                                     if (nextNotKey(it)) {
       
   519                                         if (nextNotKey(it)) {
       
   520                                             String description = it.get();
       
   521                                             if (nextNotKey(it)) {
       
   522                                                 String command = it.get();
       
   523                                                 BuildConfig.putField(null, "PrelinkDescription", description);
       
   524                                                 BuildConfig.putField(null, "PrelinkCommand", command);
       
   525                                                 it.next();
       
   526                                                 return;
       
   527                                             }
       
   528                                         }
       
   529                                     }
       
   530 
       
   531                                     empty(null,  "** Error: wrong number of args to -prelink");
       
   532                                 }
       
   533                             }
       
   534                             ),
       
   535 
       
   536                 new ArgRule("-postbuild",
       
   537                             new HsArgHandler() {
       
   538                                 public void handle(ArgIterator it) {
       
   539                                     if (nextNotKey(it)) {
       
   540                                         if (nextNotKey(it)) {
       
   541                                             String description = it.get();
       
   542                                             if (nextNotKey(it)) {
       
   543                                                 String command = it.get();
       
   544                                                 BuildConfig.putField(null, "PostbuildDescription", description);
       
   545                                                 BuildConfig.putField(null, "PostbuildCommand", command);
       
   546                                                 it.next();
       
   547                                                 return;
       
   548                                             }
       
   549                                         }
       
   550                                     }
       
   551 
       
   552                                     empty(null,  "** Error: wrong number of args to -postbuild");
       
   553                                 }
       
   554                             }
       
   555                             ),
       
   556             },
       
   557                                        new ArgHandler() {
       
   558                                            public void handle(ArgIterator it) {
       
   559 
       
   560                                                throw new RuntimeException("Arg Parser: unrecognized option "+it.get());
       
   561                                            }
       
   562                                        }
       
   563                                        );
       
   564         if (BuildConfig.getField(null, "SourceBase") == null      ||
       
   565             BuildConfig.getField(null, "BuildBase") == null       ||
       
   566             BuildConfig.getField(null, "ProjectFileName") == null ||
       
   567             BuildConfig.getField(null, "CompilerVersion") == null) {
       
   568             usage();
       
   569         }
       
   570 
       
   571         BuildConfig.putField(null, "PlatformObject", this);
       
   572     }
       
   573 
       
   574     Vector createAllConfigs(String platform) {
       
   575         Vector allConfigs = new Vector();
       
   576 
       
   577         allConfigs.add(new C1DebugConfig());
       
   578         allConfigs.add(new C1FastDebugConfig());
       
   579         allConfigs.add(new C1ProductConfig());
       
   580 
       
   581         allConfigs.add(new TieredDebugConfig());
       
   582         allConfigs.add(new TieredFastDebugConfig());
       
   583         allConfigs.add(new TieredProductConfig());
       
   584 
       
   585         return allConfigs;
       
   586     }
       
   587 
       
   588     PrintWriter printWriter;
       
   589 
       
   590     public void writeProjectFile(String projectFileName, String projectName,
       
   591                                  Vector<BuildConfig> allConfigs) throws IOException {
       
   592         throw new RuntimeException("use compiler version specific version");
       
   593     }
       
   594 
       
   595     int indent;
       
   596     private Stack<String> tagStack = new Stack<String>();
       
   597 
       
   598     private void startTagPrim(String name, String[] attrs, boolean close) {
       
   599        startTagPrim(name, attrs, close, true);
       
   600     }
       
   601 
       
   602     private void startTagPrim(String name, String[] attrs, boolean close,
       
   603           boolean newline) {
       
   604        doIndent();
       
   605        printWriter.print("<" + name);
       
   606        indent++;
       
   607 
       
   608        if (attrs != null && attrs.length > 0) {
       
   609           for (int i = 0; i < attrs.length; i += 2) {
       
   610              printWriter.print(" " + attrs[i] + "=\"" + attrs[i + 1] + "\"");
       
   611              if (i < attrs.length - 2) {
       
   612              }
       
   613           }
       
   614        }
       
   615 
       
   616        if (close) {
       
   617           indent--;
       
   618           printWriter.print(" />");
       
   619        } else {
       
   620           // TODO push tag name, and change endTag to pop and print.
       
   621           tagStack.push(name);
       
   622           printWriter.print(">");
       
   623        }
       
   624        if (newline) {
       
   625           printWriter.println();
       
   626        }
       
   627     }
       
   628 
       
   629     void startTag(String name, String... attrs) {
       
   630        startTagPrim(name, attrs, false);
       
   631     }
       
   632 
       
   633     void startTagV(String name, Vector attrs) {
       
   634        String s[] = new String[attrs.size()];
       
   635        for (int i = 0; i < attrs.size(); i++) {
       
   636           s[i] = (String) attrs.elementAt(i);
       
   637        }
       
   638        startTagPrim(name, s, false);
       
   639     }
       
   640 
       
   641     void endTag() {
       
   642        String name = tagStack.pop();
       
   643        indent--;
       
   644        doIndent();
       
   645        printWriter.println("</" + name + ">");
       
   646     }
       
   647 
       
   648     private void endTagNoIndent() {
       
   649        String name = tagStack.pop();
       
   650        indent--;
       
   651        printWriter.println("</" + name + ">");
       
   652     }
       
   653 
       
   654     void tag(String name, String... attrs) {
       
   655        startTagPrim(name, attrs, true);
       
   656     }
       
   657 
       
   658     void tagData(String name, String data) {
       
   659        startTagPrim(name, null, false, false);
       
   660        printWriter.print(data);
       
   661        endTagNoIndent();
       
   662     }
       
   663 
       
   664     void tagData(String name, String data, String... attrs) {
       
   665        startTagPrim(name, attrs, false, false);
       
   666        printWriter.print(data);
       
   667        endTagNoIndent();
       
   668     }
       
   669 
       
   670     void tagV(String name, Vector attrs) {
       
   671        String s[] = new String[attrs.size()];
       
   672        for (int i = 0; i < attrs.size(); i++) {
       
   673           s[i] = (String) attrs.elementAt(i);
       
   674        }
       
   675        startTagPrim(name, s, true);
       
   676     }
       
   677 
       
   678     void doIndent() {
       
   679        for (int i = 0; i < indent; i++) {
       
   680           printWriter.print("  ");
       
   681        }
       
   682     }
       
   683 
       
   684 
       
   685 }