#!/bin/sh
### make v6 unix source listing book
### whutt!wally WH 3A-327 AUGUST MCMLXXXVIII
# This takes forever: it will to take more than 15 minutes on a 3b20,
# So here's a timex of printing this on a lightly
# loaded IBM 3081k (2 CPU 16 MIP) running UTS:
# real 3:07.13
# user 1:23.45
# sys 15.93
# Nearly all this time is used in making the Reference pages.
# If you don't want the reference pages made set "REFS=false" below
#
# set up
REFS=${REFS:-true}
umask 066
UNIX="UNIX Operating System"
TMPHOLD=/tmp/.v6.out
TMP=/tmp/unix
ASMLST=/tmp/asm.lst
PLST=/tmp/procs.lst
ASM_ONLY=/tmp/.v6.s.tmp
NO_ASM=/tmp/.v6.no.s.tmp
XREF=/tmp/xlist.tmp
mkdir $TMP
trap "rm -rf $TMPHOLD $TMP $ASMLST $PLST $ASM_ONLY $NO_ASM $XREF;exit" 0 1 2 3
SRCDIR=`pwd`
AWK=nawk
XFILE=/tmp/unix/.unumber
# Set up order of files
SET1="param.h systm.h seg.h proc.h user.h low.s m40.s main.c slp.c prf.c malloc.c"
SET2="reg.h trap.c sysent.c sys1.c sys4.c clock.c sig.c"
SET3="text.h text.c buf.h conf.h conf.c bio.c rk.c"
SET4="file.h filsys.h ino.h inode.h sys2.c sys3.c rdwri.c subr.c fio.c alloc.c iget.c nami.c pipe.c"
SET5="tty.h kl.c tty.c pc.c lp.c mem.c"
ORDER="$SET1 $SET2 $SET3 $SET4 $SET5"
# Go!
> $XFILE
for i in $ORDER
do
# this awk script "eats" the first "^I" because "4.4%d %c%c%c" is the
# fisrt tab stop. Make each first one 2 "^I"s.
sed 's/^ / /' $i | \
$AWK '
BEGIN {XFILE="/tmp/unix/.unumber"
getline start < XFILE
if (start<100) start=100;
lineno=start;lx=0;
TAIL1="Reproduced under license from the Western Electric Company, NY";
TAIL2="Copyright, J. Lions, 1976"
}
{ printf("%4.4d ",lineno);
print $0;
lineno++;
lx++;
if(lx == 50) {
printf("\n\n%s\n%s\n\nSheet %2.2d\n",TAIL1,TAIL2,(lineno-50)/100);
lx=0;
}
}
END {print lineno > XFILE}' >$TMP/$i
done
cd $TMP/..
DIR=`echo $TMP | $AWK '{x=split($1,S,"/"); print S[x]}'`
# need to stick $DIR in front of every element in $ORDER; sure would be nice
# to have the functionality of "rc" from "Plan 9", which would do it easy.
for i in $ORDER
do
XORDER="$XORDER $DIR/$i"
done
pr -w66 -l66 $XORDER > $TMPHOLD
if $REFS
then
# Make Reference Pages Before the book!
cd $SRCDIR
# Make procedure list sorted alfa..
# first - treat assembly special they start with an _
grep '^....[ ]_[a-z][a-z]*[0-9]*:' $TMPHOLD | $AWK '{print $1, $2}' > $ASMLST
for i in `cut -d_ -f2 $ASMLST | cut -d: -f1`
do
A=`grep -l "[ (&*!|+-=/:?]*$i[ ]*(" $TMPHOLD`
if [ "$A" != "" ]
then
grep "_$i:" $ASMLST
fi
done | sed 's/_//' > $PLST
# now do all C functions.
grep '^....[ ][a-z][a-z]*[0-9]*(.*)[ ]*$' $TMPHOLD | cut -d'(' -f1 >> $PLST
sort +1 $PLST | pr -4 -w132 -l66 -h "$UNIX Procedures Sorted Alphabetically"
# Make procedure listing file by file and getline number from above
for i in $ORDER
do
echo " File $i"
FT=`echo $i | cut -d. -f2`
if [ "$FT" = "s" ]
then
# this is an assembly module
A=`grep '^_[a-z][a-z]*[0-9]*:' $i | cut -d_ -f2 | cut -d: -f1`
for j in $A
do
grep " $j:\$" $PLST
done | sed 's/ / _/'
else
A=`grep '^[a-z][a-z]*[0-9]*(.*)[ ]*$' $i | cut -d'(' -f1`
for j in $A
do
grep " $j\$" $PLST
done
fi
done | pr -5 -w132 -l66 -h "$UNIX Files and Procedures"
# Make list of all #define'd symbols and their values
grep '#define' $TMPHOLD | \
$AWK '{printf("%s %s \t%s\n",$1,$3,$4)}' | sort +1 |\
pr -5 -w132 -l66 -h "$UNIX Defined Symbols"
# Now the hard part - the Cross listing
# Use a tokenizer to get all tokens (and line numbers)
# Since rules for C and asm differ; must use sep. progs.
SSTR=`grep -n 'unix/.*\.s' $TMPHOLD | sed -n 1p | cut -d: -f1`
SEND=`grep -n 'unix/.*\.s' $TMPHOLD | tail -1 | cut -d: -f1`
SEND=`expr $SEND + 60`
sed -n $SSTR,${SEND}p $TMPHOLD > $ASM_ONLY
sed $SSTR,${SEND}d $TMPHOLD > $NO_ASM
# first the assemby --
grep '^....[ ]*[A-Za-z_][A-Za-z_0-9]*:' $ASM_ONLY | cut -d: -f1 |\
$AWK '{print $2, $1}' | sed 's/_//' > $XREF
$AWK '
BEGIN { go() }
function gettok() {
if (tok == "(eof)") return "(eof)"
sub(/^[ \t]+/, "", line)
tokno++;
while ((nlen=length(line)) == 0) {
if(getline line == 0)
return tok = "(eof)"
if (line ~ /^[0-9][0-9][0-9][0-9]/) {
lineno = substr(line, 1, 4);
line = substr(line, 5);
} else line =""
sub(/^[ \t]+/, "", line)
tokno = 0
}
if (line ~ /^[A-Za-z]/) {
nxtn = 1
xline = substr(line, 2);
while((xline ~ /^[A-Za-z_0-9]/) && (nxtn < nlen)) {
nxtn++;
xline = substr(xline, 2);
}
}
else if (line ~ /^./) {
nxtn =1
}
tok = substr(line, 1, nxtn)
line = substr(line, nxtn+1)
return tok
}
function go() {
gettok();
while ( tok != "(eof)" ) {
filter();
gettok();
}
}
function filter()
{
if( tok != "/*") {
if((tok ~ /^[A-Za-z]/) && (tokno != 0))
print tok, lineno
if(tok == "/" )
line = ""
if(tok == "\"")
if((stp=index(line, "\"")) != 0)
line = substr(line, stp+1)
}
else while((tok != "(eof)") && (tok != "*/")) gettok();
}
' $ASM_ONLY |\
sed -e '/^[bfA-Z] /d' -e '/^globl /d' -e '/^r[0-9] /d' -e '/^sp /d' -e '/^PS /s' -e '/^pc /d' >> $XREF
# this only prints the identifier tokens
$AWK '
BEGIN { go() }
function gettok() {
if (tok == "(eof)") return "(eof)"
sub(/^[ \t]+/, "", line)
while ((nlen=length(line)) == 0) {
if(getline line == 0)
return tok = "(eof)"
if (line ~ /^[0-9][0-9][0-9][0-9]/) {
lineno = substr(line, 1, 4);
line = substr(line, 5);
} else line =""
sub(/^[ \t]+/, "", line)
}
if (line ~ /^[A-Za-z]/) {
nxtn = 1
xline = substr(line, 2);
while((xline ~ /^[A-Za-z_0-9]/) && (nxtn < nlen)) {
nxtn++;
xline = substr(xline, 2);
}
}
else if((line ~ /^(\/\*)/) || (line ~ /^(\*\/)/)) {
nxtn = 2
}
else if (line ~ /^./) {
nxtn =1
}
tok = substr(line, 1, nxtn)
line = substr(line, nxtn+1)
return tok
}
function go() {
gettok();
while ( tok != "(eof)" ) {
filter();
gettok();
}
}
function filter()
{
if( tok != "/*") {
if(tok ~ /^[A-Za-z]/)
print tok, lineno
if(tok == "\"")
if((stp=index(line, "\"")) != 0)
line = substr(line, stp+1)
}
else while((tok != "(eof)") && (tok != "*/")) gettok();
}
' $NO_ASM |\
sed -e '/^for /d' -e '/^do /d' -e '/^while /d' -e '/^case /d' -e '/^switch /d' -e '/^include /d' -e '/^if /d' -e '/^define /d' -e '/^return /d' -e '/^struct /d' -e '/^int /d' -e '/^char /d' -e '/^register /d' -e '/^[a-im-pstA-Z] /d' -e '/^default /d' -e '/^goto /d' -e '/^break /d' -e '/^continue /d' -e '/^sizeof /d' >> $XREF
# the above sed removes C dirty words and other nasties
sort -f $XREF | uniq | $AWK '
BEGIN {last1 = ""; col=0}
{
if (last1 == $1) {
if(col>3) {
printf("\n ");
col = 0
}
printf("%s ",$2);
col++;
} else {
if (col > 0) printf("\n")
printf("%s",$1);
x=10-length($1)
while((x--)>0) printf(" ");
printf("%s ",$2);
col =1;
last1 = $1
}
}
END {print}
' |\
pr -4 -w132 -l66 -h "$UNIX Source Code Cross Reference Listing"
fi #end-if of if $REFS
# Now, finally print the source code!!
# sed is to fix up stuff chopped off because of "pr -2"
pr -t -2 -w132 -l66 $TMPHOLD | \
sed -e '/lists: for/s/associat./associat-/' -e '/\*f_offset/s/nter \*./nter *\//' -e '/)(ip->i_addr\[0\])$/s/$/;/' -e '/\[0\],v)./s/v)./v);/' -e '/[ers] \*$/s/$/\//' -e '/==0$/s/$/)/' -e '/++$/s/$/)/'