Dear Gentoo Users, Developers! I would like to share my little program that does header file generation from GNU C file.
See attached file. Sincerely xbx.
#!/usr/bin/env python import os import sys import re import shutil import datetime class ConfigMain(object): def __init__(self): self.confStrfTime = "%Y_%m_%d__%H_%M_%S" self.mainOutputDir = "Header-OLD-Saved" # Dictionary Keys for the Read Director class self.dictKeyDataHolderFileNameCode = 'codefileName' self.dictKeyDataHolderFilePathCode = 'codefilePath' self.dictKeyDataHolderFileNameHeader = 'headerFileName' self.dictKeyDataHolderFilePathHeader = 'headerFilePath' self.configDictKeyVoid = "FunctionVoid" self.configDictKeyChar = "FunctionChar" self.configDictKeyInteger = "FunctionInteger" self.configDictKeyStruct = "FunctionStruct" self.configDictKeyCustom = "FunctionCustom" # file extension self.configFileExtensionHeader = ".h" self.configFileExtensionC = ".c" class FileContentReader(object): def __init__(self): self.__fileName = None self.__fileHandler = None self.__fileData = None def __openFile(self): try: print("Reading file: {0}".format(self.__fileName)) self.__fileHandler = open(self.__fileName, "r") except OSError as exc: print("Exception reading C File: {0}.Exception was: {1}" .format(self.__fileName, exc)) sys.exit(1) def readDataWholeFile(self, fileNameCCode): self.__fileName = fileNameCCode self.__openFile() try: self.__fileData = self.__fileHandler.readlines() self.__fileHandler.close() self.__fileHandler = None return self.__fileData except OSError as exc: print("Exception Occured reading file: {0}. Exception was: {1}" .format(self.__fileName, exc)) sys.exit(2) def __del__(self): if self.__fileHandler is not None: self.__fileHandler.close() class HeaderFileContentWriter(object): def __init__(self): self.__fileHandlerWrite = None def openFileWrite(self, fileNameWrite): try: self.__fileHandlerWrite = open(fileNameWrite, "w") except OSError as exc: print("Exception occured: {0}".format(exc)) def writeOutData(self, writeData): try: self.__fileHandlerWrite.write(writeData) self.__fileHandlerWrite.flush() self.__fileHandlerWrite.close() self.__fileHandlerWrite = None except OSError as exc: print("Exception occured: {0}".format(exc)) def __del__(self): if self.__fileHandlerWrite is not None: self.__fileHandlerWrite.flush() self.__fileHandlerWrite.close() class HeaderFileContentGenerator(object): def __init__(self): self.__headerFileName = None self.__headerFileExtension = ".h" self.__definePre = "#ifndef " self.__defineDefine = "#define " self.__defineEnd = "#endif" self.__define_H_end = "_H__" self.__define_H_start = "__" self.__stringBuilderStart = "" self.__stringBuilderEnd = "" self.__stringBuilderFunctionAll = "" # function String buffers self.__stringBufferVoid = "" self.__stringBufferInteger = "" self.__stringBufferChar = "" self.__stringBufferStruct = "" # The Whole file String self.__functionListVoid = list() self.__functionListInteger = list() self.__functionListChar = list() self.__functionListStruct = list() self.__dataHolderBuildedStrings = "" def setVariableFileNameHeader(self, fileNameHeader): self.__headerFileName = fileNameHeader def setVariableFunctionListVoid(self, functionListVoid): if functionListVoid is not None: self.__functionListVoid = functionListVoid def setVariableFunctionListInteger(self, functionListInteger): if functionListInteger is not None: self.__functionListInteger = functionListInteger def setVariableFunctionListChar(self, functionListChar): if functionListChar is not None: self.__functionListChar = functionListChar def setVariableFunctionListStruct(self, functionListStruct): if functionListStruct is not None: self.__functionListStruct = functionListStruct def preGenerateStartDefine(self): includeHeader = "" fileNameWithoutExtension = self.__headerFileName.rstrip( self.__headerFileExtension) uppperCaseHeaderFileName = fileNameWithoutExtension.upper() #print("Header include file: {0}".format(uppperCaseHeaderFileName)) self.__stringBuilderStart += self.__definePre includeHeader += self.__define_H_start includeHeader += uppperCaseHeaderFileName includeHeader += self.__define_H_end self.__stringBuilderStart += includeHeader self.__stringBuilderStart += os.linesep self.__stringBuilderStart += self.__defineDefine self.__stringBuilderStart += includeHeader self.__stringBuilderStart += os.linesep #print(self.__stringBuilderStart) def innerGenerateCodeFunctions(self): for functionVoid in self.__functionListVoid: self.__stringBufferVoid += functionVoid + ";" + os.linesep for functionInteger in self.__functionListInteger: self.__stringBufferInteger += functionInteger + ";" + os.linesep for functionChar in self.__functionListChar: self.__stringBufferChar += functionChar + ";" + os.linesep for functionStruct in self.__functionListStruct: self.__stringBufferStruct += functionStruct + ";" + os.linesep self.__stringBuilderFunctionAll += self.__stringBufferVoid self.__stringBuilderFunctionAll += self.__stringBufferInteger self.__stringBuilderFunctionAll += self.__stringBufferChar self.__stringBuilderFunctionAll += self.__stringBufferStruct self.__stringBuilderFunctionAll += os.linesep def generateEndHeaderFileMacro(self): self.__stringBuilderEnd = self.__defineEnd def headerFileBuildPreInnerEnd(self): self.__dataHolderBuildedStrings += self.__stringBuilderStart self.__dataHolderBuildedStrings += self.__stringBuilderFunctionAll self.__dataHolderBuildedStrings += self.__stringBuilderEnd def getResultHeaderFileContentString(self): return self.__dataHolderBuildedStrings class ExceptionParseCFunction(Exception): def __init__(self, message): self.__message = "Exception Occured when parsing C Code file." + \ os.linesep + message super().__init__(self.__message) class ParseFunctionFromCode(object): def __init__(self): self.__fileDataWhole = None # Parsed list of functions # lists self.__dataFoundedVoid = None self.__dataFoundedChar = None self.__dataFoundedInteger = None self.__dataFoundedStruct = None self.__dataFoundedCustom = None # Parsed functions STATISTICS self.__countFunctionVoid = None self.__countFunctionInteger = None self.__countFunctionChar = None self.__countFunctionStruct = None # Configs for Data holder dictionary self.__objConfigMain = ConfigMain() self.__configDictKeyVoid = self.__objConfigMain.configDictKeyVoid self.__configDictKeyChar = self.__objConfigMain.configDictKeyChar self.__configDictKeyInteger = self.__objConfigMain.configDictKeyInteger self.__configDictKeyStruct = self.__objConfigMain.configDictKeyStruct self.__configDictKeyCustom = self.__objConfigMain.configDictKeyCustom self.__dataHolderFunctionsDictList = dict() def setValueCCodeFile(self, fileNameCCode): self.__fileDataWhole = fileNameCCode def regexpOneGetFunctionName(self): functionRe = 'void ([a-zA-Z_]+\([a-z0-9|_\ ,\*+]+\))' generalFunctionRegExp = r'' dataMatched = re.findall(functionRe, str(self.__fileDataWhole)) print("Data matched count: {0}".format(len(dataMatched))) for findedString in dataMatched: print(">function: {0}".format(findedString)) def __countFunctionsForStatistics(self): self.__countFunctionVoid = len(self.__dataFoundedVoid) self.__countFunctionChar = len(self.__dataFoundedChar) self.__countFunctionInteger = len(self.__dataFoundedInteger) self.__countFunctionStruct = len(self.__dataFoundedStruct) def __printFunctionStatistics(self): print(">>C Functions count void: {0}".format( self.__countFunctionVoid)) print(">>C Functions count Integer: {0}".format( self.__countFunctionInteger)) print(">>C Functions count Char: {0}".format( self.__countFunctionChar)) print(">>C Functions count Struct: {0}".format( self.__countFunctionStruct)) def regexpOneGetFunctionTypeAll(self): functionReVoid = re.compile(r'(void\ [a-zA-Z_\*]+\([a-z0-9|_\ ,\*+]+\))') functionReInt = re.compile(r'(int64\_t\ [a-zA-Z_\*]+\([a-z0-9|_\ ,\*+]+\))') functionReChar = re.compile(r'(char\ [a-zA-Z_\*]+\([a-z0-9|_\ ,\*+]+\))') functionReStruct = re.compile(r'(struct\ [a-z\_\ \*]+\ [a-zA-Z_\*]+\([a-z0-9|_\ ,\*+]+\))') self.__dataFoundedVoid = functionReVoid.findall(str(self.__fileDataWhole)) self.__dataFoundedInteger = functionReInt.findall(str(self.__fileDataWhole)) self.__dataFoundedChar = functionReChar.findall(str(self.__fileDataWhole)) self.__dataFoundedStruct = functionReStruct.findall(str(self.__fileDataWhole)) # run private method self.__countFunctionsForStatistics() print("Type variable: {0}".format(type(self.__dataFoundedVoid))) if self.__dataFoundedVoid is not None: self.__dataHolderFunctionsDictList[self.__configDictKeyVoid] = \ self.__dataFoundedVoid if self.__dataFoundedInteger is not None: self.__dataHolderFunctionsDictList[self.__configDictKeyInteger] = \ self.__dataFoundedInteger if self.__dataFoundedChar is not None: self.__dataHolderFunctionsDictList[self.__configDictKeyChar] = \ self.__dataFoundedChar if self.__dataFoundedStruct is not None: self.__dataHolderFunctionsDictList[self.__configDictKeyStruct] = \ self.__dataFoundedStruct # run private method self.__countFunctionsForStatistics() self.__printFunctionStatistics() def getResultDataDictionaryList(self): if self.__dataHolderFunctionsDictList is not None: return self.__dataHolderFunctionsDictList else: raise ExceptionParseCFunction("The Parsed Dictionary is None.") class UtilityHeader(object): def __init__(self): self.__fileNameHeader = None def boolFileExists(self, fileNameHeader): self.__fileNameHeader = fileNameHeader if os.path.isfile(self.__fileNameHeader) is True: return True else: return False class HeaderFileMacro(object): def __init__(self): self.__startMacroIfNDef = "#ifndef" self.__startMacroDefine = "#define" self.__endMacroDefine = "#endif" self.__endHeaderFileName = "_H__" self.__startHeaderFileName = "__" self.__buildedStringFileName = "" self.__buildedHeaderMacro = "" self.__headerFileName = None self.__objConfigMain = ConfigMain() self.__configHeaderFileExt = self.__objConfigMain.\ configFileExtensionHeader self.__headerFileNameNoExtension = None self.__headerFileNameUpperCase = None def setValueHeaderFileName(self, headerFileName): self.__headerFileName = headerFileName def __removeExtension(self): self.__headerFileNameNoExtension = self.__headerFileName.rstrip( self.__configHeaderFileExt) print("Data: {0}".format(self.__headerFileNameNoExtension)) def __makeUpperCaseFileName(self): self.__headerFileNameUpperCase = str(self.__headerFileNameNoExtension)\ .upper() print("Upper Case file name: {0}".format( self.__headerFileNameUpperCase)) def __buildFileNameMacro(self): self.__buildedStringFileName = self.__startHeaderFileName + \ self.__headerFileNameUpperCase + self.__endHeaderFileName def __buildHeaderMacroDefines(self): self.__buildedHeaderMacro = self.__startMacroIfNDef + str(" ") + \ self.__buildedStringFileName + os.linesep +\ self.__startMacroDefine + str(" ") +\ self.__buildedStringFileName + \ os.linesep + os.linesep def createStartHeaderMacro(self): self.__removeExtension() self.__makeUpperCaseFileName() # now from the JSONPREPROCESSOR is ready self.__buildFileNameMacro() self.__buildHeaderMacroDefines() print(self.__buildedHeaderMacro) return self.__buildedHeaderMacro def createEndHeaderMacro(self): self.__buildedHeaderEnd = self.__endMacroDefine + os.linesep return self.__buildedHeaderEnd class HeaderFileInclude(object): def __init__(self): self.__headerFileData = None self.__stringIncludes = "" self.__includesList = list() self.__includeSystemList = list() self.__includeCustomList = list() def setValueHeaderFileData(self, headerFileData): self.__headerFileData = headerFileData def __getIncludeSystemFromLine(self, inputDataLine): # #include <stdio.h> regExpIncludeSystem = r'\#include \<[a-zA-Z].+\.h\>' regExpIncludeSystemCompiled = re.compile(regExpIncludeSystem) matchedObject = re.match(regExpIncludeSystemCompiled, inputDataLine) if matchedObject is not None: self.__includeSystemList.append(inputDataLine) def __getIncludeCustomFromLine(self, inputDataLine): # #include "customheader.h" regExpIncludeCustom = r'\#include\"[a-zA-Z]\.+\.h\"' regExpIncludeCustomCompiled = re.compile(regExpIncludeCustom) matchedObject = re.match(regExpIncludeCustomCompiled, inputDataLine) if matchedObject is not None: self.__includeCustomList.append(inputDataLine) def readFileByLine(self): for oneRawLine in self.__headerFileData: stripOsLinesep = oneRawLine.rstrip(os.linesep) print(stripOsLinesep) self.__getIncludeSystemFromLine(stripOsLinesep) self.__getIncludeCustomFromLine(stripOsLinesep) def getResultIncludeSystemList(self): if self.__includeSystemList is not None: return self.__includeSystemList def getResultIncludeCustomList(self): if self.__includeCustomList is not None: return self.__includeCustomList def getResultIncludeAllList(self): if len(self.__includeSystemList) > 0: self.__includesList = self.__includeSystemList if len(self.__includeCustomList) > 0: for cIncludes in self.__includeSystemList: self.__includesList.append(cIncludes) if len(self.__includesList) > 0: return self.__includesList else: return None class ExceptionSourceDir(Exception): def __init__(self, message): self.__message = "Exception occured in SourceDir reader. " \ + os.linesep + \ "The return variable is None." \ + os.linesep super().__init__(self.__message) class ReadSourceCodeDirectory(object): def __init__(self): self.__dataHolder__listDictSrource = list() self.__dataHolder__sortedListDictSource = list() self.__sourceDirectory = None self.__objConfigMain = ConfigMain() self.__confDictKeyCCodeFileName = self.__objConfigMain.\ dictKeyDataHolderFileNameCode self.__confDictKeyHeaderFileName = self.__objConfigMain.\ dictKeyDataHolderFileNameHeader self.__confDictKeyCCodePath = self.__objConfigMain.\ dictKeyDataHolderFilePathCode self.__confDictKeyHeaderPath = self.__objConfigMain.\ dictKeyDataHolderFilePathHeader self.__configExtensionHeader = self.__objConfigMain.\ configFileExtensionHeader self.__configExtensionC = self.__objConfigMain.\ configFileExtensionC self.__configFileName = "FileName" self.__configFilePath = "FilePath" def setValueSourceDirectory(self, sourceDirectory): self.__sourceDirectory = sourceDirectory def readDirectory(self): for rootDir, dirNames, fileNames in os.walk(self.__sourceDirectory): for fileName in fileNames: fileDataDict = dict() # print("File: {0}".format(fileName)) fileDataDict[self.__configFileName] = fileName fileDataDict[self.__configFilePath] = rootDir self.__dataHolder__listDictSrource.append(fileDataDict) def __boolValueInDict(self, checkValue): for item in self.__dataHolder__listDictSrource: fileName = item[self.__configFileName] if fileName == checkValue: return fileName def __changeExtensionFromCToHeader(self, cFileName): noExtensionFileName = cFileName.rstrip(self.__configExtensionC) headerFileName = noExtensionFileName + str( self.__configExtensionHeader) return headerFileName def sortSourceHeaderFiles(self): for item in self.__dataHolder__listDictSrource: dataDictPairedFileCAndHeader = dict() fileNameRaw = item[self.__configFileName] filePath = item[self.__configFilePath] if fileNameRaw.endswith(self.__configExtensionC): fileNameHeader = self.__changeExtensionFromCToHeader( fileNameRaw) isHeaderFileExists = self.__boolValueInDict(fileNameHeader) if isHeaderFileExists: dataDictPairedFileCAndHeader[ self.__confDictKeyCCodeFileName] = fileNameRaw dataDictPairedFileCAndHeader[ self.__confDictKeyHeaderFileName] = fileNameHeader dataDictPairedFileCAndHeader[ self.__confDictKeyCCodePath] = filePath self.__dataHolder__sortedListDictSource.append( dataDictPairedFileCAndHeader) def debugDumpSortedListDictionary(self): for element in self.__dataHolder__sortedListDictSource: print(element) def getResultCCodeHeaderFiles(self): if self.__dataHolder__sortedListDictSource is not None: return self.__dataHolder__sortedListDictSource else: raise ExceptionSourceDir("In Source Dir: {0} the result is empty." .format(self.__sourceDirectory)) sys.exit(1) class RunnerMain(object): def __init__(self): self.__objCCode = ParseFunctionFromCode() self.__objGenerateHeader = HeaderFileContentGenerator() self.__objCFileReader = FileContentReader() self.__objHFileReader = FileContentReader() self.__objHeaderMacro = HeaderFileMacro() self.__objConfigMain = ConfigMain() self.__objSourceDir = ReadSourceCodeDirectory() self.__objHeaderContentWriter = HeaderFileContentWriter() self.__objHeaderFileInclude = None self.__CCodeFileName = None self.__hHeaderFileName = None self.__fileDataWhole = None self.__dataHolderCFunctions = dict() # HEADER files Start / End Macros Data Holders self.__dhStartMacro = "" self.__dhEndMacro = "" self.__dhSysIncludeLst = list() self.__dhCustomIncludeLst = list() self.__dataHolderIncludeList = list() self.__boolHeaderExists = False self.__headerFileBufferString = "" self.__dataHolder__listDictSourceDir = list() self.__confDictKeyCCodePath = self.__objConfigMain.\ dictKeyDataHolderFilePathCode self.__confDictKeyHeaderPath = self.__objConfigMain.\ dictKeyDataHolderFilePathHeader self.__confDictKeyCCodeFileName = self.__objConfigMain.\ dictKeyDataHolderFileNameCode self.__confDictKeyHeaderFileName = self.__objConfigMain.\ dictKeyDataHolderFileNameHeader self.__headerFileAndPath = None def __handleHeaderFile(self, pathAndHeaderFile, fileNameHeader): # generate Start Macro self.__objHeaderMacro.setValueHeaderFileName(fileNameHeader) self.__dhStartMacro = self.__objHeaderMacro.createStartHeaderMacro() # generate End Macro self.__dhEndMacro = self.__objHeaderMacro.createEndHeaderMacro() # self.__hHeaderFileName = fileNameHeader # The Utility class Need Path to Headder file, # self.__boolHeaderExists = UtilityHeader().boolFileExists( # self.__hHeaderFileName) self.__boolHeaderExists = UtilityHeader().boolFileExists( pathAndHeaderFile) if self.__boolHeaderExists is True: # The read File need also the Header file and path # headerFileContent = self.__objHFileReader.readDataWholeFile( # self.__hHeaderFileName) headerFileContent = self.__objHFileReader.readDataWholeFile( pathAndHeaderFile) # get the #includes from previous header file self.__objHeaderFileInclude = HeaderFileInclude() self.__objHeaderFileInclude.setValueHeaderFileData( headerFileContent) self.__objHeaderFileInclude.readFileByLine() dhIncludeList = self.__objHeaderFileInclude.\ getResultIncludeAllList() if dhIncludeList is not None: self.__dataHolderIncludeList = dhIncludeList else: self.__dataHolderIncludeList = None # includes ready # C Code Helper method def __readOneCCodeFile(self,pathAndCCodeFile): self.__fileDataWhole = self.__objCFileReader.readDataWholeFile( pathAndCCodeFile) self.__objCCode.setValueCCodeFile(self.__fileDataWhole) self.__objCCode.regexpOneGetFunctionTypeAll() self.__dataHolderCFunctions = self.__objCCode. \ getResultDataDictionaryList() # Main worker method def buildHeaderFileAll(self, filePathOnly, cCodeFileName, hHeaderFileName): self.__headerFileAndPath = os.path.join(filePathOnly, hHeaderFileName) self.__cCodeFileAndPath = os.path.join(filePathOnly, cCodeFileName) # patch self.__handleHeaderFile(self.__headerFileAndPath, hHeaderFileName) self.__readOneCCodeFile(self.__cCodeFileAndPath) # HEADER IF Macros self.__headerFileBufferString = self.__dhStartMacro # ADD INCLUDES if self.__dataHolderIncludeList is not None: for includes in self.__dataHolderIncludeList: self.__headerFileBufferString += includes + os.linesep self.__headerFileBufferString += os.linesep # C Code function ADDING for value in self.__dataHolderCFunctions.values(): for item in value: # print("Value: {0}".format(item)) self.__headerFileBufferString += item + ";" + os.linesep # Add End Macro self.__headerFileBufferString += self.__dhEndMacro # the Header File Content String Buffer now READY # Need also Path and Header file name self.__objHeaderContentWriter.openFileWrite(self.__headerFileAndPath) self.__objHeaderContentWriter.writeOutData(self.__headerFileBufferString) def debugPrintOutOneHeaderFile(self): print(">>> NEW HEADER FILE >>>") print(self.__headerFileBufferString) print(">>> END NEW HEADER FILE >>>") def readSourceDir(self, sourceCodeDirectory): self.__objSourceDir.setValueSourceDirectory(sourceCodeDirectory) self.__objSourceDir.readDirectory() self.__objSourceDir.sortSourceHeaderFiles() # self.__objSourceDir.debugDumpSortedListDictionary() self.__dataHolder__listDictSourceDir = self.__objSourceDir.\ getResultCCodeHeaderFiles() actualElementHeader = "" actualElementCCode = "" actualElementPath = "" for entryFile in self.__dataHolder__listDictSourceDir: for dictKey, fsValue in entryFile.items(): if dictKey == self.__confDictKeyCCodeFileName: actualElementCCode = fsValue if dictKey == self.__confDictKeyHeaderFileName: actualElementHeader = fsValue if dictKey == self.__confDictKeyCCodePath: actualElementPath = fsValue print("Passing Path: {0} file C: {1}, Header: {2}" .format(actualElementPath, actualElementCCode, actualElementHeader)) self.buildHeaderFileAll(actualElementPath, actualElementCCode, actualElementHeader) if __name__ == '__main__': runnerMain = RunnerMain() # runnerMain.buildHeaderFileAll(sys.argv[1], sys.argv[2]) # runnerMain.debugPrintOutOneHeaderFile() runnerMain.readSourceDir(sys.argv[1])