PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/doc/mdoc2wiki.awk

https://code.google.com/
AWK | 448 lines | 392 code | 17 blank | 39 comment | 0 complexity | 7d48c44e8695fa3bc61e79229b471c65 MD5 | raw file
Possible License(s): LGPL-2.0
  1. #!/usr/bin/awk
  2. #
  3. # Copyright (c) 2003 Peter Stuge <stuge-mdoc2man@cdy.org>
  4. #
  5. # Permission to use, copy, modify, and distribute this software for any
  6. # purpose with or without fee is hereby granted, provided that the above
  7. # copyright notice and this permission notice appear in all copies.
  8. #
  9. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. # Dramatically overhauled by Tim Kientzle. This version almost
  17. # handles library-style pages with Fn, Ft, etc commands. Still
  18. # a lot of problems...
  19. BEGIN {
  20. displaylines = 0
  21. listdepth = 0
  22. trailer = ""
  23. out = ""
  24. sep = ""
  25. nextsep = " "
  26. spaces = " "
  27. }
  28. # Add a word with appropriate preceding whitespace
  29. # Maintain a short queue of the expected upcoming word separators.
  30. function add(str) {
  31. out=out sep str
  32. sep = nextsep
  33. nextsep = " "
  34. }
  35. # Add a word with no following whitespace
  36. # Use for opening punctuation such as '('
  37. function addopen(str) {
  38. add(str)
  39. sep = ""
  40. }
  41. # Add a word with no preceding whitespace
  42. # Use for closing punctuation such as ')' or '.'
  43. function addclose(str) {
  44. sep = ""
  45. add(str)
  46. }
  47. # Add a word with no space before or after
  48. # Use for separating punctuation such as '='
  49. function addpunct(str) {
  50. sep = ""
  51. add(str)
  52. sep = ""
  53. }
  54. # Emit the current line so far
  55. function endline() {
  56. addclose(trailer)
  57. trailer = ""
  58. if(length(out) > 0) {
  59. print out
  60. out=""
  61. }
  62. if(displaylines > 0) {
  63. displaylines = displaylines - 1
  64. if (displaylines == 0)
  65. dispend()
  66. }
  67. # First word on next line has no preceding whitespace
  68. sep = ""
  69. }
  70. function linecmd(cmd) {
  71. endline()
  72. add(cmd)
  73. endline()
  74. }
  75. function breakline() {
  76. linecmd("<br>")
  77. }
  78. # Start an indented display
  79. function dispstart() {
  80. linecmd("{{{")
  81. }
  82. # End an indented display
  83. function dispend() {
  84. linecmd("}}}")
  85. }
  86. # Collect rest of input line
  87. function wtail() {
  88. retval=""
  89. while(w<nwords) {
  90. if(length(retval))
  91. retval=retval " "
  92. retval=retval words[++w]
  93. }
  94. return retval
  95. }
  96. function splitwords(l, dest, n, o, w) {
  97. n = 1
  98. delete dest
  99. while (length(l) > 0) {
  100. sub("^[ \t]*", "", l)
  101. if (match(l, "^\"")) {
  102. l = substr(l, 2)
  103. o = index(l, "\"")
  104. if (o > 0) {
  105. w = substr(l, 1, o-1)
  106. l = substr(l, o+1)
  107. dest[n++] = w
  108. } else {
  109. dest[n++] = l
  110. l = ""
  111. }
  112. } else {
  113. o = match(l, "[ \t]")
  114. if (o > 0) {
  115. w = substr(l, 1, o-1)
  116. l = substr(l, o+1)
  117. dest[n++] = w
  118. } else {
  119. dest[n++] = l
  120. l = ""
  121. }
  122. }
  123. }
  124. return n-1
  125. }
  126. ! /^\./ {
  127. out = $0
  128. endline()
  129. next
  130. }
  131. /^\.\\"/ { next }
  132. {
  133. sub("^\\.","")
  134. nwords=splitwords($0, words)
  135. # TODO: Instead of iterating 'w' over the array, have a separate
  136. # function that returns 'next word' and use that. This will allow
  137. # proper handling of double-quoted arguments as well.
  138. for(w=1;w<=nwords;w++) {
  139. if(match(words[w],"^Li$")) { # Literal; rest of line is unformatted
  140. dispstart()
  141. displaylines = 1
  142. } else if(match(words[w],"^Dl$")) { # Display literal
  143. dispstart()
  144. displaylines = 1
  145. } else if(match(words[w],"^Bd$")) { # Begin display
  146. if(match(words[w+1],"-literal")) {
  147. dispstart()
  148. displaylines=10000
  149. w=nwords
  150. }
  151. } else if(match(words[w],"^Ed$")) { # End display
  152. displaylines = 0
  153. dispend()
  154. } else if(match(words[w],"^Ns$")) { # Suppress space before next word
  155. sep=""
  156. } else if(match(words[w],"^No$")) { # Normal text
  157. add(words[++w])
  158. } else if(match(words[w],"^Dq$")) { # Quote
  159. addopen("\"")
  160. add(words[++w])
  161. while(w<nwords&&!match(words[w+1],"^[\\.,]"))
  162. add(words[++w])
  163. addclose("\"")
  164. } else if(match(words[w],"^Do$")) {
  165. addopen("\"")
  166. } else if(match(words[w],"^Dc$")) {
  167. addclose("\"")
  168. } else if(match(words[w],"^Oo$")) {
  169. addopen("`[`")
  170. } else if(match(words[w],"^Oc$")) {
  171. addclose("`]`")
  172. } else if(match(words[w],"^Ao$")) {
  173. addopen("`<`")
  174. } else if(match(words[w],"^Ac$")) {
  175. addclose("`>`")
  176. } else if(match(words[w],"^Dd$")) {
  177. date=wtail()
  178. next
  179. } else if(match(words[w],"^Dt$")) {
  180. id=wtail()
  181. next
  182. } else if(match(words[w],"^Ox$")) {
  183. add("OpenBSD")
  184. } else if(match(words[w],"^Fx$")) {
  185. add("FreeBSD")
  186. } else if(match(words[w],"^Bx$")) {
  187. add("BSD")
  188. } else if(match(words[w],"^Nx$")) {
  189. add("NetBSD")
  190. } else if(match(words[w],"^St$")) {
  191. if (match(words[w+1], "^-p1003.1$")) {
  192. w++
  193. add("IEEE Std 1003.1 (``POSIX.1'')")
  194. } else if(match(words[w+1], "^-p1003.1-96$")) {
  195. w++
  196. add("ISO/IEC 9945-1:1996 (``POSIX.1'')")
  197. } else if(match(words[w+1], "^-p1003.1-88$")) {
  198. w++
  199. add("IEEE Std 1003.1-1988 (``POSIX.1'')")
  200. } else if(match(words[w+1], "^-p1003.1-2001$")) {
  201. w++
  202. add("IEEE Std 1003.1-2001 (``POSIX.1'')")
  203. } else if(match(words[w+1], "^-susv2$")) {
  204. w++
  205. add("Version 2 of the Single UNIX Specification (``SUSv2'')")
  206. }
  207. } else if(match(words[w],"^Ex$")) {
  208. if (match(words[w+1], "^-std$")) {
  209. w++
  210. add("The *" name "* utility exits 0 on success, and >0 if an error occurs.")
  211. }
  212. } else if(match(words[w],"^Os$")) {
  213. add("#summary " id " manual page")
  214. } else if(match(words[w],"^Sh$")) {
  215. section=wtail()
  216. linecmd("== " section " ==")
  217. } else if(match(words[w],"^Xr$")) {
  218. add("*" words[++w] "*(" words[++w] ")" words[++w])
  219. } else if(match(words[w],"^Nm$")) {
  220. if(match(section,"SYNOPSIS"))
  221. breakline()
  222. if(w >= nwords)
  223. n=name
  224. else if (match(words[w+1], "^[A-Z][a-z]$"))
  225. n=name
  226. else if (match(words[w+1], "^[.,;:]$"))
  227. n=name
  228. else {
  229. n=words[++w]
  230. if(!length(name))
  231. name=n
  232. }
  233. if(!length(n))
  234. n=name
  235. if (displaylines == 0)
  236. add("*" n "*")
  237. else
  238. add(n)
  239. } else if(match(words[w],"^Nd$")) {
  240. add("- " wtail())
  241. } else if(match(words[w],"^Fl$")) {
  242. addopen("-")
  243. } else if(match(words[w],"^Ar$")) {
  244. if(w==nwords)
  245. add("_file ..._")
  246. else {
  247. ++w
  248. gsub("<", "`<`", words[w])
  249. add("_" words[w] "_")
  250. }
  251. } else if(match(words[w],"^Cm$")) {
  252. ++w
  253. if (displaylines == 0) {
  254. gsub("^_", "`_`", words[w])
  255. gsub("\\*$", "`*`", words[w])
  256. add("*" words[w] "*")
  257. } else
  258. add(words[w])
  259. } else if(match(words[w],"^Op$")) {
  260. addopen("`[`")
  261. option=1
  262. trailer="`]`" trailer
  263. } else if(match(words[w],"^Pp$")) {
  264. ++w
  265. endline()
  266. print ""
  267. } else if(match(words[w],"^An$")) {
  268. if (match(words[w+1],"-nosplit"))
  269. ++w
  270. endline()
  271. } else if(match(words[w],"^Ss$")) {
  272. add("===")
  273. trailer="==="
  274. } else if(match(words[w],"^Ft$")) {
  275. if (match(section, "SYNOPSIS")) {
  276. breakline()
  277. }
  278. l = wtail()
  279. gsub("\\*", "`*`", l)
  280. add("*" l "*")
  281. if (match(section, "SYNOPSIS")) {
  282. breakline()
  283. }
  284. } else if(match(words[w],"^Fn$")) {
  285. ++w
  286. F = "*" words[w] "*("
  287. Fsep = ""
  288. while(w<nwords) {
  289. ++w
  290. if (match(words[w], "^[.,:]$")) {
  291. --w
  292. break
  293. }
  294. gsub("\\*", "`*`", words[w])
  295. F = F Fsep "_" words[w] "_"
  296. Fsep = ", "
  297. }
  298. add(F ")")
  299. if (match(section, "SYNOPSIS")) {
  300. addclose(";")
  301. }
  302. } else if(match(words[w],"^Fo$")) {
  303. w++
  304. F = "*" words[w] "*("
  305. Fsep = ""
  306. } else if(match(words[w],"^Fa$")) {
  307. w++
  308. gsub("\\*", "`*`", words[w])
  309. F = F Fsep "_" words[w] "_"
  310. Fsep = ", "
  311. } else if(match(words[w],"^Fc$")) {
  312. add(F ")")
  313. if (match(section, "SYNOPSIS")) {
  314. addclose(";")
  315. }
  316. } else if(match(words[w],"^Va$")) {
  317. w++
  318. add("_" words[w] "_")
  319. } else if(match(words[w],"^In$")) {
  320. w++
  321. add("*#include <" words[w] ">*")
  322. } else if(match(words[w],"^Pa$")) {
  323. w++
  324. # if(match(words[w],"^\\."))
  325. # add("\\&")
  326. if (displaylines == 0)
  327. add("_" words[w] "_")
  328. else
  329. add(words[w])
  330. } else if(match(words[w],"^Dv$")) {
  331. linecmd()
  332. } else if(match(words[w],"^Em|Ev$")) {
  333. add(".IR")
  334. } else if(match(words[w],"^Pq$")) {
  335. addopen("(")
  336. trailer=")" trailer
  337. } else if(match(words[w],"^Aq$")) {
  338. addopen(" <")
  339. trailer=">" trailer
  340. } else if(match(words[w],"^Brq$")) {
  341. addopen("{")
  342. trailer="}" trailer
  343. } else if(match(words[w],"^S[xy]$")) {
  344. add(".B " wtail())
  345. } else if(match(words[w],"^Tn$")) {
  346. n=wtail()
  347. gsub("\\*$", "`*`", n)
  348. add("*" n "*")
  349. } else if(match(words[w],"^Ic$")) {
  350. add("\\fB")
  351. trailer="\\fP" trailer
  352. } else if(match(words[w],"^Bl$")) {
  353. ++listdepth
  354. listnext[listdepth]=""
  355. if(match(words[w+1],"-bullet")) {
  356. optlist[listdepth]=1
  357. addopen("<ul>")
  358. listclose[listdepth]="</ul>"
  359. } else if(match(words[w+1],"-enum")) {
  360. optlist[listdepth]=2
  361. enum=0
  362. addopen("<ol>")
  363. listclose[listdepth]="</ol>"
  364. } else if(match(words[w+1],"-tag")) {
  365. optlist[listdepth]=3
  366. addopen("<dl>")
  367. listclose[listdepth]="</dl>"
  368. } else if(match(words[w+1],"-item")) {
  369. optlist[listdepth]=4
  370. addopen("<ul>")
  371. listclose[listdepth]="</ul>"
  372. }
  373. w=nwords
  374. } else if(match(words[w],"^El$")) {
  375. addclose(listnext[listdepth])
  376. addclose(listclose[listdepth])
  377. listclose[listdepth]=""
  378. listdepth--
  379. } else if(match(words[w],"^It$")) {
  380. addclose(listnext[listdepth])
  381. if(optlist[listdepth]==1) {
  382. addpunct("<li>")
  383. listnext[listdepth] = "</li>"
  384. } else if(optlist[listdepth]==2) {
  385. addpunct("<li>")
  386. listnext[listdepth] = "</li>"
  387. } else if(optlist[listdepth]==3) {
  388. addpunct("<dt>")
  389. listnext[listdepth] = "</dt>"
  390. if(match(words[w+1],"^Xo$")) {
  391. # Suppress trailer
  392. w++
  393. } else if(match(words[w+1],"^Pa$|^Ev$")) {
  394. addopen("*")
  395. w++
  396. add(words[++w] "*")
  397. } else {
  398. trailer = listnext[listdepth] "<dd>" trailer
  399. listnext[listdepth] = "</dd>"
  400. }
  401. } else if(optlist[listdepth]==4) {
  402. addpunct("<li>")
  403. listnext[listdepth] = "</li>"
  404. }
  405. } else if(match(words[w], "^Vt$")) {
  406. w++
  407. add("_" words[w] "_")
  408. } else if(match(words[w],"^Xo$")) {
  409. # TODO: Figure out how to handle this
  410. } else if(match(words[w],"^Xc$")) {
  411. # TODO: Figure out how to handle this
  412. if (optlist[listdepth] == 3) {
  413. addclose(listnext[listdepth])
  414. addopen("<dd>")
  415. listnext[listdepth] = "</dd>"
  416. }
  417. } else if(match(words[w],"^[=]$")) {
  418. addpunct(words[w])
  419. } else if(match(words[w],"^[[{(]$")) {
  420. addopen(words[w])
  421. } else if(match(words[w],"^[\\])}.,;:]$")) {
  422. addclose(words[w])
  423. } else {
  424. sub("\\\\&", "", words[w])
  425. add(words[w])
  426. }
  427. }
  428. if(match(out,"^\\.[^a-zA-Z]"))
  429. sub("^\\.","",out)
  430. endline()
  431. }