NetBSD/gnu/dist/texinfo/util/prepinfo.awk
2001-07-25 16:20:30 +00:00

357 lines
8.1 KiB
Awk

#! /usr/local/bin/gawk -f
# prepinfo.awk --- fix node lines and menus
#
# Copyright, 1998, Arnold Robbins, arnold@gnu.org
#
# PREPINFO 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 of the License, or
# (at your option) any later version.
#
# PREPINFO 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
BEGIN \
{
# manifest constants
TRUE = 1
FALSE = 0
# Levels at which different nodes can be
Level["@top"] = 0
Level["@appendix"] = 1
Level["@chapter"] = 1
Level["@majorheading"] = 1
Level["@unnumbered"] = 1
Level["@appendixsec"] = 2
Level["@heading"] = 2
Level["@section"] = 2
Level["@unnumberedsec"] = 2
Level["@unnumberedsubsec"] = 3
Level["@appendixsubsec"] = 3
Level["@subheading"] = 3
Level["@subsection"] = 3
Level["@appendixsubsubsec"] = 4
Level["@subsubheading"] = 4
Level["@subsubsection"] = 4
Level["@unnumberedsubsubsec"] = 4
# Length of menus
Menumargin = 78
# Length of menu item
Min_menitem_length = 29
# insure that we were called correctly
if (ARGC != 2) {
printf("usage: %s texinfo-file\n", ARGV[0]) > "/dev/stderr"
exit 1
}
# Arrange for two passes over input file
Pass = 1
ARGV[2] = "Pass=2"
ARGV[3] = ARGV[1]
ARGC = 4
Lastlevel = -1
# Initialize stacks
Up[-1] = "(dir)"
Prev[0] = "(dir)"
if (Debug == "args") {
for (i = 0; i < ARGC; i++)
printf("ARGV[%d] = %s\n", i, ARGV[i]) > "/dev/stderr"
}
}
$1 == "@node" \
{
Name = getnodename($0)
Nodeseen = TRUE
if ((l = length(Name)) > Maxlen)
Maxlen = l
if (Debug == "nodenames")
printf("Name = %s\n", Name) > "/dev/stderr"
if (Pass == 1)
next
}
Pass == 1 && /^@c(omment)?[ \t]+fakenode/ \
{
if (Debug == "fakenodes")
printf("fakenode at %d\n", FNR) > "/dev/stderr"
Fakenode = TRUE
next
}
Pass == 1 && ($1 in Level) \
{
# skip fake nodes --- titles without associated @node lines
if (Fakenode) {
if (Debug == "fakenodes")
printf("%s at %d is a fakenode\n", $1, FNR) > "/dev/stderr"
Fakenode = FALSE
next
}
if (Debug == "titles")
printf("Processing %s: Name = %s\n", $1, Name) > "/dev/stderr"
# save type
type = $1
if (! Nodeseen) {
err_prefix()
printf("%s line with no @node or fakenode line\n",
type) > "/dev/stderr"
Badheading[FNR] = 1
# ??? used ???
next
} else
Nodeseen = FALSE # reset it
# Squirrel away the info
levelnum = Level[type]
Node[Name ".level"] = levelnum
Node[Name ".name"] = Name
if (Debug == "titles") {
printf("Node[%s\".level\"] = %s\n", Name, Node[Name ".level"]) > "/dev/stderr"
printf("Node[%s\".name\"] = %s\n", Name, Node[Name ".name"]) > "/dev/stderr"
}
if (levelnum == Lastlevel) { # e.g., two sections in a row
Node[Name ".up"] = Up[levelnum - 1]
if (levelnum in Prev) {
Node[Prev[levelnum] ".next"] = Name
Node[Name ".prev"] = Prev[levelnum]
}
Prev[levelnum] = Name
Up[levelnum] = Name # ???
} else if (levelnum < Lastlevel) { # section, now chapter
Lastlevel = levelnum
Node[Name ".up"] = Up[levelnum - 1]
if (levelnum in Prev) {
Node[Name ".prev"] = Prev[levelnum]
Node[Prev[levelnum] ".next"] = Name
}
Prev[levelnum] = Name
Up[levelnum] = Name
} else { # chapter, now section, levelnum > Lastlevel
Node[Name ".up"] = Up[levelnum - 1]
Node[Up[Lastlevel] ".child"] = Name
Up[levelnum] = Name
Prev[levelnum] = Name
Lastlevel = levelnum
}
# For master menu
if (Level[$1] >= 2)
List[++Sequence] = Name
if (Debug == "titles") {
printf("Node[%s\".prev\"] = %s\n", Name, Node[Name ".prev"]) > "/dev/stderr"
printf("Node[%s\".up\"] = %s\n", Name, Node[Name ".up"]) > "/dev/stderr"
printf("Node[%s\".child\"] = %s\n", Name, Node[Name ".child"]) > "/dev/stderr"
}
}
Pass == 2 && Debug == "dumptitles" && FNR <= 1 \
{
for (i in Node)
printf("Node[%s] = %s\n", i, Node[i]) | "sort 1>&2"
close("sort 1>&2")
}
/^@menu/ && Pass == 1, /^@end[ \t]+menu/ && Pass == 1 \
{
if (/^@menu/ || /^@end[ \t]+menu/)
next
# if (Debug == "menu")
# printf("processing: %s\n", $0) > "/dev/stderr"
if (/^\*/) {
if (In_menitem) { # file away info from previousline
Node[node ".mendesc"] = desc
Node[node ".longdesc"] = longdesc
if (Debug == "mendesc") {
printf("Node[%s.mendesc] = %s\n",
node, Node[node ".mendesc"]) > "/dev/stderr"
printf("Node[%s.longdesc] = %s\n",
node, Node[node ".longdesc"]) > "/dev/stderr"
}
}
In_menitem = TRUE
# pull apart menu item
$1 = "" # nuke ``*''
$0 = $0 # reparse line
i1 = index($0, ":")
if (i1 <= 0) {
err_prefix()
printf("badly formed menu item") > "/dev/stderr"
next
}
if (substr($0, i1+1, 1) != ":") { # desc: node. long desc
i2 = index($0, ".")
if (i2 <= 0) {
err_prefix()
printf("badly formed menu item") > "/dev/stderr"
next
}
desc = substr($0, 1, i1 - 1)
sub(/^[ \t]+/, "", node)
sub(/[ \t]+$/, "", node)
longdesc = substr($0, i2 + 1)
} else { # nodname:: long desc
desc = ""
node = substr($0, 1, i1 - 1)
sub(/^[ \t]+/, "", node)
sub(/[ \t]+$/, "", node)
longdesc = substr($0, i1 + 2)
}
} else if (In_menitem) { # continuation line
longdesc = longdesc " " $0
} else
In_menitem = FALSE
Node[node ".mendesc"] = desc
Node[node ".longdesc"] = longdesc
if (Debug == "mendesc") {
printf("Node[%s.mendesc] = %s\n",
node, Node[node ".mendesc"]) > "/dev/stderr"
printf("Node[%s.longdesc] = %s\n",
node, Node[node ".longdesc"]) > "/dev/stderr"
}
if (Debug == "menu")
printf("Menu:: Name %s: desc %s: longdesc %s\n",
node, desc, longdesc) > "/dev/stderr"
}
function err_prefix()
{
printf("%s: %s: %d: ", ARGV[0], FILENAME, FNR) > "/dev/stderr"
}
function getnodename(str)
{
sub(/@node[ \t]+/, "", str)
sub(/,.*/, "", str)
if (Debug == "nodenames")
printf("getnodename: return %s\n", str) > "/dev/stderr"
return str
}
Pass == 2 && /^@node/ \
{
Name = getnodename($0)
# Top node is special. It's next is the first child
n = Node[Name ".next"]
if (Node[Name ".level"] == 0 && n == "")
n = Node[Name ".child"]
printf("@node %s, %s, %s, %s\n", Name, n,
Node[Name ".prev"] ? Node[Name ".prev"] : Node[Name ".up"],
Node[Name ".up"])
next
}
Pass == 2 && /^@menu/ \
{
# First, nuke current contents of menu
do {
if ((getline) <= 0) {
err_prefix()
printf("unexpected EOF inside menu\n") > "/dev/stderr"
exit 1
}
} while (! /^@end[ \t]+menu/)
# next, compute maximum length of a node name
max = 0
for (n = Node[Name ".child"]; (n ".next") in Node; n = Node[n ".next"]) {
if ((n ".desc") in Node)
s = Node[n ".desc"] ": " n "."
else
s = n "::"
l = length(s)
if (l > max)
max = l
}
if (max < Min_menitem_length)
max = Min_menitem_length
# now dump the menu
print "@menu"
for (n = Node[Name ".child"]; (n ".next") in Node; n = Node[n ".next"]) {
print_menuitem(n, max)
}
print_menuitem(n, max)
if (Name == "Top") { # Master Menu
if (Maxlen < Min_menitem_length)
Maxlen = Min_menitem_length
print ""
for (i = 1; i <= Sequence; i++)
print_menuitem(List[i], Maxlen)
print ""
}
print "@end menu"
next
}
Pass == 2 # print
function print_menuitem(n, max, nodesc, i, dwords, count, p)
{
nodesc = FALSE
if (! ((n ".longdesc") in Node)) {
err_prefix()
printf("warning: %s: no long description\n", n) > "/dev/stderr"
nodesc = TRUE
} else {
for (i in dwords)
delete dwords[i]
count = split(Node[n ".longdesc"], dwords, "[ \t\n]+")
}
if ((n ".desc") in Node)
s = Node[n ".desc"] ": " n "."
else
s = n "::"
printf("* %-*s", max, s)
if (Debug == "mendescitem")
printf("<* %-*s>\n", max, s) > "/dev/stderr"
p = max + 2
if (! nodesc) {
for (i = 1; i <= count; i++) {
l = length(dwords[i])
if (l == 0)
continue
if (p + l + 1 > Menumargin) {
printf("\n%*s", max + 2, " ")
p = max + 2
}
printf(" %s", dwords[i])
p += l + 1
}
}
print ""
}