[gnu.gcc.bug] gcc vs. programs that use TIOCGETP/CBREAK mode

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