Sign in Join
Wiki copytemporary

Revision 2 of 3, by Trev on 11-23-2021. The page as it is now.

Rosetta Stone

Introduction

Often, people new to a programming language/library have trouble mapping the things they know how to do in other environments to the new environments.

It can be handy to have a sort of "Rosetta stone" that roughly translates tasks from one environment/language into another.

Programming languages

If you have experience in other programming languages (such as C++, Visual Basic), there are some Rosetta stone web pages that might help you. As the Free Pascal/Lazarus syntax and library is fairly consistent with Delphi's, sites that "translate" to Delphi are also a valuable resource.

Some useful pages:

Operating systems

If you know how to do something in an operating system, chances are you can do the same using FPC/Lazarus.

The table below gives a rough mapping of some tasks:

Windows/DOS

Unix/Linux

Description

FreePascal/Lazarus

assoc

Show/edit file associations

See FileAssociation

copy

cp

Copy file

Lazarus fileutil.copyfile; roll your own with filestreams, see e.g. File_Handling_In_Pascal#FileCopy

date /t

date

Show current date

sysutils.now (date/time); sysutils.date (date); sysutils.time (time)

del, erase

rm, rm -f

Delete file

sysutils.deletefile, erase

deltree, rmdir /s

rm -r,rm -rf

Remove directories with subdirectories

Lazarus fileutil.deletedirectory

dir

ls

Find files in a directory

Lazarus FindAllFiles

diskpart list volume

mount

Show partitions/volumes/drives on a computer

Windows: see Windows_Programming_Tips#Listing_all_available_drives

Linux: see Linux_Programming_Tips#Get_the_list_of_mounted_partitions

Unix: you'll have to parse some files (e.g. /etc/mtab) yourself, depending on Unix flavour; see Forum post

find

grep

Search for a text/string

Several options, including the pos, ansipos functions. Regular expression support is provided by the RegEx packages.

ldifde

ldapsearch

Search through Active Directory/LDAP

Use Synapse ldapsend unit to work with LDAP queries; see e.g. example code on Leonardo Ramé's blog

md5sum

md5sum

Calculate hash of file contents

You can use the MDFile function in the md5 FPC unit.

mkdir

mkdir

Create directory

mkdir; forcedirectories (creates entire path, if necessary)

move

mv

Move file to another directory

Within partition/disk: sysutils.renamefile; otherwise copy and delete original

rename, ren

mv

Rename file

sysutils.renamefile (can also "move" a file between directories, but only on same partition/disk

sc query <servicename>

service --status-all

Show status for service

See ServiceManager

?

sed -i 's|Delphi|FreePascal|g' readme.txt

Search and replace text in file.

See example code below.

shutdown

shutdown

Shut down computer

Windows: see forum post

tasklist

ps

List or find processes

Windows: Windows_Programming_Tips#Showing.2Ffinding_processes

?

touch

Create a new empty file

sysutils.filecreate(filename)

?

touch

Modify file time

See Create a new file date/de

?

uname

Get kernel/system info

See uname function below.

wget, curl

wget, curl

Download file from HTTP/FTP

Multiple options, e.g. use synapse httpsend or ftpsend units: Synapse#Downloading_files

?

which

Search for executable in path

Lazarus fileutil.FindDefaultExecutablePath; see also the example below.

?

whoami

Find out username

See UserName function below. On Windows: you can check if you're Administrator: winutils.iswindowsadmin(). On *nix: fpgeteuid shows you the effective userid (0 for root).

Emulating uname

Works on Linux, probably FreeBSD:

pascal
program uname;

uses  baseunix;

var KernelName: UtsName;

begin
 fpuname(KernelName);
 writeln(kernelname.sysname);
 writeln(kernelname.nodename);
 writeln(kernelname.release);
 writeln(kernelname.version);
 writeln(kernelname.machine);
 writeln(kernelname.domain);
end.

Sample output:

Linux
mydebianmachine
3.12-1-amd64
#1 SMP Debian 3.12.6-2 (2013-12-29)
x86_64
(none)

Emulating which

Although Lazarus has FindDefaultExecutablePath, it has some flaws. Use e.g. this code:

pascal
function Which(Executable: string): string;
var
  Output: string;
begin
  {$IFDEF UNIX}
  // Note: we're using external which because
  // FindDefaultExecutablePath
  // doesn't check if the user has execute permission
  // on the found file.
  ExecuteCommand('which '+Executable,Output,false);
  // Remove trailing LF(s) and other control codes:
  while (length(output)>0) and (ord(output[length(output)])<$20) do
    delete(output,length(output),1);
  {$ELSE}
  Output:=FindDefaultExecutablePath(Executable);
  {$ENDIF UNIX}
  // Extra check:
  if (Output<>'') and fileexists(Output) then
  begin
    result:=Output;
  end
  else
  begin
    result:=''; //command failed
  end;
end;

Emulating whoami

... or getting the current user's operating system username. Returns a UTF8 string.

pascal
uses
  {$IFDEF UNIX}
  {$IF (DEFINED(LINUX)) OR (DEFINED(FREEBSD))}
  ,users //not available on OSX
  {$ENDIF}
  ,baseunix //for fpgetuid
  .... //other unix stuff
  {$ENDIF}
  {$IFDEF MSWINDOWS}
  ,windows
  {$ENDIF}
  ,lazutf8

function UserName: string;
// Get Operating System user name
{$IFDEF WINDOWS}
const
  MaxLen = 256;
var
  Len: DWORD;
  WS: WideString;
  Res: windows.BOOL;
{$ENDIF}
begin
  Result := '';
  {$IFDEF WINDOWS}
    Len := MaxLen;
    {$IFNDEF WINCE}
    // Check for Win98..WinME:
    if Win32MajorVersion <= 4 then
    begin
      SetLength(Result,MaxLen);
      Res := Windows.GetUserName(@Result[1], Len);
      if Res then
      begin
        SetLength(Result,Len-1);
        Result := SysToUtf8(Result);
      end
      else
        SetLength(Result,0);
    end
    else
    {$ENDIF NOT WINCE}
    begin
      SetLength(WS, MaxLen-1);
      Res := Windows.GetUserNameW(@WS[1], Len);
      if Res then
      begin
        SetLength(WS, Len - 1);
        Result := Utf16ToUtf8(WS);
      end
      else
        SetLength(Result,0);
    end;
    {$ENDIF WINDOWS}
    {$IFDEF UNIX}
    {$IF (DEFINED(LINUX)) OR (DEFINED(FREEBSD))}
    Result := SysToUtf8(GetUserName(fpgetuid));
    {$ENDIF}
    if Result = '' then
      Result := GetEnvironmentVariableUTF8('USER'); //fallback or other unixes which export $USER and don't support GetUserName
  {$ENDIF}
end;

Finding all occurrences of some bytes in a file

A sort of grep. From forum post by KpjComp: 1

The block search class:

pascal
unit block_search;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, fgl;

type

  { TBlockSearch }
  TBlockSearchResults = specialize TFPGList<int64>;

  TBlockSearch = class
  private
    src:TStream;
    fresults:TBlockSearchResults;
    block:array of byte;
  public
    procedure SearchFor(a:array of byte);
    constructor Create(_Src:TStream; blocksize:integer = 1024*1024);
    destructor Destroy; override;
    property Results:TBlockSearchResults read fResults;
  end;

implementation

{ TBlockSearch }

procedure TBlockSearch.SearchFor(a: array of byte);
var
  readsize:integer;
  fPos:Int64;
  fifoBuff:array of byte;
  fifoSt,fifoEn,searchLen,lpbyte:integer;

  //
  procedure CheckPos;
  var
    l,p:integer;
  begin
    p := fifoST;
    for l := 0 to pred(SearchLen) do
    begin
      if a[l] <> fifoBuff[p] then exit;
      //p := (p+1) mod SearchLen,   the if seems quicker
      inc(p); if p >= SearchLen then p := 0;
    end;
    fresults.Add(fpos-searchLen);
  end;
  //
begin
  fresults.clear;
  src.Position:=0;
  readsize := src.Read(block[0],Length(block));
  searchLen := length(a);
  if searchLen > length(block) then
    raise Exception.Create('Search term larger than blocksize');
  if readsize < searchLen then exit;
  setlength(fifoBuff,searchLen);
  move(block[0],fifoBuff[0],searchLen);
  fPos:=0;
  fifoSt:=0;
  fifoEn:=SearchLen-1;
  CheckPos;
  while readsize > 0 do
  begin
    for lpByte := 0 to pred(readsize) do
    begin
      inc(fifoSt); if fifoSt>=SearchLen then fifoST := 0;
      inc(fifoEn); if fifoEn>=SearchLen then fifoEn := 0;
      fifoBuff[fifoEn] := block[lpByte];
      inc(fPos);
      CheckPos;
    end;
    readsize := src.Read(block[0],Length(block));
  end;
end;

constructor TBlockSearch.Create(_Src: TStream; blocksize: integer);
begin
  inherited Create;
  setlength(block,blocksize);
  src := _src;
  fresults := TBlockSearchResults.Create;
end;

destructor TBlockSearch.Destroy;
begin
  freeAndNil(fresults);
  inherited Destroy;
end;

end.

Example of usage:

pascal
var
  bs:TBlockSearch;
..
..
  bs := TBlockSearch.Create(SourceFile);
  try
    bs.SearchFor(WhatIAmSearchingFor);
    for i := 0 to bs.results.count-1 do
    begin
      // Example: we need to do something at an offset after the result
      SourceFile.Position := bs.Results.Items[i] + 5;
      SourceFile.ReadBuffer(RecordToParse, SizeOf(RecordToParse)); 
      // And now I work on the data in the second packed record of arrays and output to memo or whatever
    end;
  finally
    bs.free;
  end;

Search and replace in a file

This will search and replace by loading the entire file into the stringlist in memory and replacing there, then saving the stringlist again. While fine for small files, performance will likely suffer for large files.

pascal
procedure FindAndReplace(SearchFor, ReplaceWith, FileName: string);
var
  FileContents: TStringList;
begin
  FileContents:=TStringList.Create;
  try
    FileContents.LoadFromFile(FileName);
    FileContents.Text:=StringReplace(FileContents.Text, SearchFor, ReplaceWith, [rfReplaceAll,rfIgnoreCase]);
    FileContents.SaveToFile(FileName);
  finally
    FileContents.Free;
  end;
end;

From the Free Pascal wiki, page "Rosetta Stone", as it stood on 2021-11-23 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.