| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 | {    Copyright (c) 1998-2002 by Peter Vreman    This unit implements support import,export,link routines    for the (z80) MSX-DOS 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_msxdos;{$i fpcdefs.inc}{$define USE_LINKER_WLINK}interfaceimplementation    uses       SysUtils,       cutils,cfileutl,cclasses,       globtype,globals,systems,verbose,cscript,       fmodule,i_msxdos,       link,aasmbase,cpuinfo,ogrel,owar;    const      DefaultOrigin = $100;    type       { sdld - the sdld linker from the SDCC project ( http://sdcc.sourceforge.net/ ) }       { vlink - the vlink linker by Frank Wille (http://sun.hasenbraten.de/vlink/ ) }       TLinkerMSXDOS=class(texternallinker)       private          FOrigin: Word;          Function  WriteResponseFile_Sdld: Boolean;          Function  WriteResponseFile_Vlink: Boolean;          procedure SetDefaultInfo_Sdld;          procedure SetDefaultInfo_Vlink;          function  MakeExecutable_Sdld: boolean;          function  MakeExecutable_Vlink: boolean;       public          procedure SetDefaultInfo; override;          function  MakeExecutable: boolean; override;          procedure InitSysInitUnitName; override;          function postprocessexecutable(const fn : string;isdll:boolean): boolean;       end;       TInternalLinkerMSXDOS=class(tinternallinker)       private         FOrigin: Word;       protected         procedure DefaultLinkScript;override;         function ExecutableFilename:String;override;       public         constructor create;override;         procedure InitSysInitUnitName;override;         function MakeExecutable: boolean; override;         function postprocessexecutable(const fn : string): boolean;       end;{*****************************************************************************                          TLinkerMSXDOS*****************************************************************************}function TLinkerMSXDOS.WriteResponseFile_Sdld: Boolean;  Var    linkres  : TLinkRes;    s        : TCmdStr;    prtobj: string[80];  begin    result:=False;    prtobj:='prt0';    { Open link.res file }    LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);    { Write the origin (i.e. the program load address) }    LinkRes.Add('-b _CODE='+tostr(FOrigin));    if not (target_info.system in systems_internal_sysinit) and (prtobj <> '') then      begin        s:=FindObjectFile(prtobj,'',false);        LinkRes.AddFileName(s);      end;    while not ObjectFiles.Empty do     begin      s:=ObjectFiles.GetFirst;      if s<>'' then       begin        if not(cs_link_on_target in current_settings.globalswitches) then         s:=FindObjectFile(s,'',false);        LinkRes.AddFileName((maybequoted(s)));       end;     end;    { Write staticlibraries }    if not StaticLibFiles.Empty then     begin      while not StaticLibFiles.Empty do       begin        S:=StaticLibFiles.GetFirst;        LinkRes.Add('-l'+maybequoted(s));       end;     end;    { Write and Close response }    linkres.writetodisk;    linkres.free;    result:=True;  end;function TLinkerMSXDOS.WriteResponseFile_Vlink: Boolean;  Var    linkres  : TLinkRes;    s        : TCmdStr;    prtobj: string[80];  begin    result:=false;    prtobj:='prt0';    { Open link.res file }    LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);    if (source_info.dirsep <> '/') then      LinkRes.fForceUseForwardSlash:=true;    LinkRes.Add('INPUT (');    if not (target_info.system in systems_internal_sysinit) and (prtobj <> '') then      begin        s:=FindObjectFile(prtobj,'',false);        LinkRes.AddFileName(maybequoted(FixFileName(s)));      end;    while not ObjectFiles.Empty do      begin        s:=ObjectFiles.GetFirst;        if s<>'' then          begin            s:=FindObjectFile(s,'',false);            LinkRes.AddFileName(maybequoted(FixFileName(s)));          end;      end;    while not StaticLibFiles.Empty do      begin        S:=StaticLibFiles.GetFirst;        LinkRes.AddFileName(maybequoted(FixFileName(s)));      end;    LinkRes.Add(')');    with LinkRes do      begin        Add('');        Add('SECTIONS');        Add('{');        Add('  . = 0x'+hexstr(FOrigin,4)+';');        Add('  .text : { *(.text .text.* ) }');        Add('  .data : { *(.data .data.* .rodata .rodata.* .bss .bss.* .fpc.* .stack .stack.* ) }');        Add('}');      end;    { Write and Close response }    linkres.writetodisk;    linkres.free;    result:=true;  end;procedure TLinkerMSXDOS.SetDefaultInfo_Sdld;  const    ExeName='sdldz80';  begin    FOrigin:=$100;    with Info do     begin       ExeCmd[1]:=ExeName+' -n $OPT -i $MAP $EXE -f $RES'     end;  end;procedure TLinkerMSXDOS.SetDefaultInfo_Vlink;  const    ExeName='vlink';  begin    FOrigin:=$100;    with Info do     begin       ExeCmd[1]:=ExeName+' -bihex $GCSECTIONS -e $STARTSYMBOL $STRIP $OPT -o $EXE -T $RES'     end;  end;procedure TLinkerMSXDOS.SetDefaultInfo;  begin    if not (cs_link_vlink in current_settings.globalswitches) then      SetDefaultInfo_Sdld    else      SetDefaultInfo_Vlink;  end;function TLinkerMSXDOS.MakeExecutable_Sdld: boolean;  var    binstr,    cmdstr,    mapstr: TCmdStr;    success : boolean;    StaticStr,    //GCSectionsStr,    DynLinkStr,    StripStr,    FixedExeFileName: string;  begin    { for future use }    StaticStr:='';    StripStr:='';    mapstr:='';    DynLinkStr:='';    FixedExeFileName:=maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.ihx')));    if (cs_link_map in current_settings.globalswitches) then     mapstr:='-mw';  { Write used files and libraries }    WriteResponseFile_Sdld();  { Call linker }    SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);    Replace(cmdstr,'$OPT',Info.ExtraOptions);    Replace(cmdstr,'$EXE',FixedExeFileName);    Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));    Replace(cmdstr,'$STATIC',StaticStr);    Replace(cmdstr,'$STRIP',StripStr);    Replace(cmdstr,'$MAP',mapstr);    //Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);    Replace(cmdstr,'$DYNLINK',DynLinkStr);    success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);  { Remove ReponseFile }    if success and not(cs_link_nolink in current_settings.globalswitches) then     DeleteFile(outputexedir+Info.ResName);  { Post process }    if success and not(cs_link_nolink in current_settings.globalswitches) then      success:=PostProcessExecutable(FixedExeFileName,false);    result:=success;   { otherwise a recursive call to link method }  end;function TLinkerMSXDOS.MakeExecutable_Vlink: boolean;  var    binstr,    cmdstr: TCmdStr;    success: boolean;    GCSectionsStr,    StripStr,    StartSymbolStr,    FixedExeFilename: string;  begin    GCSectionsStr:='-gc-all -mtype';    StripStr:='';    StartSymbolStr:='start';    FixedExeFileName:=maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.ihx')));  { Write used files and libraries }    WriteResponseFile_Vlink();  { Call linker }    SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);    Replace(cmdstr,'$OPT',Info.ExtraOptions);    Replace(cmdstr,'$EXE',FixedExeFileName);    Replace(cmdstr,'$RES',(maybequoted(ScriptFixFileName(outputexedir+Info.ResName))));    Replace(cmdstr,'$STRIP',StripStr);    Replace(cmdstr,'$STARTSYMBOL',StartSymbolStr);    Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);    success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);  { Remove ReponseFile }    if success and not(cs_link_nolink in current_settings.globalswitches) then     DeleteFile(outputexedir+Info.ResName);  { Post process }    if success and not(cs_link_nolink in current_settings.globalswitches) then      success:=PostProcessExecutable(FixedExeFileName,false);    result:=success;  end;function TLinkerMSXDOS.MakeExecutable: boolean;  begin    if not (cs_link_vlink in current_settings.globalswitches) then      result:=MakeExecutable_Sdld    else      result:=MakeExecutable_Vlink;  end;procedure TLinkerMSXDOS.InitSysInitUnitName;begin  sysinitunit:='si_prc';end;function TLinkerMSXDOS.postprocessexecutable(const fn: string; isdll: boolean): boolean;  begin    result:=DoExec(FindUtil(utilsprefix+'ihxutil'),' -t bin '+fn+' '+maybequoted(ScriptFixFileName(current_module.exefilename)),true,false);  end;{*****************************************************************************                          TInternalLinkerZXSpectrum*****************************************************************************}procedure TInternalLinkerMSXDOS.DefaultLinkScript;  var    s        : TCmdStr;    prtobj: string[80];  begin    prtobj:='prt0';    if not (target_info.system in systems_internal_sysinit) and (prtobj <> '') then      LinkScript.Concat('READOBJECT ' + maybequoted(FindObjectFile(prtobj,'',false)));    while not ObjectFiles.Empty do      begin        s:=ObjectFiles.GetFirst;        if s<>'' then          begin            if not(cs_link_on_target in current_settings.globalswitches) then              s:=FindObjectFile(s,'',false);            LinkScript.Concat('READOBJECT ' + maybequoted(s));          end;      end;    LinkScript.Concat('GROUP');    { Write staticlibraries }    if not StaticLibFiles.Empty then      begin        while not StaticLibFiles.Empty do          begin            S:=StaticLibFiles.GetFirst;            if s<>'' then              LinkScript.Concat('READSTATICLIBRARY '+MaybeQuoted(s));          end;      end;    LinkScript.Concat('ENDGROUP');    LinkScript.Concat('IMAGEBASE '+tostr(FOrigin));    LinkScript.Concat('EXESECTION .text');    LinkScript.Concat('  OBJSECTION _CODE');    LinkScript.Concat('ENDEXESECTION');    LinkScript.Concat('EXESECTION .data');    LinkScript.Concat('  OBJSECTION _DATA');    LinkScript.Concat('ENDEXESECTION');    LinkScript.Concat('EXESECTION .bss');    LinkScript.Concat('  OBJSECTION _BSS');    LinkScript.Concat('  OBJSECTION _BSSEND');    LinkScript.Concat('  OBJSECTION _HEAP');    LinkScript.Concat('  OBJSECTION _STACK');    LinkScript.Concat('ENDEXESECTION');    LinkScript.Concat('ENTRYNAME start');  end;constructor TInternalLinkerMSXDOS.create;  begin    inherited create;    CArObjectReader:=TArObjectReader;    CExeOutput:=TIntelHexExeOutput;    CObjInput:=TRelObjInput;    if ImageBaseSetExplicity then      FOrigin:=ImageBase    else      FOrigin:=DefaultOrigin;  end;function TInternalLinkerMSXDOS.ExecutableFilename:String;  begin    result:=ChangeFileExt(current_module.exefilename,'.ihx');  end;procedure TInternalLinkerMSXDOS.InitSysInitUnitName;  begin    sysinitunit:='si_prc';  end;function TInternalLinkerMSXDOS.MakeExecutable: boolean;  begin    result:=inherited;    { Post process }    if result and not(cs_link_nolink in current_settings.globalswitches) then      result:=PostProcessExecutable(maybequoted(ScriptFixFileName(ChangeFileExt(current_module.exefilename,'.ihx'))));  end;function TInternalLinkerMSXDOS.postprocessexecutable(const fn: string): boolean;  var    exitcode: longint;    FoundBin: ansistring;    Found: Boolean;    utilexe: TCmdStr;  begin    result:=false;    utilexe:=utilsprefix+'ihxutil'+source_info.exeext;    FoundBin:='';    Found:=false;    if utilsdirectory<>'' then      Found:=FindFile(utilexe,utilsdirectory,false,Foundbin);    if (not Found) then      Found:=FindExe(utilexe,false,Foundbin);    if Found then      begin        exitcode:=RequotedExecuteProcess(foundbin,' -t bin '+fn+' '+maybequoted(ScriptFixFileName(current_module.exefilename)));        result:=exitcode<>0;      end;  end;{*****************************************************************************                                     Initialize*****************************************************************************}initialization{$ifdef z80}  RegisterLinker(ld_msxdos,TLinkerMSXDOS);  RegisterLinker(ld_int_msxdos,TInternalLinkerMSXDOS);  RegisterTarget(system_z80_msxdos_info);{$endif z80}end.
 |