10
10
System calls require a great deal of boilerplate code in order to implement
11
11
completely. This script is the first step in the build system's process of
12
12
auto-generating this code by doing a text scan of directories containing
13
- header files, and building up a database of system calls and their
13
+ C or header files, and building up a database of system calls and their
14
14
function call prototypes. This information is emitted to a generated
15
15
JSON file for further processing.
16
16
17
+ This script also scans for struct definitions such as __subsystem and
18
+ __net_socket, emitting a JSON dictionary mapping tags to all the struct
19
+ declarations found that were tagged with them.
20
+
17
21
If the output JSON file already exists, its contents are checked against
18
22
what information this script would have outputted; if the result is that the
19
23
file would be unchanged, it is not modified to prevent unnecessary
26
30
import os
27
31
import json
28
32
33
+ regex_flags = re .MULTILINE | re .VERBOSE
34
+
29
35
syscall_regex = re .compile (r'''
30
36
__syscall\s+ # __syscall attribute, must be first
31
37
([^(]+) # type and name of system call (split later)
32
38
[(] # Function opening parenthesis
33
39
([^)]*) # Arg list (split later)
34
40
[)] # Closing parenthesis
35
- ''' , re . MULTILINE | re . VERBOSE )
41
+ ''' , regex_flags )
36
42
37
- subsys_regex = re .compile (r'''
38
- __subsystem\s+ # __subsystem attribute, must be first
43
+ struct_tags = ["__subsystem" ]
44
+
45
+ tagged_struct_decl_template = r'''
46
+ %s\s+ # tag, must be first
39
47
struct\s+ # struct keyword is next
40
48
([^{]+) # name of subsystem
41
49
[{] # Open curly bracket
42
- ''' , re .MULTILINE | re .VERBOSE )
50
+ '''
51
+
52
+ def tagged_struct_update (target_list , tag , contents ):
53
+ regex = re .compile (tagged_struct_decl_template % tag , regex_flags )
54
+ items = [mo .groups ()[0 ].strip () for mo in regex .finditer (contents )]
55
+ target_list .extend (items )
56
+
43
57
44
58
def analyze_headers (multiple_directories ):
45
59
syscall_ret = []
46
- subsys_ret = []
60
+ tagged_ret = {}
61
+
62
+ for tag in struct_tags :
63
+ tagged_ret [tag ] = []
47
64
48
65
for base_path in multiple_directories :
49
66
for root , dirs , files in os .walk (base_path , topdown = True ):
50
67
dirs .sort ()
51
68
files .sort ()
52
69
for fn in files :
53
70
54
- # toolchain/common.h has the definitions of __syscall and __subsystem which we
71
+ # toolchain/common.h has the definitions of these tagswhich we
55
72
# don't want to trip over
56
73
path = os .path .join (root , fn )
57
- if not fn .endswith (".h" ) or path .endswith (os .path .join (os .sep , 'toolchain' , 'common.h' )):
74
+ if (not (path .endswith (".h" ) or path .endswith (".c" )) or
75
+ path .endswith (os .path .join (os .sep , 'toolchain' ,
76
+ 'common.h' ))):
58
77
continue
59
78
60
79
with open (path , "r" , encoding = "utf-8" ) as fp :
@@ -63,16 +82,15 @@ def analyze_headers(multiple_directories):
63
82
try :
64
83
syscall_result = [(mo .groups (), fn )
65
84
for mo in syscall_regex .finditer (contents )]
66
- subsys_result = [ mo . groups ()[ 0 ]. strip ()
67
- for mo in subsys_regex . finditer ( contents )]
85
+ for tag in struct_tags :
86
+ tagged_struct_update ( tagged_ret [ tag ], tag , contents )
68
87
except Exception :
69
88
sys .stderr .write ("While parsing %s\n " % fn )
70
89
raise
71
90
72
91
syscall_ret .extend (syscall_result )
73
- subsys_ret .extend (subsys_result )
74
92
75
- return syscall_ret , subsys_ret
93
+ return syscall_ret , tagged_ret
76
94
77
95
78
96
def update_file_if_changed (path , new ):
@@ -102,18 +120,19 @@ def parse_args():
102
120
"-j" , "--json-file" , required = True ,
103
121
help = "Write system call prototype information as json to file" )
104
122
parser .add_argument (
105
- "-s" , "--subsystem-file" , required = True ,
106
- help = "Write subsystem name information as json to file" )
123
+ "-t" , "--tag-struct-file" , required = True ,
124
+ help = "Write tagged struct name information as json to file" )
125
+
107
126
args = parser .parse_args ()
108
127
109
128
110
129
def main ():
111
130
parse_args ()
112
131
113
- syscalls , subsys = analyze_headers (args .include )
132
+ syscalls , tagged = analyze_headers (args .include )
114
133
115
134
# Only write json files if they don't exist or have changes since
116
- # they will force and incremental rebuild.
135
+ # they will force an incremental rebuild.
117
136
118
137
syscalls_in_json = json .dumps (
119
138
syscalls ,
@@ -122,12 +141,12 @@ def main():
122
141
)
123
142
update_file_if_changed (args .json_file , syscalls_in_json )
124
143
125
- subsys_in_json = json .dumps (
126
- subsys ,
144
+ tagged_struct_in_json = json .dumps (
145
+ tagged ,
127
146
indent = 4 ,
128
147
sort_keys = True
129
148
)
130
- update_file_if_changed (args .subsystem_file , subsys_in_json )
149
+ update_file_if_changed (args .tag_struct_file , tagged_struct_in_json )
131
150
132
151
133
152
if __name__ == "__main__" :
0 commit comments