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