[gnu.gcc.bug] bug in sparc gcc 1.28

trq@moose.cita.toronto.edu (Tom Quinn) (09/21/88)

The sparc assembler under SunOS 3.2-Sys4 and SunOS 4.0 turn the line:
.common _line,280,"bss"
into a global symbol, hence it can not be used to allocate bss space
for local symbols.  There is a directive ".reserve" which will
accomplish this.

Repeat by:
compile the file:
---------------------------------------------------
static char line[200 + 80], *eptr = line, *lptr = line;
---------------------------------------------------

nm file.o will give:
00000000 d _eptr
00000008 C _line
00000004 d _lptr
instead of:
00000000 d _eptr
00000008 b _line
00000004 d _lptr

My fix:

diff -c -r1.1 tm-sparc.h
*** /tmp/,RCSt1a09181   Wed Sep 21 12:21:18 1988
--- tm-sparc.h  Wed Sep 21 09:31:12 1988
***************
*** 1135,1141
     to define a local common symbol.  */
  
  #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
! ( fputs ("\n.common ", (FILE)),                       \
    assemble_name ((FILE), (NAME)),             \
    fprintf ((FILE), ",%d,\"bss\"\n", (ROUNDED)))
  

--- 1135,1141 -----
     to define a local common symbol.  */
  
  #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
! ( fputs ("\n.reserve ", (FILE)),                      \
    assemble_name ((FILE), (NAME)),             \
    fprintf ((FILE), ",%d,\"bss\"\n", (ROUNDED)))
  
Tom Quinn                 Canadian Institute for Theoretical Astrophysics
trq@moose.cita.toronto.edu
SOON TO BE trq@moose.cita.utoronto.ca
UUCP   - decvax!utgpu!moose!trq
BITNET - quinn@utorphys.bitnet
ARPA   - trq%moose.cita.toronto.edu@relay.cs.net

trq@moose.cita.toronto.edu (Tom Quinn) (09/22/88)

The following code points out an alignment bug in sparc gcc version 1.28.
The static structure zero_time is given an alignment of 4, but an
"ldd" instruction, which requires an alignment of 8, is used to access
it, giving a Bus Error if you are unlucky.  A quick fix would be in
output-sparc.c:output_move_double(): Delete the code following the
comment about knowing the structure is double aligned.

Tom Quinn                 Canadian Institute for Theoretical Astrophysics
trq@moose.cita.toronto.edu
SOON TO BE trq@moose.cita.utoronto.ca
UUCP   - decvax!utgpu!moose!trq
BITNET - quinn@utorphys.bitnet
ARPA   - trq%moose.cita.toronto.edu@relay.cs.net

The compile:
gcc -S -g -v  -sun4 -c  NextEvent.c
gcc version 1.28
 /usr/local/lib/gcc-cpp -v -undef -D__GNU__ -D__GNUC__ -Dsparc -Dsun -Dunix NextEvent.c /tmp/cca14379.cpp
GNU CPP version 1.28
 /usr/local/lib/gcc-cc1 /tmp/cca14379.cpp -quiet -dumpbase NextEvent.c -g -version -o NextEvent.s
GNU C version 1.28 (sparc) compiled by GNU C version 1.28.

Relavent assembler output:
.data
	.align 4		<<< This should be 8
_zero_time.0:
	.word 0
	.word 0
.
.
.
.stabn 68,0,45,LM10
LM10:
	set _zero_time.0,%l3
	ldd [%l3],%o2		<<< Or this should be two instructions
	std %o2,[%fp-72]

The code:
typedef char	Boolean;
struct timeval {
	long	tv_sec;		 
	long	tv_usec;	 
};
struct timezone {
	int	tz_minuteswest;	 
	int	tz_dsttime;	 
};
typedef long	xfd_mask;
typedef	struct xfd_set {
	xfd_mask fds_bits[(((256 )+(( (sizeof(xfd_mask) * 8))-1))/( (sizeof(xfd_mask) * 8))) ];
} xfd_set;
Boolean
_XtwaitForSomething(ignoreTimers, ignoreInputs, block, howlong)
Boolean ignoreTimers;
Boolean ignoreInputs;
Boolean block;
unsigned long *howlong;
{
	struct timezone cur_timezone;
	struct timeval  cur_time;
	struct timeval  start_time;
	struct timeval  wait_time;
	struct timeval  new_time;
	struct timeval  time_spent;
	struct timeval	max_wait_time;
	static struct timeval  zero_time = { 0 , 0};
	register struct timeval *wait_time_ptr;
	xfd_set rmaskfd, wmaskfd, emaskfd;
	static xfd_set zero = { 0 };
	register int     nfound, i;
	Boolean ret;
 	if(block) {
		(void) gettimeofday (&cur_time, &cur_timezone);
		start_time = cur_time;
		if(howlong == 0 ) {  
			wait_time_ptr = 0;
		} else {  
			max_wait_time.tv_sec = *howlong/1000;
			max_wait_time.tv_usec = (*howlong %1000)*1000;
			wait_time_ptr = &max_wait_time;
		}
	} else {   
		max_wait_time = zero_time;
		wait_time_ptr = &max_wait_time;
	}
    return ret;
}

trq@moose.cita.toronto.edu (Tom Quinn) (09/23/88)

The following code will compile incorrectly with the "-O" and
"-fforce-addr" flags.  This is on a Sun4/110 running SunOs 4.0.
The resulting object will generate a Bus Error at line 27 because it
is doing a "std" (store double) with an address that is not aligned on
an 8 byte boundary.  It looks like the "-fforce-addr" flag is a bad
idea on sparc, since it causes an extra register to be used, and it
wastes a cycle on an add, which would have no cost if done as register
+ offset in the store instruction.

The compile:
gcc -S -g -v -O -fforce-addr  -sun4 -c  axis.c
gcc version 1.28
 /usr/local/lib/gcc-cpp -v -undef -D__GNU__ -D__GNUC__ -Dsparc -Dsun -Dunix -D__OPTIMIZE__ axis.c /tmp/cca16875.cpp
GNU CPP version 1.28
 /usr/local/lib/gcc-cc1 /tmp/cca16875.cpp -quiet -dumpbase axis.c -fforce-addr -g -O -version -o axis.s
GNU C version 1.28 (sparc) compiled by GNU C version 1.28.

The relavent assembler:
...
.stabn 68,0,27,LM12
LM12:
	sub %sp,32,%sp
	add %sp,92,%o0		<<< Bad idea, sp is 8-byte aligned, o0
				    is therefore NOT aligned
	ld [%fp-20],%f8
	fstod %f8,%f6
	std %f6,[%fp-8]
	ldd [%fp-8],%l6
	fstod %f2,%f6
	std %f6,[%fp-8]
	ldd [%fp-8],%l4
	set _xsmall,%l2
	ld [%l2],%f2
	set _xbig,%l3
	ld [%l3],%f4
	fstod %f4,%f4
	std %f4,[%o0]		<<< Horrible death occurs here.
...

The code:
------------------------------------------------------------------------
extern float 
  	     fx1,fx2;      
extern int   gx1,gx2,gy1,gy2;      
extern double pow();
void angle(),
     ltype();
static float xsmall = 0.,
	     xbig   = 0.;
box(labelxl, labelxu)
int labelxl, labelxu;
{
   float a1,a2;
    ltype(0);
    angle(0.);
    if(xsmall < 0) {                        
       if(fabs(fx1) > 37 || fabs(fx2) > 37) {
	  msg("|x-limits| are too large for logarithmic axes\n");
	  a1 = fx1; a2 =fx2;
	  xsmall = 0;
       } else {
	  a1 = pow(10.,fx1);
	  a2 = pow(10.,fx2);
       }
    } else {				 
       a1 = fx1; a2 =fx2;
    }
    (void)axis(a1,a2,xsmall,xbig,gx1,gy1,gx2-gx1,labelxl,0); /* bombs here */
    (void)axis(a1,a2,xsmall,xbig,gx1,gy2,gx2-gx1,labelxu,1);
}
---------------------
Tom Quinn                 Canadian Institute for Theoretical Astrophysics
trq@moose.cita.toronto.edu
SOON TO BE trq@moose.cita.utoronto.ca
UUCP   - decvax!utgpu!moose!trq
BITNET - quinn@utorphys.bitnet
ARPA   - trq%moose.cita.toronto.edu@relay.cs.net

trq@moose.cita.toronto.edu (Tom Quinn) (09/26/88)

The following code will cause gcc to get a fatal signal when compile
with "-O".  This is gcc version 1.28 on a Sun4/110 running SunOs 4.0.

Tom Quinn                 Canadian Institute for Theoretical Astrophysics
trq@moose.cita.toronto.edu
SOON TO BE trq@moose.cita.utoronto.ca
UUCP   - decvax!utgpu!moose!trq
BITNET - quinn@utorphys.bitnet
ARPA   - trq%moose.cita.toronto.edu@relay.cs.net

The compile:
gcc -g -v -O  -sun4 -c  control.c
gcc version 1.28
 /usr/local/lib/gcc-cpp -v -undef -D__GNU__ -D__GNUC__ -Dsparc -Dsun -Dunix -D__OPTIMIZE__ control.c /tmp/cca04551.cpp
GNU CPP version 1.28
 /usr/local/lib/gcc-cc1 /tmp/cca04551.cpp -quiet -dumpbase control.c -g -O -version -o /tmp/cca04551.s
GNU C version 1.28 (sparc) compiled by GNU C version 1.28.
gcc: Program cc1 got fatal signal 6.

The code:
------------------------------------------------------------------------
void push(), push_dstack() ;
typedef struct {
   int nitem;				 
   char **i_list;			 
} TOK_LIST;
typedef union yystype {			 
   char charval[80			];
   float floatval;
   TOK_LIST *t_list;
};
extern union yystype  yylval;
typedef struct {		 
   char d_name[40];			 
   int (*dev_setup)(),			 
       (*dev_enable)(),			 
       (*dev_idle)(),			 
       (*dev_close)() ;			 
} DEVICES;
extern DEVICES devices[];	 
extern int devnum,			 
	   ndev;			 
   char *malloc(),
   	*sprintf(),
   	*strncat();
   static char buff[2000		 + 1],	 
	       word[80			];	 
   char *mgets();		 
   static int graph_mode = 0 ; 
typedef
  struct yyltype
    {
      int last_column;
      char *text;
   }
  yyltype;
static char yytranslate[] = {     0,
     2,     2,     2,     2,     2,     2,     2,     2,     2,     6
};
static short yyr1[] = {     0,
   112,   112,   113,   113,   113,   113,   113,   113,   113,   113
};
static short yyr2[] = {     0,
     1,     1,     0,     1
};
static short yydefact[] = {     1,
    43,   142,     0,     0
};
static short yydefgoto[] = {     1,
    74
};
static short yypact[] = {-32768,
-32768,-32768,   456,-32768
};
static short yypgoto[] = {-32768,
   198
};
static short yytable[] = {    92,
     0,     0,     0,   249
};
static short yycheck[] = {    26,
    -1,    -1,    -1,   109
};
int	yychar;			 
union yystype 	yylval;			 
yyltype  yylloc;			 
int
yyparse()
{
  register int yystate;
  register int yyn;
  register short *yyssp;
  register union yystype  *yyvsp;
  yyltype  *yylsp;
  int yyerrstatus;	 
  int yychar1;		 
  short	yyssa[200 ];	 
  union yystype  yyvsa[200 ];	 
  yyltype  yylsa[200 ];	 
  short *yyss = yyssa;		 
  union yystype  *yyvs = yyvsa;	 
  yyltype  *yyls = yylsa;
  union yystype  yyval;		 
  int yylen;
  yystate = 0;
  yyerrstatus = 0;
  yychar = 	-2 ;		 
  yyssp = yyss - 1;
  yyvsp = yyvs;
  yylsp = yyls;
yynewstate:
  *++yyssp = yystate;
  yyn = yypact[yystate];
  if (yyn == 	-32768 )
    goto yydefault;
  if (yychar == 	-2 )
    {
      yychar = 	yylex() ;
    }
  if (yychar <= 0)		 
    {
      yychar1 = 0;
      yychar = 	0 ;		 
    }
  else
    {
      yychar1 = ((unsigned)(yychar) <= 346 ? yytranslate[yychar] : 134) ;
    }
  yyn += yychar1;
  if (yyn < 0 || yyn > 	1184  || yycheck[yyn] != yychar1)
    goto yydefault;
  yyn = yytable[yyn];
  if (yyn == 	454 )
    return(0) ;
  if (yychar != 	0 )
    yychar = 	-2 ;
  *++yyvsp = yylval;
  *++yylsp = yylloc;
  if (yyerrstatus) yyerrstatus--;
  yystate = yyn;
  goto yynewstate;
yydefault:
  yyn = yydefact[yystate];
  if (yyn == 0)
    goto yyerrlab;
  yylen = yyr2[yyn];
  yyval = yyvsp[1-yylen];  
  switch (yyn) {
case 30:
{
    	      int i;
	      if(graph_mode)    (*devices[devnum].dev_idle) ();
	        (*devices[devnum].dev_close) ();
	      (void)sprintf(buff,"%s",yyvsp[0].charval);
	      (void)mgets(word,80			);  
	      (void)strncat(buff,word,2000		);
	      for(i = 0;i < ndev;i++) {
	         if(strcmp(devices[i].d_name,yyvsp[0].charval) == 0) {
	   	    devnum = i;
		    break;
	         }
	      }
	      if(i < ndev) {			 
	         if(  (*devices[devnum].dev_setup) (word) < 0) {		 
	            msg_1s("No such device %s\n",buff);
	            devnum = 0 ;
	         }
	      } else {				 
	         devnum = 1 ;
	         if(  (*devices[devnum].dev_setup) (buff) != 0) {
	            msg_1s("No such device %s\n",buff);
	            devnum = 0 ;
	         }
	      }
	      set_dev();
	      (*devices[devnum].dev_enable) (); graph_mode = 1;
	   ;
    break;}
case 31:
{
	    char *do_loop;		 
            register int i,j,k;
	    if(yyvsp[-8].charval[0] == '\0' || yyvsp[-1].t_list == 0 ) {
	       freelist(yyvsp[-1].t_list);
	       break;
	    }
	    if(yyvsp[-1].t_list->nitem <= 0) {		 
	       msg_1s("DO %s command list is empty\n",yyvsp[-8].charval);
	       freelist(yyvsp[-1].t_list);
	       break;
	    }
	    if((do_loop = malloc(2000		 + 1)) == 0 ) {
	       msg_1s("Can't allocate space for DO %s\n",yyvsp[-8].charval);
	       freelist(yyvsp[-1].t_list);
	       break;
	    }
	    j = 0;
	    for(i = 0;i < yyvsp[-1].t_list->nitem;i++) {
	       for(k = 0;k < 80			 && j < 2000		;j++,k++) {
		  if((do_loop[j] = yyvsp[-1].t_list->i_list[i][k]) == '\0') {
		     do_loop[j++] = ' ';
		     break;
		  }
	       }
            }
	    if(j == 2000		) {
	       msg_1d("Maximum length of a DO loop is %d\n",2000		);
	    }
            do_loop[j-1] = '\n'; do_loop[j] = '\0';
	    push_dstack(yyvsp[-8].charval,yyvsp[-6].floatval,yyvsp[-4].floatval,yyvsp[-3].floatval);	 
	    if(next_do() == 0) {	 
	       push(do_loop,1				);	 
	    }
            freelist(yyvsp[-1].t_list);
         ;
    break;}
}

  yyvsp -= yylen;
  yylsp -= yylen;
  yyssp -= yylen;
  *++yyvsp = yyval;
  yylsp++;
  yyn = yyr1[yyn];
  yystate = yypgoto[yyn - 112 ] + *yyssp;
  if (yystate >= 0 && yystate <= 	1184  && yycheck[yystate] == *yyssp)
    yystate = yytable[yystate];
  else
    yystate = yydefgoto[yyn - 112 ];
  goto yynewstate;
yyerrlab:    
  if (! yyerrstatus)
    {
      yyerror("parse error");
    }
  if (yyerrstatus == 3)
    {
      if (yychar == 	0 )
	return(1) ;
      yychar = 	-2 ;
    }
  yyerrstatus = 3;		 
  goto yyerrhandle;
yyerrdefault:   
  if (yyssp == yyss) return(1) ;
  yyvsp--;
  yylsp--;
  yystate = *--yyssp;
yyerrhandle:
  yyn = yypact[yystate];
  if (yyn == 	-32768 )
    goto yyerrdefault;
  yyn += 1 ;
  if (yyn < 0 || yyn > 	1184  || yycheck[yyn] != 1 )
    goto yyerrdefault;
  yyn = yytable[yyn];
  if (yyn == 	454 )
    return(0) ;
  *++yyvsp = yylval;
  *++yylsp = yylloc;
  yystate = yyn;
  goto yynewstate;
}

mike@TURING.UNM.EDU (Michael I. Bushnell) (09/27/88)

   Date: 	Mon, 26 Sep 88 11:33:42 EDT
   From: Tom Quinn <trq@moose.cita.toronto.edu>

   The following code will cause gcc to get a fatal signal when compile
   with "-O".  This is gcc version 1.28 on a Sun4/110 running SunOs 4.0.

   Tom Quinn                 Canadian Institute for Theoretical Astrophysics


This problem does not occur on a vax using the same version of GCC.

			--Mike Bushnell

trq@moose.cita.toronto.edu (Tom Quinn) (09/28/88)

The following code causes gcc to get a fatal signal.  This is gcc
version 1.28 on a sun4/110 running SunOs 4.0.

Tom Quinn                 Canadian Institute for Theoretical Astrophysics
trq@moose.cita.toronto.edu
SOON TO BE trq@moose.cita.utoronto.ca
UUCP   - decvax!utgpu!moose!trq
BITNET - quinn@utorphys.bitnet
ARPA   - trq%moose.cita.toronto.edu@relay.cs.net

The compile:
gcc -g -v -O  -sun4 -c  interface.c
gcc version 1.28
 /usr/local/lib/gcc-cpp -v -undef -D__GNU__ -D__GNUC__ -Dsparc -Dsun -Dunix -D__OPTIMIZE__ interface.c /tmp/cca03994.cpp
GNU CPP version 1.28
 /usr/local/lib/gcc-cc1 /tmp/cca03994.cpp -quiet -dumpbase interface.c -g -O -version -o /tmp/cca03994.s
GNU C version 1.28 (sparc) compiled by GNU C version 1.28.
gcc: Program cc1 got fatal signal 6.

The code:
------------------------------------------------------------------------
defimage_		(arr,x1,x2,y1,y2,nx,ny)
float *arr,
      *x1,*x2,*y1,*y2;
int *nx,*ny;
{
   char *malloc();
   static float **z = 0 ;			 
   int i;
   if((z = (float **)malloc((unsigned)(*ny)*sizeof(float *))) == 0 ) {
      msg("Can't get storage in defimage\n");
      z = 0 ;
      return;
   }
   for(i = 0;i < *ny;i++) {
      z[i] = &arr[i*(*nx)];
   }
   defimage(z,*x1,*x2,*y1,*y2,*nx,*ny);
}

trq@moose.cita.toronto.edu (Tom Quinn) (09/30/88)

Gcc compiles the following code into assembly that will cause a data
misalignment signal.  This gcc version 1.28 on a sun4/110 running
SunOS 4.0.

Tom Quinn                 Canadian Institute for Theoretical Astrophysics
trq@moose.cita.toronto.edu
SOON TO BE trq@moose.cita.utoronto.ca
UUCP   - decvax!utgpu!moose!trq
BITNET - quinn@utorphys.bitnet
ARPA   - trq%moose.cita.toronto.edu@relay.cs.net

The compile:
gcc -S -g -v  -sun4 -c  Convert.c
gcc version 1.28
 /usr/local/lib/gcc-cpp -v -undef -D__GNU__ -D__GNUC__ -Dsparc -Dsun -Dunix Convert.c /tmp/cca26062.cpp
GNU CPP version 1.28
 /usr/local/lib/gcc-cc1 /tmp/cca26062.cpp -quiet -dumpbase Convert.c -g -version -o Convert.s
GNU C version 1.28 (sparc) compiled by GNU C version 1.28.

The offending assembler:
.stabn 68,0,43,LM11
LM11:
	ld [%fp+84],%o0
	ldd [%l1+28],%l4	<<<ldd requires operands to be 8-byte
				   aligned, which is not the case here.
	std %l4,[%o0]		<<<this instruction also loses


The code:
------------------------------------------------------------------------
typedef	char *	caddr_t;
typedef struct {
    unsigned int    size;
    caddr_t	    addr;
} XrmValue, *XrmValuePtr;
typedef unsigned int   Cardinal;
typedef (*XtConverter)();
typedef struct _CacheRec *CachePtr;
typedef struct _CacheRec {
    CachePtr	next;
    int		hash;
    XtConverter converter;
    XrmValue	*args;
    Cardinal	num_args;
    XrmValue	from;
    XrmValue	to;
} CacheRec;
typedef CachePtr CacheHashTable[256 ];
static CacheHashTable	cacheHashTable;
void XtDirectConvert(converter, args, num_args, from, to)
    XtConverter     converter;
    XrmValuePtr     args;
    Cardinal	    num_args;
    register XrmValuePtr from;
    XrmValuePtr     to;
{
    register CachePtr   p;
    register int	hash;
    register Cardinal   i;
    hash = ((int)(converter) >> 2) + from->size + *((char *) from->addr);
    if (from->size > 1) hash += ((char *) from->addr)[1];
    for (p = cacheHashTable[hash & 255 ]; p != 0 ; p = p->next) {
	if ((p->hash == hash)
	 && (p->converter == converter)
	 && (p->from.size == from->size)
         && (p->num_args == num_args)) {
	    for (i = 0; i < num_args; i++) {
		if (   p->args[i].size != args[i].size ) {
		    break;
		}
	    }
	    if (i == num_args) {	 
		(*to) = p->to;
		return;
	    }
	}
    }
    (*to).size = 0;
    (*to).addr = 0 ;
    (*converter)(args, &num_args, from, to);
    CacheEnter(converter, args, num_args, from, to, hash);
}

dlong@beowulf.ucsd.edu (Dean Long) (10/01/88)

In article <8809281232.AA02342@moose.cita.toronto.edu> trq@moose.cita.toronto.edu (Tom Quinn) writes:
>The following code causes gcc to get a fatal signal.  This is gcc
>version 1.28 on a sun4/110 running SunOs 4.0.

.
.
.

>------------------------------------------------------------------------
>defimage_		(arr,x1,x2,y1,y2,nx,ny)
>float *arr,
>      *x1,*x2,*y1,*y2;
>int *nx,*ny;
>{
>   char *malloc();
>   static float **z = 0 ;			 

.
.
.

>   defimage(z,*x1,*x2,*y1,*y2,*nx,*ny);
>}

I tried this program.  Changing the float to double makes it work.  Also,
the same for this smaller version:

crash()
{
   float *x;

   foo(1,*x,*x,*x);
}

The strange thing is that small changes to the parameters, or changing
float to double makes it work.  I was using dbx and found that
a REG with SImode was using regno 34, which I think causes some
constraint to fail.

Also, when using dbx on cc1 compiled with gcc, register variable
values are printed incorrectly.  cc1 compiled with Sun cc is OK.

Dean Long
University of California, San Diego
dlong@beowulf.ucsd.edu

paul@UUNET.UU.NET (Paul Hudson) (10/03/88)

The sparc assembler limits strings to 2048 characters. This is about
half the corresponding limit on the SUN-3. Compiling code including sunview
header files with -g results in a .stabs string that is longer than this.
I don't know enough about gdb's format to know whether this can be split.
SUN say the assembler will be changed some time, but this doesn't seem to mean
soon. Any sign of gas for the sparc?

Is there a definitive list of changes to get gcc1.28 working on the sparc?
I've got it to the stage where it compiles itself, but some of my code provokes
signal 6 and 11. 

Changes I made were to cast the offending 0 to (tree)0 as discussed by
others, and patch output-sparc.h as given by Dean Long. If the signal
stuff is not fixed and it will help, I'll post the offending code.

Paul Hudson 

Snail mail: Monotype ADG	Email:	...!ukc!acorn!moncam!paul
	    Science Park,		paul@moncam.co.uk
	    Milton Road,	"Sun Microsysytems:
	    Cambridge,		 The Company is Arrogant (TM)"
	    CB4 4FQ

trq@moose.cita.toronto.edu (Tom Quinn) (10/05/88)

The following code causes gcc to get a fatal error if compiled with
the "-O" option.  This is on a Sun4/110 running SunOS 4.0.

Tom Quinn                 Canadian Institute for Theoretical Astrophysics
trq@moose.cita.toronto.edu
SOON TO BE trq@moose.cita.utoronto.ca
UUCP   - decvax!utgpu!moose!trq
BITNET - quinn@utorphys.bitnet
ARPA   - trq%moose.cita.toronto.edu@relay.cs.net

The compile:
gcc -g -v -O  -sun4 -c  nsat.c
gcc version 1.28
 /usr/local/lib/gcc-cpp -v -undef -D__GNU__ -D__GNUC__ -Dsparc -Dsun -Dunix -D__OPTIMIZE__ nsat.c /tmp/cca00727.cpp
GNU CPP version 1.28
 /usr/local/lib/gcc-cc1 /tmp/cca00727.cpp -quiet -dumpbase nsat.c -g -O -version -o /tmp/cca00727.s
GNU C version 1.28 (sparc) compiled by GNU C version 1.28.

nsat.c:80: warning: floating point number exceeds range of `double'
gcc: Program cc1 got fatal signal 6.

The code:
------------------------------------------------------------------------
extern double fabs(), floor();
extern double sqrt();
extern double  pow();
extern double sin(), cos();
extern double drem();	 
struct sat {
    double a;			 
    double e;			 
    double pomega;
    double mu;			 
    double omega;		 
    double phi;
    double p0;			 
    double yr, yi;		 
    int n;			 
    int index;			 
    int current;		 
};
static double dt;
main()
{
    struct sat *planet, test;	 
    int nplanet;
    int nsteps, i, print;
    double tmax, t;
    double p, deltay, gamma;
    double cphi, sphi;
    struct sat *sptr, *encptr, *nextpl();
    char *malloc();
    scanf("%d", &nplanet);
    if((planet = (struct sat *)malloc((unsigned) nplanet*sizeof(struct sat)))
       == 0 ) {
	exit(-1);
    }
    for(sptr = planet, i = 0; sptr < planet + nplanet; sptr++, i++) {
	scanf("%lf %lf %lf %lf", &(sptr->a), &(sptr->e), &(sptr->pomega),
	      &(sptr->mu));
	sptr->index = i;	 
	sptr->current = 0;	 
    }
    sptr = &test;
    scanf("%lf %lf %lf %lf", &(sptr->a), &(sptr->e), &(sptr->pomega),
	  &(sptr->mu));
    scanf("%d %d %lf %lf %lf", &nsteps, &print, &tmax, &t, &(sptr->phi));
    test.yr = test.e * cos(test.pomega);
    test.yi = test.e * sin(test.pomega);
    for(sptr = planet; sptr < planet + nplanet; sptr++) {
	sptr->p0 = (test.a - sptr->a)/sptr->a;
	sptr->n = 0;
	sptr->omega = pow(sptr->a, -1.5);
	sptr->phi = sptr->omega*t;
	sptr->phi -= (2.0*3.14 ) *(floor(sptr->phi/(2.0*3.14 ) ));
	sptr->yr = sptr->e * cos(sptr->pomega);
	sptr->yi = sptr->e * sin(sptr->pomega);
    }
    encptr = planet;
    for(i = 0; i < nsteps && t < tmax; i++) {
	test.omega = pow(test.a , -1.5);
	if(i % print == 0 && i != 0) {
	    double pphi = encptr->omega*3.14 /fabs(encptr->omega - test.omega);
	    pphi += test.phi;
	    cphi = cos(pphi);
	    sphi = sin(pphi);
	    printf("%g %g %g %.18g %g %d\n", test.a,
		   test.yr*cphi + test.yi*sphi,
		   -test.yr*sphi + test.yi*cphi, test.phi, t, encptr->index);
	}
	if((encptr = nextpl(planet, nplanet, test)) == 0 ) {  
	    break;
	}
	encptr->n++;
	test.phi += test.omega * dt;
	test.phi = drem(test.phi, (2.0*3.14 ) );
	if(test.phi < 0.0) test.phi = (2.0*3.14 )  + test.phi;
	test.phi -= (2.0*3.14 ) *(floor(test.phi/(2.0*3.14 ) ));
	for(sptr = planet; sptr < planet + nplanet; sptr++) {
	    sptr->phi += sptr->omega * dt;
	    sptr->phi = drem(sptr->phi, (2.0*3.14 ) );
	    if(sptr->phi < 0.0) sptr->phi = (2.0*3.14 )  + sptr->phi;
	    if(dt > 0.0) sptr->current = 0;
	}
	encptr->current++;
	t += dt;
	if(test.a > encptr->a)
	    deltay = encptr->mu * -2.23  /(encptr->p0 * encptr->p0);
	else
	    deltay = (-encptr->mu) * -2.23  /(encptr->p0 * encptr->p0);
	p = (test.a - encptr->a)/encptr->a;
	gamma = 0.75*((p)*(p))  - ((encptr->yr - test.yr)*(encptr->yr - test.yr)) 
	  - ((encptr->yi - test.yi)*(encptr->yi - test.yi)) ;
	test.yr += deltay*sin(test.phi);
	test.yi -= deltay*cos(test.phi);
	test.e = sqrt(((test.yr)*(test.yr))  + ((test.yi)*(test.yi)) );
	p = sqrt((4.0/3.0) * (gamma + ((test.yr - encptr->yr)*(test.yr - encptr->yr)) 
				    + ((test.yi - encptr->yi)*(test.yi - encptr->yi)) ));
	if(test.a > encptr->a)
	    test.a = encptr->a * (1.0 + p);
	else
	    test.a = encptr->a * (1.0 - p);
	if((test.a > encptr->a
	    && (1.0 - test.e)*test.a <= (1.0 + encptr->e)*encptr->a) 
	   || (test.a < encptr->a
	       && (1.0 + test.e)*test.a >= (1.0 - encptr->e)*encptr->a)) {
	    break;
	}
    }	
}