earle%prophet@SUN.COM (Greg Earle) (10/18/88)
Index: gcc v 1.29, Sun-3, SunOS 4.0
Description:
It appears that when programs are built with gcc, and they
contain segments of code that first save the terminal
parameters (via a TIOCGETP ioctl(2)) and then set the terminal into
CBREAK mode, the resulting executables do not handle the ioctl
properly, and the ioctl fails with errno ENOTTY.
Repeat-By:
Compile the public domain programs `less' and `top' on a 4.3BSD-based
machine, such as a Sun running SunOS 4.0 (well, close anyway (^: ).
Note that `top' only displays one set of output and it exits; when the
ioctl in question fails, `top' assumes that the terminal must be a
`dumb' terminal and only runs itself once. Commenting out the code
that sets it to `dumb' removes this problem, but leaves `top' (and,
similarly, `less') not responding properly in CBREAK mode - i.e., an
input character in either should cause immediate action (e.g., `q'
for `quit'), but instead the character is echoed, and action waits
until a Newline is entered - i.e., the terminal isn't really in
CBREAK mode at all.
The same programs, compiled with PCC-based `cc', do not have this
problem. For specifics, refer to the `screen.c' module (same name) in
each program. Look for the line with `TIOCGETP' and the following
code, in each.
Fix:
Unknown; though I have a suspicion that perhaps one of the include
files in /usr/local/lib/gcc-include that are installed with the
`fixincludes' script could be the culprit.
Here's a sample chunk of the assembler output for the `init_screen'
function (in `top', file `screen.c'), which does this ioctl almost
immediately. Note how the value pushed for the ioctl is different
from that pushed by the PCC-based `cc', by one bit; also, note that
from doing just a preprocessor phase, both appear to be generating the
same C, so it appears to be an error in the code generation phase.
[ The PCC `cpp' output is: ]
if (ioctl(1, (0x40000000|((sizeof(struct sgttyb)&0xff)<<16)|('t'<<8)| 8), &old_settings) != 0)
[ The GCC `cpp' output is: ]
if (ioctl(1 , ( 0x40000000 |((sizeof(struct sgttyb)&0xff )<<16)|('x'<<8)| 8) , &old_settings) != 0)
====
PCC:
====
.text
.stabn 0104,0,161,LL44
LL44:
.proc
|#PROC# 04
.globl _init_screen
_init_screen:
|#PROLOGUE# 0
link a6,#0
addl #-LF100,sp
moveml #LS100,sp@
|#PROLOGUE# 1
.stabn 0104,0,161,LL45
LL45:
.stabn 0104,0,163,LL46
LL46:
clrl _errno
.stabn 0104,0,165,LL47
LL47:
pea _old_settings
pea 0x40067408 <=== *** Note this value
pea 0x1
jbsr _ioctl
lea sp@(0xc),sp
tstl d0
jeq L102
.stabn 0104,0,168,LL48
LL48:
clrb _smart_terminal
========
Gnu GCC:
========
LC17:
.ascii "TIOCGETP ioctl(init_screen)\0"
.even
.globl _init_screen
_init_screen:
.stabd 68,0,161
link a6,#0
.stabd 68,0,163
clrl _errno
.stabd 68,0,165
pea _old_settings
movel #1074165768,sp@- <=== *** THIS IS 0x40067808,
pea 1:w NOT 0x40067408 AS
jbsr _ioctl IN THE ABOVE
movel d0,d0 <=== ??? Huh?
addw #12,sp
tstl d0
jeq L16
.stabd 68,0,168
clrb _smart_terminal
Submitted-by:
Greg Earle
Sun Los Angeles Consulting
earle@Sun.COM