13af6ab5fSopenharmony_ci#!/usr/bin/env python3
23af6ab5fSopenharmony_ci# coding: utf-8
33af6ab5fSopenharmony_ci# Copyright (c) 2024 Huawei Device Co., Ltd.
43af6ab5fSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
53af6ab5fSopenharmony_ci# you may not use this file except in compliance with the License.
63af6ab5fSopenharmony_ci# You may obtain a copy of the License at
73af6ab5fSopenharmony_ci#
83af6ab5fSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0
93af6ab5fSopenharmony_ci#
103af6ab5fSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
113af6ab5fSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
123af6ab5fSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133af6ab5fSopenharmony_ci# See the License for the specific language governing permissions and
143af6ab5fSopenharmony_ci# limitations under the License.
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci
173af6ab5fSopenharmony_ci"""
183af6ab5fSopenharmony_ciUsage: python3 main.py <path_to_ets2panda> <path_to_gen_dir> <path_to_header_or_dir> [<path_to_header_or_dir> ...]
193af6ab5fSopenharmony_ciDescription: Parse c++ headers to yaml files.
203af6ab5fSopenharmony_ci"""
213af6ab5fSopenharmony_ci
223af6ab5fSopenharmony_ciimport os.path
233af6ab5fSopenharmony_ciimport sys
243af6ab5fSopenharmony_ciimport traceback
253af6ab5fSopenharmony_cifrom typing import List
263af6ab5fSopenharmony_ci
273af6ab5fSopenharmony_ci# pylint: disable=W0401,W0614
283af6ab5fSopenharmony_cifrom cpp_parser import CppParser
293af6ab5fSopenharmony_cifrom log_tools import init_log, console_log, parsing_log, error_log, info_log
303af6ab5fSopenharmony_cifrom prepare_header import remove_comments, extract_and_remove_includes
313af6ab5fSopenharmony_cifrom file_tools import print_to_yaml
323af6ab5fSopenharmony_cifrom runtime_collections import (
333af6ab5fSopenharmony_ci    init_collections,
343af6ab5fSopenharmony_ci    add_to_statistics,
353af6ab5fSopenharmony_ci    add_to_custom_yamls,
363af6ab5fSopenharmony_ci    save_custom_yamls,
373af6ab5fSopenharmony_ci    save_statistics,
383af6ab5fSopenharmony_ci)
393af6ab5fSopenharmony_ci
403af6ab5fSopenharmony_ci
413af6ab5fSopenharmony_cidef parse_file(src_path: str, dest_path: str) -> None:
423af6ab5fSopenharmony_ci    """
433af6ab5fSopenharmony_ci    Parse one file.
443af6ab5fSopenharmony_ci    """
453af6ab5fSopenharmony_ci    console_log("------------------------------------------------------------------------------")
463af6ab5fSopenharmony_ci    parsing_log("Parsing file: " + src_path)
473af6ab5fSopenharmony_ci
483af6ab5fSopenharmony_ci    with open(src_path, "r", encoding="utf-8") as file:
493af6ab5fSopenharmony_ci        data = file.read()
503af6ab5fSopenharmony_ci        data = remove_comments(data)
513af6ab5fSopenharmony_ci        data, includes = extract_and_remove_includes(data)
523af6ab5fSopenharmony_ci
533af6ab5fSopenharmony_ci        try:
543af6ab5fSopenharmony_ci            res = CppParser(data).parse()
553af6ab5fSopenharmony_ci
563af6ab5fSopenharmony_ci            if len(includes) != 0:
573af6ab5fSopenharmony_ci                res["include"] = includes
583af6ab5fSopenharmony_ci
593af6ab5fSopenharmony_ci            if not os.path.exists(os.path.dirname(dest_path)):
603af6ab5fSopenharmony_ci                os.makedirs(os.path.dirname(dest_path))
613af6ab5fSopenharmony_ci
623af6ab5fSopenharmony_ci            print_to_yaml(dest_path, res)
633af6ab5fSopenharmony_ci            console_log("\n++++++++++++++++++++++++\n+ Successfully parsed! +\n++++++++++++++++++++++++")
643af6ab5fSopenharmony_ci
653af6ab5fSopenharmony_ci            # Collect statistics
663af6ab5fSopenharmony_ci            add_to_statistics("generated_yamls", dest_path)
673af6ab5fSopenharmony_ci            # Collect custom yamls
683af6ab5fSopenharmony_ci            add_to_custom_yamls("pathsToHeaders", "paths", src_path)
693af6ab5fSopenharmony_ci
703af6ab5fSopenharmony_ci        except Exception:  # pylint: disable=W0718
713af6ab5fSopenharmony_ci            os.fdopen(os.open(dest_path, os.O_CREAT, mode=511), "w", encoding="utf-8").close()
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ci            error_log("Error while parsing '" + src_path + "'\n")
743af6ab5fSopenharmony_ci            error_log(traceback.format_exc() + "\n")
753af6ab5fSopenharmony_ci            info_log("Error! Can't parse '" + src_path + "'")
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_ci
783af6ab5fSopenharmony_cidef parse_files_in_list(paths_list: List[str], result_folder: str) -> None:
793af6ab5fSopenharmony_ci    """
803af6ab5fSopenharmony_ci    Parse all headers from paths_list. Elements of list can be file's or dir's paths.
813af6ab5fSopenharmony_ci    """
823af6ab5fSopenharmony_ci    os.makedirs(result_folder, exist_ok=True)
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_ci    for path in paths_list:
853af6ab5fSopenharmony_ci        if os.path.isdir(path):
863af6ab5fSopenharmony_ci
873af6ab5fSopenharmony_ci            if path.rstrip("/") == result_folder.rstrip("/"):
883af6ab5fSopenharmony_ci                continue
893af6ab5fSopenharmony_ci
903af6ab5fSopenharmony_ci            nested_paths = [os.path.join(path, dir_file) for dir_file in os.listdir(path)]
913af6ab5fSopenharmony_ci            parse_files_in_list(nested_paths, result_folder)
923af6ab5fSopenharmony_ci
933af6ab5fSopenharmony_ci        elif os.path.isfile(path) and os.path.splitext(path)[1] == ".h":
943af6ab5fSopenharmony_ci            dst = os.path.join(result_folder, f"{os.path.splitext(os.path.relpath(path, sys.argv[1]))[0]}.yaml")
953af6ab5fSopenharmony_ci            parse_file(path, dst)
963af6ab5fSopenharmony_ci
973af6ab5fSopenharmony_ci        else:
983af6ab5fSopenharmony_ci            info_log(f"Error! File does not fit for parsing or does not exist: '{path}'")
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_ci
1013af6ab5fSopenharmony_ciif __name__ == "__main__":
1023af6ab5fSopenharmony_ci    if len(sys.argv) < 4:
1033af6ab5fSopenharmony_ci        raise RuntimeError("Wrong arguments!")
1043af6ab5fSopenharmony_ci
1053af6ab5fSopenharmony_ci    lib_gen_dir = sys.argv[2]
1063af6ab5fSopenharmony_ci    if not os.path.exists(lib_gen_dir) or not os.path.isdir(lib_gen_dir):
1073af6ab5fSopenharmony_ci        raise RuntimeError(f"Please change lib_gen_dir to correct path.\n'{lib_gen_dir}'")
1083af6ab5fSopenharmony_ci    init_collections(lib_gen_dir)
1093af6ab5fSopenharmony_ci    init_log(lib_gen_dir)
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_ci    files_list = list(sys.argv[3:])
1123af6ab5fSopenharmony_ci    parse_files_in_list(files_list, os.path.join(lib_gen_dir, "gen/headers"))
1133af6ab5fSopenharmony_ci    save_custom_yamls()
1143af6ab5fSopenharmony_ci    save_statistics()
115