D patches

Lars Ivar Igesund <[email protected]> Thu, 21 Oct 2004 18:14:17 +0100
Newsgroups gmane.comp.tools.aap.devel
Message-ID <[email protected]>
A previous patch of mine was subtly changed upon inclusion in CVS, 
resulting in a non-functional CVS (and latest release). d.diff should 
repair that (apply to d.aap).
ddepcheck has been through a major overhaul, making it more robust and 
more efficient (apply ddepcheck.diff).
The dmd tool has gotten better support for dlls (didn't I post this 
patch previously?)

Lars Ivar Igesund
d.diff (text/plain, 793 B)
Index: d.aap
===================================================================
RCS file: /cvsroot/a-a-p/Exec/modules/d.aap,v
retrieving revision 1.16
diff -u -r1.16 d.aap
--- d.aap	10 Sep 2004 18:58:43 -0000	1.16
+++ d.aap	21 Oct 2004 15:56:32 -0000
@@ -91,9 +91,9 @@
         @if _no.targettype == "object":
             :attr {buildaction = d_build} $target
         @elif _no.targettype == "libobject":
-            :attr {buillibdaction = d_buildlib} $target
+            :attr {buildlibaction = d_buildlib} $target
         @elif _no.targettype == "dllobject":
-            :attr {buildlldaction = d_builddll} $target
+            :attr {builddllaction = d_builddll} $target
         @if DEFER_ACTION_NAME:
             :do $DEFER_ACTION_NAME {target = $target} $source
         @else:
ddepcheck.diff (text/plain, 32.5 KB)
Index: ddepcheck.d
===================================================================
RCS file: /cvsroot/a-a-p/Exec/tools/ddepcheck.d,v
retrieving revision 1.5
diff -u -r1.5 ddepcheck.d
--- ddepcheck.d	19 Apr 2004 08:53:47 -0000	1.5
+++ ddepcheck.d	21 Oct 2004 16:00:35 -0000
@@ -1,7 +1,7 @@
 /*
  * ddepcheck.d
- * Version 0.9.6
- * Last modified 18th of April 2004
+ * Version 1.0.1
+ * Last modified 24th of August 2004
  *
  * Dependency walker for D source files.
  * Copyright 2003-2004 Lars Ivar Igesund <larsivar'at'igesund.net>
@@ -14,23 +14,39 @@
  * or implied warranty.
  */
 
+/*
+ * TODO:
+ * - Audit code, some of it is hairy as hell.
+ * - Exchange ctype with utype when it shows up
+ * - Document better, especially code
+ * - Long term; With multiple input files, cache import results.
+ */
+
+import std.conv;
+import std.ctype;
 import std.file;
 import std.path;
 import std.stream;
 import std.string;
 import std.c.stdio;
+import std.stdio;
+
+alias std.ctype.isdigit isdigit;
 
 version (Win32) {
 import std.c.windows.windows;
 }
 
-bool helpcalled = false;
-bool versioncalled = false;
-bool write = false;
-bool makesyntax = false;
-bool comment = false;
-bool runtime = false;
-bool checkprivate = false;
+bit helpcalled = false;
+bit versioncalled = false;
+bit write = false;
+bit makesyntax = false;
+bit comment = false;
+bit runtime = false;
+bit checkprivate = false;
+bit fulldebug = false;
+bit disableversion = false;
+bit disabledebug = false;
 int curopt = 1;
 int numpaths = 0;
 int allpaths = 10;
@@ -44,6 +60,51 @@
 char [][] depdepths;
 char [][] paths;
 char [][] argslist;
+char [][] dbgidentsstr;
+char [][] veridentsstr;
+int [][] privatearr;
+int dbgidentsnum;
+int veridentsnum;
+
+/*!
+ * Static constructor.
+ * Adds version identifier strings to the list used by ddepcheck based on what
+ * is defined by the compiler.
+ */
+
+static this()
+{
+version (DigitalMars) {
+  veridentsstr ~= "DigitalMars";
+}
+version (X86) {
+  veridentsstr ~= "X86";
+}
+version (AMD64) {
+  veridentsstr ~= "AMD64";
+}
+version (Windows) {
+  veridentsstr ~= "Windows";
+}
+version (Win32) {
+  veridentsstr ~= "Win32";
+}
+version (Win64) {
+  veridentsstr ~= "Win64";
+}
+version (linux) {
+  veridentsstr ~= "linux";
+}
+version (LittleEndian) {
+  veridentsstr ~= "LittleEndian";
+}
+version (BigEndian) {
+  veridentsstr ~= "BigEndian";
+}
+version (D_InlineAsm) {
+  veridentsstr ~= "D_InlineAsm";
+}
+}
 
 /*
  * Function called when the "help" option is specified.
@@ -53,20 +114,29 @@
 {
   optVersion();
   if (!helpcalled) {
-    printf(toStringz("\n" ~
-           "Syntax: ddepcheck [options] [src ...]\n" ~
-           "  -I[path]               Add a path to be searched.\n" ~
-           "  -h/--help              Prints this help table.\n" ~
-           "  -d=[num]/--depth=[num] Limit the depth searched \n" ~
-           "                           for dependencies.\n" ~
-           "  -m/--make-syntax       Print the dependencies using the make\n" ~
-           "                           syntax. \"objectfile : src deps\"\n" ~
-           "  -V/--version           Prints the version.\n" ~
-           "  -w/--writetofile       Prints the dependencies to the file\n" ~
-           "                           'depfile' instead of to the console.\n" ~ 
-           "  -l/--checkruntimelib   Tries to add runtimelib dependencies.\n" ~
-           "                           Note that the path must be added \n" ~
-           "                           explicitly."));
+    writefln();
+    writefln("Syntax: ddepcheck [options] [src ...]");
+    writefln(" -I[path]               Add a path to be searched.");
+    writefln(" -h/--help              Prints this help table."); 
+    writefln(" -d=[num]/--depth=[num] Limit the depth searched");
+    writefln("                          for dependencies.");
+    writefln(" -m/--make-syntax       Print the dependencies using the make");
+    writefln("                          syntax. \"objectfile : src deps\"");
+    writefln(" -V/--version           Prints the version.");
+    writefln(" -w/--writetofile       Prints the dependencies to the file");
+    writefln("                          'depfile' instead of to the console."); 
+    writefln(" -l/--checkruntimelib   Tries to add runtimelib dependencies.");
+    writefln("                          Note that the path must be added ");
+    writefln("                          explicitly.");
+    writefln(" --checkprivate         Ignore private if it affects the import");
+    writefln(" -debug=[ident/num]     Uses the same switch as the compiler");
+    writefln("                          to remove/include debug codeblocks.");
+    writefln(" -version=[ident/num]   Uses the same switch as the compiler");
+    writefln("                          to remove/include version codeblocks.");
+    writefln(" -disableVersion        Don't check for version statements.");
+    writefln("                          (All imports are checked.)");
+    writefln(" -disableDebug          Don't check for debug statements.");
+    writefln("                          (All imports are checked.)");
   }
   helpcalled = true;
 }
@@ -80,7 +150,7 @@
   runtime = true;
 }
 
-/*
+/*!
  * Function called when the "checkprivate" option is specified.
  */
 
@@ -89,21 +159,21 @@
   checkprivate = true;
 }
 
-/*
+/*!
  * Function called if the "version" option is used.
  */
 
 void optVersion()
 {
   if (!versioncalled) {
-    printf(toStringz("ddepcheck\n" ~ 
-           "Dependency walker for D source files.\n" ~
-           "Version 0.9.4 Copyright Lars Ivar Igesund 2003\n"));
+    writefln("ddepcheck"); 
+    writefln("Dependency walker for D source files.");
+    writefln("Version 1.0.1 Copyright Lars Ivar Igesund 2003 - 2004");
   }
   versioncalled = true;
 }
 
-/*
+/*!
  * Function called if the "writetofile" option is used.
  */
 
@@ -112,22 +182,22 @@
   write = true;
 }
 
-/*
+/*!
  * Function called if the "depth" option is used to decide the maximum
  * depth for recursion.
  */
 
-void optDepth(int arg, bool doubledash)
+void optDepth(int arg, bit doubledash)
 {
   if (doubledash) {
-    depthlimit = (int)atoi(argslist[arg][8..argslist[arg].length]);
+    depthlimit = cast(int)atoi(argslist[arg][8..argslist[arg].length]);
   }
   else {
-    depthlimit = (int)atoi(argslist[arg][3..argslist[arg].length]);
+    depthlimit = cast(int)atoi(argslist[arg][3..argslist[arg].length]);
   }
 }
 
-/*
+/*!
  * Function called for all the "-I" import options used.
  */
 
@@ -139,7 +209,47 @@
   addPath(argslist[arg][2..argslist[arg].length]);
 }
 
-/*
+/*!
+ * Function called for all the "-debug" options used.
+ */
+
+void optDebug(int arg)
+{
+  if (argslist[arg].length == 6) {
+    fulldebug = true;
+  }
+  else {
+    char [] ident = argslist[arg][7..argslist[arg].length];
+    bit num = isNumber(ident);
+    if (num) {
+      dbgidentsnum = toInt(ident);
+    }
+    else {
+      dbgidentsstr ~= ident;
+    }
+  }
+}
+
+/*!
+ * Function called for all the "-version" options used.
+ */
+
+void optVersion(int arg)
+{
+  if (argslist[arg].length == 2) {
+    return;
+  }
+  char [] ident = argslist[arg][9..argslist[arg].length];
+  bit num = isNumber(ident);
+  if (num) {
+    veridentsnum = toInt(ident);
+  }
+  else {
+    veridentsstr ~= ident;
+  }
+}
+
+/*!
  * Function called when the "-m"/"--make-syntax" option is used.
  */
 
@@ -148,11 +258,29 @@
   makesyntax = true;
 }
 
-/*
+/*!
+ * Function called when the "-disableVersion" option is used.
+ */
+
+void optDisableVersion()
+{
+  disableversion = true;
+}
+
+/*!
+ * Function called when the "-disableDebug" option is used.
+ */
+
+void optDisableDebug()
+{
+  disabledebug = true;
+}
+
+/*!
  * Function that checks if an argument is an option.
  */
 
-bool checkOption(int arg)
+bit checkOption(int arg)
 {
   switch (argslist[arg]) {
   case "--version":
@@ -185,10 +313,19 @@
     optCheckPrivate();
     return true;
     break;
+  case "--disableVersion":
+    optDisableVersion();
+    return true;
+    break;
+  case "--disableDebug":
+    optDisableDebug();
+    return true;
+    break;
   default:
     break;
   }
-  if (cmp(argslist[arg][0..3], "-d=") == 0) {
+  if (argslist[arg].length > 3 && 
+      cmp(argslist[arg][0..3], "-d=") == 0) {
     optDepth(arg, false);
     return true;
   }
@@ -197,14 +334,25 @@
     optDepth(arg, true);
     return true;
   }
-  if (cmp(argslist[arg][0..2], "-I") == 0) {
+  if (argslist[arg].length > 2 && 
+      cmp(argslist[arg][0..2], "-I") == 0) {
     optImport(arg);
     return true;
   }
+  if (argslist[arg].length > 5 && 
+      cmp(argslist[arg][0..6], "-debug") == 0) {
+    optDebug(arg);
+    return true;
+  }
+  if (argslist[arg].length > 8 && 
+      cmp(argslist[arg][0..8], "-version") == 0) {
+    optVersion(arg);
+    return true;
+  }
   return false;
 }
 
-/*
+/*!
  * Function that starts the dependency walking for base source files.
  */
 
@@ -214,85 +362,669 @@
   depWalk(argslist[arg], "", true);
 }
 
-/*
+/*!
  * Function that do the main dependency walking recursively. If it find
  * files that has been walked before, it skips it to avoid infinite
  * cyclic dependencies.
  */
 
-void depWalk(char [] file, char [] mod, bool base)
+void depWalk(char [] file,char [] mod, bit base)
 {
+  debug writefln("Filename: ", file);
+
   char [] filepath = file;
-  int i = 0;
-  while (i < numpaths && !fileExist(filepath)) {
-    filepath = std.path.join(paths[i], file);
-    i++;
+  char [] src;
+  int pathnum = 0;
+  int [] importpos;
+  importpos.length = 0;
+  int nextimport = -1;
+  char [][] verspecstrings;
+  char [][] dbgspecstrings;
+
+  while (pathnum < numpaths && !fileExist(filepath)) {
+    filepath = std.path.join(paths[pathnum], file);
+    pathnum++;
   }
+
+  try {
+    src = (new File(filepath)).toString();
+  }
+  catch (Error e) {
+    return;
+  }
+
   if (!base) {
     if (!addDep(filepath, mod, depth)) {
       return;
     }
   }
-  File src = new File(filepath);
-  while (!src.eof()) {
-    char [] line = src.readLine();
-    if (stripComment(line)) {
-      continue;
+
+  stripComment(src);
+
+
+  bit useVersion(int pos) 
+  {
+    int i = pos + 7;
+    int j;
+    while (src[i] != '(') {
+      i++;
+    }
+    j = i + 1;
+    while (src[j] != ')') {
+      j++;
+    }
+    char [] ident = src[i + 1..j];
+    if (ident.length == 0) {
+      return true;
+    }
+    bit num = true;
+    foreach (char c; ident) {
+      if (!isdigit(c)) {
+        num = false;
+        break;
+      }
+    }
+    if (num) {
+      int identnum = toInt(ident);
+      if (veridentsnum >= identnum) {
+        return true;
+      }
+    }
+    else {
+      foreach (char [] id; veridentsstr) {
+        if (id == ident) {
+          return true;
+        }
+        else if (id == "none") {
+          return false;
+        }
+      }
     }
-    char [][] statements = split(line, ";");
-    for (int i = 0; i < statements.length; i++ ) {
-      int pos = find(statements[i], "import");
-      if (pos == -1) {
-        continue;
+    return false;
+  }
+
+  void search(int a, int z) 
+  {
+    int dbgfound = -1;
+    int verfound = -1;
+    int impfound = -1;
+    int privfound = -1;
+  
+    int dbgend = -1;
+    int verend = -1;
+    int i = a;
+
+    bit moreimports = false;
+    bit keepprivate = false;
+
+    bit useDebug(int pos) 
+    {
+      int i = pos + 5;
+      int j;
+      if (i >= src.length) {
+        return false;
+      }
+      while (i < (src.length - 1) && isspace(src[i])) {
+        i++;
+      }
+      if (src[i] == '(') {
+        j = i + 1;
+        while (j < (src.length - 1) && src[j] != ')') {
+          j++;
+        }
+        char [] ident = src[i + 1..j];
+        bit num = true;
+        foreach (char c; ident) {
+          if (!isdigit(c)) {
+            num = false;
+            break;
+          }
+        }
+        if (num) {
+          int identnum = toInt(ident);
+          if (dbgidentsnum <= identnum) {
+            return true;
+          }
+        }
+        else {
+          foreach (char [] id; dbgidentsstr ~ dbgspecstrings) {
+            if (id == ident) {
+              return true;
+            }
+          }
+        }
+        if (fulldebug) {
+          return false;
+        }
       }
       else {
-        if (!base && !checkprivate) {
-          int privpos = rfind(statements[i], "private");
-          if (privpos > -1 && privpos < pos) {
-            char [] impstmt = statements[i][privpos..pos+7]; 
-            char [][] words = split(impstmt);
-            if (words.length == 2) {
-              continue;
+        if (fulldebug) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    bit isKeyword(int startpos, int length)
+    {
+      if (startpos < 0) {
+        debug writefln("- isKeyword startpos < 0.");
+        return false;
+      }
+      if (startpos + length >= src.length) {
+        return false;
+      }
+      debug writefln("- Checking keyword ", src[startpos..(startpos + length)]);
+      if (startpos == 0 || isspace(src[startpos - 1]) || 
+          src[startpos] == ';') {
+        debug writefln("- isKeyword: inside first nested if.");
+        if (((startpos + length) == src.length) || 
+             isspace(src[startpos + length]) ||
+             (src[startpos..startpos + length] == "debug" && 
+              src[startpos + length] == ':')) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    int findBlockEnd(int pos) 
+    {
+      int levels = 0;
+      debug writefln("- Finding block end after pos ", pos);
+
+      int j = pos;
+      if (pos >= src.length) {
+        return 0;
+      }
+      while (j < (src.length - 1) && isspace(src[j])) {
+        j++;
+      }
+
+      int findEnd()
+      {
+        while (isspace(src[j])) {
+          j++;
+        }     
+        if (src[j] == '{') {
+          levels++;
+          while (levels) {
+            j++;
+            if (src[j] == '{') {
+              levels++;
+            }
+            else if (src[j] == '}') {
+              levels--;
             }
           }
+          return j;
+        }
+        else {
+          return 0;
+        }
+      }
+      
+      int retval = -1;
+      if (src[j] != '(') {
+        retval = findEnd();
+        debug writefln("- Found end at pos ", retval);
+        return retval;
+      }
+      else {
+        j++;
+        while (src[j] != ')') {
+          j++;
+        }
+        j++;
+      }
+
+      retval = findEnd();
+      debug writefln("- Found end at pos ", retval);
+      return retval;
+    }
+
+    int findAttrEnd(int pos, bit priv = false)
+    {
+      int j = pos;
+      if (pos >= src.length) {
+        return 0;
+      }
+      while (j < (src.length - 1) && isspace(src[j])) {
+        j++;
+      }
+      if (src[j] == ':') {
+        while (j < (src.length - 1) && src[j] != '}') {
+          j++;
         }
-        char [] mod = strip(statements[i][pos+7..statements[i].length]);
-        if (statements[i][pos+6..pos+7] == r" ") {
-          if (!checkIfModule(mod)) {
-            continue;
+        int pub = find(src[pos..j], "public");
+        int prot = find(src[pos..j], "protected");
+        int best = -1;
+        if (isKeyword(pub, 6)) {
+          best = pub;
+        }
+        if (prot > -1 && prot < pub) {
+          if (isKeyword(prot, 9)) {
+            best = prot;
           }
         }
+        if (best > -1) {
+          return best;
+        }
         else {
-          continue;
+          return j;
+        }
+      }
+      else {
+        return 0;
+      }
+    }
+
+    int findDebugAndVersionEnd(int pos, bit ver, bit other) 
+    {
+      int findSpecEnd(int pos)
+      {
+        if (other) {
+          return 0;
+        }
+
+        int j = pos;
+        if (pos >= src.length) {
+          return 0;
+        }
+        while (j < (src.length - 1) && isspace(src[j])) {
+          j++;
+        }
+        if (src[j] == '=') {
+          int startidx = -1;
+          j++;
+          while (j < (src.length - 1) && src[j] != ';') {
+            if (startidx == -1 && isalnum(src[j])) {
+              startidx = j;
+            }
+            j++;
+          }
+          char [] ident = src[startidx..j];
+          if (ident.length > 0) {
+            bit num = isNumber(ident);
+            if (ver) {
+              if (num) {
+                try {
+                  veridentsnum = toInt(ident);
+                }
+                catch (Exception e) {
+                  // Catching top exception here due to strange naming 
+                  // conventions in Phobos. larsivi 20040724
+                  return j;
+                }
+              }
+              else {
+                verspecstrings ~= ident;
+              }
+            }
+            else {
+              if (num) {
+                try {
+                  dbgidentsnum = toInt(ident);
+                }
+                catch (Exception e) {
+                  // Catching top exception here due to strange naming 
+                  // conventions in Phobos. larsivi 20040724
+                  return j;
+                }
+              }
+              else {
+                dbgspecstrings ~= ident;
+              }
+            }
+          } 
+          return j;
+        }
+        return 0; 
+      }
+
+      int findStmntEnd(int pos)
+      {
+        int j = pos;
+        if (pos >= src.length) {
+          return 0;
+        }
+        while (j < (src.length - 1) && src[j] != ';') {
+          j++;
         }
-        char [] fp;
-        if (!runtime) {
-          if (checkPhobos(mod)) {
-            continue;
+        return j;
+      }
+
+      int i = pos;
+      int res = 0;
+
+      if (i >= src.length) {
+        return -1;
+      }
+    
+      if (other) {
+        i += 4;
+      }
+      else if (ver) {
+        i += 7;
+      }
+      else {
+        i += 5;
+      }
+   
+      if (cast(bit)(res = findSpecEnd(i))) {
+        return res;
+      }
+      else if (cast(bit)(res = findBlockEnd(i))) {
+        return res;
+      }
+      else if (cast(bit)(res = findAttrEnd(i))) {
+        return res;
+      }
+      else if (cast(bit)(res = findStmntEnd(i))) {
+        return res;
+      }
+      else {
+        return -1;
+      }
+    }
+
+    int findElse(int pos, bit ver, inout bit elseif)
+    {
+      int i = pos;
+      while (isspace(src[i++])) { }
+      if (src[i..i + 4] == "else") {
+        i += 4;
+        while (isspace(src[i++])) { }
+        if (ver) {
+          if (src[i..i + 7] == "version") {
+            elseif = true;            
           }
         }
-        fp = createFilePath(mod);
-        depth++;
-        if (depthlimit == -1 || depth <= depthlimit) {  
-          depWalk(fp, mod, false);
+        else {
+          if (src[i..i + 5] == "debug") {
+            elseif = true;
+          }
         }
-        depth--;
+        return findDebugAndVersionEnd(i, ver, true);
+      }
+      else {
+        return -1;
       }
     }
+
+    int checkDebugAndVersion(int pos, bit ver) 
+    {
+      int i = pos + (ver ? 7 : 5);
+    
+      int findElseifStart(int pos)
+      {
+        int i = pos;
+        while (isspace(src[i++])) { }
+        if (src[i..i + 4] == "else") {
+          i += 4;
+          while (isspace(src[i++])) { }
+        }
+        else {
+          return -1;
+        }
+        return i;
+      }
+
+      debug {
+        if (ver) {
+          writefln("- Checking if version identifier at ", pos, " is set.");
+        }
+        else {
+          writefln("- Checking if debug identifier at ", pos, " is set.");
+        }
+      }
+    
+      int elseend = -1;
+      int end = findDebugAndVersionEnd(pos, ver, false);
+      int found = -1;
+      bit elseif = false;
+      
+      if (end == -1) {
+        debug writefln("- No end found.");
+        return i;
+      }
+
+      elseend = findElse(end, ver, elseif);
+      debug writefln("- Value of elsend is ", elseend);
+      debug {
+        if (elseif) {
+          writefln("- Value of elseif is true");
+        }
+      }
+
+      if (ver ? useVersion(pos) : useDebug(pos)) {
+        debug writefln("- Using primary debug/version part.");
+        search(i, end);
+        while (elseif) {
+          elseend = findElse(elseend, ver, elseif);
+        }
+        if (elseend > -1) {
+          return elseend + 1;
+        }
+        else {
+          debug writefln("- Ending checkDebugAndVersion with value ", end + 1);
+          return end + 1;
+        }
+      }
+      else if (elseend > -1) {
+        while (elseif) {
+          int elseifstart = findElseifStart(end);
+          debug writefln("- Found elseif start at pos ", elseifstart);
+          if (ver ? useVersion(elseifstart) : useDebug(elseifstart)) {
+            search(elseifstart, elseend);
+            while (elseif) {
+              elseend = findElse(elseend, ver, elseif);
+            }
+            return elseend + 1;
+          }
+          end = elseifstart;
+          elseend = findElse(elseend, ver, elseif);
+        }
+        search(end + 1, elseend);
+        return elseend + 1;
+      }
+
+      debug writefln("- Version identifier not set.");
+      
+      return i + 1;
+    }
+
+    int handleDebug(int pos) 
+    {
+      return checkDebugAndVersion(pos, false);
+    }
+
+    int handleVersion(int pos)
+    {
+      return checkDebugAndVersion(pos, true);
+    }
+
+    int handleImport(int pos) 
+    {
+      bit checkPrivate(int pos)
+      {
+        foreach (int [] positions; privatearr) {
+          if (pos > positions[0] && pos < positions[1]) {
+            return true;
+          }
+        }
+        return false;
+      }
+    
+      debug writefln("- Handling import at position ", pos);
+      int endpos;
+      int i = pos + 8;
+      while (true) {
+        if (src[i] == ',') { // several imports following an 'import' keyword
+          moreimports = true;
+          break;
+        }
+        else if (src[i] == ';') { // last import in a list
+          moreimports = false;
+          break;
+        }
+        i++;
+        if (i == src.length) {
+          return i;
+        }
+      }
+      endpos = i;
+      if (!base && !checkprivate) {
+        if (pos > 7) {
+          if (keepprivate) {
+            debug writefln("- Ending due to private import");
+            return endpos + 1;
+          }
+          else if (checkPrivate(pos)) {
+            debug writefln("- Ending due to private import");
+            return endpos + 1;
+          }
+          i = pos - 1;
+          while (isspace(src[i]) && i > 7) {
+            i--;
+          }
+          if (i >= 7 && src[i - 6..i + 1] == "private") {
+            keepprivate = moreimports ? true : false;
+            debug writefln("- Ending due to private import");
+            return endpos + 1;
+          }
+        }
+      }
+      char [] mod = strip(src[pos + 6..endpos]);
+      debug writefln("- Handling import ", mod);
+      if (!checkIfModule(mod)) {
+        return endpos + 1;
+      }
+      if (!runtime) {
+        if (checkPhobos(mod)) {
+          return endpos + 1;
+        }
+      }
+      char [] fp = createFilePath(mod);
+      depth++;
+      if (depthlimit == -1 || depth <= depthlimit) {  
+        depWalk(fp, mod, false);
+      }
+      depth--;
+      debug writefln("- Ending handling import ", mod, " at pos ", endpos);
+      return endpos + 1;
+    }
+
+    int delegate(int) handler;
+    int best;
+
+    do {
+      handler = null;
+      best = z + 1;
+      uint belowz = z;
+
+      if (!checkprivate) {
+        int privstart = -1;
+        do {
+          int privend = 0;
+          debug writefln("- Searching for private from ", i, " to ", z);
+          privfound = find(src[i..z], "private");
+          if (privfound > -1) {
+            int privstart = privfound + i;
+            if (isKeyword(privstart, 7)) {
+              privend = findBlockEnd(privstart);
+              if (!privend) {
+                privend = findAttrEnd(privstart, true);
+              }
+              if (privend) {
+                privatearr[privatearr.length][0] = privstart;
+                privatearr[privatearr.length][1] = privend;
+              }
+            }
+          }
+        } while (privstart > -1);
+      }
+
+      debug writefln("- Searching for import from ", i, " to ", z); 
+      impfound = find(src[i..z], "import");
+      if (impfound > -1) {
+        impfound += i;
+        belowz = impfound;
+      }
+      if (!disabledebug) {
+        debug writefln("- Searching for debug from ", i, " to ", belowz);
+        dbgfound = find(src[i..belowz], "debug");
+        if (dbgfound > -1) {
+          dbgfound += i;
+          belowz = dbgfound < belowz ? dbgfound : belowz;
+        }
+      }
+      if (!disableversion) {
+        debug writefln("- Searching for version from ", i, " to ", belowz);
+        verfound = find(src[i..belowz], "version");
+        if (verfound > -1) {
+          verfound += i;
+        }
+      }
+
+      if (impfound > -1) {
+        debug writefln("- Value of impfound is ", impfound, " and i is ", i);
+        if (isKeyword(impfound, 6)) {
+          best = impfound;
+          debug writefln("- Import found at pos ", best);
+          handler = &handleImport;
+        }
+      }
+      if (!disabledebug) {
+        if (dbgfound > -1 && (dbgfound) < best) {
+          if (isKeyword(dbgfound, 5)) {
+            best = dbgfound;
+            debug writefln("- Debug found at pos ", best);
+            handler = &handleDebug;
+          }
+        }
+      }
+      if (!disableversion) {
+        if (verfound > -1 && (verfound) < best) {
+          if (isKeyword(verfound, 7)) {
+            best = verfound;
+            debug writefln("- Version found at pos ", best);
+            handler = &handleVersion;
+          }
+        }
+      }
+      if (!(handler is null)) {
+        i = handler(best);
+        while (moreimports) {
+          i = handler(i);
+        }
+      }
+      else {
+        break;
+      }
+    } while (i < z);
   }
+
+  int pos = 0;
+  int found = -1;
+
+  search(0, src.length);
+
+  dbgidentsstr ~= dbgspecstrings;
+  veridentsstr ~= verspecstrings;
 }
 
-/*
+/*!
  * Function that adds a dependency to the list when it is verified.
  * A path and the depth where it was found is also added. If the
  * dependency has been found before, the new depth is added to the
  * same entry.
  */
 
-bool addDep(char [] filepath, char [] mod, int depth)
+bit addDep(char [] filepath, char [] mod, int depth)
 {
   for (int i = 0; i < numdeps; i++) {
-    if (cmp(depmods[i], mod) == 0) {
+    if (depmods[i] == mod) {
       depdepths[i] ~= ",";
       depdepths[i] ~= toString(depth);
       return false;
@@ -306,14 +1038,14 @@
     depfiles.length = alldeps;
     depdepths.length = alldeps;
   }
-  depmods[numdeps-1] = mod;
-  depfiles[numdeps-1] = filepath;
-  depdepths[numdeps-1] = toString(depth);
+  depmods[numdeps - 1] = mod;
+  depfiles[numdeps - 1] = filepath;
+  depdepths[numdeps - 1] = toString(depth);
 
   return true;
 }
 
-/*
+/*!
  * Function that adds the filename of the current checked file to
  * the printout.
  */
@@ -334,50 +1066,58 @@
   depdepths[numdeps-3] = depdepths[numdeps-2] = depdepths[numdeps-1] = "";
 }
 
-/*
+/*!
  * Function that takes a module name and creates a real path.
  */
  
 char [] createFilePath(char [] mod)
 {
-  char [] tempmode;
-  tempmode = replace(mod, ".", sep);
-  tempmode ~= ".d";
-  return tempmode;
+  char [] tempmod;
+  tempmod = replace(mod, ".", sep);
+  tempmod ~= ".d";
+  return tempmod;
 }
 
-/*
+/*!
  * Checks if the found dependency is a part of phobos in which case
  * it is ignored.
  */
 
-bool checkPhobos(char [] mod)
+bit checkPhobos(char [] mod)
 {
-  if (cmp(mod, "Object") == 0) return true;
-  else if (cmp(mod[0..4], "std.") == 0) return true;
-  else return false;
+  if (mod == "Object") {
+    return true;
+  }
+  else if (mod.length < 4) {
+    return false;
+  }
+  else if (cmp(mod[0..4], "std.") == 0) {
+    return true;
+  }
+  else {
+    return false;
+  }
 }
 
-/*
+/*!
  * Checks if the found module really can be a module since the parsing
  * is a bit hackish.
  */
 
-bool checkIfModule(char [] mod)
+bit checkIfModule(char [] mod)
 {
-  char [] illchars = ")([]/,+?";
-  if (find(letters, mod[0]) == -1) {
+  if (!isalpha(mod[0])) {
     return false;
   }
-  for (int i = 1; i < mod.length; i++) {
-    if (find(illchars, mod[i]) > -1) {
+  foreach (char c; mod[1..mod.length]) {
+    if (!(isalnum(c) || c == '.')) {
       return false;
     }
   }
   return true;
 }
 
-/*
+/*!
  * Adds a path given with "-I" to the path list.
  */
 
@@ -391,18 +1131,18 @@
   paths[numpaths - 1] = path;
 }
 
-/*
+/*!
  * Checks if a file exist.
  */
 
-bool fileExist(char [] file)
+bit fileExist(char [] file)
 {
 version (Win32) {
   return (GetFileAttributesA(toStringz(file)) != 0xFFFFFFFF);
 }
 version (Linux) {
   // FIXME: I guess there is a better way to do this. larsivi 18042004
-  bool result = true;
+  bit result = true;
   try {
     read(file);
   }
@@ -413,56 +1153,103 @@
 }
 }
 
-/*
- * Strip of the comments.
- * Returns true if the whole line is a comment.
+/*!
+ * Checks if the string is a number. Returns true if it is.
  */
 
-bool stripComment(inout char[] line)
+bit isNumber(char [] ident)
 {
-  int res = -1;
-  bool startascomment = comment;
-
-  void toWhiteSpace(inout char[] line, int start, int stop)
-  {   
-    for (int i = start; i < stop; i++) {
-      line[i] = ' ';
+  foreach (char c; ident) {
+    if (!isdigit(c)) {
+      return false;
     }
   }
+  return true;
+}
 
-  void endStarComment(inout char[] line)
-  {
-    if (comment) {
-      res = find(line, "*/");
-      if (res > -1) {
-        comment = false;
-        toWhiteSpace(line, 0, res);
-      }
-    }
-  }
 
-  endStarComment(line);
+/*!
+ * Convert a substring in src to whitespace.
+ */
 
-  res = find(line, "//");
-  if (res > - 1) {
-    toWhiteSpace(line, res, line.length);
-    if (res < 1) {
-      return false;
-    }
-  }
+void toWhiteSpace(inout char [] src, int start, int end)
+in {
+  assert (end > start);
+  assert (start >= 0);
+  assert (end <= src.length);
+}
+body {
+  src[start..end] = ' ';
+}
 
-  res = find(line, "/*");
-  if (res > -1) {
-    comment = true;
-    toWhiteSpace(line, res, line.length);
-  }
+/*!
+ * Strip off the comments.
+ */
 
-  endStarComment(line);
+void stripComment(inout char[] src)
+{
+  int len = src.length;
+  int doubleslash = -1;
+  int star = -1;
+  int plus = 0;
+  int plusstart = -1;
+  
+  for (int i = 0; i < len; i++) {
+    if (doubleslash > -1) {
+      if (src[i] == '\\') {
+        if (src[i + 1] == 'n') {
+          toWhiteSpace(src, doubleslash, i + 2);
+          i++;
+          doubleslash = -1;
+          continue;
+        }
+      }
+      continue;
+    }
+    else if (star > -1) {
+      if (src[i] == '*') {
+        if (src[i + 1] == '/') {
+          toWhiteSpace(src, star, i + 2);
+          i++;
+          star = -1;
+          continue;
+        }
+      }
+      continue;
+    }
+    else if (plus) {
+      if (src[i] == '+') {
+        if (src[i + 1] == '/') {
+          i++;
+          plus--;
+          if (!plus) {
+            toWhiteSpace(src, plusstart, i + 1);
+            plusstart = -1;
+          }
+          continue;
+        }
+      }
+    }
 
-  return startascomment && comment;
+    if (src[i] == '/') {
+      i++;
+      if (src[i] == '/') {
+        doubleslash = i - 1;
+      }
+      else if (src[i] == '*') {
+        star = i - 1;
+      }
+      else if (src[i] == '+') {
+        if (!plus) {
+          plusstart = i - 1;
+        }
+        plus++;
+      }
+    }
+  }
 }
 
-/*
+/*!
  * Writes dependencies to file.
  */
 
@@ -475,7 +1262,7 @@
   depfile.close();
 }
 
-/*
+/*!
  * Prints dependencies to stdout.
  */
 
@@ -489,19 +1276,18 @@
     version (linux) {
       objsuf = ".o";
     }
-    printf(toStringz(replace(argslist[firstfile], ".d", objsuf) ~ " : "));
-    printf(toStringz(argslist[firstfile]));
+    writef(replace(argslist[firstfile], ".d", objsuf), " : ");
+    writef(argslist[firstfile]);
     if (numdeps > 3) {
-      printf(toStringz(" "));
+      writef(" ");
       for (int i = 3; i < numdeps; i++) {
-        printf(toStringz(depfiles[i] ~ " "));
+        writef(depfiles[i], " ");
       }
     }
   }
   else {
     for (int i = 0; i < numdeps; i++) {
-      printf(toStringz(depmods[i] ~ " " ~ depfiles[i] ~ " " ~ 
-             depdepths[i] ~ "\n"));
+      writefln(depmods[i], " ", depfiles[i], " ", depdepths[i]);
     }
   }
 }
@@ -526,12 +1312,18 @@
   if (curopt < args.length) {
     firstfile = curopt;
     for (int i = curopt; i < args.length; i++) {
+      // FIXME: Handle multiple input files better
+      // larsivi 20040715
       depBase(i);
     }
   }
 
-  if (write) printToFile();
-  else printToStdout(); 
+  if (write) {
+    printToFile();
+  }
+  else {
+    printToStdout();
+  }
 
   return 0;
 }
dmd.diff (text/plain, 4.2 KB)
Index: dmd.py
===================================================================
RCS file: /cvsroot/a-a-p/Exec/tools/dmd.py,v
retrieving revision 1.11
diff -u -r1.11 dmd.py
--- dmd.py	26 Aug 2004 15:29:36 -0000	1.11
+++ dmd.py	21 Oct 2004 15:59:33 -0000
@@ -51,6 +51,11 @@
         outtypes = ["object", "libobject", "dllobject"],
         intypes = ["d"])
 
+    define_action("compile_dmd", 0, """
+        DLINKFLAGS += source
+        """,
+        intypes = ["def"])
+
     # Build a program from object files
     define_action("build_dmd", 0, """
         DLINKFLAGS += /DELEXECUTABLE
@@ -81,22 +86,29 @@
     # Build a dll from object files  
     define_action("builddll_dmd", 0, """
         DLINKFLAGS += /DELEXECUTABLE
-        @exec "import tools.dmd"
         @if os.name == "nt":
             DIMPLIB ?= 
-            @if DIMPLIB and DIMPLIB == "yes":
+            @exec "import tools.dmd"
+            @if _no.DIMPLIB and _no.DIMPLIB == "yes":
                 DLINKFLAGS += /implib
-        @if not tools.dmd.find_dll_main_object(source):
-            @f = file("aap_dllmain.d", 'w')
-            @f.write(tools.dmd.dll_main_source())
-            @f.close()
-            :do compile {target = aap_dllmain.obj} aap_dllmain.d
-            source += aap_dllmain.obj
+            @if not tools.dmd.find_dll_main_object(source):
+                @f = file("aap_dllmain.d", 'w')
+                @f.write(tools.dmd.dll_main_source())
+                @f.close()
+                :do compile {target = aap_dllmain.obj} aap_dllmain.d
+                source += aap_dllmain.obj
+            @if not tools.dmd.find_def_file(source):
+                @f = file("aap_dll.def", 'w')
+                @f.write(tools.dmd.dll_def_file(target))
+                @f.close()
+                source += aap_dll.def
         :sys $DMD -L$*?DLINKFLAGS -L+$*?LIBS -of$target $source
-        :del {f} {q} aap_dllmain.*
+        @if os.name == "nt":
+            :del {f} {q} aap_dllmain.*
+            :del {f} {q} aap_dll.def
         """,
         outtypes = ["default"],
-        intypes = ["dllobject"])
+        intypes = ["dllobject", "def"])
 
     # Build a program directly from source
     define_action("buildonestep_dmd", 0, """ 
@@ -149,19 +161,26 @@
             DIMPLIB ?= 
             @if DIMPLIB and DIMPLIB == "yes":
                 DLINKFLAGS += -L/implib
-        @exec "import tools.dmd"
-        @if not tools.dmd.find_dll_main_source(source):
-            @f = file("aap_dllmain.d", 'w')
-            @f.write(tools.dmd.dll_main_source())
-            @f.close()
-            source += aap_dllmain.d
+            @exec "import tools.dmd"
+            @if not tools.dmd.find_dll_main_source(source):
+                @f = file("aap_dllmain.d", 'w')
+                @f.write(tools.dmd.dll_main_source())
+                @f.close()
+                source += aap_dllmain.d
+            @if not tools.dmd.find_def_file(source):
+                @f = file("aap_dll.def", 'w')
+                @f.write(tools.dmd.dll_def_file(target))
+                @f.close()
+                source += aap_dll.def
         :sys $DMD $?DFLAGS $?DVERSION $opt $dbg $?DDEBUG $?DIMPORT
                 -L$*?DLINKFLAGS -L+$*?LIBS -of$target $source
-        :del {f} {q} aap_dllmain.d
+        @if os.name == "nt":
+            :del {f} {q} aap_dllmain.d
+            :del {f} {q} aap_dll.def
         :del {q} *.obj
         """,
         outtypes = ["default"],
-        intypes = ["d"])
+        intypes = ["d", "def"])
         
     if not rd["_top"].get("DMD"):
         rd["_top"]["DMD"] = "dmd"
@@ -206,6 +225,15 @@
 
     return None 
 
+def find_def_file(sourcestr):
+    print sourcestr
+    for si in var2list(sourcestr):
+        from string import find
+        if (find(si, ".def") > -1):
+            return 1
+
+    return None
+
 def dll_main_source():
     source = """
         import std.c.windows.windows;
@@ -248,4 +276,16 @@
         """
     return source
 
+def dll_def_file(target):
+    from string import find
+    idx = find(target, ".dll")
+    source = "LIBRARY \"" + target[0:idx+4] + "\""
+    source = source + """
+EXETYPE NT
+SUBSYSTEM WINDOWS
+CODE SHARED EXECUTE
+DATA WRITE
+        """
+    return source
+
 # vim: set sw=4 et sts=4 tw=79 fo+=l: