123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- #! /usr/local/bin/gawk -f
- # prepinfo.awk --- fix node lines and menus
- #
- # Copyright 1998 Arnold Robbins
- #
- # 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 3 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, see <http://www.gnu.org/licenses/>.
- 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 ""
- }
|