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