diff --git a/cmpdbgfiles.py b/cmpdbgfiles.py index 01b1560f..6c23fd97 100644 --- a/cmpdbgfiles.py +++ b/cmpdbgfiles.py @@ -1,93 +1,62 @@ #!/usr/bin/env python3 -import sys, argparse, pathlib +import sys, argparse, pathlib, re -def readDbgFile (filename : str, check : str) -> dict: +cfgCommentRemoveRegex = [re.compile(r'(?m:^(.*?)(#.*?)$)'), r'\0'] +cfgPartsRegex = re.compile(r'(?ms:^(?P\w+) \{$(?P.*?)^\})') +cfgLineRegex = re.compile(r'(?P\w+):\s*(?P(?:\s*(?:\w+)\s*=\s*(?:\S+?)\s*(?:,|))+);') +cfgDataRegex = re.compile(r'(?:(\w+)\s*=\s*(\S+?)(?:\s*,|\s+))') + +dbgLineRegex = r'(?ms:^(?P\w+)[\t ](?P(?:\w+=(?:"[^"]*?"|[^,\n]+)(?:,|$))+))' +specDbgLineRegex = lambda x : re.compile(r'(?ms:^(?P' + x + r')[\t ](?P(?:\w+=(?:"[^"]*?"|[^,\n]+)(?:,|$))+))') +dbgDataRegex = re.compile(r'(?:(?P\w+)=(?:"(?P[^"]*?)"|(?P[^,\n]+))(?:,|$))') + +def readDbgFile (filename : pathlib.Path, check : str = None) -> dict: outdict = {} - with open(sys.path[0]+"/"+filename) as file: - for line in file: - # print(line) - if not line: - break - if line.startswith(check): - line = line.split(",") - if [i[6:-1] for i in line if i.startswith("name")][0]: - outdict[[i[6:-1] for i in line if i.startswith("name")][0]] = [int(i[5:], 0) for i in line if i.startswith("size")][0] - # names += [i[6:-1] for i in line if i.startswith("name")] - # sizes += [int(i[5:]) for i in line if i.startswith("size")] - # if (len(line) >= 2 ): - # output.append("#define "+line[0]+" "+line[2]) - # else: - # for i in outdict.items(): - # print(i) + text = filename.read_text() + + if check == None: + lineRgx = re.compile(dbgLineRegex) + else: + lineRgx = re.compile(specDbgLineRegex(check)) + + for line in re.finditer(lineRgx, text): + if line['name'] not in outdict.keys(): + outdict[line['name']] = list() + + lineData = {} + for data in re.finditer(dbgDataRegex, line['data']): + lineData[data['id']] = data[data.lastgroup] + outdict[line['name']].append(lineData) return outdict -def parseCfgLine (line : str) -> tuple: - name = "" - args = {} - line = line.split() - if len(line) == 0: - return () - idx = 0 - for i in line: - if i.startswith("#"): - return () - elif i.endswith(":"): - name = i.strip()[:-1] - break - idx += 1 - line = " ".join(line[idx+1:]) - line = line[:line.rfind(";")] - for i in line.split(","): - sub = i.split() - if (len(sub) == 3): - if sub[1] == "=": - args[sub[0]] = sub[2] - elif (len(sub) == 2): - if sub[0][-1] == "=": - args[sub[0][:-1]] = sub[2] - elif sub[2][0] == "=": - args[sub[0]] = sub[2][1:] - else: - raise ValueError (f"What the hell happened here? String:\n{i}") - elif (len(sub) == 1): - args[:i.index("=")] = args[i.index("=")+1:] - return (name, args) - - -def readCfgFile (filename : str, check : str, part : str) -> dict: +def readCfgFile (filename : pathlib.Path) -> dict: outdict = {} - lines = [] - with open(sys.path[0]+"/"+filename) as file: - - state = 0 - - for line in file: - if not line: - return {} - if state == 0: - if line.startswith(part): - line = line.split() - if line[1] == "{": - state = 1 - elif state == 1: - if "}" in line: - break - lines.append(line) - for i in lines: - data = parseCfgLine(i) - if len(data) == 0: - continue - if check in data[1].keys(): - outdict[data[0]] = data[1][check] - + text = filename.read_text() + + text = re.sub(*cfgCommentRemoveRegex, text) + + for i in re.finditer(cfgPartsRegex, text): + part = {} + + for line in re.finditer(cfgLineRegex, i['data']): + lineData = {} + for statement in re.finditer(cfgDataRegex, line['data']): + lineData[statement[1]] = statement[2] + part[line['name']] = lineData + + outdict[i['name']] = part + return outdict +ownPath = pathlib.Path(sys.path[0]).resolve() + parser = argparse.ArgumentParser() parser.add_argument("-d", "--only-diff", "--diff-only", help="Only show the differences between the .dbg files", action="store_false", default=True) parser.add_argument("-m", "--markdown-mode", "--md", help="Enable markdown code quotes around individual entries", action="store_true") parser.add_argument("-e", "--entry-type", help="The type of entries to include", default="scope", choices=["scope", "seg", "bank"]) -parser.add_argument("-c", "--compare", help="Compare the current BUILD/famidash.dbg file to an older version of the famidash.dbg file") +parser.add_argument("-f", "--file", help="Specify a path of the new famidash.dbg file, the default is BUILD/famidash.dbg", type=pathlib.Path, default = ownPath / "BUILD" / "famidash.dbg") +parser.add_argument("-c", "--compare", help="Compare the current BUILD/famidash.dbg file to an older version of the famidash.dbg file", type=pathlib.Path) parser.add_argument("-s", "--sort", help="Sorting options", default="declaration", choices= ["declaration", "d", "alphabetical", "a", "size-increasing", "si", "size-decreasing", "sd"]) args = parser.parse_args() @@ -110,8 +79,10 @@ def readCfgFile (filename : str, check : str, part : str) -> dict: # print("start") if compare: - old = readDbgFile(args.compare, check) -new = readDbgFile("BUILD/famidash.dbg", check) + oldDbgData = readDbgFile(args.compare, check) + old = {i['name'] : int(i['size'], base=0) for i in oldDbgData[check]} +newDbgData = readDbgFile(args.file, check) +new = {i['name'] : int(i['size'], base=0) for i in oldDbgData[check]} if compare: for i in old.items(): @@ -122,7 +93,10 @@ def readCfgFile (filename : str, check : str, part : str) -> dict: old[i[0]] = 0 if args.entry_type == "bank": - cfg = readCfgFile("CONFIG/mmc3.cfg", "load", "SEGMENTS") + cfgData = readCfgFile(ownPath / "CONFIG" / "mmc3.cfg") + cfg = {} + for segment in cfgData['SEGMENTS']: + cfg[segment] = cfgData['SEGMENTS'][segment]['load'] if compare: older = old.copy() old = {}