#!/bin/sh # # mangen - generate manual entries for library # # modification history # 02g,16jul93,abh Added compatibility for FORTRAN "C" style comments. See # STAR programming guidelines for template. # 02f,08may90,jdi nroff lines: took out colrm, added tbl and -Tlp. # 02e,12mar90,jdi made NOMANUAL work for module entries; # added CS/CE macros to routine declarations in lib synopsis. # 02d,25jan90,rbr works with "#!/bin/awk -f" and the like # 02c,10apr89,dnw changed to always put individual routine manual entries in # chapter 2 instead of in (summary chapter + 1), so driver # routines end up in 2 rather than 4. # 02b,05apr89,dnw removed NOT_GENERIC filter # added removing of mg.out and mgr.out before starting # 02a,05nov87,jlf changed to allow mangen'ing of scripts # changed so routine definitions that don't fit on one # one line, have a '...' appended in synopses. # changed documentation format so mangen can be mangen'ed. # # # SYNOPSIS # mangen [-d] [-n] [-l] chapter file # # DESCRIPTION # generates: . (manual entry for module) # and if "-l": . (manual entries for each routine) # # where is the "root" of the "tail" of the specified file # (i.e. if file="/usr/dave/gronk.c", then name="gronk"); # and is the single digit chapter number # (i.e. just the specified chapter number if one was given, # or the number from the table below if a chapter name was given). # # can be any digit or any of the following chapter abbreviations: # # # abbr name what # = ==== =========== ==================================== # 0 con* # over* conventions - conventions and overview material # 1 lib* libraries - subroutine library summaries # 2 routines - individual library routines # 3 task* # tsk* # dr* drivers - tasks and drivers # 4 tool* tools - Unix development/maintenence tools # # NOTE: Specifying the chapter as "lib" automatically selects the -l option. # # "-l" flag causes a special library module style manual entry to be created. # The manual entry for a library has a specially constructed synopsis section # that contains the titles and calling sequence of each routine in the library. # Also a seperate manual entry is generated for each of the routines in the # library. These routine manual entries will be put in a file named libxxx.2. # # "-d" flag causes the intermediate nroff source files to NOT be deleted. # These are called "mg.out" and "mgr.out" for the module manual entry # and individual routine entries (only if -l option specified), respectively. # This option is useful for debugging manual entries that don't look the # way you expected. # # "-n" flag causes nroff sources not to be deleted, and not to be nroffed # either. In this case, "mg.out" (and "mgr.out") will be the ONLY output # from mangen. # # EXAMPLE: # % mangen lib /usr/vw/lib/lstlib.c # will create "lstlib.1" and "liblst.2" in the current directory. #C< trap "rm -f mg.out mgr.out /tmp/mangen$$; exit" 1 2 3 15 rm -f mg.out mgr.out # start with a clean slate # set home to directory that contains this script home=`expr $0 : '\(.*/\)[^/]' '|' ./` dontdelete=0 dontnroff=0 lib=0 chapter=0 while (test $# -gt 1) do case "$1" in -d) dontdelete=1 ;; -l) lib=1 ;; -n) dontdelete=1; dontnroff=1 ;; [0-9]) chapter=$1 ;; con* | over*) chapter=0 ;; lib*) chapter=1; lib=1 ;; task* | tsk* | dr*) chapter=3 ;; tool*) chapter=4 ;; *) echo "flag not recognized:" $1; exit 1 ;; esac shift done # remove path name=`basename $1` # remove trailing component, eg. ".xx" section=`expr $name : '\(.*\)\..*' '|' $name` # create awk program found at end of this script, and # make substitutions in the awk program source awk '/^#START_AWK$/,/^#STOP_AWK$/' <$0 | \ sed -e "s^\%filename^$name^g" \ -e "s/\%chapter/$chapter/g" \ -e "s/\%lib/$lib/" \ >/tmp/mangen$$ # generate the nroff source of the manual entries awk -f /tmp/mangen$$ <$1 rm /tmp/mangen$$ # nroff them unless -n option if (test $dontnroff -eq 0) then #tbl mg.out | nroff -man -Tman >$section.$chapter #tbl mg.out | nroff -man -Tlp >$section.$chapter #tbl mg.out | nroff -mangen -Tlp >$section.$chapter tbl mg.out | nroff >$section.$chapter else mv mg.out $section.$chapter fi if (test $lib -eq 1) then if (test $dontnroff -eq 0) then #tbl mgr.out | nroff -man -Tman >$section.2 #tbl mgr.out | nroff -mangen -Tlp >$section.2 tbl mgr.out | nroff >$section.2 else mv mgr.out $section.2 fi fi # delete the nroff source, unless -d or -n option if (test $dontdelete -eq 0) then rm -f mg.out mgr.out fi exit 0 #START_AWK # mangen.awk - awk program to generate manual entries # the variable "s" holds the current state of the scan: # # title - get title line (initial state # mh0 - skip to start of modification history # mh - skip to end of modification history # desc0 - skip to start of module description # desc - process module description # # the following additional states are used if the "lib" flag is specified: # # rtn - skip to start of next routine # rtitle - skip to, and process, routine title line # rdesc - skip to, and process, routine description # rsy0 - skip to start of routine synopsis # rsy - process routine synopsis BEGIN { blanks = " " # the following values preceded by a "%" are substituted # for by a "sed" program filename = "%filename" # source filename chapter = %chapter # chapter number lib = %lib # 1 = make routine entries, 0 = don't # initialize dbg = 0 # 1 = output debug stuff s = "title" # initial state # get module name w/o the extension and the output file names dot = index (filename, ".") if (dot == 0) modname = filename else modname = substr (filename, 1, dot - 1) outfile = "mg.out" rtnfile = "mgr.out" } dbg == 1 { print s "\n" $0 >outfile } # ignore lint directive lines /LINTLIBRARY/ {next} /ARGSUSED/ {next} /VARARGS/ {next} # get ss = line without leading '/* ' or '* ' or '# ' and trailing '*/' # subhead = subheading (all caps at beginning of line w/ optional ':') # subheadl = remainder of subheading line following ':' { # detab line nf = split ($0, words, "\t") if (nf == 0) l = "" else { l = words[1] for (i = 2; i <= nf; i++) l = l substr(" ", 1, 8-(length(l) % 8)) words[i] } # strip off leading and trailing comment indicators if ((l ~ /^C>/) || (l ~ /^\/\*/)) { if ((l ~ /^C> /) || (l ~ /^\/\* /)) start = 4 else start = 3 } else if ((l ~ /^C/) || (l ~ /^\*/)) { if ((l ~ /^C /) || (l ~ /^\* /)) start = 3 else start = 2 } else if (l ~ /^\#/) { if (l ~ /^\# /) start = 3 else start = 2 } else start = 1 end = length (l) if ((l ~ /C<$/) || (l ~ /\*\/$/)) end = end - 2 ss = substr (l, start, end - start + 1) # check for sub heading line if ((ss !~ /^[A-Z][^a-z]*:/) && \ (ss !~ /^[A-Z][^a-z]*$/)) subhead = "" else { colon = index (ss, ":") if (colon == 0) { subhead = ss subheadl = "" } else { subhead = substr (ss, 1, colon - 1) subheadl = substr (ss, colon + 2) if (subheadl ~ /^ *$/) subheadl = "" } } } # get module name and title: 1st line in file s == "title" { # This gets rid of .yacc first lines ("%{"), and the first # line or two of a script ("#!/bin/sh", etc.). if (NF == 1 || index($1, "#!")) next # check that title matches module name dot = index ($2, ".") if (dot == 0) titlename = $2 else titlename = substr (ss, 1, dot - 1) if (titlename != modname) { print "ERROR: on line " NR \ ": module name inconsistent w/ file name." exit } title = ss s = "mh0" next } # skip modification history: skip, looking for 'modification history' then blank s == "mh0" { if (l ~ /modification history/) s = "mh" next } s == "mh" { if (ss ~ /^ *$/) { s = "desc0" xdesc = 0 } next } # get module description: ignore leading blank lines; turn capital lines # into subheadings; accumulate rest looking for '*/' s == "desc0" { if (l !~ /^ *$/) { ignore = 0 s = "desc" } } s == "desc" { # suppress manual entry if NOMANUAL specified if (l ~ /NO[ _-]?MANUAL/) { ignorelib = 1 } # check for end of description section if ((l ~ /^\#*C maxlen) maxlen = len # note minimum gap between code and comment if ((ic != 0) && (is != 0)) { gap = ic - is - 1 + i - 5 if (gap < mingap) mingap = gap } } else { # end of synopsis reached; output routine name, then # manual for this routine, then form-feed s = "rtn" print rnm >rtnfile stitle [++xrtn] = rtitle ssy [xrtn] = rsy[1] # print name and title print ".TH " rnm " 2" \ " \"\" \"ALICE Reference Manual\"" >rtnfile print ".ad b" >rtnfile print ".SH NAME\n" rtitle >rtnfile # print routine synopsis # figure out if we should squeeze decls and comments squeeze = 0 if (maxlen > 60) { squeeze = maxlen - 60 if (squeeze > (mingap - 1)) squeeze = mingap - 1 } print ".SH SYNOPSIS" >rtnfile print ".CS" >rtnfile print ".nf" >rtnfile print rsy[1] >rtnfile for (i = 2; i <= xrsy; i++) { if (rsyc[i] == "") n = 0 else n = rsyci[i] - length(rsy[i]) - 5 - squeeze print " " rsy[i] substr(blanks,0,n) rsyc[i] >rtnfile } print ".fi" >rtnfile print ".CE" >rtnfile # print description if ((xrdesc != 0) && (rdesc[1] !~ /^\.SH/)) print ".SH DESCRIPTION" >rtnfile seealso = 0 for (i = 1; i <= xrdesc; i++) { print rdesc[i] >rtnfile if (rdesc[i] ~ /^.SH SEE ALSO/) { print modname "(" chapter ")," >rtnfile seealso = 1 } } # print see also if not already done above if (seealso == 0) { print ".SH SEE ALSO" >rtnfile print modname "(" chapter ")" >rtnfile } # form-feed print " " >rtnfile } next } # end of file: output module manual END { if (!ignorelib) { # print name and title print ".TH " modname " " chapter \ " \"\" \"ALICE Reference Manual\"" >outfile print ".ad b" >outfile print ".SH NAME\n" title >outfile # print specially constructed synopsis, if library # If no routines, say so. if (lib == 1) { print ".SH SYNOPSIS" >outfile print ".nf" >outfile for (i = 1; i <= xrtn; i++) print stitle[i] >outfile print "" >outfile if (xrtn == 0) print "NO CALLABLE ROUTINES" >outfile print ".CS" >outfile for (i = 1; i <= xrtn; i++) { if (substr(ssy[i], length (ssy[i])) == ")") print ssy[i] >outfile else print ssy[i], "..." >outfile } print ".CE" >outfile print ".fi" >outfile } # print module description if ((xdesc != 0) && (desc[1] !~ /^\.SH/)) print ".SH DESCRIPTION" >outfile for (i = 1; i <= xdesc; i++) print desc[i] >outfile } } #STOP_AWK