| 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 <stddef.h> // For wchar_t." |
| out.write( |
| f"""{_copyright} |
| |
| /* AUTO GENERATED - DO NOT EDIT BY HAND */ |
| #ifndef {define_guard} |
| #define {define_guard} |
| {include_stddef} |
| #include <string> // 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 <stddef.h> // 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) |