From 5a4c434254011a0d193f884c5b608a3331df4aee Mon Sep 17 00:00:00 2001
From: jwang36 <jwang36@6f19259b-4bc3-4df7-8a09-765794883524>
Date: Sun, 8 Oct 2006 06:28:06 +0000
Subject: Removed the need of external MakeDeps.exe. Now parsing include files
 is built in makedeps task.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1683 6f19259b-4bc3-4df7-8a09-765794883524
---
 .../org/tianocore/framework/tasks/MakeDeps.java    | 301 ++++++++++++---------
 .../org/tianocore/framework/tasks/NestElement.java |  18 ++
 2 files changed, 197 insertions(+), 122 deletions(-)

(limited to 'Tools/Java/Source')

diff --git a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java
index 8f5664f01d..27e0ed7be5 100644
--- a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java
+++ b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java
@@ -14,11 +14,22 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 package org.tianocore.framework.tasks;
 
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.io.LineNumberReader;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -26,9 +37,8 @@ import org.apache.tools.ant.Task;
 import org.apache.tools.ant.taskdefs.Execute;
 import org.apache.tools.ant.taskdefs.LogStreamHandler;
 import org.apache.tools.ant.types.Commandline;
-
-import org.tianocore.common.logger.EdkLog;
 import org.tianocore.common.cache.FileTimeStamp;
+import org.tianocore.common.logger.EdkLog;
 
 /**
  Class MakeDeps is used to wrap MakeDeps.exe as an ANT task.
@@ -38,14 +48,17 @@ public class MakeDeps extends Task {
     //
     // private members, use set/get to access them
     //
-    private static final String toolName = "MakeDeps";
-    private FileArg              depsFile = new FileArg();
-    private ToolArg              subDir = new ToolArg();
-    private ToolArg              quietMode = new ToolArg(" -", "q");
-    private ToolArg              ignoreError = new ToolArg(" -", "ignorenotfound");
-    private IncludePath          includePathList = new IncludePath();
-    private Input                inputFileList = new Input();
-    private ToolArg              target = new FileArg(" -target ", "dummy");
+    private String      depsFilePath = "";
+    private IncludePath includePathList = new IncludePath();
+    private Input       inputFileList = new Input();
+    //
+    // cache the including files to speed up dependency check
+    // 
+    private static HashMap<String, Set<String>> includesCache = new HashMap<String, Set<String>>();
+    //
+    // regular expression for "#include ..." directive
+    // 
+    private static final Pattern incPattern = Pattern.compile("[\n\r \t]*#[ \t]*include[ \t\"<]+([^\n\r\"<>]+)");
 
     public MakeDeps() {
 
@@ -60,63 +73,59 @@ public class MakeDeps extends Task {
      @throws    BuildException
      **/
     public void execute() throws BuildException {
-        ///
-        /// check if the dependency list file is uptodate or not
-        ///
+        //
+        // check if the dependency list file is uptodate or not
+        //
         if (isUptodate()) {
             return;
         }
 
-        Project prj  = this.getOwningTarget().getProject();
-        String  toolPath = prj.getProperty("env.FRAMEWORK_TOOLS_PATH");
-
-        ///
-        /// compose full tool path
-        ///
-        if (toolPath == null || toolPath.length() == 0) {
-            toolPath = toolName;
-        } else {
-            if (toolPath.endsWith("/") || toolPath.endsWith("\\")) {
-                toolPath = toolPath + toolName;
-            } else {
-                toolPath = toolPath + File.separator + toolName;
-            }
+        //
+        // if no include path is specified, try locally
+        // 
+        if (includePathList.isEmpty()) {
+            includePathList.insPath(".");
         }
 
-        ///
-        /// compose tool arguments
-        ///
-        String argument = "" + inputFileList + includePathList + subDir
-                             + quietMode + ignoreError + target + depsFile;
+        Set<String> depFiles = getDependencies(inputFileList.toArray());
 
-        ///
-        /// prepare to execute the tool
-        ///
-        Commandline cmd = new Commandline();
-        cmd.setExecutable(toolPath);
-        cmd.createArgument().setLine(argument);
+        File depsFile = new File(depsFilePath);
+        FileWriter fileWriter = null;
+        BufferedWriter bufWriter = null;
 
-        LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN);
-        Execute runner = new Execute(streamHandler, null);
-
-        runner.setAntRun(prj);
-        runner.setCommandline(cmd.getCommandline());
+        try {
+            fileWriter = new FileWriter(depsFile);
+            bufWriter = new BufferedWriter(fileWriter);
 
-        EdkLog.log(this, EdkLog.EDK_VERBOSE, Commandline.toString(cmd.getCommandline()));
 
-        int result = 0;
-        try {
-            result = runner.execute();
-        } catch (IOException e) {
+            for (Iterator it = depFiles.iterator(); it.hasNext();) {
+                String depFile = (String)it.next();
+                bufWriter.write(depFile, 0, depFile.length());
+                bufWriter.write("\n", 0, 1);
+            }
+            //
+            // put a "tab" at the end of file as file ending flag
+            // 
+            bufWriter.write("\t", 0, 1);
+        } catch (Exception e) {
             throw new BuildException(e.getMessage());
+        } finally {
+            try {
+                if (bufWriter != null) {
+                    bufWriter.close();
+                }
+                if (fileWriter != null) {
+                    fileWriter.close();
+                }
+            } catch (Exception e) {
+                throw new BuildException(e.getMessage());
+            }
         }
 
-        if (result != 0) {
-            EdkLog.log(this, EdkLog.EDK_INFO, toolName + " failed!");
-            throw new BuildException(toolName + ": failed to generate dependency file!");
-        } else {
-            EdkLog.log(this, EdkLog.EDK_VERBOSE, toolName + " succeeded!");
-        }
+        //
+        // update time stamp of dependency file
+        // 
+        FileTimeStamp.update(depsFilePath, depsFile.lastModified());
     }
 
     /**
@@ -125,7 +134,7 @@ public class MakeDeps extends Task {
      @param     name    The name of dependency list file
      **/
     public void setDepsFile(String name) {
-        depsFile.setArg(" -o ", name);
+        depsFilePath = name;
     }
 
     /**
@@ -134,65 +143,7 @@ public class MakeDeps extends Task {
      @returns   The name of dependency list file
      **/
     public String getDepsFile() {
-        return depsFile.getValue();
-    }
-
-    /**
-     Set method for "IgnoreError" attribute
-
-     @param     ignore    flag to control error handling (true/false)
-     **/
-    public void setIgnoreError(boolean ignore) {
-        if (!ignore) {
-            ignoreError.setArg(" ", " ");
-        }
-    }
-
-    /**
-     Get method for "IgnoreError" attribute
-
-     @returns   The value of current IgnoreError flag
-     **/
-    public boolean getIgnoreError() {
-        return ignoreError.getValue().length() > 0;
-    }
-
-    /**
-     Set method for "QuietMode" attribute
-
-     @param     quiet   flag to control the output information (true/false)
-     **/
-    public void setQuietMode(boolean quiet) {
-        if (!quiet) {
-            quietMode.setArg(" ", " ");
-        }
-    }
-
-    /**
-     Get method for "QuietMode" attribute
-
-     @returns   value of current QuietMode flag
-     **/
-    public boolean getQuietMode() {
-        return quietMode.getValue().length() > 0;
-    }
-
-    /**
-     Set method for "SubDir" attribute
-
-     @param     dir     The name of sub-directory in which source files will be scanned
-     **/
-    public void setSubDir(String dir) {
-        subDir.setArg(" -s ", dir);
-    }
-
-    /**
-     Get method for "SubDir" attribute
-
-     @returns   The name of sub-directory
-     **/
-    public String getSubDir() {
-        return subDir.getValue();
+        return depsFilePath;
     }
 
     /**
@@ -220,10 +171,9 @@ public class MakeDeps extends Task {
      @returns   false   The dependency list file is outofdate. Re-generation is needed.
      **/
     private boolean isUptodate() {
-        String dfName = depsFile.getValue();
-        File df = new File(dfName);
+        File df = new File(depsFilePath);
         if (!df.exists()) {
-            EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " doesn't exist!");
+            EdkLog.log(this, EdkLog.EDK_VERBOSE, depsFilePath + " doesn't exist!");
             return false;
         }
 
@@ -231,7 +181,7 @@ public class MakeDeps extends Task {
         // If the source file(s) is newer than dependency list file, we need to
         // re-generate the dependency list file
         //
-        long depsFileTimeStamp = FileTimeStamp.get(dfName);
+        long depsFileTimeStamp = FileTimeStamp.get(depsFilePath);
         List<String> fileList = inputFileList.getNameList();
         for (int i = 0, length = fileList.size(); i < length; ++i) {
             String sf = fileList.get(i);
@@ -288,17 +238,124 @@ public class MakeDeps extends Task {
             // check if the .dep file is empty
             // 
             if (lines == 0) {
-                EdkLog.log(this, EdkLog.EDK_VERBOSE, dfName + " is empty!");
+                EdkLog.log(this, EdkLog.EDK_VERBOSE, depsFilePath + " is empty!");
                 ret = false;
             }
-
-            lineReader.close();
-            fileReader.close();
         } catch (IOException e) {
             throw new BuildException(e.getMessage());
+        } finally {
+            try {
+                if (lineReader != null) {
+                    lineReader.close();
+                }
+                if (fileReader != null) {
+                    fileReader.close();
+                }
+            } catch (Exception e) {
+                throw new BuildException(e.getMessage());
+            }
         }
 
         return ret;
     }
+
+    //
+    // get dependent files list by parsing "#include" directive
+    // 
+    private synchronized Set<String> getDependencies(String[] sourceFiles) {
+        Set<String> dependencies = new LinkedHashSet<String>();
+        String[] searchPathList = includePathList.toArray();
+
+        Stack<String> pendingFiles = new Stack<String>();
+        for (int i = 0; i < sourceFiles.length; ++i) {
+            File srcFile = new File(sourceFiles[i]);
+            if (srcFile.exists()) {
+                //
+                // a file must depend itself
+                // 
+                dependencies.add(srcFile.getAbsolutePath());
+                pendingFiles.push(sourceFiles[i]);
+            }
+        }
+
+        while (!pendingFiles.empty()) {
+            String src = pendingFiles.pop();
+            File srcFile = new File(src);
+            if (!srcFile.exists()) {
+                continue;
+            }
+
+            //
+            // try cache first
+            // 
+            Set<String> incFiles = includesCache.get(src);
+            if (incFiles == null) {
+                incFiles = new HashSet<String>();
+                FileReader fileReader = null;
+                BufferedReader bufReader = null;
+                String fileContent = "";
+                int fileLength = (int)srcFile.length();
+
+                try {
+                    fileReader = new FileReader(srcFile);
+                    bufReader  = new BufferedReader(fileReader);
+                    char[] buf = new char[fileLength];
+
+                    bufReader.read(buf, 0, fileLength);
+                    fileContent = new String(buf);
+                } catch (IOException e) {
+                    throw new BuildException(e.getMessage());
+                } finally {
+                    try {
+                        if (bufReader != null) {
+                            bufReader.close();
+                        }
+                        if (fileReader != null) {
+                            fileReader.close();
+                        }
+                    } catch (Exception e) {
+                        throw new BuildException(e.getMessage());
+                    }
+                }
+
+                //
+                // find out all "#include" lines
+                // 
+                Matcher matcher = incPattern.matcher(fileContent);
+                while (matcher.find()) {
+                    String incFilePath = fileContent.substring(matcher.start(1), matcher.end(1));
+                    incFiles.add(incFilePath);
+                }
+
+                //
+                // put the includes in cache to avoid re-parsing
+                // 
+                includesCache.put(src, incFiles);
+            }
+
+            //
+            // try each include search path to see if the include file exists or not
+            // 
+            for (Iterator<String> it = incFiles.iterator(); it.hasNext();) {
+                String depFilePath = it.next();
+
+                for (int i = 0; i < searchPathList.length; ++i) {
+                    File depFile = new File(searchPathList[i] + File.separator + depFilePath);
+                    String filePath = depFile.getAbsolutePath();
+                    //
+                    // following check is a must. it can prevent dead loop if two
+                    // files include each other
+                    // 
+                    if (depFile.exists() && !dependencies.contains(filePath)) {
+                        dependencies.add(filePath);
+                        pendingFiles.push(filePath);
+                        break;
+                    }
+                }
+            }
+        }
+
+        return dependencies;
+    }
 }
 
diff --git a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java
index 271dee6c88..dd36c9127b 100644
--- a/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java
+++ b/Tools/Java/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java
@@ -333,6 +333,24 @@ public class NestElement extends DataType {
         return toFileList(" ");
     }
 
+    /**
+       Get the array of names
+
+       @return String[]     The array contains the names
+     **/
+    public String[] toArray() {
+        return nameList.toArray(new String[nameList.size()]);
+    }
+
+    /**
+       Check if we have any name or not
+
+       @return boolean
+     **/
+    public boolean isEmpty() {
+        return nameList.isEmpty();
+    }
+
     //
     // Remove any duplicated path separator or inconsistent path separator
     //
-- 
cgit v1.2.3