[comp.unix.xenix] tgetent core dump on sco xenix

root@libove.UUCP (The Super User) (06/29/88)

A game was posted some time back called "puzzle". It doesn't work
under SCO Xenix development system 2.1.4g because if compiled with
small model, the single 64K segment isn't sufficient for all its
data, and if compiled under large model it core dumps along the lines
of the much simplified example that follows.

Can anyone explain this?

[root]/tmp:(1 ) % cat argle.c
#include <stdio.h>
#include <sgtty.h>

main()
	{
	char	buffer[1024];

	printf("%d\n",tgetent(buffer,getenv("TERM")));
	};
[root]/tmp:(2 ) % cc -Ml2e -o argle argle.c -ltermcap
argle.c
[root]/tmp:(3 ) % ./argle
./argle: Segmentation violation -- Core dumped
[root]/tmp:(4 ) % adb argle core
* $c
  tnamatch1d82efe8(5436., 0.)	from   tget1ent1d82efe8+320.
  tget1ent1d82efe8(4280., 71., 5436., 0.)	from _tgetent+29.
_tgetent(4280.,	71., 5436.)	from _main+38.
_main(1., 5338., 71., 5346., 71.)	from __start+94.
__start()	from start0+7.
* 
[root]/tmp:(5 ) % cc -o argle argle.c -ltermcap
argle.c
[root]/tmp:(6 ) % ./argle
1
[root]/tmp:(7 ) % 

This is an a PCs Limited AT (IBM PC/AT clone, 8 Mhz) with SCO Xenix 2.2.1
(modified with Ptydriver) and 2.1.4g development system.

Jay Libove               Internet: libove@cs.cmu.edu libove@andrew.cmu.edu
5313 Ellsworth Avenue              formtek!ditka!libove!libove@pt.cs.cmu.edu
Pittsburgh, PA 15232         UUCP: cmucspt!formtek!ditka!libove!libove
(412) 621-9649                     cadre!pitt!darth!libove!libove

rosso@sco.COM (Ross Oliver) (07/02/88)

In article <54@libove.UUCP> Jay Libove illistrates the single most
common mistake in large-model 286 programs.  The example he gives,
when compiled using "cc -M2l..." will dump core on execution:

>#include <stdio.h>
>#include <sgtty.h>
>
>main()
>	{
>	char	buffer[1024];
>
>	printf("%d\n",tgetent(buffer,getenv("TERM")));
>	};

Note that the return value of getenv() is not declared, therefore,
the compiler assumes int.  However, tgetent is expecting a char *,
and in large-model 286 programs, int != char *.  So, when main()
calls tgetent, it passes only two of the four bytes returned by
getenv().  tgetent picks up garbage data as the other two bytes,
and (suprise!) a segmentation violation results.  How can this be
fixed?  With the following declaration:

	char *getenv();

Here are a few tips to avoid problems like this in large-model
286 programs:

    - Declare your functions' return values.
    - Don't use "0" to mean NULL ( i.e. (char *)0 ).
    - Don't interchange ints and pointers, or longs and pointers.


Ross Oliver
SCO Technical Support

james@bigtex.uucp (James Van Artsdalen) (07/04/88)

IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
> Here are a few tips to avoid problems like this in large-model
> 286 programs:

>     - Declare your functions' return values.
>     - Don't use "0" to mean NULL ( i.e. (char *)0 ).

This last statement is incorrect, or rather, evidence of a broken
compiler.

C requires that the integer constant 0 be assignable to *any* pointer
type.  C also requires that any pointer type may be compared with the
integer constant 0.  If the Xenix compiler requires that the integer
constant 0 be cast to a pointer type first, it is broken.
-- 
James R. Van Artsdalen   ...!ut-sally!utastro!bigtex!james   "Live Free or Die"
Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746

markz@ssc.UUCP (Mark Zenier) (07/05/88)

In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes:
: IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
: > Here are a few tips to avoid problems like this in large-model
: > 286 programs:
: 
: >     - Declare your functions' return values.
: >     - Don't use "0" to mean NULL ( i.e. (char *)0 ).
: 
: This last statement is incorrect, or rather, evidence of a broken
: compiler.
> 
: C requires that the integer constant 0 be assignable to *any* pointer
: type.  C also requires that any pointer type may be compared with the
: integer constant 0.  If the Xenix compiler requires that the integer
: constant 0 be cast to a pointer type first, it is broken.

Until  ANSI C exists, there is no way the compiler can tell type of the 
expression for a function arguement that is pushed on the stack.
It would have been safer but much slower if Microsoft has chosen the
default integer size at 32 bits for large model compiles.

Mark Zenier	uunet!pilchuck!ssc!markz		
"Kinda scary. One guy said he had heard they were a bunch of wierdo gourmets
from somewhere in Orange County, looking for new taste thrills." 

chip@vector.UUCP (Chip Rosenthal) (07/05/88)

{{{ The original article was in comp.sources.d too. }}}

In article <3222@bigtex.uucp> you write:
}IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
}> Here are a few tips to avoid problems like this in large-model
}> 286 programs:
}>     - Declare your functions' return values.
}>     - Don't use "0" to mean NULL ( i.e. (char *)0 ).
}
}This last statement is incorrect, or rather, evidence of a broken
}compiler.

XENIX does the right thing.  You can do (char *) assignments and
comparisons with zero.  I still agree with the statement as a matter
of style, but that's a diatribe better left for comp.lang.c :-(.
-- 
Chip Rosenthal /// chip@vector.UUCP /// Dallas Semiconductor /// 214-450-0400
{uunet!warble,sun!texsun!rpp386,killer}!vector!chip
I won't sing for politicians.  Ain't singing for Spuds.  This note's for you.

james@bigtex.uucp (James Van Artsdalen) (07/05/88)

IN article <414@vector.UUCP>, chip@vector.UUCP (Chip Rosenthal) wrote:
> In article <3222@bigtex.uucp> james@bigtex.uucp wrote:
> }IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
> }>     - Declare your functions' return values.

> }This last statement is incorrect, or rather, evidence of a broken
> }compiler.

> XENIX does the right thing.  You can do (char *) assignments and
> comparisons with zero.

int *i, **p;

i = 0;
if (i != 0)
   printf("Broken compiler\n");

p = &i /* ie, not 0 */
if (p == 0)
   printf("Broken compiler\n");

Nobody is saying that "*i = 0; p = *i" needs to yield "p == 0".  But
the above tests should never fail or generate a warning under any
memory model.  I mean, if a compiler can handle

long l;

l = 0;

surely it can handle the "integer constant 0" business (and if it
doesn't handle either, you don't want it).  I can't remember if uPort
did this right with their 286 unix, but I expect better of SCO.
-- 
James R. Van Artsdalen   ...!ut-sally!utastro!bigtex!james   "Live Free or Die"
Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746

john@jetson.UUCP (John Owens) (07/05/88)

In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes:
> >     - Don't use "0" to mean NULL ( i.e. (char *)0 ).

> C requires that the integer constant 0 be assignable to *any* pointer
> type.  C also requires that any pointer type may be compared with the
> integer constant 0.  If the Xenix compiler requires that the integer
> constant 0 be cast to a pointer type first, it is broken.

Correct, as far as it goes.  0 must be *assignable* to any pointer
type, and the Xenix C compiler should extend it appropriately.  Also,
when using ANSI C function prototypes, 0 in an argument should be
extented to the size of a pointer.

But in non-ANSI C, in a large-data model, when passing a null pointer
as an argument to a function expecting a pointer argument, "0" will
not do, but "(pointer-type *)0" will.  This indicates nothing wrong
with the Xenix C compiler.]

[For anyone who's still not convinced, make the analogy to floats
(doubles, actually).  While
	double f;
	f = 0;
works, and
	double f;
	extern double fabs();
	f = fabs((double)0);
works,
	double f;
	extern double fabs();
	f = fabs(0);	/* expects a double */
will not.]

-- 
John Owens		SMART HOUSE Limited Partnership
john@jetson.UUCP	(old uucp) uunet!jetson!john
+1 301 249 6000		(internet) john%jetson.uucp@uunet.uu.net

karl@ddsw1.UUCP (Karl Denninger) (07/06/88)

In article <3291@bigtex.uucp> james@bigtex.UUCP (James Van Artsdalen) writes:
#IN article <414@vector.UUCP>, chip@vector.UUCP (Chip Rosenthal) wrote:
#> In article <3222@bigtex.uucp> james@bigtex.uucp wrote:
#> }IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
#> }>     - Declare your functions' return values.
#
#> }This last statement is incorrect, or rather, evidence of a broken
#> }compiler.
#
#> XENIX does the right thing.  You can do (char *) assignments and
#> comparisons with zero.
#
#int *i, **p;
#
#i = 0;
#if (i != 0)
#   printf("Broken compiler\n");
#
#p = &i /* ie, not 0 */
#if (p == 0)
#   printf("Broken compiler\n");
#
#Nobody is saying that "*i = 0; p = *i" needs to yield "p == 0".  But
#the above tests should never fail or generate a warning under any
#memory model.  I mean, if a compiler can handle

Under Xenix V/386 (2.2.1, 2.2.1 development set), it does not generate a 
warning on compile, nor do I get any "Broken Compiler" messages when
executing the output...

The example given compiles and runs properly under small model '386, as 
well as Small and large Model '286 code (I checked all three).

Please... check these assumptions!  Xenix may have had these problems once
upon a time.  All that's left seem to be the "infinite spill" errors
(grrr... you guys NEED to fix this one; it's the only really horrid 
irritant I have found in an otherwise excellent development system).

--
Karl Denninger (ddsw1!karl) Data: (312) 566-8912, Voice: (312) 566-8910
Macro Computer Solutions, Inc.    "Quality solutions at a fair price"

mike@cimcor.UUCP (Michael Grenier) (07/06/88)

: int *i, **p;
:
: i = 0;
: if (i != 0)
:   printf("Broken compiler\n");
:
: p = &i /* ie, not 0 */
: if (p == 0)
:   printf("Broken compiler\n");
:
: surely it can handle the "integer constant 0" business (and if it
: doesn't handle either, you don't want it).  I can't remember if uPort
: did this right with their 286 unix, but I expect better of SCO.


uPort has no problem with this.

    -Mike Grenier
     mike@cimcor.mn.org

peter@ficc.UUCP (Peter da Silva) (07/07/88)

In article <3222@bigtex.uucp>, james@bigtex.uucp (James Van Artsdalen) writes:
> IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
> > Here are a few tips to avoid problems like this in large-model
> > 286 programs:

> >     - Don't use "0" to mean NULL ( i.e. (char *)0 ).

> This last statement is incorrect, or rather, evidence of a broken
> compiler.

He's speaking in the context of a function call. Large model 286
programs have 32 bit pointers but 16 bit integers, so if you pass
0 to a function expecting a pointer the stack will be off by two
bytes.

So, the problem isn't a broken compiler, it's a broken CPU architecture.
-- 
-- `-_-' Peter (have you hugged your wolf today) da Silva.
--   U   Ferranti International Controls Corporation.
-- Phone: 713-274-5180. CI$: 70216,1076. ICBM: 29 37 N / 95 36 W.
-- UUCP: {uunet,academ!uhnix1,bellcore!tness1}!sugar!ficc!peter.

allbery@ncoast.UUCP (Brandon S. Allbery) (07/09/88)

As quoted from <54@libove.UUCP> by root@libove.UUCP (The Super User):
+---------------
| [root]/tmp:(1 ) % cat argle.c
| #include <stdio.h>
| #include <sgtty.h>
| 
| main()
| 	{
| 	char	buffer[1024];
| 
| 	printf("%d\n",tgetent(buffer,getenv("TERM")));
| 	};
| [root]/tmp:(2 ) % cc -Ml2e -o argle argle.c -ltermcap
| argle.c
| [root]/tmp:(3 ) % ./argle
| ./argle: Segmentation violation -- Core dumped
+---------------

If you use large model you have to include an "extern char *getenv();", or
tgetent() will get a truncated pointer:  C passes an undeclared function
argument as an (int), which is 2 bytes, but a large-model (char *) is 4
bytes.  This is an example of a gratuitous 680x0/Vax-ism, nonportable to
systems where sizeof (int) != sizeof (char *).

The core dump occurs when tnamatch() tries to access the string passed to
it, and gets a pointer with a random value.
-- 
Brandon S. Allbery, uunet!marque!ncoast!allbery			DELPHI: ALLBERY
	    For comp.sources.misc send mail to ncoast!sources-misc

donegan@stanton.TCC.COM (Steven P. Donegan) (07/10/88)

In article <517@cimcor.UUCP>, mike@cimcor.UUCP (Michael Grenier) writes:
> : int *i, **p;
> :
> : i = 0;
> : if (i != 0)
> :   printf("Broken compiler\n");
> :
> : p = &i /* ie, not 0 */
          ^
          syntax error - needs ';'

> : if (p == 0)
> :   printf("Broken compiler\n");
> :
> : surely it can handle the "integer constant 0" business (and if it
> : doesn't handle either, you don't want it).  I can't remember if uPort
> : did this right with their 286 unix, but I expect better of SCO.
> 
> 
> uPort has no problem with this.
> 
>     -Mike Grenier
>      mike@cimcor.mn.org

With the exception of the syntax error above, SCO 2.2.1 handled this program
fragment properly on my system. What exactly are you all trying to say about
the compiler being broken? What version of SCO's development system was under
discussion - my news feed has been down for about 8-10 days and I'm not at all
sure what point is trying to be made here. Thanks for any feedback...

allbery@ncoast.UUCP (Brandon S. Allbery) (07/12/88)

As quoted from <3222@bigtex.uucp> by james@bigtex.uucp (James Van Artsdalen):
+---------------
| IN article <701@nod2sco>, rosso@sco.COM (Ross Oliver) wrote:
| > Here are a few tips to avoid problems like this in large-model
| > 286 programs:
| 
| >     - Declare your functions' return values.
| >     - Don't use "0" to mean NULL ( i.e. (char *)0 ).
| 
| C requires that the integer constant 0 be assignable to *any* pointer
| type.  C also requires that any pointer type may be compared with the
| integer constant 0.  If the Xenix compiler requires that the integer
| constant 0 be cast to a pointer type first, it is broken.
+---------------

Only true in all cases IF (1) your compiler supports ANSI prototypes and (2)
you use them.  Otherwise, passing untyped 0 to a function expecting a pointer
fails for the same reason that the getenv() in the original code did:  the
compiler can't figure out what type is needed there, so it uses (int).
-- 
Brandon S. Allbery, uunet!marque!ncoast!allbery			DELPHI: ALLBERY
	    For comp.sources.misc send mail to ncoast!sources-misc