mirror of https://github.com/acidanthera/audk.git
610 lines
25 KiB
Java
610 lines
25 KiB
Java
|
/*
|
||
|
*
|
||
|
* Copyright 2002-2004 The Ant-Contrib project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
package net.sf.antcontrib.cpptasks;
|
||
|
import java.io.BufferedWriter;
|
||
|
import java.io.File;
|
||
|
import java.io.FileOutputStream;
|
||
|
import java.io.IOException;
|
||
|
import java.io.OutputStreamWriter;
|
||
|
import java.io.UnsupportedEncodingException;
|
||
|
import java.util.Enumeration;
|
||
|
import java.util.Hashtable;
|
||
|
import java.util.Vector;
|
||
|
import javax.xml.parsers.ParserConfigurationException;
|
||
|
import javax.xml.parsers.SAXParser;
|
||
|
import javax.xml.parsers.SAXParserFactory;
|
||
|
import net.sf.antcontrib.cpptasks.compiler.CompilerConfiguration;
|
||
|
import org.apache.tools.ant.BuildException;
|
||
|
import org.apache.tools.ant.Project;
|
||
|
import org.xml.sax.Attributes;
|
||
|
import org.xml.sax.SAXException;
|
||
|
import org.xml.sax.helpers.DefaultHandler;
|
||
|
/**
|
||
|
* @author Curt Arnold
|
||
|
*/
|
||
|
public final class DependencyTable {
|
||
|
/**
|
||
|
* This class handles populates the TargetHistory hashtable in response to
|
||
|
* SAX parse events
|
||
|
*/
|
||
|
private class DependencyTableHandler extends DefaultHandler {
|
||
|
private File baseDir;
|
||
|
private final DependencyTable dependencyTable;
|
||
|
private String includePath;
|
||
|
private Vector includes;
|
||
|
private String source;
|
||
|
private long sourceLastModified;
|
||
|
private Vector sysIncludes;
|
||
|
/**
|
||
|
* Constructor
|
||
|
*
|
||
|
* @param history
|
||
|
* hashtable of TargetHistory keyed by output name
|
||
|
* @param outputFiles
|
||
|
* existing files in output directory
|
||
|
*/
|
||
|
private DependencyTableHandler(DependencyTable dependencyTable,
|
||
|
File baseDir) {
|
||
|
this.dependencyTable = dependencyTable;
|
||
|
this.baseDir = baseDir;
|
||
|
includes = new Vector();
|
||
|
sysIncludes = new Vector();
|
||
|
source = null;
|
||
|
}
|
||
|
public void endElement(String namespaceURI, String localName,
|
||
|
String qName) throws SAXException {
|
||
|
//
|
||
|
// if </source> then
|
||
|
// create Dependency object and add to hashtable
|
||
|
// if corresponding source file exists and
|
||
|
// has the same timestamp
|
||
|
//
|
||
|
if (qName.equals("source")) {
|
||
|
if (source != null && includePath != null) {
|
||
|
File existingFile = new File(baseDir, source);
|
||
|
//
|
||
|
// if the file exists and the time stamp is right
|
||
|
// preserve the dependency info
|
||
|
if (existingFile.exists()) {
|
||
|
//
|
||
|
// would have expected exact matches
|
||
|
// but was seeing some unexpected difference by
|
||
|
// a few tens of milliseconds, as long
|
||
|
// as the times are within a second
|
||
|
long existingLastModified = existingFile.lastModified();
|
||
|
long diff = existingLastModified - sourceLastModified;
|
||
|
if (diff >= -500 && diff <= 500) {
|
||
|
DependencyInfo dependInfo = new DependencyInfo(
|
||
|
includePath, source, sourceLastModified,
|
||
|
includes, sysIncludes);
|
||
|
dependencyTable.putDependencyInfo(source,
|
||
|
dependInfo);
|
||
|
}
|
||
|
}
|
||
|
source = null;
|
||
|
includes.setSize(0);
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// this causes any <source> elements outside the
|
||
|
// scope of an <includePath> to be discarded
|
||
|
//
|
||
|
if (qName.equals("includePath")) {
|
||
|
includePath = null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* startElement handler
|
||
|
*/
|
||
|
public void startElement(String namespaceURI, String localName,
|
||
|
String qName, Attributes atts) throws SAXException {
|
||
|
//
|
||
|
// if includes, then add relative file name to vector
|
||
|
//
|
||
|
if (qName.equals("include")) {
|
||
|
includes.addElement(atts.getValue("file"));
|
||
|
} else {
|
||
|
if (qName.equals("sysinclude")) {
|
||
|
sysIncludes.addElement(atts.getValue("file"));
|
||
|
} else {
|
||
|
//
|
||
|
// if source then
|
||
|
// capture source file name,
|
||
|
// modification time and reset includes vector
|
||
|
//
|
||
|
if (qName.equals("source")) {
|
||
|
source = atts.getValue("file");
|
||
|
sourceLastModified = Long.parseLong(atts
|
||
|
.getValue("lastModified"), 16);
|
||
|
includes.setSize(0);
|
||
|
sysIncludes.setSize(0);
|
||
|
} else {
|
||
|
if (qName.equals("includePath")) {
|
||
|
includePath = atts.getValue("signature");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
public abstract class DependencyVisitor {
|
||
|
/**
|
||
|
* Previews all the children of this source file.
|
||
|
*
|
||
|
* May be called multiple times as DependencyInfo's for children are
|
||
|
* filled in.
|
||
|
*
|
||
|
* @return true to continue towards recursion into included files
|
||
|
*/
|
||
|
public abstract boolean preview(DependencyInfo parent,
|
||
|
DependencyInfo[] children);
|
||
|
/**
|
||
|
* Called if the dependency depth exhausted the stack.
|
||
|
*/
|
||
|
public abstract void stackExhausted();
|
||
|
/**
|
||
|
* Visits the dependency info.
|
||
|
*
|
||
|
* @returns true to continue towards recursion into included files
|
||
|
*/
|
||
|
public abstract boolean visit(DependencyInfo dependInfo);
|
||
|
}
|
||
|
public class TimestampChecker extends DependencyVisitor {
|
||
|
private boolean noNeedToRebuild;
|
||
|
private long outputLastModified;
|
||
|
private boolean rebuildOnStackExhaustion;
|
||
|
public TimestampChecker(final long outputLastModified,
|
||
|
boolean rebuildOnStackExhaustion) {
|
||
|
this.outputLastModified = outputLastModified;
|
||
|
noNeedToRebuild = true;
|
||
|
this.rebuildOnStackExhaustion = rebuildOnStackExhaustion;
|
||
|
}
|
||
|
public boolean getMustRebuild() {
|
||
|
return !noNeedToRebuild;
|
||
|
}
|
||
|
public boolean preview(DependencyInfo parent, DependencyInfo[] children) {
|
||
|
int withCompositeTimes = 0;
|
||
|
long parentCompositeLastModified = parent.getSourceLastModified();
|
||
|
for (int i = 0; i < children.length; i++) {
|
||
|
if (children[i] != null) {
|
||
|
//
|
||
|
// expedient way to determine if a child forces us to
|
||
|
// rebuild
|
||
|
//
|
||
|
visit(children[i]);
|
||
|
long childCompositeLastModified = children[i]
|
||
|
.getCompositeLastModified();
|
||
|
if (childCompositeLastModified != Long.MIN_VALUE) {
|
||
|
withCompositeTimes++;
|
||
|
if (childCompositeLastModified > parentCompositeLastModified) {
|
||
|
parentCompositeLastModified = childCompositeLastModified;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (withCompositeTimes == children.length) {
|
||
|
parent.setCompositeLastModified(parentCompositeLastModified);
|
||
|
}
|
||
|
//
|
||
|
// may have been changed by an earlier call to visit()
|
||
|
//
|
||
|
return noNeedToRebuild;
|
||
|
}
|
||
|
public void stackExhausted() {
|
||
|
if (rebuildOnStackExhaustion) {
|
||
|
noNeedToRebuild = false;
|
||
|
}
|
||
|
}
|
||
|
public boolean visit(DependencyInfo dependInfo) {
|
||
|
if (noNeedToRebuild) {
|
||
|
if (dependInfo.getSourceLastModified() > outputLastModified
|
||
|
|| dependInfo.getCompositeLastModified() > outputLastModified) {
|
||
|
noNeedToRebuild = false;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// only need to process the children if
|
||
|
// it has not yet been determined whether
|
||
|
// we need to rebuild and the composite modified time
|
||
|
// has not been determined for this file
|
||
|
return noNeedToRebuild
|
||
|
&& dependInfo.getCompositeLastModified() == Long.MIN_VALUE;
|
||
|
}
|
||
|
}
|
||
|
private/* final */File baseDir;
|
||
|
private String baseDirPath;
|
||
|
/**
|
||
|
* a hashtable of DependencyInfo[] keyed by output file name
|
||
|
*/
|
||
|
private final Hashtable dependencies = new Hashtable();
|
||
|
/** The file the cache was loaded from. */
|
||
|
private/* final */File dependenciesFile;
|
||
|
/** Flag indicating whether the cache should be written back to file. */
|
||
|
private boolean dirty;
|
||
|
/**
|
||
|
* Creates a target history table from dependencies.xml in the prject
|
||
|
* directory, if it exists. Otherwise, initializes the dependencies empty.
|
||
|
*
|
||
|
* @param task
|
||
|
* task used for logging history load errors
|
||
|
* @param baseDir
|
||
|
* output directory for task
|
||
|
*/
|
||
|
public DependencyTable(File baseDir) {
|
||
|
if (baseDir == null) {
|
||
|
throw new NullPointerException("baseDir");
|
||
|
}
|
||
|
this.baseDir = baseDir;
|
||
|
try {
|
||
|
baseDirPath = baseDir.getCanonicalPath();
|
||
|
} catch (IOException ex) {
|
||
|
baseDirPath = baseDir.toString();
|
||
|
}
|
||
|
dirty = false;
|
||
|
//
|
||
|
// load any existing dependencies from file
|
||
|
dependenciesFile = new File(baseDir, "dependencies.xml");
|
||
|
}
|
||
|
public void commit(CCTask task) {
|
||
|
//
|
||
|
// if not dirty, no need to update file
|
||
|
//
|
||
|
if (dirty) {
|
||
|
//
|
||
|
// walk through dependencies to get vector of include paths
|
||
|
// identifiers
|
||
|
//
|
||
|
Vector includePaths = getIncludePaths();
|
||
|
//
|
||
|
//
|
||
|
// write dependency file
|
||
|
//
|
||
|
try {
|
||
|
FileOutputStream outStream = new FileOutputStream(
|
||
|
dependenciesFile);
|
||
|
OutputStreamWriter streamWriter;
|
||
|
//
|
||
|
// Early VM's may not have UTF-8 support
|
||
|
// fallback to default code page which
|
||
|
// "should" be okay unless there are
|
||
|
// non ASCII file names
|
||
|
String encodingName = "UTF-8";
|
||
|
try {
|
||
|
streamWriter = new OutputStreamWriter(outStream, "UTF-8");
|
||
|
} catch (UnsupportedEncodingException ex) {
|
||
|
streamWriter = new OutputStreamWriter(outStream);
|
||
|
encodingName = streamWriter.getEncoding();
|
||
|
}
|
||
|
BufferedWriter writer = new BufferedWriter(streamWriter);
|
||
|
writer.write("<?xml version='1.0' encoding='");
|
||
|
writer.write(encodingName);
|
||
|
writer.write("'?>\n");
|
||
|
writer.write("<dependencies>\n");
|
||
|
StringBuffer buf = new StringBuffer();
|
||
|
Enumeration includePathEnum = includePaths.elements();
|
||
|
while (includePathEnum.hasMoreElements()) {
|
||
|
writeIncludePathDependencies((String) includePathEnum
|
||
|
.nextElement(), writer, buf);
|
||
|
}
|
||
|
writer.write("</dependencies>\n");
|
||
|
writer.close();
|
||
|
dirty = false;
|
||
|
} catch (IOException ex) {
|
||
|
task.log("Error writing " + dependenciesFile.toString() + ":"
|
||
|
+ ex.toString());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Returns an enumerator of DependencyInfo's
|
||
|
*/
|
||
|
public Enumeration elements() {
|
||
|
return dependencies.elements();
|
||
|
}
|
||
|
/**
|
||
|
* This method returns a DependencyInfo for the specific source file and
|
||
|
* include path identifier
|
||
|
*
|
||
|
*/
|
||
|
public DependencyInfo getDependencyInfo(String sourceRelativeName,
|
||
|
String includePathIdentifier) {
|
||
|
DependencyInfo dependInfo = null;
|
||
|
DependencyInfo[] dependInfos = (DependencyInfo[]) dependencies
|
||
|
.get(sourceRelativeName);
|
||
|
if (dependInfos != null) {
|
||
|
for (int i = 0; i < dependInfos.length; i++) {
|
||
|
dependInfo = dependInfos[i];
|
||
|
if (dependInfo.getIncludePathIdentifier().equals(
|
||
|
includePathIdentifier)) {
|
||
|
return dependInfo;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
private Vector getIncludePaths() {
|
||
|
Vector includePaths = new Vector();
|
||
|
DependencyInfo[] dependInfos;
|
||
|
Enumeration dependenciesEnum = dependencies.elements();
|
||
|
while (dependenciesEnum.hasMoreElements()) {
|
||
|
dependInfos = (DependencyInfo[]) dependenciesEnum.nextElement();
|
||
|
for (int i = 0; i < dependInfos.length; i++) {
|
||
|
DependencyInfo dependInfo = dependInfos[i];
|
||
|
boolean matchesExisting = false;
|
||
|
final String dependIncludePath = dependInfo
|
||
|
.getIncludePathIdentifier();
|
||
|
Enumeration includePathEnum = includePaths.elements();
|
||
|
while (includePathEnum.hasMoreElements()) {
|
||
|
if (dependIncludePath.equals(includePathEnum.nextElement())) {
|
||
|
matchesExisting = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!matchesExisting) {
|
||
|
includePaths.addElement(dependIncludePath);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return includePaths;
|
||
|
}
|
||
|
public void load() throws IOException, ParserConfigurationException,
|
||
|
SAXException {
|
||
|
dependencies.clear();
|
||
|
if (dependenciesFile.exists()) {
|
||
|
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||
|
factory.setValidating(false);
|
||
|
SAXParser parser = factory.newSAXParser();
|
||
|
parser.parse(dependenciesFile, new DependencyTableHandler(this,
|
||
|
baseDir));
|
||
|
dirty = false;
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Determines if the specified target needs to be rebuilt.
|
||
|
*
|
||
|
* This task may result in substantial IO as files are parsed to determine
|
||
|
* their dependencies
|
||
|
*/
|
||
|
public boolean needsRebuild(CCTask task, TargetInfo target,
|
||
|
int dependencyDepth) {
|
||
|
// look at any files where the compositeLastModified
|
||
|
// is not known, but the includes are known
|
||
|
//
|
||
|
boolean mustRebuild = false;
|
||
|
CompilerConfiguration compiler = (CompilerConfiguration) target
|
||
|
.getConfiguration();
|
||
|
String includePathIdentifier = compiler.getIncludePathIdentifier();
|
||
|
File[] sources = target.getSources();
|
||
|
DependencyInfo[] dependInfos = new DependencyInfo[sources.length];
|
||
|
long outputLastModified = target.getOutput().lastModified();
|
||
|
//
|
||
|
// try to solve problem using existing dependency info
|
||
|
// (not parsing any new files)
|
||
|
//
|
||
|
DependencyInfo[] stack = new DependencyInfo[50];
|
||
|
boolean rebuildOnStackExhaustion = true;
|
||
|
if (dependencyDepth >= 0) {
|
||
|
if (dependencyDepth < 50) {
|
||
|
stack = new DependencyInfo[dependencyDepth];
|
||
|
}
|
||
|
rebuildOnStackExhaustion = false;
|
||
|
}
|
||
|
TimestampChecker checker = new TimestampChecker(outputLastModified,
|
||
|
rebuildOnStackExhaustion);
|
||
|
for (int i = 0; i < sources.length && !mustRebuild; i++) {
|
||
|
File source = sources[i];
|
||
|
String relative = CUtil.getRelativePath(baseDirPath, source);
|
||
|
DependencyInfo dependInfo = getDependencyInfo(relative,
|
||
|
includePathIdentifier);
|
||
|
if (dependInfo == null) {
|
||
|
task.log("Parsing " + relative, Project.MSG_VERBOSE);
|
||
|
dependInfo = parseIncludes(task, compiler, source);
|
||
|
}
|
||
|
walkDependencies(task, dependInfo, compiler, stack, checker);
|
||
|
mustRebuild = checker.getMustRebuild();
|
||
|
}
|
||
|
return mustRebuild;
|
||
|
}
|
||
|
public DependencyInfo parseIncludes(CCTask task,
|
||
|
CompilerConfiguration compiler, File source) {
|
||
|
DependencyInfo dependInfo = compiler.parseIncludes(task, baseDir,
|
||
|
source);
|
||
|
String relativeSource = CUtil.getRelativePath(baseDirPath, source);
|
||
|
putDependencyInfo(relativeSource, dependInfo);
|
||
|
return dependInfo;
|
||
|
}
|
||
|
private void putDependencyInfo(String key, DependencyInfo dependInfo) {
|
||
|
//
|
||
|
// optimistic, add new value
|
||
|
//
|
||
|
DependencyInfo[] old = (DependencyInfo[]) dependencies.put(key,
|
||
|
new DependencyInfo[]{dependInfo});
|
||
|
dirty = true;
|
||
|
//
|
||
|
// something was already there
|
||
|
//
|
||
|
if (old != null) {
|
||
|
//
|
||
|
// see if the include path matches a previous entry
|
||
|
// if so replace it
|
||
|
String includePathIdentifier = dependInfo
|
||
|
.getIncludePathIdentifier();
|
||
|
for (int i = 0; i < old.length; i++) {
|
||
|
DependencyInfo oldDepend = old[i];
|
||
|
if (oldDepend.getIncludePathIdentifier().equals(
|
||
|
includePathIdentifier)) {
|
||
|
old[i] = dependInfo;
|
||
|
dependencies.put(key, old);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// no match prepend the new entry to the array
|
||
|
// of dependencies for the file
|
||
|
DependencyInfo[] combined = new DependencyInfo[old.length + 1];
|
||
|
combined[0] = dependInfo;
|
||
|
for (int i = 0; i < old.length; i++) {
|
||
|
combined[i + 1] = old[i];
|
||
|
}
|
||
|
dependencies.put(key, combined);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
public void walkDependencies(CCTask task, DependencyInfo dependInfo,
|
||
|
CompilerConfiguration compiler, DependencyInfo[] stack,
|
||
|
DependencyVisitor visitor) throws BuildException {
|
||
|
//
|
||
|
// visit this node
|
||
|
// if visit returns true then
|
||
|
// visit the referenced include and sysInclude dependencies
|
||
|
//
|
||
|
if (visitor.visit(dependInfo)) {
|
||
|
//
|
||
|
// find first null entry on stack
|
||
|
//
|
||
|
int stackPosition = -1;
|
||
|
for (int i = 0; i < stack.length; i++) {
|
||
|
if (stack[i] == null) {
|
||
|
stackPosition = i;
|
||
|
stack[i] = dependInfo;
|
||
|
break;
|
||
|
} else {
|
||
|
//
|
||
|
// if we have appeared early in the calling history
|
||
|
// then we didn't exceed the criteria
|
||
|
if (stack[i] == dependInfo) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (stackPosition == -1) {
|
||
|
visitor.stackExhausted();
|
||
|
return;
|
||
|
}
|
||
|
//
|
||
|
// locate dependency infos
|
||
|
//
|
||
|
String[] includes = dependInfo.getIncludes();
|
||
|
String includePathIdentifier = compiler.getIncludePathIdentifier();
|
||
|
DependencyInfo[] includeInfos = new DependencyInfo[includes.length];
|
||
|
for (int i = 0; i < includes.length; i++) {
|
||
|
DependencyInfo includeInfo = getDependencyInfo(includes[i],
|
||
|
includePathIdentifier);
|
||
|
includeInfos[i] = includeInfo;
|
||
|
}
|
||
|
//
|
||
|
// preview with only the already available dependency infos
|
||
|
//
|
||
|
if (visitor.preview(dependInfo, includeInfos)) {
|
||
|
//
|
||
|
// now need to fill in the missing DependencyInfos
|
||
|
//
|
||
|
int missingCount = 0;
|
||
|
for (int i = 0; i < includes.length; i++) {
|
||
|
if (includeInfos[i] == null) {
|
||
|
missingCount++;
|
||
|
task.log("Parsing " + includes[i], Project.MSG_VERBOSE);
|
||
|
// If the include is part of a UNC don't go building a
|
||
|
// relative file name.
|
||
|
File src = includes[i].startsWith("\\\\") ? new File(
|
||
|
includes[i]) : new File(baseDir, includes[i]);
|
||
|
DependencyInfo includeInfo = parseIncludes(task,
|
||
|
compiler, src);
|
||
|
includeInfos[i] = includeInfo;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// if it passes a review the second time
|
||
|
// then recurse into all the children
|
||
|
if (missingCount == 0
|
||
|
|| visitor.preview(dependInfo, includeInfos)) {
|
||
|
//
|
||
|
// recurse into
|
||
|
//
|
||
|
for (int i = 0; i < includeInfos.length; i++) {
|
||
|
DependencyInfo includeInfo = includeInfos[i];
|
||
|
walkDependencies(task, includeInfo, compiler, stack,
|
||
|
visitor);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
stack[stackPosition] = null;
|
||
|
}
|
||
|
}
|
||
|
private void writeDependencyInfo(BufferedWriter writer, StringBuffer buf,
|
||
|
DependencyInfo dependInfo) throws IOException {
|
||
|
String[] includes = dependInfo.getIncludes();
|
||
|
String[] sysIncludes = dependInfo.getSysIncludes();
|
||
|
//
|
||
|
// if the includes have not been evaluted then
|
||
|
// it is not worth our time saving it
|
||
|
// and trying to distiguish between files with
|
||
|
// no dependencies and those with undetermined dependencies
|
||
|
buf.setLength(0);
|
||
|
buf.append(" <source file=\"");
|
||
|
buf.append(CUtil.xmlAttribEncode(dependInfo.getSource()));
|
||
|
buf.append("\" lastModified=\"");
|
||
|
buf.append(Long.toHexString(dependInfo.getSourceLastModified()));
|
||
|
buf.append("\">\n");
|
||
|
writer.write(buf.toString());
|
||
|
for (int i = 0; i < includes.length; i++) {
|
||
|
buf.setLength(0);
|
||
|
buf.append(" <include file=\"");
|
||
|
buf.append(CUtil.xmlAttribEncode(includes[i]));
|
||
|
buf.append("\"/>\n");
|
||
|
writer.write(buf.toString());
|
||
|
}
|
||
|
for (int i = 0; i < sysIncludes.length; i++) {
|
||
|
buf.setLength(0);
|
||
|
buf.append(" <sysinclude file=\"");
|
||
|
buf.append(CUtil.xmlAttribEncode(sysIncludes[i]));
|
||
|
buf.append("\"/>\n");
|
||
|
writer.write(buf.toString());
|
||
|
}
|
||
|
writer.write(" </source>\n");
|
||
|
return;
|
||
|
}
|
||
|
private void writeIncludePathDependencies(String includePathIdentifier,
|
||
|
BufferedWriter writer, StringBuffer buf) throws IOException {
|
||
|
//
|
||
|
// include path element
|
||
|
//
|
||
|
buf.setLength(0);
|
||
|
buf.append(" <includePath signature=\"");
|
||
|
buf.append(CUtil.xmlAttribEncode(includePathIdentifier));
|
||
|
buf.append("\">\n");
|
||
|
writer.write(buf.toString());
|
||
|
Enumeration dependenciesEnum = dependencies.elements();
|
||
|
while (dependenciesEnum.hasMoreElements()) {
|
||
|
DependencyInfo[] dependInfos = (DependencyInfo[]) dependenciesEnum
|
||
|
.nextElement();
|
||
|
for (int i = 0; i < dependInfos.length; i++) {
|
||
|
DependencyInfo dependInfo = dependInfos[i];
|
||
|
//
|
||
|
// if this is for the same include path
|
||
|
// then output the info
|
||
|
if (dependInfo.getIncludePathIdentifier().equals(
|
||
|
includePathIdentifier)) {
|
||
|
writeDependencyInfo(writer, buf, dependInfo);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
writer.write(" </includePath>\n");
|
||
|
}
|
||
|
}
|