c2rst.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import sys
  2. import os
  3. import binascii
  4. import re
  5. # Converts a header file to restructured text documentation
  6. #
  7. # All text in /** */ comments becomes restructured text. Everything else is
  8. # included as a code-block with C syntax highlighting.
  9. #
  10. # The beginning and end of the header are removed.
  11. # - Find the first /** */ comment -> start of the documentation
  12. # - Find the last line beginning with "#ifdef" -> end of the documentation
  13. remove_keyword = [" UA_EXPORT", " UA_FUNC_ATTR_WARN_UNUSED_RESULT",
  14. " UA_FUNC_ATTR_MALLOC", " UA_RESTRICT "]
  15. def clean_comment(line):
  16. m = re.search("^( \* |/\*\* )(.*?)( \*/)?$", line)
  17. if not m:
  18. return "\n"
  19. return m.group(2) + "\n"
  20. def clean_line(line):
  21. for keyword in remove_keyword:
  22. line = line.replace(keyword, "")
  23. return line
  24. def comment_start(line):
  25. m = re.search("^/\*\*[ \n]", line)
  26. if not m:
  27. return False
  28. return True
  29. def comment_end(line):
  30. m = re.search(" \*/$", line)
  31. if not m:
  32. return False
  33. return True
  34. def first_line(c):
  35. "Searches for the first comment"
  36. for i in range(len(c)):
  37. if comment_start(c[i]):
  38. return i
  39. return -1
  40. def last_line(c):
  41. "Searches for the latest ifdef (closing the include guard)"
  42. last = 1
  43. for i in range(len(c)-1,1,-1):
  44. m = re.search("^#ifdef", c[i])
  45. if m:
  46. last = i
  47. break
  48. # skip empty lines at the end
  49. for i in range(last-1,1,-1):
  50. if len(c[i].strip()) > 0:
  51. return i
  52. return 1
  53. if len(sys.argv) < 2:
  54. print("Usage: python c2rst.py input.c/h output.rst")
  55. exit(0)
  56. with open(sys.argv[1]) as f:
  57. c = f.readlines()
  58. with open(sys.argv[2], 'w') as rst:
  59. in_doc = False
  60. last = last_line(c)
  61. for i in range(first_line(c), last+1):
  62. line = c[i]
  63. doc_start = False
  64. doc_end = False
  65. if in_doc:
  66. doc_end = comment_end(line)
  67. line = clean_comment(line)
  68. else:
  69. doc_start = comment_start(line)
  70. if doc_start:
  71. doc_end = comment_end(line)
  72. line = clean_comment(line)
  73. if doc_start:
  74. in_doc = True
  75. if not ((doc_start or doc_end) and line == "\n"):
  76. if not in_doc:
  77. line = " " + line
  78. rst.write(clean_line(line))
  79. if doc_end and i < last:
  80. rst.write("\n.. code-block:: c\n\n")
  81. in_doc = False