import os import sys _copyright = """/* * Copyright 2011-2014 Software Freedom Conservancy * * Licensed under the Apache License, Version 2.0 (the \"License\"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an \"AS IS\" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ """ def get_atom_name(name): # We had a todo here to convert camelCase and snake_case to BIG_SNAKE_CASE, but this code # will be removed when BiDi is the default, so we're not going to bother with that. name = os.path.basename(name) return name.upper() def write_atom_literal(out, name, contents, lang, utf8): # Escape the contents of the file so it can be stored as a literal. contents = contents.replace("\\", "\\\\") contents = contents.replace("\f", "\\f") contents = contents.replace("\n", "\\n") contents = contents.replace("\r", "\\r") contents = contents.replace("\t", "\\t") contents = contents.replace('"', '\\"') if "cc" == lang or "hh" == lang: if utf8: line_format = ' "{}",\n' else: line_format = ' L"{}",\n' elif "java" == lang: line_format = ' .append\("{}")\n' else: raise RuntimeError(f"Unknown language: {lang} ") name = get_atom_name(name) if "cc" == lang or "hh" == lang: char_type = "char" if utf8 else "wchar_t" out.write(f"const {char_type}* const {name}[] = {{\n") elif "java" == lang: out.write(f" {name}(new StringBuilder()\n") else: raise RuntimeError(f"Unknown language: {lang} ") # Make the header file play nicely in a terminal: limit lines to 80 # characters, but make sure we don't cut off a line in the middle # of an escape sequence. while len(contents) > 70: diff = 70 while contents[diff - 1] == "\\": diff = diff - 1 line = contents[0:diff] contents = contents[diff:] out.write(line_format.format(line)) if len(contents) > 0: out.write(line_format.format(contents)) if "cc" == lang or "hh" == lang: out.write(" NULL\n};\n\n") elif "java" == lang: out.write(" .toString()),\n") def generate_header(file_name, out, js_map, just_declare, utf8): define_guard = "WEBDRIVER_{}".format(os.path.basename(file_name.upper()).replace(".", "_")) include_stddef = "" if utf8 else "\n#include // For wchar_t." out.write( f"""{_copyright} /* AUTO GENERATED - DO NOT EDIT BY HAND */ #ifndef {define_guard} #define {define_guard} {include_stddef} #include // For std::(w)string. namespace webdriver {{ namespace atoms {{ """ ) string_type = "std::string" if utf8 else "std::wstring" char_type = "char" if utf8 else "wchar_t" for name, file in js_map.items(): if just_declare: out.write(f"extern const {char_type}* const {name.upper()}[];\n") else: contents = open(file).read() write_atom_literal(out, name, contents, "hh", utf8) out.write( f""" static inline {string_type} asString(const {char_type}* const atom[]) {{ {string_type} source; for (int i = 0; atom[i] != NULL; i++) {{ source += atom[i]; }} return source; }} }} // namespace atoms }} // namespace webdriver #endif // {define_guard} """ ) def generate_cc_source(out, js_map, utf8): out.write( f"""{_copyright} /* AUTO GENERATED - DO NOT EDIT BY HAND */ #include // For NULL. #include "atoms.h" namespace webdriver {{ namespace atoms {{ """ ) for name, file in js_map.items(): contents = open(file).read() write_atom_literal(out, name, contents, "cc", utf8) out.write(""" } // namespace atoms } // namespace webdriver """) def generate_java_source(file_name, out, preamble, js_map): if not file_name.endswith(".java"): raise RuntimeError("File name must end in .java") class_name = os.path.basename(file_name[:-5]) out.write(_copyright) out.write("\n") out.write(preamble) out.write("") out.write( f""" public enum {class_name} {{ // AUTO GENERATED - DO NOT EDIT BY HAND """ ) for name, file in js_map.items(): contents = open(file).read() write_atom_literal(out, name, contents, "java", True) out.write( f""" ; private final String value; public String getValue() {{ return value; }} public String toString() {{ return getValue(); }} {class_name}(String value) {{ this.value = value; }} }} """ ) def main(argv=[]): lang = argv[1] file_name = argv[2] preamble = argv[3] utf8 = argv[4] == "true" js_map = {} for i in range(5, len(argv), 2): js_map[argv[i]] = argv[i + 1] with open(file_name, "w") as out: if "cc" == lang: generate_cc_source(out, js_map, utf8) elif "hdecl" == lang: generate_header(file_name, out, js_map, True, utf8) elif "hh" == lang: generate_header(file_name, out, js_map, False, utf8) elif "java" == lang: generate_java_source(file_name, out, preamble, js_map) else: raise RuntimeError(f"Unknown lang: {lang}") if __name__ == "__main__": main(sys.argv)