[4bsd-f77 #24] F77 sometimes breaks on concatenations

4.2 BSD f77 bug reports 4bsd-f77 at utah-cs.UUCP
Wed Aug 1 10:02:48 AEST 1984


From: Donn Seeley <donn at utah-cs.arpa>

Subject: F77 doesn't calculate the lengths of concatenations properly
Index:	usr.bin/f77/src/f77pass1/put.c 4.2BSD

Description:
	There are at least a couple errors in the f77 compiler in the
	way it handles the lengths of concatenated strings.  One of
	them is a clear error in the code dealing with finding the
	length of a concatenation of two CHARACTER variables; the other
	is a failure to propagate the length of a CHARACTER variable
	through parentheses.  The first problem was found and fixed by
	Conrad Huang at UC San Francisco.

Repeat-By:
	I don't have a handy example of how the first problem breaks
	some code, but the error is quite obvious from just looking at
	the source.

	The other bug can be shown by attempting to compile the
	following program with the optimizer on:

	----------------------------------------------------------------
		program chcat

		character*4 hi
		character*6 there
		character*1 excl
		character*15 out

		data hi/'hi'/
		data there/'there'/
		data excl/'!'/

		out = (hi // there) // excl

		print *, out

		stop
		end
	----------------------------------------------------------------

	The compiler bombs out with the following edifying messages:

	----------------------------------------------------------------
	chcat.f:
	   MAIN chcat:
	Error on line 12 of chcat.f: nonarithmetic operand of arithmetic operator
	Error on line 12 of chcat.f: impossible element in concatenation

	Error.  No assembly.
	----------------------------------------------------------------

Fix:
	The first bug is easy to identify and to fix.  The problem is
	that the code in lencat() implies that the 'varleng' field in
	an 'Addrblock' stucture is at the same offset as the 'varleng'
	field in a 'Tempblock' structure, which, alas, it is not.  The
	fix is in lencat(), in put.c:

	----------------------------------------------------------------
	*** /tmp/,RCSt1028292	Thu Jul 19 17:27:25 1984
	--- put.c	Thu Jul 19 12:04:26 1984
	***************
	*** 173,179
		return( lencat(p->exprblock.leftp) + lencat(p->exprblock.rightp) );
	  else if( p->headblock.vleng!=NULL && ISICON(p->headblock.vleng) )
		return(p->headblock.vleng->constblock.const.ci);
	! else if((p->tag==TADDR || p->tag==TTEMP) && p->addrblock.varleng!=0)
		return(p->addrblock.varleng);
	  else
		{

	--- 186,192 -----
		return( lencat(p->exprblock.leftp) + lencat(p->exprblock.rightp) );
	  else if( p->headblock.vleng!=NULL && ISICON(p->headblock.vleng) )
		return(p->headblock.vleng->constblock.const.ci);
	! else if(p->tag==TADDR && p->addrblock.varleng!=0)
		return(p->addrblock.varleng);
	  else if(p->tag==TTEMP && p->tempblock.varleng!=0)
		return(p->tempblock.varleng);
	***************
	*** 175,180
		return(p->headblock.vleng->constblock.const.ci);
	  else if((p->tag==TADDR || p->tag==TTEMP) && p->addrblock.varleng!=0)
		return(p->addrblock.varleng);
	  else
		{
		err("impossible element in concatenation");

	--- 188,195 -----
		return(p->headblock.vleng->constblock.const.ci);
	  else if(p->tag==TADDR && p->addrblock.varleng!=0)
		return(p->addrblock.varleng);
	+ else if(p->tag==TTEMP && p->tempblock.varleng!=0)
	+ 	return(p->tempblock.varleng);
	  else
		{
  	err("impossible element in concatenation");
	----------------------------------------------------------------

	The second bug is due to the fact that for some obscure reason,
	parentheses are treated as an operator in f77 (only when the
	optimizer is enabled, by the way -- even so, none of the
	optimization code appears to use the parenthesis operator for
	anything).  A parenthesis expression has the type of its
	operand; unfortunately it does not propagate the length of its
	operand when that operand is a CHARACTER expression, leading to
	indirection through a null pointer (which explains the first
	error message in the example) and a complaint from lencat()
	because it can't get a length for one operand of a
	concatenation operator (which explains the second error
	message).  Yet another bug is concealed behind this one, which
	is that the intermediate code emitting routine putch1() does
	not know what to do with a parenthesis expression anyway,
	length or no length.

	Here is the fix to fixexpr() in expr.c to force the length to
	be passed through parentheses:

	----------------------------------------------------------------
	*** /tmp/,RCSt1028422	Thu Jul 19 17:48:21 1984
	--- expr.c	Thu Jul 19 17:21:27 1984
	***************
	*** 666,671
		case OPCOMMA:
		case OPQUEST:
		case OPCOLON:
			break;
	  
		case OPMIN:

	--- 670,679 -----
		case OPCOMMA:
		case OPQUEST:
		case OPCOLON:
	+ 		break;
	+ 
	+ 	case OPPAREN:
	+ 		p->vleng = cpexpr( lp->headblock.vleng );
			break;
	  
		case OPMIN:
	----------------------------------------------------------------

	And here is the fix to putch1() in putpcc.c:

	----------------------------------------------------------------
	*** /tmp/,RCSt1028466	Thu Jul 19 17:54:01 1984
	--- putpcc.c	Thu Jul 19 17:23:05 1984
	***************
	*** 929,934
				case OPCALL:
				case OPCCALL:
					t = putcall(p);
					break;
	  
				case OPCONCAT:

	--- 932,942 -----
				case OPCALL:
				case OPCCALL:
					t = putcall(p);
	+ 				break;
	+ 
	+ 			case OPPAREN:
	+ 				--*ncommap;
	+ 				t = putch1(p->exprblock.leftp, ncommap);
					break;
	  
				case OPCONCAT:
	----------------------------------------------------------------

Character manipulation in FORTRAN?!? -- You gotta be kidding,

Donn Seeley    University of Utah CS Dept    donn at utah-cs.arpa
40 46' 6"N 111 50' 34"W    (801) 581-5668    decvax!utah-cs!donn



More information about the Comp.bugs.4bsd.ucb-fixes mailing list