Subversion Repositories Kolibri OS

Rev

Rev 8825 | Rev 8835 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8834 Boppan 1
import re
8825 Boppan 2
import os
3
 
8834 Boppan 4
# Parameters
5
doxygen_src_path = 'docs/doxygen'
6
link_root = "http://websvn.kolibrios.org/filedetails.php?repname=Kolibri+OS&path=/kernel/trunk"
7
clean_generated_stuff = True # Remove generated doxygen files if True
8
dump_symbols = False
9
print_stats = False
8825 Boppan 10
 
11
# kernel_structure["filename"] = {
12
#   [ [],    # [0] Variables - [ line, name ]
13
#     [],    # [1] Macros - [ line, name ]
14
#     [],    # [2] Procedures - [ line, name ]
15
#     [],    # [3] Labels - [ line, name ]
16
#     [] ] } # [4] Structures - [ line, name ]
17
VARIABLES = 0
18
MACROS = 1
19
PROCEDURES = 2
20
LABELS = 3
21
STRUCTURES = 4
22
kernel_structure = {}
23
 
24
def get_declarations(asm_file_contents, asm_file_name):
25
	kernel_structure[asm_file_name] = [ [], [], [], [], [] ]
26
 
27
	variable_pattern = re.compile(r'^\s*([\w\.]+)\s+d[bwdq] .*')
28
	macro_pattern = re.compile(r'^\s*macro\s+([\w]+).*')
29
	proc_pattern = re.compile(r'^\s*proc\s+([\w\.]+).*')
30
	label_pattern = re.compile(r'^(?!;)\s*([\w\.]+):.*')
31
	struct_pattern = re.compile(r'^\s*struct\s+([\w]+).*')
32
 
33
	line_idx = 0
34
	lines = asm_file_contents.splitlines()
35
	while line_idx < len(lines):
36
		line = lines[line_idx]
37
 
38
		match = variable_pattern.findall(line)
39
		if len(match) > 0:
40
			var_name = match[0]
41
			#print(f"Variable '{var_name}' at {line_idx + 1}")
42
			kernel_structure[asm_file_name][VARIABLES].append([ line_idx + 1, var_name ])
43
			line_idx += 1
44
			continue
45
 
46
		match = macro_pattern.findall(line)
47
		if len(match) > 0:
48
			macro_name = match[0]
49
			kernel_structure[asm_file_name][MACROS].append([ line_idx + 1, macro_name ])
50
			end_of_macro = False
51
			while not end_of_macro:
52
				line = lines[line_idx]
53
				rbraces = re.finditer('}', line)
54
				for rbrace_match in rbraces:
55
					rbrace_idx = rbrace_match.start()
56
					if line[rbrace_idx - 1] != '\\':
57
						end_of_macro = True
58
				line_idx += 1
59
			continue
60
 
61
		match = proc_pattern.findall(line)
62
		if len(match) > 0:
63
			proc_name = match[0]
64
			kernel_structure[asm_file_name][PROCEDURES].append([ line_idx + 1, proc_name ])
65
			line_idx += 1
66
			continue
67
 
68
		match = label_pattern.findall(line)
69
		if len(match) > 0:
70
			label_name = match[0]
71
			# Don't count local labels
72
			if label_name[0] != '.':
73
				kernel_structure[asm_file_name][LABELS].append([ line_idx + 1, label_name ])
74
				line_idx += 1
75
				continue
76
 
77
		match = struct_pattern.findall(line)
78
		if len(match) > 0:
79
			struct_name = match[0]
80
			kernel_structure[asm_file_name][STRUCTURES].append([ line_idx + 1, struct_name ])
81
			end_of_struct = False
82
			while not end_of_struct:
83
				line = lines[line_idx]
84
				if re.match(r"^ends$", line) != None:
85
					end_of_struct = True
86
				line_idx += 1
87
			continue
88
 
89
		line_idx += 1
90
 
8834 Boppan 91
def handle_file(handled_files, asm_file_name, subdir = "."):
8825 Boppan 92
	print(f"Handling {asm_file_name}")
93
	handled_files.append(asm_file_name)
94
	try:
95
		asm_file_contents = open(asm_file_name, "r", encoding="utf-8").read()
96
	except:
97
		return
98
	get_declarations(asm_file_contents, asm_file_name)
99
	include_directive_pattern_1 = re.compile(r'include "(.*)"')
100
	include_directive_pattern_2 = re.compile(r'include \'(.*)\'')
101
	includes = include_directive_pattern_1.findall(asm_file_contents)
102
	includes += include_directive_pattern_2.findall(asm_file_contents)
103
	for include in includes:
104
		include = include.replace('\\', '/');
105
		full_path = subdir + '/' + include;
106
		if full_path not in handled_files:
107
			new_subdir = full_path.rsplit('/', 1)[0]
8834 Boppan 108
			handle_file(handled_files, full_path, new_subdir)
8825 Boppan 109
	return handled_files
110
 
111
kernel_files = []
112
 
8834 Boppan 113
handle_file(kernel_files, "./kernel.asm");
8825 Boppan 114
 
8834 Boppan 115
if dump_symbols:
116
	for source in kernel_structure:
117
		print(f"File: {source}")
118
		if len(kernel_structure[source][VARIABLES]) > 0:
119
			print(" Variables:")
120
			for variable in kernel_structure[source][VARIABLES]:
121
				print(f"  {variable[0]}: {variable[1]}")
122
		if len(kernel_structure[source][PROCEDURES]) > 0:
123
			print(" Procedures:")
124
			for procedure in kernel_structure[source][PROCEDURES]:
125
				print(f"  {procedure[0]}: {procedure[1]}")
126
		if len(kernel_structure[source][LABELS]) > 0:
127
			print(" Global labels:")
128
			for label in kernel_structure[source][LABELS]:
129
				print(f"  {label[0]}: {label[1]}")
130
		if len(kernel_structure[source][MACROS]) > 0:
131
			print(" Macroses:")
132
			for macro in kernel_structure[source][MACROS]:
133
				print(f"  {macro[0]}: {macro[1]}")
134
		if len(kernel_structure[source][STRUCTURES]) > 0:
135
			print(" Structures:")
136
			for struct in kernel_structure[source][STRUCTURES]:
137
				print(f"  {struct[0]}: {struct[1]}")
8825 Boppan 138
 
8834 Boppan 139
if print_stats:
140
	# Collect stats
141
	var_count = 0
142
	proc_count = 0
143
	label_count = 0
144
	macro_count = 0
145
	struct_count = 0
8825 Boppan 146
 
8834 Boppan 147
	for source in kernel_structure:
148
		var_count += len(kernel_structure[source][VARIABLES])
149
		proc_count += len(kernel_structure[source][PROCEDURES])
150
		label_count += len(kernel_structure[source][LABELS])
151
		macro_count += len(kernel_structure[source][MACROS])
152
		struct_count += len(kernel_structure[source][STRUCTURES])
8825 Boppan 153
 
8834 Boppan 154
	print(f"Variable count: {var_count}")
155
	print(f"Procedures count: {proc_count}")
156
	print(f"Global labels count: {label_count}")
157
	print(f"Macroses count: {macro_count}")
158
	print(f"Structures count: {struct_count}")
8825 Boppan 159
 
8834 Boppan 160
print(f"Writing doumented sources to {doxygen_src_path}")
161
 
162
created_files = []
163
 
164
def write_variable(source, line, name, type = "int", brief = "Undocumented",
165
	               init = None):
166
	source = source.replace("./", "")
167
	full_path = doxygen_src_path + '/' + source
168
	# Remove the file on first access if it was created by previous generation
169
	if full_path not in created_files:
170
		if os.path.isfile(full_path):
171
			os.remove(full_path)
172
		created_files.append(full_path)
173
	# Only remove the file on 'clean_generated_stuff' flag (removed above, just return)
174
	if clean_generated_stuff: return
175
	# Create directories need for the file
176
	os.makedirs(os.path.dirname(full_path), exist_ok=True)
177
	name = name.replace(".", "_")
178
	f = open(full_path, "a")
179
	f.write(f"/**\n")
180
	f.write(f" * @brief {brief}\n")
181
	f.write(f" * @par Initial value\n")
182
	f.write(f" * {init}\n")
183
	f.write(f" * @par Source\n")
184
	f.write(f" * {source}:{line}\n")
185
	f.write(f" */\n")
186
	if init == None:
187
		set_init = ""
188
	else:
189
		set_init = f" = {init}"
190
	f.write(f"{type} {name}{set_init};\n\n")
191
	f.close()
192
 
193
i = 1
194
for source in kernel_structure:
195
	# Print progress: current/total
196
	print(f"{i}/{len(kernel_structure)} Writing {source}")
197
	# Write variables doxygen of the source file
198
	if len(kernel_structure[source][VARIABLES]) > 0:
199
		for variable in kernel_structure[source][VARIABLES]:
200
			write_variable(source, variable[0], variable[1])
201
	i += 1