consoleio.pp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2011 by the Free Pascal development team.
  4. Console i/o for the FPC FreeRTOS target
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$IFNDEF FPC_DOTTEDUNITS}
  12. Unit consoleio;
  13. {$ENDIF FPC_DOTTEDUNITS}
  14. interface
  15. type
  16. TWriteCharFunc = function(ACh: AnsiChar; AUserData: pointer): boolean;
  17. TReadCharFunc = function(var ACh: AnsiChar; AUserData: pointer): boolean;
  18. procedure OpenIO(var f: Text; AWrite: TWriteCharFunc; ARead: TReadCharFunc; AMode: word; AUserData: pointer);
  19. implementation
  20. {$i textrec.inc}
  21. type
  22. PUserData = ^TUserData;
  23. TUserData = record
  24. WriteChar: TWriteCharFunc;
  25. ReadChar: TReadCharFunc;
  26. UserData: Pointer;
  27. end;
  28. function EmptyWrite(ACh: AnsiChar; AUserData: pointer): boolean;
  29. begin
  30. EmptyWrite:=true;
  31. end;
  32. function EmptyRead(var ACh: AnsiChar; AUserData: pointer): boolean;
  33. begin
  34. EmptyRead:=true;
  35. ACh:=#0;
  36. end;
  37. procedure Console_Close(var t:TextRec);
  38. begin
  39. end;
  40. function ReadData(Func: TReadCharFunc; UserData: pointer; Buffer: PAnsiChar; count: SizeInt): SizeInt;
  41. var
  42. c: AnsiChar;
  43. got_linechar: boolean;
  44. begin
  45. ReadData:=0;
  46. got_linechar:=false;
  47. while (ReadData < count) and (not got_linechar) do
  48. begin
  49. if Func(c, UserData) then
  50. begin
  51. if c = #10 then
  52. got_linechar:=true;
  53. buffer^:=c;
  54. inc(buffer);
  55. inc(ReadData);
  56. end;
  57. end;
  58. end;
  59. Procedure Console_Read(var t:TextRec);
  60. var
  61. userdata: PUserData;
  62. begin
  63. userdata:[email protected][1];
  64. InOutRes:=0;
  65. t.bufend:=ReadData(userdata^.ReadChar,userdata^.UserData,PAnsiChar(t.bufptr),t.bufsize);
  66. t.bufpos:=0;
  67. end;
  68. Procedure Console_Write(var t:TextRec);
  69. var
  70. userdata: PUserData;
  71. p: PAnsiChar;
  72. i: SizeInt;
  73. begin
  74. if t.BufPos=0 then exit;
  75. userdata:[email protected][1];
  76. i := 0;
  77. p := PAnsiChar(t.bufptr);
  78. while i < t.bufpos do
  79. begin
  80. if not userdata^.WriteChar(p^, userdata^.UserData) then
  81. break;
  82. inc(p);
  83. inc(i);
  84. end;
  85. if i<>t.BufPos then
  86. InOutRes:=101
  87. else
  88. InOutRes:=0;
  89. t.BufPos:=0;
  90. end;
  91. procedure OpenIO(var f: Text; AWrite: TWriteCharFunc; ARead: TReadCharFunc; AMode: word; AUserData: pointer);
  92. var
  93. userdata: PUserData;
  94. begin
  95. { Essentially just init everything, more or less what Assign(f,'');
  96. does }
  97. FillChar(f,SizeOf(TextRec),0);
  98. { only set things that are not zero }
  99. TextRec(f).Handle:=UnusedHandle;
  100. TextRec(f).BufSize:=TextRecBufSize;
  101. TextRec(f).Bufptr:=@TextRec(f).Buffer;
  102. TextRec(f).OpenFunc:=nil;
  103. TextRec(f).LineEnd := #13#10;
  104. userdata:=@TextRec(f).UserData[1];
  105. TextRec(f).Mode:=AMode;
  106. case AMode of
  107. fmInput: TextRec(f).Handle:=StdInputHandle;
  108. fmOutput: TextRec(f).Handle:=StdOutputHandle;
  109. end;
  110. TextRec(f).CloseFunc:=@Console_Close;
  111. TextRec(f).FlushFunc:=nil;
  112. case AMode of
  113. fmInput: TextRec(f).InOutFunc:=@Console_Read;
  114. fmOutput:
  115. begin
  116. TextRec(f).InOutFunc:=@Console_Write;
  117. TextRec(f).FlushFunc:=@Console_Write;
  118. end;
  119. end;
  120. userdata^.WriteChar := AWrite;
  121. userdata^.ReadChar := ARead;
  122. userdata^.UserData := AUserData;
  123. end;
  124. procedure SysInitStdIO;
  125. begin
  126. OpenIO(Input, @EmptyWrite, @EmptyRead, fmInput, nil);
  127. OpenIO(Output, @EmptyWrite, @EmptyRead, fmOutput, nil);
  128. OpenIO(ErrOutput, @EmptyWrite, @EmptyRead, fmOutput, nil);
  129. OpenIO(StdOut, @EmptyWrite, @EmptyRead, fmOutput, nil);
  130. OpenIO(StdErr, @EmptyWrite, @EmptyRead, fmOutput, nil);
  131. end;
  132. procedure SysFlushStdIO;
  133. begin
  134. end;
  135. var
  136. ErrorBase : Pointer;external name 'FPC_ERRORBASE';
  137. var
  138. pstdout : ^Text;
  139. {$ifndef CPUAVR}
  140. initialization
  141. { Setup stdin, stdout and stderr }
  142. SysInitStdIO;
  143. finalization
  144. { Show runtime error and exit }
  145. pstdout:=@stdout;
  146. If erroraddr<>nil Then
  147. Begin
  148. Writeln(pstdout^,'Runtime error ',Errorcode,' at $',hexstr(erroraddr));
  149. { to get a nice symify }
  150. Writeln(pstdout^,BackTraceStrFunc(Erroraddr));
  151. dump_stack(pstdout^,ErrorBase,erroraddr);
  152. Writeln(pstdout^,'');
  153. End;
  154. SysFlushStdIO;
  155. {$endif CPUAVR}
  156. end.