| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | |
| 37 | |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | |
| 59 | |
| 60 | |
| 61 | |
| 62 | |
| 63 | |
| 64 | |
| 65 | |
| 66 | |
| 67 | |
| 68 | |
| 69 | |
| 70 | |
| 71 | |
| 72 | |
| 73 | |
| 74 | |
| 75 | |
| 76 | |
| 77 | |
| 78 | |
| 79 | |
| 80 |
|
| 81 | |
| 82 | kernel_doc
|
| 83 | ==========
|
| 84 |
|
| 85 | Print formatted kernel documentation to stdout
|
| 86 |
|
| 87 | Read C language source or header FILEs, extract embedded
|
| 88 | documentation comments, and print formatted documentation
|
| 89 | to standard output.
|
| 90 |
|
| 91 | The documentation comments are identified by the "/**"
|
| 92 | opening comment mark.
|
| 93 |
|
| 94 | See Documentation/doc-guide/kernel-doc.rst for the
|
| 95 | documentation comment syntax.
|
| 96 |
|
| 97 |
|
| 98 | import argparse
|
| 99 | import logging
|
| 100 | import os
|
| 101 | import sys
|
| 102 |
|
| 103 | |
| 104 |
|
| 105 | LIB_DIR = "lib/kdoc"
|
| 106 | SRC_DIR = os.path.dirname(os.path.realpath(__file__))
|
| 107 |
|
| 108 | sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR))
|
| 109 |
|
| 110 | from kdoc_files import KernelFiles |
| 111 | from kdoc_output import RestFormat, ManFormat |
| 112 |
|
| 113 | DESC = """
|
| 114 | Read C language source or header FILEs, extract embedded documentation comments,
|
| 115 | and print formatted documentation to standard output.
|
| 116 |
|
| 117 | The documentation comments are identified by the "/**" opening comment mark.
|
| 118 |
|
| 119 | See Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax.
|
| 120 | """
|
| 121 |
|
| 122 | EXPORT_FILE_DESC = """
|
| 123 | Specify an additional FILE in which to look for EXPORT_SYMBOL information.
|
| 124 |
|
| 125 | May be used multiple times.
|
| 126 | """
|
| 127 |
|
| 128 | EXPORT_DESC = """
|
| 129 | Only output documentation for the symbols that have been
|
| 130 | exported using EXPORT_SYMBOL() and related macros in any input
|
| 131 | FILE or -export-file FILE.
|
| 132 | """
|
| 133 |
|
| 134 | INTERNAL_DESC = """
|
| 135 | Only output documentation for the symbols that have NOT been
|
| 136 | exported using EXPORT_SYMBOL() and related macros in any input
|
| 137 | FILE or -export-file FILE.
|
| 138 | """
|
| 139 |
|
| 140 | FUNCTION_DESC = """
|
| 141 | Only output documentation for the given function or DOC: section
|
| 142 | title. All other functions and DOC: sections are ignored.
|
| 143 |
|
| 144 | May be used multiple times.
|
| 145 | """
|
| 146 |
|
| 147 | NOSYMBOL_DESC = """
|
| 148 | Exclude the specified symbol from the output documentation.
|
| 149 |
|
| 150 | May be used multiple times.
|
| 151 | """
|
| 152 |
|
| 153 | FILES_DESC = """
|
| 154 | Header and C source files to be parsed.
|
| 155 | """
|
| 156 |
|
| 157 | WARN_CONTENTS_BEFORE_SECTIONS_DESC = """
|
| 158 | Warns if there are contents before sections (deprecated).
|
| 159 |
|
| 160 | This option is kept just for backward-compatibility, but it does nothing,
|
| 161 | neither here nor at the original Perl script.
|
| 162 | """
|
| 163 |
|
| 164 |
|
| 165 | class MsgFormatter(logging.Formatter):
|
| 166 |
|
| 167 |
|
| 168 | def format(self, record):
|
| 169 | record.levelname = record.levelname.capitalize()
|
| 170 | return logging.Formatter.format(self, record)
|
| 171 |
|
| 172 | def main():
|
| 173 |
|
| 174 |
|
| 175 | parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
|
| 176 | description=DESC)
|
| 177 |
|
| 178 | |
| 179 |
|
| 180 | parser.add_argument("-v", "-verbose", "--verbose", action="store_true",
|
| 181 | help="Verbose output, more warnings and other information.")
|
| 182 |
|
| 183 | parser.add_argument("-d", "-debug", "--debug", action="store_true",
|
| 184 | help="Enable debug messages")
|
| 185 |
|
| 186 | parser.add_argument("-M", "-modulename", "--modulename",
|
| 187 | default="Kernel API",
|
| 188 | help="Allow setting a module name at the output.")
|
| 189 |
|
| 190 | parser.add_argument("-l", "-enable-lineno", "--enable_lineno",
|
| 191 | action="store_true",
|
| 192 | help="Enable line number output (only in ReST mode)")
|
| 193 |
|
| 194 | |
| 195 |
|
| 196 | parser.add_argument("-Wreturn", "--wreturn", action="store_true",
|
| 197 | help="Warns about the lack of a return markup on functions.")
|
| 198 |
|
| 199 | parser.add_argument("-Wshort-desc", "-Wshort-description", "--wshort-desc",
|
| 200 | action="store_true",
|
| 201 | help="Warns if initial short description is missing")
|
| 202 |
|
| 203 | parser.add_argument("-Wcontents-before-sections",
|
| 204 | "--wcontents-before-sections", action="store_true",
|
| 205 | help=WARN_CONTENTS_BEFORE_SECTIONS_DESC)
|
| 206 |
|
| 207 | parser.add_argument("-Wall", "--wall", action="store_true",
|
| 208 | help="Enable all types of warnings")
|
| 209 |
|
| 210 | parser.add_argument("-Werror", "--werror", action="store_true",
|
| 211 | help="Treat warnings as errors.")
|
| 212 |
|
| 213 | parser.add_argument("-export-file", "--export-file", action='append',
|
| 214 | help=EXPORT_FILE_DESC)
|
| 215 |
|
| 216 | |
| 217 |
|
| 218 | out_group = parser.add_argument_group("Output format selection (mutually exclusive)")
|
| 219 |
|
| 220 | out_fmt = out_group.add_mutually_exclusive_group()
|
| 221 |
|
| 222 | out_fmt.add_argument("-m", "-man", "--man", action="store_true",
|
| 223 | help="Output troff manual page format.")
|
| 224 | out_fmt.add_argument("-r", "-rst", "--rst", action="store_true",
|
| 225 | help="Output reStructuredText format (default).")
|
| 226 | out_fmt.add_argument("-N", "-none", "--none", action="store_true",
|
| 227 | help="Do not output documentation, only warnings.")
|
| 228 |
|
| 229 | |
| 230 |
|
| 231 | sel_group = parser.add_argument_group("Output selection (mutually exclusive)")
|
| 232 | sel_mut = sel_group.add_mutually_exclusive_group()
|
| 233 |
|
| 234 | sel_mut.add_argument("-e", "-export", "--export", action='store_true',
|
| 235 | help=EXPORT_DESC)
|
| 236 |
|
| 237 | sel_mut.add_argument("-i", "-internal", "--internal", action='store_true',
|
| 238 | help=INTERNAL_DESC)
|
| 239 |
|
| 240 | sel_mut.add_argument("-s", "-function", "--symbol", action='append',
|
| 241 | help=FUNCTION_DESC)
|
| 242 |
|
| 243 | |
| 244 | parser.add_argument("-n", "-nosymbol", "--nosymbol", action='append',
|
| 245 | help=NOSYMBOL_DESC)
|
| 246 |
|
| 247 | parser.add_argument("-D", "-no-doc-sections", "--no-doc-sections",
|
| 248 | action='store_true', help="Don't outputt DOC sections")
|
| 249 |
|
| 250 | parser.add_argument("files", metavar="FILE",
|
| 251 | nargs="+", help=FILES_DESC)
|
| 252 |
|
| 253 | args = parser.parse_args()
|
| 254 |
|
| 255 | if args.wall:
|
| 256 | args.wreturn = True
|
| 257 | args.wshort_desc = True
|
| 258 | args.wcontents_before_sections = True
|
| 259 |
|
| 260 | logger = logging.getLogger()
|
| 261 |
|
| 262 | if not args.debug:
|
| 263 | logger.setLevel(logging.INFO)
|
| 264 | else:
|
| 265 | logger.setLevel(logging.DEBUG)
|
| 266 |
|
| 267 | formatter = MsgFormatter('%(levelname)s: %(message)s')
|
| 268 |
|
| 269 | handler = logging.StreamHandler()
|
| 270 | handler.setFormatter(formatter)
|
| 271 |
|
| 272 | logger.addHandler(handler)
|
| 273 |
|
| 274 | python_ver = sys.version_info[:2]
|
| 275 | if python_ver < (3,6):
|
| 276 | logger.warning("Python 3.6 or later is required by kernel-doc")
|
| 277 |
|
| 278 | |
| 279 | sys.exit(0)
|
| 280 |
|
| 281 | if python_ver < (3,7):
|
| 282 | logger.warning("Python 3.7 or later is required for correct results")
|
| 283 |
|
| 284 | if args.man:
|
| 285 | out_style = ManFormat(modulename=args.modulename)
|
| 286 | elif args.none:
|
| 287 | out_style = None
|
| 288 | else:
|
| 289 | out_style = RestFormat()
|
| 290 |
|
| 291 | kfiles = KernelFiles(verbose=args.verbose,
|
| 292 | out_style=out_style, werror=args.werror,
|
| 293 | wreturn=args.wreturn, wshort_desc=args.wshort_desc,
|
| 294 | wcontents_before_sections=args.wcontents_before_sections)
|
| 295 |
|
| 296 | kfiles.parse(args.files, export_file=args.export_file)
|
| 297 |
|
| 298 | for t in kfiles.msg(enable_lineno=args.enable_lineno, export=args.export,
|
| 299 | internal=args.internal, symbol=args.symbol,
|
| 300 | nosymbol=args.nosymbol, export_file=args.export_file,
|
| 301 | no_doc_sections=args.no_doc_sections):
|
| 302 | msg = t[1]
|
| 303 | if msg:
|
| 304 | print(msg)
|
| 305 |
|
| 306 | error_count = kfiles.errors
|
| 307 | if not error_count:
|
| 308 | sys.exit(0)
|
| 309 |
|
| 310 | if args.werror:
|
| 311 | print(f"{error_count} warnings as errors")
|
| 312 | sys.exit(error_count)
|
| 313 |
|
| 314 | if args.verbose:
|
| 315 | print(f"{error_count} errors")
|
| 316 |
|
| 317 | if args.none:
|
| 318 | sys.exit(0)
|
| 319 |
|
| 320 | sys.exit(error_count)
|
| 321 |
|
| 322 |
|
| 323 | |
| 324 | if __name__ == "__main__":
|
| 325 | main()
|