(* Output the content of a file, iff there are multiple lines they will be
separated by the OS-specific line ending. Optionally, tabs may be converted
to single spaces and then multiple consecutive spaces collapsed to single.
*)
function cat(const fn: string; match: string= '';
collapseWhitespace: boolean= false): string;
var
sl: TStringList;
i: integer;
begin
result := '';
try
sl := TStringList.Create;
try
sl.LoadFromFile(fn);
(* The RTL documentation says that the strings will be separated by the EOL *)
(* marker, but this cannot be trusted: assume that there might be a terminator *)
(* which should be removed (and that also removing any trailing spaces is not *)
(* likely to cause problems to the caller). *)
if match = '' then
result := TrimRight(sl.Text)
else begin
for i := 0 to sl.Count - 1 do begin
if collapseWhitespace then
sl[i] := DelSpace1(Tab2Space(sl[i], 1));
if Pos(match, sl[i]) > 0 then begin
if result <> '' then
result += LineEnding;
result += sl[i]
end
end
end
finally
FreeAndNil(sl)
end
except (* Inability to open or read the file *)
end (* returns an empty string. *)
end { cat } ;
(* Under Linux, return true if the program is running under a debugger (gdb or
fpcdebug). The rationale for this is that there might be problems catching
e.g. the HUP and USR1 signals while debugging, so it is desirable to add menu
entries or some sort of "easter egg" to the GUI to simulate them.
*)
function isDebuggerPresent(): boolean;
const
xIsDebuggerPresent: byte= 2; (* Static variable *)
begin
if not (xIsDebuggerPresent in [0, 1]) then
xIsDebuggerPresent := Ord(cat('/proc/' + IntToStr(GetProcessID()) + '/status',
'TracerPid:', true) <> 'TracerPid: 0');
result := boolean(xIsDebuggerPresent)
end { isDebuggerPresent } ;
...
asm
int3
end;