1 /*
   2  * Copyright (c) 1999, 2010, 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 import java.io.*;
  26 import java.util.*;
  27 
  28 abstract class HsArgHandler extends ArgHandler {
  29     static final int STRING = 1;
  30     static final int VECTOR = 2;
  31     static final int HASH   = 3;
  32 
  33     boolean nextNotKey(ArgIterator it) {
  34         if (it.next()) {
  35             String s = it.get();
  36             return (s.length() == 0) || (s.charAt(0) != '-');
  37         } else {
  38             return false;
  39         }
  40     }
  41 
  42     void empty(String key, String message) {
  43         if (key != null) {
  44             System.err.println("** Error: empty " + key);
  45         }
  46         if (message != null) {
  47             System.err.println(message);
  48         }
  49         WinGammaPlatform.usage();
  50     }
  51 
  52     static String getCfg(String val) {
  53         int under = val.indexOf('_');
  54         int len = val.length();
  55         if (under != -1 && under < len - 1) {
  56             return val.substring(under+1, len);
  57         } else {
  58             return null;
  59         }
  60     }
  61 }
  62 
  63 class ArgRuleSpecific extends ArgRule {
  64     ArgRuleSpecific(String arg, ArgHandler handler) {
  65         super(arg, handler);
  66     }
  67 
  68     boolean match(String rulePattern, String arg) {
  69         return rulePattern.startsWith(arg);
  70     }
  71 }
  72 
  73 
  74 class SpecificHsArgHandler extends HsArgHandler {
  75 
  76     String message, argKey, valKey;
  77     int type;
  78 
  79     public void handle(ArgIterator it) {
  80         String cfg = getCfg(it.get());
  81         if (nextNotKey(it)) {
  82             String val = it.get();
  83             switch (type) {
  84             case VECTOR:
  85                 BuildConfig.addFieldVector(cfg, valKey, val);
  86                 break;
  87             case HASH:
  88                 BuildConfig.putFieldHash(cfg, valKey, val, "1");
  89                 break;
  90             case STRING:
  91                 BuildConfig.putField(cfg, valKey, val);
  92                 break;
  93             default:
  94                 empty(valKey, "Unknown type: "+type);
  95             }
  96             it.next();
  97 
  98         } else {
  99             empty(argKey, message);
 100         }
 101     }
 102 
 103     SpecificHsArgHandler(String argKey, String valKey, String message, int type) {
 104         this.argKey = argKey;
 105         this.valKey = valKey;
 106         this.message = message;
 107         this.type = type;
 108     }
 109 }
 110 
 111 
 112 class HsArgRule extends ArgRuleSpecific {
 113 
 114     HsArgRule(String argKey, String valKey, String message, int type) {
 115         super(argKey, new SpecificHsArgHandler(argKey, valKey, message, type));
 116     }
 117 
 118 }
 119 
 120 public abstract class WinGammaPlatform {
 121     
 122     public boolean fileNameStringEquality(String s1, String s2) {
 123         return s1.equalsIgnoreCase(s2);
 124     }
 125 
 126     static void usage() throws IllegalArgumentException {
 127         System.err.println("WinGammaPlatform platform-specific options:");
 128         System.err.println("  -sourceBase <path to directory (workspace) " +
 129                            "containing source files; no trailing slash>");
 130         System.err.println("  -projectFileName <full pathname to which project file " +
 131                            "will be written; all parent directories must " +
 132                            "already exist>");
 133         System.err.println("  If any of the above are specified, "+
 134                            "they must all be.");
 135         System.err.println("  Additional, optional arguments, which can be " +
 136                            "specified multiple times:");
 137         System.err.println("    -absoluteInclude <string containing absolute " +
 138                            "path to include directory>");
 139         System.err.println("    -relativeInclude <string containing include " +
 140                            "directory relative to -sourceBase>");
 141         System.err.println("    -define <preprocessor flag to be #defined " +
 142                            "(note: doesn't yet support " +
 143                            "#define (flag) (value))>");
 144         System.err.println("    -startAt <subdir of sourceBase>");
 145         System.err.println("    -additionalFile <file not in database but " +
 146                            "which should show up in project file>");
 147         System.err.println("    -additionalGeneratedFile <absolute path to " +
 148                            "directory containing file; no trailing slash> " +
 149                            "<name of file generated later in the build process>");
 150         throw new IllegalArgumentException();
 151     }
 152 
 153 
 154     public void addPerFileLine(Hashtable table,
 155                                String fileName,
 156                                String line) {
 157         Vector v = (Vector) table.get(fileName);
 158         if (v != null) {
 159             v.add(line);
 160         } else {
 161             v = new Vector();
 162             v.add(line);
 163             table.put(fileName, v);
 164         }
 165     }
 166 
 167     protected static class PerFileCondData {
 168         public String releaseString;
 169         public String debugString;
 170     }
 171 
 172     protected void addConditionalPerFileLine(Hashtable table,
 173                                            String fileName,
 174                                            String releaseLine,
 175                                            String debugLine) {
 176         PerFileCondData data = new PerFileCondData();
 177         data.releaseString = releaseLine;
 178         data.debugString = debugLine;
 179         Vector v = (Vector) table.get(fileName);
 180         if (v != null) {
 181             v.add(data);
 182         } else {
 183             v = new Vector();
 184             v.add(data);
 185             table.put(fileName, v);
 186         }
 187     }
 188 
 189     protected static class PrelinkCommandData {
 190       String description;
 191       String commands;
 192     }
 193 
 194     protected void addPrelinkCommand(Hashtable table,
 195                                      String build,
 196                                      String description,
 197                                      String commands) {
 198       PrelinkCommandData data = new PrelinkCommandData();
 199       data.description = description;
 200       data.commands = commands;
 201       table.put(build, data);
 202     }
 203 
 204     public boolean findString(Vector v, String s) {
 205         for (Iterator iter = v.iterator(); iter.hasNext(); ) {
 206             if (((String) iter.next()).equals(s)) {
 207                 return true;
 208             }
 209         }
 210 
 211         return false;
 212     }
 213 
 214     /* This returns a String containing the full path to the passed
 215        file name, or null if an error occurred. If the file was not
 216        found or was a duplicate and couldn't be resolved using the
 217        preferred paths, the file name is added to the appropriate
 218        Vector of Strings. */
 219     private String findFileInDirectory(String fileName,
 220                                        DirectoryTree directory,
 221                                        Vector preferredPaths,
 222                                        Vector filesNotFound,
 223                                        Vector filesDuplicate) {
 224         List locationsInTree = directory.findFile(fileName);
 225         int  rootNameLength = directory.getRootNodeName().length();
 226         String name = null;
 227         if ((locationsInTree == null) ||
 228             (locationsInTree.size() == 0)) {
 229             filesNotFound.add(fileName);
 230         } else if (locationsInTree.size() > 1) {
 231             // We shouldn't have duplicate file names in our workspace.
 232             System.err.println();
 233             System.err.println("There are multiple files named as: " + fileName);
 234             System.exit(-1);
 235             // The following code could be safely removed if we don't need duplicate
 236             // file names.
 237 
 238             // Iterate through them, trying to find one with a
 239             // preferred path
 240         search:
 241             {
 242                 for (Iterator locIter = locationsInTree.iterator();
 243                      locIter.hasNext(); ) {
 244                     DirectoryTreeNode node =
 245                         (DirectoryTreeNode) locIter.next();
 246                     String tmpName = node.getName();
 247                     for (Iterator prefIter = preferredPaths.iterator();
 248                          prefIter.hasNext(); ) {
 249                         // We need to make sure the preferred path is
 250                         // found from the file path not including the root node name.
 251                         if (tmpName.indexOf((String)prefIter.next(),
 252                                             rootNameLength) != -1) {
 253                             name = tmpName;
 254                             break search;
 255                         }
 256                     }
 257                 }
 258             }
 259 
 260             if (name == null) {
 261                 filesDuplicate.add(fileName);
 262             }
 263         } else {
 264             name = ((DirectoryTreeNode) locationsInTree.get(0)).getName();
 265         }
 266 
 267         return name;
 268     }
 269 
 270     protected String envVarPrefixedFileName(String fileName,
 271                                             int sourceBaseLen,
 272                                             DirectoryTree tree,
 273                                             Vector preferredPaths,
 274                                             Vector filesNotFound,
 275                                             Vector filesDuplicate) {
 276         String fullName = findFileInDirectory(fileName,
 277                                               tree,
 278                                               preferredPaths,
 279                                               filesNotFound,
 280                                               filesDuplicate);
 281         return fullName;
 282     }
 283 
 284      String getProjectName(String fullPath, String extension)
 285         throws IllegalArgumentException, IOException {
 286         File file = new File(fullPath).getCanonicalFile();
 287         fullPath = file.getCanonicalPath();
 288         String parent = file.getParent();
 289 
 290         if (!fullPath.endsWith(extension)) {
 291             throw new IllegalArgumentException("project file name \"" +
 292                                                fullPath +
 293                                                "\" does not end in "+extension);
 294         }
 295 
 296         if ((parent != null) &&
 297             (!fullPath.startsWith(parent))) {
 298             throw new RuntimeException(
 299                 "Internal error: parent of file name \"" + parent +
 300                 "\" does not match file name \"" + fullPath + "\""
 301             );
 302         }
 303 
 304         int len = parent.length();
 305         if (!parent.endsWith(Util.sep)) {
 306             len += Util.sep.length();
 307         }
 308 
 309         int end = fullPath.length() - extension.length();
 310 
 311         if (len == end) {
 312             throw new RuntimeException(
 313                 "Internal error: file name was empty"
 314             );
 315         }
 316 
 317         return fullPath.substring(len, end);
 318     }
 319 
 320     protected abstract String getProjectExt();
 321 
 322     public void createVcproj(String[] args)
 323         throws IllegalArgumentException, IOException {
 324 
 325         parseArguments(args);
 326 
 327         String projectFileName = BuildConfig.getFieldString(null, "ProjectFileName");
 328         String ext = getProjectExt();
 329 
 330         String projectName = getProjectName(projectFileName, ext);
 331 
 332         writeProjectFile(projectFileName, projectName, createAllConfigs());
 333     }
 334 
 335     protected void writePrologue(String[] args) {
 336         System.err.println("WinGammaPlatform platform-specific arguments:");
 337         for (int i = 0; i < args.length; i++) {
 338             System.err.print(args[i] + " ");
 339         }
 340         System.err.println();
 341     }
 342 
 343 
 344     void parseArguments(String[] args) {
 345         new ArgsParser(args,
 346                        new ArgRule[]
 347             {
 348                 new HsArgRule("-sourceBase",
 349                               "SourceBase",
 350                               "   (Did you set the HotSpotWorkSpace environment variable?)",
 351                               HsArgHandler.STRING
 352                               ),
 353 
 354                 new HsArgRule("-buildBase",
 355                               "BuildBase",
 356                               "   (Did you set the HotSpotBuildSpace environment variable?)",
 357                               HsArgHandler.STRING
 358                               ),
 359 
 360                 new HsArgRule("-projectFileName",
 361                               "ProjectFileName",
 362                               null,
 363                               HsArgHandler.STRING
 364                               ),
 365 
 366                 new HsArgRule("-jdkTargetRoot",
 367                               "JdkTargetRoot",
 368                               "   (Did you set the HotSpotJDKDist environment variable?)",
 369                               HsArgHandler.STRING
 370                               ),
 371 
 372                 new HsArgRule("-compiler",
 373                               "CompilerVersion",
 374                               "   (Did you set the VcVersion correctly?)",
 375                               HsArgHandler.STRING
 376                               ),
 377 
 378                 new HsArgRule("-platform",
 379                               "Platform",
 380                               null,
 381                               HsArgHandler.STRING
 382                               ),
 383 
 384                 new HsArgRule("-absoluteInclude",
 385                               "AbsoluteInclude",
 386                               null,
 387                               HsArgHandler.VECTOR
 388                               ),
 389 
 390                 new HsArgRule("-relativeInclude",
 391                               "RelativeInclude",
 392                               null,
 393                               HsArgHandler.VECTOR
 394                               ),
 395 
 396                 new HsArgRule("-define",
 397                               "Define",
 398                               null,
 399                               HsArgHandler.VECTOR
 400                               ),
 401 
 402                 new HsArgRule("-useToGeneratePch",
 403                               "UseToGeneratePch",
 404                               null,
 405                               HsArgHandler.STRING
 406                               ),
 407 
 408                 new ArgRuleSpecific("-perFileLine",
 409                             new HsArgHandler() {
 410                                 public void handle(ArgIterator it) {
 411                                     String cfg = getCfg(it.get());
 412                                     if (nextNotKey(it)) {
 413                                         String fileName = it.get();
 414                                         if (nextNotKey(it)) {
 415                                             String line = it.get();
 416                                             BuildConfig.putFieldHash(cfg, "PerFileLine", fileName, line);
 417                                             it.next();
 418                                             return;
 419                                         }
 420                                     }
 421                                     empty(null, "** Error: wrong number of args to -perFileLine");
 422                                 }
 423                             }
 424                             ),
 425 
 426                 new ArgRuleSpecific("-conditionalPerFileLine",
 427                             new HsArgHandler() {
 428                                 public void handle(ArgIterator it) {
 429                                     String cfg = getCfg(it.get());
 430                                     if (nextNotKey(it)) {
 431                                         String fileName = it.get();
 432                                         if (nextNotKey(it)) {
 433                                             String productLine = it.get();
 434                                             if (nextNotKey(it)) {
 435                                                 String debugLine = it.get();
 436                                                 BuildConfig.putFieldHash(cfg+"_debug", "CondPerFileLine",
 437                                                                          fileName, debugLine);
 438                                                 BuildConfig.putFieldHash(cfg+"_product", "CondPerFileLine",
 439                                                                          fileName, productLine);
 440                                                 it.next();
 441                                                 return;
 442                                             }
 443                                         }
 444                                     }
 445 
 446                                     empty(null, "** Error: wrong number of args to -conditionalPerFileLine");
 447                                 }
 448                             }
 449                             ),
 450 
 451                 new HsArgRule("-disablePch",
 452                               "DisablePch",
 453                               null,
 454                               HsArgHandler.HASH
 455                               ),
 456 
 457                 new ArgRule("-startAt",
 458                             new HsArgHandler() {
 459                                 public void handle(ArgIterator it) {
 460                                     if (BuildConfig.getField(null, "StartAt") != null) {
 461                                         empty(null, "** Error: multiple -startAt");
 462                                     }
 463                                     if (nextNotKey(it)) {
 464                                         BuildConfig.putField(null, "StartAt", it.get());
 465                                         it.next();
 466                                     } else {
 467                                         empty("-startAt", null);
 468                                     }
 469                                 }
 470                             }
 471                             ),
 472 
 473                 new HsArgRule("-ignoreFile",
 474                                       "IgnoreFile",
 475                                       null,
 476                                       HsArgHandler.HASH
 477                                       ),
 478 
 479                 new HsArgRule("-ignorePath",
 480                               "IgnorePath",
 481                               null,
 482                               HsArgHandler.VECTOR
 483                               ),
 484 
 485                 new HsArgRule("-additionalFile",
 486                               "AdditionalFile",
 487                               null,
 488                               HsArgHandler.VECTOR
 489                               ),
 490 
 491                 new ArgRuleSpecific("-additionalGeneratedFile",
 492                             new HsArgHandler() {
 493                                 public void handle(ArgIterator it) {
 494                                     String cfg = getCfg(it.get());
 495                                     if (nextNotKey(it)) {
 496                                         String dir = it.get();
 497                                         if (nextNotKey(it)) {
 498                                             String fileName = it.get();
 499                                             // we ignore files that we know are generated, so we coudn't
 500                                             // find them in sources
 501                                             BuildConfig.putFieldHash(cfg, "IgnoreFile",  fileName, "1");
 502                                             BuildConfig.putFieldHash(cfg, "AdditionalGeneratedFile",
 503                                                                      Util.normalize(dir + Util.sep + fileName),
 504                                                                      fileName);
 505                                             it.next();
 506                                             return;
 507                                         }
 508                                     }
 509                                     empty(null, "** Error: wrong number of args to -additionalGeneratedFile");
 510                                 }
 511                             }
 512                             ),
 513 
 514                 new ArgRule("-prelink",
 515                             new HsArgHandler() {
 516                                 public void handle(ArgIterator it) {
 517                                     if (nextNotKey(it)) {
 518                                         String build = it.get();
 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 ArgHandler() {
 537                                            public void handle(ArgIterator it) {
 538 
 539                                                throw new RuntimeException("Arg Parser: unrecognized option "+it.get());
 540                                            }
 541                                        }
 542                                        );
 543         if (BuildConfig.getField(null, "SourceBase") == null      ||
 544             BuildConfig.getField(null, "BuildBase") == null       ||
 545             BuildConfig.getField(null, "ProjectFileName") == null ||
 546             BuildConfig.getField(null, "CompilerVersion") == null) {
 547             usage();
 548         }
 549 
 550         if (BuildConfig.getField(null, "UseToGeneratePch") == null) {
 551             throw new RuntimeException("ERROR: need to specify one file to compute PCH, with -useToGeneratePch flag");
 552         }
 553 
 554         BuildConfig.putField(null, "PlatformObject", this);
 555     }
 556 
 557     Vector createAllConfigs() {
 558         Vector allConfigs = new Vector();
 559 
 560         allConfigs.add(new C1DebugConfig());
 561 
 562         boolean b = true;
 563         if (b) {
 564             allConfigs.add(new C1FastDebugConfig());
 565             allConfigs.add(new C1ProductConfig());
 566 
 567             allConfigs.add(new C2DebugConfig());
 568             allConfigs.add(new C2FastDebugConfig());
 569             allConfigs.add(new C2ProductConfig());
 570 
 571             allConfigs.add(new TieredDebugConfig());
 572             allConfigs.add(new TieredFastDebugConfig());
 573             allConfigs.add(new TieredProductConfig());
 574 
 575             allConfigs.add(new CoreDebugConfig());
 576             allConfigs.add(new CoreFastDebugConfig());
 577             allConfigs.add(new CoreProductConfig());
 578 
 579             allConfigs.add(new KernelDebugConfig());
 580             allConfigs.add(new KernelFastDebugConfig());
 581             allConfigs.add(new KernelProductConfig());
 582         }
 583 
 584         return allConfigs;
 585     }
 586 
 587     class FileAttribute {
 588         int     numConfigs;
 589         Vector  configs;
 590         String  shortName;
 591         boolean noPch, pchRoot;
 592 
 593         FileAttribute(String shortName, BuildConfig cfg, int numConfigs) {
 594             this.shortName = shortName;
 595             this.noPch =  (cfg.lookupHashFieldInContext("DisablePch", shortName) != null);
 596             this.pchRoot = shortName.equals(BuildConfig.getFieldString(null, "UseToGeneratePch"));
 597             this.numConfigs = numConfigs;
 598 
 599             configs = new Vector();
 600             add(cfg.get("Name"));
 601         }
 602 
 603         void add(String confName) {
 604             configs.add(confName);
 605 
 606             // if presented in all configs
 607             if (configs.size() == numConfigs) {
 608                 configs = null;
 609             }
 610         }
 611     }
 612 
 613     class FileInfo implements Comparable {
 614         String        full;
 615         FileAttribute attr;
 616 
 617         FileInfo(String full, FileAttribute  attr) {
 618             this.full = full;
 619             this.attr = attr;
 620         }
 621 
 622         public int compareTo(Object o) {
 623             FileInfo oo = (FileInfo)o;
 624             // Don't squelch identical short file names where the full
 625             // paths are different
 626             if (!attr.shortName.equals(oo.attr.shortName))
 627               return attr.shortName.compareTo(oo.attr.shortName);
 628             return full.compareTo(oo.full);
 629         }
 630 
 631         boolean isHeader() {
 632             return attr.shortName.endsWith(".h") || attr.shortName.endsWith(".hpp");
 633         }
 634     }
 635 
 636 
 637     TreeSet sortFiles(Hashtable allFiles) {
 638         TreeSet rv = new TreeSet();
 639         Enumeration e = allFiles.keys();
 640         while (e.hasMoreElements()) {
 641             String fullPath = (String)e.nextElement();
 642             rv.add(new FileInfo(fullPath, (FileAttribute)allFiles.get(fullPath)));
 643         }
 644         return rv;
 645     }
 646 
 647     Hashtable computeAttributedFiles(Vector allConfigs) {
 648         Hashtable ht = new Hashtable();
 649         int numConfigs = allConfigs.size();
 650 
 651         for (Iterator i = allConfigs.iterator(); i.hasNext(); ) {
 652             BuildConfig bc = (BuildConfig)i.next();
 653             Hashtable  confFiles = (Hashtable)bc.getSpecificField("AllFilesHash");
 654             String confName = bc.get("Name");
 655 
 656             for (Enumeration e=confFiles.keys(); e.hasMoreElements(); ) {
 657                 String filePath = (String)e.nextElement();
 658                 FileAttribute fa = (FileAttribute)ht.get(filePath);
 659 
 660                 if (fa == null) {
 661                     fa = new FileAttribute((String)confFiles.get(filePath), bc, numConfigs);
 662                     ht.put(filePath, fa);
 663                 } else {
 664                     fa.add(confName);
 665                 }
 666             }
 667         }
 668 
 669         return ht;
 670     }
 671 
 672      Hashtable computeAttributedFiles(BuildConfig bc) {
 673         Hashtable ht = new Hashtable();
 674         Hashtable confFiles = (Hashtable)bc.getSpecificField("AllFilesHash");
 675 
 676         for (Enumeration e = confFiles.keys(); e.hasMoreElements(); ) {
 677             String filePath = (String)e.nextElement();
 678             ht.put(filePath,  new FileAttribute((String)confFiles.get(filePath), bc, 1));
 679         }
 680 
 681         return ht;
 682     }
 683 
 684     PrintWriter printWriter;
 685 
 686     public void writeProjectFile(String projectFileName, String projectName,
 687                                  Vector allConfigs) throws IOException {
 688         throw new RuntimeException("use compiler version specific version");
 689     }
 690 }