Home | History | Annotate | Line # | Download | only in util
      1 #! /usr/local/bin/gawk -f
      2 
      3 # prepinfo.awk --- fix node lines and menus
      4 #
      5 # Copyright, 1998, Arnold Robbins, arnold (at] 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 
     21 BEGIN	\
     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 
     90 Pass == 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 
     98 Pass == 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 
    169 Pass == 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 
    243 function err_prefix()
    244 {
    245 	printf("%s: %s: %d: ", ARGV[0], FILENAME, FNR) > "/dev/stderr"
    246 }
    247 
    248 function 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 
    257 Pass == 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 
    272 Pass == 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 
    317 Pass == 2	# print
    318 
    319 
    320 function 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