55# SPDX-License-Identifier: Apache-2.0
66
77"""
8- Script to scan Zephyr include directories and emit system call metadata
8+ Script to scan Zephyr include directories and emit system call and subsystem metadata
99
1010System calls require a great deal of boilerplate code in order to implement
1111completely. This script is the first step in the build system's process of
2626import os
2727import json
2828
29- api_regex = re .compile (r'''
29+ syscall_regex = re .compile (r'''
3030__syscall\s+ # __syscall attribute, must be first
3131([^(]+) # type and name of system call (split later)
3232[(] # Function opening parenthesis
3333([^)]*) # Arg list (split later)
3434[)] # Closing parenthesis
3535''' , re .MULTILINE | re .VERBOSE )
3636
37+ subsys_regex = re .compile (r'''
38+ __subsystem\s+ # __subsystem attribute, must be first
39+ struct\s+ # struct keyword is next
40+ ([^{]+) # name of subsystem
41+ [{] # Open curly bracket
42+ ''' , re .MULTILINE | re .VERBOSE )
3743
3844def analyze_headers (multiple_directories ):
39- ret = []
45+ syscall_ret = []
46+ subsys_ret = []
4047
4148 for base_path in multiple_directories :
4249 for root , dirs , files in os .walk (base_path , topdown = True ):
4350 dirs .sort ()
4451 files .sort ()
4552 for fn in files :
4653
47- # toolchain/common.h has the definition of __syscall which we
54+ # toolchain/common.h has the definitions of __syscall and __subsystem which we
4855 # don't want to trip over
4956 path = os .path .join (root , fn )
5057 if not fn .endswith (".h" ) or path .endswith (os .path .join (os .sep , 'toolchain' , 'common.h' )):
5158 continue
5259
5360 with open (path , "r" , encoding = "utf-8" ) as fp :
54- try :
55- result = [(mo .groups (), fn )
56- for mo in api_regex .finditer (fp .read ())]
57- except Exception :
58- sys .stderr .write ("While parsing %s\n " % fn )
59- raise
61+ contents = fp .read ()
62+
63+ try :
64+ syscall_result = [(mo .groups (), fn )
65+ for mo in syscall_regex .finditer (contents )]
66+ subsys_result = [mo .groups ()[0 ].strip ()
67+ for mo in subsys_regex .finditer (contents )]
68+ except Exception :
69+ sys .stderr .write ("While parsing %s\n " % fn )
70+ raise
6071
61- ret .extend (result )
72+ syscall_ret .extend (syscall_result )
73+ subsys_ret .extend (subsys_result )
6274
63- return ret
75+ return syscall_ret , subsys_ret
76+
77+
78+ def update_file_if_changed (path , new ):
79+ if os .path .exists (path ):
80+ with open (path , 'r' ) as fp :
81+ old = fp .read ()
82+
83+ if new != old :
84+ with open (path , 'w' ) as fp :
85+ fp .write (new )
86+ else :
87+ with open (path , 'w' ) as fp :
88+ fp .write (new )
6489
6590
6691def parse_args ():
@@ -76,34 +101,33 @@ def parse_args():
76101 parser .add_argument (
77102 "-j" , "--json-file" , required = True ,
78103 help = "Write system call prototype information as json to file" )
104+ parser .add_argument (
105+ "-s" , "--subsystem-file" , required = True ,
106+ help = "Write subsystem name information as json to file" )
79107 args = parser .parse_args ()
80108
81109
82110def main ():
83111 parse_args ()
84112
85- syscalls = analyze_headers (args .include )
113+ syscalls , subsys = analyze_headers (args .include )
114+
115+ # Only write json files if they don't exist or have changes since
116+ # they will force and incremental rebuild.
86117
87118 syscalls_in_json = json .dumps (
88119 syscalls ,
89120 indent = 4 ,
90121 sort_keys = True
91122 )
123+ update_file_if_changed (args .json_file , syscalls_in_json )
92124
93- # Check if the file already exists, and if there are no changes,
94- # don't touch it since that will force an incremental rebuild
95- path = args .json_file
96- new = syscalls_in_json
97- if os .path .exists (path ):
98- with open (path , 'r' ) as fp :
99- old = fp .read ()
100-
101- if new != old :
102- with open (path , 'w' ) as fp :
103- fp .write (new )
104- else :
105- with open (path , 'w' ) as fp :
106- fp .write (new )
125+ subsys_in_json = json .dumps (
126+ subsys ,
127+ indent = 4 ,
128+ sort_keys = True
129+ )
130+ update_file_if_changed (args .subsystem_file , subsys_in_json )
107131
108132
109133if __name__ == "__main__" :
0 commit comments