15f9996aaSopenharmony_ci#!/usr/bin/env python 25f9996aaSopenharmony_ci# -*- coding: utf-8 -*- 35f9996aaSopenharmony_ci# Copyright (c) 2024 Huawei Device Co., Ltd. 45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License. 65f9996aaSopenharmony_ci# You may obtain a copy of the License at 75f9996aaSopenharmony_ci# 85f9996aaSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 95f9996aaSopenharmony_ci# 105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and 145f9996aaSopenharmony_ci# limitations under the License. 155f9996aaSopenharmony_ci 165f9996aaSopenharmony_ciimport os 175f9996aaSopenharmony_ciimport sys 185f9996aaSopenharmony_cifrom queue import Queue 195f9996aaSopenharmony_ci 205f9996aaSopenharmony_ci 215f9996aaSopenharmony_ciclass TokenType(object): 225f9996aaSopenharmony_ci UNKNOWN = 0 235f9996aaSopenharmony_ci END_OF_FILE = 1 245f9996aaSopenharmony_ci COMMENT = 2 # comment 255f9996aaSopenharmony_ci INCLUDE = 3 # include 265f9996aaSopenharmony_ci STRING = 4 # character string 275f9996aaSopenharmony_ci 285f9996aaSopenharmony_ci 295f9996aaSopenharmony_ciclass Token(object): 305f9996aaSopenharmony_ci def __init__(self, file_name, token_type, value): 315f9996aaSopenharmony_ci self.token_type = token_type 325f9996aaSopenharmony_ci self.value = value 335f9996aaSopenharmony_ci self.row = 1 345f9996aaSopenharmony_ci self.col = 1 355f9996aaSopenharmony_ci self.file_name = file_name 365f9996aaSopenharmony_ci 375f9996aaSopenharmony_ci def clean(self): 385f9996aaSopenharmony_ci self.token_type = TokenType.UNKNOWN 395f9996aaSopenharmony_ci self.value = "" 405f9996aaSopenharmony_ci self.row = 1 415f9996aaSopenharmony_ci self.col = 1 425f9996aaSopenharmony_ci 435f9996aaSopenharmony_ci def dump(self): 445f9996aaSopenharmony_ci return "<{}:{}:{}: {},'{}'>".format(self.file_name, self.row, self.col, 455f9996aaSopenharmony_ci self.token_type, self.value) 465f9996aaSopenharmony_ci 475f9996aaSopenharmony_ci def info(self): 485f9996aaSopenharmony_ci return "{}:{}:{}".format(self.file_name, self.row, self.col) 495f9996aaSopenharmony_ci 505f9996aaSopenharmony_ci 515f9996aaSopenharmony_ciclass Char(object): 525f9996aaSopenharmony_ci def __init__(self, is_eof, char): 535f9996aaSopenharmony_ci self.is_eof = is_eof 545f9996aaSopenharmony_ci self.char = char 555f9996aaSopenharmony_ci 565f9996aaSopenharmony_ci def dump(self): 575f9996aaSopenharmony_ci return "{%s, %s}" % (self.is_eof, self.char) 585f9996aaSopenharmony_ci 595f9996aaSopenharmony_ci 605f9996aaSopenharmony_ciclass Lexer(object): 615f9996aaSopenharmony_ci def __init__(self, idl_file_path): 625f9996aaSopenharmony_ci self.have_peek = False 635f9996aaSopenharmony_ci with open(idl_file_path, 'r') as idl_file: 645f9996aaSopenharmony_ci file_info = idl_file.read() 655f9996aaSopenharmony_ci self.data = file_info 665f9996aaSopenharmony_ci self.data_len = len(self.data) 675f9996aaSopenharmony_ci self.read_index = 0 685f9996aaSopenharmony_ci self.cur_token = Token(os.path.basename(idl_file_path), 695f9996aaSopenharmony_ci TokenType.UNKNOWN, "") 705f9996aaSopenharmony_ci self.cur_row = 1 715f9996aaSopenharmony_ci self.cur_col = 1 725f9996aaSopenharmony_ci 735f9996aaSopenharmony_ci def peek_char(self, peek_count=0): 745f9996aaSopenharmony_ci index = self.read_index + peek_count 755f9996aaSopenharmony_ci if index >= self.data_len: 765f9996aaSopenharmony_ci return Char(True, '0') 775f9996aaSopenharmony_ci return Char(False, self.data[index]) 785f9996aaSopenharmony_ci 795f9996aaSopenharmony_ci def get_char(self): 805f9996aaSopenharmony_ci if self.read_index >= self.data_len: 815f9996aaSopenharmony_ci return Char(True, '0') 825f9996aaSopenharmony_ci read_index = self.read_index 835f9996aaSopenharmony_ci self.read_index += 1 845f9996aaSopenharmony_ci if self.data[read_index] == '\n': 855f9996aaSopenharmony_ci self.cur_row += 1 865f9996aaSopenharmony_ci self.cur_col = 1 875f9996aaSopenharmony_ci else: 885f9996aaSopenharmony_ci self.cur_col += 1 895f9996aaSopenharmony_ci return Char(False, self.data[read_index]) 905f9996aaSopenharmony_ci 915f9996aaSopenharmony_ci def peek_token(self): 925f9996aaSopenharmony_ci if not self.have_peek: 935f9996aaSopenharmony_ci self.read_token() 945f9996aaSopenharmony_ci self.have_peek = True 955f9996aaSopenharmony_ci return self.cur_token 965f9996aaSopenharmony_ci 975f9996aaSopenharmony_ci def get_token(self): 985f9996aaSopenharmony_ci if not self.have_peek: 995f9996aaSopenharmony_ci self.read_token() 1005f9996aaSopenharmony_ci self.have_peek = False 1015f9996aaSopenharmony_ci return self.cur_token 1025f9996aaSopenharmony_ci 1035f9996aaSopenharmony_ci def read_token(self): 1045f9996aaSopenharmony_ci self.cur_token.clean() 1055f9996aaSopenharmony_ci while not self.peek_char().is_eof: 1065f9996aaSopenharmony_ci new_char = self.peek_char() 1075f9996aaSopenharmony_ci if new_char.char.isspace(): 1085f9996aaSopenharmony_ci self.get_char() 1095f9996aaSopenharmony_ci continue 1105f9996aaSopenharmony_ci self.cur_token.row = self.cur_row 1115f9996aaSopenharmony_ci self.cur_token.col = self.cur_col 1125f9996aaSopenharmony_ci if new_char.char == '#': 1135f9996aaSopenharmony_ci self.read_include() 1145f9996aaSopenharmony_ci return 1155f9996aaSopenharmony_ci if new_char.char == '"': 1165f9996aaSopenharmony_ci self.read_string() 1175f9996aaSopenharmony_ci return 1185f9996aaSopenharmony_ci if new_char.char == '/': 1195f9996aaSopenharmony_ci self.read_comment() 1205f9996aaSopenharmony_ci return 1215f9996aaSopenharmony_ci self.cur_token.value = new_char.char 1225f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.UNKNOWN 1235f9996aaSopenharmony_ci self.get_char() 1245f9996aaSopenharmony_ci return 1255f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.END_OF_FILE 1265f9996aaSopenharmony_ci 1275f9996aaSopenharmony_ci def read_include(self): 1285f9996aaSopenharmony_ci token_value = [] 1295f9996aaSopenharmony_ci token_value.append(self.get_char().char) 1305f9996aaSopenharmony_ci while not self.peek_char().is_eof: 1315f9996aaSopenharmony_ci new_char = self.peek_char() 1325f9996aaSopenharmony_ci if new_char.char.isalpha(): 1335f9996aaSopenharmony_ci token_value.append(new_char.char) 1345f9996aaSopenharmony_ci self.get_char() 1355f9996aaSopenharmony_ci continue 1365f9996aaSopenharmony_ci break 1375f9996aaSopenharmony_ci key_str = "".join(token_value) 1385f9996aaSopenharmony_ci if key_str == "#include": 1395f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.INCLUDE 1405f9996aaSopenharmony_ci else: 1415f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.UNKNOWN 1425f9996aaSopenharmony_ci self.cur_token.value = key_str 1435f9996aaSopenharmony_ci 1445f9996aaSopenharmony_ci def read_string(self): 1455f9996aaSopenharmony_ci token_value = [] 1465f9996aaSopenharmony_ci self.get_char() 1475f9996aaSopenharmony_ci while not self.peek_char().is_eof and self.peek_char().char != '"': 1485f9996aaSopenharmony_ci token_value.append(self.get_char().char) 1495f9996aaSopenharmony_ci 1505f9996aaSopenharmony_ci if self.peek_char().char == '"': 1515f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.STRING 1525f9996aaSopenharmony_ci self.get_char() 1535f9996aaSopenharmony_ci else: 1545f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.UNKNOWN 1555f9996aaSopenharmony_ci self.cur_token.value = "".join(token_value) 1565f9996aaSopenharmony_ci 1575f9996aaSopenharmony_ci def read_comment(self): 1585f9996aaSopenharmony_ci token_value = [] 1595f9996aaSopenharmony_ci token_value.append(self.get_char().char) 1605f9996aaSopenharmony_ci new_char = self.peek_char() 1615f9996aaSopenharmony_ci if not new_char.is_eof: 1625f9996aaSopenharmony_ci if new_char.char == '/': 1635f9996aaSopenharmony_ci self.read_line_comment(token_value) 1645f9996aaSopenharmony_ci return 1655f9996aaSopenharmony_ci elif new_char.char == '*': 1665f9996aaSopenharmony_ci self.read_block_comment(token_value) 1675f9996aaSopenharmony_ci return 1685f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.UNKNOWN 1695f9996aaSopenharmony_ci self.cur_token.value = "".join(token_value) 1705f9996aaSopenharmony_ci 1715f9996aaSopenharmony_ci def read_line_comment(self, token_value): 1725f9996aaSopenharmony_ci token_value.append(self.get_char().char) 1735f9996aaSopenharmony_ci while not self.peek_char().is_eof: 1745f9996aaSopenharmony_ci new_char = self.get_char() 1755f9996aaSopenharmony_ci if new_char.char == '\n': 1765f9996aaSopenharmony_ci break 1775f9996aaSopenharmony_ci token_value.append(new_char.char) 1785f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.COMMENT 1795f9996aaSopenharmony_ci self.cur_token.value = "".join(token_value) 1805f9996aaSopenharmony_ci 1815f9996aaSopenharmony_ci def read_block_comment(self, token_value): 1825f9996aaSopenharmony_ci # read * 1835f9996aaSopenharmony_ci token_value.append(self.get_char().char) 1845f9996aaSopenharmony_ci while not self.peek_char().is_eof: 1855f9996aaSopenharmony_ci new_char = self.get_char() 1865f9996aaSopenharmony_ci token_value.append(new_char.char) 1875f9996aaSopenharmony_ci if new_char.char == '*' and self.peek_char().char == '/': 1885f9996aaSopenharmony_ci token_value.append(self.get_char().char) 1895f9996aaSopenharmony_ci break 1905f9996aaSopenharmony_ci value = "".join(token_value) 1915f9996aaSopenharmony_ci if value.endswith("*/"): 1925f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.COMMENT 1935f9996aaSopenharmony_ci else: 1945f9996aaSopenharmony_ci self.cur_token.token_type = TokenType.UNKNOWN 1955f9996aaSopenharmony_ci self.cur_token.value = value 1965f9996aaSopenharmony_ci 1975f9996aaSopenharmony_ci 1985f9996aaSopenharmony_ciclass HcsParser(object): 1995f9996aaSopenharmony_ci def __init__(self): 2005f9996aaSopenharmony_ci self.all_hcs_files = set() 2015f9996aaSopenharmony_ci self.src_queue = Queue() 2025f9996aaSopenharmony_ci 2035f9996aaSopenharmony_ci # get all hcs files by root hcs file 2045f9996aaSopenharmony_ci def get_hcs_info(self): 2055f9996aaSopenharmony_ci result_str = "" 2065f9996aaSopenharmony_ci all_hcs_files_list = sorted(list(self.all_hcs_files)) 2075f9996aaSopenharmony_ci for file_path in all_hcs_files_list: 2085f9996aaSopenharmony_ci result_str += "{}\n".format(file_path) 2095f9996aaSopenharmony_ci return result_str 2105f9996aaSopenharmony_ci 2115f9996aaSopenharmony_ci def parse(self, root_hcs_file): 2125f9996aaSopenharmony_ci if not os.path.exists(root_hcs_file): 2135f9996aaSopenharmony_ci return 2145f9996aaSopenharmony_ci self.src_queue.put(os.path.abspath(root_hcs_file)) 2155f9996aaSopenharmony_ci while not self.src_queue.empty(): 2165f9996aaSopenharmony_ci cur_hcs_file = self.src_queue.get() 2175f9996aaSopenharmony_ci self.all_hcs_files.add(cur_hcs_file) 2185f9996aaSopenharmony_ci self.parse_one(cur_hcs_file) 2195f9996aaSopenharmony_ci 2205f9996aaSopenharmony_ci def parse_one(self, cur_hcs_file_path): 2215f9996aaSopenharmony_ci hcs_file_dir = os.path.dirname(cur_hcs_file_path) 2225f9996aaSopenharmony_ci lex = Lexer(cur_hcs_file_path) 2235f9996aaSopenharmony_ci while lex.peek_token().token_type != TokenType.END_OF_FILE: 2245f9996aaSopenharmony_ci cur_token_type = lex.peek_token().token_type 2255f9996aaSopenharmony_ci if cur_token_type == TokenType.INCLUDE: 2265f9996aaSopenharmony_ci self.parse_include(lex, hcs_file_dir) 2275f9996aaSopenharmony_ci else: 2285f9996aaSopenharmony_ci lex.get_token() 2295f9996aaSopenharmony_ci 2305f9996aaSopenharmony_ci def parse_include(self, lex, hcs_file_dir): 2315f9996aaSopenharmony_ci lex.get_token() # include token 2325f9996aaSopenharmony_ci token = lex.peek_token() 2335f9996aaSopenharmony_ci if token.token_type == TokenType.STRING: 2345f9996aaSopenharmony_ci hcs_file_path = os.path.join(hcs_file_dir, token.value) 2355f9996aaSopenharmony_ci # do not parse the hcs file that does not exist 2365f9996aaSopenharmony_ci if not os.path.exists(hcs_file_path): 2375f9996aaSopenharmony_ci return 2385f9996aaSopenharmony_ci self.src_queue.put(os.path.abspath(hcs_file_path)) 2395f9996aaSopenharmony_ci 2405f9996aaSopenharmony_ci 2415f9996aaSopenharmony_cidef check_python_version(): 2425f9996aaSopenharmony_ci if sys.version_info < (3, 0): 2435f9996aaSopenharmony_ci raise Exception("Please run with python version >= 3.0") 2445f9996aaSopenharmony_ci 2455f9996aaSopenharmony_ci 2465f9996aaSopenharmony_ciif __name__ == "__main__": 2475f9996aaSopenharmony_ci check_python_version() 2485f9996aaSopenharmony_ci if len(sys.argv) < 2: 2495f9996aaSopenharmony_ci raise Exception("No hcs source files, please check input") 2505f9996aaSopenharmony_ci all_hcs_files = sys.argv[1:] 2515f9996aaSopenharmony_ci parser = HcsParser() 2525f9996aaSopenharmony_ci for hcs_file in all_hcs_files: 2535f9996aaSopenharmony_ci parser.parse(hcs_file) 2545f9996aaSopenharmony_ci 2555f9996aaSopenharmony_ci sys.stdout.write(parser.get_hcs_info()) 2565f9996aaSopenharmony_ci sys.stdout.flush() 257