# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. import json import os import posixpath from os import PathLike # `typing.Literal` not available until Python 3.8; # `typing_extensions` not generally available here from typing import Iterable, Set FIRST_LINE = "// This file was generated by {}. DO NOT EDIT.".format( # `posixpath` for forward slashes, for presentation purposes posixpath.relpath(__file__, os.getenv("TOPSRCDIR", "/")) ) def generate_allowed_items( which: str, # should be: Literal["files", "names"], paths: Iterable[PathLike], ) -> str: def remove_trailing_comment(s: str) -> str: return s[0 : s.find("#")] def read_items_from_path(path: PathLike) -> Set[str]: out = set() with open(path) as file: for line in file.readlines(): line = remove_trailing_comment(line).strip() if not line: continue # comment or empty line; discard out.add(line) return out allowed = set().union(*(read_items_from_path(path) for path in paths)) # BUG: `json.dumps` may not correctly handle use of the quote character in # thread names allowed_list_s = ",\n ".join(json.dumps(elem) for elem in sorted(allowed)) return f"""\ static const char *allow_thread_{which}[] = {{ {allowed_list_s} }};""" def generate_allows( *, allowed_names: Iterable[PathLike], allowed_files: Iterable[PathLike] ) -> str: """ This function reads in the specified sets of files -- ordinarily, ["ThreadAllows.txt"] and ["ThreadFileAllows.txt"] -- and generates the text of a header file containing two arrays with their contents, for inclusion by the thread-name checker. The checker will reject the creation of any thread via NS_NewNamedThread unless either: - the thread's name is a literal string which is found in the set of allowed thread names; or - the thread's creation occurs within a file which is found in the set of unchecked files. The latter condition exists mostly for the definition of NS_NewNamedThread, but there also exist a few cases where the thread name is dynamically computed (and so can't be checked). """ output_string = ( FIRST_LINE + "\n\n" + generate_allowed_items("files", allowed_files) + "\n\n" + generate_allowed_items("names", allowed_names) + "\n" ) return output_string # Entry point used by build/clang-plugin/moz.build (q.v.). def generate_file(output, allowed_names, allowed_files): output.write( generate_allows(allowed_names=[allowed_names], allowed_files=[allowed_files]) )