bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Wrong 'baud_rate' initialization


From: Matthias Habl t2065
Subject: Wrong 'baud_rate' initialization
Date: Tue, 19 Jun 2001 09:17:44 +0200 (MET DST)

In GNU Emacs 20.6.2 (i586-acer-netbsd1.4.2, X toolkit)
 of Sat Apr 29 2000 on mhibsd
configured using `configure  i586-acer-netbsd1.4.2 --with-pop --with-kerberos'

Please describe exactly what actions triggered the bug
and the precise symptoms of the bug:

I'm using a VT520 at a baud rate of 115200. But the internal variable
'baud-rate' of Emacs claims that it would be only 9600. A detailed
examination of this inconsistency revealed some considerable bugs in
'sysdep.c', especially in the function init_baud_rate(). In the
following, I'm trying to demonstrate the inadequacies:

In file 'sysdep.c', line 244 (all line numbers refer to version 20.7):

        extern short ospeed;

This is correct, because the manpage TERMCAP(3) says:

        short ospeed;

And really, the program 'nm' yields:

        /usr/lib/libtermcap.a:
        tputs.o:
                 U __ctype_     tputs.o:0
        00000004 C _PC
        00000004 C _ospeed
        0000003c T _tputs

But later we will see that a definition like

        speed_t ospeed;

would be better, because 'speed_t' (= unsigned) hat usually 32bits.

Let us see what happens in init_baud_rate(), file sysdep.c,
from line 334:

        struct termios sg;

        sg.c_cflag = B9600;
        tcgetattr (input_fd, &sg);
        ospeed = cfgetospeed (&sg);

Does the statement 'sg.c_cflag = B9600' make any sense? The member
'c_cflag' of the structure 'termios' is a bit pattern, which contains
information about parity, number of stop bits, word size, method of
handshaking and so on. Something like 'sg.c_ospeed = B9600' would be
more reasonable, but just as useless.

The first problem arises with 'ospeed = cfgetospeed (&sg)'. The 
function 

        speed_t cfgetospeed(const struct termios *t)

returns an unsigned (4 bytes), which is converted to the short int of
'ospeed'. Actually, debugging yielded, that 'ospeed' has the the value
49664 = 0xc200 instead of 115200 = 0x1c200, which is wrong.

Then in line 389 of 'sysdep.c' something happens, which is completely
wrong:

          baud_rate = (ospeed < sizeof baud_convert / 
                                sizeof baud_convert[0]
               ? baud_convert[ospeed] : 9600);

Here 'ospeed', which is already the wanted baud rate, is converted by
a formula, which yields for 'ospeed > 15' allways 9600.

I think the reason for the described bugs is the mixture of different,
partly obsolete mechanisms for describing terminals. There are two
important structures. First (in termios.h):

typedef unsigned int    tcflag_t;
typedef unsigned char   cc_t;
typedef unsigned int    speed_t;

struct termios {
        tcflag_t        c_iflag;        /* input flags */
        tcflag_t        c_oflag;        /* output flags */
        tcflag_t        c_cflag;        /* control flags */
        tcflag_t        c_lflag;        /* local flags */
        cc_t            c_cc[NCCS];     /* control chars */
        int             c_ispeed;       /* input speed */
        int             c_ospeed;       /* output speed */
};

On the other hand there is a quite obsolete structure:

struct sgttyb {
        char    sg_ispeed;              /* input speed */
        char    sg_ospeed;              /* output speed */
        char    sg_erase;               /* erase character */
        char    sg_kill;                /* kill character */
        short   sg_flags;               /* mode flags */
};

which can be handled with

        #include <sgtty.h>
        stty(int fd, struct sgttyb *buf);
        gtty(int fd, struct sgttyb *buf);

or with 'ioctl (input_fd, TIOCGETP, &sg)'.

I think the conversion with 'baud_convert' was originally written for
'sgttyb.sg_ospeed' and is also used for 'termios.c_ospeed' by mistake.

For my system (and probably many others) something like

        struct termios t;

        tcgetattr (input_fd, &t);
        baud_rate = cfgetospeed (&t);

would be the right thing.

I hope this is a useful contribution for the improvement of the
great Emacs. If you like, I'm willing to design a patch.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]