Relay-Version: version B 2.10.3 alpha 4/15/85; site seismo.UUCP Posting-Version: version B 2.10.2 9/3/84; site genrad.UUCP Path: seismo!harvard!think!mit-eddie!genrad!sources-request From: sources-request@genrad.UUCP Newsgroups: mod.sources Subject: a cross reference program Message-ID: <870@genrad.UUCP> Date: 26 May 85 16:08:43 GMT Sender: john@genrad.UUCP Organization: U Wisconsin-Madison Academic Computing Ctr Lines: 312 Approved: john@genrad.UUCP From: harvard!seismo!uwvax!uwmacc!jiml (Jim Leinweber) In the last few months a couple of requests for f77 or C cross reference map generators have appeared on the net. This submission is a quick and dirty implementation of a general purpose (i.e. stupid) cross reference utility. It was done using lex, awk, and sh as an example for a UNIX tutorial. I have mailed copies to the original requestors. Possibly some of the rest of the net isn't satisfied by egrep, ctags, ptx, etc., and might like it too. -- Jim Leinweber (jiml@uwmacc.UUCP, leinwebe@wisc-ai.arpa) ----------------- cut here -------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by uwmacc!jiml on Fri May 24 12:42:06 CDT 1985 # Contents: Makefile READ_ME mergelines.awk xref.man xref.man.sh xref.sh # xrefhead.sh xreflex.l echo x - Makefile sed 's/^x//' > "Makefile" <<'x//E*O*F Makefile//' xCFLAGS = -O xLINT = lint -ph xDESTDIR = /usr/local xMANLOC = /usr/man/manl/xref.l x xall : xref xreflex xref.1 ; @echo 1>&2 "[Made xref xreflex xref.1]" x xxref : xrefhead.sh mergelines.awk ; sh xref.sh $(DESTDIR) >/dev/null x xxreflex : lex.yy.c ; cc -o xreflex $(CFLAGS) lex.yy.c -ll xlex.yy.c : xreflex.l ; lex -v xreflex.l x xxref.1 : xref.man ; sh xref.man.sh $(DESTDIR) >/dev/null x x xpiecetest : x xreflex xreflex.l xref.man >xreflex_out x sort -u +0f -1 +0 -1 +1 -2 +2n sort_out x awk -f mergelines.awk awk_out x xlint : lex.yy.c ; $(LINT) lex.yy.c > xreflex.lint x xinstall : all x install -c xref $(DESTDIR) x install -c -s xreflex $(DESTDIR) x install -c -m 644 xref.1 $(MANLOC) x xclean : ; -rm *_out *.lint *.yy.c xref xreflex xref.1 x//E*O*F Makefile// chmod u=rw,g=r,o=r Makefile echo x - READ_ME sed 's/^x//' > "READ_ME" <<'x//E*O*F READ_ME//' xIn the last few months there have been requests on USENET for a cross xreferencing program. Standard UNIX usage is, one supposes, to use xegrep on a case by case basis for this purpose. However, I cobbled up xsuch a program as an example using of using make, lex and awk for a xshort UNIX tutorial. It has had only minimal testing and is not xespecially efficient; caveat emptor! x xThis package makes three files: x xref - a shell script which cross references files x xreflex - a lex(1) program used by xref x xref.1 - a manual entry for xref x xIt was developed on a 4.2BSD system, and assumes that make, lex, cc, xsh, ed, fgrep, sort, and awk are available under /bin or x/usr/{bin,ucb,local}. It should run with at worst minimal changes xunder any other flavor of UNIX. If fgrep, sort, and awk are somewhere xelse be sure to change the PATH in xrefhead.sh. x xThe idea is to cross reference files by "xref file1 ... >listing". xA pipeline of the form "lex program | fgrep | sort | awk" extracts xwords and their locations, discards extraneous ones, sorts the rest, xand merges the resulting name,file,line triples into a fairly standard xcross reference map. x xVarious make targets are available: x make all # makes xref & xreflex for /usr/local x make DESTDIR=somewhere all # ... for somewhere instead. x make piecetest # produce intermediate *_out files. x make DESTDIR=somewhere MANLOC=elsewhere install x # install xref, xreflex, xref.1 x make clean # remove computed files x xxref is produced by minor editing from xrefhead.sh and mergelines.awk. xxref.1 is produced by minor editing from xref.man. xxreflex is produced by lex and cc from xref.l. x x-- Jim Leinweber (jiml@uwmacc.UUCP, leinwebe@wisc-ai.ARPA) xMadison Academic Computing Center, 1210 W. Dayton ST., Madison Wi 53706 x//E*O*F READ_ME// chmod u=rw,g=r,o=r READ_ME echo x - mergelines.awk sed 's/^x//' > "mergelines.awk" <<'x//E*O*F mergelines.awk//' x# Input: lines of the form "name \t file \t line number" x# Output: merged lines of the form "name \t file \t n1 n2 n3 ..." x# Starts a new line for new names or files, and when line gets long. x# Suppresses name and previous file on continuation lines. x xBEGIN { # Print header and compute usable width x fmt = "%-14s\t%-14s\t%s\n" x printf fmt, "NAME", "FILE", "LINE NUMBERS" x ###uwidth = '$width'-16-16-5; # sizes of name, file, number x if (uwidth<3) uwidth=80-16-16-5; } x x$1 != name { printf fmt, pname, pfile, line; x name = pname = $1; file = pfile = $2; line = "" } x x$2 != file { printf fmt, pname, pfile, line; x pname = ""; file = pfile = $2; line = "" } x xlength(line) > uwidth { printf fmt, pname, pfile, line; x pname = ""; pfile = ""; line = "" } x x{ line = line " " sprintf("%4s",$3) } x xEND { printf fmt, pname, pfile, line } x//E*O*F mergelines.awk// chmod u=rw,g=r,o=r mergelines.awk echo x - xref.man sed 's/^x//' > "xref.man" <<'x//E*O*F xref.man//' x.TH XREF LOCAL U-WISC x.ad b x.SH NAME xxref \- cross reference files x.SH SYNOPSIS x\fBxref\fR [\fB-k\fR keyfile] [\fB-w\fR n] file ... x.SH DESCRIPTION x.I Xref xcross references to standard output xall the "names" in its (text) input files xtogether with the files and line numbers they occur on. xIf no files are supplied, it reads standard input. xNames consist of letters, underscores, and (non-initial) digits. x.PP xAvailable options are: x.TP x.B \-k " keyfile" xUse keyfile as a list of words which should be xsuppressed from the cross reference. xAs the removal is done via "fgrep -v", the words should occur one xper line. xTo prevent internal matches from discarding valid longer words, xeach word can be preceded by a space and followed by a tab. xBy default all words are included. x.TP x.B \-w " n" xFormat the output with a width of n columns, by default 80. xN is primarily intended for raising the line length; xa lower limit of 40 is silently enforced. x.ne 5 x.SH FILES x.br x???usrlocal/xreflex first stage of xref (lexical analyzer) x.SH DIAGNOSTICS xComplains about unreadable files, and exits with status 2 if no xfiles can be read. xUnhappy subprocesses (fgrep, sort, awk) may also bleat. x.SH "SEE ALSO" xctags(1), xegrep(1), xptx(1) x.SH BUGS xFilenames containing shell meta-characters may be misprocessed. xThe four stage pipeline is relatively inefficient. xA general purpose program cannot take advantage of semantic xknowledge of its input in order to produce prettier, better classified xoutput. x.SH AUTHOR xJim Leinweber x//E*O*F xref.man// chmod u=rw,g=r,o=r xref.man echo x - xref.man.sh sed 's/^x//' > "xref.man.sh" <<'x//E*O*F xref.man.sh//' x>xref.1 xed xref.1 < "xref.sh" <<'x//E*O*F xref.sh//' x>xref xed xref < "xrefhead.sh" <<'x//E*O*F xrefhead.sh//' x#! /bin/sh x# quick and dirty cross reference generator x xDESTDIR=???usrlocal # revised by Makefile xPATH=/bin:/usr/bin:/usr/ucb:$DESTDIR # revise these if necessary x xwidth=80 # defaults xfarg="-e '~'" # a dummy character x xfiles="" xwhile true xdo x case "$1" in x "") break;; x -k) keywords=$2; shift x farg="-f $keywords";; x -w) width=$2; shift;; x -*) echo 1>&2 "Usage: xref [-k keyfile] [-w n] [file ...]" x exit 2;; x *) files="$files $1";; x esac x shift xdone x xxreflex $files | x fgrep -v $farg | x sort -u +0f -1 +0 -1 +1 -2 +2n | x awk '\ x//E*O*F xrefhead.sh// chmod u=rw,g=r,o=r xrefhead.sh echo x - xreflex.l sed 's/^x//' > "xreflex.l" <<'x//E*O*F xreflex.l//' x%{ x#define INFINITE_LOOP while (1) xint gargc; /* global argc duplicate */ xchar **gargv; /* global argv duplicate */ xint n = 1; /* line counter */ xchar *fname = "-"; /* current file name */ x x%} xstartid [A-Za-z_] xmoreid [A-Za-z_0-9] x%% x{startid}{moreid}* printf(" %s\t%s\t%d\n", yytext, fname, n); x\n n++; x. ; x%% x xyywrap() x{ x /* reset line count & proceed to next file, or quit */ x n = 1; x if (next_open()) return(0); x else exit(0); x} x xnext_open() x{ x (void) fclose(stdin); x while (--gargc > 0) { x fname = *++gargv; x if (fopen(fname,"r") != NULL) x return(1); x fprintf(stderr, "xref: can't open %s\n", fname); x } x return(0); x} x xmain(argc,argv,env) xint argc; char **argv; char *env[]; x{ x gargc = argc; gargv=argv; x if (gargc==1 || next_open()) x INFINITE_LOOP (void) yylex(); x exit(2); x} x//E*O*F xreflex.l// chmod u=rw,g=r,o=r xreflex.l echo Inspecting for damage in transit... temp=/tmp/shar$$ dtemp=/tmp/.shar$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 28 117 746 Makefile 38 289 1792 READ_ME 23 161 847 mergelines.awk 49 251 1509 xref.man 8 11 66 xref.man.sh 11 15 108 xref.sh 28 84 557 xrefhead.sh 44 123 837 xreflex.l 229 1051 6462 total !!! wc Makefile READ_ME mergelines.awk xref.man xref.man.sh xref.sh\ xrefhead.sh xreflex.l | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0