#!/usr/bin/env python3 """Turns proto/cmdids.txt into a constant header plus a name table for logging.""" import argparse import os def write_if_changed(path, text): if os.path.exists(path): with open(path, encoding="utf-8") as fh: if fh.read() == text: return with open(path, "w", encoding="utf-8", newline="\n") as fh: fh.write(text) def main(): ap = argparse.ArgumentParser() ap.add_argument("--input", required=True) ap.add_argument("--out-dir", required=True) args = ap.parse_args() entries = [] with open(args.input, encoding="utf-8") as fh: for line in fh: line = line.split("#", 1)[0].strip() if not line or "=" not in line: continue name, value = (part.strip() for part in line.split("=", 1)) if name == "None": continue entries.append((name, int(value))) entries.sort(key=lambda e: e[0]) h = ["// generated by tools/gen_cmdids.py -- do not edit", "#pragma once", "#include ", "#include ", "", "namespace cmd {", ""] for name, value in entries: h.append(f"constexpr uint16_t {name} = {value};") h += ["", "// packet name for logging; \"Unknown()\" when the dump has no name for it", "std::string name(uint16_t id);", "", "// 0 when the dump has no packet by that name", "uint16_t id(const std::string& name);", "", "} // namespace cmd", ""] write_if_changed(os.path.join(args.out_dir, "cmd_ids.h"), "\n".join(h)) # first name wins for aliased ids, so the table stays 1:1 by_id = {} for name, value in entries: by_id.setdefault(value, name) c = ["// generated by tools/gen_cmdids.py -- do not edit", '#include "net/cmd_ids.h"', "", "#include ", "", "namespace cmd {", "namespace {", "const std::unordered_map& table() {", " static const std::unordered_map t = {"] for value, name in sorted(by_id.items()): c.append(f' {{{value}, "{name}"}},') c += [" };", " return t;", "}", "", "const std::unordered_map& reverse() {", " static const std::unordered_map t = [] {", " std::unordered_map m;", " for (const auto& [k, v] : table()) m.emplace(v, k);", " return m;", " }();", " return t;", "}", "} // namespace", "", "std::string name(uint16_t id) {", " auto it = table().find(id);", " if (it != table().end()) return it->second;", ' return "Unknown(" + std::to_string(id) + ")";', "}", "", "uint16_t id(const std::string& n) {", " auto it = reverse().find(n);", " return it == reverse().end() ? 0 : it->second;", "}", "", "} // namespace cmd", ""] write_if_changed(os.path.join(args.out_dir, "cmd_ids.cpp"), "\n".join(c)) print(f" {len(entries)} cmd ids, {len(by_id)} unique") if __name__ == "__main__": main()