blob: b9971e54c1c82008648bc58402622f7fd569a09a [file] [log] [blame]
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys
import re
# Converts a header file to restructured text documentation
#
# All text in /** */ comments becomes restructured text. Everything else is
# included as a code-block with C syntax highlighting.
#
# The beginning and end of the header are removed.
# - Find the first /** */ comment -> start of the documentation
# - Find the last line beginning with "#ifdef" -> end of the documentation
remove_keyword = [" UA_EXPORT", " UA_FUNC_ATTR_WARN_UNUSED_RESULT",
" UA_FUNC_ATTR_MALLOC", " UA_RESTRICT "]
def clean_comment(line):
m = re.search("^\s*(\* |/\*\* )(.*?)( \*/)?$", line)
if not m:
return "\n"
return m.group(2) + "\n"
def clean_line(line):
for keyword in remove_keyword:
line = line.replace(keyword, "")
return line
def comment_start(line):
m = re.search("^\s*/\*\*[ \n]", line)
if not m:
return False
return True
def comment_end(line):
m = re.search(" \*/$", line)
if not m:
return False
return True
def first_line(c):
"Searches for the first comment"
for i in range(len(c)):
if comment_start(c[i]):
return i
return -1
def last_line(c):
"Searches for the latest ifdef (closing the include guard)"
reg = re.compile("^#ifdef")
for i in range(len(c)-1,1,-1):
if "_UA_END_DECLS" in c[i]:
reg = re.compile("^_UA_END_DECLS")
last = 1
for i in range(len(c)-1,1,-1):
m = reg.match(c[i])
if m:
last = i
break
# skip empty lines at the end
for i in range(last-1,1,-1):
if len(c[i].strip()) > 0:
return i
return len(c)-1
if len(sys.argv) < 2:
print("Usage: python c2rst.py input.c/h output.rst")
exit(0)
with open(sys.argv[1]) as f:
c = f.readlines()
with open(sys.argv[2], 'w') as rst:
in_doc = False
last = last_line(c)
for i in range(first_line(c), last+1):
line = c[i]
doc_start = False
doc_end = False
if in_doc:
doc_end = comment_end(line)
line = clean_comment(line)
else:
doc_start = comment_start(line)
if doc_start:
doc_end = comment_end(line)
line = clean_comment(line)
if doc_start:
in_doc = True
if not ((doc_start or doc_end) and line == "\n"):
if not in_doc:
line = " " + line
rst.write(clean_line(line))
if doc_end and i < last:
rst.write("\n.. code-block:: c\n\n")
in_doc = False