-
Notifications
You must be signed in to change notification settings - Fork 3
/
runoff
executable file
·246 lines (221 loc) · 4.92 KB
/
runoff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#!/bin/sh
echo This script takes a minute to run. Be patient. 1>&2
LC_CTYPE=C export LC_CTYPE
# pad stdin to multiple of 120 lines
pad()
{
awk '{print} END{for(; NR%120!=0; NR++) print ""}'
}
# create formatted (numbered) files
mkdir -p fmt
rm -f fmt/*
cp README fmt
echo > fmt/blank
files=`grep -v '^#' runoff.list | awk '{print $1}'`
n=99
for i in $files
do
./runoff1 -n $n $i >fmt/$i
nn=`tail -1 fmt/$i | sed 's/ .*//; s/^0*//'`
if [ "x$nn" != x ]; then
n=$nn
fi
done
# create table of contents
cat toc.hdr >fmt/toc
pr -e8 -t runoff.list | awk '
/^[a-z0-9]/ {
s=$0
f="fmt/"$1
getline<f
close(f)
n=$1
printf("%02d %s\n", n/100, s);
printf("TOC: %04d %s\n", n, s) >"fmt/tocdata"
next
}
{
print
}' | pr -3 -t >>fmt/toc
cat toc.ftr >>fmt/toc
# check for bad alignments
perl -e '
$leftwarn = 0;
while(<>){
chomp;
s!#.*!!;
s!\s+! !g;
s! +$!!;
next if /^$/;
if(/TOC: (\d+) (.*)/){
$toc{$2} = $1;
next;
}
if(/sheet1: (left|right)$/){
print STDERR "assuming that sheet 1 is a $1 page. double-check!\n";
$left = $1 eq "left" ? "13579" : "02468";
$right = $1 eq "left" ? "02468" : "13579";
next;
}
if(/even: (.*)/){
$file = $1;
if(!defined($toc{$file})){
print STDERR "Have no toc for $file\n";
next;
}
if($toc{$file} =~ /^\d\d[^0]/){
print STDERR "$file does not start on a fresh page.\n";
}
next;
}
if(/odd: (.*)/){
$file = $1;
if(!defined($toc{$file})){
print STDERR "Have no toc for $file\n";
next;
}
if($toc{$file} !~ /^\d\d5/){
print STDERR "$file does not start on a second half page.\n";
}
next;
}
if(/(left|right): (.*)/){
$what = $1;
$file = $2;
if(!defined($toc{$file})){
print STDERR "Have no toc for $file\n";
next;
}
if($what eq "left" && !($toc{$file} =~ /^\d[$left][05]/)){
print STDERR "$file does not start on a left page [$toc{$file}]\n";
}
# why does this not work if I inline $x in the if?
$x = ($toc{$file} =~ /^\d[$right][05]/);
if($what eq "right" && !$x){
print STDERR "$file does not start on a right page [$toc{$file}] [$x]\n";
}
next;
}
print STDERR "Unknown spec: $_\n";
}
' fmt/tocdata runoff.spec
# make definition list
cd fmt
perl -e '
while(<>) {
chomp;
s!//.*!!;
s!/\*([^*]|[*][^/])*\*/!!g;
s!\s! !g;
s! +$!!;
# look for declarations like char* x;
if (/^[0-9]+ typedef .* u(int|short|long|char);/) {
next;
}
if (/^[0-9]+ extern/) {
next;
}
if (/^[0-9]+ struct [a-zA-Z0-9_]+;/) {
next;
}
if (/^([0-9]+) #define +([A-za-z0-9_]+) +?\(.*/) {
print "$1 $2\n"
}
elsif (/^([0-9]+) #define +([A-Za-z0-9_]+) +([^ ]+)/) {
print "$1 $2 $3\n";
}
elsif (/^([0-9]+) #define +([A-Za-z0-9_]+)/) {
print "$1 $2\n";
}
if(/^^([0-9]+) \.globl ([a-zA-Z0-9_]+)/){
$isglobl{$2} = 1;
}
if(/^^([0-9]+) ([a-zA-Z0-9_]+):$/ && $isglobl{$2}){
print "$1 $2\n";
}
if (/\(/) {
next;
}
if (/^([0-9]+) (((static|struct|extern|union|enum) +)*([A-Za-z0-9_]+))( .*)? +([A-Za-z_][A-Za-z0-9_]*)(,|;|=| =)/) {
print "$1 $7\n";
}
elsif(/^([0-9]+) (enum|struct|union) +([A-Za-z0-9_]+) +{/){
print "$1 $3\n";
}
# TODO: enum members
}
' $files >defs
(for i in $files
do
case "$i" in
*.S)
cat $i | sed 's;#.*;;; s;//.*;;;'
;;
*)
cat $i | sed 's;//.*;;; s;"([^"\\]|\\.)*";;;'
esac
done
) >alltext
perl -n -e 'print if s/^([0-9]+ [a-zA-Z0-9_]+)\(.*$/\1/;' alltext |
egrep -v ' (STUB|usage|main|if|for)$' >>defs
#perl -n -e 'print if s/^([0-9]+) STUB\(([a-zA-Z0-9_]+)\)$/\1 \2/;' alltext \
# >>defs
(
>s.defs
# make reference list
for i in `awk '{print $2}' defs | sort -f | uniq`
do
defs=`egrep '^[0-9]+ '$i'( |$)' defs | awk '{print $1}'`
echo $i $defs >>s.defs
uses=`egrep -h '([^a-zA-Z_0-9])'$i'($|[^a-zA-Z_0-9])' alltext | awk '{print $1}'`
if [ "x$defs" != "x$uses" ]; then
echo $i $defs
echo $uses |fmt -29 | sed 's/^/ /'
# else
# echo $i defined but not used >&2
fi
done
) >refs
# build defs list
awk '
{
printf("%04d %s\n", $2, $1);
for(i=3; i<=NF; i++)
printf("%04d \" \n", $i);
}
' s.defs > t.defs
# format the whole thing
(
../pr.pl README
../pr.pl -h "table of contents" toc
# pr -t -2 t.defs | ../pr.pl -h "definitions" | pad
pr -t -l50 -2 refs | ../pr.pl -h "cross-references" | pad
# pr.pl -h "definitions" -2 t.defs | pad
# pr.pl -h "cross-references" -2 refs | pad
../pr.pl blank # make sheet 1 start on left page
../pr.pl blank
for i in $files
do
../pr.pl -h "xv6/$i" $i
done
) | mpage -m50t50b -o -bLetter -T -t -2 -FCourier -L60 >all.ps
grep Pages: all.ps
# if we have the nice font, use it
nicefont=LucidaSans-Typewriter83
if [ ! -f ../$nicefont ]
then
if git cat-file blob font:$nicefont > ../$nicefont~; then
mv ../$nicefont~ ../$nicefont
fi
fi
if [ -f ../$nicefont ]
then
echo nicefont
(sed 1q all.ps; cat ../$nicefont; sed "1d; s/Courier/$nicefont/" all.ps) >allf.ps
else
echo ugly font!
cp all.ps allf.ps
fi
ps2pdf allf.ps ../xv6.pdf
# cd ..
# pdftops xv6.pdf xv6.ps