1#!/bin/bash 2 3# Runs doxygen and massages the output files. 4# Copyright (C) 2001-2020 Free Software Foundation, Inc. 5# 6# Synopsis: run_doxygen --mode=[html|latex|man|xml] --host_alias=<alias> \ 7# v3srcdir \ 8# v3builddir \ 9# shortname 10# 11# Originally hacked together by Phil Edwards <pme@gcc.gnu.org> 12 13 14# We can check now that the version of doxygen is >= this variable. 15DOXYVER=1.7.0 16 17find_doxygen() { 18 local -r v_required=`echo $DOXYVER | \ 19 awk -F. '{if(NF<3)$3=0;print ($1*100+$2)*100+$3}'` 20 local testing_version doxygen maybedoxy v_found 21 # thank you goat book 22 set `IFS=:; X="$PATH:/usr/local/bin:/bin:/usr/bin"; echo $X` 23 for dir 24 do 25 # AC_EXEEXT could come in useful here 26 maybedoxy="$dir/doxygen" 27 test -f "$maybedoxy" && testing_version=`$maybedoxy --version` 28 if test -n "$testing_version"; then 29 v_found=`echo $testing_version | \ 30 awk -F. '{if(NF<3)$3=0;print ($1*100+$2)*100+$3}'` 31 if test $v_found -ge $v_required; then 32 doxygen="$maybedoxy" 33 break 34 fi 35 fi 36 done 37 if test -z "$doxygen"; then 38 echo run_doxygen error: Could not find Doxygen $DOXYVER in path. 1>&2 39 print_usage 40 fi 41 # We need to use other tools from the same package/version. 42 echo :: Using Doxygen tools from ${dir}. 43 PATH=$dir:$PATH 44 hash -r 45} 46 47print_usage() { 48 cat 1>&2 <<EOF 49Usage: run_doxygen --mode=MODE --host_alias=BUILD_ALIAS [<options>] 50 <v3-src-dir> <v3-build-dir> <shortnamesp> 51 MODE is one of: 52 html Generate user-level HTML library documentation. 53 man Generate user-level man pages. 54 xml Generate user-level XML pages. 55 latex Generate user-level LaTeX pages. 56 57 BUILD_ALIAS is the GCC build alias set at configure time. 58 59Note: Requires Doxygen ${DOXYVER} or later; get it at 60 ftp://ftp.stack.nl/pub/users/dimitri/doxygen-${DOXYVER}.src.tar.gz 61 62EOF 63 exit 1 64} 65 66parse_options() { 67 for o 68 do 69 # Blatantly ripped from autoconf, er, I mean, "gratefully standing 70 # on the shoulders of those giants who have gone before us." 71 case "$o" in 72 -*=*) arg=`echo "$o" | sed 's/[-_a-zA-Z0-9]*=//'` ;; 73 *) arg= ;; 74 esac 75 76 case "$o" in 77 --mode=*) 78 mode=$arg ;; 79 --host_alias=*) 80 host_alias=$arg ;; 81 --mode | --host_alias | --help | -h) 82 print_usage ;; 83 *) 84 # this turned out to be a mess, maybe change to --srcdir=, etc 85 if test $srcdir = unset; then 86 srcdir=$o 87 elif test $outdir = unset; then 88 builddir=${o} 89 outdir=${o}/doc/doxygen 90 elif test $shortname = unset; then 91 shortname=$o 92 else 93 echo run_doxygen error: Too many arguments 1>&2 94 exit 1 95 fi 96 ;; 97 esac 98 done 99} 100 101 102# script begins here 103mode=unset 104host_alias=unset 105srcdir=unset 106outdir=unset 107shortname=unset 108do_html=false 109do_man=false 110do_xml=false 111do_latex=false 112enabled_sections= 113generate_tagfile= 114DATEtext=`date '+%Y-%m-%d'` 115 116# Show how this script is called. 117echo run_doxygen $* 118 119parse_options $* 120find_doxygen 121 122if test $srcdir = unset || test $outdir = unset || test $mode = unset || test $shortname = unset || test $host_alias = unset; then 123 # this could be better 124 echo run_doxygen error: You have not given enough information...! 1>&2 125 print_usage 126fi 127 128case x"$mode" in 129 xhtml) 130 do_html=true 131 enabled_sections=maint 132 generate_tagfile="$outdir/html/libstdc++.tag" 133 ;; 134 xlatex) 135 do_latex=true 136 enabled_sections=maint 137 ;; 138 xman) 139 do_man=true 140 ;; 141 xxml) 142 do_xml=true 143 enabled_sections=maint 144 ;; 145 *) 146 echo run_doxygen error: $mode is an invalid mode 1>&2 147 exit 1 ;; 148esac 149 150case x"$shortname" in 151 xYES) 152 ;; 153 xNO) 154 ;; 155 *) 156 echo run_doxygen error: $shortname is invalid 1>&2 157 exit 1 ;; 158esac 159 160 161mkdir -p $outdir 162chmod u+w $outdir 163 164# Run it 165( 166 set -e 167 cd $builddir 168 sed -e "s=@outdir@=${outdir}=g" \ 169 -e "s=@srcdir@=${srcdir}=g" \ 170 -e "s=@shortname@=${shortname}=g" \ 171 -e "s=@builddir@=${builddir}=g" \ 172 -e "s=@host_alias@=${host_alias}=g" \ 173 -e "s=@enabled_sections@=${enabled_sections}=" \ 174 -e "s=@do_html@=${do_html}=" \ 175 -e "s=@do_latex@=${do_latex}=" \ 176 -e "s=@do_man@=${do_man}=" \ 177 -e "s=@do_xml@=${do_xml}=" \ 178 -e "s=@generate_tagfile@=${generate_tagfile}=" \ 179 ${srcdir}/doc/doxygen/user.cfg.in > ${outdir}/${mode}.cfg 180 echo :: NOTE that this may take some time... 181 echo doxygen ${outdir}/${mode}.cfg 182 doxygen ${outdir}/${mode}.cfg 183) 184ret=$? 185test $ret -ne 0 && exit $ret 186 187if $do_xml; then 188 echo :: 189 echo :: XML pages begin with 190 echo :: ${outdir}/xml/index.xml 191fi 192 193if $do_latex; then 194 cd ${outdir}/${mode} 195 196 # Grrr, Doxygen 1.8.x changed the -w latex options. 197 need_footer=`doxygen -h | sed -n -e '/-w latex/s=.*footer.*=true=p'` 198 199 # Also drop in the header file (maybe footer file) and style sheet 200 if $need_footer; then 201 doxygen -w latex header.tex footer.tex doxygen.sty 202 else 203 doxygen -w latex header.tex doxygen.sty 204 fi 205 206 echo :: 207 echo :: LaTeX pages begin with 208 echo :: ${outdir}/latex/refman.tex 209fi 210 211if $do_html; then 212 cd ${outdir}/${mode} 213 214 #doxytag -t libstdc++.tag . > /dev/null 2>&1 215 216 # Strip pathnames from tag file. 217 sed -e '/<path>/d' libstdc++.tag > TEMP 218 mv TEMP libstdc++.tag 219 220 sed -e "s=@DATE@=${DATEtext}=" \ 221 ${srcdir}/doc/doxygen/mainpage.html > index.html 222 223 # The following bit of line noise changes annoying 224 # std::foo < typename _Ugly1, typename _Ugly2, .... _DefaultUgly17 > 225 # to user-friendly 226 # std::foo 227 # in the major "Compound List" page. 228 sed -e 's=\(::[[:alnum:]_]*\)< .* >=\1=' annotated.html > annstrip.html 229 mv annstrip.html annotated.html 230 231 cp ${srcdir}/doc/doxygen/tables.html tables.html 232 233 echo :: 234 echo :: HTML pages begin with 235 echo :: ${outdir}/html/index.html 236fi 237 238# Mess with the man pages. We don't need documentation of the internal 239# headers, since the man pages for those contain nothing useful anyhow. The 240# man pages for doxygen modules need to be renamed (or deleted). And the 241# generated #include lines need to be changed from the internal names to the 242# standard ones (e.g., "#include <stl_tempbuf.h>" -> "#include <memory>"). 243if $do_man; then 244echo :: 245echo :: Fixing up the man pages... 246cd $outdir/man/man3 247 248# File names with embedded spaces (EVIL!) need to be....? renamed or removed? 249find . -name "* *" -print0 | xargs -0r rm # requires GNU tools 250 251# man pages are for functions/types/other entities, not source files 252# directly. who the heck would type "man foo.h" anyhow? 253find . -name "[a-z]*" -a ! -name "std_*" -print | xargs rm 254rm -f *.h.3 *.hpp.3 *config* *.cc.3 *.tcc.3 *_t.3 255#rm ext_*.3 tr1_*.3 debug_*.3 256 257# this is used to examine what we would have deleted, for debugging 258#mkdir trash 259#find . -name "[a-z]*" -a ! -name "std_*" -print | xargs -i mv {} trash 260#mv *.h.3 *config* *.cc.3 *.tcc.3 *_t.3 trash 261 262# Standardize the displayed header names. If anyone who knows perl cares 263# enough to rewrite all this, feel free. This only gets run once a century, 264# and I'm off getting coffee then anyhow, so I didn't care enough to make 265# this super-fast. 266g++ ${srcdir}/doc/doxygen/stdheader.cc -o ./stdheader 267problematic=`egrep -l '#include <.*_.*>' [a-z]*.3` 268for f in $problematic; do 269 # this is also slow, but safe and easy to debug 270 oldh=`sed -n '/fC#include </s/.*<\(.*\)>.*/\1/p' $f` 271 newh=`echo $oldh | ./stdheader` 272 sed 's=${oldh}=${newh}=' $f > TEMP 273 mv TEMP $f 274done 275rm stdheader 276 277# Some of the pages for generated modules have text that confuses certain 278# implementations of man(1), e.g. on GNU/Linux. We need to have another 279# top-level *roff tag to /stop/ the .SH NAME entry. 280problematic=`egrep --files-without-match '^\.SH SYNOPSIS' [A-Z]*.3` 281#problematic='Containers.3 Sequences.3 Assoc_containers.3 Iterator_types.3' 282 283for f in $problematic; do 284 sed '/^\.SH NAME/{ 285n 286a\ 287\ 288.SH SYNOPSIS 289 }' $f > TEMP 290 mv TEMP $f 291done 292 293# Also, break this (generated) line up. It's ugly as sin. 294problematic=`grep -l '[^^]Definition at line' *.3` 295for f in $problematic; do 296 sed 's/Definition at line/\ 297.PP\ 298&/' $f > TEMP 299 mv TEMP $f 300done 301 302cp ${srcdir}/doc/doxygen/Intro.3 C++Intro.3 303 304# Why didn't I do this at the start? Were rabid weasels eating my brain? 305# Who the fsck would "man std_vector" when the class isn't named that? 306 307# First, deal with nested namespaces. 308for f in *chrono_*; do 309 newname=`echo $f | sed 's/chrono_/chrono::/'` 310 mv $f $newname 311done 312for f in *__debug_*; do 313 newname=`echo $f | sed 's/__debug_/__debug::/'` 314 mv $f $newname 315done 316for f in *decimal_*; do 317 newname=`echo $f | sed 's/decimal_/decimal::/'` 318 mv $f $newname 319done 320for f in *__detail_*; do 321 newname=`echo $f | sed 's/__detail_/__detail::/'` 322 mv $f $newname 323done 324for f in *__gnu_pbds_detail_*; do 325 newname=`echo $f | sed 's/detail_/detail::/'` 326 mv $f $newname 327done 328for f in *__parallel_*; do 329 newname=`echo $f | sed 's/__parallel_/__parallel::/'` 330 mv $f $newname 331done 332 333# Remove inline namespaces used for versioning. 334for f in *_V2_*; do 335 newname=`echo $f | sed 's/_V2_/::/'` 336 sed 's/::_V2::/::/g' $f > $newname 337 rm $f 338done 339for f in *_experimental_filesystem_v?_*; do 340 newname=`echo $f | sed 's/_filesystem_v._/::filesystem::/'` 341 sed 's/::filesystem::v.::/::filesystem::/g' $f > $newname 342 rm $f 343done 344for f in *experimental_fundamentals_v?_*; do 345 newname=`echo $f | sed 's/experimental_.*_v[[:digit:]]_/experimental::/'` 346 sed 's/::experimental::fundamentals_v[[:digit:]]::/::experimental::/g' $f > $newname 347 rm $f 348done 349 350# Then, clean up other top-level namespaces. 351for f in std_tr1_*; do 352 newname=`echo $f | sed 's/^std_tr1_/std::tr1::/'` 353 mv $f $newname 354done 355for f in std_tr2_*; do 356 newname=`echo $f | sed 's/^std_tr2_/std::tr2::/'` 357 mv $f $newname 358done 359for f in std_*; do 360 newname=`echo $f | sed 's/^std_/std::/'` 361 mv $f $newname 362done 363for f in __gnu_cxx_*; do 364 newname=`echo $f | sed 's/^__gnu_cxx_/__gnu_cxx::/'` 365 mv $f $newname 366done 367for f in __gnu_debug_*; do 368 newname=`echo $f | sed 's/^__gnu_debug_/__gnu_debug::/'` 369 mv $f $newname 370done 371for f in __gnu_parallel_*; do 372 newname=`echo $f | sed 's/^__gnu_parallel_/__gnu_parallel::/'` 373 mv $f $newname 374done 375for f in __gnu_pbds_*; do 376 newname=`echo $f | sed 's/^__gnu_pbds_/__gnu_pbds::/'` 377 mv $f $newname 378done 379for f in __cxxabiv1_*; do 380 newname=`echo $f | sed 's/^__cxxabiv1_/abi::/'` 381 mv $f $newname 382done 383 384# Then piecemeal nested classes 385 386 387# Generic removal bits, where there are things in the generated man 388# pages that need to be killed. 389for f in *_libstdc__-v3_*; do 390 rm $f 391done 392 393for f in *_src_*; do 394 rm $f 395done 396 397 398# Also, for some reason, typedefs don't get their own man pages. Sigh. 399for f in ios streambuf istream ostream iostream stringbuf \ 400 istringstream ostringstream stringstream filebuf ifstream \ 401 ofstream fstream string; 402do 403 echo ".so man3/std::basic_${f}.3" > std::${f}.3 404 echo ".so man3/std::basic_${f}.3" > std::w${f}.3 405done 406 407echo :: 408echo :: Man pages in ${outdir}/man 409fi 410 411# all done 412echo :: 413 414exit 0 415