| #!/usr/bin/env fuchsia-vendored-python |
| # Copyright 2020 The Fuchsia Authors |
| # |
| # Use of this source code is governed by a MIT-style |
| # license that can be found in the LICENSE file or at |
| # https://opensource.org/licenses/MIT |
| |
| import argparse |
| import json |
| import os |
| import sys |
| |
| # Some boot options have non-primitive types. |
| # This map is used to map the type of the boot-option |
| # to a string suitable for markdown documentation about the option. |
| SPECIAL_TYPES = { |
| "AutoOr<uint64_t>": r"\[auto | \<uint64>\]", |
| "SmallString": r"\<string>", |
| "RedactedHex": r"\<hexadecimal>", |
| "TestOption": "test", |
| "uart::all::Config<>": r"\[none | legacy | qemu | \<type>,\<base>,\<irq>\]", |
| } |
| |
| |
| def generate_doc(option): |
| # Types that are lists are enumerations of valid values for this option. |
| # and are printed as [ <value1> | <value2> |...]. |
| if isinstance(option["type"], list): |
| option["type"] = r"\[%s\]" % " | ".join(option["type"]) |
| else: |
| # Non-list types could be a special type, or default to the |
| # type passed in. This allows SPECIAL_TYPES to handle non-primitive |
| # types and primitive types fall back to themselves as the default. |
| option["type"] = SPECIAL_TYPES.get( |
| option["type"], |
| r"\<%s>" % option["type"], |
| ) |
| if "default_description" in option: |
| option["default"] = "**Default:** %s\n" % option["default_description"] |
| elif option["default"] != "": |
| if isinstance(option["default"], bool): |
| option["default"] = "true" if option["default"] else "false" |
| elif isinstance(option["default"], int): |
| option["default"] = "%#x" % option["default"] |
| option["default"] = "**Default:** `%s`\n" % option["default"] |
| # Return the multiline string with the values interpolated. |
| return """ |
| ### {name}={type} |
| |
| {default} |
| {documentation} |
| """.format( |
| **option, |
| ) |
| |
| |
| def generate_docs(title, options): |
| return """ |
| ## Options {title} |
| {options} |
| """.format( |
| title=title, |
| options="".join(generate_doc(option) for option in options), |
| ) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser(description="Produce boot-options.md") |
| parser.add_argument( |
| "output", |
| help="Output file", |
| metavar="//docs/gen/boot-options.md", |
| ) |
| parser.add_argument( |
| "json", |
| help="JSON input file", |
| metavar="boot-options.json", |
| ) |
| parser.add_argument( |
| "preamble", |
| help="Markdown preamble file", |
| metavar="preamble.md", |
| ) |
| parser.add_argument( |
| "postamble", |
| help="Markdown postamble file", |
| metavar="postamble.md", |
| ) |
| args = parser.parse_args() |
| |
| with open(args.json) as f: |
| options = json.load(f) |
| |
| with open(args.preamble) as f: |
| preamble = f.read() |
| |
| with open(args.postamble) as f: |
| postamble = f.read() |
| |
| text = preamble |
| |
| text += generate_docs("common to all machines", options["common"]) |
| del options["common"] |
| for arch, arch_options in sorted(options.items()): |
| text += generate_docs( |
| "available only on %s machines" % arch, |
| arch_options, |
| ) |
| |
| text += postamble |
| |
| if os.path.exists(args.output): |
| with open(args.output) as f: |
| if f.read() == text: |
| return 0 |
| |
| with open(args.output, "w") as f: |
| f.write(text) |
| |
| return 0 |
| |
| |
| if __name__ == "__main__": |
| sys.exit(main()) |