newLisp compiles also on OpenBSD3.4

Started by pjot, December 02, 2004, 04:35:40 AM

Previous topic - Next topic

pjot

Hi Lutz,



Fiddling with the keyboard stuff I thought: why not try to compile on OpenBSD as well?



The BSD makefile did not work; I used the Linux makefile, but I had to adjusted this line:



$(CC) $(OBJS) -g -lm -ldl -lreadline -lncurses -o newlisp



to:



$(CC) $(OBJS) -g -lm -lreadline -lncurses -o newlisp





Thereby omitting the DL library. I used OpenBSD 3.4. It compiles OK now, and testing with a few small programs seem to work fine. I will do some more tests today.



Peter

Lutz

#1
Exactly that line is included in the BSD makefile, but out-commented and with a note to use it for NetBSD. Looks like I can add OpenBSD to the note.



I would include specific makefile for NetBSD and OpenBSD (or any other OS), if I would have access to such a system, so I could test/tune every release on it. One of the people on this board gave me permanent access to a Sparc Solaris system which is a great help.



I will release the new 'read-key' function in the next release and hope that it works on most BSD releases. The FreeBSD system I am using at my ISP may be configured in an unusual way and for that reason the function may not work there. The description of tcsetattr() and the termios.h include file are similar on Linux and BSD systems, so I think it should work. I also tried fctnl(O_NONBLOCK) on BSD but with unreliable results and no possibility to turn it back to blocking mode.



Lutz

pjot

#2
For the compilation of newLisp on OpenBSD I used the pre-installed gcc version 2.95.3 with the modified Makefile. The "file" command on the resulting binary shows:



peter@openbsd ~> file newlisp

newlisp: ELF 32-bit LSB executable, Intel 80386, version 1, for OpenBSD, dynamically linked (uses shared libs), stripped



peter@openbsd ~> ldd newlisp

newlisp:

        Start    End      Type Ref Name

        00000000 00000000 exe   1  newlisp

        0212c000 22133000 rlib  1  /usr/lib/libm.so.1.0

        0b1c0000 2b1c9000 rlib  1  /usr/lib/libreadline.so.1.0

        012d6000 212ea000 rlib  1  /usr/lib/libncurses.so.9.0

        0b2fd000 2b336000 rlib  1  /usr/lib/libc.so.30.1

        0dea2000 0dea2000 rtld  1  /usr/libexec/ld.so





For the keyboard stuff, if the termios.h file is present, one might expect it to work indeed. Thanks by the way for the new command!

Lutz

#3
Meanwhie I could try the new 'read-key' on a NetBSD system, but with the same result: getchar() always returns -1 and 'read-key' will hang in the while loop for that reason. Let me know if you can get it work on OpenBSD.



Lutz

pjot

#4
It seems not to work with OpenBSD either:

#include <termios.h>
#include <stdio.h>

int kb_hit(void)
{
struct termios term, oterm;
int fd = 0;
int c = 0;

/* get the terminal settings */
tcgetattr(fd, &oterm);

/* get a copy of the settings, which we modify */
memcpy(&term, &oterm, sizeof(term));

/* put the terminal in non-canonical mode, any
reads timeout after 0.1 seconds or when a
single character is read */
term.c_lflag = term.c_lflag & (!ICANON);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(fd, TCSANOW, &term);

/* get input - timeout after 0.1 seconds or
when one character is read. If timed out
getchar() returns -1, otherwise it returns
the character */
c=getchar();

/* reset the terminal to original state */
tcsetattr(fd, TCSANOW, &oterm);

/* return character */
return c;
}

int main()
{
sleep(1);
printf("Key pressed: %dn", kb_hit());
return 0;
}

If I run this, I receive a '-1' on the prompt. Annoying! I have to leave office now, tomorrow I can continue testing with OpenBSD...

pjot

#5
Sorry, it DOES run ok on OpenBSD but I have to press a key in time:



peter@openbsd ~> ./key

eKey pressed: 101



As you can see I pressed the "e" of which the ASCII code is 101. If I do not press a key the function returns a -1, but that is because of the timeout.

Lutz

#6
That is the same, I get, but works fine on Linux and Solaris. Also, you should change one of the lines:



from:

term.c_lflag = term.c_lflag & (!ICANON);



to:

term.c_lflag = term.c_lflag & ~ICANON;

or:

term.c_lflag &= ~ICANON;



Because !ICANON will alwyas give 0 instead of the bit-complement, which is what you want and have to do with ~ICANON. The '!' in 'C' is a logical not, not a bit-not which is the '~'



But that will not make the difference, you will still get -1. I also tried the following on BSD:



------------BSD code not working -------------

int c, flags;



flags = fcntl(0, F_GETFL);

fcntl(0, F_SETFL, flags | O_NONBLOCK);



while((c=getchar()) == -1);



fcntl(0, F_SETFL, flags);



return(c)

--------------------------------------------------



But it will not unblock, but leave things like they are before. Tried this on FeeBSD and NetBSD. Any BSD experts out there!?



Lutz

pjot

#7
I see; I will test these modifications tomorrow on OpenBSD, I cannot reach the BSD machine anymore.

pjot

#8
Indeed, it remains hanging on OpenBSD as well. So with BSD it is not going to work. I'll try to find out some things today.

pjot

#9
Hi Lutz,



I found this code which is slightly different BUT runs fine with OpenBSD:

/* readchar.c
 * Written by RenĂ© Schleicher <rs@bofh.name>
 */
#include <termios.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

int
main (void)
{
  char c;
  struct termios new_kbd_mode;
  struct termios g_old_kbd_mode;

  /* put keyboard (stdin) in raw, unbuffered mode */
  tcgetattr (0, &g_old_kbd_mode);
  memcpy (&new_kbd_mode, &g_old_kbd_mode, sizeof (struct termios));

  new_kbd_mode.c_lflag &= ~(ICANON | ECHO);
  new_kbd_mode.c_cc[VTIME] = 0;
  new_kbd_mode.c_cc[VMIN] = 1;
  tcsetattr (0, TCSANOW, &new_kbd_mode);


  if (read (0, &c, 1) != 1)
    {
      fprintf (stderr, "read() failedn");
      _exit (-1);
    }

  /* set back into old mode */
  tcsetattr (0, TCSANOW, &g_old_kbd_mode);
 
  printf ("%dn", c);
 
  return 0;
}


It performs a READ instead of a getchar(). Can you test it with FreeBSD?

Lutz

#10
Also fails on BSD, read() will always fail with 0, :( .



Seems we are out of luck on this for BSD, but I will release it anyway, as it works on all other OSs and eventually somebody will find the solution for BSD. It's just frustrating, because you would think, it is a standard thing to do.



Lutz

pjot

#11
Annoying! The 'read' seems to work with OpenBSD though, no matter how long I wait for a keypress.



You say it returns a '0', doesn't that mean the 'read' reached an EOF? Maybe something special is going on with STDIN on BSD...

Lutz

#12
YES, of course what was I thinking, it works now doing this:



while(read(0, &c, 1) == 0);



So we have it finally working now!



Lutz

pjot

#13
GREAT!! Good news! Indeed this was a pain in the you-know-what, such a simple 'standard' thing.... :-)) Thanks!

pjot

#14
In the newLisp documentation I see that the new "read-key" command does not work in Mac-OSX. How come? The gcc cross-compiler with the POSIX header files for the Mac *should* be compatible...?



I also saw this remark from some Apple developers:


Quote
termio.h

    This header file has become obsolete, and has been replaced by termios.h, which is part of the POSIX standard. These two header files are very similar, however, the termios.h does not include the same header files as termio.h. Thus, you should make sure to look directly at the termios.h to make sure it does what your application needs.


Maybe this termio.h is needed instead of termios.h?













Furhermore I noticed a small typo in the second example of the "do-until" command:
Quote
(set 'x 10)

(whole (< x 10) (inc 'x))

x                             => 10


I think the 'whole' should be 'while'?