PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/doc/mdoc2wiki.awk

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