123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- {
- Copyright (c) 1998-2002 by Peter Vreman
- This unit handles the writing of script files
- 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 cscript;
- {$i fpcdefs.inc}
- interface
- {$H+}
- uses
- sysutils,
- globtype,
- cclasses;
- type
- TScript=class
- fn : TCmdStr;
- data : TCmdStrList;
- executable : boolean;
- constructor Create(const s:TCmdStr);
- constructor CreateExec(const s:TCmdStr);
- destructor Destroy;override;
- procedure AddStart(const s:TCmdStr);
- procedure Add(const s:TCmdStr);
- Function Empty:boolean;
- procedure WriteToDisk;virtual;
- end;
- TAsmScript = class (TScript)
- Constructor Create(Const ScriptName : TCmdStr); virtual;
- Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);virtual;abstract;
- Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);virtual;abstract;
- Procedure AddDeleteCommand (Const FileName : TCmdStr);virtual;abstract;
- Procedure AddDeleteDirCommand (Const FileName : TCmdStr);virtual;abstract;
- end;
- TAsmScriptDos = class (TAsmScript)
- Constructor Create (Const ScriptName : TCmdStr); override;
- Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);override;
- Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);override;
- Procedure AddDeleteCommand (Const FileName : TCmdStr);override;
- Procedure AddDeleteDirCommand (Const FileName : TCmdStr);override;
- Procedure WriteToDisk;override;
- end;
- TAsmScriptAmiga = class (TAsmScript)
- Constructor Create (Const ScriptName : TCmdStr); override;
- Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);override;
- Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);override;
- Procedure AddDeleteCommand (Const FileName : TCmdStr);override;
- Procedure AddDeleteDirCommand (Const FileName : TCmdStr);override;
- Procedure WriteToDisk;override;
- end;
- TAsmScriptUnix = class (TAsmScript)
- Constructor Create (Const ScriptName : TCmdStr);override;
- Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);override;
- Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);override;
- Procedure AddDeleteCommand (Const FileName : TCmdStr);override;
- Procedure AddDeleteDirCommand (Const FileName : TCmdStr);override;
- Procedure WriteToDisk;override;
- end;
- TAsmScriptMPW = class (TAsmScript)
- Constructor Create (Const ScriptName : TCmdStr); override;
- Procedure AddAsmCommand (Const Command, Options,FileName : TCmdStr);override;
- Procedure AddLinkCommand (Const Command, Options, FileName : TCmdStr);override;
- Procedure AddDeleteCommand (Const FileName : TCmdStr);override;
- Procedure AddDeleteDirCommand (Const FileName : TCmdStr);override;
- Procedure WriteToDisk;override;
- end;
- TLinkRes = Class (TScript)
- section: string[30];
- fRealResponseFile: Boolean;
- fForceUseForwardSlash: Boolean;
- constructor Create(const ScriptName : TCmdStr; RealResponseFile: Boolean);
- procedure Add(const s:TCmdStr);
- procedure AddFileName(const s:TCmdStr);
- procedure EndSection(const s:TCmdStr);
- procedure StartSection(const s:TCmdStr);
- end;
- var
- AsmRes : TAsmScript;
- Function ScriptFixFileName(const s:TCmdStr):TCmdStr;
- Procedure GenerateAsmRes(const st : TCmdStr);
- Function GenerateScript(const st : TCmdStr): TAsmScript;
- implementation
- uses
- {$ifdef hasUnix}
- BaseUnix,
- {$endif}
- cutils,cfileutl,
- globals,systems,verbose;
- {****************************************************************************
- Helpers
- ****************************************************************************}
- Function ScriptFixFileName(const s:TCmdStr):TCmdStr;
- begin
- if cs_link_on_target in current_settings.globalswitches then
- ScriptFixFileName:=TargetFixFileName(s)
- else
- ScriptFixFileName:=FixFileName(s);
- end;
- {****************************************************************************
- TScript
- ****************************************************************************}
- constructor TScript.Create(const s: TCmdStr);
- begin
- fn:=FixFileName(s);
- executable:=false;
- data:=TCmdStrList.Create;
- end;
- constructor TScript.CreateExec(const s:TCmdStr);
- begin
- fn:=FixFileName(s);
- if cs_link_on_target in current_settings.globalswitches then
- fn:=ChangeFileExt(fn,target_info.scriptext)
- else
- fn:=ChangeFileExt(fn,source_info.scriptext);
- executable:=true;
- data:=TCmdStrList.Create;
- end;
- destructor TScript.Destroy;
- begin
- data.Free;
- end;
- procedure TScript.AddStart(const s:TCmdStr);
- begin
- data.Insert(s);
- end;
- procedure TScript.Add(const s:TCmdStr);
- begin
- data.Concat(s);
- end;
- Function TScript.Empty:boolean;
- begin
- Empty:=Data.Empty;
- end;
- procedure TScript.WriteToDisk;
- var
- t : file;
- i : longint;
- s : TCmdStr;
- le: string[2];
- begin
- Assign(t,fn);
- if cs_link_on_target in current_settings.globalswitches then
- le:= target_info.newline
- else
- le:= source_info.newline;
- {$push}{$I-}
- Rewrite(t,1);
- if ioresult<>0 then
- exit;
- while not data.Empty do
- begin
- s:=data.GetFirst;
- Blockwrite(t,s[1],length(s),i);
- Blockwrite(t,le[1],length(le),i);
- end;
- Close(t);
- {$pop}
- i:=ioresult;
- {$ifdef hasUnix}
- if executable then
- fpchmod(fn,493);
- {$endif}
- end;
- {****************************************************************************
- Asm Response
- ****************************************************************************}
- Constructor TAsmScript.Create (Const ScriptName : TCmdStr);
- begin
- Inherited CreateExec(ScriptName);
- end;
- {****************************************************************************
- DOS Asm Response
- ****************************************************************************}
- Constructor TAsmScriptDos.Create (Const ScriptName : TCmdStr);
- begin
- Inherited Create(ScriptName);
- end;
- Procedure TAsmScriptDos.AddAsmCommand (Const Command, Options,FileName : TCmdStr);
- begin
- if FileName<>'' then
- begin
- Add('SET THEFILE='+ScriptFixFileName(FileName));
- Add('echo Assembling %THEFILE%');
- end;
- Add(maybequoted(command)+' '+Options);
- Add('if errorlevel 1 goto asmend');
- end;
- Procedure TAsmScriptDos.AddLinkCommand (Const Command, Options, FileName : TCmdStr);
- begin
- if FileName<>'' then
- begin
- Add('SET THEFILE='+ScriptFixFileName(FileName));
- Add('echo Linking %THEFILE%');
- end;
- Add(maybequoted(command)+' '+Options);
- Add('if errorlevel 1 goto linkend');
- end;
- Procedure TAsmScriptDos.AddDeleteCommand (Const FileName : TCmdStr);
- begin
- Add('Del ' + MaybeQuoted (ScriptFixFileName (FileName)));
- end;
- Procedure TAsmScriptDos.AddDeleteDirCommand (Const FileName : TCmdStr);
- begin
- Add('Rmdir ' + MaybeQuoted (ScriptFixFileName (FileName)));
- end;
- Procedure TAsmScriptDos.WriteToDisk;
- Begin
- AddStart('@echo off');
- Add('goto end');
- Add(':asmend');
- Add('echo An error occurred while assembling %THEFILE%');
- Add('goto end');
- Add(':linkend');
- Add('echo An error occurred while linking %THEFILE%');
- Add(':end');
- inherited WriteToDisk;
- end;
- {****************************************************************************
- Amiga Asm Response
- ****************************************************************************}
- Constructor TAsmScriptAmiga.Create (Const ScriptName : TCmdStr);
- begin
- Inherited Create(ScriptName);
- end;
- Procedure TAsmScriptAmiga.AddAsmCommand (Const Command, Options,FileName : TCmdStr);
- begin
- if FileName<>'' then
- begin
- Add('SET THEFILE '+ScriptFixFileName(FileName));
- Add('echo Assembling $THEFILE');
- end;
- Add(maybequoted(command)+' '+Options);
- { There is a problem here,
- as always return with a non zero error value PM }
- Add('if error');
- Add('why');
- Add('skip asmend');
- Add('endif');
- end;
- Procedure TAsmScriptAmiga.AddLinkCommand (Const Command, Options, FileName : TCmdStr);
- begin
- if FileName<>'' then
- begin
- Add('SET THEFILE '+ScriptFixFileName(FileName));
- Add('echo Linking $THEFILE');
- end;
- Add(maybequoted(command)+' '+Options);
- Add('if error');
- Add('skip linkend');
- Add('endif');
- end;
- Procedure TAsmScriptAmiga.AddDeleteCommand (Const FileName : TCmdStr);
- begin
- Add('Delete ' + Unix2AmigaPath(MaybeQuoted(ScriptFixFileName(FileName))) + ' Quiet');
- end;
- Procedure TAsmScriptAmiga.AddDeleteDirCommand (Const FileName : TCmdStr);
- begin
- Add('Delete ' + Unix2AmigaPath(MaybeQuoted(ScriptFixFileName(FileName))) + ' All Quiet');
- end;
- Procedure TAsmScriptAmiga.WriteToDisk;
- Begin
- Add('skip end');
- Add('lab asmend');
- Add('why');
- Add('echo An error occurred while assembling $THEFILE');
- Add('skip end');
- Add('lab linkend');
- Add('why');
- Add('echo An error occurred while linking $THEFILE');
- Add('lab end');
- inherited WriteToDisk;
- end;
- {****************************************************************************
- Unix Asm Response
- ****************************************************************************}
- Constructor TAsmScriptUnix.Create (Const ScriptName : TCmdStr);
- begin
- Inherited Create(ScriptName);
- end;
- Procedure TAsmScriptUnix.AddAsmCommand (Const Command, Options,FileName : TCmdStr);
- begin
- if FileName<>'' then
- Add('echo Assembling '+maybequoted(ScriptFixFileName(FileName)));
- Add(maybequoted(command)+' '+Options);
- Add('if [ $? != 0 ]; then DoExitAsm '+maybequoted(ScriptFixFileName(FileName))+'; fi');
- end;
- Procedure TAsmScriptUnix.AddLinkCommand (Const Command, Options, FileName : TCmdStr);
- begin
- if FileName<>'' then
- Add('echo Linking '+ScriptFixFileName(FileName));
- Add('OFS=$IFS');
- Add('IFS="');
- Add('"');
- Add(maybequoted(command)+' '+Options);
- Add('if [ $? != 0 ]; then DoExitLink '+ScriptFixFileName(FileName)+'; fi');
- Add('IFS=$OFS');
- end;
- Procedure TAsmScriptUnix.AddDeleteCommand (Const FileName : TCmdStr);
- begin
- Add('rm ' + MaybeQuoted (ScriptFixFileName(FileName)));
- end;
- Procedure TAsmScriptUnix.AddDeleteDirCommand (Const FileName : TCmdStr);
- begin
- Add('rmdir ' + MaybeQuoted (ScriptFixFileName(FileName)));
- end;
- Procedure TAsmScriptUnix.WriteToDisk;
- Begin
- AddStart('{ echo "An error occurred while linking $1"; exit 1; }');
- AddStart('DoExitLink ()');
- AddStart('{ echo "An error occurred while assembling $1"; exit 1; }');
- AddStart('DoExitAsm ()');
- {$ifdef BEOS}
- AddStart('#!/boot/beos/bin/sh');
- {$else}
- AddStart('#!/bin/sh');
- {$endif}
- inherited WriteToDisk;
- end;
- {****************************************************************************
- MPW (MacOS) Asm Response
- ****************************************************************************}
- Constructor TAsmScriptMPW.Create (Const ScriptName : TCmdStr);
- begin
- Inherited Create(ScriptName);
- end;
- Procedure TAsmScriptMPW.AddAsmCommand (Const Command, Options,FileName : TCmdStr);
- begin
- if FileName<>'' then
- Add('Echo Assembling '+ScriptFixFileName(FileName));
- Add(maybequoted(command)+' '+Options);
- Add('Exit If "{Status}" != 0');
- end;
- Procedure TAsmScriptMPW.AddLinkCommand (Const Command, Options, FileName : TCmdStr);
- begin
- if FileName<>'' then
- Add('Echo Linking '+ScriptFixFileName(FileName));
- Add(maybequoted(command)+' '+Options);
- Add('Exit If "{Status}" != 0');
- {Add resources}
- if apptype = app_cui then {If SIOW}
- begin
- Add('Rez -append "{RIncludes}"SIOW.r -o '+ ScriptFixFileName(FileName));
- Add('Exit If "{Status}" != 0');
- end;
- end;
- Procedure TAsmScriptMPW.AddDeleteCommand (Const FileName : TCmdStr);
- begin
- Add('Delete ' + MaybeQuoted (ScriptFixFileName(FileName)));
- end;
- Procedure TAsmScriptMPW.AddDeleteDirCommand (Const FileName : TCmdStr);
- begin
- Add('Delete ' + MaybeQuoted (ScriptFixFileName (FileName)));
- end;
- Procedure TAsmScriptMPW.WriteToDisk;
- Begin
- AddStart('# Script for assembling and linking a FreePascal program on MPW (MacOS)');
- Add('Echo Done');
- inherited WriteToDisk;
- end;
- Procedure GenerateAsmRes(const st : TCmdStr);
- begin
- AsmRes:=GenerateScript(st);
- end;
- function GenerateScript(const st: TCmdStr): TAsmScript;
- var
- scripttyp : tscripttype;
- begin
- if cs_link_on_target in current_settings.globalswitches then
- scripttyp := target_info.script
- else
- scripttyp := source_info.script;
- case scripttyp of
- script_unix :
- Result:=TAsmScriptUnix.Create(st);
- script_dos :
- Result:=TAsmScriptDos.Create(st);
- script_amiga :
- Result:=TAsmScriptAmiga.Create(st);
- script_mpw :
- Result:=TAsmScriptMPW.Create(st);
- else
- internalerror(2013112805);
- end;
- end;
- {****************************************************************************
- Link Response
- ****************************************************************************}
- constructor TLinkRes.Create(const ScriptName: TCmdStr; RealResponseFile: Boolean);
- begin
- inherited Create(ScriptName);
- fRealResponseFile:=RealResponseFile;
- fForceUseForwardSlash:=false;
- end;
- procedure TLinkRes.Add(const s:TCmdStr);
- begin
- if s<>'' then
- inherited Add(s);
- end;
- procedure TLinkRes.AddFileName(const s:TCmdStr);
- var
- ls: TCmdStr;
- i: longint;
- begin
- if section<>'' then
- begin
- inherited Add(section);
- section:='';
- end;
- if s<>'' then
- begin
- ls:=s;
- if fForceUseForwardSlash then
- { Fix separator }
- for i:=1 to length(ls) do
- if (ls[i]=source_info.dirsep) then
- ls[i]:='/';
- { GNU ld only supports double quotes in the response file. }
- if fRealResponseFile and
- (ls[1]='''') and
- (((cs_link_on_target in current_settings.globalswitches) and
- (target_info.script=script_unix)) or
- (not(cs_link_on_target in current_settings.globalswitches) and
- (source_info.script=script_unix))) then
- inherited add(UnixRequoteWithDoubleQuotes(s))
- else if not(ls[1] in ['a'..'z','A'..'Z','/','\','.','"']) then
- begin
- if fForceUseForwardSlash then
- inherited Add('./'+ls)
- else if (cs_link_on_target in current_settings.globalswitches) then
- inherited Add('.'+target_info.DirSep+ls)
- else
- inherited Add('.'+source_info.DirSep+ls);
- end
- else
- inherited Add(ls);
- end;
- end;
- procedure TLinkRes.EndSection(const s:TCmdStr);
- begin
- { only terminate if we started the section }
- if section='' then
- inherited Add(s);
- section:='';
- end;
- procedure TLinkRes.StartSection(const s:TCmdStr);
- begin
- section:=s;
- end;
- end.
|