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 }