prepinfo.awk 8.1 KB

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