[SOLVED] output redirection with unit crt inserts wrong char $0A and $0D in outp lazarus / 32-Linux ---------------------------------------------------------------------- Hartmut · 2019-02-04 20:14 I use FPC 3.0.4 on Linux (Ubuntu 18.04). If you run the following code in a terminal console, you'll see 30 lines of 100 chars each: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program demo; {$mode objfpc}{$H+} uses crt; var s: string[255];    i: integer; begins:=''; for i:=1 to 10 do  s:=s + '1234567890';for i:=1 to 30 do  writeln(i:2, ' ', s);end. But if you redirect the output like Code: [Select]demo > outfile.txtyou'll have 2 strange things in your file (see attached screenshot):  - each line has wrongly inserted a Linefeed ($0A) after column 80  - from line 13 on, each line is followed by an empty line, because it ends with $0A0D instead of $0A On Windows this problem does not exist, only on Linux. I found out, that the "culprit" ist unit crt. If you omit unit crt, the problem disappears. But my "real program" uses a couple of units, which directly or indirectly use unit crt, so I can't avoid unit crt. Question #1: is this a bug or "as designed"? To avoid the problem I tried: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i begincrt.WindMaxX:=2000;crt.WindMaxY:=dword(-1);s:=''; for i:=1 to 10 do  s:=s + '1234567890';for i:=1 to 30 do  writeln(i:2, ' ', s);end. The redirected output now is correct, but now I get 2 Runtime errors: Code: [Select]hg6@i3300:~$ demo > outfile.txt Runtime error 216 at $0805D8D4   $0805D8D4   $0806EC5D Runtime error 216 at $0805D888   $0805D888   $0806EC5DRuntime error 216 means "General Protection fault. The application tried to access invalid memory space."    Question #2: does anybody know how to avoid these runtime errors or knows another way to avoid the $0A and $0D in the redirected output? Thanks in advance. ---------------------------------------------------------------------- Hartmut · 2019-02-04 20:17 to provide a 2nd screenshot I had to use this reply because of the maximum of 250 KB ---------------------------------------------------------------------- dbannon · 2019-02-04 21:49 I don't understand why crt is outputting a windows style line ending on Linux. But maybe you could provide your own line ending, do - write('stuff' + LineEnding);    Davo ---------------------------------------------------------------------- valdir.marcos · 2019-02-05 01:18 Quote from: Hartmut on February 04, 2019, 09:14:48 pmI use FPC 3.0.4 on Linux (Ubuntu 18.04). If you run the following code in a terminal console, you'll see 30 lines of 100 chars each: On Windows this problem does not exist, only on Linux. I found out, that the "culprit" ist unit crt. If you omit unit crt, the problem disappears. But my "real program" uses a couple of units, which directly or indirectly use unit crt, so I can't avoid unit crt. Question #1: is this a bug or "as designed"?   Question #2: does anybody know how to avoid these runtime errors or knows another way to avoid the $0A and $0D in the redirected output? Thanks in advance. Quote from: dbannon on February 04, 2019, 10:49:22 pmI don't understand why crt is outputting a windows style line ending on Linux. But maybe you could provide your own line ending, do - write('stuff' + LineEnding);Shouldn't this behaviour be reported as a bug? ---------------------------------------------------------------------- Handoko · 2019-02-05 03:40 I think it is not bug. Quote from: Hartmut on February 04, 2019, 09:14:48 pm - each line has wrongly inserted a Linefeed ($0A) after column 80 I remember in my old computer, the width of DOS text mode is 80. It seems the crt unit will automatically add chr($0A) when the output reach 80 characters from the left. Quote from: Hartmut on February 04, 2019, 09:14:48 pm - from line 13 on, each line is followed by an empty line, because it ends with $0A0D instead of $0A https://en.wikipedia.org/wiki/Text_mode#PC_common_text_modes The common text mode for VGA is 80x25. OP's code generate 2 output lines for each single writeln. So when it reaches the line 13th, the total screen output is the line 26th. And the crt will automatically added an extra chr($0D). Quote from: Hartmut on February 04, 2019, 09:14:48 pmThe redirected output now is correct, but now I get 2 Runtime errors: Code: [Select]hg6@i3300:~$ demo > outfile.txt Runtime error 216 at $0805D8D4   $0805D8D4   $0806EC5D crt.WindMaxX:=2000; crt.WindMaxY:=dword(-1); I'm not familiar with WindMax, but it seems that the value must be below 80x25. Quote from: Hartmut on February 04, 2019, 09:14:48 pmQuestion #2: does anybody know how to avoid these runtime errors or knows another way to avoid the $0A and $0D in the redirected output? Thanks in advance. I remember I ever heard there are crt unit alternatives. But why those behaviors don't appear on Windows? I don't know. Maybe it is OS depended. --edit-- I checked the initialization code of crt unit. I can't understand but maybe you can understand and do a temporary redirect back to normal standard output when it writes to a file (if ParamCount > 0). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Initialization{$ifdef debugcrt}  Assign(DebugFile,'debug.txt');  ReWrite(DebugFile);{$endif}  { Redirect the standard output }  assigncrt(Output);  Rewrite(Output);  TextRec(Output).Handle:=StdOutputHandle;  assigncrt(Input);  Reset(Input);  TextRec(Input).Handle:=StdInputHandle;{ Are we redirected to a file ? }  OutputRedir:= IsAtty(TextRec(Output).Handle)<>1;{ does the input come from another console or from a file? }  InputRedir :=   (IsAtty(TextRec(Input).Handle)<>1) or   (not OutputRedir and    (TTYName(TextRec(Input).Handle) <> TTYName(TextRec(Output).Handle)));{ Get Size of terminal and set WindMax to the window }  GetConsoleBuf;  WindMinX:=1;  WindMinY:=1;  WindMaxX:=ScreenWidth;  WindMaxY:=ScreenHeight;  WindMax:=((ScreenHeight-1) Shl 8)+(ScreenWidth-1);{Get Current X&Y or Reset to Home}  if OutputRedir then   begin     CurrX:=1;     CurrY:=1;   end  else   begin   { Set default Terminal Settings }     SetRawMode(True);   { Get current X,Y if not set already }     GetXY(CurrX,CurrY);     if (CurrX=0) then    begin        CurrX:=1;        CurrY:=1;        ttySendStr(#27'[H');    end;   {Reset Attribute (TextAttr=7 at startup)}      ttySendStr(#27'[m');    end; ---------------------------------------------------------------------- GAN · 2019-02-05 04:37 A String variable declared with a length specifier will always be a ShortString regardless of the compiler setting for String alias. http://wiki.freepascal.org/String But this does not solve the problem. ---------------------------------------------------------------------- Hartmut · 2019-02-05 12:03 Thanks a lot to all for your numerous replies. I will answer them one by one. Please keep in mind, that the wronlgly inserted chars $0A and $0D only appear, when the output is redirected. Without redirection everything is ok. And the problem is only in Linux, not on Windows. Quote from: dbannon on February 04, 2019, 10:49:22 pmBut maybe you could provide your own line ending, do - write('stuff' + LineEnding);    I tried it and it makes no difference. Quote from: valdir.marcos on February 05, 2019, 02:18:55 amShouldn't this behaviour be reported as a bug? That was my question... Quote from: Handoko on February 05, 2019, 04:40:59 amI think it is not bug. I remember in my old computer, the width of DOS text mode is 80. It seems the crt unit will automatically add chr($0A) when the output reach 80 characters from the left. ... The common text mode for VGA is 80x25. OP's code generate 2 output lines for each single writeln. So when it reaches the line 13th, the total screen output is the line 26th. And the crt will automatically added an extra chr($0D). This sounds convincing. But why does this behavior only occur when the output is redirected? And why not on Windows? Quote from: Handoko on February 05, 2019, 04:40:59 amcrt.WindMaxX:=2000; crt.WindMaxY:=dword(-1); I'm not familiar with WindMax, but it seems that the value must be below 80x25. If this value must be below 80x25, then this could not be a solution for my problem. But WindMaxX and WindMaxY are of type dword. They replace the deprecated variable 'WindMax', which had type Word. So I can't believe hat they must be below 80x25. Quote from: Handoko on February 05, 2019, 04:40:59 amI remember I ever heard there are crt unit alternatives. My "real program" uses a couple of units, which directly or indirectly use unit crt, so I can't avoid unit crt. Quote from: Handoko on February 05, 2019, 04:40:59 amI checked the initialization code of crt unit. I can't understand but maybe you can understand and do a temporary redirect back to normal standard output when it writes to a file (if ParamCount > 0). Thank you for providing this code. I checked it, but as far as I understand, I see nothing which is wrong or could be adapted to solve my problem. Quote from: GAN on February 05, 2019, 05:37:57 amA String variable declared with a length specifier will always be a ShortString regardless of the compiler setting for String alias. http://wiki.freepascal.org/String But this does not solve the problem. That's true. ---------------------------------------------------------------------- lucamar · 2019-02-05 13:49 I'm not sure whether this will work but try doing Code: [Select]Assign(Output, ''); Rewrite(Output) at the start of your program. ---------------------------------------------------------------------- Hartmut · 2019-02-05 18:55 Quote from: lucamar on February 05, 2019, 02:49:54 pmI'm not sure whether this will work but try doing Code: [Select]Assign(Output, ''); Rewrite(Output)at the start of your program. This works! Thank you very much for that idea, lucamar. Now my program starts like: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$IFDEF LINUX}function ConOutRedirected: boolean;   {checks if Console Output was redirected}   begin   exit(termio.IsATTY(Output) = 0); // 0=redirected / 1=normal   end; ...    if ConOutRedirected then    begin Assign(Output, ''); Rewrite(Output); end; {$ENDIF} ---------------------------------------------------------------------- lucamar · 2019-02-05 19:31 It's an old TP/BP "trick" and since normally I don't use crt I wasn't sure it would work. Mighty glad it did