0001: /*
0002: *
0003: *
0004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: */
0026:
0027: package makedep;
0028:
0029: import java.io.*;
0030: import java.util.*;
0031:
0032: public class Database {
0033: private MacroDefinitions macros;
0034: // allFiles is kept in lexicographically sorted order. See get().
0035: private FileList allFiles;
0036: // files that have implicit dependency on platform files
0037: // e.g. os.hpp: os_<os_family>.hpp os_<os_arch>.hpp but only
0038: // recorded if the platform file was seen.
0039: private FileList platformFiles;
0040: private FileList outerFiles;
0041: private FileList indivIncludes;
0042: private FileList grandInclude; // the results for the grand include file
0043: private long threshold;
0044: private int nOuterFiles;
0045: private int nPrecompiledFiles;
0046: private boolean missingOk;
0047:
0048: private Platform plat;
0049: /** These allow you to specify files not in the include database
0050: which are prepended and appended to the file list, allowing
0051: you to have well-known functions at the start and end of the
0052: text segment (allows us to find out in a portable fashion
0053: whether the current PC is in VM code or not upon a crash) */
0054: private String firstFile;
0055: private String lastFile;
0056: private boolean resolveVpath;
0057: private int sourceMergerLimit = 0;
0058: private String workspace;
0059: private String genDir;
0060: private Vector vpaths = null;
0061: private Hashtable resolvedFileNames;
0062: private Hashtable grandIncludeEntries = new Hashtable();
0063: static private String outputDir = ".";
0064:
0065: public Database(Platform plat, long t) {
0066: this .plat = plat;
0067: macros = new MacroDefinitions();
0068: allFiles = new FileList("allFiles", plat);
0069: platformFiles = new FileList("platformFiles", plat);
0070: outerFiles = new FileList("outerFiles", plat);
0071: indivIncludes = new FileList("IndivIncludes", plat);
0072: grandInclude = new FileList(plat.getGIFileTemplate()
0073: .nameOfList(), plat);
0074:
0075: threshold = t;
0076: nOuterFiles = 0;
0077: nPrecompiledFiles = 0;
0078: missingOk = false;
0079: firstFile = null;
0080: lastFile = null;
0081: resolveVpath = false;
0082: };
0083:
0084: public FileList getAllFiles() {
0085: return allFiles;
0086: }
0087:
0088: public FileList getOuterFiles() {
0089: return outerFiles;
0090: }
0091:
0092: public String getMacroContent(String name) {
0093: return macros.getMacroContent(name);
0094: }
0095:
0096: public void canBeMissing() {
0097: missingOk = true;
0098: }
0099:
0100: public boolean hfileIsInGrandInclude(FileList hfile, FileList cfile) {
0101: return ((hfile.getCount() >= threshold) && (cfile
0102: .getUseGrandInclude()));
0103: }
0104:
0105: /** These allow you to specify files not in the include database
0106: which are prepended and appended to the file list, allowing
0107: you to have well-known functions at the start and end of the
0108: text segment (allows us to find out in a portable fashion
0109: whether the current PC is in VM code or not upon a crash) */
0110: public void setFirstFile(String fileName) {
0111: firstFile = fileName;
0112: }
0113:
0114: public void setLastFile(String fileName) {
0115: lastFile = fileName;
0116: }
0117:
0118: public void setWorkspace(String fileName) {
0119: workspace = fileName;
0120: }
0121:
0122: public String getWorkspace() {
0123: return workspace;
0124: }
0125:
0126: public void setGenDir(String path) {
0127: genDir = path;
0128: }
0129:
0130: public String getGenDir() {
0131: return genDir;
0132: }
0133:
0134: public void setOutputDir(String path) {
0135: outputDir = path;
0136: }
0137:
0138: private void initVpath() {
0139: if (vpaths != null) {
0140: return;
0141: }
0142: resolvedFileNames = new Hashtable();
0143: vpaths = new Vector();
0144: if (genDir != null) {
0145: addVpath(genDir);
0146: addVpath(genDir + "/incls");
0147: }
0148: String cpu = macros.getMacroContent("arch");
0149: String cpu_variant = macros.getMacroContent("cpu_variant");
0150:
0151: addVpath(workspace + "/src/vm/cpu/arm");
0152: addVpath(workspace + "/src/vm/cpu/arm/jazelle");
0153: addVpath(workspace + "/src/vm/cpu/c");
0154: addVpath(workspace + "/src/vm/cpu/i386");
0155: addVpath(workspace + "/src/vm/cpu/sh");
0156: addVpath(workspace + "/src/vm/cpu/thumb");
0157: addVpath(workspace + "/src/vm/cpu/thumb2");
0158: if ((cpu_variant != null) && (!cpu_variant.equals(""))) {
0159: addVpath(workspace + "/src/vm/cpu/" + cpu + "/"
0160: + cpu_variant);
0161: }
0162:
0163: addVpath(workspace + "/src/vm/os/"
0164: + macros.getMacroContent("os_family"));
0165: addVpath(workspace + "/src/vm/os/utilities");
0166: addVpath(workspace + "/src/vm/share/compiler");
0167: addVpath(workspace + "/src/vm/share/float");
0168: addVpath(workspace + "/src/vm/share/handles");
0169: addVpath(workspace + "/src/vm/share/interpreter");
0170: addVpath(workspace + "/src/vm/share/memory");
0171: addVpath(workspace + "/src/vm/share/natives");
0172: addVpath(workspace + "/src/vm/share/ROM");
0173: addVpath(workspace + "/src/vm/share/reflection");
0174: addVpath(workspace + "/src/vm/share/runtime");
0175: addVpath(workspace + "/src/vm/share/utilities");
0176: addVpath(workspace + "/src/vm/share/verifier");
0177: addVpath(workspace + "/src/vm/share/debugger");
0178: addVpath(workspace + "/src/vm/share/isolate");
0179: addVpath(workspace + "/src/vm/share/dynupdate");
0180: addVpath(workspace + "/src/vm/share/memoryprofiler");
0181: }
0182:
0183: private void addVpath(String path) {
0184: // System.out.println("adding = " + path);
0185: File file = new File(path);
0186: if (file.isDirectory()) {
0187: vpaths.addElement(path);
0188: }
0189: }
0190:
0191: public void setResolveVpath(boolean r) {
0192: resolveVpath = r;
0193: }
0194:
0195: /**
0196: * Reads an entire includeDB file and stores its contents into
0197: * internal representations.
0198: */
0199: public void get(String platFileName, String dbFileName,
0200: Properties globalProps) throws FileFormatException,
0201: IOException, FileNotFoundException {
0202: macros.readFrom(platFileName, missingOk);
0203:
0204: BufferedReader reader = null;
0205: try {
0206: reader = new BufferedReader(new FileReader(dbFileName));
0207: } catch (FileNotFoundException e) {
0208: if (missingOk) {
0209: return;
0210: } else {
0211: throw (e);
0212: }
0213: }
0214: System.out.println("\treading database: " + dbFileName);
0215: String line;
0216: int lineNo = 0;
0217: Stack ifdef_stack = new Stack();
0218: do {
0219: line = reader.readLine();
0220: lineNo++;
0221: if (line != null) {
0222: StreamTokenizer tokenizer = new StreamTokenizer(
0223: new StringReader(line));
0224: tokenizer.slashSlashComments(true);
0225: tokenizer.wordChars('_', '_');
0226: tokenizer.wordChars('<', '>');
0227: tokenizer.wordChars('#', '#');
0228: tokenizer.wordChars('!', '!');
0229:
0230: // NOTE: if we didn't have to do this line by line,
0231: // we could trivially recognize C-style comments as
0232: // well.
0233: // tokenizer.slashStarComments(true);
0234: int numTok = 0;
0235: int res;
0236: String unexpandedIncluder = null;
0237: String unexpandedIncludee = null;
0238: String thirdToken = null;
0239: do {
0240: res = tokenizer.nextToken();
0241: if (res != StreamTokenizer.TT_EOF) {
0242: if (numTok == 0) {
0243: unexpandedIncluder = tokenizer.sval;
0244: } else if (numTok == 1) {
0245: unexpandedIncludee = tokenizer.sval;
0246: } else if (numTok == 2) {
0247: thirdToken = tokenizer.sval;
0248: } else {
0249: throw new FileFormatException(
0250: "invalid line: \""
0251: + line
0252: + "\". Error position: line "
0253: + lineNo);
0254: }
0255: numTok++;
0256: }
0257: } while (res != StreamTokenizer.TT_EOF);
0258:
0259: boolean valid = true;
0260: if (numTok == 0) {
0261: valid = true;
0262: } else if (unexpandedIncluder != null
0263: && unexpandedIncluder.charAt(0) == '#') {
0264: if (equalsIgnoreCase(unexpandedIncluder, "#if")) {
0265: valid = (numTok == 2);
0266: } else if (equalsIgnoreCase(unexpandedIncluder,
0267: "#ifeq")) {
0268: valid = (numTok == 3);
0269: } else if (equalsIgnoreCase(unexpandedIncluder,
0270: "#endif")) {
0271: valid = (numTok == 1 || numTok == 2);
0272: } else {
0273: System.out
0274: .println("Unknown preprocessor command: "
0275: + unexpandedIncluder
0276: + " at line " + lineNo);
0277: System.exit(1);
0278: }
0279: } else {
0280: valid = (numTok == 2);
0281: }
0282:
0283: if (!valid) {
0284: throw new FileFormatException("invalid line: \""
0285: + line + "\". Error position: line "
0286: + lineNo);
0287: }
0288:
0289: if (numTok != 0) { // Non-empty line
0290: if (equalsIgnoreCase(unexpandedIncluder, "#if")) {
0291: push(ifdef_stack, getIfdefValue(globalProps,
0292: unexpandedIncludee));
0293: continue;
0294: } else if (equalsIgnoreCase(unexpandedIncluder,
0295: "#ifeq")) {
0296: push(ifdef_stack, getIfeqValue(globalProps,
0297: unexpandedIncludee, thirdToken));
0298: continue;
0299: } else if (equalsIgnoreCase(unexpandedIncluder,
0300: "#endif")) {
0301: if (ifdef_stack.empty()) {
0302: throw new FileFormatException(
0303: "#endif without #if at line: \""
0304: + line);
0305: }
0306: }
0307:
0308: if (!ifdef_stack.empty()) {
0309: if (equalsIgnoreCase(unexpandedIncluder,
0310: "#endif")) {
0311: ifdef_stack.pop();
0312: continue;
0313: }
0314:
0315: Object obj = ifdef_stack.peek();
0316: Boolean b = (Boolean) obj;
0317: if (b.booleanValue() == false) {
0318: continue;
0319: }
0320: }
0321:
0322: String includer = macros.expand(unexpandedIncluder);
0323: String includee = macros.expand(unexpandedIncludee);
0324:
0325: if (includee.equals(plat
0326: .generatePlatformDependentInclude())) {
0327: generatePlatformDependentInclude(
0328: unexpandedIncluder, includer);
0329: } else {
0330: FileList p = allFiles.listForFile(includer);
0331: if (isOuterFile(includer)) {
0332: outerFiles.addIfAbsent(p);
0333: }
0334:
0335: if (includee.equals(plat.noGrandInclude())) {
0336: p.setUseGrandInclude(false);
0337: } else {
0338: FileList q = allFiles.listForFile(includee);
0339: p.addIfAbsent(q);
0340: }
0341: }
0342: }
0343: }
0344: } while (line != null);
0345:
0346: if (!ifdef_stack.empty()) {
0347: throw new FileFormatException(
0348: "#endif not found before end of file");
0349: }
0350: reader.close();
0351:
0352: if (sourceMergerLimit > 1) {
0353: createMergedOuterFiles();
0354: }
0355:
0356: // Keep allFiles in well-known order so we can easily determine
0357: // whether the known files are the same
0358: allFiles.sortByName();
0359:
0360: // Add first and last files differently to prevent a mistake
0361: // in ordering in the include databases from breaking the
0362: // error reporting in the VM.
0363: if (firstFile != null) {
0364: FileList p = allFiles.listForFile(firstFile);
0365: allFiles.setFirstFile(p);
0366: outerFiles.setFirstFile(p);
0367: }
0368:
0369: if (lastFile != null) {
0370: FileList p = allFiles.listForFile(lastFile);
0371: allFiles.setLastFile(p);
0372: outerFiles.setLastFile(p);
0373: }
0374: }
0375:
0376: static boolean equalsIgnoreCase(String a, String b) {
0377: return (a.compareToIgnoreCase(b) == 0);
0378: }
0379:
0380: /**
0381: * @param boolValue must be "true" or "false"
0382: */
0383: void push(Stack ifdef_stack, String boolValue) {
0384: if (!ifdef_stack.empty()) {
0385: Object obj = ifdef_stack.peek();
0386: Boolean b = (Boolean) obj;
0387: String prop;
0388: if (b.booleanValue() == false) {
0389: boolValue = "false";
0390: }
0391: }
0392: ifdef_stack.push(new Boolean(boolValue));
0393: }
0394:
0395: void generatePlatformDependentInclude(String unexpandedIncluder,
0396: String includer) throws IOException {
0397: MacroDefinitions localExpander = macros.copy();
0398: MacroDefinitions localExpander2 = macros.copy();
0399: localExpander.setAllMacroBodiesTo("pd");
0400: localExpander2.setAllMacroBodiesTo("");
0401:
0402: // unexpanded_includer e.g. thread_<os_arch>.hpp
0403: // thread_solaris_i486.hpp -> _thread_pd.hpp.incl
0404:
0405: FileName pdName = plat.getInclFileTemplate().copyStem(
0406: localExpander.expand(unexpandedIncluder));
0407:
0408: // derive generic name from platform specific name
0409: // e.g. os_<arch_os>.hpp => os.hpp
0410:
0411: String newIncluder = localExpander2.expand(unexpandedIncluder);
0412:
0413: FileList p = allFiles.listForFile(includer);
0414: p.setPlatformDependentInclude(pdName.dirPreStemSuff());
0415:
0416: // Add an implicit dependency on platform
0417: // specific file for the generic file
0418:
0419: p = platformFiles.listForFile(newIncluder);
0420:
0421: ByteArrayOutputStream baos = new ByteArrayOutputStream();
0422: OutputStreamWriter writer = new OutputStreamWriter(baos);
0423: PrintWriter pdFile = new PrintWriter(writer);
0424:
0425: String incname = tryGetFullPath(includer);
0426: incname = plat.translateFileName(incname);
0427: pdFile.println("#include \"" + incname + "\"");
0428: pdFile.flush();
0429: updateFile(pdName.dirPreStemSuff(), baos);
0430: pdFile.close();
0431:
0432: // Add the platform specific file to the list
0433: // for this generic file.
0434:
0435: FileList q = allFiles.listForFile(includer);
0436: p.addIfAbsent(q);
0437: }
0438:
0439: static String getIfdefValue(Properties globalProps, String token) {
0440: boolean negate = false;
0441: if (token.startsWith("!")) {
0442: token = token.substring(1);
0443: negate = true;
0444: }
0445: String result = globalProps.getProperty(token, "false");
0446: if (negate) {
0447: if (result.equals("false")) {
0448: result = "true";
0449: } else {
0450: result = "false";
0451: }
0452: }
0453: return result;
0454: }
0455:
0456: String getIfeqValue(Properties globalProps, String name,
0457: String value) {
0458: String result = macros.getMacroContent(name);
0459: if (result == null) {
0460: result = globalProps.getProperty(name, null);
0461: }
0462:
0463: if (value.equals(result)) {
0464: return "true";
0465: } else {
0466: return "false";
0467: }
0468: }
0469:
0470: /**
0471: * We need to exclude some files from the merged source files. See
0472: * in-line comments for reasons.
0473: */
0474: boolean needToExcludeFromMerge(String file) {
0475: if (file.equals("ROMImage.cpp")) {
0476: // ROM image is not part of VM library.
0477: return true;
0478: }
0479: if (file.equals("NativesTable.cpp")) {
0480: // Natives Table is not part of VM library.
0481: return true;
0482: }
0483: if (file.equals("BSDSocket.cpp")) {
0484: // BSDSocket is not part of VM library.
0485: return true;
0486: }
0487: if (file.equals("PCSLSocket.cpp")) {
0488: // PCSLSocket is not part of VM library.
0489: return true;
0490: }
0491: if (file.equals("ReflectNatives.cpp")) {
0492: // ReflectNatives is not part of VM library.
0493: return true;
0494: }
0495:
0496: if (file.equals("HotRoutines0.cpp")
0497: || file.equals("HotRoutines1.cpp")) {
0498: // These could be placed in fast memory on low-end
0499: // ARM7TDMI devices, so don't merge them with other
0500: // files.
0501: return true;
0502: }
0503: if (file.equals("jvmspi.cpp")) {
0504: // SPI implementation is not part of VM library
0505: return true;
0506: }
0507: if (file.toLowerCase().startsWith("main_")) {
0508: // Main function is not part of VM library.
0509: return true;
0510: }
0511: if (file.toLowerCase().startsWith("ossocket_")) {
0512: // socket code is not part of VM library.
0513: return true;
0514: }
0515: if (file.toLowerCase().startsWith("floatsupport_")) {
0516: // On ARM we should build FloatSupport_arm.cpp in ARM
0517: // mode. If compiled in THUMB mode functions like jvm_fadd()
0518: // will be compiled into library calls instead of VFP instructions.
0519: return true;
0520: }
0521: if (file.toLowerCase().endsWith("uncommon.cpp")) {
0522: // This file is rarely used by optimized MIDP, so let's
0523: // leave in a separate .o file, which gcc could eliminate from
0524: // final executable image.
0525: return true;
0526: }
0527: if (file.toLowerCase().startsWith("os")
0528: && !file.equals("OS.cpp")) {
0529: // IMPORTANT: this has to be here for Linux and ADS:
0530: // -> leads to compilation problems (FIELD_OFFSET) if merged
0531:
0532: // IMPORTANT: this has to be here for GBA:
0533: // contains interrupt handler that HAVE to be in ARM, not Thumb
0534: return true;
0535: }
0536: return false;
0537: }
0538:
0539: /**
0540: * Merge multiple .cpp files into a single .cpp file to speed
0541: * up GCC compilation. This is done by creating a new 'outer' source
0542: * file that depends on several of the original outer source files.
0543: * E.g., if we merge Foo1.cpp, Foo2.cpp Foo3.cpp into _MergedSrc001.cpp,
0544: * we'd have the following files:
0545: *
0546: * _MergedSrc001.cpp:
0547: * #include "incls/_precompiled.incl"
0548: * #include "incls/__MergedSrc001.cpp.incl"
0549: *
0550: * incls/__MergedSrc001.cpp.incl:
0551: * #include "/path/to/Foo1.cpp"
0552: * #include "/path/to/Foo2.cpp"
0553: * #include "/path/to/Foo3.cpp"
0554: *
0555: * The Makefile is directed to build _MergedSrc001.o, which will include
0556: * the contents of Foo1.cpp, Foo2.cpp and Foo3.cpp
0557: *
0558: * This speeds up GCC compilation time by 2x ~ 3x.
0559: */
0560: void createMergedOuterFiles() throws IOException {
0561: System.out.println("\tmerging source files, limit = "
0562: + sourceMergerLimit);
0563: int nNewFiles = 1;
0564: int nMerged = 0;
0565: FileList oldOuterFiles = outerFiles;
0566: outerFiles = new FileList("outerFiles", plat);
0567:
0568: FileList newOuter = null;
0569: for (int i = 0; i < oldOuterFiles.size(); i++) {
0570: FileList oldOuter = (FileList) oldOuterFiles.elementAt(i);
0571:
0572: if (needToExcludeFromMerge(oldOuter.getName())) {
0573: System.out.println("\t\texcluded from merging: "
0574: + oldOuter.getName());
0575: outerFiles.addIfAbsent(oldOuter);
0576: } else {
0577: if (newOuter == null) {
0578: String name = "_MergedSrc" + numToString(nNewFiles)
0579: + ".cpp";
0580: newOuter = new FileList(name, plat);
0581: outerFiles.addIfAbsent(newOuter);
0582: nNewFiles++;
0583:
0584: ByteArrayOutputStream baos = new ByteArrayOutputStream();
0585: OutputStreamWriter writer = new OutputStreamWriter(
0586: baos);
0587: PrintWriter pw = new PrintWriter(writer);
0588: pw.println("#include \"incls/_precompiled.incl\"");
0589: pw.println("#include \"incls/_" + name + ".incl\"");
0590: pw.flush();
0591: updateFile(name, baos);
0592: pw.close();
0593: }
0594:
0595: // Create blank incl file for the oldOuter
0596: String blankFile = "incls/_" + oldOuter.getName()
0597: + ".incl";
0598: ByteArrayOutputStream baos = new ByteArrayOutputStream();
0599: updateFile(blankFile, baos);
0600: baos.close();
0601:
0602: newOuter.addIfAbsent(oldOuter);
0603: nMerged++;
0604: if (nMerged >= sourceMergerLimit) {
0605: nMerged = 0;
0606: newOuter = null;
0607: }
0608: }
0609: }
0610: }
0611:
0612: String numToString(int n) {
0613: String s = Integer.toString(n);
0614: while (s.length() < 3) {
0615: s = "0" + s;
0616: }
0617: return s;
0618: }
0619:
0620: public void compute() {
0621: // build both indiv and grand results
0622: for (Iterator iter = outerFiles.iterator(); iter.hasNext();) {
0623: indivIncludes.add(((FileList) iter.next()).doCFile());
0624: ++nOuterFiles;
0625: }
0626:
0627: if (!plat.haveGrandInclude())
0628: return; // nothing in grand include
0629:
0630: // count how many times each include is included & add em to grand
0631: for (Iterator iter = indivIncludes.iterator(); iter.hasNext();) {
0632: FileList indivInclude = (FileList) iter.next();
0633: if (!indivInclude.getUseGrandInclude()) {
0634: continue; // do not bump count if my files cannot be
0635: // in grand include
0636: }
0637: indivInclude.doFiles(grandInclude); // put em on
0638: // grand_include list
0639: for (Iterator incListIter = indivInclude.iterator(); incListIter
0640: .hasNext();) {
0641: ((FileList) incListIter.next()).incrementCount();
0642: }
0643: }
0644: }
0645:
0646: // Consider whether it is necessary in Java
0647: public void verify() {
0648: for (Iterator iter = indivIncludes.iterator(); iter.hasNext();) {
0649: if (iter.next() == null) {
0650: plat.abort();
0651: }
0652: }
0653: }
0654:
0655: public void put() throws IOException {
0656: writeIndividualIncludes();
0657: writeGrandInclude();
0658: writeCompleteInclude();
0659: writeGrandUnixMakefile();
0660: writeDox();
0661: }
0662:
0663: // Write the include file for each individual .cpp file. E.g.,
0664: // create _BinaryAssembler_arm.cpp.incl for _BinaryAssembler_arm.cpp
0665: private void writeIndividualIncludes() throws IOException {
0666: System.out.print("\twriting individual include files ...");
0667: int count = 0;
0668: for (Iterator iter = indivIncludes.iterator(); iter.hasNext();) {
0669: FileList list = (FileList) iter.next();
0670: //System.out.println("\tcreating " + list.getName());
0671: list.putInclFile(this );
0672: ++count;
0673: }
0674: System.out.println(" done (" + count + " files.)");
0675: }
0676:
0677: // Write the header file that contains all of the VM's
0678: // .hpp files. This file can be used for compiling C++ files
0679: // that are not part of the VM code (e.g.,
0680: // src/tests/natives/InternalNatives.cpp). This makes it possible
0681: // to link extra C++ files into the VM without editing includeDB
0682: private void writeCompleteInclude() throws IOException {
0683: Hashtable written = new Hashtable();
0684: String filename = outputDir + "/incls/_CompleteInclude.incl";
0685: PrintWriter inclFile = new PrintWriter(new FileWriter(filename));
0686: String filename2 = outputDir + "/incls/_CompleteInclude2.incl";
0687: PrintWriter inclFile2 = new PrintWriter(new FileWriter(
0688: filename2));
0689:
0690: inclFile2
0691: .println("/* This file contains all files that are in */");
0692: inclFile2.println("/* _CompleteInclude.incl but not in */");
0693: inclFile2.println("/* _precompiled.incl */");
0694:
0695: for (Iterator iter = indivIncludes.iterator(); iter.hasNext();) {
0696: FileList list = (FileList) iter.next();
0697:
0698: for (Iterator files = list.iterator(); files.hasNext();) {
0699: FileList file = (FileList) files.next();
0700: String name = file.getName();
0701: if (!name.endsWith(".hpp") && !name.endsWith(".h")) {
0702: continue;
0703: }
0704: String incname = plat.getInclFileTemplate().getInvDir()
0705: + tryGetFullPath(name);
0706: incname = plat.translateFileName(incname);
0707: if (written.get(incname) == null) {
0708: written.put(incname, incname);
0709: inclFile.println("#include \"" + incname + "\"");
0710:
0711: if (grandIncludeEntries.get(incname) == null) {
0712: inclFile2.println("#include \"" + incname
0713: + "\"");
0714: }
0715: }
0716: }
0717: }
0718: inclFile.close();
0719: inclFile2.close();
0720: }
0721:
0722: // Write a file for controlling the Doxygen documentation
0723: // processor. See build/share/dox.make.
0724: private void writeDox() throws IOException {
0725: Hashtable written = new Hashtable();
0726: String filename = outputDir + "/Dox.tail";
0727: PrintWriter doxFile = new PrintWriter(new FileWriter(filename));
0728:
0729: doxFile.println("# Dox.tail -- this file is auto-generated.");
0730: doxFile.println("# do not edit");
0731: doxFile.println("#");
0732: doxFile.print("INPUT =");
0733: for (Iterator iter = indivIncludes.iterator(); iter.hasNext();) {
0734: FileList list = (FileList) iter.next();
0735:
0736: for (Iterator files = list.iterator(); files.hasNext();) {
0737: FileList file = (FileList) files.next();
0738: String name = file.getName();
0739: if (!name.endsWith(".hpp") && !name.endsWith(".h")) {
0740: continue;
0741: }
0742: String incname = plat.getInclFileTemplate().getInvDir()
0743: + tryGetFullPath(name);
0744: incname = plat.translateFileName(incname);
0745: if (written.get(incname) == null) {
0746: written.put(incname, incname);
0747: //if (incname.indexOf("memory") >= 0) {
0748: doxFile.print(" " + incname);
0749: //}
0750: }
0751: }
0752: }
0753: doxFile.println("");
0754: doxFile.close();
0755: }
0756:
0757: // Write the _precompiled.incl file
0758: private void writeGrandInclude() throws IOException {
0759: System.out.println("\twriting grand include file\n");
0760: String filename = outputDir + "/"
0761: + plat.getGIFileTemplate().dirPreStemSuff();
0762: PrintWriter inclFile = new PrintWriter(new FileWriter(filename));
0763:
0764: // This file is always included first
0765: inclFile.println("#include \"jvmconfig.h\"");
0766:
0767: if (plat.haveGrandInclude()) {
0768: plat.writeGIPragma(inclFile);
0769: for (Iterator iter = grandInclude.iterator(); iter
0770: .hasNext();) {
0771: FileList list = (FileList) iter.next();
0772: if (list.getCount() >= threshold) {
0773: String incname = tryGetFullPath(list.getName());
0774: incname = plat.translateFileName(incname);
0775: inclFile.println("#include \""
0776: + plat.getGIFileTemplate().getInvDir()
0777: + incname + "\"");
0778: nPrecompiledFiles += 1;
0779: grandIncludeEntries.put(incname, incname);
0780: }
0781: }
0782: }
0783: inclFile.println();
0784: inclFile.close();
0785: }
0786:
0787: private void writeGrandUnixMakefile() throws IOException {
0788: if (resolveVpath) {
0789: initVpath();
0790: }
0791:
0792: if (!plat.writeDeps()) {
0793: return;
0794: }
0795:
0796: System.out.println("\twriting dependencies file\n");
0797: String fileName = outputDir + "/"
0798: + plat.getGDFileTemplate().dirPreStemSuff();
0799: PrintWriter gd = new PrintWriter(new FileWriter(fileName));
0800:
0801: gd.println("# generated by makeDeps");
0802: gd.println();
0803:
0804: {
0805: // write Obj_Files = ...
0806: String prefix = "Obj_Files = \\\n\t";
0807: outerFiles.sortByName();
0808: for (Iterator iter = outerFiles.iterator(); iter.hasNext();) {
0809: FileList anOuterFile = (FileList) iter.next();
0810:
0811: gd.print(prefix);
0812: String stemName = removeSuffixFrom(anOuterFile
0813: .getName());
0814: gd.print(stemName + plat.objFileSuffix());
0815: prefix = " \\\n\t";
0816: }
0817: gd.println();
0818: gd.println();
0819: }
0820:
0821: if (plat.haveGrandInclude()) {
0822: String prefix = "Precompiled_Headers = \\\n\t";
0823: for (Iterator iter = grandInclude.iterator(); iter
0824: .hasNext();) {
0825: FileList list = (FileList) iter.next();
0826: if (list.getCount() >= threshold) {
0827: gd.print(prefix);
0828: gd.print(tryGetFullPath(list.getName()));
0829: prefix = " \\\n\t";
0830: }
0831: }
0832: gd.println();
0833: gd.println();
0834: }
0835:
0836: {
0837: // write each dependency
0838:
0839: for (Iterator iter = indivIncludes.iterator(); iter
0840: .hasNext();) {
0841:
0842: FileList anII = (FileList) iter.next();
0843:
0844: String stemName = removeSuffixFrom(anII.getName());
0845: gd.println(stemName + plat.objFileSuffix() + ": \\");
0846: gd.print("$(GEN_DIR)/jvmconfig.h ");
0847:
0848: printDependentOn(gd, anII.getName());
0849:
0850: for (Iterator iiIter = anII.iterator(); iiIter
0851: .hasNext();) {
0852: FileList hfile = (FileList) iiIter.next();
0853: if (!hfileIsInGrandInclude(hfile, anII)) {
0854: printDependentOn(gd, hfile.getName());
0855: }
0856: if (platformFiles.hasListForFile(hfile.getName())) {
0857: FileList p = platformFiles.listForFile(hfile
0858: .getName());
0859: ;
0860: for (Iterator hiIter = p.iterator(); hiIter
0861: .hasNext();) {
0862: FileList hi2 = (FileList) hiIter.next();
0863: if (!hfileIsInGrandInclude(hi2, p)) {
0864: printDependentOn(gd, hi2.getName());
0865: }
0866: }
0867: }
0868: }
0869: if (plat.haveGrandInclude()) {
0870: gd.println(" $(Precompiled_Headers)");
0871: }
0872: gd.println();
0873: gd.println();
0874: }
0875: }
0876:
0877: gd.close();
0878: }
0879:
0880: public void putDiffs(Database previous) throws IOException {
0881: System.out.println("\tupdating output files\n");
0882:
0883: if (!indivIncludes.compareLists(previous.indivIncludes)
0884: || !grandInclude.compareLists(previous.grandInclude)) {
0885: System.out.println("The order of .c or .s has changed, or "
0886: + "the grand include file has changed.");
0887: put();
0888: return;
0889: }
0890:
0891: Iterator curIter = indivIncludes.iterator();
0892: Iterator prevIter = previous.indivIncludes.iterator();
0893:
0894: try {
0895: while (curIter.hasNext()) {
0896: FileList newCFileList = (FileList) curIter.next();
0897: FileList prevCFileList = (FileList) prevIter.next();
0898: if (!newCFileList.compareLists(prevCFileList)) {
0899: System.out.println("\tupdating "
0900: + newCFileList.getName());
0901: newCFileList.putInclFile(this );
0902: }
0903: }
0904: } catch (Exception e) {
0905: throw new InternalError("assertion failure: cur and prev "
0906: + "database lists changed unexpectedly.");
0907: }
0908:
0909: writeGrandUnixMakefile();
0910: }
0911:
0912: private void printDependentOn(PrintWriter gd, String name) {
0913: gd.print(" ");
0914: gd.print(tryGetFullPath(plat.dependentPrefix(), name));
0915: }
0916:
0917: public String tryGetFullPath(String filename) {
0918: return tryGetFullPath("", filename);
0919: }
0920:
0921: private String tryGetFullPath(String prefix, String filename) {
0922: if (resolveVpath) {
0923: String file = getFullPath(prefix, filename);
0924: if (file != null) {
0925: return file;
0926: }
0927: }
0928:
0929: return prefix + filename;
0930: }
0931:
0932: public String getFullPath(String filename) {
0933: return getFullPath("", filename);
0934: }
0935:
0936: public String getFullPath(String prefix, String filename) {
0937: initVpath();
0938: String cached = (String) resolvedFileNames.get(filename);
0939: if (cached != null) {
0940: return cached;
0941: }
0942:
0943: String found = null;
0944: for (int i = 0; i < vpaths.size(); i++) {
0945: String vpath = (String) vpaths.elementAt(i);
0946: File file = new File(vpath + "/" + filename);
0947: if (file.isFile()) {
0948: found = vpath + "/" + filename;
0949: break;
0950: }
0951: }
0952: if (found == null) {
0953: if (filename.equals("NativesTable.cpp")
0954: || filename.equals("ROMImage.cpp")
0955: || filename.startsWith("_MergedSrc")) {
0956: found = "../generated/" + filename;
0957: }
0958: }
0959:
0960: if (found != null) {
0961: resolvedFileNames.put(filename, found);
0962: return found;
0963: }
0964: System.err.println("couldn't find in vpath: " + filename);
0965:
0966: return null;
0967: }
0968:
0969: /**
0970: * Checks whether a file is an outer file - which means a
0971: * makefile rule has to be generated to compile this file
0972: * into an object file.
0973: *
0974: * This is done by checking if the suffix of the file is one
0975: * of plat.outerSuffixes(), which are typically .cpp and .c
0976: */
0977: private boolean isOuterFile(String s) {
0978: int len = s.length();
0979: String[] suffixes = plat.outerSuffixes();
0980: for (int i = 0; i < suffixes.length; i++) {
0981: String suffix = suffixes[i];
0982: int suffLen = suffix.length();
0983: if ((len >= suffLen)
0984: && (plat.fileNameStringEquality(s.substring(len
0985: - suffLen), suffix))) {
0986: return true;
0987: }
0988: }
0989: return false;
0990: }
0991:
0992: private String removeSuffixFrom(String s) {
0993: int idx = s.lastIndexOf('.');
0994: if (idx <= 0)
0995: plat.abort();
0996: return s.substring(0, idx);
0997: }
0998:
0999: public void setSourceMergerLimit(int size) {
1000: sourceMergerLimit = size;
1001: }
1002:
1003: /**
1004: * Write the content of the baos to the given file, but only if the
1005: * change has been changed. We don't rewrite the file if the content is
1006: * the same. This avoids excessive rebuilding.
1007: */
1008: public static void updateFile(String filename,
1009: ByteArrayOutputStream baos) throws IOException {
1010: byte newContent[] = baos.toByteArray();
1011: byte oldContent[] = readFile(filename);
1012:
1013: // We won't write to the file if the content has not changed.
1014: // This will avoid excessive rebuilding when we change
1015: // includeDB, etc.
1016: if (oldContent != null
1017: && oldContent.length == newContent.length) {
1018: boolean same = true;
1019:
1020: for (int i = 0; i < oldContent.length; i++) {
1021: if (oldContent[i] != newContent[i]) {
1022: same = false;
1023: break;
1024: }
1025: }
1026: if (same) {
1027: //System.out.println(filename + " same");
1028: return;
1029: }
1030: }
1031:
1032: filename = outputDir + "/" + filename;
1033: FileOutputStream out = new FileOutputStream(filename);
1034: out.write(newContent);
1035: out.close();
1036: }
1037:
1038: public static byte[] readFile(String filename) throws IOException {
1039: try {
1040: ByteArrayOutputStream baos = new ByteArrayOutputStream();
1041: FileInputStream in = new FileInputStream(filename);
1042: byte buffer[] = new byte[1024];
1043: int n;
1044: while ((n = in.read(buffer)) > 0) {
1045: baos.write(buffer, 0, n);
1046: }
1047: byte result[] = baos.toByteArray();
1048: baos.close();
1049: in.close();
1050: return result;
1051: } catch (IOException e) {
1052: return null;
1053: }
1054: }
1055: }
|