summaryrefslogtreecommitdiff
path: root/man/make_man_page.py
diff options
context:
space:
mode:
Diffstat (limited to 'man/make_man_page.py')
-rw-r--r--man/make_man_page.py68
1 files changed, 44 insertions, 24 deletions
diff --git a/man/make_man_page.py b/man/make_man_page.py
index 5ed5b0c..3183397 100644
--- a/man/make_man_page.py
+++ b/man/make_man_page.py
@@ -2,71 +2,91 @@
# Creates a man page from a C file.
-# Comments beginning with `/**` are treated as Markdown.
+# Comments beginning with `/**` are treated as Groff man.
-# Non-blank lines immediately following a Markdown comment are treated
-# as function signatures or examples and included verbatim. The
-# immediately preceding markdown chunk is printed after the example
+# Non-blank lines immediately following a man page comment are treated
+# as function signatures or examples and parsed into .Ft, .Fo, .Fa, .Fc. The
+# immediately preceding man documentation chunk is printed after the example
# as a comment on it.
# That's about it!
-import sys
-import re
-
-if len(sys.argv) > 1:
- sourcefile = sys.argv[1]
-else:
- print("Usage: make_man_page.py sourcefile")
- exit(1)
+import sys, re, os
+from datetime import date
comment_start_re = re.compile('^\/\*\* ?')
comment_delim_re = re.compile('^[/ ]\** ?')
comment_end_re = re.compile('^ \**\/')
+function_re = re.compile('^ *(?:CMARK_EXPORT\s+)?(?P<type>(?:const\s+)?\w+(?:\s*[*])?)\s*(?P<name>\w+)\s*\((?P<args>[^)]*)\)')
blank_re = re.compile('^\s*$')
macro_re = re.compile('CMARK_EXPORT *')
+typedef_start_re = re.compile('typedef.*{$')
+typedef_end_re = re.compile('}')
+typedef = False
mdlines = []
chunk = []
sig = []
+if len(sys.argv) > 1:
+ sourcefile = sys.argv[1]
+else:
+ print("Usage: make_man_page.py sourcefile")
+ exit(1)
+
with open(sourcefile, 'r') as cmarkh:
state = 'default'
for line in cmarkh:
# state transition
oldstate = state
if comment_start_re.match(line):
- state = 'markdown'
- elif comment_end_re.match(line) and state == 'markdown':
+ state = 'man'
+ elif comment_end_re.match(line) and state == 'man':
continue
- elif comment_delim_re.match(line) and state == 'markdown':
- state = 'markdown'
- elif blank_re.match(line):
+ elif comment_delim_re.match(line) and state == 'man':
+ state = 'man'
+ elif not typedef and blank_re.match(line):
state = 'default'
- elif state == 'markdown':
+ elif typedef and typedef_end_re.match(line):
+ typedef = False
+ elif state == 'man':
state = 'signature'
+ typedef = typedef_start_re.match(line)
# handle line
- if state == 'markdown':
+ if state == 'man':
chunk.append(re.sub(comment_delim_re, '', line))
elif state == 'signature':
ln = re.sub(macro_re, '', line)
- if not re.match(blank_re, ln):
- sig.append(' ' + ln)
+ if typedef or not re.match(blank_re, ln):
+ sig.append(ln)
elif oldstate == 'signature' and state != 'signature':
if len(mdlines) > 0 and mdlines[-1] != '\n':
mdlines.append('\n')
- mdlines += sig # add sig, then prepended markdown comment
+ rawsig = ''.join(sig)
+ m = function_re.match(rawsig)
+ if m:
+ mdlines.append('.Ft ' + m.group('type') + '\n')
+ mdlines.append('.Fo ' + m.group('name') + '\n')
+ for argument in re.split('/s*,/s*', m.group('args')):
+ mdlines.append('.Fa ' + argument + '\n')
+ mdlines.append('.Fc\n')
+ else:
+ mdlines.append('.Bd -literal\n')
+ mdlines += sig
+ mdlines.append('.Ed\n')
if len(mdlines) > 0 and mdlines[-1] != '\n':
mdlines.append('\n')
mdlines += chunk
chunk = []
sig = []
- elif oldstate == 'markdown' and state != 'signature':
+ elif oldstate == 'man' and state != 'signature':
if len(mdlines) > 0 and mdlines[-1] != '\n':
mdlines.append('\n')
- mdlines += chunk # add markdown chunk
+ mdlines += chunk # add man chunk
chunk = []
mdlines.append('\n')
+sys.stdout.write('.Dd ' + date.today().isoformat() + '\n')
+sys.stdout.write('.Dt ' + os.path.basename(sourcefile) + '\n')
sys.stdout.write(''.join(mdlines))