1#! /usr/local/bin/gawk -f 2 3# prepinfo.awk --- fix node lines and menus 4# 5# Copyright, 1998, Arnold Robbins, arnold@gnu.org 6# 7# PREPINFO is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# PREPINFO is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; if not, write to the Free Software 19# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 20 21BEGIN \ 22{ 23 # manifest constants 24 TRUE = 1 25 FALSE = 0 26 27 # Levels at which different nodes can be 28 Level["@top"] = 0 29 Level["@appendix"] = 1 30 Level["@chapter"] = 1 31 Level["@majorheading"] = 1 32 Level["@unnumbered"] = 1 33 Level["@appendixsec"] = 2 34 Level["@heading"] = 2 35 Level["@section"] = 2 36 Level["@unnumberedsec"] = 2 37 Level["@unnumberedsubsec"] = 3 38 Level["@appendixsubsec"] = 3 39 Level["@subheading"] = 3 40 Level["@subsection"] = 3 41 Level["@appendixsubsubsec"] = 4 42 Level["@subsubheading"] = 4 43 Level["@subsubsection"] = 4 44 Level["@unnumberedsubsubsec"] = 4 45 46 # Length of menus 47 Menumargin = 78 48 49 # Length of menu item 50 Min_menitem_length = 29 51 52 # insure that we were called correctly 53 if (ARGC != 2) { 54 printf("usage: %s texinfo-file\n", ARGV[0]) > "/dev/stderr" 55 exit 1 56 } 57 58 # Arrange for two passes over input file 59 Pass = 1 60 ARGV[2] = "Pass=2" 61 ARGV[3] = ARGV[1] 62 ARGC = 4 63 Lastlevel = -1 64 65 # Initialize stacks 66 Up[-1] = "(dir)" 67 Prev[0] = "(dir)" 68 69 if (Debug == "args") { 70 for (i = 0; i < ARGC; i++) 71 printf("ARGV[%d] = %s\n", i, ARGV[i]) > "/dev/stderr" 72 } 73} 74 75$1 == "@node" \ 76{ 77 Name = getnodename($0) 78 Nodeseen = TRUE 79 80 if ((l = length(Name)) > Maxlen) 81 Maxlen = l 82 83 if (Debug == "nodenames") 84 printf("Name = %s\n", Name) > "/dev/stderr" 85 86 if (Pass == 1) 87 next 88} 89 90Pass == 1 && /^@c(omment)?[ \t]+fakenode/ \ 91{ 92 if (Debug == "fakenodes") 93 printf("fakenode at %d\n", FNR) > "/dev/stderr" 94 Fakenode = TRUE 95 next 96} 97 98Pass == 1 && ($1 in Level) \ 99{ 100 # skip fake nodes --- titles without associated @node lines 101 if (Fakenode) { 102 if (Debug == "fakenodes") 103 printf("%s at %d is a fakenode\n", $1, FNR) > "/dev/stderr" 104 Fakenode = FALSE 105 next 106 } 107 108 if (Debug == "titles") 109 printf("Processing %s: Name = %s\n", $1, Name) > "/dev/stderr" 110 111 # save type 112 type = $1 113 114 if (! Nodeseen) { 115 err_prefix() 116 printf("%s line with no @node or fakenode line\n", 117 type) > "/dev/stderr" 118 Badheading[FNR] = 1 119 # ??? used ??? 120 next 121 } else 122 Nodeseen = FALSE # reset it 123 124 # Squirrel away the info 125 levelnum = Level[type] 126 Node[Name ".level"] = levelnum 127 Node[Name ".name"] = Name 128 if (Debug == "titles") { 129 printf("Node[%s\".level\"] = %s\n", Name, Node[Name ".level"]) > "/dev/stderr" 130 printf("Node[%s\".name\"] = %s\n", Name, Node[Name ".name"]) > "/dev/stderr" 131 } 132 133 if (levelnum == Lastlevel) { # e.g., two sections in a row 134 Node[Name ".up"] = Up[levelnum - 1] 135 if (levelnum in Prev) { 136 Node[Prev[levelnum] ".next"] = Name 137 Node[Name ".prev"] = Prev[levelnum] 138 } 139 Prev[levelnum] = Name 140 Up[levelnum] = Name # ??? 141 } else if (levelnum < Lastlevel) { # section, now chapter 142 Lastlevel = levelnum 143 Node[Name ".up"] = Up[levelnum - 1] 144 if (levelnum in Prev) { 145 Node[Name ".prev"] = Prev[levelnum] 146 Node[Prev[levelnum] ".next"] = Name 147 } 148 Prev[levelnum] = Name 149 Up[levelnum] = Name 150 } else { # chapter, now section, levelnum > Lastlevel 151 Node[Name ".up"] = Up[levelnum - 1] 152 Node[Up[Lastlevel] ".child"] = Name 153 Up[levelnum] = Name 154 Prev[levelnum] = Name 155 Lastlevel = levelnum 156 } 157 158 # For master menu 159 if (Level[$1] >= 2) 160 List[++Sequence] = Name 161 162 if (Debug == "titles") { 163 printf("Node[%s\".prev\"] = %s\n", Name, Node[Name ".prev"]) > "/dev/stderr" 164 printf("Node[%s\".up\"] = %s\n", Name, Node[Name ".up"]) > "/dev/stderr" 165 printf("Node[%s\".child\"] = %s\n", Name, Node[Name ".child"]) > "/dev/stderr" 166 } 167} 168 169Pass == 2 && Debug == "dumptitles" && FNR <= 1 \ 170{ 171 for (i in Node) 172 printf("Node[%s] = %s\n", i, Node[i]) | "sort 1>&2" 173 close("sort 1>&2") 174} 175 176/^@menu/ && Pass == 1, /^@end[ \t]+menu/ && Pass == 1 \ 177{ 178 if (/^@menu/ || /^@end[ \t]+menu/) 179 next 180 181# if (Debug == "menu") 182# printf("processing: %s\n", $0) > "/dev/stderr" 183 184 if (/^\*/) { 185 if (In_menitem) { # file away info from previousline 186 Node[node ".mendesc"] = desc 187 Node[node ".longdesc"] = longdesc 188 if (Debug == "mendesc") { 189 printf("Node[%s.mendesc] = %s\n", 190 node, Node[node ".mendesc"]) > "/dev/stderr" 191 printf("Node[%s.longdesc] = %s\n", 192 node, Node[node ".longdesc"]) > "/dev/stderr" 193 } 194 } 195 In_menitem = TRUE 196 197 # pull apart menu item 198 $1 = "" # nuke ``*'' 199 $0 = $0 # reparse line 200 i1 = index($0, ":") 201 if (i1 <= 0) { 202 err_prefix() 203 printf("badly formed menu item") > "/dev/stderr" 204 next 205 } 206 if (substr($0, i1+1, 1) != ":") { # desc: node. long desc 207 i2 = index($0, ".") 208 if (i2 <= 0) { 209 err_prefix() 210 printf("badly formed menu item") > "/dev/stderr" 211 next 212 } 213 desc = substr($0, 1, i1 - 1) 214 sub(/^[ \t]+/, "", node) 215 sub(/[ \t]+$/, "", node) 216 longdesc = substr($0, i2 + 1) 217 } else { # nodname:: long desc 218 desc = "" 219 node = substr($0, 1, i1 - 1) 220 sub(/^[ \t]+/, "", node) 221 sub(/[ \t]+$/, "", node) 222 longdesc = substr($0, i1 + 2) 223 } 224 } else if (In_menitem) { # continuation line 225 longdesc = longdesc " " $0 226 } else 227 In_menitem = FALSE 228 229 Node[node ".mendesc"] = desc 230 Node[node ".longdesc"] = longdesc 231 if (Debug == "mendesc") { 232 printf("Node[%s.mendesc] = %s\n", 233 node, Node[node ".mendesc"]) > "/dev/stderr" 234 printf("Node[%s.longdesc] = %s\n", 235 node, Node[node ".longdesc"]) > "/dev/stderr" 236 } 237 238 if (Debug == "menu") 239 printf("Menu:: Name %s: desc %s: longdesc %s\n", 240 node, desc, longdesc) > "/dev/stderr" 241} 242 243function err_prefix() 244{ 245 printf("%s: %s: %d: ", ARGV[0], FILENAME, FNR) > "/dev/stderr" 246} 247 248function getnodename(str) 249{ 250 sub(/@node[ \t]+/, "", str) 251 sub(/,.*/, "", str) 252 if (Debug == "nodenames") 253 printf("getnodename: return %s\n", str) > "/dev/stderr" 254 return str 255} 256 257Pass == 2 && /^@node/ \ 258{ 259 Name = getnodename($0) 260 261 # Top node is special. It's next is the first child 262 n = Node[Name ".next"] 263 if (Node[Name ".level"] == 0 && n == "") 264 n = Node[Name ".child"] 265 266 printf("@node %s, %s, %s, %s\n", Name, n, 267 Node[Name ".prev"] ? Node[Name ".prev"] : Node[Name ".up"], 268 Node[Name ".up"]) 269 next 270} 271 272Pass == 2 && /^@menu/ \ 273{ 274 # First, nuke current contents of menu 275 do { 276 if ((getline) <= 0) { 277 err_prefix() 278 printf("unexpected EOF inside menu\n") > "/dev/stderr" 279 exit 1 280 } 281 } while (! /^@end[ \t]+menu/) 282 283 # next, compute maximum length of a node name 284 max = 0 285 for (n = Node[Name ".child"]; (n ".next") in Node; n = Node[n ".next"]) { 286 if ((n ".desc") in Node) 287 s = Node[n ".desc"] ": " n "." 288 else 289 s = n "::" 290 l = length(s) 291 if (l > max) 292 max = l 293 } 294 if (max < Min_menitem_length) 295 max = Min_menitem_length 296 297 # now dump the menu 298 print "@menu" 299 300 for (n = Node[Name ".child"]; (n ".next") in Node; n = Node[n ".next"]) { 301 print_menuitem(n, max) 302 } 303 print_menuitem(n, max) 304 305 if (Name == "Top") { # Master Menu 306 if (Maxlen < Min_menitem_length) 307 Maxlen = Min_menitem_length 308 print "" 309 for (i = 1; i <= Sequence; i++) 310 print_menuitem(List[i], Maxlen) 311 print "" 312 } 313 print "@end menu" 314 next 315} 316 317Pass == 2 # print 318 319 320function print_menuitem(n, max, nodesc, i, dwords, count, p) 321{ 322 nodesc = FALSE 323 if (! ((n ".longdesc") in Node)) { 324 err_prefix() 325 printf("warning: %s: no long description\n", n) > "/dev/stderr" 326 nodesc = TRUE 327 } else { 328 for (i in dwords) 329 delete dwords[i] 330 count = split(Node[n ".longdesc"], dwords, "[ \t\n]+") 331 } 332 if ((n ".desc") in Node) 333 s = Node[n ".desc"] ": " n "." 334 else 335 s = n "::" 336 printf("* %-*s", max, s) 337 338 if (Debug == "mendescitem") 339 printf("<* %-*s>\n", max, s) > "/dev/stderr" 340 341 p = max + 2 342 if (! nodesc) { 343 for (i = 1; i <= count; i++) { 344 l = length(dwords[i]) 345 if (l == 0) 346 continue 347 if (p + l + 1 > Menumargin) { 348 printf("\n%*s", max + 2, " ") 349 p = max + 2 350 } 351 printf(" %s", dwords[i]) 352 p += l + 1 353 } 354 } 355 print "" 356} 357