Forum > Unix

ReadLn does not stop reading until \n

(1/1)

doink32:
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h> int main(int argc, char *argv[]) {/* Adjust standard in and out to minimise buffering when using '\r' line endings *    * Line buffering works best for stdin *       * No buffering works best for stdout */setvbuf(stdin, NULL, _IOLBF, 0);setvbuf(stdout, NULL, _IONBF, 0);int loop = 1;size_t size = 32 * sizeof(char);char *buffer = malloc(size); if (argc != 2) {  fprintf(stderr, "Usage: %s calling_station\n", argv[0]);  exit(1);}while(loop==1) {        /* Display greeting using callsign from command line argument */printf("R,S,K,B> ");                 /* Read in a line */if (getdelim(&buffer, &size, '\r', stdin) < 0) {  fprintf(stderr, "Failed to read line\n");  exit(1);}/* Strip carriage return from response */buffer[strcspn(buffer, "\r")] = 0;         /* Reply */printf("Your Input: %s\r", buffer);if(buffer[0]=='b') {  loop=0;}}   printf("Good bye.\r");free(buffer);return 0;} 
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program Project1;{$mode fpc}{$H+}uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  sysutils,  Classes;var        //i: Longint;        callsign: string;        loop: Boolean;        choice: string; const        prompt = 'L,S,R,K,H,B> ';begin        if ParamCount<1 then        begin                write('Enter your callsign: ');                ReadLn(callsign);        end        else        begin                callsign:=ParamStr(1);        end;        callsign:=UpperCase(callsign);        writeln(callsign);        loop:=True;        while loop do begin                write(prompt);                flush(output);                ReadLn(choice);                if sizeof(choice) > 0 then begin                        if (uppercase(choice)='B') or (uppercase(choice)='BYE') then begin                                loop:=False;                        end                        else if (uppercase(choice)='L') then begin                                writeln('This would list messages');                                flush(output);                        end                        else if (uppercase(choice)='H') then begin                                writeln('This would list the help commands');                                flush(output);                        end;                end;        end; end. 

marcov:

--- Quote from: doink32 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.

--- End quote ---

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:

--- Quote from: marcov on March 04, 2020, 08:59:00 am ---
--- Quote from: doink32 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.

--- End quote ---

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

--- End quote ---
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:

--- Quote from: marcov on March 04, 2020, 08:59:00 am ---
--- Quote from: doink32 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.

--- End quote ---

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.

--- End quote ---

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

Navigation

[0] Message Index

Go to full version