1 /*
   2  * Copyright (c) 1999, 2007, 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 extends Platform {
 121     public void setupFileTemplates() {
 122         inclFileTemplate = new FileName(this,
 123             "incls\\", "_", "",                      ".incl", "", ""
 124         );
 125         giFileTemplate = new FileName(this,
 126             "incls\\", "",  "_precompiled", ".incl", "", ""
 127         );
 128         gdFileTemplate = new FileName(this,
 129             "", "",  "Dependencies",         "",      "", ""
 130         );
 131     }
 132 
 133     private static String[] suffixes = { ".cpp", ".c" };
 134 
 135     public String[] outerSuffixes() {
 136         return suffixes;
 137     }
 138 
 139     public String objFileSuffix() {
 140         return ".obj";
 141     }
 142 
 143     public String asmFileSuffix() {
 144         return ".i";
 145     }
 146 
 147     public String dependentPrefix() {
 148         return "$(VM_PATH)";
 149     }
 150 
 151     public boolean includeGIInEachIncl() {
 152         return false;
 153     }
 154 
 155     public boolean fileNameStringEquality(String s1, String s2) {
 156         return s1.equalsIgnoreCase(s2);
 157     }
 158 
 159     static void usage() throws IllegalArgumentException {
 160         System.err.println("WinGammaPlatform platform-specific options:");
 161         System.err.println("  -sourceBase <path to directory (workspace) " +
 162                            "containing source files; no trailing slash>");
 163         System.err.println("  -projectFileName <full pathname to which project file " +
 164                            "will be written; all parent directories must " +
 165                            "already exist>");
 166         System.err.println("  If any of the above are specified, "+
 167                            "they must all be.");
 168         System.err.println("  Additional, optional arguments, which can be " +
 169                            "specified multiple times:");
 170         System.err.println("    -absoluteInclude <string containing absolute " +
 171                            "path to include directory>");
 172         System.err.println("    -relativeInclude <string containing include " +
 173                            "directory relative to -sourceBase>");
 174         System.err.println("    -define <preprocessor flag to be #defined " +
 175                            "(note: doesn't yet support " +
 176                            "#define (flag) (value))>");
 177         System.err.println("    -startAt <subdir of sourceBase>");
 178         System.err.println("    -additionalFile <file not in database but " +
 179                            "which should show up in project file, like " +
 180                            "includeDB_core>");
 181         System.err.println("    -additionalGeneratedFile <absolute path to " +
 182                            "directory containing file; no trailing slash> " +
 183                            "<name of file generated later in the build process>");
 184         throw new IllegalArgumentException();
 185     }
 186 
 187 
 188     public void addPerFileLine(Hashtable table,
 189                                String fileName,
 190                                String line) {
 191         Vector v = (Vector) table.get(fileName);
 192         if (v != null) {
 193             v.add(line);
 194         } else {
 195             v = new Vector();
 196             v.add(line);
 197             table.put(fileName, v);
 198         }
 199     }
 200 
 201     protected static class PerFileCondData {
 202         public String releaseString;
 203         public String debugString;
 204     }
 205 
 206     protected void addConditionalPerFileLine(Hashtable table,
 207                                            String fileName,
 208                                            String releaseLine,
 209                                            String debugLine) {
 210         PerFileCondData data = new PerFileCondData();
 211         data.releaseString = releaseLine;
 212         data.debugString = debugLine;
 213         Vector v = (Vector) table.get(fileName);
 214         if (v != null) {
 215             v.add(data);
 216         } else {
 217             v = new Vector();
 218             v.add(data);
 219             table.put(fileName, v);
 220         }
 221     }
 222 
 223     protected static class PrelinkCommandData {
 224       String description;
 225       String commands;
 226     }
 227 
 228     protected void addPrelinkCommand(Hashtable table,
 229                                      String build,
 230                                      String description,
 231                                      String commands) {
 232       PrelinkCommandData data = new PrelinkCommandData();
 233       data.description = description;
 234       data.commands = commands;
 235       table.put(build, data);
 236     }
 237 
 238     public boolean findString(Vector v, String s) {
 239         for (Iterator iter = v.iterator(); iter.hasNext(); ) {
 240             if (((String) iter.next()).equals(s)) {
 241                 return true;
 242             }
 243         }
 244 
 245         return false;
 246     }
 247 
 248     /* This returns a String containing the full path to the passed
 249        file name, or null if an error occurred. If the file was not
 250        found or was a duplicate and couldn't be resolved using the
 251        preferred paths, the file name is added to the appropriate
 252        Vector of Strings. */
 253     private String findFileInDirectory(String fileName,
 254                                        DirectoryTree directory,
 255                                        Vector preferredPaths,
 256                                        Vector filesNotFound,
 257                                        Vector filesDuplicate) {
 258         List locationsInTree = directory.findFile(fileName);
 259         int  rootNameLength = directory.getRootNodeName().length();
 260         String name = null;
 261         if ((locationsInTree == null) ||
 262             (locationsInTree.size() == 0)) {
 263             filesNotFound.add(fileName);
 264         } else if (locationsInTree.size() > 1) {
 265             // We shouldn't have duplicate file names in our workspace.
 266             System.err.println();
 267             System.err.println("There are multiple files named as: " + fileName);
 268             System.exit(-1);
 269             // The following code could be safely removed if we don't need duplicate
 270             // file names.
 271 
 272             // Iterate through them, trying to find one with a
 273             // preferred path
 274         search:
 275             {
 276                 for (Iterator locIter = locationsInTree.iterator();
 277                      locIter.hasNext(); ) {
 278                     DirectoryTreeNode node =
 279                         (DirectoryTreeNode) locIter.next();
 280                     String tmpName = node.getName();
 281                     for (Iterator prefIter = preferredPaths.iterator();
 282                          prefIter.hasNext(); ) {
 283                         // We need to make sure the preferred path is
 284                         // found from the file path not including the root node name.
 285                         if (tmpName.indexOf((String)prefIter.next(),
 286                                             rootNameLength) != -1) {
 287                             name = tmpName;
 288                             break search;
 289                         }
 290                     }
 291                 }
 292             }
 293 
 294             if (name == null) {
 295                 filesDuplicate.add(fileName);
 296             }
 297         } else {
 298             name = ((DirectoryTreeNode) locationsInTree.get(0)).getName();
 299         }
 300 
 301         return name;
 302     }
 303 
 304     protected boolean databaseAllFilesEqual(Database previousDB,
 305                                             Database currentDB) {
 306         Iterator i1 = previousDB.getAllFiles().iterator();
 307         Iterator i2 = currentDB.getAllFiles().iterator();
 308 
 309         while (i1.hasNext() && i2.hasNext()) {
 310             FileList fl1 = (FileList) i1.next();
 311             FileList fl2 = (FileList) i2.next();
 312             if (!fl1.getName().equals(fl2.getName())) {
 313                 return false;
 314             }
 315         }
 316 
 317         if (i1.hasNext() != i2.hasNext()) {
 318             // Different lengths
 319             return false;
 320         }
 321 
 322         return true;
 323     }
 324 
 325     protected String envVarPrefixedFileName(String fileName,
 326                                             int sourceBaseLen,
 327                                             DirectoryTree tree,
 328                                             Vector preferredPaths,
 329                                             Vector filesNotFound,
 330                                             Vector filesDuplicate) {
 331         String fullName = findFileInDirectory(fileName,
 332                                               tree,
 333                                               preferredPaths,
 334                                               filesNotFound,
 335                                               filesDuplicate);
 336         return fullName;
 337     }
 338 
 339      String getProjectName(String fullPath, String extension)
 340         throws IllegalArgumentException, IOException {
 341         File file = new File(fullPath).getCanonicalFile();
 342         fullPath = file.getCanonicalPath();
 343         String parent = file.getParent();
 344 
 345         if (!fullPath.endsWith(extension)) {
 346             throw new IllegalArgumentException("project file name \"" +
 347                                                fullPath +
 348                                                "\" does not end in "+extension);
 349         }
 350 
 351         if ((parent != null) &&
 352             (!fullPath.startsWith(parent))) {
 353             throw new RuntimeException(
 354                 "Internal error: parent of file name \"" + parent +
 355                 "\" does not match file name \"" + fullPath + "\""
 356             );
 357         }
 358 
 359         int len = parent.length();
 360         if (!parent.endsWith(Util.sep)) {
 361             len += Util.sep.length();
 362         }
 363 
 364         int end = fullPath.length() - extension.length();
 365 
 366         if (len == end) {
 367             throw new RuntimeException(
 368                 "Internal error: file name was empty"
 369             );
 370         }
 371 
 372         return fullPath.substring(len, end);
 373     }
 374 
 375     protected abstract String getProjectExt();
 376 
 377     public void writePlatformSpecificFiles(Database previousDB,
 378                                            Database currentDB, String[] args)
 379         throws IllegalArgumentException, IOException {
 380 
 381         parseArguments(args);
 382 
 383         String projectFileName = BuildConfig.getFieldString(null, "ProjectFileName");
 384         String ext = getProjectExt();
 385 
 386         // Compare contents of allFiles of previousDB and includeDB.
 387         // If these haven't changed, then skip writing the .vcproj file.
 388         if (false && databaseAllFilesEqual(previousDB, currentDB) &&
 389             new File(projectFileName).exists()) {
 390             System.out.println(
 391                                "    Databases unchanged; skipping overwrite of "+ext+" file."
 392                                );
 393             return;
 394         }
 395 
 396         String projectName = getProjectName(projectFileName, ext);
 397 
 398         writeProjectFile(projectFileName, projectName, createAllConfigs());
 399     }
 400 
 401     protected void writePrologue(String[] args) {
 402         System.err.println("WinGammaPlatform platform-specific arguments:");
 403         for (int i = 0; i < args.length; i++) {
 404             System.err.print(args[i] + " ");
 405         }
 406         System.err.println();
 407     }
 408 
 409 
 410     void setInclFileTemplate(FileName val) {
 411         this.inclFileTemplate = val;
 412     }
 413 
 414     void setGIFileTemplate(FileName val) {
 415         this.giFileTemplate = val;
 416     }
 417 
 418 
 419     void parseArguments(String[] args) {
 420         new ArgsParser(args,
 421                        new ArgRule[]
 422             {
 423                 new HsArgRule("-sourceBase",
 424                               "SourceBase",
 425                               "   (Did you set the HotSpotWorkSpace environment variable?)",
 426                               HsArgHandler.STRING
 427                               ),
 428 
 429                 new HsArgRule("-buildBase",
 430                               "BuildBase",
 431                               "   (Did you set the HotSpotBuildSpace environment variable?)",
 432                               HsArgHandler.STRING
 433                               ),
 434 
 435                 new HsArgRule("-projectFileName",
 436                               "ProjectFileName",
 437                               null,
 438                               HsArgHandler.STRING
 439                               ),
 440 
 441                 new HsArgRule("-jdkTargetRoot",
 442                               "JdkTargetRoot",
 443                               "   (Did you set the HotSpotJDKDist environment variable?)",
 444                               HsArgHandler.STRING
 445                               ),
 446 
 447                 new HsArgRule("-compiler",
 448                               "CompilerVersion",
 449                               "   (Did you set the VcVersion correctly?)",
 450                               HsArgHandler.STRING
 451                               ),
 452 
 453                 new HsArgRule("-platform",
 454                               "Platform",
 455                               null,
 456                               HsArgHandler.STRING
 457                               ),
 458 
 459                 new HsArgRule("-absoluteInclude",
 460                               "AbsoluteInclude",
 461                               null,
 462                               HsArgHandler.VECTOR
 463                               ),
 464 
 465                 new HsArgRule("-relativeInclude",
 466                               "RelativeInclude",
 467                               null,
 468                               HsArgHandler.VECTOR
 469                               ),
 470 
 471                 new HsArgRule("-define",
 472                               "Define",
 473                               null,
 474                               HsArgHandler.VECTOR
 475                               ),
 476 
 477                 new HsArgRule("-useToGeneratePch",
 478                               "UseToGeneratePch",
 479                               null,
 480                               HsArgHandler.STRING
 481                               ),
 482 
 483                 new ArgRuleSpecific("-perFileLine",
 484                             new HsArgHandler() {
 485                                 public void handle(ArgIterator it) {
 486                                     String cfg = getCfg(it.get());
 487                                     if (nextNotKey(it)) {
 488                                         String fileName = it.get();
 489                                         if (nextNotKey(it)) {
 490                                             String line = it.get();
 491                                             BuildConfig.putFieldHash(cfg, "PerFileLine", fileName, line);
 492                                             it.next();
 493                                             return;
 494                                         }
 495                                     }
 496                                     empty(null, "** Error: wrong number of args to -perFileLine");
 497                                 }
 498                             }
 499                             ),
 500 
 501                 new ArgRuleSpecific("-conditionalPerFileLine",
 502                             new HsArgHandler() {
 503                                 public void handle(ArgIterator it) {
 504                                     String cfg = getCfg(it.get());
 505                                     if (nextNotKey(it)) {
 506                                         String fileName = it.get();
 507                                         if (nextNotKey(it)) {
 508                                             String productLine = it.get();
 509                                             if (nextNotKey(it)) {
 510                                                 String debugLine = it.get();
 511                                                 BuildConfig.putFieldHash(cfg+"_debug", "CondPerFileLine",
 512                                                                          fileName, debugLine);
 513                                                 BuildConfig.putFieldHash(cfg+"_product", "CondPerFileLine",
 514                                                                          fileName, productLine);
 515                                                 it.next();
 516                                                 return;
 517                                             }
 518                                         }
 519                                     }
 520 
 521                                     empty(null, "** Error: wrong number of args to -conditionalPerFileLine");
 522                                 }
 523                             }
 524                             ),
 525 
 526                 new HsArgRule("-disablePch",
 527                               "DisablePch",
 528                               null,
 529                               HsArgHandler.HASH
 530                               ),
 531 
 532                 new ArgRule("-startAt",
 533                             new HsArgHandler() {
 534                                 public void handle(ArgIterator it) {
 535                                     if (BuildConfig.getField(null, "StartAt") != null) {
 536                                         empty(null, "** Error: multiple -startAt");
 537                                     }
 538                                     if (nextNotKey(it)) {
 539                                         BuildConfig.putField(null, "StartAt", it.get());
 540                                         it.next();
 541                                     } else {
 542                                         empty("-startAt", null);
 543                                     }
 544                                 }
 545                             }
 546                             ),
 547 
 548                 new HsArgRule("-ignoreFile",
 549                                       "IgnoreFile",
 550                                       null,
 551                                       HsArgHandler.HASH
 552                                       ),
 553 
 554                 new HsArgRule("-additionalFile",
 555                               "AdditionalFile",
 556                               null,
 557                               HsArgHandler.VECTOR
 558                               ),
 559 
 560                 new ArgRuleSpecific("-additionalGeneratedFile",
 561                             new HsArgHandler() {
 562                                 public void handle(ArgIterator it) {
 563                                     String cfg = getCfg(it.get());
 564                                     if (nextNotKey(it)) {
 565                                         String dir = it.get();
 566                                         if (nextNotKey(it)) {
 567                                             String fileName = it.get();
 568                                             // we ignore files that we know are generated, so we coudn't
 569                                             // find them in sources
 570                                             BuildConfig.putFieldHash(cfg, "IgnoreFile",  fileName, "1");
 571                                             BuildConfig.putFieldHash(cfg, "AdditionalGeneratedFile",
 572                                                                      Util.normalize(dir + Util.sep + fileName),
 573                                                                      fileName);
 574                                             it.next();
 575                                             return;
 576                                         }
 577                                     }
 578                                     empty(null, "** Error: wrong number of args to -additionalGeneratedFile");
 579                                 }
 580                             }
 581                             ),
 582 
 583                 new HsArgRule("-includeDB",
 584                               "IncludeDB",
 585                               null,
 586                               HsArgHandler.STRING
 587                               ),
 588 
 589                 new ArgRule("-prelink",
 590                             new HsArgHandler() {
 591                                 public void handle(ArgIterator it) {
 592                                     if (nextNotKey(it)) {
 593                                         String build = it.get();
 594                                         if (nextNotKey(it)) {
 595                                             String description = it.get();
 596                                             if (nextNotKey(it)) {
 597                                                 String command = it.get();
 598                                                 BuildConfig.putField(null, "PrelinkDescription", description);
 599                                                 BuildConfig.putField(null, "PrelinkCommand", command);
 600                                                 it.next();
 601                                                 return;
 602                                             }
 603                                         }
 604                                     }
 605 
 606                                     empty(null,  "** Error: wrong number of args to -prelink");
 607                                 }
 608                             }
 609                             )
 610             },
 611                                        new ArgHandler() {
 612                                            public void handle(ArgIterator it) {
 613 
 614                                                throw new RuntimeException("Arg Parser: unrecognized option "+it.get());
 615                                            }
 616                                        }
 617                                        );
 618         if (BuildConfig.getField(null, "SourceBase") == null      ||
 619             BuildConfig.getField(null, "BuildBase") == null       ||
 620             BuildConfig.getField(null, "ProjectFileName") == null ||
 621             BuildConfig.getField(null, "CompilerVersion") == null) {
 622             usage();
 623         }
 624 
 625         if (BuildConfig.getField(null, "UseToGeneratePch") == null) {
 626             throw new RuntimeException("ERROR: need to specify one file to compute PCH, with -useToGeneratePch flag");
 627         }
 628 
 629         BuildConfig.putField(null, "PlatformObject", this);
 630     }
 631 
 632     Vector createAllConfigs() {
 633         Vector allConfigs = new Vector();
 634 
 635         allConfigs.add(new C1DebugConfig());
 636 
 637         boolean b = true;
 638         if (b) {
 639             allConfigs.add(new C1FastDebugConfig());
 640             allConfigs.add(new C1ProductConfig());
 641 
 642             allConfigs.add(new C2DebugConfig());
 643             allConfigs.add(new C2FastDebugConfig());
 644             allConfigs.add(new C2ProductConfig());
 645 
 646             allConfigs.add(new TieredDebugConfig());
 647             allConfigs.add(new TieredFastDebugConfig());
 648             allConfigs.add(new TieredProductConfig());
 649 
 650             allConfigs.add(new CoreDebugConfig());
 651             allConfigs.add(new CoreFastDebugConfig());
 652             allConfigs.add(new CoreProductConfig());
 653 
 654             allConfigs.add(new KernelDebugConfig());
 655             allConfigs.add(new KernelFastDebugConfig());
 656             allConfigs.add(new KernelProductConfig());
 657         }
 658 
 659         return allConfigs;
 660     }
 661 
 662     class FileAttribute {
 663         int     numConfigs;
 664         Vector  configs;
 665         String  shortName;
 666         boolean noPch, pchRoot;
 667 
 668         FileAttribute(String shortName, BuildConfig cfg, int numConfigs) {
 669             this.shortName = shortName;
 670             this.noPch =  (cfg.lookupHashFieldInContext("DisablePch", shortName) != null);
 671             this.pchRoot = shortName.equals(BuildConfig.getFieldString(null, "UseToGeneratePch"));
 672             this.numConfigs = numConfigs;
 673 
 674             configs = new Vector();
 675             add(cfg.get("Name"));
 676         }
 677 
 678         void add(String confName) {
 679             configs.add(confName);
 680 
 681             // if presented in all configs
 682             if (configs.size() == numConfigs) {
 683                 configs = null;
 684             }
 685         }
 686     }
 687 
 688     class FileInfo implements Comparable {
 689         String        full;
 690         FileAttribute attr;
 691 
 692         FileInfo(String full, FileAttribute  attr) {
 693             this.full = full;
 694             this.attr = attr;
 695         }
 696 
 697         public int compareTo(Object o) {
 698             FileInfo oo = (FileInfo)o;
 699             // Don't squelch identical short file names where the full
 700             // paths are different
 701             if (!attr.shortName.equals(oo.attr.shortName))
 702               return attr.shortName.compareTo(oo.attr.shortName);
 703             return full.compareTo(oo.full);
 704         }
 705 
 706         boolean isHeader() {
 707             return attr.shortName.endsWith(".h") || attr.shortName.endsWith(".hpp");
 708         }
 709     }
 710 
 711 
 712     TreeSet sortFiles(Hashtable allFiles) {
 713         TreeSet rv = new TreeSet();
 714         Enumeration e = allFiles.keys();
 715         while (e.hasMoreElements()) {
 716             String fullPath = (String)e.nextElement();
 717             rv.add(new FileInfo(fullPath, (FileAttribute)allFiles.get(fullPath)));
 718         }
 719         return rv;
 720     }
 721 
 722     Hashtable computeAttributedFiles(Vector allConfigs) {
 723         Hashtable ht = new Hashtable();
 724         int numConfigs = allConfigs.size();
 725 
 726         for (Iterator i = allConfigs.iterator(); i.hasNext(); ) {
 727             BuildConfig bc = (BuildConfig)i.next();
 728             Hashtable  confFiles = (Hashtable)bc.getSpecificField("AllFilesHash");
 729             String confName = bc.get("Name");
 730 
 731             for (Enumeration e=confFiles.keys(); e.hasMoreElements(); ) {
 732                 String filePath = (String)e.nextElement();
 733                 FileAttribute fa = (FileAttribute)ht.get(filePath);
 734 
 735                 if (fa == null) {
 736                     fa = new FileAttribute((String)confFiles.get(filePath), bc, numConfigs);
 737                     ht.put(filePath, fa);
 738                 } else {
 739                     fa.add(confName);
 740                 }
 741             }
 742         }
 743 
 744         return ht;
 745     }
 746 
 747      Hashtable computeAttributedFiles(BuildConfig bc) {
 748         Hashtable ht = new Hashtable();
 749         Hashtable confFiles = (Hashtable)bc.getSpecificField("AllFilesHash");
 750 
 751         for (Enumeration e = confFiles.keys(); e.hasMoreElements(); ) {
 752             String filePath = (String)e.nextElement();
 753             ht.put(filePath,  new FileAttribute((String)confFiles.get(filePath), bc, 1));
 754         }
 755 
 756         return ht;
 757     }
 758 
 759     PrintWriter printWriter;
 760 
 761     public void writeProjectFile(String projectFileName, String projectName,
 762                                  Vector allConfigs) throws IOException {
 763         throw new RuntimeException("use compiler version specific version");
 764     }
 765 }