#!/usr/bin/python import lutinDebug as debug import sys import lutinTools import CppHeaderParser import re import codeBB import collections global_class_link = { "std::string" : "http://www.cplusplus.com/reference/string/string/", "std::u16string" : "http://www.cplusplus.com/reference/string/u16string/", "std::u32string" : "http://www.cplusplus.com/reference/string/u32string/", "std::wstring" : "http://www.cplusplus.com/reference/string/wstring/", "std::vector" : "http://www.cplusplus.com/reference/vector/vector/" } def replace_type(match): value = "" + match.group() + "" return value def replace_storage_keyword(match): value = "" + match.group() + "" return value def display_color(valBase): # storage keyword : p = re.compile("(inline|const|class|virtual|private|public|protected|friend|const|extern|auto|register|static|volatile|typedef|struct|union|enum)") val = p.sub(replace_storage_keyword, valBase) # type : p = re.compile("(bool|BOOL|char(16_t|32_t)?|double|float|u?int(8|16|32|64|128)?(_t)?|long|short|signed|size_t|unsigned|void|(I|U)(8|16|32|64|128))") val = p.sub(replace_type, val) return val, len(valBase) def display_type(type, myDoc): type = type.replace("inline ", "") lenght = 0; isFirst = True out = '' # we split all the element in list sepa=rated with space to keep class... and standard c+ class for element in type.split(' '): if isFirst == False: out += " " lenght += 1 isFirst = False # check if the element in internal at the current lib name, link = myDoc.get_class_link(element) if len(link) != 0: out += "" + name + "" lenght += len(element) # Ckeck if the variable in a standard class: elif element in global_class_link.keys(): out += "" + element + "" lenght += len(element) else: data, lenghtTmp = display_color(element) out += data lenght += lenghtTmp # get every subelement class : return [out,lenght] def display_doxygen_param(comment, input, output): data = "Parameter" if input == True: data += " [input]" if output == True: data += " [output]" data += ": " #extract first element: val = comment.find(" ") var = comment[:val] endComment = comment[val:] # TODO : Check if it exist in the parameter list ... data += "" + var + " " + endComment data += "
" return data def parse_doxygen(data) : pos = data.find("/*"); if pos > 0: data = data[pos:] if data[0] == '/' \ and data[1] == '*' \ and data[2] == '*': data = data[3:len(data)-2] data = data.replace("\n** ", "\n") data = data.replace("\n**", "\n") data = data.replace("\n* ", "\n") data = data.replace("\n*", "\n") data = data.replace("\n ** ", "\n") data = data.replace("\n **", "\n") data = data.replace("\n * ", "\n") data = data.replace("\n *", "\n") data = data.replace("\r", '') streams = data.split("@") data2 = '' for element in streams: if element[:1] == "\n" \ or element[:2] == "\n\n": # nothing to do : Nomale case of the first \n None elif element[:6] == "brief ": data2 += element[6:] data2 += "
" for element in streams: if element[:1] == "\n" \ or element[:2] == "\n\n": # nothing to do : Nomale case of the first \n None elif element[:5] == "note ": data2 += "Notes: " data2 += element[5:] data2 += "
" data3 = '' for element in streams: if element[:1] == "\n" \ or element[:2] == "\n\n": # nothing to do : Nomale case of the first \n None elif element[:14] == "param[in,out] " \ or element[:14] == "param[out,in] ": data3 += display_doxygen_param(element[14:], True, True) elif element[:10] == "param[in] ": data3 += display_doxygen_param(element[10:], True, False) elif element[:11] == "param[out] ": data3 += display_doxygen_param(element[11:], False, True) elif element[:6] == "param ": data3 += display_doxygen_param(element[6:], False, False) elif element[:7] == "return ": data3 += "Return: " data3 += element[7:] data3 += "
" if data3 != '': data2 += "\n" return data2 def white_space(size) : ret = '' for iii in range(len(ret), size): ret += " " return ret def display_reduct_function(function, file, classement, sizeReturn, sizefunction, myDoc) : file.write(classement + " ") lenght = len(classement)+1; if function['destructor'] : file.write(white_space(sizeReturn) + "~") lenght += sizeReturn+1; elif function['constructor'] : file.write(white_space(sizeReturn+1)) lenght += sizeReturn+1; else : typeData, typeLen = display_type(function["rtnType"], myDoc); file.write(typeData) file.write(white_space(sizeReturn+1 - typeLen)) lenght += sizeReturn+1; parameterPos = lenght + sizefunction+2; file.write("" + function["name"] + "") file.write(white_space(sizefunction+1 - len(function["name"]))) file.write("(") isFirst = True for param in function["parameters"]: if isFirst == False: file.write(",
") file.write(white_space(parameterPos)) typeData, typeLen = display_type(param["type"], myDoc); file.write(typeData) if param['name'] != "": file.write(" ") file.write("" + param['name'] + "") isFirst = False file.write(");") file.write("
") def displayFunction(namespace, function, file, classement, sizeReturn, sizefunction, myDoc) : lineData = "" if ( function['constructor'] == True \ or function['destructor'] == True \ or function['static'] == True ) \ and namespace != "": lineData = namespace + "::" if function['destructor'] : lineData += "~" lineData +="" + function["name"] + " ()" file.write("

" + lineData + "

\n\n") file.write("
\n");
	if function['destructor'] :
		file.write("~")
		lenght = 1;
	elif function['constructor'] :
		lenght = 0;
	else :
		typeData, typeLen = display_type(function["rtnType"], myDoc);
		file.write(typeData + " ")
		lenght = typeLen+1;
	
	parameterPos = lenght + len(function["name"]) + 1;
	file.write("" + function["name"] + "(")
	isFirst = True
	for param in function["parameters"]:
		if isFirst == False:
			file.write(",\n")
			file.write(white_space(parameterPos))
		typeData, typeLen = display_type(param["type"], myDoc);
		file.write(typeData)
		if param['name'] != "":
			file.write(" ")
			file.write("" + param['name'] + "")
		isFirst = False
	file.write(");")
	file.write("
\n"); file.write("
\n") if "doxygen" in function: # TODO : parse doxygen ... file.write(parse_doxygen(function["doxygen"])) file.write("
\n") def calsulateSizeFunction(function, size) : if len(function["name"]) > size: return len(function["name"])+1 return size def calsulateSizeReturn(function, size) : if len(function["rtnType"]) > size: return len(function["rtnType"])+1 return size def class_name_to_file_name(className): className = className.replace(":", "_") className = className.replace(" ", "") className += ".html" return className """ """ def addElement(elementList, tree): if elementList[0] in tree.keys(): tree[elementList[0]] == addElement(elementList[1:], tree[elementList[0]]) else : tree[elementList[0]] == elementList[0] if len(elementList) != 1: tree[elementList[0]] == addElement(elementList[1:], tree[elementList[0]]) return tree def recursively_default_dict(): return collections.defaultdict(recursively_default_dict) def createTree(list): output = [] myTree = recursively_default_dict() #myTree['a']['b'] = 'c' for className in sorted(list) : list = className.split("::") if len(list)==1: myTree[list[0]] == className elif len(list)==2: myTree[list[0]][list[1]] == className elif len(list)==3: myTree[list[0]][list[1]][list[2]] == className elif len(list)==4: myTree[list[0]][list[1]][list[2]][list[3]] == className elif len(list)==5: myTree[list[0]][list[1]][list[2]][list[3]][list[4]] == className else: myTree[list[0]][list[1]][list[2]][list[3]][list[4]][list[5]] == className #output.append(className.split("::")) #myTree = addElement(className.split("::"), myTree) #debug.info("plop" + str(myTree)) return myTree def addSub(tree, filterSubNamespace=False): return "" def generate(myDoc, outFolder) : lutinTools.CopyFile(lutinTools.GetCurrentPath(__file__)+"/theme/base.css", outFolder+"/base.css") lutinTools.CopyFile(lutinTools.GetCurrentPath(__file__)+"/theme/menu.css", outFolder+"/menu.css") # create common header genericHeader = "\n" genericHeader += "\n" genericHeader += "\n" genericHeader += " \n" genericHeader += " " + myDoc.moduleName + " Library\n" genericHeader += " \n" genericHeader += " \n" genericHeader += "\n" genericHeader += "\n" genericHeader += "
\n" genericHeader += "
\n" genericHeader += "

" + myDoc.moduleName + " Library

\n" genericHeader += ' \n' """ genericHeader += '

\n' genericHeader += '
\n' genericHeader += "
\n" genericHeader += " \n" genericHeader += "
\n" genericFooter = "
\n" genericFooter += "\n" genericFooter += "\n" # create index.hml : file = open(outFolder + "/index.html", "w") file.write(genericHeader) file.write("

" + myDoc.moduleName + "

"); file.write("
"); file.write("TODO : Main page ..."); file.write("
"); file.write("
"); file.write(genericFooter) file.close(); for className in sorted(myDoc.listClass.iterkeys()) : localClass = myDoc.listClass[className] debug.debug(" class: " + className) classFileName = outFolder + "/" + class_name_to_file_name(className) # create directory (in case) lutinTools.CreateDirectoryOfFile(classFileName); debug.printElement("doc", myDoc.moduleName, "<==", className) # open the file : file = open(classFileName, "w") file.write(genericHeader) file.write("

Class: " + className + "

\n") file.write("
\n") # calculate function max size return & function name size: sizeReturn=0 sizefunction=0 for function in localClass["methods"]["public"]: sizefunction = calsulateSizeFunction(function, sizefunction) sizeReturn = calsulateSizeReturn(function, sizeReturn) for function in localClass["methods"]["protected"]: sizefunction = calsulateSizeFunction(function, sizefunction) sizeReturn = calsulateSizeReturn(function, sizeReturn) for function in localClass["methods"]["private"]: sizefunction = calsulateSizeFunction(function, sizefunction) sizeReturn = calsulateSizeReturn(function, sizeReturn) file.write("

Constructor and Destructor:

\n") file.write("
\n");
		for function in localClass["methods"]["public"]:
			if    function['destructor'] \
			   or function['constructor'] :
				display_reduct_function(function, file, "+ ", sizeReturn, sizefunction, myDoc)
		for function in localClass["methods"]["protected"]:
			if    function['destructor'] \
			   or function['constructor'] :
				display_reduct_function(function, file, "# ", sizeReturn, sizefunction, myDoc)
		for function in localClass["methods"]["private"]:
			if    function['destructor'] \
			   or function['constructor'] :
				display_reduct_function(function, file, "- ", sizeReturn, sizefunction, myDoc)
		
		file.write("
\n"); file.write("

Synopsis:

\n") # display all functions : # TODO: ... file.write("
\n");
		for function in localClass["methods"]["public"]:
			if     not function['destructor'] \
			   and not function['constructor'] :
				display_reduct_function(function, file, "+ ", sizeReturn, sizefunction, myDoc)
		for function in localClass["methods"]["protected"]:
			if     not function['destructor'] \
			   and not function['constructor'] :
				display_reduct_function(function, file, "# ", sizeReturn, sizefunction, myDoc)
		for function in localClass["methods"]["private"]:
			if     not function['destructor'] \
			   and not function['constructor'] :
				display_reduct_function(function, file, "- ", sizeReturn, sizefunction, myDoc)
		file.write("
\n"); file.write("\n") file.write("\n") heritage = myDoc.get_heritage_list(className) heritageDown = myDoc.get_down_heritage_list(className) if len(heritage) > 1 \ or len(heritageDown) > 0: file.write("

Object Hierarchy:

\n") file.write("
\n")
			level = 0;
			for heritedClass in heritage:
				if level != 0:
					file.write(white_space(level*4) + "+--> ")
				if heritedClass != className:
					name, link = myDoc.get_class_link(heritedClass)
					file.write("" + name + "\n")
				else:
					file.write("" + heritedClass + "\n")
				level += 1;
			for heritedClass in heritageDown:
				file.write(white_space(level*4) + "+--> ")
				name, link = myDoc.get_class_link(heritedClass)
				file.write("" + name + "\n")
			file.write("
\n") file.write("
\n") """ file.write("

Signals:

\n") # display all signals : # TODO: ... file.write("

Configuration:

\n") # display all configuration : # TODO: ... """ if "doxygen" in localClass: file.write("

Description:

\n") # display Class description : file.write(localClass["doxygen"]) file.write("

Detail:

\n") # display all the class internal functions : for function in localClass["methods"]["public"]: displayFunction(localClass['namespace'] , function, file, "+ ", sizeReturn, sizefunction, myDoc) file.write("\n
\n") for function in localClass["methods"]["protected"]: displayFunction(localClass['namespace'] , function, file, "# ", sizeReturn, sizefunction, myDoc) file.write("\n
\n") for function in localClass["methods"]["private"]: displayFunction(localClass['namespace'] , function, file, "- ", sizeReturn, sizefunction, myDoc) file.write("\n
\n") file.write(genericFooter) file.close() for enumName in sorted(myDoc.listEnum.iterkeys()) : localEnum = myDoc.listEnum[enumName] debug.debug(" enum: " + enumName) fileName = outFolder + "/" + class_name_to_file_name(enumName) # create directory (in case) lutinTools.CreateDirectoryOfFile(fileName); debug.printElement("doc", myDoc.moduleName, "<==", enumName) # open the file : file = open(fileName, "w") file.write(genericHeader) file.write("

Enum: " + enumName + "

\n") file.write("
\n") file.write("Value :
\n") file.write("\n") file.write(genericFooter) file.close() for docInputName,outpath in myDoc.listDocFile : debug.printElement("doc", myDoc.moduleName, "<==", docInputName) outputFileName = outFolder + "/" + outpath.replace('/','_') +".html" debug.debug("output file : " + outputFileName) lutinTools.CreateDirectoryOfFile(outputFileName) inData = lutinTools.FileReadData(docInputName) if inData == "": continue outData = genericHeader + codeBB.transcode(inData) + genericFooter lutinTools.FileWriteData(outputFileName, outData) for docInputName,outpath in myDoc.listTutorialFile : debug.printElement("tutorial", myDoc.moduleName, "<==", docInputName) outputFileName = outFolder + "/" + outpath+".html" debug.debug("output file : " + outputFileName) lutinTools.CreateDirectoryOfFile(outputFileName) inData = lutinTools.FileReadData(docInputName) if inData == "": continue outData = genericHeader + codeBB.transcode(inData) + genericFooter lutinTools.FileWriteData(outputFileName, outData)