Pascal Script Examples

From Free Pascal wiki
Jump to navigationJump to search

English (en) español (es)

This is a simple example of a actual script that shows how to do try except with raising a exception and doing something with the exception message.

var
   filename,emsg:string;
begin
    filename = '';
    try
       if filename = '' then
          RaiseException(erCustomError, 'File name cannot be blank');

    except
          emsg:=ExceptionToString(ExceptionType, ExceptionParam);
          //do somethign with the exception message i.e. email it or
          //save to a log etc
    end;

end.

To run the above script drop a TPSScript component on your form and either copy the above script to the script property or use the script properties LoadFromFile. We will call the TPSScript component "ps_script" for this example.

Place a button on your form and create a new Onclick event for it and add this to it:

ps_script.Script.LoadFromFile('yourscript.txt');
if ps_script.compile then
   ps_script.execute
else
   //show any compile errors
   showmessage(ps_script.CompilerErrorToStr(0));

Ok, what if some standard functions are not available in the base scripting engine? No problem, just create the OnCompile event for the TPSScript component. Here we extend the script engine by adding two functions from the standard sysutils that don't seem to be included with the base engine.

procedure TForm1.ps_ScriptCompile(Sender: TPSScript);
begin
     sender.AddFunction(@ExtractFileExt,'function ExtractFileExt(const FileName: string): string;');
     sender.AddFunction(@ExtractFileName,'function ExtractFileName(const FileName: string): string;');
 end;

Your script will now have access to these functions.



The following examples are FPC code and do not show a script.

program psce;
//enhanced with compiler messages to the shell and output to shell
//bytecode and dissasembly output
//jan 2011 www.softwareschule.ch/maxbox.htm, loc's =218
{$APPTYPE CONSOLE}

{$IFDEF FPC}
{$mode delphi}{$H+}
{$ENDIF}

uses
  SysUtils,
  Classes,
  Forms,
  uPSCompiler,
  uPSR_std,
  uPSC_std,
  uPSR_classes,
  uPSC_classes,
  uPSC_controls,
  uPSR_controls,
  uPSC_forms,
  uPSR_forms,
  uPSRuntime,
  uPSComponent,
  uPSDisassembly,
  uPSR_dateutils,
  uPSC_dateutils,
  uPSR_dll,
  uPSC_dll;

type
  TPSCE = class
   protected
    FScr: TPSScript;
    procedure SaveCompiled(var Data: String);
    procedure SaveDissasembly(var Data: String);
    procedure OnCompile(Sender: TPSScript);
    procedure OnExecImport(Sender: TObject; se: TPSExec;
                                   x: TPSRuntimeClassImporter);
   public
    constructor Create;
    destructor Destroy; override;
    function Compile(const FileName: string): Boolean;
    function Execute: Boolean;
  end;


var
  aPSCE: TPSCE;
  SFile, sData: String;


procedure MWritedt(d : TDateTime);
var
 s: String;
begin
  s:= DateToStr(d) + ' ' + TimeToStr(d);
  Write(s);
end;


procedure MWrites(const s: string);
begin
  Write(s);
end;

procedure MWritei(const i: Integer);
begin
  Write(i);
end;

procedure MWrited(const d: Double);
begin
  Write(d:0:1);
end;

procedure MWriteln;
begin
  Writeln;
end;

procedure MyVal(const s: string; var n, z: Integer);
begin
  Val(s, n, z);
end;

constructor TPSCE.Create;
begin
  FScr:= TPSScript.Create(nil);
  FScr.OnCompile:= OnCompile;
  FScr.OnExecImport:= OnExecImport;
end;

destructor TPSCE.Destroy;
begin
  FScr.Free;
end;

procedure TPSCE.SaveCompiled(var Data : String);
var
  OutFile: string;
  Fx: Longint ;
begin
  OutFile:= ExtractFilePath(ParamStr(0)) + ChangeFileExt(SFile,'.out');
  Fx:= FileCreate(OutFile) ;
  FileWrite(Fx,Data[1],Length(Data));
  FileClose(Fx) ;
end;

procedure TPSCE.SaveDissasembly(var Data: String);
var
  OutFile: string;
  Fx: Longint ;
begin
  OutFile:= ExtractFilePath(ParamStr(0)) + ChangeFileExt(SFile,'.dis');
  Fx:= FileCreate(OutFile) ;
  FileWrite(Fx, Data[1], Length(Data));
  FileClose(Fx) ;
end;


procedure TPSCE.OnExecImport(Sender: TObject; se: TPSExec; x: TPSRuntimeClassImporter);
begin
  RIRegister_Std(x);
  RIRegister_Classes(x,true);
  RIRegister_Controls(x);
  RIRegister_Forms(x);
  RegisterDateTimeLibrary_R(se);
  RegisterDLLRuntime(se);
end;

procedure TPSCE.OnCompile(Sender: TPSScript);
begin
  RegisterDateTimeLibrary_C(Sender.Comp);
  Sender.AddFunction(@MWrites, 'procedure Writes(const s: string)');
  Sender.AddFunction(@MWritedt,'procedure WriteDT(d : TDateTime)');
  Sender.AddFunction(@MWritei, 'procedure Writei(const i: Integer)');
  Sender.AddFunction(@MWrited, 'procedure Writed(const f: Double)');
  Sender.AddFunction(@MWriteln, 'procedure Writeln');
  Sender.AddFunction(@MyVal, 'procedure Val(const s: string; var n, z: Integer)');
  Sender.AddFunction(@FileCreate, 'Function FileCreate(const FileName: string): integer)');
  Sender.AddFunction(@FileWrite, 'function FileWrite(Handle: Integer; const Buffer: pChar; Count: LongWord): Integer)');
  Sender.AddFunction(@FileClose, 'Procedure FileClose(handle: integer)');
  //Sender.AddRegisteredVariable('Application', 'TApplication');
  SIRegister_Std(Sender.Comp);
  SIRegister_Classes(Sender.Comp,true);
  SIRegister_Controls(Sender.Comp);
  SIRegister_Forms(Sender.Comp);
end;


function TPSCE.Compile(const FileName: string): Boolean;
var
  S: TStringList;
  i: Integer;
begin
  Result:= False;
  if FileExists(FileName) then begin
    S:= TStringList.Create;
    S.LoadFromFile(FileName);
    FScr.Script:= S;
    Result:= FScr.Compile;
    for i:= 0 to aPSCE.FScr.CompilerMessageCount - 1 do
      writeln(aPSCE.FScr.CompilerMessages[i].MessageToString);
    S.Free;
    if not Result then
      if FScr.CompilerMessageCount > 0 then
        for i:= 0 to FScr.CompilerMessageCount-1 do
          Writeln(FScr.CompilerErrorToStr(i));
      end else Writeln('Script File not found: ', FileName);
end;

function TPSCE.Execute: Boolean;
begin
  //FScr.SetVarToInstance('APPLICATION', Application);
  //FScr.SetVarToInstance('SELF', Self);
  Result:= FScr.Execute;
  //writeln(FScr.About);
  if not Result then
    Writeln('Run-time error:' + FScr.ExecErrorToString);
end;


begin  //main
  Application.Initialize;
  aPSCE:= TPSCE.Create;
  if ParamCount = 0 then begin
    Writeln('Usage: ', ExtractFileName(ParamStr(0)), ' [--compile|--dissasembly] <script.pss>');
    Writeln('');
    Writeln('--compile : Save compiled script bytecode');
    Writeln('--dissasembly: Save dissasembly of script');
    Exit;
  end;
 SFile:= ParamStr(1);
 if (ParamStr(1)='--compile') or (ParamStr(1)='--dissasembly') then begin
  SFile:= ParamStr(2);
  aPSCE.Compile(SFile);
  aPSCE.Execute;   //output on shell
  aPSCE.FScr.GetCompiled(sData);
  if Paramstr(1)='--compile' then begin
    aPSCE.FScr.Comp.GetOutput(sData);
    aPSCE.SaveCompiled(sData);
  end;
  if Paramstr(1)='--dissasembly' then begin
    aPSCE.FScr.GetCompiled(sData);
    if not IFPS3DataToText(sData, sData)
      then begin
        Writeln('Create or create not dissasembly!');
        aPSCE.SaveDissasembly(sData);  //do it anyway
    end else
    aPSCE.SaveDissasembly(sData);
  end;
  Exit;
 end;
 aPSCE.Compile(SFile);
 aPSCE.Execute;
 aPSCE.Free;
end.


2. Example of Lazarus with GUI Components

unit unit1pscript2;
//compiled by max
////oct 2014: www.softwareschule.ch/maxbox.htm

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, SynMemo, SynHighlighterPas, uPSComponent,
  uPSComponent_Default, uPSComponent_StdCtrls, uPSComponent_Forms, Forms,
  Controls, Graphics, Dialogs, StdCtrls, Buttons, ExtCtrls, uPSRuntime,
  uPSComponent_DB, uPSCompiler;

type

  { TpsForm1 }
   TpsForm1 = class(TForm)
    btnImport: TBitBtn;
    btnCompile: TBitBtn;
    btnSaveScript: TBitBtn;
    btnSaveComp: TBitBtn;
    btnLoadScript: TBitBtn;
    btngetCompiled: TBitBtn;
    btnExecute: TButton;
    btnRunbytecode: TButton;
    Image1: TImage;
    Image2: TImage;
    Memo1: TMemo;
    PSImport_Classes1: TPSImport_Classes;
    PSImport_DateUtils1: TPSImport_DateUtils;
    PSImport_DB1: TPSImport_DB;
    PSImport_Forms1: TPSImport_Forms;
    PSImport_StdCtrls1: TPSImport_StdCtrls;
    PSScript1: TPSScript;
    SynMemo1: TSynMemo;
    SynPasSyn1: TSynPasSyn;
    procedure btnImportClick(Sender: TObject);
    procedure btnLoadScriptClick(Sender: TObject);
    procedure btnRunbytecodeClick(Sender: TObject);
    procedure Compile1Click(Sender: TObject);
    procedure btnSaveScriptClick(Sender: TObject);
    procedure btnSaveCompClick(Sender: TObject);
    procedure btngetCompiledClick(Sender: TObject);
    procedure btnExecuteClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure PSScript1AfterExecute(Sender: TPSScript);
    procedure PSScript1Compile(Sender: TPSScript);
    procedure PSScript1CompImport(Sender: TObject; x: TPSPascalCompiler);
    procedure PSScript1ExecImport(Sender: TObject; se: TPSExec;
      x: TPSRuntimeClassImporter);
    procedure SynMemo1Change(Sender: TObject);
  private
    function RunCompiledScript2(Bytecode: AnsiString; out
      RuntimeErrors: AnsiString): Boolean;
    { private declarations }
  public
    { public declarations }
  end;

Const SCRIPTFILE = 'paswiki2.txt';

var
  psForm1: TpsForm1;

implementation

{$R *.lfm}

 uses  uPSDisassembly;

{ TpsForm1 }

procedure TpsForm1.btnExecuteClick(Sender: TObject);
var res: boolean;
begin
  //showmessage('run max box');
   Res:= PSScript1.Execute;
   if not Res then
     memo1.lines.add('Run-time error:'+ PSScript1.ExecErrorToString) else
       image1.Show;
end;

procedure MWritedt(d : TDateTime);
var
 s: String;
begin
  s:= DateToStr(d) + ' ' + TimeToStr(d);
  psForm1.memo1.lines.add(s);
end;

procedure MWrites(const s: string);
begin
  psForm1.memo1.lines.add(s);
end;

procedure MWritei(const i: Integer);
begin
  psForm1.memo1.lines.add(inttostr(i));
end;

procedure MVal(const s: string; var n, z: Integer);
begin
  Val(s, n, z);
end;


procedure TpsForm1.FormActivate(Sender: TObject);
begin
  synmemo1.Text:= '';
  synmemo1.Lines.LoadFromFile(SCRIPTFILE);
  self.caption:= SCRIPTFILE +' loaded '+caption;
  btnsaveComp.enabled:= false;
  btnExecute.enabled:= false;
  image1.hide;
end;

procedure TpsForm1.PSScript1AfterExecute(Sender: TPSScript);
begin
  //
end;

procedure TpsForm1.PSScript1Compile(Sender: TPSScript);
begin
  //your own executables
  Sender.AddFunction(@MWrites, 'procedure Writes(const s: string)');
  Sender.AddFunction(@MWritedt,'procedure WriteDT(d : TDateTime)');
  Sender.AddFunction(@MWritei, 'procedure Writei(const i: Integer)');
  Sender.AddFunction(@MWrites, 'procedure Writeln(const s: string)');  //alias
  Sender.AddFunction(@MVal, 'procedure Val(const s: string; var n, z: Integer)');
end;

procedure TpsForm1.PSScript1CompImport(Sender: TObject; x: TPSPascalCompiler);
begin
  {uPSC_std.SIRegister_Std(X);
  uPSC_classes.SIRegister_Classes(X,true);
  SIRegister_Forms(x);
  SIRegister_Controls(x);}
end;

procedure TpsForm1.PSScript1ExecImport(Sender: TObject; se: TPSExec;
  x: TPSRuntimeClassImporter);
begin
  //add lib at run- or designtime
  {  RIRegister_Std(x);
  RIRegister_Classes(x,true);
  RIRegister_Forms(x);
  RIRegister_Controls(x);
  RegisterDateTimeLibrary_R(se);
  RegisterDLLRuntime(se); }
  {Se.RegisterDelphiFunction(@MWrites, 'procedure Writes(const s: string)', cdRegister);
  Se.RegisterDelphiFunction(@MWritedt,'procedure WriteDT(d : TDateTime)', cdRegister);
  Se.RegisterDelphiFunction(@MWritei, 'procedure Writei(const i: Integer)', cdRegister);
  Se.RegisterDelphiFunction(@MWrites, 'procedure Writeln(const s: string)', cdRegister);  //alias
  Se.RegisterDelphiFunction(@MVal, 'procedure Val(const s: string; var n, z: Integer)', cdRegister);
  }
  // showmessage('import PORT ')
  //x.RegisterMethod(@MWrites, 'procedure Writes(const s: string)');
end;

procedure TpsForm1.SynMemo1Change(Sender: TObject);
begin
  //showmessage('to debug gutter');
end;

procedure TpsForm1.Compile1Click(Sender: TObject);
var
//S: TStringList;
i: Integer;
result: boolean;
  //showmessage('compile file');
begin
  Result:= False;
  //if FileExists(FileName) then begin
    //S:=TStringList.Create;
    //S.LoadFromFile(FileName);
    PSScript1.Script.Text:= Synmemo1.Text;
    result:= Psscript1.Compile;
    for i:= 0 to Psscript1.CompilerMessageCount - 1 do
      memo1.lines.add(Psscript1.CompilerMessages[i].MessageToString);
    //S.Free;
    if not Result then
      if Psscript1.CompilerMessageCount > 0 then
        for i:= 0 to Psscript1.CompilerMessageCount-1 do
          memo1.lines.add(Psscript1.CompilerErrorToStr(i));
    //else memo1.lines.add('Script File not found: ', FileName); }
    if Result then begin
      btnExecute.Enabled:= true;
      btnsaveComp.enabled:= true;
    end;
end;

procedure TpsForm1.btnLoadScriptClick(Sender: TObject);
begin
 synMemo1.lines.loadFromFile(SCRIPTFILE)
end;

procedure TpsForm1.btnImportClick(Sender: TObject);
begin
  //psForm1.Close;
 {if synmemo1.Focused then} synMemo1.PasteFromClipboard;
end;


function TpsForm1.RunCompiledScript2(Bytecode: AnsiString; out RuntimeErrors: AnsiString): Boolean;
var Runtime: TPSExec;  //to debug
begin
  Runtime:= TPSExec.Create;
  try
    //IFPS3ClassesPlugin1ExecImport(Self, runtime, classImporter);
    //PSScript1.RuntimeImporter.CreateAndRegister(runtime, false);
     result:= PSScript1.Exec.LoadData(bytecode)
             and PSScript1.Exec.RunScript and (PSScript1.Exec.ExceptionCode = erNoError);
     if not result then
       RunTimeErrors:= PSErrorToString(PSScript1.Exec.ExceptionCode,'');

    //PSScript1.SetCompiled(Bytecode);
    //IFPS3DataToText(Bytecode,Bytecode);
    //memo1.lines.add(bytecode);
  finally
    Runtime.Free;
  end;
end;


function LoadFile(const FileName: TFileName): string;
   begin
     with TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite) do begin
       try
         SetLength(Result, Size);
         Read(Pointer(Result)^, Size);
       except
         Result := '';  // Deallocates memory
         Free;
         raise;
       end;
       Free;
     end;
   end;


procedure TpsForm1.btnRunbytecodeClick(Sender: TObject);
var sdata, filename, bcerrorcode: string;
  fhandle: THandle;
begin
   //sdata:= synmemo1.Text;
   //Compile1Click(self);
   //PSScript1.GetCompiled(sData);
    filename:= ExtractFilePath(ParamStr(0)) + ChangeFileExt(SCRIPTFILE,'.out');
    //fhandle:= fileopen(filename, 2);
    //fileread(fhandle, sdata, 100);
   sdata:= loadFile(filename);
   if RunCompiledScript2(sdata, bcerrorcode) then begin
       sysutils.beep;
       showmessage('Byte Code run success')
   end else
      Memo1.lines.add('ByteCode Error Message: '+bcerrorcode);
    // fileclose(fhandle)
   //PSScript1.SetCompiled(sData);
   //synmemo1.Text:= sData;
   //btnExecuteClick(self)
end;

procedure TpsForm1.btnSaveScriptClick(Sender: TObject);
begin
  synMemo1.lines.saveToFile(SCRIPTFILE)
end;

procedure TpsForm1.btnSaveCompClick(Sender: TObject);
var
  OutFile, sdata: string;
  Fx: Longint ;
begin
  PSScript1.GetCompiled(sData);
  OutFile:= ExtractFilePath(ParamStr(0)) + ChangeFileExt(SCRIPTFILE,'.out');
  Fx:= FileCreate(OutFile) ;
  FileWrite(Fx,sData[1],Length(sData));
  FileClose(Fx) ;
end;

procedure TpsForm1.btngetCompiledClick(Sender: TObject);
var sdata: string;
begin
   PSScript1.GetCompiled(sData);
   // {if not} PSScript1.SetCompiled(sData);
   if not IFPS3DataToText(sData,sData)
     then memo1.lines.add('¡No puedo crear el desensamblado!')
   else
     synmemo1.Text:= sData;
  //aPSCE.SaveDissasembly(sData);
end;

end.

maXbox mini LAZARUS.png maXbox mini LAZARUS2.png