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> |