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