2
0
Эх сурвалжийг харах

* redesigned linker object
+ library support for linux (only procedures can be exported)

peter 26 жил өмнө
parent
commit
fefc839b29

+ 11 - 2
compiler/cgai386.pas

@@ -27,7 +27,7 @@ unit cgai386;
     uses
        cobjects,tree,
        cpubase,cpuasm,
-       symconst,symtable,aasm,win_targ;
+       symconst,symtable,aasm;
 
 {$define TESTGETTEMP to store const that
  are written into temps for later release PM }
@@ -150,6 +150,9 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
        tgeni386,temp_gen,hcodegen,ppu
 {$ifdef GDB}
        ,gdb
+{$endif}
+{$ifndef NOTARGETWIN32}
+       ,t_win32
 {$endif}
        ;
 
@@ -2605,6 +2608,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
               exprasmlist^.concat(new(paicpu,
                 op_const_reg(A_IMUL,S_L,
                 parraydef(pvarsym(p)^.definition)^.definition^.size,R_EDI)));
+{$ifndef NOTARGETWIN32}
               { windows guards only a few pages for stack growing, }
               { so we have to access every page first              }
               if target_os.id=os_i386_win32 then
@@ -2642,6 +2646,7 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
                      parraydef(pvarsym(p)^.definition)^.definition^.size,R_EDI)));
                 end
               else
+{$endif NOTARGETWIN32}
                 begin
                    exprasmlist^.concat(new(paicpu,
                      op_reg_reg(A_SUB,S_L,R_EDI,R_ESP)));
@@ -3414,7 +3419,11 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
 end.
 {
   $Log$
-  Revision 1.53  1999-10-13 22:09:29  pierre
+  Revision 1.54  1999-10-21 14:29:32  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+  Revision 1.53  1999/10/13 22:09:29  pierre
    * fix for uggly bug of Marco
 
   Revision 1.52  1999/10/08 15:40:47  pierre

+ 0 - 157
compiler/dos_targ.pas

@@ -1,157 +0,0 @@
-{
-    $Id$
-    Copyright (c) 1999 by Peter Vreman
-
-    This unit implements some support routines for the Dos targets
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ****************************************************************************
-}
-unit dos_targ;
-
-  interface
-  uses
-    link;
-
-  type
-    plinkergo32v2=^tlinkergo32v2;
-    tlinkergo32v2=object(tlinker)
-      procedure postprocessexecutable(const n : string);virtual;
-    end;
-
-
-  implementation
-
-    uses
-       strings,globtype,globals,cobjects,systems,verbose;
-
-
-{****************************************************************************
-                            Postprocess Executable
-****************************************************************************}
-
-    procedure tlinkergo32v2.postprocessexecutable(const n : string);
-      begin
-      end;
-
-{$ifdef dummy}
-      type
-        tcoffheader=packed record
-          mach   : word;
-          nsects : word;
-          time   : longint;
-          sympos : longint;
-          syms   : longint;
-          opthdr : word;
-          flag   : word;
-        end;
-        tcoffsechdr=packed record
-          name     : array[0..7] of char;
-          vsize    : longint;
-          rvaofs   : longint;
-          datalen  : longint;
-          datapos  : longint;
-          relocpos : longint;
-          lineno1  : longint;
-          nrelocs  : word;
-          lineno2  : word;
-          flags    : longint;
-        end;
-        psecfill=^tsecfill;
-        tsecfill=record
-          fillpos,
-          fillsize : longint;
-          next : psecfill;
-        end;
-
-      var
-         f : file;
-         coffheader : tcoffheader;
-         firstsecpos,
-         maxfillsize,
-         l : longint;
-         coffsec : tcoffsechdr;
-         secroot,hsecroot : psecfill;
-         zerobuf : pointer;
-      begin
-         { when -s is used quit, because there is no .exe }
-         if cs_link_extern in aktglobalswitches then
-          exit;
-         { open file }
-         assign(f,n);
-         {$I-}
-          reset(f,1);
-         if ioresult<>0 then
-           Message1(execinfo_f_cant_open_executable,n);
-         { read headers }
-         seek(f,2048);
-         blockread(f,coffheader,sizeof(tcoffheader));
-         { read section info }
-         maxfillsize:=0;
-         firstsecpos:=0;
-         secroot:=nil;
-         for l:=1to coffheader.nSects do
-          begin
-            blockread(f,coffsec,sizeof(tcoffsechdr));
-            if coffsec.datapos>0 then
-             begin
-               if secroot=nil then
-                firstsecpos:=coffsec.datapos;
-               new(hsecroot);
-               hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
-               hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
-               hsecroot^.next:=secroot;
-               secroot:=hsecroot;
-               if secroot^.fillsize>maxfillsize then
-                maxfillsize:=secroot^.fillsize;
-             end;
-          end;
-         if firstsecpos>0 then
-          begin
-            l:=firstsecpos-filepos(f);
-            if l>maxfillsize then
-             maxfillsize:=l;
-          end
-         else
-          l:=0;
-         { get zero buffer }
-         getmem(zerobuf,maxfillsize);
-         fillchar(zerobuf^,maxfillsize,0);
-         { zero from sectioninfo until first section }
-         blockwrite(f,zerobuf^,l);
-         { zero section alignments }
-         while assigned(secroot) do
-          begin
-            seek(f,secroot^.fillpos);
-            blockwrite(f,zerobuf^,secroot^.fillsize);
-            hsecroot:=secroot;
-            secroot:=secroot^.next;
-            dispose(hsecroot);
-          end;
-         freemem(zerobuf,maxfillsize);
-         close(f);
-         {$I+}
-      end;
-{$endif}
-
-end.
-{
-  $Log$
-  Revision 1.1  1999-08-11 17:26:32  peter
-    * tlinker object is now inherited for win32 and dos
-    * postprocessexecutable is now a method of tlinker
-
-}

+ 4 - 5
compiler/errore.msg

@@ -1311,16 +1311,15 @@ exec_w_error_while_assembling=W_Error while assembling exitcode $1
 exec_w_cant_call_assembler=W_Can't call the assembler, error $1 switching to external assembling
 exec_i_assembling=I_Assembling $1
 exec_i_assembling_smart=I_Assembling smartlink $1
-exec_w_linker_not_found=W_Linker $1 not found, switching to external linking
-exec_t_using_linker=T_Using linker: $1
 exec_w_objfile_not_found=W_Object $1 not found, Linking may fail !
 exec_w_libfile_not_found=W_Library $1 not found, Linking may fail !
 exec_w_error_while_linking=W_Error while linking
 exec_w_cant_call_linker=W_Can't call the linker, switching to external linking
 exec_i_linking=I_Linking $1
-exec_w_binder_not_found=W_binder not found, switching to external binding
-exec_w_ar_not_found=W_ar not found, switching to external ar
-exec_e_dll_not_supported=E_Dynamic Libraries not supported
+exec_w_util_not_found=W_Util $1 not found, switching to external linking
+exec_t_using_util=T_Using util $1
+exec_e_exe_not_supported=E_Creation of Executables not supported
+exec_e_dll_not_supported=E_Creation of Dynamic/Shared Libraries not supported
 exec_i_closing_script=I_Closing script $1
 exec_w_res_not_found=W_resource compiler not found, switching to external mode
 exec_i_compilingresource=I_Compiling resource $1

+ 36 - 7
compiler/export.pas

@@ -39,6 +39,7 @@ type
       index : longint;
       name : pstring;
       options : word;
+      is_var : boolean;
       constructor init;
       destructor done;virtual;
    end;
@@ -64,10 +65,34 @@ implementation
 uses
   systems,verbose,globals,files
 {$ifdef i386}
-  ,os2_targ
-  ,win_targ
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
+  {$ifndef NOTARGETOS2}
+    ,t_os2
+  {$endif}
+  {$ifndef NOTARGETWIN32}
+    ,t_win32
+  {$endif}
+  {$ifndef NOTARGETGO32V2}
+    ,t_go32v2
+  {$endif}
+{$endif}
+{$ifdef m68k}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
+{$endif}
+{$ifdef powerpc}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
+{$endif}
+{$ifdef alpha}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
 {$endif}
-  ,lin_targ
   ;
 
 {****************************************************************************
@@ -81,6 +106,7 @@ begin
   index:=-1;
   name:=nil;
   options:=0;
+  is_var:=false;
 end;
 
 
@@ -137,9 +163,8 @@ procedure InitExport;
 begin
   case target_info.target of
 {$ifdef i386}
-{    target_i386_Linux :
-      importlib:=new(pimportliblinux,Init);
-}
+    target_i386_Linux :
+      exportlib:=new(pexportliblinux,Init);
     target_i386_Win32 :
       exportlib:=new(pexportlibwin32,Init);
 {
@@ -168,7 +193,11 @@ end;
 end.
 {
   $Log$
-  Revision 1.6  1999-08-04 13:02:41  jonas
+  Revision 1.7  1999-10-21 14:29:34  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+  Revision 1.6  1999/08/04 13:02:41  jonas
     * all tokens now start with an underscore
     * PowerPC compiles!!
 

+ 65 - 4
compiler/globals.pas

@@ -235,13 +235,16 @@ unit globals;
     Function ForceExtension(Const HStr,ext:String):String;
     Function FixPath(s:string;allowdot:boolean):string;
     function FixFileName(const s:string):string;
+    procedure SplitBinCmd(const s:string;var bstr,cstr:string);
     procedure AddPathToList(var list:string;s:string;first:boolean);
-    function search(const f : string;path : string;var b : boolean) : string;
+    function  getpathfromlist(var list:string):string;
+    function  search(const f : string;path : string;var b : boolean) : string;
     procedure SynchronizeFileTime(const fn1,fn2:string);
     function FindExe(bin:string;var found:boolean):string;
+    Procedure Shell(const command:string);
 
-   procedure InitGlobals;
-   procedure DoneGlobals;
+    procedure InitGlobals;
+    procedure DoneGlobals;
 
     procedure strdispose(var p : pchar);
 
@@ -972,6 +975,24 @@ unit globals;
        {$endif}
      end;
 
+   procedure SplitBinCmd(const s:string;var bstr,cstr:string);
+     var
+       i : longint;
+     begin
+       i:=pos(' ',s);
+       if i>0 then
+        begin
+          bstr:=Copy(s,1,i-1);
+          cstr:=Copy(s,i+1,length(s)-i);
+        end
+       else
+        begin
+          bstr:='';
+          cstr:='';
+        end;
+     end;
+
+
 
    procedure AddPathToList(var list:string;s:string;first:boolean);
      var
@@ -1039,6 +1060,26 @@ unit globals;
      end;
 
 
+   function getpathfromlist(var list:string):string;
+     var
+       s : string;
+       i : longint;
+     begin
+       s:='';
+       while (list<>'') do
+        begin
+          i:=Pos(';',list);
+          If i=0 then
+           i:=255;
+          S:=Copy(list,1,i-1);
+          Delete (list,1,i);
+          if (S<>'') then
+           break;
+        end;
+       GetPathFromList:=s;
+     end;
+
+
    function search(const f : string;path : string;var b : boolean) : string;
       Var
         singlepathstring : string;
@@ -1158,6 +1199,22 @@ unit globals;
      end;
 
 
+Procedure Shell(const command:string);
+{ This is already defined in the linux.ppu for linux, need for the *
+  expansion under linux }
+{$ifdef linux}
+begin
+  Linux.Shell(command);
+end;
+{$else}
+var
+  comspec : string;
+begin
+  comspec:=getenv('COMSPEC');
+  Exec(comspec,' /C '+command);
+end;
+{$endif}
+
  {****************************************************************************
                                     Init
  ****************************************************************************}
@@ -1258,7 +1315,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.25  1999-09-10 18:48:02  florian
+  Revision 1.26  1999-10-21 14:29:34  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+  Revision 1.25  1999/09/10 18:48:02  florian
     * some bug fixes (e.g. must_be_valid and procinfo.funcret_is_valid)
     * most things for stored properties fixed
 

+ 32 - 4
compiler/import.pas

@@ -67,10 +67,34 @@ implementation
 uses
   systems,verbose,globals
 {$ifdef i386}
-  ,os2_targ
-  ,win_targ
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
+  {$ifndef NOTARGETOS2}
+    ,t_os2
+  {$endif}
+  {$ifndef NOTARGETWIN32}
+    ,t_win32
+  {$endif}
+  {$ifndef NOTARGETGO32V2}
+    ,t_go32v2
+  {$endif}
+{$endif}
+{$ifdef m68k}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
+{$endif}
+{$ifdef powerpc}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
+{$endif}
+{$ifdef alpha}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
 {$endif}
-  ,lin_targ
   ;
 
 {****************************************************************************
@@ -203,7 +227,11 @@ end;
 end.
 {
   $Log$
-  Revision 1.12  1999-08-04 13:02:44  jonas
+  Revision 1.13  1999-10-21 14:29:34  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+  Revision 1.12  1999/08/04 13:02:44  jonas
     * all tokens now start with an underscore
     * PowerPC compiles!!
 

+ 0 - 106
compiler/lin_targ.pas

@@ -1,106 +0,0 @@
-{
-    $Id$
-    Copyright (c) 1998 by Florian Klaempfl
-
-    This unit implements some support routines for the linux target like
-    import/export handling
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ****************************************************************************
-}
-unit lin_targ;
-interface
-
-  uses import;
-
-  type
-    pimportliblinux=^timportliblinux;
-    timportliblinux=object(timportlib)
-      procedure preparelib(const s:string);virtual;
-      procedure importprocedure(const func,module:string;index:longint;const name:string);virtual;
-      procedure importvariable(const varname,module:string;const name:string);virtual;
-      procedure generatelib;virtual;
-    end;
-
-
-implementation
-
-  uses
-    verbose,strings,cobjects,systems,globtype,globals,
-    symconst,
-    files,aasm,symtable;
-
-
-    procedure timportliblinux.preparelib(const s : string);
-      begin
-      end;
-
-
-    procedure timportliblinux.importprocedure(const func,module : string;index : longint;const name : string);
-      begin
-        { insert sharedlibrary }
-        current_module^.linkothersharedlibs.insert(SplitName(module),link_allways);
-        { do nothing with the procedure, only set the mangledname }
-        if name<>'' then
-          aktprocsym^.definition^.setmangledname(name)
-        else
-          Message(parser_e_empty_import_name);
-      end;
-
-
-    procedure timportliblinux.importvariable(const varname,module:string;const name:string);
-      begin
-        { insert sharedlibrary }
-        current_module^.linkothersharedlibs.insert(SplitName(module),link_allways);
-        { reset the mangledname and turn off the dll_var option }
-        aktvarsym^.setmangledname(name);
-{$ifdef INCLUDEOK}
-        exclude(aktvarsym^.varoptions,vo_is_dll_var);
-{$else}
-        aktvarsym^.varoptions:=aktvarsym^.varoptions-[vo_is_dll_var];
-{$endif}
-      end;
-
-
-    procedure timportliblinux.generatelib;
-      begin
-      end;
-
-
-end.
-{
-  $Log$
-  Revision 1.5  1999-08-03 22:02:54  peter
-    * moved bitmask constants to sets
-    * some other type/const renamings
-
-  Revision 1.4  1999/07/03 00:29:50  peter
-    * new link writing to the ppu, one .ppu is needed for all link types,
-      static (.o) is now always created also when smartlinking is used
-
-  Revision 1.3  1999/01/20 14:18:32  pierre
-    * bugs related to mangledname solved
-      - linux external without name
-      -external procs already used
-      (added count and is_used boolean fiels in tprocvar)
-
-  Revision 1.2  1998/11/28 16:20:51  peter
-    + support for dll variables
-
-  Revision 1.1  1998/10/19 18:07:13  peter
-    + external dll_name name func support for linux
-
-}

+ 135 - 405
compiler/link.pas

@@ -33,17 +33,21 @@ Interface
 uses cobjects,files;
 
 Type
+    TLinkerInfo=record
+      ExeCmd,
+      DllCmd        : array[1..3] of string[80];
+      ResName       : string[12];
+      ExtraOptions  : string;
+      DynamicLinker : string[80];
+    end;
+
+    PLinker=^TLinker;
     TLinker = Object
-       Glibc2,
-       Glibc21,
-       LinkToC,                           { Should we link to the C libs? }
-       Strip             : Boolean;       { Strip symbols ? }
+    public
+       Info            : TLinkerInfo;
        ObjectFiles,
        SharedLibFiles,
-       StaticLibFiles    : TStringContainer;
-       LinkOptions       : string;        { Additional options to the linker }
-       DynamicLinker     : String[80];    { What Dynamic linker ? }
-       LinkResName       : String[32];    { Name of response file }
+       StaticLibFiles  : TStringContainer;
      { Methods }
        Constructor Init;
        Destructor Done;
@@ -53,15 +57,14 @@ Type
        Procedure AddObject(const S : String);
        Procedure AddStaticLibrary(const S : String);
        Procedure AddSharedLibrary(S : String);
-       Function  FindLinker:String;      { Find linker, sets Name }
-       Function  DoExec(const command,para:string;info,useshell:boolean):boolean;
-       Function  WriteResponseFile:Boolean;
-       Function  MakeExecutable:boolean;
-       Procedure MakeStaticLibrary(filescnt:longint);
-       Procedure MakeSharedLibrary;
-       procedure postprocessexecutable(const n : string);virtual;
+       Function  FindUtil(const s:string):String;
+       Function  DoExec(const command,para:string;showinfo,useshell:boolean):boolean;
+     { Virtuals }
+       procedure SetDefaultInfo;virtual;
+       Function  MakeExecutable:boolean;virtual;
+       Function  MakeSharedLibrary:boolean;virtual;
+       Function  MakeStaticLibrary(filescnt:longint):boolean;virtual;
      end;
-     PLinker=^TLinker;
 
 Var
   Linker : PLinker;
@@ -81,61 +84,61 @@ uses
   globtype,systems,
   script,globals,verbose,ppu
 {$ifdef i386}
-  ,win_targ
-  ,dos_targ
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
+  {$ifndef NOTARGETOS2}
+    ,t_os2
+  {$endif}
+  {$ifndef NOTARGETWIN32}
+    ,t_win32
+  {$endif}
+  {$ifndef NOTARGETGO32V1}
+    ,t_go32v1
+  {$endif}
+  {$ifndef NOTARGETGO32V2}
+    ,t_go32v2
+  {$endif}
+{$endif}
+{$ifdef m68k}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
 {$endif}
-{$ifdef linux}
-  ,linux
+{$ifdef powerpc}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
+{$endif}
+{$ifdef alpha}
+  {$ifndef NOTARGETLINUX}
+    ,t_linux
+  {$endif}
 {$endif}
   ,gendef
   ;
 
-{$ifndef linux}
-Procedure Shell(const command:string);
-{ This is already defined in the linux.ppu for linux, need for the *
-  expansion under linux }
-var
-  comspec : string;
-begin
-  comspec:=getenv('COMSPEC');
-  Exec(comspec,' /C '+command);
-end;
-{$endif}
-
-
+{*****************************************************************************
+                                   TLINKER
+*****************************************************************************}
 
 Constructor TLinker.Init;
 begin
   ObjectFiles.Init_no_double;
-  { libraries sometimes need to be loaded several times PM }
-  SharedLibFiles.Init{_no_double};
-  StaticLibFiles.Init{_no_double};
-  LinkToC:=(cs_link_toc in aktglobalswitches);
-  Strip:=(cs_link_strip in aktglobalswitches);
-  LinkOptions:=ParaLinkOptions;
-  DynamicLinker:=ParaDynamicLinker;
-  LinkResName:='link.res';
-  Glibc2:=false;
-  Glibc21:=false;
-  if target_info.target=target_i386_linux then
+  SharedLibFiles.Init_no_double;
+  StaticLibFiles.Init_no_double;
+{ set generic defaults }
+  FillChar(Info,sizeof(Info),0);
+  Info.ResName:='link.res';
+{ set the linker specific defaults }
+  SetDefaultInfo;
+{ Allow Parameter overrides for linker info }
+  with Info do
    begin
-     if DynamicLinker='' then
-      begin
-        { first try glibc2 }
-        DynamicLinker:='/lib/ld-linux.so.2';
-        if FileExists(DynamicLinker) then
-         begin
-           Glibc2:=true;
-           { also glibc 2.1 / 2.1.1 / 2.1.2 ? }
-           if FileExists('/lib/ld-2.1.so') or
-              FileExists('/lib/ld-2.1.1.so') or
-              FileExists('/lib/ld-2.1.2.so') then
-            Glibc21:=true;
-         end
-        else
-         DynamicLinker:='/lib/ld-linux.so.1';
-      end;
-     AddPathToList(LibrarySearchPath,'/lib;/usr/lib;/usr/X11R6/lib',true);
+     if ParaLinkOptions<>'' then
+      ExtraOptions:=ParaLinkOptions;
+     if ParaDynamicLinker<>'' then
+      DynamicLinker:=ParaDynamicLinker;
    end;
 end;
 
@@ -148,6 +151,11 @@ begin
 end;
 
 
+Procedure TLinker.SetDefaultInfo;
+begin
+end;
+
+
 procedure TLinker.AddModuleFiles(hp:pmodule);
 var
   mask : longint;
@@ -229,28 +237,24 @@ begin
 end;
 
 
-var
-  LastLDBin : string;
-Function TLinker.FindLinker:string;
+Function TLinker.FindUtil(const s:string):string;
 var
   ldfound : boolean;
+  LastBin : string;
 begin
-  if LastLDBin='' then
+  LastBin:='';
+  if utilsdirectory<>'' then
+   LastBin:=Search(s+source_os.exeext,utilsdirectory,ldfound)+s+source_os.exeext;
+  if LastBin='' then
+   LastBin:=FindExe(s,ldfound);
+  if (not ldfound) and not(cs_link_extern in aktglobalswitches) then
    begin
-     if utilsdirectory<>'' then
-       LastLDBin:=Search(target_link.linkbin+source_os.exeext,utilsdirectory,ldfound)+
-         target_link.linkbin+source_os.exeext;
-     if LastLDBin='' then
-       LastLDBin:=FindExe(target_link.linkbin,ldfound);
-     if (not ldfound) and not(cs_link_extern in aktglobalswitches) then
-      begin
-        Message1(exec_w_linker_not_found,LastLDBin);
-        aktglobalswitches:=aktglobalswitches+[cs_link_extern];
-      end;
-     if ldfound then
-      Message1(exec_t_using_linker,LastLDBin);
+     Message1(exec_w_util_not_found,s);
+     aktglobalswitches:=aktglobalswitches+[cs_link_extern];
    end;
-  FindLinker:=LastLDBin;
+  if ldfound then
+   Message1(exec_t_using_util,LastBin);
+  FindUtil:=LastBin;
 end;
 
 
@@ -349,7 +353,7 @@ begin
 end;
 
 
-Function TLinker.DoExec(const command,para:string;info,useshell:boolean):boolean;
+Function TLinker.DoExec(const command,para:string;showinfo,useshell:boolean):boolean;
 begin
   DoExec:=true;
   if not(cs_link_extern in aktglobalswitches) then
@@ -381,7 +385,7 @@ begin
 { Update asmres when externmode is set }
   if cs_link_extern in aktglobalswitches then
    begin
-     if info then
+     if showinfo then
       AsmRes.AddLinkCommand(Command,Para,current_module^.exefilename^)
      else
       AsmRes.AddLinkCommand(Command,Para,'');
@@ -389,329 +393,43 @@ begin
 end;
 
 
-Function TLinker.WriteResponseFile : Boolean;
-Var
-  LinkResponse : Text;
-  i            : longint;
-  cprtobj,
-  gprtobj,
-  prtobj       : string[80];
-  s,s2         : string;
-  found,linux_link_c,
-  linkdynamic,
-  linklibc     : boolean;
-
-  procedure WriteRes(const s:string);
-  begin
-    if s<>'' then
-     WriteLn(Linkresponse,s);
-  end;
-
-  procedure WriteResFileName(const s:string);
-  begin
-    if s<>'' then
-     begin
-       if not(s[1] in ['a'..'z','A'..'Z','/','\','.']) then
-         Write(Linkresponse,'.',DirSep);
-       WriteLn(Linkresponse,s);
-     end;
-  end;
-
+function TLinker.MakeExecutable:boolean;
 begin
-  WriteResponseFile:=False;
-  linux_link_c:=false;
-{ set special options for some targets }
-  linkdynamic:=not(SharedLibFiles.empty);
-  linklibc:=SharedLibFiles.Find('c');
-  prtobj:='prt0';
-  cprtobj:='cprt0';
-  gprtobj:='gprt0';
-  if glibc21 then
-   begin
-     cprtobj:='cprt21';
-     gprtobj:='gprt21';
-   end;
-  case target_info.target of
-   target_m68k_Palmos,
-   target_i386_Win32 :
-     begin
-       if DLLsource then
-         prtobj:='wdllprt0'
-       else
-         prtobj:='wprt0';
-     end;
-   target_m68k_linux,
-   target_i386_linux :
-     begin
-       if cs_profile in aktmoduleswitches then
-        begin
-          prtobj:=gprtobj;
-          if not glibc2 then
-           AddSharedLibrary('gmon');
-          AddSharedLibrary('c');
-          linklibc:=true;
-        end
-       else
-        begin
-          if linklibc then
-           prtobj:=cprtobj;
-        end;
-       if linklibc then
-         linux_link_c:=true;
-     end;
-  end;
-
-{ Fix command line options }
-  If (DynamicLinker<>'') and (not SharedLibFiles.Empty) then
-   LinkOptions:='-dynamic-linker='+DynamicLinker+' '+LinkOptions;
-  if Strip and not(cs_debuginfo in aktmoduleswitches) and
-                           not (Target_Link.StripBind) then
-   LinkOptions:=LinkOptions+' '+target_link.stripopt;
-
-{ Open linkresponse and write header }
-  assign(linkresponse,current_module^.outpath^+LinkResName);
-  {$I-}
-   rewrite(linkresponse);
-  {$I+}
-  if ioresult<>0 then
-   exit;
-
-  { Write library searchpath }
-  if assigned(current_module^.locallibrarysearchpath) then
-   begin
-     S2:=current_module^.locallibrarysearchpath^;
-     Repeat
-       i:=Pos(';',S2);
-       If i=0 then
-        i:=255;
-       S:=Copy(S2,1,i-1);
-       If S<>'' then
-         WriteRes(target_link.libpathprefix+s+target_link.libpathsuffix);
-       Delete (S2,1,i);
-     until S2='';
-   end;
-  S2:=LibrarySearchPath;
-  Repeat
-    i:=Pos(';',S2);
-    If i=0 then
-     i:=255;
-    S:=Copy(S2,1,i-1);
-    If S<>'' then
-      WriteRes(target_link.libpathprefix+s+target_link.libpathsuffix);
-    Delete (S2,1,i);
-  until S2='';
-
-  WriteRes(target_link.inputstart);
-  { add objectfiles, start with prt0 always }
-  if prtobj<>'' then
-   WriteResFileName(FindObjectFile(prtobj));
-  { try to add crti and crtbegin, they are normally not required, but
-    adding can sometimes be usefull }
-  if linux_link_c then
-   begin
-     s:=search('crtbegin.o',librarysearchpath,found)+'crtbegin.o';
-     if found then
-      WriteResFileName(s);
-     s:=search('crti.o',librarysearchpath,found)+'crti.o';
-     if found then
-      WriteResFileName(s);
-   end;
-  while not ObjectFiles.Empty do
-   begin
-     s:=ObjectFiles.Get;
-     if s<>'' then
-      WriteResFileName(s);
-   end;
-  if linux_link_c then
-   begin
-     s:=search('crtend.o',librarysearchpath,found)+'crtend.o';
-     if found then
-      WriteResFileName(s);
-     s:=search('crtn.o',librarysearchpath,found)+'crtn.o';
-     if found then
-      WriteResFileName(s);
-   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) }
-  While not SharedLibFiles.Empty do
-   begin
-     S:=SharedLibFiles.Get;
-     if s<>'c' then
-      begin
-        i:=Pos(target_os.sharedlibext,S);
-        if i>0 then
-         Delete(S,i,255);
-        WriteRes(target_link.libprefix+s);
-      end
-     else
-      begin
-        { Some times several references to libc are necessary !! PM }
-        WriteRes(target_link.libprefix+s);
-        linklibc:=true;
-        linkdynamic:=false; { C add's it automaticly }
-      end;
-   end;
-  { be sure that libc is the last lib }
-  { arghhhh  this is wrong for DJGPP !!!
-    DJGPP need gcc after c lib (umod...) (PM) }
-  if linklibc then
-   WriteRes(target_link.libprefix+'c');
-  { add libgcc after ! }
-  if linklibc and (target_info.target=target_i386_go32v2) then
-   WriteRes(target_link.libprefix+'gcc');
-  if linkdynamic and (DynamicLinker<>'') then
-   WriteResFileName(DynamicLinker);
-  WriteRes(target_link.inputend);
-
-  { Write staticlibraries }
-  if not StaticLibFiles.Empty then
-   begin
-     WriteRes(target_link.GroupStart);
-     While not StaticLibFiles.Empty do
-      begin
-        S:=StaticLibFiles.Get;
-        WriteResFileName(s)
-      end;
-     WriteRes(target_link.GroupEnd);
-   end;
-
-{ Close response }
-  close(linkresponse);
-  WriteResponseFile:=True;
+  MakeExecutable:=false;
+  Message(exec_e_exe_not_supported);
 end;
 
 
-function TLinker.MakeExecutable:boolean;
-var
-  bindbin    : string[80];
-  bindfound  : boolean;
-  s          : string;
-  success    : boolean;
-  ii         : longint;
+Function TLinker.MakeSharedLibrary:boolean;
 begin
-  { can be changed after InitLinker
-    for DLLs due to relocation problems PM }
-  Strip:=(cs_link_strip in aktglobalswitches);
-{$ifdef linux}
-  if LinkToC then
-   begin
-     AddObject('/usr/lib/crt0.o');
-     AddObject('lprt');
-     AddStaticLibrary('libc.a');
-     AddStaticLibrary('libgcc.a');
-   end;
-{$endif Linux}
-
-{ Write used files and libraries }
-  WriteResponseFile;
-
-{ Call linker }
-  if not(cs_link_extern in aktglobalswitches) then
-   Message1(exec_i_linking,current_module^.exefilename^);
-  s:=target_link.linkcmd;
-  if DLLsource then
-    Replace(s,'$EXE',current_module^.sharedlibfilename^)
-  else
-    Replace(s,'$EXE',current_module^.exefilename^);
-  Replace(s,'$OPT',LinkOptions);
-  Replace(s,'$RES',current_module^.outpath^+LinkResName);
-  success:=DoExec(FindLinker,s,true,false);
-{Bind}
-  if (target_link.bindbin[1]<>'') and
-     ((target_info.target<>target_i386_win32) or
-     (RelocSection and not Deffile.empty)) then
-   for ii:=1 to target_link.binders do
-   begin
-     s:=target_link.bindcmd[ii];
-     Replace(s,'$OPT',LinkOptions);
-     Replace(s,'$RES',current_module^.outpath^+LinkResName);
-     if DLLsource then
-       Replace(s,'$EXE',current_module^.sharedlibfilename^)
-     else
-       Replace(s,'$EXE',current_module^.exefilename^);
-     {Size of the heap when an EMX program runs in OS/2.}
-     Replace(s,'$HEAPMB',tostr((maxheapsize+1048575) shr 20));
-     {Size of the stack when an EMX program runs in OS/2.}
-     Replace(s,'$STACKKB',tostr((stacksize+1023) shr 10));
-     {When an EMX program runs in DOS, the heap and stack share the
-      same memory pool. The heap grows upwards, the stack grows downwards.}
-     Replace(s,'$DOSHEAPKB',tostr((stacksize+maxheapsize+1023) shr 10));
-     if Strip and Target_Link.StripBind then
-       Replace (S, '$STRIP', Target_Link.StripOpt)
-     else
-       Replace (S, '$STRIP', '');
-     {This is a hack. But I don't think other platforms have a presenation
-      manager, so it should work. (DM)}
-     if usewindowapi then
-       replace (s, '$PM',' -p')
-     else
-       replace (s, '$PM','');
-     if utilsdirectory<>'' then
-       begin
-          bindbin:=Search(target_link.bindbin[ii]+source_os.exeext,
-            utilsdirectory,bindfound)+target_link.bindbin[ii]+source_os.exeext;
-       end
-     else
-       bindbin:=FindExe(target_link.bindbin[ii],bindfound);
-     if (not bindfound) and not (cs_link_extern in aktglobalswitches) then
-      begin
-        Message1(exec_w_binder_not_found,bindbin);
-        aktglobalswitches:=aktglobalswitches+[cs_link_extern];
-      end;
-     DoExec(bindbin,s,false,false);
-   end;
-
-{ Post processor executable }
-  if success and
-     not(cs_link_extern in aktglobalswitches) then
-   begin
-     if DLLsource then
-      postprocessexecutable(current_module^.sharedlibfilename^)
-     else
-      postprocessexecutable(current_module^.exefilename^);
-   end;
-
-{Remove ReponseFile}
-  if (success) and not(cs_link_extern in aktglobalswitches) then
-   RemoveFile(current_module^.outpath^+LinkResName);
-  MakeExecutable:=success;   { otherwise a recursive call to link method }
+  MakeSharedLibrary:=false;
+  Message(exec_e_dll_not_supported);
 end;
 
 
-Procedure TLinker.MakeStaticLibrary(filescnt:longint);
+Function TLinker.MakeStaticLibrary(filescnt:longint):boolean;
 {
   FilesCnt holds the amount of .o files created, if filescnt=0 then
   no smartlinking is used
 }
 var
   smartpath,
-  s,
-  arbin   : string;
-  arfound : boolean;
+  cmdstr,
+  binstr  : string;
+  success : boolean;
   cnt     : longint;
 begin
+  MakeStaticLibrary:=false;
+
   smartpath:=current_module^.path^+FixPath(FixFileName(current_module^.modulename^)+target_info.smartext,false);
-{ find ar binary }
-  if utilsdirectory<>'' then
-    begin
-       arbin:=Search(target_ar.arbin+source_os.exeext,
-         utilsdirectory,arfound)+target_ar.arbin+source_os.exeext;
-    end
-  else
-    arbin:=FindExe(target_ar.arbin,arfound);
-  if (not arfound) and not(cs_link_extern in aktglobalswitches) then
-   begin
-     Message(exec_w_ar_not_found);
-     aktglobalswitches:=aktglobalswitches+[cs_link_extern];
-   end;
-  s:=target_ar.arcmd;
-  Replace(s,'$LIB',current_module^.staticlibfilename^);
+  SplitBinCmd(target_ar.arcmd,binstr,cmdstr);
+  Replace(cmdstr,'$LIB',current_module^.staticlibfilename^);
   if filescnt=0 then
-    Replace(s,'$FILES',current_module^.objfilename^)
+    Replace(cmdstr,'$FILES',current_module^.objfilename^)
   else
-    Replace(s,'$FILES',FixFileName(smartpath+current_module^.asmprefix^+'*'+target_info.objext));
-  DoExec(arbin,s,false,true);
+    Replace(cmdstr,'$FILES',FixFileName(smartpath+current_module^.asmprefix^+'*'+target_info.objext));
+  success:=DoExec(FindUtil(binstr),cmdstr,false,true);
+
 { Clean up }
   if not(cs_asm_leave in aktglobalswitches) then
    if not(cs_link_extern in aktglobalswitches) then
@@ -736,45 +454,56 @@ begin
          AsmRes.Add('rmdir '+smartpath);
        end;
     end;
+  MakeStaticLibrary:=success;
 end;
 
 
-Procedure TLinker.MakeSharedLibrary;
-var
-  s : string;
-begin
-  s:=' -shared -o $LIB $FILES';
-  Replace(s,'$LIB',current_module^.sharedlibfilename^);
-  Replace(s,'$FILES',current_module^.objfilename^);
-  if DoExec(FindLinker,s,false,false) then
-   RemoveFile(current_module^.objfilename^);
-end;
-
-procedure tlinker.postprocessexecutable(const n:string);
-begin
-end;
-
+{*****************************************************************************
+                                 Init/Done
+*****************************************************************************}
 
 procedure InitLinker;
 begin
   case target_info.target of
 {$ifdef i386}
+  {$ifndef NOTARGETLINUX}
+    target_i386_linux :
+      linker:=new(plinkerlinux,Init);
+  {$endif}
+  {$ifndef NOTARGETWIN32}
     target_i386_Win32 :
       linker:=new(plinkerwin32,Init);
+  {$endif}
+  {$ifndef NOTARGETGO32V1}
+    target_i386_Go32v1 :
+      linker:=new(plinkergo32v1,Init);
+  {$endif}
+  {$ifndef NOTARGETGO32V2}
     target_i386_Go32v2 :
       linker:=new(plinkergo32v2,Init);
+  {$endif}
 {$endif i386}
 {$ifdef m68k}
+  {$ifndef NOTARGETPALMOS}
     target_m68k_palmos:
       linker:=new(plinker,Init);
+  {$endif}
+  {$ifndef NOTARGETLINUX}
+    target_m68k_linux :
+      linker:=new(plinkerlinux,Init);
+  {$endif}
 {$endif m68k}
 {$ifdef alpha}
-    target_alpha_linux:
-      linker:=new(plinker,Init);
+  {$ifndef NOTARGETLINUX}
+    target_alpha_linux :
+      linker:=new(plinkerlinux,Init);
+  {$endif}
 {$endif alpha}
 {$ifdef powerpc}
-    target_powerpc_linux:
-      linker:=new(plinker,Init);
+  {$ifndef NOTARGETLINUX}
+    target_powerpc_linux :
+      linker:=new(plinkerlinux,Init);
+  {$endif}
 {$endif powerpc}
     else
       linker:=new(plinker,Init);
@@ -792,8 +521,9 @@ end;
 end.
 {
   $Log$
-  Revision 1.73  1999-10-08 15:38:42  pierre
-   * library list keeps doubles
+  Revision 1.74  1999-10-21 14:29:34  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
 
   Revision 1.72  1999/09/16 23:05:52  florian
     * m68k compiler is again compilable (only gas writer, no assembler reader)

+ 3 - 4
compiler/msgidx.inc

@@ -413,15 +413,14 @@ type tmsgconst=(
   exec_w_cant_call_assembler,
   exec_i_assembling,
   exec_i_assembling_smart,
-  exec_w_linker_not_found,
-  exec_t_using_linker,
   exec_w_objfile_not_found,
   exec_w_libfile_not_found,
   exec_w_error_while_linking,
   exec_w_cant_call_linker,
   exec_i_linking,
-  exec_w_binder_not_found,
-  exec_w_ar_not_found,
+  exec_w_util_not_found,
+  exec_t_using_util,
+  exec_e_exe_not_supported,
   exec_e_dll_not_supported,
   exec_i_closing_script,
   exec_w_res_not_found,

+ 73 - 73
compiler/msgtxt.inc

@@ -1,7 +1,7 @@
 {$ifdef Delphi}
-const msgtxt : array[0..000103] of string[240]=(
+const msgtxt : array[0..000102] of string[240]=(
 {$else Delphi}
-const msgtxt : array[0..000103,1..240] of char=(
+const msgtxt : array[0..000102,1..240] of char=(
 {$endif Delphi}
   'T_Compiler: $1'#000+
   'D_Compiler OS: $1'#000+
@@ -436,135 +436,134 @@ const msgtxt : array[0..000103,1..240] of char=(
   'ing'#000+
   'I_Assembling $1'#000+
   'I_Assembling smartlink $1'#000+
-  'W_Linker $1 not found, sw','itching to external linking'#000+
-  'T_Using linker: $1'#000+
-  'W_Object $1 not found, Linking may fail !'#000+
+  'W_Object $1 not found, Li','nking may fail !'#000+
   'W_Library $1 not found, Linking may fail !'#000+
   'W_Error while linking'#000+
   'W_Can'#039't call the linker, switching to external linking'#000+
   'I_Linking $1'#000+
-  'W_binder not found',', switching to external binding'#000+
-  'W_ar not found, switching to external ar'#000+
-  'E_Dynamic Libraries not supported'#000+
+  'W_$1 not found: $2, switching to external linking'#000+
+  'T_Using $1: $2'#000+
+  'E_Creation of Executables',' not supported'#000+
+  'E_Creation of Dynamic/Shared Libraries not supported'#000+
   'I_Closing script $1'#000+
   'W_resource compiler not found, switching to external mode'#000+
   'I_Compiling resource $1'#000+
-  'F_Can'#039't post process executable',' $1'#000+
+  'F_Can'#039't post process executable $1'#000+
   'F_Can'#039't open executable $1'#000+
-  'X_Size of Code: $1 bytes'#000+
+  'X_Size o','f Code: $1 bytes'#000+
   'X_Size of initialized data: $1 bytes'#000+
   'X_Size of uninitialized data: $1 bytes'#000+
   'X_Stack space reserved: $1 bytes'#000+
   'X_Stack space commited: $1 bytes'#000+
   'T_Unitsearch: $1'#000+
   'T_PPU Loading $1'#000+
-  'U_PPU Na','me: $1'#000+
+  'U_PPU Name: $1'#000+
   'U_PPU Flags: $1'#000+
   'U_PPU Crc: $1'#000+
-  'U_PPU Time: $1'#000+
+  'U_','PPU Time: $1'#000+
   'U_PPU File too short'#000+
   'U_PPU Invalid Header (no PPU at the begin)'#000+
   'U_PPU Invalid Version $1'#000+
   'U_PPU is compiled for an other processor'#000+
   'U_PPU is compiled for an other target'#000+
   'U_PPU Source: $1'#000+
-  'U_W','riting $1'#000+
+  'U_Writing $1'#000+
   'F_Can'#039't Write PPU-File'#000+
-  'F_reading PPU-File'#000+
+  'F_read','ing PPU-File'#000+
   'F_unexpected end of PPU-File'#000+
   'F_Invalid PPU-File entry: $1'#000+
   'F_PPU Dbx count problem'#000+
   'E_Illegal unit name: $1'#000+
   'F_Too much units'#000+
   'F_Circular unit reference between $1 and $2'#000+
-  'F_Can'#039't compile unit ','$1, no sources available'#000+
-  'F_Can'#039't find unit $1'#000+
+  'F_Can'#039't compile unit $1, no sources available'#000+
+  'F_Can'#039't find u','nit $1'#000+
   'W_Unit $1 was not found but $2 exists'#000+
   'F_Unit $1 searched but $2 found'#000+
   'W_Compiling the system unit requires the -Us switch'#000+
   'F_There were $1 errors compiling module, stopping'#000+
-  'U_Load from $1 ($2) un','it $3'#000+
-  'U_Recompiling $1, checksum changed for $2'#000+
+  'U_Load from $1 ($2) unit $3'#000+
+  'U_Recompiling $1, checksum change','d for $2'#000+
   'U_Recompiling $1, source found only'#000+
   'U_Recompiling unit, static lib is older than ppufile'#000+
   'U_Recompiling unit, shared lib is older than ppufile'#000+
-  'U_Recompiling unit, obj and asm are older than ppu','file'#000+
-  'U_Recompiling unit, obj is older than asm'#000+
+  'U_Recompiling unit, obj and asm are older than ppufile'#000+
+  'U_Recompiling unit, obj is older t','han asm'#000+
   'U_Parsing interface of $1'#000+
   'U_Parsing implementation of $1'#000+
   'U_Second load for unit $1'#000+
   'U_PPU Check file $1 time $2'#000+
   '$1 [options] <inputfile> [options]'#000+
   'W_Only one source file supported'#000+
-  'W_DEF file can',' be created only for OS/2'#000+
-  'E_nested response files are not supported'#000+
+  'W_DEF file can be created only for OS/2'#000+
+  'E_nested resp','onse files are not supported'#000+
   'F_No source file name in command line'#000+
   'E_Illegal parameter: $1'#000+
   'H_-? writes help pages'#000+
   'F_Too many config files nested'#000+
   'F_Unable to open file $1'#000+
-  'N_Reading further options from ','$1'#000+
+  'N_Reading further options from $1'#000+
   'W_Target is already set to: $1'#000+
-  'W_Shared libs not supported on DOS platform, reverting to static'#000+
+  'W_Sha','red libs not supported on DOS platform, reverting to static'#000+
   'F_too many IF(N)DEFs'#000+
   'F_too many ENDIFs'#000+
   'F_open conditional at the end of the file'#000+
-  'W_Debug information generation is not supported by this exec','utable'#000+
+  'W_Debug information generation is not supported by this executable'#000+
   'H_Try recompiling with -dGDB'#000+
-  'E_You are using the obsolete switch $1'#000+
+  'E_Y','ou are using the obsolete switch $1'#000+
   'E_You are using the obsolete switch $1, please use $2'#000+
   'N_Switching assembler to default source writing assembler'#000+
-  'Free Pascal Compiler version $FPCVER [$FPCDATE] for $','FPCTARGET'#000+
-  'Copyright (c) 1993-1999 by Florian Klaempfl'#000+
+  'Free Pascal Compiler version $FPCVER [$FPCDATE] for $FPCTARGET'#000+
+  'Copyright (c) 1993-1999 by Fl','orian Klaempfl'#000+
   'Free Pascal Compiler version $FPCVER'#000+
   #000+
   'Compiler Date  : $FPCDATE'#000+
   'Compiler Target: $FPCTARGET'#000+
   #000+
   'This program comes under the GNU General Public Licence'#000+
-  'For more information read COPYING.FPC',#000+
+  'For more information read COPYING.FPC'#000+
   #000+
   'Report bugs,suggestions etc to:'#000+
-  '                 [email protected]'#000+
+  '     ','            [email protected]'#000+
   '**0*_put + after a boolean switch option to enable it, - to disable it'+
   #000+
   '**1a_the compiler doesn'#039't delete the generated assembler file'#000+
-  '**2al_list sourcecode ','lines in assembler file'#000+
-  '**2ar_list register allocation/release info in assembler file'#000+
+  '**2al_list sourcecode lines in assembler file'#000+
+  '**2ar_list regi','ster allocation/release info in assembler file'#000+
   '**2at_list temp allocation/release info in assembler file'#000+
   '**1b_generate browser info'#000+
   '**2bl_generate local symbol info'#000+
   '**1B_build all modules'#000+
-  '**1C<x>_code ','generation options:'#000+
-  '3*2CD_create dynamic library'#000+
+  '**1C<x>_code generation options:'#000+
+  '3*2CD_create dynami','c library'#000+
   '**2Ch<n>_<n> bytes heap (between 1023 and 67107840)'#000+
   '**2Ci_IO-checking'#000+
   '**2Cn_omit linking stage'#000+
   '**2Co_check overflow of integer operations'#000+
   '**2Cr_range checking'#000+
   '**2Cs<n>_set stack size to <n>'#000+
-  '*','*2Ct_stack checking'#000+
-  '**2CD_create also dynamic library (* doesn'#039't work yet *)'#000+
+  '**2Ct_stack checking'#000+
+  '**2CD_create also d','ynamic library (* doesn'#039't work yet *)'#000+
   '**2CX_create also smartlinked library'#000+
   '**1d<x>_defines the symbol <x>'#000+
   '*O1D_generate a DEF file'#000+
   '*O2Dd<x>_set description to <x>'#000+
   '*O2Dw_PM application'#000+
-  '**1e<x>_set path',' to executable'#000+
+  '**1e<x>_set path to executable'#000+
   '**1E_same as -Cn'#000+
-  '**1F<x>_set file names and paths:'#000+
+  '**1F<x>','_set file names and paths:'#000+
   '**2FD<x>_sets the directory where to search for compiler utilities'#000+
   '**2Fe<x>_redirect error output to <x>'#000+
   '**2FE<x>_set exe/unit output path to <x>'#000+
-  '**2Fi<x>_adds <x> to include',' path'#000+
-  '**2Fl<x>_adds <x> to library path'#000+
+  '**2Fi<x>_adds <x> to include path'#000+
+  '**2Fl<x>_adds <x> to library path',#000+
   '*L2FL<x>_uses <x> as dynamic linker'#000+
   '**2Fo<x>_adds <x> to object path'#000+
   '**2Fr<x>_load error message file <x>'#000+
   '**2Fu<x>_adds <x> to unit path'#000+
   '**2FU<x>_set unit output path to <x>, overrides -FE'#000+
-  '*g1g<x>_gen','erate debugger information:'#000+
-  '*g2gg_use gsym'#000+
+  '*g1g<x>_generate debugger information:'#000+
+  '*g2gg_use g','sym'#000+
   '*g2gd_use dbx'#000+
   '*g2gh_use heap trace unit'#000+
   '*g2gc_generate checks for pointers'#000+
@@ -572,97 +571,98 @@ const msgtxt : array[0..000103,1..240] of char=(
   '**2iD_return compiler date'#000+
   '**2iV_return compiler version'#000+
   '**2iSO_return compiler OS'#000+
-  '**2iSP_return compiler',' processor'#000+
+  '**2iSP_return compiler processor'#000+
   '**2iTO_return target OS'#000+
-  '**2iTP_return target processor'#000+
+  '**2i','TP_return target processor'#000+
   '**1I<x>_adds <x> to include path'#000+
   '**1k<x>_Pass <x> to the linker'#000+
   '**1l_write logo'#000+
   '**1n_don'#039't read the default config file'#000+
-  '**1o<x>_change the name of the executable produced to ','<x>'#000+
-  '**1pg_generate profile code for gprof (defines FPC_PROFILE)'#000+
+  '**1o<x>_change the name of the executable produced to <x>'#000+
+  '**1pg_generate profile code for gpr','of (defines FPC_PROFILE)'#000+
   '*L1P_use pipes instead of creating temporary assembler files'#000+
   '**1S<x>_syntax options:'#000+
   '**2S2_switch some Delphi 2 extensions on'#000+
-  '**2Sc_supports operators like C (*=,+=,/= and -=)'#000,
+  '**2Sc_supports operators like C (*=,+=,/= and -=)'#000+
   '**2Sd_tries to be Delphi compatible'#000+
-  '**2Se<x>_compiler stops after the <x> errors (default is 1)'#000+
+  '**2','Se<x>_compiler stops after the <x> errors (default is 1)'#000+
   '**2Sg_allow LABEL and GOTO'#000+
   '**2Sh_Use ansistrings'#000+
   '**2Si_support C++ styled INLINE'#000+
   '**2Sm_support macros like C (global)'#000+
-  '**2So_tries to be TP/BP 7.','0 compatible'#000+
-  '**2Sp_tries to be gpc compatible'#000+
+  '**2So_tries to be TP/BP 7.0 compatible'#000+
+  '**2Sp_tries to be gpc comp','atible'#000+
   '**2Ss_constructor name must be init (destructor must be done)'#000+
   '**2St_allow static keyword in objects'#000+
   '**1s_don'#039't call assembler and linker (only with -a)'#000+
   '**1u<x>_undefines the symbol <x>'#000+
-  '**1U_unit',' options:'#000+
-  '**2Un_don'#039't check the unit name'#000+
+  '**1U_unit options:'#000+
+  '**2Un_don'#039't check the unit na','me'#000+
   '**2Us_compile a system unit'#000+
   '**1v<x>_Be verbose. <x> is a combination of the following letters:'#000+
   '**2*_e : Show errors (default)       d : Show debug info'#000+
-  '**2*_w : Show warnings               u : Show ','unit info'#000+
-  '**2*_n : Show notes                  t : Show tried/used files'#000+
+  '**2*_w : Show warnings               u : Show unit info'#000+
+  '**2*_n : Show notes          ','        t : Show tried/used files'#000+
   '**2*_h : Show hints                  m : Show defined macros'#000+
   '**2*_i : Show general info           p : Show compiled procedures'#000+
-  '**2*_l : Show linenumbers            c :',' Show conditionals'#000+
-  '**2*_a : Show everything             0 : Show nothing (except errors)'#000+
+  '**2*_l : Show linenumbers            c : Show conditionals'#000+
+  '**2*_a : Show everyt','hing             0 : Show nothing (except errors'+
+  ')'#000+
   '**2*_b : Show all procedure          r : Rhide/GCC compatibility mode'#000+
   '**2*_    declarations if an error    x : Executable info (Win32 only)'#000+
-  '**2*_    oc','curs'#000+
+  '**2*_    occurs'#000+
   '**1X_executable options:'#000+
-  '*L2Xc_link with the c library'#000+
+  '*L2Xc_lin','k with the c library'#000+
   '**2Xs_strip all symbols from executable'#000+
   '**2XD_try to link dynamic          (defines FPC_LINK_DYNAMIC)'#000+
   '**2XS_try to link static (default) (defines FPC_LINK_STATIC)'#000+
-  '**2XX_try to link',' smart            (defines FPC_LINK_SMART)'#000+
+  '**2XX_try to link smart            (defines FPC_LINK_SMA','RT)'#000+
   '**0*_Processor specific options:'#000+
   '3*1A<x>_output format:'#000+
   '3*2Aas_assemble using GNU AS'#000+
   '3*2Aasaout_assemble using GNU AS for aout (Go32v1)'#000+
   '3*2Anasmcoff_coff (Go32v2) file using Nasm'#000+
-  '3*2Anasmelf_elf32 ','(Linux) file using Nasm'#000+
-  '3*2Anasmobj_obj file using Nasm'#000+
+  '3*2Anasmelf_elf32 (Linux) file using Nasm'#000+
+  '3*2Anasmobj_obj',' file using Nasm'#000+
   '3*2Amasm_obj file using Masm (Microsoft)'#000+
   '3*2Atasm_obj file using Tasm (Borland)'#000+
   '3*2Acoff_coff (Go32v2) using internal writer'#000+
   '3*2Apecoff_pecoff (Win32) using internal writer'#000+
-  '3*1R<x>_ass','embler reading style:'#000+
-  '3*2Ratt_read AT&T style assembler'#000+
+  '3*1R<x>_assembler reading style:'#000+
+  '3*2Ratt_read AT&T',' style assembler'#000+
   '3*2Rintel_read Intel style assembler'#000+
   '3*2Rdirect_copy assembler text directly to assembler file'#000+
   '3*1O<x>_optimizations:'#000+
   '3*2Og_generate smaller code'#000+
   '3*2OG_generate faster code (default)'#000+
-  '3','*2Or_keep certain variables in registers (still BUGGY!!!)'#000+
+  '3*2Or_keep certain variables in register','s (still BUGGY!!!)'#000+
   '3*2Ou_enable uncertain optimizations (see docs)'#000+
   '3*2O1_level 1 optimizations (quick optimizations)'#000+
   '3*2O2_level 2 optimizations (-O1 + slower optimizations)'#000+
-  '3*2O3_level 3 optimizations',' (same as -O2u)'#000+
-  '3*2Op<x>_target processor:'#000+
+  '3*2O3_level 3 optimizations (same as -O2u)'#000+
+  '3*2Op<x>_target process','or:'#000+
   '3*3Op1_set target processor to 386/486'#000+
   '3*3Op2_set target processor to Pentium/PentiumMMX (tm)'#000+
   '3*3Op3_set target processor to PPro/PII/c6x86/K6 (tm)'#000+
   '3*1T<x>_Target operating system:'#000+
-  '3*2TGO32V1_versi','on 1 of DJ Delorie DOS extender'#000+
-  '3*2TGO32V2_version 2 of DJ Delorie DOS extender'#000+
+  '3*2TGO32V1_version 1 of DJ Delorie DOS extender'#000+
+  '3*2TGO3','2V2_version 2 of DJ Delorie DOS extender'#000+
   '3*2TLINUX_Linux'#000+
   '3*2TOS2_OS/2 2.x'#000+
   '3*2TWin32_Windows 32 Bit'#000+
   '6*1A<x>_output format'#000+
   '6*2Aas_Unix o-file using GNU AS'#000+
   '6*2Agas_GNU Motorola assembler'#000+
-  '6*2Amit_MIT Synta','x (old GAS)'#000+
-  '6*2Amot_Standard Motorola assembler'#000+
+  '6*2Amit_MIT Syntax (old GAS)'#000+
+  '6*2Amot_Standard Motorola a','ssembler'#000+
   '6*1O_optimizations:'#000+
   '6*2Oa_turn on the optimizer'#000+
   '6*2Og_generate smaller code'#000+
   '6*2OG_generate faster code (default)'#000+
   '6*2Ox_optimize maximum (still BUGGY!!!)'#000+
-  '6*2O2_set target processor to a MC68020','+'#000+
+  '6*2O2_set target processor to a MC68020+'#000+
   '6*1R<x>_assembler reading style:'#000+
-  '6*2RMOT_read motorola style assembler'#000+
+  '6*2R','MOT_read motorola style assembler'#000+
   '6*1T<x>_Target operating system:'#000+
   '6*2TAMIGA_Commodore Amiga'#000+
   '6*2TATARI_Atari ST/STe/TT'#000+
@@ -670,5 +670,5 @@ const msgtxt : array[0..000103,1..240] of char=(
   '6*2TLINUX_Linux-68k'#000+
   '**1*_'#000+
   '**1?_shows this help'#000+
-  '**1h_shows',' this help without waiting'#000
+  '**1h_shows this help without waiting'#000
 );

+ 11 - 29
compiler/pmodules.pas

@@ -274,33 +274,6 @@ unit pmodules;
               datasegment^.concat(new(pai_symbol,initname_global('__stklen',4)));
               datasegment^.concat(new(pai_const,init_32bit(stacksize)));
             end;
-          target_i386_WIN32 :
-            begin
-              target_link.bindcmd[1]:=target_link.bindcmd[1]+' -d '+deffile.fname;
-              if DLLsource then
-               begin
-                 target_link.binders:=2;
-                 target_link.linkcmd:='--dll '+target_link.linkcmd;
-                 target_link.bindcmd[2]:='--dll '+target_link.bindcmd[2];
-                 if RelocSection then
-                  begin
-                    target_link.linkcmd:=target_link.linkcmd+' --base-file base.$$$';
-                    target_link.bindcmd[1]:=target_link.bindcmd[1]+' --base-file base.$$$';
-                  end;
-                 if assigned(DLLImageBase) then
-                   begin
-                     target_link.linkcmd:=target_link.linkcmd+' --image-base=0x'+DLLImageBase^;
-                     target_link.bindcmd[2]:=target_link.bindcmd[2]+' --image-base=0x'+DLLImageBase^;
-                   end;
-               end;
-              if apptype=at_gui then
-               begin
-                target_link.linkcmd:='--subsystem windows '+target_link.linkcmd;
-                target_link.bindcmd[2]:='--subsystem windows '+target_link.bindcmd[2];
-               end;
-              if (cs_link_strip in aktglobalswitches) then
-                target_link.bindcmd[2]:='-s '+target_link.bindcmd[2];
-            end;
 {$endif i386}
 {$ifdef m68k}
           target_m68k_Atari :
@@ -1453,14 +1426,23 @@ unit pmodules;
              deffile.writefile;
             { finally we can create a executable }
             if (not current_module^.is_unit) then
-             Linker^.MakeExecutable;
+             begin
+               if DLLSource then
+                Linker^.MakeSharedLibrary
+               else
+                Linker^.MakeExecutable;
+             end;
           end;
       end;
 
 end.
 {
   $Log$
-  Revision 1.159  1999-10-12 21:20:45  florian
+  Revision 1.160  1999-10-21 14:29:37  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+  Revision 1.159  1999/10/12 21:20:45  florian
     * new codegenerator compiles again
 
   Revision 1.158  1999/10/03 19:44:42  peter

+ 50 - 7
compiler/script.pas

@@ -31,7 +31,9 @@ type
   TScript=object
     fn   : string[80];
     data : TStringQueue;
+    executable : boolean;
     constructor Init(const s:string);
+    constructor InitExec(const s:string);
     destructor Done;
     procedure AddStart(const s:string);
     procedure Add(const s:string);
@@ -39,18 +41,24 @@ type
     procedure WriteToDisk;virtual;
   end;
 
+  PAsmScript = ^TAsmScript;
   TAsmScript = Object (TScript)
     Constructor Init (Const ScriptName : String);
     Procedure AddAsmCommand (Const Command, Options,FileName : String);
     Procedure AddLinkCommand (Const Command, Options, FileName : String);
     Procedure AddDeleteCommand (Const FileName : String);
     Procedure WriteToDisk;virtual;
-    end;
-  PAsmScript = ^TAsmScript;
+  end;
+
+  PLinkRes = ^TLinkRes;
+  TLinkRes = Object (TScript)
+    procedure Add(const s:string);
+    procedure AddFileName(const s:string);
+  end;
 
-{ Asm response file }
 var
   AsmRes : TAsmScript;
+  LinkRes : TLinkRes;
 
 
 implementation
@@ -67,8 +75,17 @@ uses
 ****************************************************************************}
 
 constructor TScript.Init(const s:string);
+begin
+  fn:=FixFileName(s);
+  executable:=false;
+  data.Init;
+end;
+
+
+constructor TScript.InitExec(const s:string);
 begin
   fn:=FixFileName(s)+source_os.scriptext;
+  executable:=true;
   data.Init;
 end;
 
@@ -107,7 +124,8 @@ begin
    Writeln(t,data.Get);
   Close(t);
 {$ifdef linux}
-  ChMod(fn,493);
+  if executable then
+   ChMod(fn,493);
 {$endif}
 end;
 
@@ -118,7 +136,7 @@ end;
 
 Constructor TAsmScript.Init (Const ScriptName : String);
 begin
-  Inherited Init(ScriptName);
+  Inherited InitExec(ScriptName);
 end;
 
 
@@ -188,14 +206,39 @@ Begin
   Add('echo An error occured while linking %THEFILE%');
   Add(':end');
 {$endif}
-  TScript.WriteToDisk;
+  inherited WriteToDisk;
 end;
 
 
+{****************************************************************************
+                                  Link Response
+****************************************************************************}
+
+procedure TLinkRes.Add(const s:string);
+begin
+  if s<>'' then
+   inherited Add(s);
+end;
+
+procedure TLinkRes.AddFileName(const s:string);
+begin
+  if s<>'' then
+   begin
+     if not(s[1] in ['a'..'z','A'..'Z','/','\','.']) then
+      inherited Add('.'+DirSep+s)
+     else
+      inherited Add(s);
+   end;
+end;
+
 end.
 {
   $Log$
-  Revision 1.2  1998-05-04 17:54:29  peter
+  Revision 1.3  1999-10-21 14:29:37  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+  Revision 1.2  1998/05/04 17:54:29  peter
     + smartlinking works (only case jumptable left todo)
     * redesign of systems.pas to support assemblers and linkers
     + Unitname is now also in the PPU-file, increased version to 14

+ 9 - 224
compiler/systems.pas

@@ -96,20 +96,6 @@ unit systems;
          as_i386_dbg,as_i386_coff,as_i386_pecoff
        ];
 
-     type
-       tlink = (link_none
-            ,link_i386_ld,link_i386_ldgo32v1,
-            link_i386_ldgo32v2,link_i386_ldw,
-            link_i386_ldos2
-            ,link_m68k_ld,link_alpha_ld,link_powerpc_ld
-       );
-     const
-       {$ifdef i386} i386linkcnt=5; {$else} i386linkcnt=0; {$endif}
-       {$ifdef m68k} m68klinkcnt=1; {$else} m68klinkcnt=0; {$endif}
-       {$ifdef alpha} alphalinkcnt=1; {$else} alphalinkcnt=0; {$endif}
-       {$ifdef powerpc} powerpclinkcnt=1; {$else} powerpclinkcnt=0; {$endif}
-       linkcnt=i386linkcnt+m68klinkcnt+alphalinkcnt+powerpclinkcnt+1;
-
      type
        tar = (ar_none
             ,ar_i386_ar,ar_i386_arw
@@ -149,9 +135,9 @@ unit systems;
 
    type
        tosinfo = packed record
-          id    : tos;
-          name      : string[30];
-          shortname : string[8];
+          id           : tos;
+          name         : string[30];
+          shortname    : string[8];
           sharedlibext : string[10];
           staticlibext,
           sourceext,
@@ -171,7 +157,7 @@ unit systems;
        end;
 
        tasminfo = packed record
-          id      : tasm;
+          id          : tasm;
           idtxt       : string[8];
           asmbin      : string[8];
           asmcmd      : string[50];
@@ -183,24 +169,6 @@ unit systems;
           secnames    : array[tsection] of string[20];
        end;
 
-       tlinkinfo = packed record
-          id        : tlink;
-          linkbin       : string[8];
-          linkcmd       : string[127];
-          binders       : word;
-          bindbin       : array[1..2]of string[8];
-          bindcmd       : array[1..2]of string[127];
-          stripopt      : string[2];
-          stripbind     : boolean;     { Strip symbols in binder? }
-          libpathprefix : string[13];
-          libpathsuffix : string[2];
-          groupstart    : string[8];
-          groupend      : string[2];
-          inputstart    : string[8];
-          inputend      : string[2];
-          libprefix     : string[2];
-       end;
-
        tarinfo = packed record
           id      : tar;
           arbin   : string[8];
@@ -229,7 +197,6 @@ unit systems;
           resobjext,
           exeext      : string[4];
           os          : tos;
-          link        : tlink;
           assem       : tasm;
           assemsrc    : tasm; { default source writing assembler }
           ar          : tar;
@@ -249,7 +216,6 @@ unit systems;
        target_info : ttargetinfo;
        target_os   : tosinfo;
        target_asm  : tasminfo;
-       target_link : tlinkinfo;
        target_ar   : tarinfo;
        target_res  : tresinfo;
        target_path : string[12]; { for rtl/<X>/,fcl/<X>/, etc. }
@@ -257,7 +223,6 @@ unit systems;
 
     function set_target_os(t:tos):boolean;
     function set_target_asm(t:tasm):boolean;
-    function set_target_link(t:tlink):boolean;
     function set_target_ar(t:tar):boolean;
     function set_target_res(t:tres):boolean;
     function set_target_info(t:ttarget):boolean;
@@ -828,162 +793,6 @@ implementation
           );
 
 
-{****************************************************************************
-                            Linker Info
-****************************************************************************}
-
-       link_infos : array[1..linkcnt] of tlinkinfo = (
-          (
-            id      : link_none
-          )
-{$ifdef i386}
-          ,(
-            id      : link_i386_ld;
-            linkbin : 'ld';
-            linkcmd : '$OPT -o $EXE $RES';
-            binders : 0;
-            bindbin : ('','');
-            bindcmd : ('','');
-            stripopt   : '-s';
-            stripbind  : false;
-            libpathprefix : 'SEARCH_DIR(';
-            libpathsuffix : ')';
-            groupstart : 'GROUP(';
-            groupend   : ')';
-            inputstart : 'INPUT(';
-            inputend   : ')';
-            libprefix  : '-l'
-          )
-          ,(
-            id      : link_i386_ldgo32v1;
-            linkbin : 'ld';
-            linkcmd : '-oformat coff-go32 $OPT -o $EXE @$RES';
-            binders : 1;
-            bindbin : ('aout2exe','');
-            bindcmd : ('$EXE','');
-            stripopt   : '-s';
-            stripbind  : false;
-            libpathprefix : '-L';
-            libpathsuffix : '';
-            groupstart : '-(';
-            groupend   : '-)';
-            inputstart : '';
-            inputend   : '';
-            libprefix  : '-l'
-          )
-          ,(
-            id      : link_i386_ldgo32v2;
-            linkbin : 'ld';
-            linkcmd : '-oformat coff-go32-exe $OPT -o $EXE @$RES';
-            binders:0;
-            bindbin : ('','');
-            bindcmd : ('','');
-            stripopt   : '-s';
-            stripbind  : false;
-            libpathprefix : '-L';
-            libpathsuffix : '';
-            groupstart : '-(';
-            groupend   : '-)';
-            inputstart : '';
-            inputend   : '';
-            libprefix  : '-l'
-          )
-          ,(
-            id      : link_i386_ldw;
-            linkbin : 'ldw';
-            linkcmd : '$OPT -o $EXE $RES';
-            binders : 0;
-            bindbin : ('dlltool','ldw');
-            bindcmd : ('--as asw.exe --dllname $EXE --output-exp exp.$$$',
-                       '$OPT -o $EXE $RES exp.$$$');
-            stripopt   : '-s';
-            stripbind  : false;
-            libpathprefix : 'SEARCH_DIR(';
-            libpathsuffix : ')';
-            groupstart : 'GROUP(';
-            groupend   : ')';
-            inputstart : 'INPUT(';
-            inputend   : ')';
-            libprefix  : '-l'
-          )
-          ,(
-            id      : link_i386_ldos2;
-            linkbin : 'ld';  { Os/2 }
-            linkcmd : '-o $EXE @$RES';
-            binders : 1;
-            bindbin : ('emxbind','');
-            bindcmd : ('-b $STRIP$PM -k$STACKKB -h$HEAPMB -o $EXE.exe $EXE -aim -s$DOSHEAPKB',
-                       '');
-            stripopt   : '-s';
-            stripbind  : true;
-            libpathprefix : '-L';
-            libpathsuffix : '';
-            groupstart : ''; {Linker is too primitive...}
-            groupend   : '';
-            inputstart : '';
-            inputend   : '';
-            libprefix  : '-l'
-          )
-{$endif i386}
-{$ifdef m68k}
-          ,(
-            id      : link_m68k_ld;
-            linkbin : 'ld';
-            linkcmd : '$OPT -o $EXE $RES';
-            binders:0;
-            bindbin : ('','');
-            bindcmd : ('','');
-            stripopt   : '-s';
-            stripbind  : false;
-            libpathprefix : 'SEARCH_DIR(';
-            libpathsuffix : ')';
-            groupstart : 'GROUP(';
-            groupend   : ')';
-            inputstart : 'INPUT(';
-            inputend   : ')';
-            libprefix  : '-l'
-          )
-{$endif m68k}
-{$ifdef alpha}
-          ,(
-            id      : link_alpha_ld;
-            linkbin : 'ld';
-            linkcmd : '$OPT -o $EXE $RES';
-            binders : 0;
-            bindbin : ('','');
-            bindcmd : ('','');
-            stripopt   : '-s';
-            stripbind  : false;
-            libpathprefix : 'SEARCH_DIR(';
-            libpathsuffix : ')';
-            groupstart : 'GROUP(';
-            groupend   : ')';
-            inputstart : 'INPUT(';
-            inputend   : ')';
-            libprefix  : '-l'
-          )
-{$endif}
-{$ifdef powerpc}
-          ,(
-            id      : link_powerpc_ld;
-            linkbin : 'ld';
-            linkcmd : '$OPT -o $EXE $RES';
-            binders : 0;
-            bindbin : ('','');
-            bindcmd : ('','');
-            stripopt   : '-s';
-            stripbind  : false;
-            libpathprefix : 'SEARCH_DIR(';
-            libpathsuffix : ')';
-            groupstart : 'GROUP(';
-            groupend   : ')';
-            inputstart : 'INPUT(';
-            inputend   : ')';
-            libprefix  : '-l'
-          )
-{$endif}
-          );
-
 {****************************************************************************
                                  Ar Info
 ****************************************************************************}
@@ -1071,7 +880,6 @@ implementation
             resobjext   : '.o1r';
             exeext      : ''; { The linker produces a.out }
             os          : os_i386_GO32V1;
-            link        : link_i386_ldgo32v1;
             assem       : as_i386_as;
             assemsrc    : as_i386_as;
             ar          : ar_i386_ar;
@@ -1096,7 +904,6 @@ implementation
             resobjext   : '.or';
             exeext      : '.exe';
             os          : os_i386_GO32V2;
-            link        : link_i386_ldgo32v2;
             assem       : as_i386_coff;
             assemsrc    : as_i386_as;
             ar          : ar_i386_ar;
@@ -1121,7 +928,6 @@ implementation
             resobjext   : '.or';
             exeext      : '';
             os          : os_i386_Linux;
-            link        : link_i386_ld;
             assem       : as_i386_as;
             assemsrc    : as_i386_as;
             ar          : ar_i386_ar;
@@ -1146,7 +952,6 @@ implementation
             resobjext   : '.oor';
             exeext      : ''; { The linker produces a.out }
             os          : os_i386_OS2;
-            link        : link_i386_ldos2;
             assem       : as_i386_as_aout;
             assemsrc    : as_i386_as_aout;
             ar          : ar_i386_ar;
@@ -1171,7 +976,6 @@ implementation
             resobjext   : '.owr';
             exeext      : '.exe';
             os          : os_i386_Win32;
-            link        : link_i386_ldw;
             assem       : as_i386_pecoff;
             assemsrc    : as_i386_asw;
             ar          : ar_i386_arw;
@@ -1198,7 +1002,6 @@ implementation
             resobjext   : '.or';
             exeext      : '';
             os          : os_m68k_Amiga;
-            link        : link_m68k_ld;
             assem       : as_m68k_as;
             assemsrc    : as_m68k_as;
             ar          : ar_m68k_ar;
@@ -1223,7 +1026,6 @@ implementation
             resobjext   : '.or';
             exeext      : '.ttp';
             os          : os_m68k_Atari;
-            link        : link_m68k_ld;
             assem       : as_m68k_as;
             assemsrc    : as_m68k_as;
             ar          : ar_m68k_ar;
@@ -1248,7 +1050,6 @@ implementation
             resobjext   : '.or';
             exeext      : '';
             os          : os_m68k_Mac;
-            link        : link_m68k_ld;
             assem       : as_m68k_mpw;
             assemsrc    : as_m68k_mpw;
             ar          : ar_m68k_ar;
@@ -1273,7 +1074,6 @@ implementation
             resobjext   : '.or';
             exeext      : '';
             os          : os_m68k_Linux;
-            link        : link_m68k_ld;
             assem       : as_m68k_as;
             assemsrc    : as_m68k_as;
             ar          : ar_m68k_ar;
@@ -1298,7 +1098,6 @@ implementation
             resobjext   : '.or';
             exeext      : '';
             os          : os_m68k_PalmOS;
-            link        : link_m68k_ld;
             assem       : as_m68k_as;
             assemsrc    : as_m68k_as;
             ar          : ar_m68k_ar;
@@ -1325,7 +1124,6 @@ implementation
             resobjext   : '.or';
             exeext      : '';
             os          : os_alpha_Linux;
-            link        : link_alpha_ld;
             assem       : as_alpha_as;
             assemsrc    : as_alpha_as;
             ar          : ar_alpha_ar;
@@ -1352,7 +1150,6 @@ implementation
             resobjext   : '.or';
             exeext      : '';
             os          : os_powerpc_Linux;
-            link        : link_powerpc_ld;
             assem       : as_powerpc_as;
             assemsrc    : as_powerpc_as;
             ar          : ar_powerpc_ar;
@@ -1482,21 +1279,6 @@ begin
 end;
 
 
-function set_target_link(t:tlink):boolean;
-var
-  i : longint;
-begin
-  set_target_link:=false;
-  for i:=1 to linkcnt do
-   if link_infos[i].id=t then
-    begin
-      target_link:=link_infos[i];
-      set_target_link:=true;
-      exit;
-    end;
-end;
-
-
 function set_target_ar(t:tar):boolean;
 var
   i : longint;
@@ -1538,7 +1320,6 @@ begin
       target_info:=target_infos[i];
       set_target_os(target_info.os);
       set_target_asm(target_info.assem);
-      set_target_link(target_info.link);
       set_target_ar(target_info.ar);
       set_target_res(target_info.res);
       target_path:=lower(target_info.short_name);
@@ -1734,7 +1515,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.94  1999-09-15 22:09:27  florian
+  Revision 1.95  1999-10-21 14:29:37  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+  Revision 1.94  1999/09/15 22:09:27  florian
     + rtti is now automatically generated for published classes, i.e.
       they are handled like an implicit property
 

+ 194 - 0
compiler/t_go32v1.pas

@@ -0,0 +1,194 @@
+{
+    $Id$
+    Copyright (c) 1999 by Peter Vreman
+
+    This unit implements support import,export,link routines
+    for the (i386) go32v1 target
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_go32v1;
+
+  interface
+  uses
+    link;
+
+  type
+    plinkergo32v1=^tlinkergo32v1;
+    tlinkergo32v1=object(tlinker)
+    private
+       Function  WriteResponseFile(isdll:boolean) : Boolean;
+    public
+       constructor Init;
+       procedure SetDefaultInfo;virtual;
+       function  MakeExecutable:boolean;virtual;
+    end;
+
+
+  implementation
+
+    uses
+       globtype,globals,cobjects,systems,verbose,script,files;
+
+
+{****************************************************************************
+                               TLinkergo32v1
+****************************************************************************}
+
+Constructor TLinkergo32v1.Init;
+begin
+  Inherited Init;
+  { allow duplicated libs (PM) }
+  SharedLibFiles.doubles:=true;
+  StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkergo32v1.SetDefaultInfo;
+begin
+  with Info do
+   begin
+     ExeCmd[1]:='ld -oformat coff-go32 $OPT $STRIP -o $EXE @$RES';
+     ExeCmd[2]:='aout2exe $EXE';
+   end;
+end;
+
+
+Function TLinkergo32v1.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+  linkres  : TLinkRes;
+  i        : longint;
+  s,s2     : string;
+  linklibc : boolean;
+begin
+  WriteResponseFile:=False;
+
+  { Open link.res file }
+  LinkRes.Init(Info.ResName);
+
+  { Write path to search libraries }
+  if assigned(current_module^.locallibrarysearchpath) then
+   begin
+     S:=current_module^.locallibrarysearchpath^;
+     while s<>'' do
+      begin
+        s2:=GetPathFromList(s);
+        LinkRes.Add('-L'+s2);
+      end;
+   end;
+  S:=LibrarySearchPath;
+  while s<>'' do
+   begin
+     s2:=GetPathFromList(s);
+     LinkRes.Add('-L'+s2);
+   end;
+
+  { add objectfiles, start with prt0 always }
+  LinkRes.AddFileName(FindObjectFile('prt0'));
+  while not ObjectFiles.Empty do
+   begin
+     s:=ObjectFiles.Get;
+     if s<>'' then
+      LinkRes.AddFileName(s);
+   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) }
+  While not SharedLibFiles.Empty do
+   begin
+     S:=SharedLibFiles.Get;
+     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&libgcc is the last lib }
+  if linklibc then
+   begin
+     LinkRes.Add('-lc');
+     LinkRes.Add('-lgcc');
+   end;
+
+  { Write staticlibraries }
+  if not StaticLibFiles.Empty then
+   begin
+     LinkRes.Add('-(');
+     While not StaticLibFiles.Empty do
+      begin
+        S:=StaticLibFiles.Get;
+        LinkRes.AddFileName(s)
+      end;
+     LinkRes.Add('-)');
+   end;
+
+{ Write and Close response }
+  linkres.writetodisk;
+  linkres.done;
+
+  WriteResponseFile:=True;
+end;
+
+
+function TLinkergo32v1.MakeExecutable:boolean;
+var
+  binstr,
+  cmdstr  : string;
+  success : boolean;
+  StripStr : string[40];
+begin
+  if not(cs_link_extern in aktglobalswitches) then
+   Message1(exec_i_linking,current_module^.exefilename^);
+
+{ Create some replacements }
+  StripStr:='';
+  if (cs_link_strip in aktglobalswitches) then
+   StripStr:='-s';
+
+{ Write used files and libraries }
+  WriteResponseFile(false);
+
+{ Call linker }
+  SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+  Replace(cmdstr,'$EXE',current_module^.exefilename^);
+  Replace(cmdstr,'$OPT',Info.ExtraOptions);
+  Replace(cmdstr,'$RES',current_module^.outpath^+Info.ResName);
+  Replace(cmdstr,'$STRIP',StripStr);
+  success:=DoExec(FindUtil(BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+  if (success) and not(cs_link_extern in aktglobalswitches) then
+   RemoveFile(current_module^.outpath^+Info.ResName);
+
+  MakeExecutable:=success;   { otherwise a recursive call to link method }
+end;
+
+end.
+{
+  $Log$
+  Revision 1.1  1999-10-21 14:29:38  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+}

+ 296 - 0
compiler/t_go32v2.pas

@@ -0,0 +1,296 @@
+{
+    $Id$
+    Copyright (c) 1999 by Peter Vreman
+
+    This unit implements support import,export,link routines
+    for the (i386) Go32v2 target
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_go32v2;
+
+  interface
+  uses
+    link;
+
+  type
+    plinkergo32v2=^tlinkergo32v2;
+    tlinkergo32v2=object(tlinker)
+    private
+       Function  WriteResponseFile(isdll:boolean) : Boolean;
+    public
+       constructor Init;
+       procedure SetDefaultInfo;virtual;
+       function  MakeExecutable:boolean;virtual;
+    end;
+
+
+  implementation
+
+    uses
+       strings,globtype,globals,cobjects,systems,verbose,script,files;
+
+
+{****************************************************************************
+                               TLinkerGo32v2
+****************************************************************************}
+
+Constructor TLinkerGo32v2.Init;
+begin
+  Inherited Init;
+  { allow duplicated libs (PM) }
+  SharedLibFiles.doubles:=true;
+  StaticLibFiles.doubles:=true;
+end;
+
+
+procedure TLinkerGo32v2.SetDefaultInfo;
+begin
+  with Info do
+   begin
+     ExeCmd[1]:='ld -oformat coff-go32-exe $OPT $STRIP -o $EXE @$RES';
+   end;
+end;
+
+
+Function TLinkerGo32v2.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+  linkres  : TLinkRes;
+  i        : longint;
+  s,s2     : string;
+  linklibc : boolean;
+begin
+  WriteResponseFile:=False;
+
+  { Open link.res file }
+  LinkRes.Init(Info.ResName);
+
+  { Write path to search libraries }
+  if assigned(current_module^.locallibrarysearchpath) then
+   begin
+     S:=current_module^.locallibrarysearchpath^;
+     while s<>'' do
+      begin
+        s2:=GetPathFromList(s);
+        LinkRes.Add('-L'+s2);
+      end;
+   end;
+  S:=LibrarySearchPath;
+  while s<>'' do
+   begin
+     s2:=GetPathFromList(s);
+     LinkRes.Add('-L'+s2);
+   end;
+
+  { add objectfiles, start with prt0 always }
+  LinkRes.AddFileName(FindObjectFile('prt0'));
+  while not ObjectFiles.Empty do
+   begin
+     s:=ObjectFiles.Get;
+     if s<>'' then
+      LinkRes.AddFileName(s);
+   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) }
+  While not SharedLibFiles.Empty do
+   begin
+     S:=SharedLibFiles.Get;
+     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&libgcc is the last lib }
+  if linklibc then
+   begin
+     LinkRes.Add('-lc');
+     LinkRes.Add('-lgcc');
+   end;
+
+  { Write staticlibraries }
+  if not StaticLibFiles.Empty then
+   begin
+     LinkRes.Add('-(');
+     While not StaticLibFiles.Empty do
+      begin
+        S:=StaticLibFiles.Get;
+        LinkRes.AddFileName(s)
+      end;
+     LinkRes.Add('-)');
+   end;
+
+{ Write and Close response }
+  linkres.writetodisk;
+  linkres.done;
+
+  WriteResponseFile:=True;
+end;
+
+
+function TLinkerGo32v2.MakeExecutable:boolean;
+var
+  binstr,
+  cmdstr  : string;
+  success : boolean;
+  StripStr : string[40];
+begin
+  if not(cs_link_extern in aktglobalswitches) then
+   Message1(exec_i_linking,current_module^.exefilename^);
+
+{ Create some replacements }
+  StripStr:='';
+  if (cs_link_strip in aktglobalswitches) then
+   StripStr:='-s';
+
+{ Write used files and libraries }
+  WriteResponseFile(false);
+
+{ Call linker }
+  SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+  Replace(cmdstr,'$EXE',current_module^.exefilename^);
+  Replace(cmdstr,'$OPT',Info.ExtraOptions);
+  Replace(cmdstr,'$RES',current_module^.outpath^+Info.ResName);
+  Replace(cmdstr,'$STRIP',StripStr);
+  success:=DoExec(FindUtil(BinStr),cmdstr,true,false);
+
+{ Remove ReponseFile }
+  if (success) and not(cs_link_extern in aktglobalswitches) then
+   RemoveFile(current_module^.outpath^+Info.ResName);
+
+  MakeExecutable:=success;   { otherwise a recursive call to link method }
+end;
+
+
+{$ifdef notnecessary}
+procedure tlinkergo32v2.postprocessexecutable(const n : string);
+type
+  tcoffheader=packed record
+    mach   : word;
+    nsects : word;
+    time   : longint;
+    sympos : longint;
+    syms   : longint;
+    opthdr : word;
+    flag   : word;
+  end;
+  tcoffsechdr=packed record
+    name     : array[0..7] of char;
+    vsize    : longint;
+    rvaofs   : longint;
+    datalen  : longint;
+    datapos  : longint;
+    relocpos : longint;
+    lineno1  : longint;
+    nrelocs  : word;
+    lineno2  : word;
+    flags    : longint;
+  end;
+  psecfill=^tsecfill;
+  tsecfill=record
+    fillpos,
+    fillsize : longint;
+    next : psecfill;
+  end;
+var
+  f : file;
+  coffheader : tcoffheader;
+  firstsecpos,
+  maxfillsize,
+  l : longint;
+  coffsec : tcoffsechdr;
+  secroot,hsecroot : psecfill;
+  zerobuf : pointer;
+begin
+  { when -s is used quit, because there is no .exe }
+  if cs_link_extern in aktglobalswitches then
+   exit;
+  { open file }
+  assign(f,n);
+  {$I-}
+   reset(f,1);
+  if ioresult<>0 then
+    Message1(execinfo_f_cant_open_executable,n);
+  { read headers }
+  seek(f,2048);
+  blockread(f,coffheader,sizeof(tcoffheader));
+  { read section info }
+  maxfillsize:=0;
+  firstsecpos:=0;
+  secroot:=nil;
+  for l:=1to coffheader.nSects do
+   begin
+     blockread(f,coffsec,sizeof(tcoffsechdr));
+     if coffsec.datapos>0 then
+      begin
+        if secroot=nil then
+         firstsecpos:=coffsec.datapos;
+        new(hsecroot);
+        hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
+        hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
+        hsecroot^.next:=secroot;
+        secroot:=hsecroot;
+        if secroot^.fillsize>maxfillsize then
+         maxfillsize:=secroot^.fillsize;
+      end;
+   end;
+  if firstsecpos>0 then
+   begin
+     l:=firstsecpos-filepos(f);
+     if l>maxfillsize then
+      maxfillsize:=l;
+   end
+  else
+   l:=0;
+  { get zero buffer }
+  getmem(zerobuf,maxfillsize);
+  fillchar(zerobuf^,maxfillsize,0);
+  { zero from sectioninfo until first section }
+  blockwrite(f,zerobuf^,l);
+  { zero section alignments }
+  while assigned(secroot) do
+   begin
+     seek(f,secroot^.fillpos);
+     blockwrite(f,zerobuf^,secroot^.fillsize);
+     hsecroot:=secroot;
+     secroot:=secroot^.next;
+     dispose(hsecroot);
+   end;
+  freemem(zerobuf,maxfillsize);
+  close(f);
+  {$I+}
+  i:=ioresult;
+  postprocessexecutable:=true;
+end;
+{$endif}
+
+end.
+{
+  $Log$
+  Revision 1.1  1999-10-21 14:29:38  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+}

+ 441 - 0
compiler/t_linux.pas

@@ -0,0 +1,441 @@
+{
+    $Id$
+    Copyright (c) 1999 by Peter Vreman
+
+    This unit implements support import,export,link routines
+    for the (i386) Linux target
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit t_linux;
+interface
+
+  uses
+    import,export,link;
+
+  type
+    pimportliblinux=^timportliblinux;
+    timportliblinux=object(timportlib)
+      procedure preparelib(const s:string);virtual;
+      procedure importprocedure(const func,module:string;index:longint;const name:string);virtual;
+      procedure importvariable(const varname,module:string;const name:string);virtual;
+      procedure generatelib;virtual;
+    end;
+
+    pexportliblinux=^texportliblinux;
+    texportliblinux=object(texportlib)
+      procedure preparelib(const s : string);virtual;
+      procedure exportprocedure(hp : pexported_item);virtual;
+      procedure exportvar(hp : pexported_item);virtual;
+      procedure generatelib;virtual;
+    end;
+
+    plinkerlinux=^tlinkerlinux;
+    tlinkerlinux=object(tlinker)
+    private
+      Glibc2,
+      Glibc21 : boolean;
+      Function  WriteResponseFile(isdll:boolean) : Boolean;
+    public
+      constructor Init;
+      procedure SetDefaultInfo;virtual;
+      function  MakeExecutable:boolean;virtual;
+      function  MakeSharedLibrary:boolean;virtual;
+    end;
+
+
+implementation
+
+  uses
+    verbose,strings,cobjects,systems,globtype,globals,
+    symconst,script,
+    files,aasm,cpuasm,cpubase,symtable;
+
+{*****************************************************************************
+                               TIMPORTLIBLINUX
+*****************************************************************************}
+
+procedure timportliblinux.preparelib(const s : string);
+begin
+end;
+
+
+procedure timportliblinux.importprocedure(const func,module : string;index : longint;const name : string);
+begin
+  { insert sharedlibrary }
+  current_module^.linkothersharedlibs.insert(SplitName(module),link_allways);
+  { do nothing with the procedure, only set the mangledname }
+  if name<>'' then
+    aktprocsym^.definition^.setmangledname(name)
+  else
+    Message(parser_e_empty_import_name);
+end;
+
+
+procedure timportliblinux.importvariable(const varname,module:string;const name:string);
+begin
+  { insert sharedlibrary }
+  current_module^.linkothersharedlibs.insert(SplitName(module),link_allways);
+  { reset the mangledname and turn off the dll_var option }
+  aktvarsym^.setmangledname(name);
+{$ifdef INCLUDEOK}
+  exclude(aktvarsym^.varoptions,vo_is_dll_var);
+{$else}
+  aktvarsym^.varoptions:=aktvarsym^.varoptions-[vo_is_dll_var];
+{$endif}
+end;
+
+
+procedure timportliblinux.generatelib;
+begin
+end;
+
+
+{*****************************************************************************
+                               TEXPORTLIBLINUX
+*****************************************************************************}
+
+procedure texportliblinux.preparelib(const s:string);
+begin
+end;
+
+
+procedure texportliblinux.exportprocedure(hp : pexported_item);
+var
+  hp2 : pexported_item;
+begin
+  { first test the index value }
+  if (hp^.options and eo_index)<>0 then
+   begin
+     Comment(V_Error,'can''t export with index under linux');
+     exit;
+   end;
+  { use pascal name is none specified }
+  if (hp^.options and eo_name)=0 then
+    begin
+       hp^.name:=stringdup(hp^.sym^.name);
+       hp^.options:=hp^.options or eo_name;
+    end;
+  { now place in correct order }
+  hp2:=pexported_item(current_module^._exports^.first);
+  while assigned(hp2) and
+     (hp^.name^>hp2^.name^) do
+    hp2:=pexported_item(hp2^.next);
+  { insert hp there !! }
+  if assigned(hp2) and (hp2^.name^=hp^.name^) then
+    begin
+      { this is not allowed !! }
+      Message1(parser_e_export_name_double,hp^.name^);
+      exit;
+    end;
+  if hp2=pexported_item(current_module^._exports^.first) then
+    current_module^._exports^.insert(hp)
+  else if assigned(hp2) then
+    begin
+       hp^.next:=hp2;
+       hp^.previous:=hp2^.previous;
+       if assigned(hp2^.previous) then
+         hp2^.previous^.next:=hp;
+       hp2^.previous:=hp;
+    end
+  else
+    current_module^._exports^.concat(hp);
+end;
+
+
+procedure texportliblinux.exportvar(hp : pexported_item);
+begin
+  hp^.is_var:=true;
+  exportprocedure(hp);
+end;
+
+
+procedure texportliblinux.generatelib;
+var
+  hp2 : pexported_item;
+begin
+  hp2:=pexported_item(current_module^._exports^.first);
+  while assigned(hp2) do
+   begin
+     if not hp2^.is_var then
+      begin
+        { place jump in codesegment }
+        codesegment^.concat(new(pai_align,init_op(4,$90)));
+        codesegment^.concat(new(pai_symbol,initname_global(hp2^.name^,0)));
+        codesegment^.concat(new(paicpu,op_sym(A_JMP,S_NO,newasmsymbol(hp2^.sym^.mangledname))));
+        codesegment^.concat(new(pai_symbol_end,initname(hp2^.name^)));
+      end
+     else
+      Comment(V_Error,'Exporting of variables is not supported under linux');
+     hp2:=pexported_item(hp2^.next);
+   end;
+end;
+
+
+{*****************************************************************************
+                                  TLINKERLINUX
+*****************************************************************************}
+
+Constructor TLinkerLinux.Init;
+begin
+  Inherited Init;
+  AddPathToList(LibrarySearchPath,'/lib;/usr/lib;/usr/X11R6/lib',true);
+end;
+
+
+procedure TLinkerLinux.SetDefaultInfo;
+{
+  This will also detect which libc version will be used
+}
+begin
+  Glibc2:=false;
+  Glibc21:=false;
+  with Info do
+   begin
+     ExeCmd[1]:='ld $OPT $DYNLINK $STRIP -L. -o $EXE $RES';
+     DllCmd[1]:='ld $OPT -shared -L. -o $EXE $RES';
+     DllCmd[2]:='strip --strip-unneeded $EXE';
+     { first try glibc2 }
+     DynamicLinker:='/lib/ld-linux.so.2';
+     if FileExists(DynamicLinker) then
+      begin
+        Glibc2:=true;
+        { also glibc 2.1 / 2.1.1 / 2.1.2 ? }
+        if FileExists('/lib/ld-2.1.so') or
+           FileExists('/lib/ld-2.1.1.so') or
+           FileExists('/lib/ld-2.1.2.so') then
+         Glibc21:=true;
+      end
+     else
+      DynamicLinker:='/lib/ld-linux.so.1';
+   end;
+end;
+
+
+Function TLinkerLinux.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+  linkres      : TLinkRes;
+  i            : longint;
+  cprtobj,
+  gprtobj,
+  prtobj       : string[80];
+  s,s2         : string;
+  found,
+  linkdynamic,
+  linklibc     : boolean;
+begin
+  WriteResponseFile:=False;
+{ set special options for some targets }
+  linkdynamic:=not(SharedLibFiles.empty);
+  linklibc:=SharedLibFiles.Find('c');
+  prtobj:='prt0';
+  cprtobj:='cprt0';
+  gprtobj:='gprt0';
+  if glibc21 then
+   begin
+     cprtobj:='cprt21';
+     gprtobj:='gprt21';
+   end;
+  if cs_profile in aktmoduleswitches then
+   begin
+     prtobj:=gprtobj;
+     if not glibc2 then
+      AddSharedLibrary('gmon');
+     AddSharedLibrary('c');
+     linklibc:=true;
+   end
+  else
+   begin
+     if linklibc then
+      prtobj:=cprtobj;
+   end;
+
+  { Open link.res file }
+  LinkRes.Init(Info.ResName);
+
+  { Write path to search libraries }
+  if assigned(current_module^.locallibrarysearchpath) then
+   begin
+     S:=current_module^.locallibrarysearchpath^;
+     while s<>'' do
+      begin
+        s2:=GetPathFromList(s);
+        LinkRes.Add('SEARCH_DIR('+s2+')');
+      end;
+   end;
+  S:=LibrarySearchPath;
+  while s<>'' do
+   begin
+     s2:=GetPathFromList(s);
+     LinkRes.Add('SEARCH_DIR('+s2+')');
+   end;
+
+  LinkRes.Add('INPUT(');
+  { add objectfiles, start with prt0 always }
+  if prtobj<>'' then
+   LinkRes.AddFileName(FindObjectFile(prtobj));
+  { try to add crti and crtbegin, they are normally not required, but
+    adding can sometimes be usefull }
+  s:=search('crtbegin.o',librarysearchpath,found)+'crtbegin.o';
+  if found then
+   LinkRes.AddFileName(s);
+  s:=search('crti.o',librarysearchpath,found)+'crti.o';
+  if found then
+   LinkRes.AddFileName(s);
+  { main objectfiles }
+  while not ObjectFiles.Empty do
+   begin
+     s:=ObjectFiles.Get;
+     if s<>'' then
+      LinkRes.AddFileName(s);
+   end;
+  { objects which must be at the end }
+  s:=search('crtend.o',librarysearchpath,found)+'crtend.o';
+  if found then
+   LinkRes.AddFileName(s);
+  s:=search('crtn.o',librarysearchpath,found)+'crtn.o';
+  if found then
+   LinkRes.AddFileName(s);
+
+  { 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) }
+  While not SharedLibFiles.Empty do
+   begin
+     S:=SharedLibFiles.Get;
+     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
+        linklibc:=true;
+        linkdynamic:=false; { libc will include the ld-linux for us }
+      end;
+   end;
+  { be sure that libc is the last lib }
+  if linklibc then
+   LinkRes.Add('-lc');
+  if linkdynamic and (Info.DynamicLinker<>'') then
+   LinkRes.AddFileName(Info.DynamicLinker);
+  LinkRes.Add(')');
+
+  { Write staticlibraries }
+  if not StaticLibFiles.Empty then
+   begin
+     LinkRes.Add('GROUP(');
+     While not StaticLibFiles.Empty do
+      begin
+        S:=StaticLibFiles.Get;
+        LinkRes.AddFileName(s)
+      end;
+     LinkRes.Add(')');
+   end;
+
+{ Write and Close response }
+  linkres.writetodisk;
+  linkres.done;
+
+  WriteResponseFile:=True;
+end;
+
+
+function TLinkerLinux.MakeExecutable:boolean;
+var
+  binstr,
+  cmdstr  : string;
+  success : boolean;
+  DynLinkStr : string[60];
+  StripStr   : string[40];
+begin
+  if not(cs_link_extern in aktglobalswitches) then
+   Message1(exec_i_linking,current_module^.exefilename^);
+
+{ Create some replacements }
+  StripStr:='';
+  DynLinkStr:='';
+  if (cs_link_strip in aktglobalswitches) then
+   StripStr:='-s';
+  If (Info.DynamicLinker<>'') and (not SharedLibFiles.Empty) then
+   DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
+
+{ Write used files and libraries }
+  WriteResponseFile(false);
+
+{ Call linker }
+  SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
+  Replace(cmdstr,'$EXE',current_module^.exefilename^);
+  Replace(cmdstr,'$OPT',Info.ExtraOptions);
+  Replace(cmdstr,'$RES',current_module^.outpath^+Info.ResName);
+  Replace(cmdstr,'$STRIP',StripStr);
+  Replace(cmdstr,'$DYNLINK',DynLinkStr);
+  success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
+
+{ Remove ReponseFile }
+  if (success) and not(cs_link_extern in aktglobalswitches) then
+   RemoveFile(current_module^.outpath^+Info.ResName);
+
+  MakeExecutable:=success;   { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerLinux.MakeSharedLibrary:boolean;
+var
+  binstr,
+  cmdstr  : string;
+  success : boolean;
+begin
+  MakeSharedLibrary:=false;
+  if not(cs_link_extern in aktglobalswitches) then
+   Message1(exec_i_linking,current_module^.sharedlibfilename^);
+
+{ Write used files and libraries }
+  WriteResponseFile(true);
+
+{ Call linker }
+  SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
+  Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
+  Replace(cmdstr,'$OPT',Info.ExtraOptions);
+  Replace(cmdstr,'$RES',current_module^.outpath^+Info.ResName);
+  success:=DoExec(FindUtil(binstr),cmdstr,true,false);
+
+{ Strip the library ? }
+  if success and (cs_link_strip in aktglobalswitches) then
+   begin
+     SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
+     Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
+     success:=DoExec(FindUtil(binstr),cmdstr,true,false);
+   end;
+
+{ Remove ReponseFile }
+  if (success) and not(cs_link_extern in aktglobalswitches) then
+   RemoveFile(current_module^.outpath^+Info.ResName);
+
+  MakeSharedLibrary:=success;   { otherwise a recursive call to link method }
+end;
+
+
+end.
+{
+  $Log$
+  Revision 1.1  1999-10-21 14:29:38  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
+
+}

+ 157 - 39
compiler/os2_targ.pas → compiler/t_os2.pas

@@ -28,10 +28,11 @@
    port, please send questions to Daniel Mantione
    <[email protected]>.
 }
-unit os2_targ;
+unit t_os2;
 
 interface
-uses import;
+uses
+  import,link;
 
 type
   pimportlibos2=^timportlibos2;
@@ -41,6 +42,17 @@ type
     procedure generatelib;virtual;
   end;
 
+    plinkeros2=^tlinkeros2;
+    tlinkeros2=object(tlinker)
+    private
+       Function  WriteResponseFile(isdll:boolean) : Boolean;
+    public
+       constructor Init;
+       procedure SetDefaultInfo;virtual;
+       function  MakeExecutable:boolean;virtual;
+    end;
+
+
 {***************************************************************************}
 
 {***************************************************************************}
@@ -53,8 +65,8 @@ implementation
 {$else Delphi}
      dos,
 {$endif Delphi}
-     globtype,strings,comphook,
-     globals,link,files;
+     globtype,strings,comphook,systems,
+     globals,verbose,files,script;
 
 const   profile_flag:boolean=false;
 
@@ -331,49 +343,155 @@ begin
 end;
 
 
+{****************************************************************************
+                               TLinkeros2
+****************************************************************************}
 
-end.
-
-{
-  $Log$
-  Revision 1.11  1999-09-20 16:38:59  peter
-    * cs_create_smart instead of cs_smartlink
-    * -CX is create smartlink
-    * -CD is create dynamic, but does nothing atm.
-
-  Revision 1.10  1999/09/07 15:05:19  pierre
-  * use do_halt instead of runerror
+Constructor TLinkeros2.Init;
+begin
+  Inherited Init;
+  { allow duplicated libs (PM) }
+  SharedLibFiles.doubles:=true;
+  StaticLibFiles.doubles:=true;
+end;
 
-  Revision 1.9  1999/07/18 10:19:58  florian
-    * made it compilable with Dlephi 4 again
-    + fixed problem with large stack allocations on win32
 
-  Revision 1.8  1999/07/03 00:29:55  peter
-    * new link writing to the ppu, one .ppu is needed for all link types,
-      static (.o) is now always created also when smartlinking is used
+procedure TLinkeros2.SetDefaultInfo;
+begin
+  with Info do
+   begin
+     ExeCmd[1]:='ld -o $EXE @$RES';
+     ExeCmd[2]:='emxbind -b $STRIP$PM -k$STACKKB -h$HEAPMB -o $EXE.exe $EXE -aim -s$DOSHEAPKB';
+   end;
+end;
 
-  Revision 1.7  1999/05/04 21:44:52  florian
-    * changes to compile it with Delphi 4.0
 
-  Revision 1.6  1998/12/11 00:03:25  peter
-    + globtype,tokens,version unit splitted from globals
+Function TLinkeros2.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+  linkres  : TLinkRes;
+  i        : longint;
+  s,s2     : string;
+begin
+  WriteResponseFile:=False;
+
+  { Open link.res file }
+  LinkRes.Init(Info.ResName);
+
+  { Write path to search libraries }
+  if assigned(current_module^.locallibrarysearchpath) then
+   begin
+     S:=current_module^.locallibrarysearchpath^;
+     while s<>'' do
+      begin
+        s2:=GetPathFromList(s);
+        LinkRes.Add('-L'+s2);
+      end;
+   end;
+  S:=LibrarySearchPath;
+  while s<>'' do
+   begin
+     s2:=GetPathFromList(s);
+     LinkRes.Add('-L'+s2);
+   end;
+
+  { add objectfiles, start with prt0 always }
+  LinkRes.AddFileName(FindObjectFile('prt0'));
+  while not ObjectFiles.Empty do
+   begin
+     s:=ObjectFiles.Get;
+     if s<>'' then
+      LinkRes.AddFileName(s);
+   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) }
+  While not SharedLibFiles.Empty do
+   begin
+     S:=SharedLibFiles.Get;
+     i:=Pos(target_os.sharedlibext,S);
+     if i>0 then
+      Delete(S,i,255);
+     LinkRes.Add('-l'+s);
+   end;
+
+  { Write staticlibraries }
+  if not StaticLibFiles.Empty then
+   begin
+     While not StaticLibFiles.Empty do
+      begin
+        S:=StaticLibFiles.Get;
+        LinkRes.AddFileName(s)
+      end;
+   end;
+
+{ Write and Close response }
+  linkres.writetodisk;
+  linkres.done;
+
+  WriteResponseFile:=True;
+end;
 
-  Revision 1.5  1998/10/16 14:20:53  daniel
-  * Faster keyword scanning.
-  * Import library and smartlink library in one file.
 
-  Revision 1.4  1998/06/17 14:10:14  peter
-    * small os2 fixes
-    * fixed interdependent units with newppu (remake3 under linux works now)
+function TLinkeros2.MakeExecutable:boolean;
+var
+  binstr,
+  cmdstr  : string;
+  success : boolean;
+  i       : longint;
+  PMStr,
+  StripStr : string[40];
+begin
+  if not(cs_link_extern in aktglobalswitches) then
+   Message1(exec_i_linking,current_module^.exefilename^);
+
+{ Create some replacements }
+  StripStr:='';
+  PMStr:='';
+  if (cs_link_strip in aktglobalswitches) then
+   StripStr:='-s';
+  if usewindowapi then
+   PMStr:='-p';
+
+{ Write used files and libraries }
+  WriteResponseFile(false);
+
+{ Call linker }
+  success:=false;
+  for i:=1to 2 do
+   begin
+     SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+     if binstr<>'' then
+      begin
+        Replace(cmdstr,'$EXE',current_module^.exefilename^);
+        Replace(cmdstr,'$OPT',Info.ExtraOptions);
+        Replace(cmdstr,'$RES',current_module^.outpath^+Info.ResName);
+        Replace(cmdstr,'$STRIP',StripStr);
+        Replace(cmdstr,'$HEAPMB',tostr((maxheapsize+1048575) shr 20));
+        {Size of the stack when an EMX program runs in OS/2.}
+        Replace(cmdstr,'$STACKKB',tostr((stacksize+1023) shr 10));
+        {When an EMX program runs in DOS, the heap and stack share the
+         same memory pool. The heap grows upwards, the stack grows downwards.}
+        Replace(cmdstr,'$DOSHEAPKB',tostr((stacksize+maxheapsize+1023) shr 10));
+        Replace(cmdstr,'$PM',PMStr);
+        success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
+        if not success then
+         break;
+      end;
+   end;
+
+{ Remove ReponseFile }
+  if (success) and not(cs_link_extern in aktglobalswitches) then
+   RemoveFile(current_module^.outpath^+Info.ResName);
+
+  MakeExecutable:=success;   { otherwise a recursive call to link method }
+end;
 
-  Revision 1.3  1998/06/04 23:51:48  peter
-    * m68k compiles
-    + .def file creation moved to gendef.pas so it could also be used
-      for win32
 
-  Revision 1.2  1998/05/04 17:54:27  peter
-    + smartlinking works (only case jumptable left todo)
-    * redesign of systems.pas to support assemblers and linkers
-    + Unitname is now also in the PPU-file, increased version to 14
+end.
+{
+  $Log$
+  Revision 1.1  1999-10-21 14:29:38  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
 
 }

+ 457 - 331
compiler/win_targ.pas → compiler/t_win32.pas

@@ -1,9 +1,9 @@
 {
     $Id$
-    Copyright (c) 1998 by Florian Klaempfl
+    Copyright (c) 1999 by Peter Vreman
 
-    This unit implements some support routines for the win32 target like
-    import/export handling
+    This unit implements support import,export,link routines
+    for the (i386) Win32 target
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
 
  ****************************************************************************
 }
-unit win_targ;
+unit t_win32;
 
   interface
 
@@ -52,14 +52,21 @@ unit win_targ;
 
     plinkerwin32=^tlinkerwin32;
     tlinkerwin32=object(tlinker)
-      procedure postprocessexecutable(const n : string);virtual;
+    private
+       Function  WriteResponseFile(isdll:boolean) : Boolean;
+       Function  PostProcessExecutable(const fn:string;isdll:boolean) : Boolean;
+    public
+       Procedure SetDefaultInfo;virtual;
+       function  MakeExecutable:boolean;virtual;
+       function  MakeSharedLibrary:boolean;virtual;
     end;
 
 
   implementation
 
     uses
-       aasm,files,strings,globtype,globals,cobjects,systems,verbose,
+       aasm,files,globtype,globals,cobjects,systems,verbose,
+       script,gendef,
        cpubase,cpuasm
 {$ifdef GDB}
        ,gdb
@@ -75,21 +82,25 @@ unit win_targ;
          else
            DllName:=Name+target_os.sharedlibext;
       end;
-    procedure timportlibwin32.preparelib(const s : string);
 
+
+{*****************************************************************************
+                             TIMPORTLIBWIN32
+*****************************************************************************}
+
+    procedure timportlibwin32.preparelib(const s : string);
       begin
          if not(assigned(importssection)) then
            importssection:=new(paasmoutput,init);
       end;
 
+
     procedure timportlibwin32.importprocedure(const func,module : string;index : longint;const name : string);
       var
          hp1 : pimportlist;
          hp2 : pimported_item;
          hs  : string;
       begin
-         { that IS wrong for DRV files
-         hs:=SplitName(module); }
          hs:=DllName(module);
          { search for the module }
          hp1:=pimportlist(current_module^.imports^.first);
@@ -366,8 +377,12 @@ unit win_targ;
            end;
       end;
 
-    procedure texportlibwin32.preparelib(const s:string);
 
+{*****************************************************************************
+                             TEXPORTLIBWIN32
+*****************************************************************************}
+
+    procedure texportlibwin32.preparelib(const s:string);
       begin
          if not(assigned(exportssection)) then
            exportssection:=new(paasmoutput,init);
@@ -384,22 +399,27 @@ unit win_targ;
 
 
     procedure texportlibwin32.exportprocedure(hp : pexported_item);
-
       { must be ordered at least for win32 !! }
-      var hp2 : pexported_item;
-
-    begin
-        hp2:=pexported_item(current_module^._exports^.first);
+      var
+        hp2 : pexported_item;
+      begin
         { first test the index value }
         if (hp^.options and eo_index)<>0 then
           begin
              if (hp^.index<=0) or (hp^.index>$ffff) then
-               message1(parser_e_export_invalid_index,tostr(hp^.index))
-             else while assigned(hp2) do
+               begin
+                 message1(parser_e_export_invalid_index,tostr(hp^.index));
+                 exit;
+               end;
+             hp2:=pexported_item(current_module^._exports^.first);
+             while assigned(hp2) do
                begin
                   if (hp^.index=hp2^.index) then
                     if ((hp2^.options and eo_index)<>0) then
-                      message1(parser_e_export_ordinal_double,tostr(hp^.index))
+                      begin
+                        message1(parser_e_export_ordinal_double,tostr(hp^.index));
+                        exit;
+                      end
                     else
                       begin
                          inc(last_index);
@@ -421,7 +441,6 @@ unit win_targ;
              hp^.name:=stringdup(hp^.sym^.name);
              hp^.options:=hp^.options or eo_name;
           end;
-
         { now place in correct order }
         hp2:=pexported_item(current_module^._exports^.first);
         while assigned(hp2) and
@@ -432,6 +451,7 @@ unit win_targ;
           begin
              { this is not allowed !! }
              message1(parser_e_export_name_double,hp^.name^);
+             exit;
           end;
         if hp2=pexported_item(current_module^._exports^.first) then
           current_module^._exports^.insert(hp)
@@ -445,11 +465,10 @@ unit win_targ;
           end
         else
           current_module^._exports^.concat(hp);
-    end;
+      end;
 
 
     procedure texportlibwin32.generatelib;
-
       var
          ordinal_base,ordinal_max,ordinal_min : longint;
          current_index : longint;
@@ -460,7 +479,6 @@ unit win_targ;
          tempexport : plinkedlist;
          address_table,name_table_pointers,
          name_table,ordinal_table : paasmoutput;
-
       begin
          ordinal_max:=0;
          ordinal_min:=$7FFFFFFF;
@@ -579,8 +597,6 @@ unit win_targ;
               hp:=pexported_item(current_module^._exports^.first);;
            end;
 
-
-
          { write the export adress table }
          current_index:=ordinal_base;
          hp:=pexported_item(tempexport^.first);
@@ -610,320 +626,430 @@ unit win_targ;
 
 
 {****************************************************************************
-                            Postprocess Executable
+                              TLINKERWIN32
 ****************************************************************************}
 
-    procedure tlinkerwin32.postprocessexecutable(const n : string);
-      type
-         tdosheader = packed record
-            e_magic : word;
-            e_cblp : word;
-            e_cp : word;
-            e_crlc : word;
-            e_cparhdr : word;
-            e_minalloc : word;
-            e_maxalloc : word;
-            e_ss : word;
-            e_sp : word;
-            e_csum : word;
-            e_ip : word;
-            e_cs : word;
-            e_lfarlc : word;
-            e_ovno : word;
-            e_res : array[0..3] of word;
-            e_oemid : word;
-            e_oeminfo : word;
-            e_res2 : array[0..9] of word;
-            e_lfanew : longint;
-         end;
-
-         tpeheader = packed record
-            PEMagic : array[0..3] of char;
-            Machine : word;
-            NumberOfSections : word;
-            TimeDateStamp : longint;
-            PointerToSymbolTable : longint;
-            NumberOfSymbols : longint;
-            SizeOfOptionalHeader : word;
-            Characteristics : word;
-            Magic : word;
-            MajorLinkerVersion : byte;
-            MinorLinkerVersion : byte;
-            SizeOfCode : longint;
-            SizeOfInitializedData : longint;
-            SizeOfUninitializedData : longint;
-            AddressOfEntryPoint : longint;
-            BaseOfCode : longint;
-            BaseOfData : longint;
-            ImageBase : longint;
-            SectionAlignment : longint;
-            FileAlignment : longint;
-            MajorOperatingSystemVersion : word;
-            MinorOperatingSystemVersion : word;
-            MajorImageVersion : word;
-            MinorImageVersion : word;
-            MajorSubsystemVersion : word;
-            MinorSubsystemVersion : word;
-            Reserved1 : longint;
-            SizeOfImage : longint;
-            SizeOfHeaders : longint;
-            CheckSum : longint;
-            Subsystem : word;
-            DllCharacteristics : word;
-            SizeOfStackReserve : longint;
-            SizeOfStackCommit : longint;
-            SizeOfHeapReserve : longint;
-            SizeOfHeapCommit : longint;
-            LoaderFlags : longint;
-            NumberOfRvaAndSizes : longint;
-            DataDirectory : array[1..$80] of byte;
-         end;
-        tcoffsechdr=packed record
-          name     : array[0..7] of char;
-          vsize    : longint;
-          rvaofs   : longint;
-          datalen  : longint;
-          datapos  : longint;
-          relocpos : longint;
-          lineno1  : longint;
-          nrelocs  : word;
-          lineno2  : word;
-          flags    : longint;
-        end;
-        psecfill=^tsecfill;
-        tsecfill=record
-          fillpos,
-          fillsize : longint;
-          next : psecfill;
-        end;
-
-      var
-         f : file;
-         dosheader : tdosheader;
-         peheader : tpeheader;
-         firstsecpos,
-         maxfillsize,
-         l,peheaderpos : longint;
-         coffsec : tcoffsechdr;
-         secroot,hsecroot : psecfill;
-         zerobuf : pointer;
+Procedure TLinkerWin32.SetDefaultInfo;
+begin
+  with Info do
+   begin
+     ExeCmd[1]:='ldw $OPT $STRIP $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
+     DllCmd[1]:='ldw $OPT --dll $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
+     DllCmd[2]:='dlltool --as asw.exe --dllname $EXE --output-exp exp.$$$ $RELOC -d $DEF';
+     DllCmd[3]:='ldw $OPT $STRIP --dll $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
+   end;
+end;
+
+
+Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
+Var
+  linkres  : TLinkRes;
+  i        : longint;
+  s,s2     : string;
+  linklibc : boolean;
+begin
+  WriteResponseFile:=False;
+
+  { Open link.res file }
+  LinkRes.Init(Info.ResName);
+
+  { Write path to search libraries }
+  if assigned(current_module^.locallibrarysearchpath) then
+   begin
+     S:=current_module^.locallibrarysearchpath^;
+     while s<>'' do
       begin
-         { when -s is used quit, because there is no .exe }
-         if cs_link_extern in aktglobalswitches then
-          exit;
-         { open file }
-         assign(f,n);
-         {$I-}
-          reset(f,1);
-         if ioresult<>0 then
-           Message1(execinfo_f_cant_open_executable,n);
-         { read headers }
-         blockread(f,dosheader,sizeof(tdosheader));
-         peheaderpos:=dosheader.e_lfanew;
-         seek(f,peheaderpos);
-         blockread(f,peheader,sizeof(tpeheader));
-         { write info }
-         Message1(execinfo_x_codesize,tostr(peheader.SizeOfCode));
-         Message1(execinfo_x_initdatasize,tostr(peheader.SizeOfInitializedData));
-         Message1(execinfo_x_uninitdatasize,tostr(peheader.SizeOfUninitializedData));
-
-         { change stack size (PM) }
-         { I am not sure that the default value is adequate !! }
-         peheader.SizeOfStackReserve:=stacksize;
-         { change the header }
-         { sub system }
-         { gui=2 }
-         { cui=3 }
-         if apptype=at_gui then
-           peheader.Subsystem:=2
-         else if apptype=at_cui then
-           peheader.Subsystem:=3;
-         seek(f,peheaderpos);
-         blockwrite(f,peheader,sizeof(tpeheader));
-         if ioresult<>0 then
-           Message1(execinfo_f_cant_process_executable,n);
-         seek(f,peheaderpos);
-         blockread(f,peheader,sizeof(tpeheader));
-         { write the value after the change }
-
-         Message1(execinfo_x_stackreserve,tostr(peheader.SizeOfStackReserve));
-         Message1(execinfo_x_stackcommit,tostr(peheader.SizeOfStackCommit));
-
-         { read section info }
-         maxfillsize:=0;
-         firstsecpos:=0;
-         secroot:=nil;
-         for l:=1to peheader.NumberOfSections do
-          begin
-            blockread(f,coffsec,sizeof(tcoffsechdr));
-            if coffsec.datapos>0 then
-             begin
-               if secroot=nil then
-                firstsecpos:=coffsec.datapos;
-               new(hsecroot);
-               hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
-               hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
-               hsecroot^.next:=secroot;
-               secroot:=hsecroot;
-               if secroot^.fillsize>maxfillsize then
-                maxfillsize:=secroot^.fillsize;
-             end;
-          end;
-         if firstsecpos>0 then
-          begin
-            l:=firstsecpos-filepos(f);
-            if l>maxfillsize then
-             maxfillsize:=l;
-          end
-         else
-          l:=0;
-         { get zero buffer }
-         getmem(zerobuf,maxfillsize);
-         fillchar(zerobuf^,maxfillsize,0);
-         { zero from sectioninfo until first section }
-         blockwrite(f,zerobuf^,l);
-         { zero section alignments }
-         while assigned(secroot) do
-          begin
-            seek(f,secroot^.fillpos);
-            blockwrite(f,zerobuf^,secroot^.fillsize);
-            hsecroot:=secroot;
-            secroot:=secroot^.next;
-            dispose(hsecroot);
-          end;
-         freemem(zerobuf,maxfillsize);
-         close(f);
-         {$I+}
+        s2:=GetPathFromList(s);
+        LinkRes.Add('SEARCH_DIR('+s2+')');
       end;
+   end;
+  S:=LibrarySearchPath;
+  while s<>'' do
+   begin
+     s2:=GetPathFromList(s);
+     LinkRes.Add('SEARCH_DIR('+s2+')');
+   end;
+
+  { add objectfiles, start with prt0 always }
+  LinkRes.Add('INPUT(');
+  if isdll then
+   LinkRes.AddFileName(FindObjectFile('wdllprt0'))
+  else
+   LinkRes.AddFileName(FindObjectFile('wprt0'));
+  while not ObjectFiles.Empty do
+   begin
+     s:=ObjectFiles.Get;
+     if s<>'' then
+      LinkRes.AddFileName(s);
+   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) }
+  While not SharedLibFiles.Empty do
+   begin
+     S:=SharedLibFiles.Get;
+     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(')');
+
+  { Write staticlibraries }
+  if not StaticLibFiles.Empty then
+   begin
+     LinkRes.Add('GROUP(');
+     While not StaticLibFiles.Empty do
+      begin
+        S:=StaticLibFiles.Get;
+        LinkRes.AddFileName(s)
+      end;
+     LinkRes.Add(')');
+   end;
+
+{ Write and Close response }
+  linkres.writetodisk;
+  linkres.done;
+
+  WriteResponseFile:=True;
+end;
+
+
+function TLinkerWin32.MakeExecutable:boolean;
+var
+  binstr,
+  cmdstr  : string;
+  success : boolean;
+  i       : longint;
+  StripStr,
+  RelocStr,
+  AppTypeStr,
+  ImageBaseStr : string[40];
+begin
+  if not(cs_link_extern in aktglobalswitches) then
+   Message1(exec_i_linking,current_module^.exefilename^);
+
+{ Create some replacements }
+  RelocStr:='';
+  AppTypeStr:='';
+  ImageBaseStr:='';
+  StripStr:='';
+  if RelocSection then
+   RelocStr:='--base-file base.$$$';
+  if apptype=at_gui then
+   AppTypeStr:='--subsystem windows';
+  if assigned(DLLImageBase) then
+   ImageBaseStr:='--image-base=0x'+DLLImageBase^;
+  if (cs_link_strip in aktglobalswitches) then
+   StripStr:='-s';
+
+{ Write used files and libraries }
+  WriteResponseFile(false);
+
+{ Call linker }
+  success:=false;
+  for i:=1to 1 do
+   begin
+     SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
+     if binstr<>'' then
+      begin
+        Replace(cmdstr,'$EXE',current_module^.exefilename^);
+        Replace(cmdstr,'$OPT',Info.ExtraOptions);
+        Replace(cmdstr,'$RES',current_module^.outpath^+Info.ResName);
+        Replace(cmdstr,'$APPTYPE',AppTypeStr);
+        Replace(cmdstr,'$RELOC',RelocStr);
+        Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
+        Replace(cmdstr,'$STRIP',StripStr);
+        success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
+        if not success then
+         break;
+      end;
+   end;
+
+{ Post process }
+  if success then
+   success:=PostProcessExecutable(current_module^.exefilename^,false);
+
+{ Remove ReponseFile }
+  if (success) and not(cs_link_extern in aktglobalswitches) then
+   begin
+     RemoveFile(current_module^.outpath^+Info.ResName);
+     RemoveFile('base.$$$');
+     RemoveFile('exp.$$$');
+   end;
+
+  MakeExecutable:=success;   { otherwise a recursive call to link method }
+end;
+
+
+Function TLinkerWin32.MakeSharedLibrary:boolean;
+var
+  binstr,
+  cmdstr  : string;
+  success : boolean;
+  i       : longint;
+  StripStr,
+  RelocStr,
+  AppTypeStr,
+  ImageBaseStr : string[40];
+begin
+  MakeSharedLibrary:=false;
+  if not(cs_link_extern in aktglobalswitches) then
+   Message1(exec_i_linking,current_module^.sharedlibfilename^);
+
+{ Create some replacements }
+  RelocStr:='';
+  AppTypeStr:='';
+  ImageBaseStr:='';
+  StripStr:='';
+  if RelocSection then
+   RelocStr:='--base-file base.$$$';
+  if apptype=at_gui then
+   AppTypeStr:='--subsystem windows';
+  if assigned(DLLImageBase) then
+   ImageBaseStr:='--image-base=0x'+DLLImageBase^;
+  if (cs_link_strip in aktglobalswitches) then
+   StripStr:='-s';
+
+{ Write used files and libraries }
+  WriteResponseFile(true);
+
+{ Call linker }
+  success:=false;
+  for i:=1to 3 do
+   begin
+     SplitBinCmd(Info.DllCmd[i],binstr,cmdstr);
+     if binstr<>'' then
+      begin
+        Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
+        Replace(cmdstr,'$OPT',Info.ExtraOptions);
+        Replace(cmdstr,'$RES',current_module^.outpath^+Info.ResName);
+        Replace(cmdstr,'$APPTYPE',AppTypeStr);
+        Replace(cmdstr,'$RELOC',RelocStr);
+        Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
+        Replace(cmdstr,'$STRIP',StripStr);
+        Replace(cmdstr,'$DEF',deffile.fname);
+        success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
+        if not success then
+         break;
+      end;
+   end;
+
+{ Post process }
+  if success then
+   success:=PostProcessExecutable(current_module^.sharedlibfilename^,true);
+
+{ Remove ReponseFile }
+  if (success) and not(cs_link_extern in aktglobalswitches) then
+   begin
+     RemoveFile(current_module^.outpath^+Info.ResName);
+     RemoveFile('base.$$$');
+     RemoveFile('exp.$$$');
+   end;
+  MakeSharedLibrary:=success;   { otherwise a recursive call to link method }
+end;
+
+
+function tlinkerwin32.postprocessexecutable(const fn : string;isdll:boolean):boolean;
+type
+  tdosheader = packed record
+     e_magic : word;
+     e_cblp : word;
+     e_cp : word;
+     e_crlc : word;
+     e_cparhdr : word;
+     e_minalloc : word;
+     e_maxalloc : word;
+     e_ss : word;
+     e_sp : word;
+     e_csum : word;
+     e_ip : word;
+     e_cs : word;
+     e_lfarlc : word;
+     e_ovno : word;
+     e_res : array[0..3] of word;
+     e_oemid : word;
+     e_oeminfo : word;
+     e_res2 : array[0..9] of word;
+     e_lfanew : longint;
+  end;
+  tpeheader = packed record
+     PEMagic : array[0..3] of char;
+     Machine : word;
+     NumberOfSections : word;
+     TimeDateStamp : longint;
+     PointerToSymbolTable : longint;
+     NumberOfSymbols : longint;
+     SizeOfOptionalHeader : word;
+     Characteristics : word;
+     Magic : word;
+     MajorLinkerVersion : byte;
+     MinorLinkerVersion : byte;
+     SizeOfCode : longint;
+     SizeOfInitializedData : longint;
+     SizeOfUninitializedData : longint;
+     AddressOfEntryPoint : longint;
+     BaseOfCode : longint;
+     BaseOfData : longint;
+     ImageBase : longint;
+     SectionAlignment : longint;
+     FileAlignment : longint;
+     MajorOperatingSystemVersion : word;
+     MinorOperatingSystemVersion : word;
+     MajorImageVersion : word;
+     MinorImageVersion : word;
+     MajorSubsystemVersion : word;
+     MinorSubsystemVersion : word;
+     Reserved1 : longint;
+     SizeOfImage : longint;
+     SizeOfHeaders : longint;
+     CheckSum : longint;
+     Subsystem : word;
+     DllCharacteristics : word;
+     SizeOfStackReserve : longint;
+     SizeOfStackCommit : longint;
+     SizeOfHeapReserve : longint;
+     SizeOfHeapCommit : longint;
+     LoaderFlags : longint;
+     NumberOfRvaAndSizes : longint;
+     DataDirectory : array[1..$80] of byte;
+  end;
+  tcoffsechdr=packed record
+    name     : array[0..7] of char;
+    vsize    : longint;
+    rvaofs   : longint;
+    datalen  : longint;
+    datapos  : longint;
+    relocpos : longint;
+    lineno1  : longint;
+    nrelocs  : word;
+    lineno2  : word;
+    flags    : longint;
+  end;
+  psecfill=^tsecfill;
+  tsecfill=record
+    fillpos,
+    fillsize : longint;
+    next : psecfill;
+  end;
+var
+  f : file;
+  dosheader : tdosheader;
+  peheader : tpeheader;
+  firstsecpos,
+  maxfillsize,
+  i,l,peheaderpos : longint;
+  coffsec : tcoffsechdr;
+  secroot,hsecroot : psecfill;
+  zerobuf : pointer;
+begin
+  postprocessexecutable:=false;
+  { when -s is used or it's a dll then quit }
+  if (cs_link_extern in aktglobalswitches) then
+   begin
+     postprocessexecutable:=true;
+     exit;
+   end;
+  { open file }
+  assign(f,fn);
+  {$I-}
+   reset(f,1);
+  if ioresult<>0 then
+    Message1(execinfo_f_cant_open_executable,fn);
+  { read headers }
+  blockread(f,dosheader,sizeof(tdosheader));
+  peheaderpos:=dosheader.e_lfanew;
+  seek(f,peheaderpos);
+  blockread(f,peheader,sizeof(tpeheader));
+  { write info }
+  Message1(execinfo_x_codesize,tostr(peheader.SizeOfCode));
+  Message1(execinfo_x_initdatasize,tostr(peheader.SizeOfInitializedData));
+  Message1(execinfo_x_uninitdatasize,tostr(peheader.SizeOfUninitializedData));
+  { change stack size (PM) }
+  { I am not sure that the default value is adequate !! }
+  peheader.SizeOfStackReserve:=stacksize;
+  { change the header }
+  { sub system }
+  { gui=2 }
+  { cui=3 }
+  if apptype=at_gui then
+    peheader.Subsystem:=2
+  else if apptype=at_cui then
+    peheader.Subsystem:=3;
+  seek(f,peheaderpos);
+  blockwrite(f,peheader,sizeof(tpeheader));
+  if ioresult<>0 then
+    Message1(execinfo_f_cant_process_executable,fn);
+  seek(f,peheaderpos);
+  blockread(f,peheader,sizeof(tpeheader));
+  { write the value after the change }
+  Message1(execinfo_x_stackreserve,tostr(peheader.SizeOfStackReserve));
+  Message1(execinfo_x_stackcommit,tostr(peheader.SizeOfStackCommit));
+  { read section info }
+  maxfillsize:=0;
+  firstsecpos:=0;
+  secroot:=nil;
+  for l:=1to peheader.NumberOfSections do
+   begin
+     blockread(f,coffsec,sizeof(tcoffsechdr));
+     if coffsec.datapos>0 then
+      begin
+        if secroot=nil then
+         firstsecpos:=coffsec.datapos;
+        new(hsecroot);
+        hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
+        hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
+        hsecroot^.next:=secroot;
+        secroot:=hsecroot;
+        if secroot^.fillsize>maxfillsize then
+         maxfillsize:=secroot^.fillsize;
+      end;
+   end;
+  if firstsecpos>0 then
+   begin
+     l:=firstsecpos-filepos(f);
+     if l>maxfillsize then
+      maxfillsize:=l;
+   end
+  else
+   l:=0;
+  { get zero buffer }
+  getmem(zerobuf,maxfillsize);
+  fillchar(zerobuf^,maxfillsize,0);
+  { zero from sectioninfo until first section }
+  blockwrite(f,zerobuf^,l);
+  { zero section alignments }
+  while assigned(secroot) do
+   begin
+     seek(f,secroot^.fillpos);
+     blockwrite(f,zerobuf^,secroot^.fillsize);
+     hsecroot:=secroot;
+     secroot:=secroot^.next;
+     dispose(hsecroot);
+   end;
+  freemem(zerobuf,maxfillsize);
+  close(f);
+  {$I+}
+  i:=ioresult;
+  postprocessexecutable:=true;
+end;
 
 end.
 {
   $Log$
-  Revision 1.34  1999-09-20 16:39:04  peter
-    * cs_create_smart instead of cs_smartlink
-    * -CX is create smartlink
-    * -CD is create dynamic, but does nothing atm.
-
-  Revision 1.33  1999/08/25 12:00:07  jonas
-    * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
-
-  Revision 1.32  1999/08/11 17:26:38  peter
-    * tlinker object is now inherited for win32 and dos
-    * postprocessexecutable is now a method of tlinker
-
-  Revision 1.31  1999/08/04 00:23:50  florian
-    * renamed i386asm and i386base to cpuasm and cpubase
-
-  Revision 1.30  1999/07/29 20:54:11  peter
-    * write .size also
-
-  Revision 1.29  1999/07/22 16:12:28  peter
-    * merged
-
-  Revision 1.28  1999/07/18 10:20:03  florian
-    * made it compilable with Dlephi 4 again
-    + fixed problem with large stack allocations on win32
-
-  Revision 1.27.2.1  1999/07/22 16:09:30  peter
-    * reuse old import entries
-
-  Revision 1.27  1999/05/27 19:45:30  peter
-    * removed oldasm
-    * plabel -> pasmlabel
-    * -a switches to source writing automaticly
-    * assembler readers OOPed
-    * asmsymbol automaticly external
-    * jumptables and other label fixes for asm readers
-
-  Revision 1.26  1999/05/21 13:55:24  peter
-    * NEWLAB for label as symbol
-
-  Revision 1.25  1999/05/17 13:02:13  pierre
-   * -Csmmm works for win32 but default is set to 32Mb
-
-  Revision 1.24  1999/05/01 13:25:04  peter
-    * merged nasm compiler
-    * old asm moved to oldasm/
-
-  Revision 1.23  1999/04/07 14:18:32  pierre
-   * typo correction
-
-  Revision 1.22  1999/04/07 14:04:40  pierre
-    * adds .dll as library suffix only if
-      the name does not end with .dll .drv or .exe !
-
-  Revision 1.21  1999/02/25 21:02:59  peter
-    * ag386bin updates
-    + coff writer
-
-  Revision 1.20  1999/02/22 02:44:14  peter
-    * ag386bin doesn't use i386.pas anymore
-
-  Revision 1.19  1998/12/11 00:04:06  peter
-    + globtype,tokens,version unit splitted from globals
-
-  Revision 1.18  1998/12/02 10:26:13  pierre
-    * writing of .edata was wrong for indexes above number of exported items
-    * importing by index only did not work !
-
-  Revision 1.17  1998/12/01 23:35:43  pierre
-   * alignment fixes
-
-  Revision 1.16  1998/11/30 13:26:26  pierre
-    * the code for ordering the exported procs/vars was buggy
-    + added -WB to force binding (Ozerski way of creating DLL)
-      this is off by default as direct writing of .edata section seems
-      OK
-
-  Revision 1.15  1998/11/30 09:43:25  pierre
-    * some range check bugs fixed (still not working !)
-    + added DLL writing support for win32 (also accepts variables)
-    + TempAnsi for code that could be used for Temporary ansi strings
-      handling
-
-  Revision 1.14  1998/11/28 16:21:00  peter
-    + support for dll variables
-
-  Revision 1.13  1998/10/29 11:35:54  florian
-    * some dll support for win32
-    * fixed assembler writing for PalmOS
-
-  Revision 1.12  1998/10/27 10:22:35  florian
-    + First things for win32 export sections
-
-  Revision 1.11  1998/10/22 17:54:09  florian
-    + switch $APPTYPE for win32 added
-
-  Revision 1.10  1998/10/22 15:18:51  florian
-    + switch -vx for win32 added
-
-  Revision 1.9  1998/10/19 15:41:03  peter
-    * better splitname to support glib-1.1.dll alike names
-
-  Revision 1.8  1998/09/07 18:33:35  peter
-    + smartlinking for win95 imports
-
-  Revision 1.7  1998/09/03 17:39:06  florian
-    + better code for type conversation longint/dword to real type
-
-  Revision 1.6  1998/08/10 14:50:38  peter
-    + localswitches, moduleswitches, globalswitches splitting
-
-  Revision 1.5  1998/06/10 10:43:18  peter
-    * write also the .dll extension (needed for NT)
-
-  Revision 1.4  1998/06/08 22:59:56  peter
-    * smartlinking works for win32
-    * some defines to exclude some compiler parts
-
-  Revision 1.3  1998/06/04 23:52:06  peter
-    * m68k compiles
-    + .def file creation moved to gendef.pas so it could also be used
-      for win32
-
-  Revision 1.2  1998/05/06 18:36:55  peter
-    * tai_section extended with code,data,bss sections and enumerated type
-    * ident 'compiled by FPC' moved to pmodules
-    * small fix for smartlink
+  Revision 1.1  1999-10-21 14:29:38  peter
+    * redesigned linker object
+    + library support for linux (only procedures can be exported)
 
 }