blob: 7eab8faabfd2a8f8a07a00004eaa5f83a1b5e145 (
plain)
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
|
#!/bin/sh
[ -n "$BASH" ] || exec bash -p $0 $@
# Script to process man pages output by doxygen.
# We need to use bash for its associative array facility.
# (`bash -p` prevents import of functions from the environment).
# Args: none or 2 being man7 page name & relative path of source with \mainpage
declare -A renamed_page
main(){
set -e
pushd man/man3 >/dev/null; rm -f _*
count_real_pages
rename_real_pages
make_symlinks
post_process $@
}
count_real_pages(){
page_count=0
#
# Count "real" man pages (i.e. not generated by MAN_LINKS)
# MAN_LINKS pages are 1-liners starting .so
# Method: list files in descending order of size,
# looking for the first 1-liner
#
for i in $(ls -S)
do head -n1 $i | grep -E -q '^\.so' && break
page_count=$(($page_count + 1))
done
first_link=$(($page_count + 1))
}
rename_real_pages(){
for i in $(ls -S | head -n$page_count)
do for j in $(ls -S | tail -n+$first_link)
do grep -E -q $i$ $j && break
done
mv -f $i $j
renamed_page[$i]=$j
done
}
make_symlinks(){
for j in $(ls -S | tail -n+$first_link)
do ln -sf ${renamed_page[$(cat $j | cut -f2 -d/)]} $j
done
}
post_process(){
make_temp_files
#
# DIAGNOSTIC / DEVELOPMENT CODE
# set -x and restrict processing to keep_me: un-comment to activate
# Change keep_me as required
#
#keep_me=nfq_icmp_get_hdr.3;\
#do_diagnostics;\
#
# Work through the "real" man pages
for target in $(ls -S | head -n$page_count)
do mygrep "^\\.SH \"Function Documentation" $target
# Next file if this isn't a function page
[ $linnum -ne 0 ] || continue
del_modules
del_bogus_synopsis
fix_name_line
move_synopsis
del_empty_det_desc
del_def_at_lines
fix_double_blanks
# Fix rendering of verbatim "\n" (in code snippets)
sed -i 's/\\n/\\\\n/' $target
done
[ $# -ne 2 ] || make_man7 $@
remove_temp_files
}
make_man7(){
popd >/dev/null
target=$(grep -Ew INPUT doxygen.cfg | rev | cut -f1 -d' ' | rev)/$2
mypath=$(dirname $0)
# Build up temporary source in temp.c
# (doxygen only makes man pages from .c files).
mygrep \\\\mainpage $target
tail -n+$((linnum-1)) $target | head -n1 >temp.c
echo " * \\defgroup $1 $1 overview" >>temp.c
tail -n+$((linnum+1)) $target >$fileA
linnum=$(grep -En '\*/' $fileA | head -n1 | cut -d: -f1)
head -n$((linnum - 1)) $fileA >> temp.c
echo ' */' >> temp.c
cat >> temp.c <<////
/**
* @{
*
* $1 - DELETE_ME
*/
int $1(void)
{
return 0;
}
/**
* @}
*/
////
# Create temporary doxygen config in fileC
cat /dev/null >$fileC
for i in \
PROJECT_NAME \
PROJECT_NUMBER \
ABBREVIATE_BRIEF \
FULL_PATH_NAMES \
TAB_SIZE \
OPTIMIZE_OUTPUT_FOR_C \
EXAMPLE_PATTERNS \
ALPHABETICAL_INDEX \
SEARCHENGINE \
GENERATE_LATEX \
; do grep -Ew $i doxygen.cfg >>$fileC; done
cat >>$fileC <<////
INPUT = temp.c
GENERATE_HTML = NO
GENERATE_MAN = YES
MAN_EXTENSION = .7
////
doxygen $fileC >/dev/null
# Remove SYNOPSIS line if there is one
target=man/man7/$1.7
mygrep "SH SYNOPSIS" $target
[ $linnum -eq 0 ] || delete_lines $linnum $((linnum+1))
# doxygen 1.8.9.1 and possibly newer run the first para into NAME
# (i.e. in this unusual group). There won't be a SYNOPSIS when this happens
if grep -Eq "overview$1" $target; then
head -n2 temp.c >$fileA
cat >>$fileA <<////
* \\manonly
.PP
.SH "Detailed Description"
.PP
\\endmanonly
////
tail -n+3 temp.c >>$fileA
cat $fileA >temp.c
doxygen $fileC >/dev/null
fi
# Insert top-level "See also" of man7 page in all real man3 pages
for target in $(find man/man3 -type f)
do mygrep "Detailed Description" $target
[ $linnum -ne 0 ] || mygrep "Function Documentation" $target
[ $linnum -ne 0 ] || { echo "NO HEADER IN $target" >&2; continue; }
head -n$((linnum-1)) $target >$fileA
cat >>$fileA <<////
.SH "See also"
\\fB${1}\\fP(7)
////
tail -n+$linnum $target >>$fileA
cp $fileA $target
done
rm temp.c
}
fix_double_blanks(){
linnum=1
#
# Older versions of man display a blank line on encountering "\fB\fP";
# newer versions of man do not.
# doxygen emits "\fB\fP" on seeing "\par" on a line by itself.
# "\par" gives us double-spacing in the web doc, which we want, but double-
# spacing looks odd in a man page so remove "\fB\fP".
#
while [ $linnum -ne 0 ]
do mygrep \\\\fB\\\\fP $target
[ $linnum -eq 0 ] || delete_lines $linnum $linnum
done
}
del_def_at_lines(){
linnum=1
while [ $linnum -ne 0 ]
do mygrep '^Definition at line (\\fB)?[[:digit:]]*(\\fP)? of file' $target
[ $linnum -eq 0 ] || delete_lines $(($linnum - 1)) $linnum
done
}
# Only invoked if you un-comment the 2 diagnostic / development lines above
do_diagnostics(){
mv $keep_me xxx
rm *.3
mv xxx $keep_me
page_count=1
set -x
}
del_empty_det_desc(){
mygrep "^\\.SH \"Function Documentation" $target
i=$linnum
mygrep "^\\.SH \"Detailed Description" $target
[ $linnum -ne 0 ] || return 0
[ $(($i - $linnum)) -eq 3 ] || return 0
# A 1-line Detailed Description is also 3 lines long,
# but the 3rd line is not empty
i=$(($i -1))
[ $(tail -n+$i $target | head -n1 | wc -c) -le 2 ] || return 0
delete_lines $linnum $i
}
move_synopsis(){
mygrep "SH SYNOPSIS" $target
[ $linnum -ne 0 ] || return 0
i=$linnum
# If this is a doxygen-created synopsis, leave it.
# (We haven't inserted our own one in the source yet)
mygrep "^\\.SS \"Functions" $target
[ $i -gt $linnum ] || return 0
mygrep "^\\.SH \"Function Documentation" $target
j=$(($linnum - 1))
head -n$(($j - 1)) $target | tail -n$(($linnum - $i - 1)) >$fileC
delete_lines $i $j
mygrep "^\\.SS \"Functions" $target
head -n$(($linnum - 1)) $target >$fileA
tail -n+$(($linnum + 1)) $target >$fileB
cat $fileA $fileC $fileB >$target
}
fix_name_line(){
all_funcs=""
# Search a shortened version of the page in case there are .RI lines later
mygrep "^\\.SH \"Function Documentation" $target
head -n$linnum $target >$fileC
while :
do mygrep ^\\.RI $fileC
[ $linnum -ne 0 ] || break
# Discard this entry
tail -n+$(($linnum + 1)) $fileC >$fileB
cp $fileB $fileC
func=$(cat $fileG | cut -f2 -d\\ | cut -c3-)
[ -z "$all_funcs" ] && all_funcs=$func ||\
all_funcs="$all_funcs, $func"
done
# For now, assume name is at line 5
head -n4 $target >$fileA
desc=$(head -n5 $target | tail -n1 | cut -f3- -d" ")
tail -n+6 $target >$fileB
cat $fileA >$target
echo "$all_funcs \\- $desc" >>$target
cat $fileB >>$target
}
del_modules(){
mygrep "^\.SS \"Modules" $target
[ $linnum -ne 0 ] || return 0
i=$linnum
mygrep "^\\.SS \"Functions" $target
delete_lines $i $(($linnum - 1))
}
del_bogus_synopsis(){
mygrep "SH SYNOPSIS" $target
#
# doxygen 1.8.20 inserts its own SYNOPSIS line but there is no mention
# in the documentation or git log what to do with it.
# So get rid of it
#
[ $linnum -ne 0 ] || return 0
i=$linnum
# Look for the next one
tail -n+$(($i + 1)) $target >$fileC;\
mygrep "SH SYNOPSIS" $fileC
[ $linnum -ne 0 ] || return 0
mygrep "^\\.SS \"Functions" $target
delete_lines $i $(($linnum - 1))
}
# Delete lines $1 through $2 from $target
delete_lines(){
head -n$(($1 - 1)) $target >$fileA
tail -n+$(($2 +1)) $target >$fileB
cat $fileA $fileB >$target
}
mygrep(){
set +e
grep -En "$1" $2 2>/dev/null >$fileH
[ $? -ne 0 ] && linnum=0 ||\
{ head -n1 $fileH >$fileG; linnum=$(cat $fileG | cut -f1 -d:); }
set -e
}
make_temp_files(){
temps="A B C G H"
for i in $temps
do declare -g file$i=$(mktemp)
done
}
remove_temp_files(){
for i in $temps
do j=file$i
rm ${!j}
done
}
main $@
|