Recent

Author Topic: Any way to intercept stdout/stderr?  (Read 2066 times)

rishav

  • New Member
  • *
  • Posts: 10
Any way to intercept stdout/stderr?
« on: June 04, 2023, 10:26:52 am »
Hi

I want to intercept all the run time errors Pascal code may have, so that I can reformat some of them.
I don't want to wrap all Pascal code in try catches, instead I was wondering if I can provide a custom stdout/stderr interface to it, so that i can update the strigs on the fly.

Would anyone know how to go about this?

dbannon

  • Hero Member
  • *****
  • Posts: 3156
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Any way to intercept stdout/stderr?
« Reply #1 on: June 04, 2023, 12:34:06 pm »
rishav, I suspect most (all?) of the Pascal errors you are thinking about will terminate your application unless you handle them with a try statement.

But, maybe you are seeing some OS errors ?  The fact you know about stdout and stderr indicates you may be a linux user. GTK2, in particular generates lots of, mostly, insignificant errors. Usually distribution/desktop dependent. Damm nuisance but not much can be done about them.

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Any way to intercept stdout/stderr?
« Reply #2 on: June 04, 2023, 01:42:13 pm »
One possibility may be to do a search for "textfile device driver" on this or a Delphi forum, which miight allow you to redirect output text data for further processing or analysis.

BobDog

  • Sr. Member
  • ****
  • Posts: 394
Re: Any way to intercept stdout/stderr?
« Reply #3 on: June 04, 2023, 04:20:18 pm »

Windows.
This should redirect sdtdout/stderr to the console.(function console)
Everything else in the code is for a demo.
Code: Pascal  [Select][+][-]
  1.  
  2. uses sysutils;
  3.  
  4. function  system(s:pchar):integer ; cdecl external 'msvcrt.dll' name 'system';
  5.  function filelength(filename:ansistring):longword;
  6. Var F : File Of byte;
  7. var L:longword;
  8. begin
  9. Assign (F,filename);
  10.   Reset (F);
  11.   L:=FileSize(F);
  12.   Close (F);
  13.   exit(L);
  14. end;
  15.  
  16.  
  17.  function loadfile(filename:ansistring):ansistring;
  18.    Var Fin : File;
  19.    Var x:longint;
  20.    var content:ansistring='';
  21.    begin
  22.    x:=filelength(filename);
  23.    setlength(content,x);
  24.    Assign (Fin,filename);
  25.    Reset (Fin,x);
  26.    BlockRead (Fin,content[1],1);
  27.    close(fin);
  28.    exit(content);
  29. end;
  30.  
  31.  procedure savefile(s:ansistring ;filename:ansistring);
  32.     var
  33.     fout:file;
  34.     begin
  35.     Assign(fout,filename);
  36.     Rewrite(fout,length(s));
  37.     blockwrite(fout,s[1],1);
  38.     close(fout);
  39.   end;
  40.  
  41.  function console(cmd:ansiString):ansistring;
  42.  var
  43.  _file:string;
  44.  e:integer;
  45.  txt:ansistring='';
  46.  begin
  47.  _file:=getcurrentdir+'/'+'testcode';
  48.     e:=system(pchar(cmd+' '+' >>'+_file+' 2>&1'));
  49.      if (e=-1) then exit('error');
  50.     txt:=loadfile(_file);
  51.     if fileexists(_File) then deletefile( _File);
  52.     exit( txt);
  53. End;
  54.  
  55.  
  56.  
  57. var
  58. code:ansistring;
  59. pas:ansistring;
  60.  
  61.  
  62.  
  63. begin
  64. pas:=getcurrentdir+'\heloo.pas';
  65.  
  66. code:='var p:pinteger;'+chr(10);
  67. code:=code +'begin'+chr(10);
  68. code:=code+'writeln(p^);'+chr(10);
  69. code:=code+'readln;'+chr(10);
  70. code:=code+'end.';
  71.  
  72.  
  73. savefile(code,pas);
  74. writeln(loadfile(pas));
  75. writeln(fileexists(pas));
  76. writeln;
  77. writeln;
  78.  
  79. writeln(console('fpc -vwnhi '+ pas));
  80. writeln(console(getcurrentdir+'\heloo.exe'));
  81. //deletefile(pas);
  82. writeln('Press return to end . . .');
  83. readln;
  84. end.
  85.  
  86.  
please delete the files created by this manually.

rishav

  • New Member
  • *
  • Posts: 10
Re: Any way to intercept stdout/stderr?
« Reply #4 on: June 04, 2023, 10:40:31 pm »
Thanks everyone. I was trying to see if I can do better error reporting/formatting than what is currently possible in Free Pascal. I was hoping that it would be easier to intercept error messages than putting everything in a large try catch. :(

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: Any way to intercept stdout/stderr?
« Reply #5 on: June 05, 2023, 08:35:10 am »
I was hoping that it would be easier to intercept error messages than putting everything in a large try catch. :(
The developer is responsible for handling errors so in those cases it does output something it is your own fault  :P

But since you changed the requirement to handling unhandled  exceptions:
Code: Pascal  [Select][+][-]
  1. program catchyrhymes;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   sysutils, classes;
  7.  
  8. var
  9.   rhymes: TStringList = nil;
  10.  
  11. procedure CatchNonHandledExceptions(Obj : TObject; Addr: CodePointer; FrameCount: Longint; Frames: PCodePointer);
  12. begin
  13.   rhymes.Add('You have stumbled upon an unhandled exception');
  14. end;
  15.  
  16. procedure FamousLastWords;
  17. begin
  18.   if assigned(rhymes) then
  19.   begin
  20.     if rhymes.Count > 0 then
  21.     begin
  22.       writeln('---');
  23.       writeln(rhymes.Text);
  24.       writeln('---')
  25.     end;
  26.     FreeAndNil(rhymes)
  27.   end;
  28. end;
  29.  
  30. procedure SmartCalculation;
  31. var x,y:integer;
  32. begin
  33.   y:= 0;
  34.   x:= 1 div y
  35. end;
  36.  
  37. begin
  38.   rhymes:= TStringList.Create;
  39.  
  40.   System.AddExitProc(@FamousLastWords);
  41.   System.ExceptProc:= @CatchNonHandledExceptions;
  42.  
  43.   writeln('To calculate');
  44.   SmartCalculation;
  45.   writeln('or not to calculate')
  46. end.
  47.  
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

BobDog

  • Sr. Member
  • ****
  • Posts: 394
Re: Any way to intercept stdout/stderr?
« Reply #6 on: June 05, 2023, 12:13:40 pm »

I don't use Lazarus ide, but Geany ide will keep the console open after a crash.

In windows the command to run the .exe is
'cmd /c '+ file.exe  +'& pause'
Example:
Code: Pascal  [Select][+][-]
  1.  
  2.  
  3.  
  4. uses sysutils;
  5.  
  6. function  system(s:pchar):integer ; cdecl external 'msvcrt.dll' name 'system';
  7.  
  8.  
  9.  function filelength(filename:ansistring):longword;
  10. Var F : File Of byte;
  11. var L:longword;
  12. begin
  13. Assign (F,filename);
  14.   Reset (F);
  15.   L:=FileSize(F);
  16.   Close (F);
  17.   exit(L);
  18. end;
  19.  
  20.  
  21.  function loadfile(filename:ansistring):ansistring;
  22.    Var Fin : File;
  23.    Var x:longint;
  24.    var content:ansistring='';
  25.    begin
  26.    x:=filelength(filename);
  27.    setlength(content,x);
  28.    Assign (Fin,filename);
  29.    Reset (Fin,x);
  30.    BlockRead (Fin,content[1],1);
  31.    close(fin);
  32.    exit(content);
  33. end;
  34.  
  35.  procedure savefile(s:ansistring ;filename:ansistring);
  36.     var
  37.     fout:file;
  38.     begin
  39.     Assign(fout,filename);
  40.     Rewrite(fout,length(s));
  41.     blockwrite(fout,s[1],1);
  42.     close(fout);
  43.   end;
  44.  
  45.  
  46.  
  47. var
  48. code:ansistring;
  49. pas:ansistring;
  50. s:ansistring;
  51.  
  52.  
  53. begin
  54. pas:=getcurrentdir+'\heloo.pas';
  55.  
  56. code:='var x,y:integer;'+chr(10);
  57. code:=code +'begin'+chr(10);
  58. code:=code+'y:=0;'+chr(10);
  59. code:=code+' x:= 1 div y;'+chr(10);
  60. code:=code+'readln;'+chr(10);
  61. code:=code+'end.';
  62.  
  63.  
  64. savefile(code,pas);
  65. writeln(loadfile(pas));
  66. writeln(fileexists(pas));
  67. writeln;
  68. writeln;
  69.  
  70. system(pchar('fpc -vwnhi '+ pas));
  71.  
  72. system(pchar('cmd /c '+getcurrentdir+'\heloo.exe' +'& pause'));
  73.  
  74. end.
  75.  
  76.  
  77.  

ccrause

  • Hero Member
  • *****
  • Posts: 970
Re: Any way to intercept stdout/stderr?
« Reply #7 on: June 05, 2023, 01:04:53 pm »
I was hoping that it would be easier to intercept error messages than putting everything in a large try catch. :(
The developer is responsible for handling errors so in those cases it does output something it is your own fault  :P

But since you changed the requirement to handling unhandled  exceptions:
Code: Pascal  [Select][+][-]
  1.   System.ExceptProc:= @CatchNonHandledExceptions;

As TRon mentioned, you can hook into ExceptProc to catch unhandled exceptions. You can also hook into ErrorProc to catch runtime errors.  This way you can customize the generated output.

rishav

  • New Member
  • *
  • Posts: 10
Re: Any way to intercept stdout/stderr?
« Reply #8 on: June 05, 2023, 03:13:23 pm »
Thank you @ccrause and @TRon. I think ExceptProc and ErrorProc are exactly what I was looking for.

Thaddy

  • Hero Member
  • *****
  • Posts: 16183
  • Censorship about opinions does not belong here.
Re: Any way to intercept stdout/stderr?
« Reply #9 on: June 11, 2023, 03:12:43 pm »
AssignStream?
https://www.freepascal.org/docs-html/rtl/unix/assignstream.html

The text types are simply the handles for stdin/out/err
Linux only.
If I smell bad code it usually is bad code and that includes my own code.

 

TinyPortal © 2005-2018