diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2013-05-03 21:08:42 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2013-05-03 21:08:42 +0400 |
commit | 1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch) | |
tree | 4495d23e7b54ab5700e3839081e797c1eafe0db9 /setup/txt2man | |
download | oss4-1058def8e7827e56ce4a70afb4aeacb5dc44148f.tar.gz |
Imported Upstream version 4.2-build2006upstream/4.2-build2006upstream
Diffstat (limited to 'setup/txt2man')
-rwxr-xr-x | setup/txt2man | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/setup/txt2man b/setup/txt2man new file mode 100755 index 0000000..d6a0686 --- /dev/null +++ b/setup/txt2man @@ -0,0 +1,383 @@ +#!/bin/sh +test "$HOME" = ~ || exec ksh $0 "$@" # try ksh if sh too old (not yet POSIX) + +# Copyright (C) 2001, 2002, 2003 Marc Vertes + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# release 1.5.5 + +usage() +{ +cat << EOT +NAME + txt2man - convert flat ASCII text to man page format +SYNOPSIS + txt2man [-hpTX] [-t mytitle] [-P pname] [-r rel] [-s sect] + [-v vol] [-I txt] [-B txt] [-d date] [ifile] +DESCRIPTION + txt2man converts the input text into nroff/troff standard man(7) + macros used to format Unix manual pages. Nice pages can be generated + specially for commands (section 1 or 8) or for C functions reference + (sections 2, 3), with the ability to recognize and format command and + function names, flags, types and arguments. + + txt2man is also able to recognize and format sections, paragraphs, + lists (standard, numbered, description, nested), cross references and + literal display blocks. + + If input file ifile is omitted, standard input is used. Result is + displayed on standard output. + + Here is how text patterns are recognized and processed: + Sections These headers are defined by a line in upper case, starting + column 1. If there is one or more leading spaces, a + sub-section will be generated instead. + Paragraphs They must be separated by a blank line, and left aligned. + Tag list The item definition is separated from the item description + by at least 2 blank spaces, even before a new line, if + definition is too long. Definition will be emphasized + by default. + Bullet list + Bullet list items are defined by the first word being "-" + or "*" or "o". + Enumerated list + The first word must be a number followed by a dot. + Literal display blocks + This paragraph type is used to display unmodified text, + for example source code. It must be separated by a blank + line, and be indented. It is primarily used to format + unmodified source code. It will be printed using fixed font + whenever possible (troff). + Cross references + A cross reference (another man page) is defined by a word + followed by a number in parenthesis. + + Special sections: + NAME The function or command name and short description are set in + this section. + SYNOPSIS This section receives a special treatment to identify command + name, flags and arguments, and propagate corresponding + attributes later in the text. If a C like function is recognized + (word immediately followed by an open parenthesis), txt2man will + print function name in bold font, types in normal font, and + variables in italic font. The whole section will be printed using + a fixed font family (courier) whenever possible (troff). + + It is a good practice to embed documentation into source code, by using + comments or constant text variables. txt2man allows to do that, keeping + the document source readable, usable even without further formatting + (i.e. for online help) and easy to write. The result is high quality + and standard complying document. +OPTIONS + -h The option -h displays help. + -d date Set date in header. Defaults to current date. + -P pname Set pname as project name in header. Default to uname -s. + -p Probe title, section name and volume. + -t mytitle Set mytitle as title of generated man page. + -r rel Set rel as project name and release. + -s sect Set sect as section in heading, ususally a value from 1 to 8. + -v vol Set vol as volume name, i.e. "Unix user 's manual". + -I txt Italicize txt in output. Can be specified more than once. + -B txt Emphasize (bold) txt in output. Can be specified more than once. + -T Text result previewing using PAGER, usually more(1). + -X X11 result previewing using gxditview(1). +ENVIRONMENT + PAGER name of paging command, usually more(1), or less(1). If not set + falls back to more(1). +EXAMPLE + Try this command to format this text itself: + + $ txt2man -h 2>&1 | txt2man -T +HINTS + To obtain an overall good formating of output document, keep paragraphs + indented correctly. If you have unwanted bold sections, search for + multiple spaces between words, which are used to identify a tag list + (term followed by a description). Choose also carefully the name of + command line or function parameters, as they will be emphasized each + time they are encountered in the document. +SEE ALSO + man(1), mandoc(7), rman(1), groff(1), more(1), gxditview(1), troff(1). +BUGS + - Automatic probe (-p option) works only if input is a regular file (i.e. + not stdin). +AUTHOR + Marc Vertes <mvertes@free.fr> +EOT +} + +sys=$(uname -s) +rel= +volume= +section= +title=untitled +doprobe= +itxt= +btxt= +post=cat +while getopts :d:hpTXr:s:t:v:P:I:B: opt +do + case $opt in + d) date=$OPTARG;; + r) rel=$OPTARG;; + t) title=$OPTARG;; + s) section=$OPTARG;; + v) volume=$OPTARG;; + P) sys=$OPTARG;; + p) doprobe=1;; + I) itxt="$OPTARG§$itxt";; + B) btxt=$OPTARG;; + T) post="groff -mandoc -Tlatin1 | ${PAGER:-more}";; + X) post="groff -mandoc -X";; + *) usage; exit;; + esac +done +shift $(($OPTIND - 1)) +date=${date:-$(date +'%d %B %Y')} + +if test "$doprobe" +then + title=${1##*/}; title=${title%.txt} + if grep -q '#include ' $1 + then + section=${section:-3} + volume=${volume:-"$sys Programmer's Manual"} + else + section=${section:-1} + volume=${volume:-"$sys Reference Manual"} + fi + # get release from path + rel=$(pwd | sed 's:/.*[^0-9]/::g; s:/.*::g') +fi + +head=".\\\" Text automatically generated by txt2man +.TH $title $section \"$date\" \"$rel\" \"$volume\"" + +# All tabs converted to spaces +expand $* | +# gawk is needed because use of non standard regexp +gawk --re-interval -v head="$head" -v itxt="$itxt" -v btxt="$btxt" ' +BEGIN { + print head + avar[1] = btxt; avar[2] = itxt + for (k in avar) { + mark = (k == 1) ? "\\fB" : "\\fI" + split(avar[k], tt, "§") + for (i in tt) + if (tt[i] != "") + subwords["\\<" tt[i] "\\>"] = mark tt[i] "\\fP" + for (i in tt) + delete tt[i] + } + for (k in avar) + delete avar[k] +} +{ + # to avoid some side effects in regexp + sub(/\.\.\./, "\\.\\.\\.") + # remove spaces in empty lines + sub(/^ +$/,"") +} +/^[[:upper:][:space:]]+$/ { + # Section header + if ((in_bd + 0) == 1) { + in_bd = 0 + print ".fam T\n.fi" + } + if (section == "SYNOPSIS") { + print ".fam T\n.fi" + type["SYNOPSIS"] = "" + } + if ($0 ~/^[^[:space:]]/) + print ".SH " $0 + else + print ".SS" $0 + sub(/^ +/, "") + section = $0 + if (section == "SYNOPSIS") { + print ".nf\n.fam C" + in_bd = 1 + } + ls = 0 # line start index + pls = 0 # previous line start index + pnzls = 0 # previous non zero line start index + ni = 0 # indent level + ind[0] = 0 # indent offset table + prevblankline = 0 + next +} +{ + # Compute line start index, handle start of example display block + pls = ls + if (ls != 0) + pnzls = ls + match($0, /[^ ]/) + ls = RSTART + if (pls == 0 && pnzls > 0 && ls > pnzls && $1 !~ /^[0-9\-\*\o]\.*$/) { + # example display block + if (prevblankline == 1) { + print ".PP" + prevblankline = 0 + } + print ".nf\n.fam C" + in_bd = 1 + eoff = ls + } + if (ls > 0 && ind[0] == 0) + ind[0] = ls +} +(in_bd + 0) == 1 { + # In block display + if (section == "SYNOPSIS") + ; + else if (ls != 0 && ls < eoff) { + # End of litteral display block + in_bd = 0 + print ".fam T\n.fi" + } else { print; next } +} +section == "NAME" { + $1 = "\\fB" $1 + sub(/ \- /, " \\fP- ") +} +section == "SYNOPSIS" { + # Identify arguments of fcts and cmds + if (type["SYNOPSIS"] == "") { + if ($0 ~ /\(/) + type["SYNOPSIS"] = "fct" + else if ($1 == "struct" || $2 == "struct") + type["SYNOPSIS"] = "struct" + else if ($1 && $1 !~ /^#|typedef|struct|union|enum/) + type["SYNOPSIS"] = "cmd" + } + if (type["SYNOPSIS"] == "cmd") { + # Line is a command line + if ($1 !~ /^\[/) { + b = $1 + sub(/^\*/, "", b) + subwords["\\<" b "\\>"] = "\\fB" b "\\fP" + } + for (i = 2; i <= NF; i++) { + a = $i + gsub(/[\[\]\|]/, "", a) + if (a ~ /^[^\-]/) + subwords["\\<" a "\\>"] = "\\fI" a "\\fP" + } + } else if (type["SYNOPSIS"] == "fct") { + # Line is a C function definition + if ($1 == "typedef") { + if ($0 !~ /\(\*/) + subwords["\\<" $2 "\\>"] = "\\fI" $2 "\\fP" + } else if ($1 == "#define") + subwords["\\<" $2 "\\>"] = "\\fI" $2 "\\fP" + for (i = 1; i <= NF; i++) { + if ($i ~ /[\,\)]\;*$/) { + a = $i + sub(/.*\(/, "", a) + gsub(/\W/, "", a) + subwords["\\<" a "\\>"] = "\\fI" a "\\fP" + } + } + } +} +{ + # protect dots inside words + while ($0 ~ /\w\.\w/) + sub(/\./, "_dOt_") + # identify func calls and cross refs + for (i = 1; i <= NF; i++) { + b = $i + sub(/^\*/, "", b) + if ((a = index(b, ")(")) > 3) { + w = substr(b, 3, a - 3) + subwords["\\<" w "\\>"] = "\\fI" w "\\fP" + } + if ((a = index(b, "(")) > 1) { + w = substr(b, 1, a - 1) + subwords["\\<" w "\\("] = "\\fB" w "\\fP(" + } + } + # word attributes + for (i in subwords) + gsub(i, subwords[i]) + # shell options + gsub(/\B\-+\w+(\-\w+)*/, "\\fB&\\fP") + # unprotect dots inside words + gsub(/_dOt_/, ".") + + if (section == "SYNOPSIS") { + sub(/^ /, "") + print + next + } + if (match($0, /[^ ] +/) > 0) { + # tag list item + adjust_indent() + tag = substr($0, 1, RSTART) + sub(/^ */, "", tag) + if (RSTART+RLENGTH < length()) + $0 = substr($0, RSTART + RLENGTH) + else + $0 = "" + print ".TP\n.B" + print tag + prevblankline = 0 + if (NF == 0) + next + } else if ($1 == "-"||$1 == "o"||$1 == "*") { + # bullet list item + adjust_indent() + print ".IP \\(bu 3" + prevblankline = 0 + $1 = "" + } else if ($1 ~ /^[0-9]+[\).]$/) { + # enum list item + adjust_indent() + print ".IP " $1 " 4" + prevblankline = 0 + $1 = "" + } else if (pls == 0) { + # new paragraph + adjust_indent() + } else if (NF == 0) { + # blank line + prevblankline = 1 + next + } else + prevblankline = 0 + # flush vertical space + if (prevblankline == 1) { + print ".PP" + prevblankline = 0 + } + if (section != "SYNOPSIS" || $0 ~ /^ {1,4}/) + sub(/ */,"") + print +} + +function adjust_indent() +{ + if (ls > ind[ni]) { + ind[++ni] = ls + print ".RS" + } else if (ls < ind[ni]) { + while (ls < ind[ni]) { + ni-- + print ".RE" + } + } +} +' | eval $post |