#! /usr/bin/python3.7 """ @file mib_objects.py @brief Part of the Mission Information Base Exporter for the SOURCE project by KSat. @details Event exporter. To use MySQLdb, run pip install mysqlclient or install in IDE. On Windows, Build Tools installation might be necessary @data 21.11.2019 """ import re import os import shutil import pprint from utility.mib_csv_writer import CsvWriter generateCpp = True generateCsv = True copyCppFile = True moveCsvFile = True cppFilename = "translateEvents.cpp" csvFilename = "MIB_Events.csv" cppCopyDestination = "../../config/objects/" csvMoveDestination = "../" fileSeparator = ";" pp = pprint.PrettyPrinter(indent=0, width=250) def main(): print("Parsing events: ") listItems = parseOBSW() handleFileExport(listItems) print("") def parseOBSW(): idSubsystemDefinitions = parseSubsystemDefinitionFile("../../config/tmtc/subsystemIdRanges.h") tempList = parseSubsystemDefinitionFile("../../fsfw/events/fwSubsystemIdRanges.h") idSubsystemDefinitions.update(tempList) print(len(idSubsystemDefinitions)) # print ("Dictionary size is " + str(len(idInterfaceDefinitions)) ) # for entry in idSubsystemDefinitions: # print(entry) myHeaderList = getHeaderFileList("../../mission/") myHeaderList = myHeaderList + getHeaderFileList("../../fsfw/") myEventList = parseHeaderFiles(idSubsystemDefinitions, myHeaderList) listItems = sorted(myEventList.items()) print("Found " + str(len(listItems)) + " entries:") pp.pprint(listItems) print(len(listItems)) return listItems def handleFileExport(listItems): csvWriter = CsvWriter(csvFilename) if generateCpp: print("Generating translation cpp file.") writeTranslationFile(cppFilename, listItems) if generateCpp and copyCppFile: dst = shutil.copy2("../events/translateEvents.cpp", "../../config/events/") print("CPP file was copied to " + dst) if generateCsv: print("Generating text export.") exportToFile(csvFilename, listItems) if generateCsv and moveCsvFile: csvWriter.move_csv(csvMoveDestination) # The output files are generated by putting the name of the output CPP file as first argument and the name of the # csv or txt output as second argument in the Run Configuration. # Config Parameters: translateEvents.cpp translateEvents.csv def parseSubsystemDefinitionFile(filename): file = open(filename, "r") interfaces = dict() for line in file.readlines(): match = re.search('([A-Z0-9_]*) = ([0-9]{1,2})', line) if match: interfaces.update({match.group(1): [match.group(2)]}) return interfaces def returnNumberFromString(aString): if aString.startswith('0x'): return int(aString, 16) elif aString.isdigit(): return int(aString) else: print('Error: Illegal number representation: ' + aString) return 0 def convert(name): singleStrings = name.split('_') newString = '' for oneString in singleStrings: oneString = oneString.lower() oneString = oneString.capitalize() newString = newString + oneString return newString def buildCheckedString(firstPart, secondPart): myStr = firstPart + convert(secondPart) if len(myStr) > 16: print("Error: Entry: " + myStr + " too long. Will truncate.") myStr = myStr[0:14] # else: # print( "Entry: " + myStr + " is all right.") return myStr def cleanUpDescription(description): description = description.lstrip('//!<>') description = description.lstrip() if description == '': description = ' ' return description def parseHeaderFiles(interfaceList, fileList): dictionnary = dict() totalCount = 0 count = 0 # noinspection PyUnusedLocal currentId = 0 for fileName in fileList: file = open(fileName, "r") oldline = file.readline() myId = 0 # print(file_name) while True: newline = file.readline() if not newline: break # EOF if not oldline == '\n': twolines = oldline + ' ' + newline.strip() else: twolines = '' match1 = re.search('SUBSYSTEM_ID[\s]*=[\s]*SUBSYSTEM_ID::([A-Z_0-9]*);', twolines) if match1: currentId = interfaceList[match1.group(1)][0] # print( "Current ID: " + str(currentId) ) myId = returnNumberFromString(currentId) match = re.search('(//)?[\t ]*static const Event[\s]*([A-Z_0-9]*)[\s]*=[\s]*MAKE_EVENT\(([0-9]{1,2}),' '[\s]*SEVERITY::([A-Z]*)\);[\t ]*(//!<)?([^\n]*)', twolines) if match: if match.group(1): oldline = newline continue description = " " if match.group(6): description = cleanUpDescription(match.group(6)) stringToAdd = match.group(2) fullId = (myId * 100) + returnNumberFromString(match.group(3)) severity = match.group(4) if fullId in dictionnary: print('duplicate Event ' + hex(fullId) + ' from ' + fileName + ' was already in ' + dictionnary[fullId][3]) dictionnary.update({fullId: (stringToAdd, severity, description, fileName)}) count = count + 1 oldline = newline if count > 0: print("File " + fileName + " contained " + str(count) + " events.") totalCount += count count = 0 print("Total events: " + str(totalCount)) return dictionnary def getHeaderFileList(base): # print("getHeaderFileList called with" + base) baseList = os.listdir(base) fileList = [] for entry in baseList: # Remove all hidden files: if os.path.isdir(base + entry) and (entry[0] != ".") and (entry[0] != "_"): fileList = fileList + getHeaderFileList(base + entry + "/") if re.match("[^.]*\.h", entry) and os.path.isfile(base + entry): fileList.append(base + entry) return fileList def exportToFile(filename, listOfEntries): print('Exporting to file: ' + filename) file = open(filename, "w") for entry in listOfEntries: file.write(str(entry[0]) + fileSeparator + entry[1][0] + fileSeparator + entry[1][1] + fileSeparator + entry[1][2] + fileSeparator + entry[1][3] + '\n') file.close() return def writeTranslationFile(filename, listOfEntries): outputfile = open(filename, "w") definitions = "" function = "const char * translateEvents(Event event){\n\tswitch((event&0xFFFF)){\n" for entry in listOfEntries: definitions += "const char *" + entry[1][0] + "_STRING = \"" + entry[1][0] + "\";\n" function += "\t\tcase " + str(entry[0]) + ":\n\t\t\treturn " + entry[1][0] + "_STRING;\n" function += '\t\tdefault:\n\t\t\treturn "UNKNOWN_EVENT";\n' outputfile.write("/* Auto-generated event translation file. Contains " + str(len(listOfEntries)) + " translations. */\n") outputfile.write("#include \"translateEvents.h\"\n\n") outputfile.write(definitions + "\n" + function + "\t}\n\treturn 0;\n}\n") outputfile.close() if __name__ == "__main__": main()