Recent

Author Topic: ReadLn does not stop reading until \n  (Read 3292 times)

doink32

  • Newbie
  • Posts: 2
ReadLn does not stop reading until \n
« on: March 04, 2020, 04:27:45 am »
I have searched the web and the forum for an answer to the problem I am running into.  If I missed something, please direct me to the answer.

I am working on writing a program that will utilize AX25 on a unix system.  I have been using a Raspberry Pi but also have a full CentOS7 system.  The program is a console application that runs similar to a listening socket server (but more for AX25).

I understand that on a Unix/Linux system, ReadLn transfer information to the variable when a line feed (\n) is received.  On a Windows system it is a carriage return and line feed (\r\n).  I have also learned that some older mac systems used just carriage return (\r).

When I create a little test program and run it from a terminal, the program runs great.  When I put it in and try to work with it through AX25, it no longer behaves correctly.  The code below is one of my test programs.  When it works over AX25, I have to press the enter key 2 times (which the program receives 2 \r characters) to get it past the ReadLn.  Another observation is that if I just continue to perform inputs, the output was one <enter> press behind.

I ran into a site that talked about this problem but used C code.  Here is the link: https://thomask.sdf.org/blog/2015/09/27/ax-25-client-and-server-programming.html
Here is the modified C code (which does work):
Code: C  [Select][+][-]
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6.  
  7. int main(int argc, char *argv[]) {
  8. /* Adjust standard in and out to minimise buffering when using '\r' line endings
  9.  *    * Line buffering works best for stdin
  10.  *       * No buffering works best for stdout */
  11. setvbuf(stdin, NULL, _IOLBF, 0);
  12. setvbuf(stdout, NULL, _IONBF, 0);
  13. int loop = 1;
  14. size_t size = 32 * sizeof(char);
  15. char *buffer = malloc(size);
  16.  
  17. if (argc != 2) {
  18.   fprintf(stderr, "Usage: %s calling_station\n", argv[0]);
  19.   exit(1);
  20. }
  21. while(loop==1) {
  22.        
  23. /* Display greeting using callsign from command line argument */
  24. printf("R,S,K,B> ");
  25.                  
  26. /* Read in a line */
  27. if (getdelim(&buffer, &size, '\r', stdin) < 0) {
  28.   fprintf(stderr, "Failed to read line\n");
  29.   exit(1);
  30. }
  31. /* Strip carriage return from response */
  32. buffer[strcspn(buffer, "\r")] = 0;
  33.          
  34. /* Reply */
  35. printf("Your Input: %s\r", buffer);
  36. if(buffer[0]=='b') {
  37.   loop=0;
  38. }
  39. }  
  40. printf("Good bye.\r");
  41. free(buffer);
  42. return 0;
  43. }
  44.  

It has been many years since I have programmed in C.  While C will produce some very tight and efficient code, FPC is much more easy to deal with strings and still produce fairly tight code (it also depends on my programming skill).  I also find FPC very easy to integrate with MariaDB/MySQL.

Can someone point me in a direction that could help me get the ReadLn to work?

Thank you!
Matt

Sample code:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$mode fpc}{$H+}
  3. uses
  4.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  5.   cthreads,
  6.   {$ENDIF}{$ENDIF}
  7.   sysutils,
  8.   Classes;
  9. var
  10.         //i: Longint;
  11.         callsign: string;
  12.         loop: Boolean;
  13.         choice: string;
  14.  
  15. const
  16.         prompt = 'L,S,R,K,H,B> ';
  17. begin
  18.         if ParamCount<1 then
  19.         begin
  20.                 write('Enter your callsign: ');
  21.                 ReadLn(callsign);
  22.         end
  23.         else
  24.         begin
  25.                 callsign:=ParamStr(1);
  26.         end;
  27.         callsign:=UpperCase(callsign);
  28.         writeln(callsign);
  29.         loop:=True;
  30.         while loop do begin
  31.                 write(prompt);
  32.                 flush(output);
  33.                 ReadLn(choice);
  34.                 if sizeof(choice) > 0 then begin
  35.                         if (uppercase(choice)='B') or (uppercase(choice)='BYE') then begin
  36.                                 loop:=False;
  37.                         end
  38.                         else if (uppercase(choice)='L') then begin
  39.                                 writeln('This would list messages');
  40.                                 flush(output);
  41.                         end
  42.                         else if (uppercase(choice)='H') then begin
  43.                                 writeln('This would list the help commands');
  44.                                 flush(output);
  45.                         end;
  46.                 end;
  47.         end;
  48.  
  49. end.
  50.  

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11384
  • FPC developer.
Re: ReadLn does not stop reading until \n
« Reply #1 on: March 04, 2020, 08:59:00 am »
I have searched the web and the forum for an answer to the problem I am running into.  If I missed something, please direct me to the answer.

FPC uses the lineending character for that platform, for Linux #10 (linefeed), and not #13 (carriage return)

So simply use a read() in a repeat..until loop.

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 1058
Re: ReadLn does not stop reading until \n
« Reply #2 on: March 04, 2020, 08:56:33 pm »
I have searched the web and the forum for an answer to the problem I am running into.  If I missed something, please direct me to the answer.

FPC uses the lineending character for that platform, for Linux #10 (linefeed), and not #13 (carriage return)
FPC only uses the platform's line-ending sequence when writing. When reading, it supports #10 (*nix), #13 (classic MacOS) and #13#10 (Dos/Windows).

This means that when getting a #13, the RTL will always try to read the next character to see whether it's a #10. That is probably why you need to press enter twice (in theory any other key would be fine too, but since the input is line-buffered, only once you press enter it gets sent to the other side). At this time, there is no way to work around this behaviour of the RTL. There's even a custom classic MacOS ifdef to prevent it from doing this on that platform when reading from stdin, probably to avoid this very issue there.

doink32

  • Newbie
  • Posts: 2
Re: ReadLn does not stop reading until \n
« Reply #3 on: March 06, 2020, 06:25:52 am »
I have searched the web and the forum for an answer to the problem I am running into.  If I missed something, please direct me to the answer.

FPC uses the lineending character for that platform, for Linux #10 (linefeed), and not #13 (carriage return)

So simply use a read() in a repeat..until loop.

This is exactly what I was looking for.  I have pushed through the road block and have it reading correctly.  Thank you marcov!

 

TinyPortal © 2005-2018