[4bsd-f77 #38] Using the f77 ASSIGN statement with FORMAT statements
4.2 BSD f77 bug reports
4bsd-f77 at utah-cs.UUCP
Sat Sep 1 09:42:39 AEST 1984
From: Jerry Berkman <jerry%ucbopal.CC at Berkeley.ARPA>
Subject: Using the f77 ASSIGN statement with FORMAT statement numbers
Index: usr.bin/f77/src/f77pass1 4.2BSD
Description:
[F77 sometimes breaks when asked to compile a program which
uses an ASSIGN statement to put the line number of a FORMAT
statement into a variable, and subsequently tries to WRITE
or PRINT with it. I have taken the liberty of adding headers
and running 'fmt' on Jerry's report. -- Ed.]
Repeat-By:
This works with f77 if the format statement occurs before the
assign statement, e.g.:
8020 format('hi')
assign 8020 to i
print i
end
or if the format statement number occurs as a format specifier
in an I/O statement before the assign statement, e.g.:
print 8020
assign 8020 to i
print i
8020 format ( ' hi there ' )
end
It does not work if the assign statement occurs before the
compiler knowns the label is a format label. You either get a
loading error(!):
assign 8020 to i
print 8020
print i
8020 format ( ' hi there ' )
end
or an execution I/O error:
assign 8020 to i
print i
8020 format ( ' hi there ' )
end
Fix:
The bug is in the grammar. In gram.head, in the action for
'thislabel', when a non-zero statement number is scanned, first
mklabel is called to get a label block for the statement
number. One is created if none existed for it.
Then, if it's not known to be a format, a label is put in the
text stream (see the putlabel() at line 157). This is all
before it looks at the statement body. When it looks at the
statement body, if it is a format statement, it calls fmtstmt()
(in io.c) to get a labelblock and then it calls setfmt() to put
the label in the initialized data stream.
So it puts one label in the text stream and one in the data
stream. So that they won't be the same, fmtstmt() gets a new
label and wipes out any prior label in the labelblock. Try
compiling the following with the -S flag:
i = 1
100 format('hi')
200 format('lo')
i =2
end
The assembler code shows two useless labels between the movl's
for 'i = 1' and 'i = 2'.
Back to the test program which got an I/O error:
assign 8000 to i
print i
8000 format('hi')
end
When the 8000 in the assign is scanned, a labelblock is created
for statement number 8000 and assigned label number 15. So the
assign is compiled to move the value of L15 into the variable
i. When the 8000 on the format statement is scanned, L15 is
put out in the text stream. Then it figures out it has a
format, replaces the 15 in the labelblock for 8000 by the label
17, and generates L17 in the data stream. So the assign is
pointing the wrong place and you get an I/O error during
execution.
The solution is to generate labels in the text stream only for
executable statements by moving the code from the action for
'thislabel' to the actions for 'end_spec' and 'let'. Then
delete the line in fmtstmt() which replaces the label with a
new label.
This has the side effect of generating less labels so that
larger source files may be compiled; it may also help the
optimizer.
Here are the diffs:
----------------------------------------------------------------
*** gram.exec4.2 Tue Jul 17 17:52:31 1984
***************
*** 77,82
newproc();
startproc(PNULL, CLMAIN);
}
}
;
--- 77,87 -----
newproc();
startproc(PNULL, CLMAIN);
}
+ if( yystno != 0 && thislabel->labtype != LABFORMAT)
+ if (optimflag)
+ optbuff (SKLABEL, 0, thislabel->labelno, 1);
+ else
+ putlabel(thislabel->labelno);
}
;
***************
*** 150,155
startproc(PNULL, CLMAIN);
}
if(parstate < INDATA) enddcl();
}
;
--- 155,165 -----
startproc(PNULL, CLMAIN);
}
if(parstate < INDATA) enddcl();
+ if( yystno != 0 && thislabel->labtype != LABFORMAT)
+ if (optimflag)
+ optbuff (SKLABEL, 0, thislabel->labelno, 1);
+ else
+ putlabel(thislabel->labelno);
+ yystno = 0;
}
;
----------------------------------------------------------------
----------------------------------------------------------------
*** gram.head4.2 Tue Jul 17 17:52:50 1984
***************
*** 156,167
convic( (ftnint) (thislabel->stateno) ) );
thislabel->blklevel = blklevel;
thislabel->labdefined = YES;
- if(thislabel->labtype != LABFORMAT)
- if (optimflag)
- optbuff (SKLABEL, 0,
- thislabel->labelno, 1);
- else
- putlabel(thislabel->labelno);
}
}
else $$ = thislabel = NULL;
--- 156,161 -----
convic( (ftnint) (thislabel->stateno) ) );
thislabel->blklevel = blklevel;
thislabel->labdefined = YES;
}
}
else $$ = thislabel = NULL;
----------------------------------------------------------------
----------------------------------------------------------------
*** io.c4.1 Tue Jul 17 17:53:13 1984
***************
*** 175,181
if(lp->labtype == LABUNKNOWN)
{
lp->labtype = LABFORMAT;
- lp->labelno = newlabel();
}
else if(lp->labtype != LABFORMAT)
{
--- 175,180 -----
if(lp->labtype == LABUNKNOWN)
{
lp->labtype = LABFORMAT;
}
else if(lp->labtype != LABFORMAT)
{
----------------------------------------------------------------
- Jerry Berkman
Computing Services, (415) 642-4804
ucbvax!ucbopal!jerry
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list