[comp.sys.masscomp] FORTRAN cross-referencer

masscomp-request@soma.UUCP (08/18/87)

Stan, please pass this on the comp.sys.masscomp
I can't really claim authorship for this program, as it is derived
(quite loosely by this point) from work done by others. Mainly, I made
it case-insensitive, jazzed up the output, and made it recognize MASSCOMP
extensions to FORTRAN-77.

	jeff carter

------Cut Here----------------------
#!/bin/sh
# This is a shell archive. Remove everything prior to the previous line
# and execute using '% sh thisfilename'. The makefile and documentation
# should be self-explanatory :-). 
#
# As usual, this program is provided as-is, no warranty expressed or implied.
# It is shear coincidence that I happen to work for MASSCOMP, this software
# should in no way be misconstrued as MASSCOMP-supplied, supported or even
# confessed-to (Is that enough disclaimer?) I will happily receive all 
# applause, suggestions, enhancements, etc. Complaints and flames to the usual
# place, please.
# 		Jeff Carter (masscomp!carter)
echo shar: extracting Makefile
cat << \SHAR_EOF > 'Makefile'
# makefile for fxref, the f77 xref program from Bourne 8.2.2

# where the executable shell is located
BIN = /usr/local
# where the executable binaries are located
LIB = /usr/local/lib
MAN = /usr/man/man1
CFLAGS = -O
XREFA = $(LIB)/fxrefa
XREFB = $(LIB)/fxrefb

all: fxrefa fxrefb fxref

fxref: fxref.sh
	cp fxref.sh fxref

fxrefa: lex.yy.c
	cc -O -o fxrefa lex.yy.c -ll

fxrefb: fxrefb.c
	cc -O -o fxrefb fxrefb.c

lex.yy.c: fxrefa.l
	lex fxrefa.l > lex.rec 

install: all
	mv fxrefa $(XREFA)
	mv fxrefb $(XREFB)
	mv fxref $(BIN)
	cp fxref.1 $(MAN)
clean:
	rm -f lex.yy.c *.o

clobber: clean
	-rm -f fxrefa fxrefb fxref
SHAR_EOF
echo shar: extracting fxref.sh
cat << \SHAR_EOF > 'fxref.sh'
#! /bin/sh
# f77 xref based on Bourne 8.2.2
LIB=/usr/local/lib
PATH=$PATH:$LIB
case $# in
0)	;;
*)	case $1 in
	-w*)	arg=$1 ; shift ;;
	-*)	echo "`basename $0: do not understand $1`" ; exit 1 ;;
	*)	arg= ;;
	esac
esac
fxrefa $* | sort -ut: +0 -1 +1 -2 +2n -3 | fxrefb $arg
SHAR_EOF
echo shar: extracting fxrefa.l
cat << \SHAR_EOF > 'fxrefa.l'
/* xref.a -- f77 cross reference mapper -- from Bourne's C xref, p. 204 */
%k 300
%a 10000
%o 5000
%n 800
%e 2000
%p 5000
%{
static char SCCSID[] = "@(#)fxrefa.l	Ver. 2.1, 85/06/28 09:37:30";
char *filename="-";
char *flag;
char *oflag;

#undef input
#define input() tolower(((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)

main(argc,argv)
	int argc;
	char *argv[];
{
	register int rc=0;
	flag = "";
	if(argc <= 1) {
		yylex();
	}
	else {
		while(argc > 1) {
			if(freopen(argv[1],"r",stdin)==NULL) {
				fprintf(stderr,"%s: %s: cannot open\n",
						argv[0],argv[1]);
				rc++;
			}
			else {
				filename=argv[1];
				yylineno=1;
				yylex();
			}
			argc--;
			argv++;
		}
	}
	return(rc);
}
%}
W	[ \t]*
%%
aimag{W}"("	;
aint{W}"("	;
cabs{W}"("	;
ccos{W}"("	;
cexp{W}"("	;
clog{W}"("	;
cmplx{W}"("	;
conjg{W}"("	;
csin{W}"("	;
csqrt{W}"("	;
dabs{W}"("	;
datan{W}"("	;
datan2{W}"("	;
dble{W}"("	;
dcos{W}"("	;
dexp{W}"("	;
dlog{W}"("	;
dlog10{W}"("	;
dmax1{W}"("	;
dmin1{W}"("	;
dmod{W}"("	;
dsign{W}"("	;
dsin{W}"("	;
dsqrt{W}"("	;
iabs{W}"("	;
idim{W}"("	;
idint{W}"("	;
alog{W}"("	;
alog10{W}"("	;
amax0{W}"("	;
amax1{W}"("	;
amin0{W}"("	;
amin1{W}"("	;
amod{W}"("	;
complex		flag = "CMPLX";
complex\*8	flag = "C*8";
complex\*16	flag = "C*16";
double{W}complex	flag = "C*16";  /* (extension) */
double{W}precision	flag = "R*8";
implicit	;
isign{W}"("	;
max0{W}"("	;
max1{W}"("	;
min0{W}"("	;
min1{W}"("	;
^[c*].*\n	; /* skip comments */
"\'"		{
		while(yyinput() != '\''); /* skip quoted material */
		}
^"     "[^ 0]	flag=oflag ; /* continuation line */
^\&		flag=oflag ; /* continuation line (extension) */
abs{W}"("	;
\.and\.		;
atan{W}"("	;
atan2{W}"("	;
backspace	;
block{W}data	flag = "BLKD";
call		flag = "CALL";
character	flag = "CHAR";
close{W}"("	flag = "CLOSE";
common		flag = "COMM";
continue	;
cos{W}"("	;
acos{W}"("	;
data		flag = "DATA";
dimension	flag = "DIM";
do{W}[0-9]+	flag = "DO";
else{W}if{W}"("	flag = "ELSIF";
else		;
end{W}file	;
end{W}if	;
end		;
entry		flag = "ENTRY";
\.eq\.		;
equivalence{W}"("	flag =  "EQUIV";
exp{W}"("	;
external	flag =  "EXTRN";
\.false\.	;
file		;
float{W}"("	;
format{W}"("	;
function	flag =  "FUNC";
\.ge\.		;
go{W}to		;
\.gt\.		;
if{W}"("	flag = "IF";
ifix{W}"("	;
index{W}"("	;
int{W}"("	;
integer		flag = "INTGR";
integer\*2	flag = "I*2";
integer\*4	flag = "I*4";
internal	flag = "INTRN";
\.le\.		;
\.lge\.		;
\.lgt\.		;
\.lle\.		;
\.llt\.		;
log{W}"("	;
log10{W}"("	;
logical		flag = "LGCL";
logical\*2	flag = "L*2";
logical\*4	flag = "L*4";
\.lt\.		;
max{W}"("	;
min{W}"("	;
mod{W}"("	;
\.ne\.		;
\.not\.		;
\.or\.		;
open{W}"("	flag = "OPEN";
parameter{W}"("	flag = "PARAM";
print		flag = "PRINT";
program		flag = "PROG";
read{W}"("	flag = "READ";
real		flag = "REAL";
real\*4		flag = "R*4";
real\*8		flag = "R*8";
recl		;
return		;
rewind{W}"("	;
save		flag = "SAVE";
sign{W}"("	;
sin{W}"("	;
sqrt{W}"("	;
stop		;
subroutine	flag = "SUBR";
tanh{W}"("	;
then		;
to		;
\.true\.	;
write{W}"("	flag = "WRITE";
[0-9.]*[ed][-+0-9]*	;
[a-z][a-z0-9]*	{
		printf("%s\t%s\t%03d %-5s\n", yytext, filename, yylineno, flag);
		}
=		{
		if(strcmp(flag,"ASSGN")==0)
			flag = "";
		}
.		;
\n		{
		oflag = flag;
		flag =  "ASSGN";
		}
SHAR_EOF
echo shar: extracting fxrefb.c
cat << \SHAR_EOF > 'fxrefb.c'
/* second part of f77 xref program.  Developed from Bourne p. 207 */
#include <stdio.h>
static char SCCSID[] = "@(#)fxrefb.c	Ver. 2.1, 85/06/28 09:37:55";
#define MAXW 256
char	lastw[MAXW]; /* last word read */
char	lastc;

main(argc,argv)
	int argc;
	char *argv[];
{
	char f1[MAXW], f2[MAXW];
	char first=0;
	int width, col=0;

	switch(argc) {
	case 1:
		width=80; /* default */
		break;
	case 2:
		if(sscanf(argv[1], "-w%d", &width) == 1) {
			width = 5 * (width / 5);
			break;
		}
	default:
		printf("%s: illegal argument\n", argv[0]);
		exit(1);
	}
	f1[0]=0;
	f2[0]=0;

	printf("\t\t\tFlags mean:\n");
	printf("PROG\tprogram unit header\t");
	printf("PARM\tPARAMETER definition\n");
	printf("LGCL\tLOGICAL declaration\t");
	printf("L*2\tLOGICAL*2 declaration\n");
	printf("L*4\tLOGICAL*4 declaration\t");
	printf("CHAR\tCHARACTER declaration\n");
	printf("INTGR\tINTEGER declaration\t");
	printf("R*8\tDOUBLE PRECISION declaration\n");
	printf("CMPLX\tCOMPLEX declaration\t");
	printf("C*8\tCOMPLEX*8 declaration\n");
	printf("C*16\tCOMPLEX*16 declaration\t");
	printf("REAL\tREAL declaration  \n");
	printf("DIM\tDIMENSION statement\t");
	printf("COMM\tCOMMON statement   \n");
	printf("EQUIV\tEQUIVALENCE        \t");
	printf("DATA\tDATA initialization\n");
	printf("EXTRN\tEXTERNAL           \t");
	printf("IF\tIF line\n");
	printf("CALL\tCALL               \t");
	printf("DO\tDO loop\n");
	printf("READ\tinput              \t");
	printf("WRITE\toutput\n");
	printf("OPEN\tOPEN statement     \t");
	printf("R*4\tREAL*4 declaration  \n");
	printf("SAVE\tSAVE statement     \t");
	printf("SUBR\tSUBROUTINE statement\n");

	while(word() != EOF) { 			/* get symbol name */
		if(lastw[0] != first) {		/* cause a break between 
						   symbols starting with 
						   different letters */
			first = lastw[0];
			printf("\n");
			col=0;
		}
		if(strcmp(lastw, f1) == 0) {	/* is symbol same as current? */
			word();			/* get filename */
			if( ! strcmp(lastw, f2) == 0) {
						/* filename same as current ? */
						/* if not, change filename    */
				col = printf("\n          %-10s", lastw) - 1;
				strcpy(f2, lastw);
			}
		}
		else {
						/* if symbol is not the same, 
						save new symbol, and start 
						new section                   */
			strcpy(f1, lastw);
			col = printf("\n\n%-10s", f1) - 2; /* print symbol    */
			word();				/* get the filename   */
			strcpy(f2, lastw);		/* save as current fn */
			col += printf("%-10s", f2);	/* print filename     */
		}
		if(col >= (width - 11)) {  
			/* references exceed page width, so wrap */
			col = printf("\n                    ") - 1;
		}
		if(lastc != '\n') {
			word();				/* get reference id   */
			col += printf(" %10s", lastw);	/* print reference id */
		}
		lastc = 0;
	}
	printf("\n");
	exit(0);
}

int word()
{
	register char *p=lastw;
	register int c;

	if(lastc != '\n') {
		while((c = getchar()) != '\t' && c != '\n' && c != EOF) {
			if(p < &lastw[MAXW])
				*p++ = c;
		}
		lastc=c;
	}
	*p++ = 0;
	return(lastc);
}
SHAR_EOF
echo shar: extracting fxref.1
cat << \SHAR_EOF > 'fxref.1'
.TH FXREF 1L
.SH NAME
fxref \- cross reference for f77 programs
.SH SYNOPSIS
.B fxref
[ file ... ]
.SH DESCRIPTION
.I Fxref\^
reads the named 
.I files\^
or the standard input if no file is specified
and prints a cross reference consisting of lines
of the form
.nf

	identifier	file-name	line-numbers ...
.fi
.PP
Each line number may be followed by a symbol denoting the type of usage
on that line, e.g. COMMON declaration, DATA initialization, or
subroutine CALL.  These symbols are defined in a header to the output file.
.SH EXAMPLE
.IP
fxref program.f
.PP
will return a cross reference listing of all the identifiers
in the f77 program named "program.f".
.SH FILES
/usr/local/fxref,
/usr/local/lib/fxrefa,
/usr/local/lib/fxrefb
.SH BUGS
Fxref does not ignore blanks as f77 does: thus VAR ONE is the same variable
as VARONE in a Fortran program, but will be treated as two variables by fxref.
Symbols which identify the type of usage are not always reliable.
.SH AUTHORS
Written by William Silvert, Marine Ecology Laboratory, Dartmouth, N. S.
Based on a C cross-reference program by Steve Bourne.
Consult Bourne's book, "The UNIX System", for program details.
Enhanced by Jeff Carter, MASSCOMP, Westford, MA.
SHAR_EOF
exit 0

wcw@psueclb.bitnet (08/26/87)

Thanks to jeff carter and sob for getting the fxref program posted.  I
ran into a problem compiling it, however, because somewhere along the
path to our VAX the last few characters of the longest line got lopped off.
Fortunately, I had an incomplete listing of the program and I could
restore it.  The problem line was in line 15 of fxrefa.l, after unpacking.
In case anyone else has this problem, I'll list it here (the following
2 lines should be just one line):

#define input() tolower(((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==
10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)

                                  Bill Ward
                        The Pennsylvania State Univerity
                            Noise Control Laboratory
---------------------------------------------------------------
Bitnet: wcw@psuecla
UUCP:   psuvax1!ncl!wcw
USPS:   157 Hammond Bldg.               (814)865-7262
        University Park, PA 16802