From c867c5020b759688f74b425a532a18e22da41688 Mon Sep 17 00:00:00 2001 From: "Magomed Kostoev (mkostoevr)" Date: Tue, 7 Dec 2021 15:48:11 +0000 Subject: [PATCH] [ASMXYGEN] Convert indentation to spaces git-svn-id: svn://kolibrios.org@9407 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/asmxygen.py | 1718 +++++++++++++++++++------------------- 1 file changed, 859 insertions(+), 859 deletions(-) diff --git a/kernel/trunk/asmxygen.py b/kernel/trunk/asmxygen.py index da7c657ba1..da21f33207 100644 --- a/kernel/trunk/asmxygen.py +++ b/kernel/trunk/asmxygen.py @@ -156,974 +156,974 @@ keywords = [ ] fasm_types = [ - "db", "rb", - "dw", "rw", - "dd", "rd", - "dp", "rp", - "df", "rf", - "dq", "rq", - "dt", "rt", - "du", + "db", "rb", + "dw", "rw", + "dd", "rd", + "dp", "rp", + "df", "rf", + "dq", "rq", + "dt", "rt", + "du", ] # Add kind flag to identifier in id2kind def id_add_kind(identifier, kind): - if identifier not in id2kind: - id2kind[identifier] = '' - id2kind[identifier] += kind + if identifier not in id2kind: + id2kind[identifier] = '' + id2kind[identifier] += kind # Remove kind flag of identifier in id2kind def id_remove_kind(identifier, kind): - if identifier in id2kind: - if kind in id2kind[identifier]: - id2kind[identifier] = id2kind[identifier].replace(kind, '') + if identifier in id2kind: + if kind in id2kind[identifier]: + id2kind[identifier] = id2kind[identifier].replace(kind, '') # Get kind of an identifier def id_get_kind(identifier): - if identifier in id2kind: - return id2kind[identifier] - else: - return '' + if identifier in id2kind: + return id2kind[identifier] + else: + return '' class LegacyAsmReader: - def __init__(self, file): - self.file = file - self.lines = open(file, "r", encoding="utf-8").readlines() - self.line_idx = 0 - self.i = 0 + def __init__(self, file): + self.file = file + self.lines = open(file, "r", encoding="utf-8").readlines() + self.line_idx = 0 + self.i = 0 - def currline(self): - return self.lines[self.line_idx] + def currline(self): + return self.lines[self.line_idx] - def curr(self): - try: return self.lines[self.line_idx][self.i] - except: return '' + def curr(self): + try: return self.lines[self.line_idx][self.i] + except: return '' - def step(self): - c = self.curr() - self.i += 1 - # Wrap the line if '\\' followed by whitespaces and/or comment - while self.curr() == '\\': - i_of_backslash = self.i - self.i += 1 - while self.curr().isspace(): - self.i += 1 - if self.curr() == ';' or self.curr() == '': - self.line_idx += 1 - self.i = 0 - else: - # There's something other than a comment after the backslash - # So don't interpret the backslash as a line wrap - self.i = i_of_backslash - break - return c + def step(self): + c = self.curr() + self.i += 1 + # Wrap the line if '\\' followed by whitespaces and/or comment + while self.curr() == '\\': + i_of_backslash = self.i + self.i += 1 + while self.curr().isspace(): + self.i += 1 + if self.curr() == ';' or self.curr() == '': + self.line_idx += 1 + self.i = 0 + else: + # There's something other than a comment after the backslash + # So don't interpret the backslash as a line wrap + self.i = i_of_backslash + break + return c - def nextline(self): - c = self.curr() - while c != '': - c = self.step() - self.line_idx += 1 - self.i = 0 + def nextline(self): + c = self.curr() + while c != '': + c = self.step() + self.line_idx += 1 + self.i = 0 - def no_lines(self): - if self.line_idx >= len(self.lines): - return True - return False + def no_lines(self): + if self.line_idx >= len(self.lines): + return True + return False - def location(self): - return f"{self.file}:{self.line_idx + 1}" + def location(self): + return f"{self.file}:{self.line_idx + 1}" - def skip_spaces(self): - while self.curr().isspace(): - self.step() + def skip_spaces(self): + while self.curr().isspace(): + self.step() class AsmReaderRecognizingStrings(LegacyAsmReader): - def __init__(self, file): - super().__init__(file) - self.in_string = None - self.should_recognize_strings = True + def __init__(self, file): + super().__init__(file) + self.in_string = None + self.should_recognize_strings = True - def step(self): - c = super().step() - if self.should_recognize_strings and (c == '"' or c == "'"): - # If just now we was at the double or single quotation mark - # and we aren't in a string yet - # then say "we are in a string openned with this quotation mark now" - if self.in_string == None: - self.in_string = c - # If just now we was at the double or single quotation mark - # and we are in the string entered with the same quotation mark - # then say "we aren't in a string anymore" - elif self.in_string == c: - self.in_string = None - return c + def step(self): + c = super().step() + if self.should_recognize_strings and (c == '"' or c == "'"): + # If just now we was at the double or single quotation mark + # and we aren't in a string yet + # then say "we are in a string openned with this quotation mark now" + if self.in_string == None: + self.in_string = c + # If just now we was at the double or single quotation mark + # and we are in the string entered with the same quotation mark + # then say "we aren't in a string anymore" + elif self.in_string == c: + self.in_string = None + return c class AsmReaderReadingComments(AsmReaderRecognizingStrings): - def __init__(self, file): - super().__init__(file) - self.status = dict() - self.status_reset() - self.comment = '' + def __init__(self, file): + super().__init__(file) + self.status = dict() + self.status_reset() + self.comment = '' - def status_reset(self): - # If the line has non-comment code - self.status_has_code = False - # If the line has a comment at the end - self.status_has_comment = False - # Let it recognize strings further, we are definitely out of a comment - self.should_recognize_strings = True + def status_reset(self): + # If the line has non-comment code + self.status_has_code = False + # If the line has a comment at the end + self.status_has_comment = False + # Let it recognize strings further, we are definitely out of a comment + self.should_recognize_strings = True - def status_set_has_comment(self): - self.status_has_comment = True - # Don't let it recognize strings cause we are in a comment now - self.should_recognize_strings = False + def status_set_has_comment(self): + self.status_has_comment = True + # Don't let it recognize strings cause we are in a comment now + self.should_recognize_strings = False - def status_set_has_code(self): - self.status_has_code = True + def status_set_has_code(self): + self.status_has_code = True - def update_status(self): - # If we aren't in a comment and we aren't in a string - say we are now in a comment if ';' met - if not self.status_has_comment and not self.in_string and self.curr() == ';': - self.status_set_has_comment() - # Else if we are in a comment - collect the comment - elif self.status_has_comment: - self.comment += self.curr() - # Else if there's some non-whitespace character out of a comment - # then the line has code - elif not self.status_has_comment and not self.curr().isspace(): - self.status_set_has_code() + def update_status(self): + # If we aren't in a comment and we aren't in a string - say we are now in a comment if ';' met + if not self.status_has_comment and not self.in_string and self.curr() == ';': + self.status_set_has_comment() + # Else if we are in a comment - collect the comment + elif self.status_has_comment: + self.comment += self.curr() + # Else if there's some non-whitespace character out of a comment + # then the line has code + elif not self.status_has_comment and not self.curr().isspace(): + self.status_set_has_code() - def step(self): - # Get to the next character - c = super().step() - # Update status of the line according to the next character - self.update_status() - return c + def step(self): + # Get to the next character + c = super().step() + # Update status of the line according to the next character + self.update_status() + return c - def nextline(self): - prev_line = self.currline() - super().nextline() - # If the line we leave was not a comment-only line - # then forget the collected comment - # Otherwise the collected comment should be complemented by comment from next line in step() - if self.status_has_code: - # But we should preserve comment for the next line - # If previous line set align (cause many functions re documented - # right before align set, not before their labels) - if not prev_line.startswith("align "): - self.comment = '' - # Reset the line status (now it's the status of the new line) - self.status_reset() - # Set new status for this line according to the first character in the line - self.update_status() + def nextline(self): + prev_line = self.currline() + super().nextline() + # If the line we leave was not a comment-only line + # then forget the collected comment + # Otherwise the collected comment should be complemented by comment from next line in step() + if self.status_has_code: + # But we should preserve comment for the next line + # If previous line set align (cause many functions re documented + # right before align set, not before their labels) + if not prev_line.startswith("align "): + self.comment = '' + # Reset the line status (now it's the status of the new line) + self.status_reset() + # Set new status for this line according to the first character in the line + self.update_status() class AsmReaderFetchingIdentifiers(AsmReaderReadingComments): - def __init__(self, file): - super().__init__(file) + def __init__(self, file): + super().__init__(file) - def fetch_identifier(self): - self.skip_spaces() - result = '' - while is_id(self.curr()): - result += self.step() - return result + def fetch_identifier(self): + self.skip_spaces() + result = '' + while is_id(self.curr()): + result += self.step() + return result class AsmReader(AsmReaderFetchingIdentifiers): - def __init__(self, file): - super().__init__(file) + def __init__(self, file): + super().__init__(file) def append_file(full_path, contents): - if debug_mode: - if full_path not in output_files: - output_files[full_path] = "" - output_files[full_path] += contents - else: - f = open(full_path, "a") - f.write(contents) - f.close() + if debug_mode: + if full_path not in output_files: + output_files[full_path] = "" + output_files[full_path] += contents + else: + f = open(full_path, "a") + f.write(contents) + f.close() class AsmElement: - def __init__(self, location, name, comment): - global warnings + def __init__(self, location, name, comment): + global warnings - # If the element was constructed during this execution then the element is new - self.new = True - self.location = location - self.file = self.location.split(':')[0].replace('\\', '/') - self.line = self.location.split(':')[1] - self.name = name - self.comment = comment + # If the element was constructed during this execution then the element is new + self.new = True + self.location = location + self.file = self.location.split(':')[0].replace('\\', '/') + self.line = self.location.split(':')[1] + self.name = name + self.comment = comment - if self.comment == '': - warnings += f'{self.location}: Undocumented element\n' + if self.comment == '': + warnings += f'{self.location}: Undocumented element\n' - def dump(self): - print(f"\n{self.location}: {self.name}") - print(f"{self.comment}") + def dump(self): + print(f"\n{self.location}: {self.name}") + print(f"{self.comment}") - def emit(self, dest, doxycomment = '', declaration = ''): - # Do not emit anything if the symbol is marked as hidden in its comment - if '@dont_give_a_doxygen' in self.comment: - return + def emit(self, dest, doxycomment = '', declaration = ''): + # Do not emit anything if the symbol is marked as hidden in its comment + if '@dont_give_a_doxygen' in self.comment: + return - global warnings - # Redefine default declaration - if declaration == '': - declaration = f'#define {self.name}' - # Check doxycomment - if not doxycomment.endswith('\n'): - doxycomment += '\n' - if doxycomment.split('@brief ')[1][0].islower(): - warnings += f"{self.location}: Brief comment starting from lowercase\n" - # Build contents to emit - contents = '' - contents += '/**\n' - contents += doxycomment - contents += (f"@par Source\n" + - f"{self.file}:{self.line}\n") - contents += '*/\n' - contents += declaration - contents += '\n\n' - # Get path to file to emit this - full_path = dest + '/' + self.file - # Remove the file on first access if it was created by previous generation - if full_path not in created_files: - if os.path.isfile(full_path): - os.remove(full_path) - created_files.append(full_path) - # Create directories need for the file - os.makedirs(os.path.dirname(full_path), exist_ok=True) - contents = ''.join([i if ord(i) < 128 else '?' for i in contents]) + global warnings + # Redefine default declaration + if declaration == '': + declaration = f'#define {self.name}' + # Check doxycomment + if not doxycomment.endswith('\n'): + doxycomment += '\n' + if doxycomment.split('@brief ')[1][0].islower(): + warnings += f"{self.location}: Brief comment starting from lowercase\n" + # Build contents to emit + contents = '' + contents += '/**\n' + contents += doxycomment + contents += (f"@par Source\n" + + f"{self.file}:{self.line}\n") + contents += '*/\n' + contents += declaration + contents += '\n\n' + # Get path to file to emit this + full_path = dest + '/' + self.file + # Remove the file on first access if it was created by previous generation + if full_path not in created_files: + if os.path.isfile(full_path): + os.remove(full_path) + created_files.append(full_path) + # Create directories need for the file + os.makedirs(os.path.dirname(full_path), exist_ok=True) + contents = ''.join([i if ord(i) < 128 else '?' for i in contents]) - append_file(full_path, contents) + append_file(full_path, contents) class AsmVariable(AsmElement): - def __init__(self, location, name, comment, type, init): - super().__init__(location, name, comment) - self.type = type - self.init = init + def __init__(self, location, name, comment, type, init): + super().__init__(location, name, comment) + self.type = type + self.init = init - def dump(self): - super().dump() - print(f"(Variable)\n---") + def dump(self): + super().dump() + print(f"(Variable)\n---") - def emit(self, dest): - # Build doxycomment specific for the variable - doxycomment = '' - doxycomment += self.comment - if '@brief' not in doxycomment: - doxycomment = '@brief ' + doxycomment - doxycomment += (f"@par Initial value\n" + - f"{self.init}\n") - # Build the declaration - name = self.name.replace(".", "_") - var_type = self.type.replace(".", "_") - declaration = f"{var_type} {name};" - # Emit this - super().emit(dest, doxycomment, declaration) + def emit(self, dest): + # Build doxycomment specific for the variable + doxycomment = '' + doxycomment += self.comment + if '@brief' not in doxycomment: + doxycomment = '@brief ' + doxycomment + doxycomment += (f"@par Initial value\n" + + f"{self.init}\n") + # Build the declaration + name = self.name.replace(".", "_") + var_type = self.type.replace(".", "_") + declaration = f"{var_type} {name};" + # Emit this + super().emit(dest, doxycomment, declaration) class AsmFunction(AsmElement): - def __init__(self, location, name, comment, calling_convention, args, used_regs): - super().__init__(location, name, comment) - self.calling_convention = calling_convention - self.args = args - self.used_regs = used_regs + def __init__(self, location, name, comment, calling_convention, args, used_regs): + super().__init__(location, name, comment) + self.calling_convention = calling_convention + self.args = args + self.used_regs = used_regs - def dump(self): - super().dump() - print(f"(Function)\n---") + def dump(self): + super().dump() + print(f"(Function)\n---") - def emit(self, dest): - # Build doxycomment specific for the variable - doxycomment = '' - doxycomment += self.comment - if '@brief' not in doxycomment: - doxycomment = '@brief ' + doxycomment - # If there was no arguments, maybe that's just a label - # then parse parameters from its comment - if len(self.args) == 0 and '@param' in self.comment: - i = 0 - while '@param' in self.comment[i:]: - i = self.comment.index('@param', i) - # Skip '@param' - i += len('@param') - # Skip spaces after '@param' - while self.comment[i].isspace(): - i += 1 - # Get the parameter name - name = '' - while is_id(self.comment[i]): - name += self.comment[i] - i += 1 - # Save the parameter - self.args.append((name, 'arg_t')) - # Build the arg list for declaration - arg_list = '(' - if len(self.args) > 0: - argc = 0 - for arg in self.args: - if argc != 0: - arg_list += ", " - arg_list += f"{arg[1]} {arg[0]}" - argc += 1 - arg_list += ')' - # Build the declaration - name = self.name.replace(".", "_") - declaration = f"void {name}{arg_list};" - # Emit this - super().emit(dest, doxycomment, declaration) + def emit(self, dest): + # Build doxycomment specific for the variable + doxycomment = '' + doxycomment += self.comment + if '@brief' not in doxycomment: + doxycomment = '@brief ' + doxycomment + # If there was no arguments, maybe that's just a label + # then parse parameters from its comment + if len(self.args) == 0 and '@param' in self.comment: + i = 0 + while '@param' in self.comment[i:]: + i = self.comment.index('@param', i) + # Skip '@param' + i += len('@param') + # Skip spaces after '@param' + while self.comment[i].isspace(): + i += 1 + # Get the parameter name + name = '' + while is_id(self.comment[i]): + name += self.comment[i] + i += 1 + # Save the parameter + self.args.append((name, 'arg_t')) + # Build the arg list for declaration + arg_list = '(' + if len(self.args) > 0: + argc = 0 + for arg in self.args: + if argc != 0: + arg_list += ", " + arg_list += f"{arg[1]} {arg[0]}" + argc += 1 + arg_list += ')' + # Build the declaration + name = self.name.replace(".", "_") + declaration = f"void {name}{arg_list};" + # Emit this + super().emit(dest, doxycomment, declaration) class AsmLabel(AsmElement): - def __init__(self, location, name, comment): - super().__init__(location, name, comment) + def __init__(self, location, name, comment): + super().__init__(location, name, comment) - def dump(self): - super().dump() - print(f"(Label)\n---") + def dump(self): + super().dump() + print(f"(Label)\n---") - def emit(self, dest): - # Build doxycomment specific for the variable - doxycomment = '' - doxycomment += self.comment - if '@brief' not in doxycomment: - doxycomment = '@brief ' + doxycomment - # Build the declaration - name = self.name.replace(".", "_") - declaration = f"label {name};" - # Emit this - super().emit(dest, doxycomment, declaration) + def emit(self, dest): + # Build doxycomment specific for the variable + doxycomment = '' + doxycomment += self.comment + if '@brief' not in doxycomment: + doxycomment = '@brief ' + doxycomment + # Build the declaration + name = self.name.replace(".", "_") + declaration = f"label {name};" + # Emit this + super().emit(dest, doxycomment, declaration) class AsmMacro(AsmElement): - def __init__(self, location, name, comment, args): - super().__init__(location, name, comment) - self.args = args + def __init__(self, location, name, comment, args): + super().__init__(location, name, comment) + self.args = args - def dump(self): - super().dump() - print(f"(Macro)\n---") + def dump(self): + super().dump() + print(f"(Macro)\n---") - def emit(self, dest): - # Construct arg list without '['s, ']'s and '*'s - args = [arg for arg in self.args if arg not in "[]*"] - # Construct C-like arg list - arg_list = "" - if len(args) > 0: - arg_list += '(' - argc = 0 - for arg in args: - if argc != 0: - arg_list += ", " - arg_list += arg - argc += 1 - arg_list += ')' - # Build doxycomment - doxycomment = '' - doxycomment += self.comment - if '@brief' not in doxycomment: - doxycomment = '@brief ' + doxycomment - # Build declaration - declaration = f"#define {self.name}{arg_list}" - # Emit this - super().emit(dest, doxycomment, declaration) + def emit(self, dest): + # Construct arg list without '['s, ']'s and '*'s + args = [arg for arg in self.args if arg not in "[]*"] + # Construct C-like arg list + arg_list = "" + if len(args) > 0: + arg_list += '(' + argc = 0 + for arg in args: + if argc != 0: + arg_list += ", " + arg_list += arg + argc += 1 + arg_list += ')' + # Build doxycomment + doxycomment = '' + doxycomment += self.comment + if '@brief' not in doxycomment: + doxycomment = '@brief ' + doxycomment + # Build declaration + declaration = f"#define {self.name}{arg_list}" + # Emit this + super().emit(dest, doxycomment, declaration) class AsmStruct(AsmElement): - def __init__(self, location, name, comment, members): - super().__init__(location, name, comment) - self.members = members + def __init__(self, location, name, comment, members): + super().__init__(location, name, comment) + self.members = members - def dump(self): - super().dump() - print(f"(Struct)\n---") + def dump(self): + super().dump() + print(f"(Struct)\n---") - def emit(self, dest): - # Build doxycomment - doxycomment = '' - doxycomment += self.comment - if '@brief' not in doxycomment: - doxycomment = '@brief ' + doxycomment - doxycomment += '\n' - # Build declaration - declaration = f"struct {self.name}" + " {\n" - for member in self.members: - if type(member) == AsmVariable: - declaration += f'\t{member.type} {member.name}; /**< {member.comment} */\n' - declaration += '};' - # Emit this - super().emit(dest, doxycomment, declaration) + def emit(self, dest): + # Build doxycomment + doxycomment = '' + doxycomment += self.comment + if '@brief' not in doxycomment: + doxycomment = '@brief ' + doxycomment + doxycomment += '\n' + # Build declaration + declaration = f"struct {self.name}" + " {\n" + for member in self.members: + if type(member) == AsmVariable: + declaration += f'\t{member.type} {member.name}; /**< {member.comment} */\n' + declaration += '};' + # Emit this + super().emit(dest, doxycomment, declaration) class AsmUnion(AsmElement): - def __init__(self, location, name, comment, members): - super().__init__(location, name, comment) - self.members = members + def __init__(self, location, name, comment, members): + super().__init__(location, name, comment) + self.members = members - def dump(self): - super().dump() - print(f"(Union)\n---") + def dump(self): + super().dump() + print(f"(Union)\n---") - def emit(self, dest): - # Build doxycomment - doxycomment = '' - doxycomment += self.comment - if '@brief' not in doxycomment: - doxycomment = '@brief ' + doxycomment - # Build declaration - declaration = f"union {self.name}" + " {};" - # Emit this - super().emit(dest, doxycomment, declaration) + def emit(self, dest): + # Build doxycomment + doxycomment = '' + doxycomment += self.comment + if '@brief' not in doxycomment: + doxycomment = '@brief ' + doxycomment + # Build declaration + declaration = f"union {self.name}" + " {};" + # Emit this + super().emit(dest, doxycomment, declaration) class VariableNameIsMacroName: - def __init__(self, name): - self.name = name + def __init__(self, name): + self.name = name def is_id(c): - return c.isprintable() and c not in "+-/*=<>()[]{};:,|&~#`'\" \n\r\t\v" + return c.isprintable() and c not in "+-/*=<>()[]{};:,|&~#`'\" \n\r\t\v" def is_starts_as_id(s): - return not s[0].isdigit() + return not s[0].isdigit() def parse_after_macro(r): - location = r.location() + location = r.location() - # Skip spaces after the "macro" keyword - r.skip_spaces() - # Read macro name - name = "" - while is_id(r.curr()) or r.curr() == '#': - name += r.step() - # Skip spaces after macro name - r.skip_spaces() - # Find all arguments - args = [] - arg = '' - while r.curr() and r.curr() != ';' and r.curr() != '{': - # Collect identifier - if is_id(r.curr()): - arg += r.step() - # Save the collected identifier - elif r.curr() == ',': - args.append(arg) - arg = '' - r.step() - # Just push the '[' - elif r.curr() == '[': - args.append(r.step()) - # Just push the identifier and get ']' ready to be pushed on next comma - elif r.curr() == ']': - args.append(arg) - arg = r.step() - # Just push the identifier and get '*' ready to be pushed on next comma - elif r.curr() == '*': - args.append(arg) - arg = r.step() - # Just skip whitespaces - elif r.curr().isspace(): - r.step() - # Something unexpected - else: - raise Exception(f"Unexpected symbol '{r.curr()}' at index #{r.i} " + - f"in the macro declaration at {location} " + - f"(line: {r.lines[r.line_idx]})\n''") - # Append the last argument - if arg != '': - args.append(arg) - # Skip t spaces after the argument list - r.skip_spaces() - # Get a comment if it is: read till the end of the line and get the comment from the reader - while r.curr() != '': - r.step() - comment = r.comment - # Find end of the macro - prev = '' - while True: - if r.curr() == '}' and prev != '\\': - break - elif r.curr() == '': - prev = '' - r.nextline() - continue - prev = r.step() - # Build the output - return AsmMacro(location, name, comment, args) + # Skip spaces after the "macro" keyword + r.skip_spaces() + # Read macro name + name = "" + while is_id(r.curr()) or r.curr() == '#': + name += r.step() + # Skip spaces after macro name + r.skip_spaces() + # Find all arguments + args = [] + arg = '' + while r.curr() and r.curr() != ';' and r.curr() != '{': + # Collect identifier + if is_id(r.curr()): + arg += r.step() + # Save the collected identifier + elif r.curr() == ',': + args.append(arg) + arg = '' + r.step() + # Just push the '[' + elif r.curr() == '[': + args.append(r.step()) + # Just push the identifier and get ']' ready to be pushed on next comma + elif r.curr() == ']': + args.append(arg) + arg = r.step() + # Just push the identifier and get '*' ready to be pushed on next comma + elif r.curr() == '*': + args.append(arg) + arg = r.step() + # Just skip whitespaces + elif r.curr().isspace(): + r.step() + # Something unexpected + else: + raise Exception(f"Unexpected symbol '{r.curr()}' at index #{r.i} " + + f"in the macro declaration at {location} " + + f"(line: {r.lines[r.line_idx]})\n''") + # Append the last argument + if arg != '': + args.append(arg) + # Skip t spaces after the argument list + r.skip_spaces() + # Get a comment if it is: read till the end of the line and get the comment from the reader + while r.curr() != '': + r.step() + comment = r.comment + # Find end of the macro + prev = '' + while True: + if r.curr() == '}' and prev != '\\': + break + elif r.curr() == '': + prev = '' + r.nextline() + continue + prev = r.step() + # Build the output + return AsmMacro(location, name, comment, args) def parse_variable(r, first_word = None): - global warnings - location = r.location() + global warnings + location = r.location() - # Skip spaces before variable name - r.skip_spaces() - # Get variable name - name = "" - # Read it if it was not supplied - if first_word == None: - while is_id(r.curr()): - name += r.step() - # Or use the supplied one instead - else: - name = first_word - # Check the name - # If it's 0 len, that means threr's something else than an identifier at the beginning - if len(name) == 0: - return None - # If it starts from digit or othervice illegally it's illegal - if not is_starts_as_id(name): - return None - # Get kind of the identifier from id2kind table - kind = id_get_kind(name) - # If it's a keyword, that's not a variable declaration - if ID_KIND_KEYWORD in kind: - return None - # If it's a macro name, that's not a variable declaration - if ID_KIND_MACRO_NAME in kind: - return VariableNameIsMacroName(name) - # If it's a datatype or a structure name that's not a variable declaration: that's just a data - # don't document just a data for now - if ID_KIND_STRUCT_NAME in kind or ID_KIND_FASM_TYPE in kind: - return None - # Skip spaces before type name - r.skip_spaces() - # Read type name - var_type = "" - while is_id(r.curr()): - var_type += r.step() - # Check the type name - if len(var_type) == 0: - # If there's no type identifier after the name - # maybe the name is something meaningful for the next parser - # return it - return name - # If it starts from digit or othervice illegally it's illegal - if not is_starts_as_id(var_type): - return None - # Get kind of type identifier - type_kind = id_get_kind(var_type) - # If it's a keyword, that's not a variable declaration - # return the two words of the lexical structure - if ID_KIND_KEYWORD in type_kind: - return (name, var_type) - # Skip spaces before the value - r.skip_spaces() - # Read the value until the comment or end of the line - value = "" - while r.curr() != ';' and r.curr() != '' and r.curr() != '\n': - value += r.step() - # Skip spaces after the value - r.skip_spaces() - # Read till end of the line to get a comment from the reader - while r.curr() != '': - r.step() - # Build the result - return AsmVariable(location, name, r.comment, var_type, value) + # Skip spaces before variable name + r.skip_spaces() + # Get variable name + name = "" + # Read it if it was not supplied + if first_word == None: + while is_id(r.curr()): + name += r.step() + # Or use the supplied one instead + else: + name = first_word + # Check the name + # If it's 0 len, that means threr's something else than an identifier at the beginning + if len(name) == 0: + return None + # If it starts from digit or othervice illegally it's illegal + if not is_starts_as_id(name): + return None + # Get kind of the identifier from id2kind table + kind = id_get_kind(name) + # If it's a keyword, that's not a variable declaration + if ID_KIND_KEYWORD in kind: + return None + # If it's a macro name, that's not a variable declaration + if ID_KIND_MACRO_NAME in kind: + return VariableNameIsMacroName(name) + # If it's a datatype or a structure name that's not a variable declaration: that's just a data + # don't document just a data for now + if ID_KIND_STRUCT_NAME in kind or ID_KIND_FASM_TYPE in kind: + return None + # Skip spaces before type name + r.skip_spaces() + # Read type name + var_type = "" + while is_id(r.curr()): + var_type += r.step() + # Check the type name + if len(var_type) == 0: + # If there's no type identifier after the name + # maybe the name is something meaningful for the next parser + # return it + return name + # If it starts from digit or othervice illegally it's illegal + if not is_starts_as_id(var_type): + return None + # Get kind of type identifier + type_kind = id_get_kind(var_type) + # If it's a keyword, that's not a variable declaration + # return the two words of the lexical structure + if ID_KIND_KEYWORD in type_kind: + return (name, var_type) + # Skip spaces before the value + r.skip_spaces() + # Read the value until the comment or end of the line + value = "" + while r.curr() != ';' and r.curr() != '' and r.curr() != '\n': + value += r.step() + # Skip spaces after the value + r.skip_spaces() + # Read till end of the line to get a comment from the reader + while r.curr() != '': + r.step() + # Build the result + return AsmVariable(location, name, r.comment, var_type, value) def parse_after_struct(r, as_union = True): - global warnings - location = r.location() + global warnings + location = r.location() - # Skip spaces after "struct" keyword - r.skip_spaces() - # Read struct name - name = "" - while is_id(r.curr()): - name += r.step() - # Read till end of the line and get the comment from the reader - while r.curr() != '': - r.step() - comment = r.comment - # Get to the next line to parse struct members - r.nextline() - # Parse struct members - members = [] - while True: - r.skip_spaces() - var = parse_variable(r) - if type(var) == AsmVariable: - members.append(var) - elif type(var) == str: - if var == 'union': - # Parse the union as a struct - union = parse_after_struct(r, as_union = True) - members.append(union) - # Skip the ends of the union - r.nextline() - elif r.curr() == ':': - warnings += f"{r.location()}: Skept the label in the struct\n" - else: - raise Exception(f"Garbage in struct member at {location} (got '{var}' identifier)") - elif type(var) == VariableNameIsMacroName: - if var.name == 'ends': - break - r.nextline() - # Return the result - if as_union: - return AsmStruct(location, name, comment, members) - else: - return AsmUnion(location, name, comment, members) + # Skip spaces after "struct" keyword + r.skip_spaces() + # Read struct name + name = "" + while is_id(r.curr()): + name += r.step() + # Read till end of the line and get the comment from the reader + while r.curr() != '': + r.step() + comment = r.comment + # Get to the next line to parse struct members + r.nextline() + # Parse struct members + members = [] + while True: + r.skip_spaces() + var = parse_variable(r) + if type(var) == AsmVariable: + members.append(var) + elif type(var) == str: + if var == 'union': + # Parse the union as a struct + union = parse_after_struct(r, as_union = True) + members.append(union) + # Skip the ends of the union + r.nextline() + elif r.curr() == ':': + warnings += f"{r.location()}: Skept the label in the struct\n" + else: + raise Exception(f"Garbage in struct member at {location} (got '{var}' identifier)") + elif type(var) == VariableNameIsMacroName: + if var.name == 'ends': + break + r.nextline() + # Return the result + if as_union: + return AsmStruct(location, name, comment, members) + else: + return AsmUnion(location, name, comment, members) def parse_after_proc(r): - # Get proc name - name = r.fetch_identifier() - # Next identifier after the proc name - identifier = r.fetch_identifier() - # Check if the id is 'stdcall' or 'c' (calling convention specifier) - # and if so - save the convention and lookup the next identifier - calling_convention = '' - if identifier == 'stdcall' or identifier == 'c': - calling_convention = identifier - # If next is a comma, just skip it - if r.curr() == ',': - r.step() - # Read the next identifier - identifier = r.fetch_identifier() - # Check if the id is 'uses' (used register list specifier) - # and if so save the used register list - used_regs = [] - if identifier == 'uses': - # Read the registers - while True: - reg_name = r.fetch_identifier() - if reg_name != '': - used_regs.append(reg_name) - else: - break - # If next is a comma, just skip it - if r.curr() == ',': - r.step() - # Read the next identifier - identifier = r.fetch_identifier() - # Check if there are argument identifiers - args = [] - while identifier != '': - arg_name = identifier - arg_type = 'arg_t' - # Skip spaces after argument name - r.skip_spaces() - # If there's a ':' after the name - the next identifier is type - if r.curr() == ':': - r.step() - arg_type = r.fetch_identifier() - # If there's a comma - there's one more argument - # else no arguments anymore - if r.curr() == ',': - r.step() - identifier = r.fetch_identifier() - else: - identifier = '' - args.append((arg_name, arg_type)) - # Get to the end of the line and get a comment from the reader - while r.curr() != '': - r.step() - comment = r.comment - # Build the element - return AsmFunction(r.location(), name, comment, calling_convention, args, used_regs) + # Get proc name + name = r.fetch_identifier() + # Next identifier after the proc name + identifier = r.fetch_identifier() + # Check if the id is 'stdcall' or 'c' (calling convention specifier) + # and if so - save the convention and lookup the next identifier + calling_convention = '' + if identifier == 'stdcall' or identifier == 'c': + calling_convention = identifier + # If next is a comma, just skip it + if r.curr() == ',': + r.step() + # Read the next identifier + identifier = r.fetch_identifier() + # Check if the id is 'uses' (used register list specifier) + # and if so save the used register list + used_regs = [] + if identifier == 'uses': + # Read the registers + while True: + reg_name = r.fetch_identifier() + if reg_name != '': + used_regs.append(reg_name) + else: + break + # If next is a comma, just skip it + if r.curr() == ',': + r.step() + # Read the next identifier + identifier = r.fetch_identifier() + # Check if there are argument identifiers + args = [] + while identifier != '': + arg_name = identifier + arg_type = 'arg_t' + # Skip spaces after argument name + r.skip_spaces() + # If there's a ':' after the name - the next identifier is type + if r.curr() == ':': + r.step() + arg_type = r.fetch_identifier() + # If there's a comma - there's one more argument + # else no arguments anymore + if r.curr() == ',': + r.step() + identifier = r.fetch_identifier() + else: + identifier = '' + args.append((arg_name, arg_type)) + # Get to the end of the line and get a comment from the reader + while r.curr() != '': + r.step() + comment = r.comment + # Build the element + return AsmFunction(r.location(), name, comment, calling_convention, args, used_regs) def get_declarations(asm_file_contents, asm_file_name): - r = AsmReader(asm_file_name) + r = AsmReader(asm_file_name) - while not r.no_lines(): - # Skip leading spaces - r.skip_spaces() - # Skip the line if it's starting with a comment - if r.curr() == ';': - r.nextline() - continue - # Get first word - first_word = "" - while is_id(r.curr()): - first_word += r.step() - # Match macro declaration - if first_word == "macro": - macro = parse_after_macro(r) - elements.append(macro) - id_add_kind(macro.name, ID_KIND_MACRO_NAME) - # Match structure declaration - elif first_word == "struct": - struct = parse_after_struct(r) - elements.append(struct) - id_add_kind(struct.name, ID_KIND_STRUCT_NAME) - # Match function definition - elif first_word == "proc": - proc = parse_after_proc(r) - elements.append(proc) - elif first_word == 'format': - # Skip the format directive - pass - elif first_word == 'include': - # Skip the include directive - pass - elif first_word == 'if': - # Skip the conditional directive - pass - elif first_word == 'repeat': - # Skip the repeat directive - pass - elif first_word == 'purge': - while True: - # Skip spaces after the 'purge' keyword or after the comma what separated the previous macro name - r.skip_spaces() - # Get the purged macro name - name = '' - while is_id(r.curr()): - name += r.step() - # Remove the purged macro from the macro names list - try: - id_remove_kind(name, ID_KIND_MACRO_NAME) - except: - pass - # Skip spaces after the name - r.skip_spaces() - # If it's comma (',') after then that's not the last purged macro, continue purging - if r.curr() == ',': - r.step() - continue - # Here we purged all the macros should be purged - break - # Match label or a variable - elif len(first_word) != 0: - # Skip spaces after the identifier - r.skip_spaces() - # Match a variable - var = parse_variable(r, first_word) - if type(var) == AsmVariable: - elements.append(var) - # If it wasn't a variable but there was an identifier - # Maybe that's a label and the identifier is the label name - # The parse_variable returns the first found or supplied identifier - # In this case it returns the first_word which is supplied - # If it didn't match a type identifier after the word - elif type(var) == str: - name = var - # Match label beginning (':' after name) - if r.curr() == ':': - # Get to the end of the line and get the coment from the reader - while r.curr() != '': - r.step() - comment = r.comment - # Only handle non-local labels - if name[0] != '.' and name != "@@" and name != "$Revision": - if '@return' in comment or '@param' in comment: - element = AsmFunction(r.location(), name, comment, '', [], []) - else: - element = AsmLabel(r.location(), name, comment) - elements.append(element) - elif r.curr() == '=': - # Save the identifier as a set constant - id_add_kind(first_word, ID_KIND_SET_CONSTANT) - elif type(var) == tuple: - (word_one, word_two) = var - if word_two == 'equ': - # Save the identifier as an equated constant - id_add_kind(word_one, ID_KIND_EQUATED_CONSTANT) - r.nextline() + while not r.no_lines(): + # Skip leading spaces + r.skip_spaces() + # Skip the line if it's starting with a comment + if r.curr() == ';': + r.nextline() + continue + # Get first word + first_word = "" + while is_id(r.curr()): + first_word += r.step() + # Match macro declaration + if first_word == "macro": + macro = parse_after_macro(r) + elements.append(macro) + id_add_kind(macro.name, ID_KIND_MACRO_NAME) + # Match structure declaration + elif first_word == "struct": + struct = parse_after_struct(r) + elements.append(struct) + id_add_kind(struct.name, ID_KIND_STRUCT_NAME) + # Match function definition + elif first_word == "proc": + proc = parse_after_proc(r) + elements.append(proc) + elif first_word == 'format': + # Skip the format directive + pass + elif first_word == 'include': + # Skip the include directive + pass + elif first_word == 'if': + # Skip the conditional directive + pass + elif first_word == 'repeat': + # Skip the repeat directive + pass + elif first_word == 'purge': + while True: + # Skip spaces after the 'purge' keyword or after the comma what separated the previous macro name + r.skip_spaces() + # Get the purged macro name + name = '' + while is_id(r.curr()): + name += r.step() + # Remove the purged macro from the macro names list + try: + id_remove_kind(name, ID_KIND_MACRO_NAME) + except: + pass + # Skip spaces after the name + r.skip_spaces() + # If it's comma (',') after then that's not the last purged macro, continue purging + if r.curr() == ',': + r.step() + continue + # Here we purged all the macros should be purged + break + # Match label or a variable + elif len(first_word) != 0: + # Skip spaces after the identifier + r.skip_spaces() + # Match a variable + var = parse_variable(r, first_word) + if type(var) == AsmVariable: + elements.append(var) + # If it wasn't a variable but there was an identifier + # Maybe that's a label and the identifier is the label name + # The parse_variable returns the first found or supplied identifier + # In this case it returns the first_word which is supplied + # If it didn't match a type identifier after the word + elif type(var) == str: + name = var + # Match label beginning (':' after name) + if r.curr() == ':': + # Get to the end of the line and get the coment from the reader + while r.curr() != '': + r.step() + comment = r.comment + # Only handle non-local labels + if name[0] != '.' and name != "@@" and name != "$Revision": + if '@return' in comment or '@param' in comment: + element = AsmFunction(r.location(), name, comment, '', [], []) + else: + element = AsmLabel(r.location(), name, comment) + elements.append(element) + elif r.curr() == '=': + # Save the identifier as a set constant + id_add_kind(first_word, ID_KIND_SET_CONSTANT) + elif type(var) == tuple: + (word_one, word_two) = var + if word_two == 'equ': + # Save the identifier as an equated constant + id_add_kind(word_one, ID_KIND_EQUATED_CONSTANT) + r.nextline() def it_neds_to_be_parsed(source_file): - # If there's no symbols file saved - parse it anyway - # cause we need to create the symbols file and use it - # if we gonna generate proper doxygen - if not os.path.isfile('asmxygen.elements.pickle'): - return True - dest = doxygen_src_path + '/' + source_file - # If there's no the doxygen file it should be compiled to - # then yes, we should compile it to doxygen - if not os.path.isfile(dest): - return True - source_change_time = os.path.getmtime(source_file) - dest_change_file = os.path.getmtime(dest) - # If the source is newer than the doxygen it was compiled to - # then the source should be recompiled (existing doxygen is old) - if source_change_time > dest_change_file: - return True - return False + # If there's no symbols file saved - parse it anyway + # cause we need to create the symbols file and use it + # if we gonna generate proper doxygen + if not os.path.isfile('asmxygen.elements.pickle'): + return True + dest = doxygen_src_path + '/' + source_file + # If there's no the doxygen file it should be compiled to + # then yes, we should compile it to doxygen + if not os.path.isfile(dest): + return True + source_change_time = os.path.getmtime(source_file) + dest_change_file = os.path.getmtime(dest) + # If the source is newer than the doxygen it was compiled to + # then the source should be recompiled (existing doxygen is old) + if source_change_time > dest_change_file: + return True + return False def handle_file(handled_files, asm_file_name, subdir = "."): - global elements - # Canonicalize the file path and get it relative to cwd - cwd = os.path.abspath(os.path.dirname(sys.argv[0])) - asm_file_name = os.path.realpath(asm_file_name) - asm_file_name = asm_file_name[len(cwd) + 1:] - # If it's lang.inc - skip it - if asm_file_name == 'lang.inc': - return - # If the file was handled in this execution before - skip it - if asm_file_name in handled_files: - return - # Say that the file was handled in this execution - handled_files.append(asm_file_name) - # Check if the file should be parsed (if it was modified or wasn't parsed yet) - should_get_declarations = True - if not it_neds_to_be_parsed(asm_file_name): - print(f"Skipping {asm_file_name} (already newest)") - should_get_declarations = False - else: - print(f"Handling {asm_file_name}") - # Remove elements parsed from this file before if any - elements_to_remove = [x for x in elements if x.location.split(':')[0] == asm_file_name] - elements = [x for x in elements if x.location.split(':')[0] != asm_file_name] - # Forget types of identifiers of names of the removed elements - for element in elements_to_remove: - if type(element) == AsmStruct: - id_remove_kind(element.name, ID_KIND_STRUCT_NAME) - elif type(element) == AsmMacro: - id_remove_kind(element.name, ID_KIND_MACRO_NAME) - # Read the source - asm_file_contents = open(asm_file_name, "r", encoding="utf-8").read() - # Find includes, fix their paths and handle em recoursively - includes = re.findall(r'^include (["\'])(.*)\1', asm_file_contents, flags=re.MULTILINE) - for include in includes: - include = include[1].replace('\\', '/'); - full_path = subdir + '/' + include; - # If the path isn't valid, maybe that's not relative path - if not os.path.isfile(full_path): - full_path = include - new_subdir = full_path.rsplit('/', 1)[0] - handle_file(handled_files, full_path, new_subdir) - # Only collect declarations from the file if it wasn't parsed before - if should_get_declarations and not clean_generated_stuff: - get_declarations(asm_file_contents, asm_file_name) + global elements + # Canonicalize the file path and get it relative to cwd + cwd = os.path.abspath(os.path.dirname(sys.argv[0])) + asm_file_name = os.path.realpath(asm_file_name) + asm_file_name = asm_file_name[len(cwd) + 1:] + # If it's lang.inc - skip it + if asm_file_name == 'lang.inc': + return + # If the file was handled in this execution before - skip it + if asm_file_name in handled_files: + return + # Say that the file was handled in this execution + handled_files.append(asm_file_name) + # Check if the file should be parsed (if it was modified or wasn't parsed yet) + should_get_declarations = True + if not it_neds_to_be_parsed(asm_file_name): + print(f"Skipping {asm_file_name} (already newest)") + should_get_declarations = False + else: + print(f"Handling {asm_file_name}") + # Remove elements parsed from this file before if any + elements_to_remove = [x for x in elements if x.location.split(':')[0] == asm_file_name] + elements = [x for x in elements if x.location.split(':')[0] != asm_file_name] + # Forget types of identifiers of names of the removed elements + for element in elements_to_remove: + if type(element) == AsmStruct: + id_remove_kind(element.name, ID_KIND_STRUCT_NAME) + elif type(element) == AsmMacro: + id_remove_kind(element.name, ID_KIND_MACRO_NAME) + # Read the source + asm_file_contents = open(asm_file_name, "r", encoding="utf-8").read() + # Find includes, fix their paths and handle em recoursively + includes = re.findall(r'^include (["\'])(.*)\1', asm_file_contents, flags=re.MULTILINE) + for include in includes: + include = include[1].replace('\\', '/'); + full_path = subdir + '/' + include; + # If the path isn't valid, maybe that's not relative path + if not os.path.isfile(full_path): + full_path = include + new_subdir = full_path.rsplit('/', 1)[0] + handle_file(handled_files, full_path, new_subdir) + # Only collect declarations from the file if it wasn't parsed before + if should_get_declarations and not clean_generated_stuff: + get_declarations(asm_file_contents, asm_file_name) if __name__ == "__main__": - link_root = "http://websvn.kolibrios.org/filedetails.php?repname=Kolibri+OS&path=/kernel/trunk" + link_root = "http://websvn.kolibrios.org/filedetails.php?repname=Kolibri+OS&path=/kernel/trunk" - # Dict where an identifier is assicoated with a string - # The string contains characters specifying flags - # Available flags: - # k - Keyword - # m - Macro name - # t - fasm data Type name (db, rq, etc.) - # s - Struct type name - # e - equated constant (name equ value) - # = - set constants (name = value) - ID_KIND_KEYWORD = 'k' - ID_KIND_MACRO_NAME = 'm' - ID_KIND_FASM_TYPE = 't' - ID_KIND_STRUCT_NAME = 's' - ID_KIND_EQUATED_CONSTANT = 'e' - ID_KIND_SET_CONSTANT = '=' - id2kind = {} + # Dict where an identifier is assicoated with a string + # The string contains characters specifying flags + # Available flags: + # k - Keyword + # m - Macro name + # t - fasm data Type name (db, rq, etc.) + # s - Struct type name + # e - equated constant (name equ value) + # = - set constants (name = value) + ID_KIND_KEYWORD = 'k' + ID_KIND_MACRO_NAME = 'm' + ID_KIND_FASM_TYPE = 't' + ID_KIND_STRUCT_NAME = 's' + ID_KIND_EQUATED_CONSTANT = 'e' + ID_KIND_SET_CONSTANT = '=' + id2kind = {} - for keyword in keywords: - id_add_kind(keyword, ID_KIND_KEYWORD) + for keyword in keywords: + id_add_kind(keyword, ID_KIND_KEYWORD) - for fasm_type in fasm_types: - id_add_kind(fasm_type, ID_KIND_FASM_TYPE) + for fasm_type in fasm_types: + id_add_kind(fasm_type, ID_KIND_FASM_TYPE) - # Warning list - warnings = "" + # Warning list + warnings = "" - # Parameters - # Path to doxygen folder to make doxygen files in: -o - doxygen_src_path = 'docs/doxygen' - # Remove generated doxygen files: --clean - clean_generated_stuff = False - # Dump all defined symbols: --dump - dump_symbols = False - # Print symbol stats: --stats - print_stats = False - # Do not write warnings file: --nowarn - enable_warnings = True + # Parameters + # Path to doxygen folder to make doxygen files in: -o + doxygen_src_path = 'docs/doxygen' + # Remove generated doxygen files: --clean + clean_generated_stuff = False + # Dump all defined symbols: --dump + dump_symbols = False + # Print symbol stats: --stats + print_stats = False + # Do not write warnings file: --nowarn + enable_warnings = True - # Parse arguments - parser = argparse.ArgumentParser() - parser.add_argument("-o", help="Doxygen output folder") - parser.add_argument("--clean", help="Remove generated files", action="store_true") - parser.add_argument("--dump", help="Dump all defined symbols", action="store_true") - parser.add_argument("--stats", help="Print symbol stats", action="store_true") - parser.add_argument("--nowarn", help="Do not write warnings file", action="store_true") - parser.add_argument("--noemit", help="Do not emit doxygen files (for testing)", action="store_true") - parser.add_argument("--debug", help="Show hashes of files (for testing)", action="store_true") - args = parser.parse_args() - doxygen_src_path = args.o if args.o else 'docs/doxygen' - clean_generated_stuff = args.clean - dump_symbols = args.dump - print_stats = args.stats - enable_warnings = not args.nowarn - noemit = args.noemit - debug_mode = args.debug + # Parse arguments + parser = argparse.ArgumentParser() + parser.add_argument("-o", help="Doxygen output folder") + parser.add_argument("--clean", help="Remove generated files", action="store_true") + parser.add_argument("--dump", help="Dump all defined symbols", action="store_true") + parser.add_argument("--stats", help="Print symbol stats", action="store_true") + parser.add_argument("--nowarn", help="Do not write warnings file", action="store_true") + parser.add_argument("--noemit", help="Do not emit doxygen files (for testing)", action="store_true") + parser.add_argument("--debug", help="Show hashes of files (for testing)", action="store_true") + args = parser.parse_args() + doxygen_src_path = args.o if args.o else 'docs/doxygen' + clean_generated_stuff = args.clean + dump_symbols = args.dump + print_stats = args.stats + enable_warnings = not args.nowarn + noemit = args.noemit + debug_mode = args.debug - # Variables, functions, labels, macros, structure types - elements = [] - created_files = [] - kernel_files = [] - output_files = {} # If --debug then all the files are written here + # Variables, functions, labels, macros, structure types + elements = [] + created_files = [] + kernel_files = [] + output_files = {} # If --debug then all the files are written here - # Load remembered list of symbols - if os.path.isfile('asmxygen.elements.pickle'): - print('Reading existing dump of symbols') - (elements, id2kind) = pickle.load(open('asmxygen.elements.pickle', 'rb')) + # Load remembered list of symbols + if os.path.isfile('asmxygen.elements.pickle'): + print('Reading existing dump of symbols') + (elements, id2kind) = pickle.load(open('asmxygen.elements.pickle', 'rb')) - handle_file(kernel_files, "./kernel.asm"); + handle_file(kernel_files, "./kernel.asm"); - if dump_symbols: - stdout = sys.stdout - sys.stdout = open('asmxygen.dump.txt', 'w', encoding = 'utf-8') - for asm_element in elements: - asm_element.dump() - sys.stdout = stdout + if dump_symbols: + stdout = sys.stdout + sys.stdout = open('asmxygen.dump.txt', 'w', encoding = 'utf-8') + for asm_element in elements: + asm_element.dump() + sys.stdout = stdout - if clean_generated_stuff: - kernel_files_set = set(kernel_files) - for file in kernel_files: - doxygen_file = f"{doxygen_src_path}/{file}" - if (os.path.isfile(doxygen_file)): - print(f"Removing {file}... ", end = '') - os.remove(doxygen_file) - print("Done.") - elif not noemit: - print(f"Writing doumented sources to {doxygen_src_path}") + if clean_generated_stuff: + kernel_files_set = set(kernel_files) + for file in kernel_files: + doxygen_file = f"{doxygen_src_path}/{file}" + if (os.path.isfile(doxygen_file)): + print(f"Removing {file}... ", end = '') + os.remove(doxygen_file) + print("Done.") + elif not noemit: + print(f"Writing doumented sources to {doxygen_src_path}") - i = 0 - new_elements = [x for x in elements if x.new] - for element in new_elements: - print(f"[{i + 1}/{len(new_elements)}] Emitting {element.name} from {element.location}") - element.emit(doxygen_src_path) - i += 1 + i = 0 + new_elements = [x for x in elements if x.new] + for element in new_elements: + print(f"[{i + 1}/{len(new_elements)}] Emitting {element.name} from {element.location}") + element.emit(doxygen_src_path) + i += 1 - print(f"Writing dump of symbols to asmxygen.elements.pickle") + print(f"Writing dump of symbols to asmxygen.elements.pickle") - # Now when the new elements already was written, there's no new elements anymore - for element in elements: - element.new = False - pickle.dump((elements, id2kind), open('asmxygen.elements.pickle', 'wb')) + # Now when the new elements already was written, there's no new elements anymore + for element in elements: + element.new = False + pickle.dump((elements, id2kind), open('asmxygen.elements.pickle', 'wb')) - if print_stats: - var_count = 0 - mac_count = 0 - lab_count = 0 - fun_count = 0 - uni_count = 0 - str_count = 0 - for element in elements: - if type(element) == AsmVariable: - var_count += 1 - elif type(element) == AsmMacro: - mac_count += 1 - elif type(element) == AsmLabel: - lab_count += 1 - elif type(element) == AsmFunction: - fun_count += 1 - elif type(element) == AsmUnion: - uni_count += 1 - elif type(element) == AsmStruct: - str_count += 1 - print(f'Parsed variable count: {var_count}') - print(f'Parsed macro count: {mac_count}') - print(f'Parsed label count: {lab_count}') - print(f'Parsed function count: {fun_count}') - print(f'Parsed union type count: {uni_count}') - print(f'Parsed structure type count: {str_count}') + if print_stats: + var_count = 0 + mac_count = 0 + lab_count = 0 + fun_count = 0 + uni_count = 0 + str_count = 0 + for element in elements: + if type(element) == AsmVariable: + var_count += 1 + elif type(element) == AsmMacro: + mac_count += 1 + elif type(element) == AsmLabel: + lab_count += 1 + elif type(element) == AsmFunction: + fun_count += 1 + elif type(element) == AsmUnion: + uni_count += 1 + elif type(element) == AsmStruct: + str_count += 1 + print(f'Parsed variable count: {var_count}') + print(f'Parsed macro count: {mac_count}') + print(f'Parsed label count: {lab_count}') + print(f'Parsed function count: {fun_count}') + print(f'Parsed union type count: {uni_count}') + print(f'Parsed structure type count: {str_count}') - if enable_warnings: - open('asmxygen.txt', "w", encoding = "utf-8").write(warnings) + if enable_warnings: + open('asmxygen.txt', "w", encoding = "utf-8").write(warnings) - if debug_mode: - hash_per_file = "" - for file in output_files: - h = hashlib.sha1(bytes(output_files[file], "ascii")).hexdigest() - hash_per_file += f"{file}: {h}\n" - if not os.path.exists("asmxygen_hash_per_file.txt"): - open("asmxygen_hash_per_file.txt", "w").write(hash_per_file) - print("NEW") - else: - reference_hash_per_file = open("asmxygen_hash_per_file.txt").read() - if reference_hash_per_file != hash_per_file: - print(''.join(difflib.ndiff(reference_hash_per_file, hash_per_file))) - else: - print("SUCCESS") + if debug_mode: + hash_per_file = "" + for file in output_files: + h = hashlib.sha1(bytes(output_files[file], "ascii")).hexdigest() + hash_per_file += f"{file}: {h}\n" + if not os.path.exists("asmxygen_hash_per_file.txt"): + open("asmxygen_hash_per_file.txt", "w").write(hash_per_file) + print("NEW") + else: + reference_hash_per_file = open("asmxygen_hash_per_file.txt").read() + if reference_hash_per_file != hash_per_file: + print(''.join(difflib.ndiff(reference_hash_per_file, hash_per_file))) + else: + print("SUCCESS")