浏览代码

* patch from Pavel with a new and much faster DLL Scanner for
automatic importing so $linklib works for DLLs. Thanks Pavel!

peter 24 年之前
父节点
当前提交
aab27143a3
共有 7 个文件被更改,包括 419 次插入153 次删除
  1. 39 2
      compiler/fmodule.pas
  2. 18 1
      compiler/import.pas
  3. 12 2
      compiler/pdecsub.pas
  4. 8 1
      compiler/pdecvar.pas
  5. 47 8
      compiler/pmodules.pas
  6. 40 17
      compiler/systems.pas
  7. 255 122
      compiler/targets/t_win32.pas

+ 39 - 2
compiler/fmodule.pas

@@ -52,6 +52,14 @@ interface
          rr_asmolder,rr_crcchanged
          rr_asmolder,rr_crcchanged
        );
        );
 
 
+       TExternalsItem=class(TLinkedListItem)
+       public
+         found : longbool;
+         data  : pstring;
+         constructor Create(const s:string);
+         Destructor Destroy;override;
+       end;
+
        tlinkcontaineritem=class(tlinkedlistitem)
        tlinkcontaineritem=class(tlinkedlistitem)
        public
        public
           data : pstring;
           data : pstring;
@@ -105,7 +113,7 @@ interface
           uses_imports  : boolean;  { Set if the module imports from DLL's.}
           uses_imports  : boolean;  { Set if the module imports from DLL's.}
           imports       : tlinkedlist;
           imports       : tlinkedlist;
           _exports      : tlinkedlist;
           _exports      : tlinkedlist;
-
+          externals     : tlinkedlist; {Only for DLL scanners by using Unix-style $LINKLIB }
           resourcefiles : tstringlist;
           resourcefiles : tstringlist;
 
 
           linkunitofiles,
           linkunitofiles,
@@ -286,6 +294,25 @@ uses
       end;
       end;
 
 
 
 
+{****************************************************************************
+                              TExternalsItem
+ ****************************************************************************}
+
+    constructor tExternalsItem.Create(const s:string);
+      begin
+        inherited Create;
+        found:=false;
+        data:=stringdup(s);
+      end;
+      
+      
+    destructor tExternalsItem.Destroy;
+      begin
+        stringdispose(data);
+        inherited;
+      end;
+
+
 {****************************************************************************
 {****************************************************************************
                                   TMODULE
                                   TMODULE
  ****************************************************************************}
  ****************************************************************************}
@@ -614,6 +641,8 @@ uses
         imports:=tlinkedlist.create;
         imports:=tlinkedlist.create;
         _exports.free;
         _exports.free;
         _exports:=tlinkedlist.create;
         _exports:=tlinkedlist.create;
+        externals.free;
+        externals:=tlinkedlist.create;
         used_units.free;
         used_units.free;
         used_units:=TLinkedList.Create;
         used_units:=TLinkedList.Create;
         { all units that depend on this one must be recompiled ! }
         { all units that depend on this one must be recompiled ! }
@@ -745,6 +774,7 @@ uses
         uses_imports:=false;
         uses_imports:=false;
         imports:=TLinkedList.Create;
         imports:=TLinkedList.Create;
         _exports:=TLinkedList.Create;
         _exports:=TLinkedList.Create;
+        externals:=TLinkedList.Create;
       { search the PPU file if it is an unit }
       { search the PPU file if it is an unit }
         if is_unit then
         if is_unit then
          begin
          begin
@@ -776,6 +806,9 @@ uses
         if assigned(_exports) then
         if assigned(_exports) then
          _exports.free;
          _exports.free;
         _exports:=nil;
         _exports:=nil;
+        if assigned(externals) then
+         externals.free;
+        externals:=nil;
         if assigned(scanner) then
         if assigned(scanner) then
           pscannerfile(scanner)^.invalid:=true;
           pscannerfile(scanner)^.invalid:=true;
         if assigned(sourcefiles) then
         if assigned(sourcefiles) then
@@ -873,7 +906,11 @@ uses
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.7  2001-02-20 21:41:15  peter
+  Revision 1.8  2001-03-06 18:28:02  peter
+    * patch from Pavel with a new and much faster DLL Scanner for
+      automatic importing so $linklib works for DLLs. Thanks Pavel!
+
+  Revision 1.7  2001/02/20 21:41:15  peter
     * new fixfilename, findfile for unix. Look first for lowercase, then
     * new fixfilename, findfile for unix. Look first for lowercase, then
       NormalCase and last for UPPERCASE names.
       NormalCase and last for UPPERCASE names.
 
 

+ 18 - 1
compiler/import.pas

@@ -61,6 +61,19 @@ type
       procedure generatesmartlib;virtual;
       procedure generatesmartlib;virtual;
    end;
    end;
 
 
+   TDLLScanner=class
+   public
+     f:file;
+     impname:string;
+     TheWord:array[0..1]of char;
+     HeaderOffset:cardinal;
+     loaded:integer;
+     function isSuitableFileType(x:cardinal):longbool;virtual;abstract;
+     function GetEdata(HeaderEntry:cardinal):longbool;virtual;abstract;
+     function Scan(const binname:string):longbool;virtual;abstract;
+   end;
+
+
 var
 var
   importlib : timportlib;
   importlib : timportlib;
 
 
@@ -277,7 +290,11 @@ end;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.10  2001-02-26 19:44:52  peter
+  Revision 1.11  2001-03-06 18:28:02  peter
+    * patch from Pavel with a new and much faster DLL Scanner for
+      automatic importing so $linklib works for DLLs. Thanks Pavel!
+
+  Revision 1.10  2001/02/26 19:44:52  peter
     * merged generic m68k updates from fixes branch
     * merged generic m68k updates from fixes branch
 
 
   Revision 1.9  2001/02/03 00:09:02  peter
   Revision 1.9  2001/02/03 00:09:02  peter

+ 12 - 2
compiler/pdecsub.pas

@@ -1059,12 +1059,18 @@ begin
          consume(_NAME);
          consume(_NAME);
          import_name:=get_stringconst;
          import_name:=get_stringconst;
          aktprocsym^.definition^.setmangledname(import_name);
          aktprocsym^.definition^.setmangledname(import_name);
+         if target_info.DllScanSupported then
+           current_module.externals.insert(tExternalsItem.create(import_name));
        end
        end
       else
       else
        begin
        begin
          { external shouldn't override the cdecl/system name }
          { external shouldn't override the cdecl/system name }
          if not (pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
          if not (pocall_clearstack in aktprocsym^.definition^.proccalloptions) then
-           aktprocsym^.definition^.setmangledname(aktprocsym^.realname);
+          begin
+            aktprocsym^.definition^.setmangledname(aktprocsym^.realname);
+            if target_info.DllScanSupported then
+             current_module.externals.insert(tExternalsItem.create(aktprocsym^.realname));
+          end;
        end;
        end;
     end;
     end;
 end;
 end;
@@ -1872,7 +1878,11 @@ end;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.11  2001-01-08 21:40:26  peter
+  Revision 1.12  2001-03-06 18:28:02  peter
+    * patch from Pavel with a new and much faster DLL Scanner for
+      automatic importing so $linklib works for DLLs. Thanks Pavel!
+
+  Revision 1.11  2001/01/08 21:40:26  peter
     * fixed crash with unsupported token overloading
     * fixed crash with unsupported token overloading
 
 
   Revision 1.10  2000/12/25 00:07:27  peter
   Revision 1.10  2000/12/25 00:07:27  peter

+ 8 - 1
compiler/pdecvar.pas

@@ -402,6 +402,9 @@ implementation
                           end;
                           end;
                          importlib.importvariable(aktvarsym^.mangledname,dll_name,C_name)
                          importlib.importvariable(aktvarsym^.mangledname,dll_name,C_name)
                        end
                        end
+                      else
+                       if target_info.DllScanSupported then
+                        current_module.Externals.insert(tExternalsItem.create(aktvarsym^.mangledname));
                     end;
                     end;
                    symdone:=true;
                    symdone:=true;
                  end
                  end
@@ -538,7 +541,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.9  2001-02-20 21:42:54  peter
+  Revision 1.10  2001-03-06 18:28:02  peter
+    * patch from Pavel with a new and much faster DLL Scanner for
+      automatic importing so $linklib works for DLLs. Thanks Pavel!
+
+  Revision 1.9  2001/02/20 21:42:54  peter
     * record and object declaration with same field as type fixed
     * record and object declaration with same field as type fixed
 
 
   Revision 1.7  2001/02/20 11:19:45  marco
   Revision 1.7  2001/02/20 11:19:45  marco

+ 47 - 8
compiler/pmodules.pas

@@ -54,6 +54,9 @@ implementation
        hcodegen,
        hcodegen,
 {$ifdef i386}
 {$ifdef i386}
        cgai386,
        cgai386,
+  {$ifndef NOTARGETWIN32}
+       t_win32,
+  {$endif}     
 {$endif i386}
 {$endif i386}
 {$endif newcg}
 {$endif newcg}
        link,assemble,import,export,gendef,ppu,comprsrc,
        link,assemble,import,export,gendef,ppu,comprsrc,
@@ -64,7 +67,43 @@ implementation
        scanner,pbase,psystem,psub,parser;
        scanner,pbase,psystem,psub,parser;
 
 
     procedure create_objectfile;
     procedure create_objectfile;
+      var
+        DLLScanner      : TDLLScanner;
+        s               : string;
       begin
       begin
+        { try to create import entries from system dlls }
+        if target_info.DllScanSupported and
+           (not current_module.linkOtherSharedLibs.Empty) then
+         begin
+           { Init DLLScanner }
+           case target_info.target of
+{$ifdef i386}
+  {$ifndef NOTARGETWIN32}
+             target_i386_win32 :
+               DLLScanner:=tDLLscannerWin32.create;
+  {$endif}               
+{$endif}
+             else
+               internalerror(769795413);  
+           end;              
+           { Walk all shared libs }
+           While not current_module.linkOtherSharedLibs.Empty do
+            begin
+              S:=current_module.linkOtherSharedLibs.Getusemask(link_allways);
+              DLLScanner.scan(s)
+            end;
+           DLLscanner.Free;
+           { Recreate import section }
+           if (target_info.target=target_i386_win32) then
+            begin
+              if assigned(importssection)then
+               importssection.clear
+              else
+               importssection:=taasmoutput.Create;
+              importlib.generatelib;
+            end;
+         end;
+          
         { create the .s file and assemble it }
         { create the .s file and assemble it }
         GenerateAsm(false);
         GenerateAsm(false);
 
 
@@ -173,13 +212,9 @@ implementation
            Inc(Count);
            Inc(Count);
          end;
          end;
         { TableCount }
         { TableCount }
-{ doesn't work because of bug in the compiler !! (JM)
-        With ResourceStringTables do}
-          begin
-          ResourceStringTables.insert(Tai_const.Create_32bit(count));
-          ResourceStringTables.insert(Tai_symbol.Createdataname_global('FPC_RESOURCESTRINGTABLES',0));
-          ResourceStringTables.concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
-          end;
+        ResourceStringTables.insert(Tai_const.Create_32bit(count));
+        ResourceStringTables.insert(Tai_symbol.Createdataname_global('FPC_RESOURCESTRINGTABLES',0));
+        ResourceStringTables.concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
         { insert in data segment }
         { insert in data segment }
         if (cs_create_smart in aktmoduleswitches) then
         if (cs_create_smart in aktmoduleswitches) then
           dataSegment.concat(Tai_cut.Create);
           dataSegment.concat(Tai_cut.Create);
@@ -1627,7 +1662,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.23  2001-02-24 10:44:56  peter
+  Revision 1.24  2001-03-06 18:28:02  peter
+    * patch from Pavel with a new and much faster DLL Scanner for
+      automatic importing so $linklib works for DLLs. Thanks Pavel!
+
+  Revision 1.23  2001/02/24 10:44:56  peter
     * generate .rst from ppufilename instead of modulename
     * generate .rst from ppufilename instead of modulename
 
 
   Revision 1.22  2001/02/21 19:37:19  peter
   Revision 1.22  2001/02/21 19:37:19  peter

+ 40 - 17
compiler/systems.pas

@@ -214,6 +214,7 @@ interface
           heapsize,
           heapsize,
           maxheapsize,
           maxheapsize,
           stacksize   : longint;
           stacksize   : longint;
+          DllScanSupported : boolean;
        end;
        end;
 
 
        tasmmodeinfo=packed record
        tasmmodeinfo=packed record
@@ -1080,7 +1081,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 2048*1024;
             heapsize    : 2048*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 16384
+            stacksize   : 16384;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_i386_GO32V2;
             target      : target_i386_GO32V2;
@@ -1103,7 +1105,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 2048*1024;
             heapsize    : 2048*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 16384
+            stacksize   : 16384;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_i386_LINUX;
             target      : target_i386_LINUX;
@@ -1126,7 +1129,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_i386_FreeBSD;
             target      : target_i386_FreeBSD;
@@ -1149,7 +1153,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_i386_OS2;
             target      : target_i386_OS2;
@@ -1172,7 +1177,8 @@ implementation
             res         : res_i386_emx;
             res         : res_i386_emx;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 256*1024
+            stacksize   : 256*1024;
+            DllScanSupported:true
           ),
           ),
           (
           (
             target      : target_i386_WIN32;
             target      : target_i386_WIN32;
@@ -1195,7 +1201,8 @@ implementation
             res         : res_i386_windres;
             res         : res_i386_windres;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32*1024*1024;
             maxheapsize : 32*1024*1024;
-            stacksize   : 32*1024*1024
+            stacksize   : 32*1024*1024;
+            DllScanSupported:true
           ),
           ),
           (
           (
             target      : target_i386_NETWARE;
             target      : target_i386_NETWARE;
@@ -1218,7 +1225,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_i386_sunos;
             target      : target_i386_sunos;
@@ -1241,7 +1249,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           )
           )
 {$endif i386}
 {$endif i386}
 {$ifdef m68k}
 {$ifdef m68k}
@@ -1266,7 +1275,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 128*1024;
             heapsize    : 128*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_m68k_Atari;
             target      : target_m68k_Atari;
@@ -1289,7 +1299,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 16*1024;
             heapsize    : 16*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_m68k_Mac;
             target      : target_m68k_Mac;
@@ -1312,7 +1323,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 128*1024;
             heapsize    : 128*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_m68k_linux;
             target      : target_m68k_linux;
@@ -1335,7 +1347,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 128*1024;
             heapsize    : 128*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_m68k_PalmOS;
             target      : target_m68k_PalmOS;
@@ -1358,7 +1371,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 128*1024;
             heapsize    : 128*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           )
           )
 {$endif m68k}
 {$endif m68k}
 {$ifdef alpha}
 {$ifdef alpha}
@@ -1383,7 +1397,10 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+{*** Changes made by Ozerski at 05.03.2001}
+            stacksize   : 8192;
+            DllScanSupported:false
+{*** End changes}
           )
           )
 {$endif}
 {$endif}
 {$ifdef powerpc}
 {$ifdef powerpc}
@@ -1408,7 +1425,8 @@ implementation
             res         : res_none;
             res         : res_none;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           ),
           ),
           (
           (
             target      : target_powerpc_MACOS;
             target      : target_powerpc_MACOS;
@@ -1431,7 +1449,8 @@ implementation
             res         : res_powerpc_mpw;
             res         : res_powerpc_mpw;
             heapsize    : 256*1024;
             heapsize    : 256*1024;
             maxheapsize : 32768*1024;
             maxheapsize : 32768*1024;
-            stacksize   : 8192
+            stacksize   : 8192;
+            DllScanSupported:false
           )
           )
 {$endif}
 {$endif}
           );
           );
@@ -1763,7 +1782,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.14  2001-02-26 19:44:55  peter
+  Revision 1.15  2001-03-06 18:28:02  peter
+    * patch from Pavel with a new and much faster DLL Scanner for
+      automatic importing so $linklib works for DLLs. Thanks Pavel!
+
+  Revision 1.14  2001/02/26 19:44:55  peter
     * merged generic m68k updates from fixes branch
     * merged generic m68k updates from fixes branch
 
 
   Revision 1.13  2001/02/20 21:36:40  peter
   Revision 1.13  2001/02/20 21:36:40  peter

+ 255 - 122
compiler/targets/t_win32.pas

@@ -63,6 +63,18 @@ interface
        function  MakeSharedLibrary:boolean;override;
        function  MakeSharedLibrary:boolean;override;
     end;
     end;
 
 
+    tDLLScannerWin32=class(tDLLScanner)
+    private
+      cstring : array[0..127]of char;
+      function DOSstubOK(var x:cardinal):longbool;
+      function FindDLL(const s:string;var founddll:string):boolean;
+      function DllName(Const Name : string) : string;
+    public
+      function isSuitableFileType(x:cardinal):longbool;override;
+      function GetEdata(HeaderEntry:cardinal):longbool;override;
+      function Scan(const binname:string):longbool;override;
+    end;
+
 
 
 implementation
 implementation
 
 
@@ -74,7 +86,7 @@ implementation
 {$endif Delphi}
 {$endif Delphi}
        cutils,cclasses,
        cutils,cclasses,
        aasm,fmodule,globtype,globals,systems,verbose,
        aasm,fmodule,globtype,globals,systems,verbose,
-       script,gendef,impdef,
+       script,gendef,
        cpubase,cpuasm
        cpubase,cpuasm
 {$ifdef GDB}
 {$ifdef GDB}
        ,gdb
        ,gdb
@@ -92,34 +104,6 @@ implementation
       end;
       end;
 
 
 
 
-    function FindDLL(const s:string):string;
-      var
-        sysdir : string;
-        FoundDll : string;
-        Found : boolean;
-      begin
-        Found:=false;
-        { Look for DLL in:
-          1. Current dir
-          2. Library Path
-          3. windir,windir/system,windir/system32 }
-        Found:=FindFile(s,'.'+DirSep,founddll);
-        if (not found) then
-         Found:=includesearchpath.FindFile(s,founddll);
-        if (not found) then
-         begin
-           sysdir:=FixPath(GetEnv('windir'),false);
-           Found:=FindFile(s,sysdir+';'+sysdir+'system'+DirSep+';'+sysdir+'system32'+DirSep,founddll);
-         end;
-        if (not found) then
-         begin
-           message1(exec_w_libfile_not_found,s);
-           FoundDll:=s;
-         end;
-        FindDll:=FoundDll;
-      end;
-
-
 {*****************************************************************************
 {*****************************************************************************
                              TIMPORTLIBWIN32
                              TIMPORTLIBWIN32
 *****************************************************************************}
 *****************************************************************************}
@@ -737,64 +721,15 @@ end;
 
 
 
 
 Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
 Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
-
-  function do_makedef(const DllName,LibName:string):boolean;
-  var
-    CmdLine : string;
-  begin
-    if (not do_build) and
-       FileExists(LibName) then
-     begin
-       if GetNamedFileTime(LibName)>GetNamedFileTime(DllName) then
-        begin
-          do_makedef:=true;
-          exit;
-        end;
-     end;
-    asw_name:=FindUtil('asw');
-    arw_name:=FindUtil('arw');
-    if cs_link_extern in aktglobalswitches then
-     begin
-       CmdLine:='-l '+LibName+' -i '+DLLName;
-       if asw_name<>'' then
-        CmdLine:=CmdLine+' -a '+asw_name;
-       if arw_name<>'' then
-        CmdLine:=CmdLine+' -r '+arw_name;
-       do_makedef:=DoExec(FindUtil('fpimpdef'),CmdLine,false,false);
-     end
-    else
-     do_makedef:=makedef(DLLName,LIbName);
-  end;
-
 Var
 Var
   linkres  : TLinkRes;
   linkres  : TLinkRes;
   i        : longint;
   i        : longint;
   HPath    : TStringListItem;
   HPath    : TStringListItem;
   s,s2     : string;
   s,s2     : string;
-  found,
-  linklibc : boolean;
+  found:boolean;
 begin
 begin
   WriteResponseFile:=False;
   WriteResponseFile:=False;
 
 
-  { Create static import libraries for DLL that are
-    included using the $linklib directive }
-  While not SharedLibFiles.Empty do
-   begin
-     s:=SharedLibFiles.GetFirst;
-     s2:=AddExtension(s,target_os.sharedlibext);
-     s:=target_os.libprefix+SplitName(s)+target_os.staticlibext;
-     if Do_makedef(FindDLL(s2),s) then
-      begin
-        if s<>''then
-         StaticLibFiles.insert(s);
-      end
-     else
-      begin
-        Message(exec_w_error_while_linking);
-        aktglobalswitches:=aktglobalswitches+[cs_link_extern];
-      end;
-   end;
-
   { Open link.res file }
   { Open link.res file }
   LinkRes.Init(outputexedir+Info.ResName);
   LinkRes.Init(outputexedir+Info.ResName);
 
 
@@ -838,48 +773,6 @@ begin
      LinkRes.Add(')');
      LinkRes.Add(')');
    end;
    end;
 
 
-  { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
-    here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
-  if not SharedLibFiles.Empty then
-   begin
-     linklibc:=false;
-     LinkRes.Add('INPUT(');
-     While not SharedLibFiles.Empty do
-      begin
-        S:=SharedLibFiles.GetFirst;
-        if pos('.',s)=0 then
-          { we never directly link a DLL
-            its allways through an import library PM }
-          { libraries created by C compilers have .a extensions }
-          s2:=s+'.a'{ target_os.sharedlibext }
-        else
-          s2:=s;
-        s2:=FindLibraryFile(s2,'',found);
-        if found then
-          begin
-            LinkRes.Add(s2);
-            continue;
-          end;
-        if pos(target_os.libprefix,s)=1 then
-          s:=copy(s,length(target_os.libprefix)+1,255);
-        if s<>'c' then
-         begin
-           i:=Pos(target_os.sharedlibext,S);
-           if i>0 then
-            Delete(S,i,255);
-           LinkRes.Add('-l'+s);
-         end
-        else
-         begin
-           LinkRes.Add('-l'+s);
-           linklibc:=true;
-         end;
-      end;
-     { be sure that libc is the last lib }
-     if linklibc then
-      LinkRes.Add('-lc');
-     LinkRes.Add(')');
-   end;
 { Write and Close response }
 { Write and Close response }
   linkres.writetodisk;
   linkres.writetodisk;
   linkres.done;
   linkres.done;
@@ -1251,10 +1144,250 @@ begin
   postprocessexecutable:=true;
   postprocessexecutable:=true;
 end;
 end;
 
 
+
+{****************************************************************************
+                            TDLLScannerWin32
+****************************************************************************}
+
+function tDLLScannerWin32.DOSstubOK(var x:cardinal):longbool;
+ begin
+  blockread(f,TheWord,2,loaded);
+  if loaded<>2 then
+   DOSstubOK:=false
+  else
+   begin
+    DOSstubOK:=TheWord='MZ';
+    seek(f,$3C);
+    blockread(f,x,4,loaded);
+    if(loaded<>4)or(x>filesize(f))then
+     DOSstubOK:=false;
+   end;
+ end;
+
+    function TDLLScannerWin32.FindDLL(const s:string;var founddll:string):boolean;
+      var
+        sysdir : string;
+        Found : boolean;
+      begin
+        Found:=false;
+        { Look for DLL in:
+          1. Current dir
+          2. Library Path
+          3. windir,windir/system,windir/system32 }
+        Found:=FindFile(s,'.'+DirSep,founddll);
+        if (not found) then
+         Found:=librarysearchpath.FindFile(s,founddll);
+        if (not found) then
+         begin
+           sysdir:=FixPath(GetEnv('windir'),false);
+           Found:=FindFile(s,sysdir+';'+sysdir+'system'+DirSep+';'+sysdir+'system32'+DirSep,founddll);
+         end;
+        if (not found) then
+         begin
+           message1(exec_w_libfile_not_found,s);
+           FoundDll:=s;
+         end;
+        FindDll:=Found;
+      end;
+
+
+    function tDLLScannerWin32.DllName(Const Name : string) : string;
+      var n : string;
+      begin
+         n:=Upper(SplitExtension(Name));
+         if (n='.DLL') or (n='.DRV') or (n='.EXE') then
+           DllName:=Name
+         else
+           DllName:=Name+target_os.sharedlibext;
+      end;
+
+
+
+function tDLLScannerWin32.isSuitableFileType(x:cardinal):longbool;
+ begin
+  seek(f,x);
+  blockread(f,TheWord,2,loaded);
+  isSuitableFileType:=(loaded=2)and(TheWord='PE');
+ end;
+
+ 
+function tDLLScannerWin32.GetEdata(HeaderEntry:cardinal):longbool;
+ type
+  TObjInfo=packed record
+   ObjName:array[0..7]of char;
+   VirtSize,
+   VirtAddr,
+   RawSize,
+   RawOffset,
+   Reloc,
+   LineNum:cardinal;
+   RelCount,
+   LineCount:word;
+   flags:cardinal;
+  end;
+ var
+  i:cardinal;
+  ObjOfs:cardinal;
+  Obj:TObjInfo;
+  APE_obj,APE_Optsize:word;
+  ExportRVA:cardinal;
+  delta:cardinal;
+ const
+  IMAGE_SCN_CNT_CODE=$00000020;
+ var
+ _d:dirstr;
+ _n:namestr;
+ _e:extstr;
+ function isUsedFunction(name:pchar):longbool;
+  var
+   hp:tExternalsItem;
+  begin
+   isUsedFunction:=false;
+   hp:=tExternalsItem(current_module.Externals.first);
+   while assigned(hp)do
+    begin
+     if(assigned(hp.data))and(not hp.found)then
+      if hp.data^=StrPas(name)then
+       begin
+        isUsedFunction:=true;
+        hp.found:=true;
+        exit;
+       end;
+     hp:=tExternalsItem(hp.next);
+    end;
+  end;
+ 
+ procedure Store(index:cardinal;name:pchar;isData:longbool);
+  begin
+   if not isUsedFunction(name)then
+    exit;
+   if not(current_module.uses_imports) then
+    begin
+     current_module.uses_imports:=true;
+     importlib.preparelib(current_module.modulename^);
+    end;
+   if IsData then
+    importlib.importvariable(name,_n,name)
+   else
+    importlib.importprocedure(name,_n,index,name);
+  end;
+
+ procedure ProcessEdata;
+  type
+   a8=array[0..7]of char;
+  function GetSectionName(rva:cardinal;var Flags:cardinal):a8;
+   var
+    i:cardinal;
+    LocObjOfs:cardinal;
+    LocObj:TObjInfo;
+   begin
+    GetSectionName:='';
+    Flags:=0;
+    LocObjOfs:=APE_OptSize+HeaderOffset+24;
+    for i:=1 to APE_obj do
+     begin
+      seek(f,LocObjOfs);
+      blockread(f,LocObj,sizeof(LocObj));
+      if(rva>=LocObj.VirtAddr)and(rva<=LocObj.VirtAddr+LocObj.RawSize)then
+       begin
+        GetSectionName:=a8(LocObj.ObjName);
+        Flags:=LocObj.flags;
+       end;
+     end;
+   end;
+  var
+   j,Fl:cardinal;
+   ulongval,procEntry:cardinal;
+   Ordinal:word;
+   isData:longbool;
+   ExpDir:packed record
+    flag,
+    stamp:cardinal;
+    Major,
+    Minor:word;
+    Name,
+    Base,
+    NumFuncs,
+    NumNames,
+    AddrFuncs,
+    AddrNames,
+    AddrOrds:cardinal;
+   end;
+  begin
+   with Obj do
+    begin
+     seek(f,RawOffset+delta);
+     blockread(f,ExpDir,sizeof(ExpDir));
+     fsplit(impname,_d,_n,_e);
+     for j:=0 to pred(ExpDir.NumNames)do
+      begin
+       seek(f,RawOffset-VirtAddr+ExpDir.AddrOrds+j*2);
+       blockread(f,Ordinal,2);
+       seek(f,RawOffset-VirtAddr+ExpDir.AddrFuncs+Ordinal*4);
+       blockread(f,ProcEntry,4);
+       seek(f,RawOffset-VirtAddr+ExpDir.AddrNames+j*4);
+       blockread(f,ulongval,4);
+       seek(f,RawOffset-VirtAddr+ulongval);
+       blockread(f,cstring,sizeof(cstring));
+       isData:=GetSectionName(procentry,Fl)='';
+       if not isData then
+        isData:=Fl and IMAGE_SCN_CNT_CODE<>IMAGE_SCN_CNT_CODE;
+       Store(succ(Ordinal),cstring,isData);
+      end;
+   end;
+  end;
+ begin
+  GetEdata:=false;
+  seek(f,HeaderEntry+120);
+  blockread(f,ExportRVA,4);
+  seek(f,HeaderEntry+6);
+  blockread(f,APE_Obj,2);
+  seek(f,HeaderEntry+20);
+  blockread(f,APE_OptSize,2);
+  ObjOfs:=APE_OptSize+HeaderOffset+24;
+  for i:=1 to APE_obj do
+   begin
+    seek(f,ObjOfs);
+    blockread(f,Obj,sizeof(Obj));
+    inc(ObjOfs,sizeof(Obj));
+    with Obj do
+     if(VirtAddr<=ExportRva)and(ExportRva<VirtAddr+VirtSize)then
+      begin
+       delta:=ExportRva-VirtAddr;
+       ProcessEdata;
+       GetEdata:=true;
+      end;
+   end;
+ end;
+
+function tDLLScannerWin32.scan(const binname:string):longbool;
+ var
+  OldFileMode:longint;
+ begin
+  if not FindDll(DLLName(binname),impname) then
+   exit;
+  assign(f,impname);
+  OldFileMode:=filemode;
+  filemode:=0;
+  reset(f,1);
+  filemode:=OldFileMode;
+  if not DOSstubOK(HeaderOffset)then
+   scan:=false
+  else if not isSuitableFileType(HeaderOffset)then
+   scan:=false
+  else
+   scan:=GetEdata(HeaderOffset);
+  close(f);
+ end;
+
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.1  2001-02-26 19:43:11  peter
+  Revision 1.2  2001-03-06 18:28:02  peter
+    * patch from Pavel with a new and much faster DLL Scanner for
+      automatic importing so $linklib works for DLLs. Thanks Pavel!
+
+  Revision 1.1  2001/02/26 19:43:11  peter
     * moved target units to subdir
     * moved target units to subdir
 
 
   Revision 1.10  2001/02/20 21:41:16  peter
   Revision 1.10  2001/02/20 21:41:16  peter