Subversion Repositories Kolibri OS

Rev

Rev 8834 | Rev 8841 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. import re
  2. import os
  3.  
  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 = False # Remove generated doxygen files if True
  8. dump_symbols = False
  9. print_stats = False
  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.  
  91. def handle_file(handled_files, asm_file_name, subdir = "."):
  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]
  108.                         handle_file(handled_files, full_path, new_subdir)
  109.         return handled_files
  110.  
  111. kernel_files = []
  112.  
  113. handle_file(kernel_files, "./kernel.asm");
  114.  
  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]}")
  138.  
  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
  146.  
  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])
  153.  
  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}")
  159.  
  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" * <a href='{link_root}/{source}#line-{line}'>{source}:{line}</a>\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
  202.