Index: src/util.cpp
===================================================================
--- src/util.cpp	(revision 780)
+++ src/util.cpp	(working copy)
@@ -28,6 +28,8 @@
 #include <qdir.h>
 #include <qdatetime.h>
 #include <qcache.h>
+#include <qlist.h>
+#include <qmap.h>
 
 #include "util.h"
 #include "message.h"
@@ -80,6 +82,20 @@
 
 #define REL_PATH_TO_ROOT "../../"
 
+/* Prototypes ... TODO: move to header file */
+static bool matchPrototypeDefinition(MemberName *mn,
+   		                             FileDef *fd,
+                                     QList<MemberDef> *members,
+                                     QList<MemberDef> *membersPrototype,
+                                     MemberDef **md,
+                                     bool debug);
+static bool followIncludeFileList(QCString findName,int level,  QList<IncludeInfo> *includeFileList, bool debug);
+static bool followIncludedByFileList(QCString findName, int level,  QList<IncludeInfo> *includedByFileList, bool debug);
+
+static QMap<QCString, QCString> includeMap;    /* map include->function */
+static QMap<QCString, QCString> includedByMap; /* map includedBy->function */
+
+
 //------------------------------------------------------------------------
 // TextGeneratorOLImpl implementation
 //------------------------------------------------------------------------
@@ -3714,7 +3730,7 @@
     FileDef *currentFile,
     bool checkCV
     )
-{
+{ bool debug=false;
   fd=0, md=0, cd=0, nd=0, gd=0;
   if (memberName.isEmpty()) return FALSE; /* empty name => nothing to link */
 
@@ -4020,6 +4036,8 @@
     //else // no scope => global function
     {
       QList<MemberDef> members;
+      QList<MemberDef> membersPrototype;
+      QList<MemberDef> membersCode;
       // search for matches with strict static checking
       findMembersWithSpecificName(mn,args,TRUE,currentFile,checkCV,members);
       if (members.count()==0) // nothing found
@@ -4027,22 +4045,44 @@
         // search again without strict static checking
         findMembersWithSpecificName(mn,args,FALSE,currentFile,checkCV,members);
       }
+      if(debug)
+      printf("--- *** util.cpp getDefs Found member %s count %i \n",mn->last()->name().data(),members.count());
+
+  	  bool goodMatch=false;
       if (members.count()!=1 && args && !strcmp(args,"()"))
       {
         // no exact match found, but if args="()" an arbitrary 
         // member will do
         md=mn->last();
-        while (md /* && md->isLinkable()*/)
+        while (md /* && md->isLinkable()*/ &&!goodMatch)
         {
           //printf("Found member `%s'\n",md->name().data());
           //printf("member is linkable md->name()=`%s'\n",md->name().data());
           fd=md->getFileDef();
           gd=md->getGroupDef();
+
+          if (debug)
+          {
+        	printf("--- *** util.cpp getDefs Found member %s ",md->name().data());
+            printf("isPrototype %d ",md->isPrototype());
+            printf("fd=%p gd=%p (gd && gd->isLinkable())=%d (fd && fd->isLinkable())=%d ",fd,gd,(gd && gd->isLinkable()),(fd && fd->isLinkable()));
+            printf("file=%s\n",(fd?fd->localName().data():"(na)"));
+          }
           if (
               (gd && gd->isLinkable()) || (fd && fd->isLinkable()) 
              )
           {
             members.append(md);
+
+            if( currentFile
+             && fd
+             && currentFile->getPath()==fd->getPath()
+             && currentFile->localName()==fd->localName())
+            	 goodMatch=true;  /* match found within same file as currentFile */
+
+            /* splitting members acording to type */
+            if( md->isPrototype()) membersPrototype.append(md);
+            else membersCode.append(md);
           }
           md=mn->prev();
         }
@@ -4050,13 +4090,24 @@
       //printf("found %d candidate members\n",members.count());
       if (members.count()>0) // at least one match
       {
-        md=members.last();
+       	     if(goodMatch)                  md=members.last();         /* use one from same file                 */
+    	else if(members.count()==1)         md=members.last();         /* there is just one match, use it!       */
+    	else if (matchPrototypeDefinition(mn,currentFile,&membersCode,&membersPrototype,&md,debug))
+    	     { if (debug) printf("--- --*+util.cpp Matched via prototype ... we did it .... !!!!! \n"); }
+        else /* zero or more than one pragma export found, use last in list */
+        {   md=members.last();  /* best effort use last in matched members */
+        }
       }
       if (md) // found a matching global member
       {
         fd=md->getFileDef();
         gd=md->getGroupDef();
         //printf("fd=%p gd=%p gd->isLinkable()=%d\n",fd,gd,gd->isLinkable());
+        if (debug) printf("--- --c util.cpp getDefs returns TRUE. goodMatch %d, FileDef = %s, GroupDef = %s, CurrentFile=%s \n"
+        		          ,goodMatch
+        		          ,(fd?fd->localName().data():"(na)")
+        		          ,(gd?gd->localName().data():"(na)")
+        		          ,(currentFile?currentFile->localName().data():"(na)"));
         if (gd && gd->isLinkable()) fd=0; else gd=0;
         return TRUE;
       }
@@ -4067,6 +4118,171 @@
   return FALSE;
 }
 
+static bool matchPrototypeDefinition(MemberName *mn,
+		                             FileDef *fd,
+                                     QList<MemberDef> *members,
+                                     QList<MemberDef> *membersPrototype,
+                                     MemberDef **mdOut,
+                                     bool debug=FALSE)
+{
+	/*
+	 * match the prototype definition with the include file list for fd.
+	 *
+	 *   mn is member name to search for
+	 *   fd is the file definition to link with a member.
+	 *   members contains all definitions of the name.
+	 *   membersPrototype contains all prototypes for the name.
+	 *
+	 * Here is the plan.
+	 *   1) pair the member definition with their prototype
+	 *   2) if fd->includeFileList matches any of 1)->includedByFileList then thats the match
+	 *   3) else dunno
+	 *
+	 */
+    MemberDef *mdImpl;
+    MemberDef *mdProto;
+    int i;
+
+    if(fd==0) return false; /* cannot match with unknown name */
+
+    if (debug)
+      printf("--- --* util.cpp matchPrototypeDefinition: Membername %s, Filename %s, Number of Members %i, Number of prototypes %i \n"
+    		, mn->memberName()
+    		, (fd?fd->localName().data():"(na)")
+    		, members->count()
+    		, membersPrototype->count()
+    		);
+
+       if(fd)
+       { if (debug)
+    	 { printf("--- --* util.cpp     filename %s \n",fd->localName().data());
+           followIncludeFileList("-ALL-",1,fd->includeFileList(),debug);
+    	 }
+       }
+
+      bool protoMatch=false;
+      bool implMatch=false;
+
+
+      /* Look for prototype the is included by fd */
+      if (debug) printf("--- --* util.cpp matchPrototypeDefinition: content of membersPrototype (%i)\n",membersPrototype->count());
+      if(membersPrototype->count()>0)
+      {
+      QListIterator<MemberDef> mdpi(*(membersPrototype));
+      for (i=0,mdpi.toFirst();(!protoMatch)&&(mdProto=mdpi.current());++mdpi,i++)
+      {  if(mdProto->getFileDef())
+         {  if (debug) printf("--- --* util.cpp     [%i] filename %s \n",i,mdProto->getFileDef()->localName().data());
+	        protoMatch=followIncludedByFileList(fd->localName(),1,mdProto->getFileDef()->includedByFileList(),debug);
+         }
+      }
+
+      /* mdProto now contains the prototype that are used by the current file */
+
+      }
+
+      if (protoMatch==false) { if(debug) printf("--- --* util.cpp matchPrototypeDefinition: No prototype found \n"); return false; }
+
+      /* now look for the file implementing the prototype */
+      if (debug) printf("--- --* util.cpp matchPrototypeDefinition: content of members (%i)\n",members->count());
+      if(members->count()>0)
+      {
+      QListIterator<MemberDef> mdi(*(members));
+      for (i=0,mdi.toFirst();(!implMatch)&&(mdImpl=mdi.current());++mdi,i++)
+      {  if(mdImpl->getFileDef())
+    	 { if (debug) printf("--- --* util.cpp     [%i] filename %s \n",i,mdImpl->getFileDef()->localName().data());
+    	   implMatch=followIncludeFileList(mdProto->getFileDef()->localName(),1,mdImpl->getFileDef()->includeFileList(),debug);
+    	 }
+      }
+
+      if (implMatch)
+      { *mdOut=mdImpl;
+         if (debug)
+    	   printf("--- --* util.cpp matchPrototypeDefinition: Membername %s, Filename %s. Found prototype %s. Found implementation %s \n"
+         		, mn->memberName()
+          		, (fd?fd->localName().data():"(na)")
+           		, mdProto->getFileDef()->localName().data()
+           		, mdImpl->getFileDef()->localName().data()
+           		);
+
+        return true;
+      }
+      else
+    	  printf("--- --* util.cpp matchPrototypeDefinition: Membername %s, Filename %s. Found prototype %s. Implementation Not Found \n" /* TODO: warning */
+           		, mn->memberName()
+            	, (fd?fd->localName().data():"(na)")
+             	, mdProto->getFileDef()->localName().data()
+             	);
+
+
+
+      }
+	return false;
+}
+
+
+/*!
+ * Follow list of included files until the findName is found.
+ * The names are tracked in the QMap includeMap
+ */
+
+
+static bool followIncludeFileList(QCString findName,int level,  QList<IncludeInfo> *includeFileList, bool debug)
+{   QCString pad="+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
+    if (level>15) { if(debug) printf(" ... followIncludeFileList exhausted at %i \n",level); return false; }
+    if (includeFileList==0) return false;
+    if (includeFileList->isEmpty()) return false;
+    if (level==1) includeMap.clear();
+
+    bool match=false;
+
+    int i;
+    QListIterator<IncludeInfo> fdiii(*(includeFileList));
+    IncludeInfo *ii;
+    for (i=0,fdiii.toFirst();(!match)&&(ii=fdiii.current());++fdiii,i++) // foreach #include...
+    { if(debug) printf("--- --* util.cpp     %s[%i] include name %s \n",pad.left(level*3).data(),  i,ii->includeName.data());
+
+
+      if(findName==ii->includeName.right(findName.length())) return true;
+
+      if(ii->fileDef&&includeMap[ii->includeName].isNull())
+      {
+    	includeMap[ii->includeName]=findName;
+    	match=followIncludeFileList(findName,level+1,ii->fileDef->includeFileList(),debug);
+      }
+
+
+    }
+    return match;
+}
+
+/*!
+ * Follow list if included by files until findName is found
+ * The names are tracked in the QMap includedByMap
+ */
+static bool followIncludedByFileList(QCString findName, int level,  QList<IncludeInfo> *includedByFileList, bool debug)
+{   QCString pad="+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
+    if (level>15) { if(debug) printf(" ... followIncludedByFileList exhausted at %i \n",level); return false; }
+    if (includedByFileList==0) return false;
+    if (includedByFileList->isEmpty()) return false;
+    if (level==1) includedByMap.clear();
+
+
+    bool match=false;
+
+    int i;
+    QListIterator<IncludeInfo> fdiii(*(includedByFileList));
+    IncludeInfo *ii;
+    for (i=0,fdiii.toFirst();(!match)&&(ii=fdiii.current());++fdiii,i++) // foreach #include...
+    { if(debug) printf("--- --* util.cpp     %s[%i] included by name %s \n",pad.left(level*3).data(),  i,ii->includeName.data());
+      if(findName==ii->includeName.right(findName.length())) return true;
+      if(ii->fileDef&&includedByMap[ii->includeName].isNull())
+      { includedByMap[ii->includeName]=findName;
+        match=followIncludedByFileList(findName,level+1,ii->fileDef->includedByFileList(),debug);
+      }
+    }
+    return match;
+}
+
 /*!
  * Searches for a scope definition given its name as a string via parameter
  * `scope'. 
