Index: search.c
===================================================================
--- search.c	(Revision 2879)
+++ search.c	(Arbeitskopie)
@@ -8,6 +8,9 @@
  * are clearly marked.
  *
  * ALL WARRANTIES ARE HEREBY DISCLAIMED.
+ * 
+ * Modifications:
+ * - D support (search for "D support")
  */
 #include "jam.h"
 #include "hash.h"
@@ -39,6 +42,12 @@
 	char buf3[MAXJPATH];
 	int system = (_header[0] == '<');
 	LIST *list = searchdirs->next;
+	
+	//D support
+	int dMode=0;
+	int fnlen=strlen(source);
+	if(source[fnlen-2]=='.' && source[fnlen-1]=='d')
+		dMode=1;
 
 	/* <foo.h> --> foo.h */
 	strcpy(header, _header + 1);
@@ -131,33 +140,37 @@
 			return newstr(buf);
 	}
 
-#if 1
+	if(!dMode)
+	{
 #ifdef SEARCH_OPTIM
-	// remember that this file could not be found
-	{
-		char key[MAXJPATH] = "";
-		SEARCH search, *s = &search;
-		if (!system)
+		// remember that this file could not be found
 		{
-			strcpy(key, buf3);
-			strcat(key, ",");
+			char key[MAXJPATH] = "";
+			SEARCH search, *s = &search;
+			if (!system)
+			{
+				strcpy(key, buf3);
+				strcat(key, ",");
+			}
+			strcat(key, _header);
+			s->key = newstr(key);
+			s->time = 0;
+			s->path = NULL;
+			(void) hashenter(searchhash, (HASHDATA **)&s);
 		}
-		strcat(key, _header);
-		s->key = newstr(key);
-		s->time = 0;
-		s->path = NULL;
-		(void) hashenter(searchhash, (HASHDATA **)&s);
-	}
 #endif
 
-	/* C compilers do *not* look in the current directory for #include files */
-	*time = 0;
-	return NULL;
-#else
-	f->f_root.ptr = 0;
-	f->f_root.len = 0;
+		/* C compilers do *not* look in the current directory for #include files */
+		*time = 0;
+		return NULL;
+	}
+	//D support (look in current directory)
+	else
+	{
+		f->f_root.ptr = 0;
+		f->f_root.len = 0;
 
-	path_build( f, buf, 1 );
+		path_build( f, buf, 1 );
 
 {
 PATHSPLIT f;
@@ -168,13 +181,54 @@
 strcpy(buf, buf2);
 }
 
-	if( DEBUG_SEARCH )
-	    printf( "search %s: %s\n", _header, buf );
+		if( DEBUG_SEARCH )
+			printf( "search %s: %s\n", _header, buf );
 
-	timestamp( buf, time );
+		timestamp( buf, time );
 
-	return newstr( buf );
+
+#ifdef SEARCH_OPTIM
+		if (*time)
+		{
+			char key[MAXJPATH] = "";
+			SEARCH search, *s = &search;
+			if (!system)
+			{
+				strcpy(key, buf3);
+				strcat(key, ",");
+			}
+			strcat(key, _header);
+			s->key = newstr(key);
+			s->time = *time;
+			s->path = newstr(buf);
+			(void) hashenter(searchhash, (HASHDATA **)&s);
+		}
 #endif
+
+		if (*time)
+			return newstr(buf);
+		
+#ifdef SEARCH_OPTIM
+		// remember that this file could not be found
+		{
+			char key[MAXJPATH] = "";
+			SEARCH search, *s = &search;
+			if (!system)
+			{
+				strcpy(key, buf3);
+				strcat(key, ",");
+			}
+			strcat(key, _header);
+			s->key = newstr(key);
+			s->time = 0;
+			s->path = NULL;
+			(void) hashenter(searchhash, (HASHDATA **)&s);
+		}
+#endif
+
+		*time = 0;
+		return NULL;
+	}
 }
 
 void search_adddir(const char *path)
Index: headers.c
===================================================================
--- headers.c	(Revision 2879)
+++ headers.c	(Arbeitskopie)
@@ -8,6 +8,12 @@
  * are clearly marked.
  *
  * ALL WARRANTIES ARE HEREBY DISCLAIMED.
+ * 
+ * Modifications:
+ * - D support (search for "D support")
+ * - Depth level counting (needed for D support)
+ * - Simple optimization by avoiding regexec most of the time
+ * - Special cache keys for source files (needed for D support)
  */
 #include "jam.h"
 #include "alloc.h"
@@ -25,13 +31,26 @@
 
 struct hash *headerhash = 0;
 static regexp *hdrre = 0;
+//D support
+static regexp *dimpre = 0;
 
-LIST *headers1(const char *file)
+LIST *headers1(const char *file, int depth)
 {
 	FILE *f;
 	regexp *re;
 	LIST *result = 0;
 	char buf[1024];
+	int fnlen=strlen(file);
+	
+	//D support
+	int dMode=0;
+	int dState=0;
+	if(file[fnlen-2] == '.' && file[fnlen-1] == 'd')
+	{
+		dMode=1;
+		if( DEBUG_HEADER )
+			printf("D file detected\n");
+	}
 
 	if (!(f = fopen(file, "r")))
 		return result;
@@ -42,21 +61,91 @@
 	if (!hdrre)
 		hdrre = my_regcomp("^[ 	]*#[ 	]*include[ 	]*([<\"])([^\">]*)([\">]).*$");
 	re = hdrre;
-
+	
+	//D support
+	if(dMode)
+	{
+		if(!dimpre)
+			dimpre = my_regcomp(
+				"^.*import[ \t]*([[A-Za-z_ \t]+=[ \t]*)?([A-Za-z_\\.]+)(\\:.+)?;.*$");
+		re = dimpre;
+	}
+	
 	while (fgets(buf, sizeof(buf), f))
 	{
-		if (my_regexec(re, buf) && re->startp[3])
+		//D support
+		if(dMode)
 		{
-			char buf2[MAXSYM];
+			if(dState == 0)
+			{
+				if(strstr(buf, "public"))
+					dState=1;
+			}
+			if(dState >= 1)
+			{
+				if(strchr(buf, '{'))
+					++dState;
+				if(strchr(buf, '}'))
+					--dState;
+			}
+		}
+		
+		//Simple reduction of regex overhead
+		if(strstr(buf, dMode ? "import" : "include"))
+			if (my_regexec(re, buf))
+			{
+				char buf2[MAXSYM];
 
-			//FIXME: don't add duplicate headers
-			int l = re->endp[3] - re->startp[1];
-			memcpy(buf2, re->startp[1], l);
-			buf2[l] = '\0';
-			result = list_new(result, buf2, 0);
+				//FIXME: don't add duplicate headers
+				if(!dMode && re->startp[3])
+				{
+					int l = re->endp[3] - re->startp[1];
+					memcpy(buf2, re->startp[1], l);
+					buf2[l] = '\0';
+				}
+				//D support
+				else if(re->startp[2])
+				{
+					if(depth > 0)
+					{
+						//private import?
+						if(dState == 0)
+							continue;
+					}
+					
+					buf2[0] = '<';
+					const char* p;
+					int j = 0;
+					for(p = re->startp[2];p < re->endp[2];++p)
+					{
+						char c=*p;
+						++j;
+						if(c == '.')
+							buf2[j] = '/';
+						else buf2[j] = c;
+					}
+					buf2[++j]='.';
+					buf2[++j]='d';
+					buf2[++j]='>';
+					buf2[++j] = '\0';
+				}
+				result = list_new(result, buf2, 0);
 
-			if (DEBUG_HEADER)
-				printf("header found: %s\n", buf2);
+				if (DEBUG_HEADER)
+					printf("header found: %s\n", buf2);
+			}
+		
+		//D support
+		if(dMode)
+		{
+			if(dState == 1)
+			{
+				if(strchr(buf, ';'))
+					dState=0;
+				
+				if(strchr(buf, '}'))
+					dState=0;
+			}
 		}
 	}
 
@@ -90,15 +179,24 @@
 	return chain;
 }
 
-HEADER *headers(const char *t, time_t time)
+HEADER *headersDepth(const char *t, time_t time, int depth)
 {
 	HEADER hdr, *h = &hdr;
 	LIST *l;
+	const char* cachekey=t;
 
+	//D support (doesn't affect C(++), because a source file is never included)
+	if(depth == 0)
+	{
+		cachekey=malloc(strlen(t)+sizeof("source:"));
+		strcpy((char*)cachekey,"source:");
+		strcpy((char*)cachekey+7,t);
+	}
+	
 	if (!headerhash)
 		headerhash = hashinit(sizeof(HEADER), "headers");
 
-	h->key = t;
+	h->key = cachekey;
 	h->includes = 0;
 	h->time = time;
 	h->headers = 0;
@@ -108,27 +206,34 @@
 
 	h->key = newstr(t);
 #ifdef USE_CACHE
-	if (!cache_check(t, time, &h->includes))
+	if (!cache_check(cachekey, time, &h->includes))
 	{
-		h->includes = headers1(t);
-		cache_enter(t, time, h->includes);
+		h->includes = headers1(t, depth);
+		cache_enter(cachekey, time, h->includes);
 	}
 #else
-	h->includes = headers1(t);
+	h->includes = headers1(t, depth);
 #endif
+	if(depth == 0)
+		free((char*)cachekey);
 
 	l = h->includes;
 	while (l)
 	{
 		const char *t2 = search(t, l->string, &time);
 		if (time)
-			h->headers = headerentry(h->headers, headers(t2, time));
+			h->headers = headerentry(h->headers, headersDepth(t2, time, depth+1));
 		l = list_next(l);
 	}
 
 	return h;
 }
 
+HEADER *headers(const char *t, time_t time)
+{
+	return headersDepth(t, time, 0);
+}
+
 void headernewest(HEADER *h)
 {
 	HEADERS *hs = h->headers;
@@ -149,6 +254,9 @@
 {
 	my_redone(hdrre);
 	hdrre = 0;
+	//D support
+	my_redone(dimpre);
+	dimpre = 0;
 	hashdone(headerhash);
 	headerhash = 0;
 	alloc_free(hdralloc);
