diff --git a/tools/normalizeFortranFile.py b/tools/normalizeFortranFile.py new file mode 100755 index 0000000000..1804c5c0db --- /dev/null +++ b/tools/normalizeFortranFile.py @@ -0,0 +1,664 @@ +#! /usr/bin/env python + +import sys +import re +import string +from sys import argv +from cStringIO import StringIO + +varRe=re.compile(r" *(?P[a-zA-Z_0-9]+) *(?P(?:\((?P(?:[^()]+|\((?:[^()]+|\([^()]*\))*\))*)\))? *(?:= *(?P(:?[^\"',()]+|\((?:[^()\"']+|\([^()\"']*\)|\"[^\"]*\"|'[^']*')*\)|\"[^\"]*\"|'[^']*')+))?)? *(?:(?P,)|\n?) *",re.IGNORECASE) +useParseRe=re.compile( + r" *use +(?P[a-zA-Z_][a-zA-Z_0-9]*)(?P *, *only *:)? *(?P.*)$", + flags=re.IGNORECASE) + +def readFortranLine(infile): + """Reads a group of connected lines (connected with &) + returns a touple with the joined line, and a list with the original lines. + Doesn't support multiline character constants!""" + lineRe=re.compile( + r"(?:(?P#.*\n?)| *(&)?(?P(?:[^&!\"']+|\"[^\"]*\"|'[^']*')*)(?P&)? *(?P!.*\n?)?\n?)",#$ + re.IGNORECASE) + joinedLine="" + comments=None + lines=[] + while 1: + line=infile.readline() + if not line: break + m=lineRe.match(line) + if not m or m.span()[1]!=len(line): + raise SyntaxError("unexpected line format:"+repr(line)) + if m.group("preprocessor"): + if len(lines)>0: + raise SyntaxError("continuation to a preprocessor line not supported "+repr(line)) + lines.append(line) + comments=line + break + joinedLine+=m.group("core") + lines.append(line) + if m.group("comment"): + if comments: + comments+=m.group("comment") + else: + comments=m.group("comment") + if not m.group("continue"): break + return (joinedLine,comments,lines) + +def parseRoutine(inFile): + """Parses a routine""" + startRe=re.compile(r" *(?:recursive +|pure +|elemental +)*(?:subroutine|function)",re.IGNORECASE) + endRe=re.compile(r" *end (?:subroutine|function)",re.IGNORECASE) + startRoutineRe=re.compile(r" *(?:recursive +|pure +|elemental +)*(?Psubroutine|function) +(?P[a-zA-Z_][a-zA-Z_0-9]*) *(?:\((?P[^()]*)\))? *(?:result *\( *(?P[a-zA-Z_][a-zA-Z_0-9]*) *\))? *\n?",re.IGNORECASE)#$ + typeBeginRe=re.compile(r" *(?Pinteger(?: *\* *[0-9]+)?|logical|character(?: *\* *[0-9]+)?|real(?: *\* *[0-9]+)?|complex(?: *\* *[0-9]+)?|type)", + re.IGNORECASE) + typeRe=re.compile(r" *(?Pinteger(?: *\* *[0-9]+)?|logical|character(?: *\* *[0-9]+)?|real(?: *\* *[0-9]+)?|complex(?: *\* *[0-9]+)?|type) *(?P\((?:[^()]+|\([^()]*\))*\))? *(?P(?: *, *[a-zA-Z_0-9]+(?: *\((?:[^()]+|\((?:[^()]+|\([^()]*\))*\))*\))?)+)? *(?P::)?(?P[^\n]+)\n?",re.IGNORECASE)#$ + attributeRe=re.compile(r" *, *(?P[a-zA-Z_0-9]+) *(?:\( *(?P(?:[^()]+|\((?:[^()]+|\([^()]*\))*\))*)\))? *",re.IGNORECASE) + ignoreRe=re.compile(r" *(?:|implicit +none *)$",re.IGNORECASE) + interfaceStartRe=re.compile(r" *interface *$",re.IGNORECASE) + interfaceEndRe=re.compile(r" *end +interface *$",re.IGNORECASE) + routine={'preRoutine':[], + 'core':[], + 'strippedCore':[], + 'begin':[], + 'end':[], + 'declarations':[], + 'declComments':[], + 'parsedDeclarations':[], + 'postRoutine':[], + 'kind':None,'name':None,'arguments':None,'result':None, + 'interfaceCount':0, + 'use':[] + } + while 1: + (jline,comments,lines)=readFortranLine(inFile) + if len(lines)==0: break + if startRe.match(jline):break + routine['preRoutine'].extend(lines) + if jline: + routine['begin']=lines + m=startRoutineRe.match(jline) + if not m or m.span()[1]!=len(jline): + raise SyntaxError("unexpected subroutine start format:"+repr(lines)) + routine['name']=m.group('name') + routine['kind']=m.group('kind') + if (m.group('arguments') and m.group('arguments').strip()): + routine['arguments']=map(lambda x: x.strip(), + m.group('arguments').split(",")) + if (m.group('result')): + routine['result']=m.group('result') + if (not routine['result'])and(routine['kind'].lower()=="function"): + routine['result']=routine['name'] + while 1: + (jline,comments,lines)=readFortranLine(inFile) + if len(lines)==0: break + if not ignoreRe.match(jline): + if typeBeginRe.match(jline): + m=typeRe.match(jline) + if (m.group('type').lower()=='type' and + not m.group('parameters')): + break + if not m or m.span()[1]!=len(jline): + raise SyntaxError("unexpected type format:"+repr(jline)) + decl={'type':m.group("type"), + 'parameters':None, + 'attributes':[], + 'vars':[]} + if m.group('parameters'): + decl['parameters']=(m.group("parameters").replace(" ",""). + replace(",",", ")) + str=m.group("attributes") + while(str): + m2=attributeRe.match(str) + if not m2: + raise SyntaxError("unexpected attribute format "+ + repr(str)+" in "+repr(lines)) + decl['attributes'].append(m2.group().replace(" ",""). + replace(",",", ")[2:]) + str=str[m2.span()[1]:] + str=m.group("vars") + while 1: + m2=varRe.match(str) + if not m2: + raise SyntaxError("unexpected var format "+ + repr(str)+" in "+repr(lines)) + var=m2.group("var") + if m2.group("param"):var+="("+m2.group("param")+")" + if m2.group("value"): + var+=" = " + var+=m2.group("value") + decl['vars'].append(var) + str=str[m2.span()[1]:] + if not m2.group("continue"): + if str: + raise SyntaxError("error parsing vars (leftover="+ + repr(str)+") in "+repr(lines)) + break + routine['parsedDeclarations'].append(decl) + elif interfaceStartRe.match(jline): + istart=lines + interfaceDeclFile=StringIO() + while 1: + (jline,comments,lines)=readFortranLine(inFile) + if interfaceEndRe.match(jline): + iend=lines + break + interfaceDeclFile.writelines(lines) + interfaceDeclFile=StringIO(interfaceDeclFile.getvalue()) + iroutines=[] + while 1: + iroutine=parseRoutine(interfaceDeclFile) + if not iroutine['kind']: + if len(iroutines)==0: + interfaceDeclFile.seek(0) + raise SyntaxError("error parsing interface:"+ + repr(interfaceDeclFile.read())) + iroutines[-1]['postRoutine'].extend(iroutine['preRoutine']) + break + iroutines.append(iroutine) + for iroutine in iroutines: + routine['interfaceCount']+=1 + decl={'type':'z_interface%02d'%(routine['interfaceCount']), + 'parameters':None, + 'attributes':[], + 'vars':[iroutine['name']], + 'iroutine':iroutine, + 'istart':istart, + 'iend':iend + } + routine['parsedDeclarations'].append(decl) + elif useParseRe.match(jline): + routine['use'].append("".join(lines)) + else: + break + routine['declarations'].append("".join(lines)) + if comments: + routine['declComments'].append(comments) + while len(lines)>0: + if endRe.match(jline): + routine['end']=lines + break + routine['strippedCore'].append(jline) + routine['core'].append("".join(lines)) + (jline,comments,lines)=readFortranLine(inFile) + return routine + +def findWord(word,text): + """Returns the position of word in text or -1 if not found. + A match is valid only if it is a whole word (i.e. findWord('try','retry') + returns false)""" + pos=text.find(word) + while((pos>0 and (text[pos-1].isalnum() or + (text[pos-1]=='_' and (pos==1 or text[pos-2].isalpha())) + )) or + (pos>=0 and pos+len(word)1: + newDecl={} + newDecl.update(declarations[idecl]) + newDecl['vars']=[declarations[idecl]['vars'][ivar]] + declarations.insert(idecl2+1,newDecl) + del declarations[idecl]['vars'][ivar] + else: + declarations.insert(idecl2+1, + declarations[idecl]) + del declarations[idecl] + ivar=0 + moved=1 + break + if moved: + break + if not moved: ivar+=1 + idecl+=1 + + for i in range(len(declarations)-1,0,-1): + if (declarations[i]['normalizedType'].lower()== + declarations[i-1]['normalizedType'].lower()): + declarations[i-1]['vars'].extend(declarations[i]['vars']) + del declarations[i] + +def sortDeclarations(declarations): + """sorts, compacts declarations and respects dependencies + normalizedType has to be defined for the declarations""" + + declarations.sort(lambda x,y:cmp(x['normalizedType'].lower(), + y['normalizedType'].lower())) + + for i in range(len(declarations)-1,0,-1): + if (declarations[i]['normalizedType'].lower()== + declarations[i-1]['normalizedType'].lower()): + declarations[i-1]['vars'].extend(declarations[i]['vars']) + del declarations[i] + + for decl in declarations: + decl['vars'].sort(lambda x,y:cmp(x.lower(),y.lower())) + enforceDeclDependecies(declarations) + +def writeRoutine(routine, outFile): + """writes the given routine to outFile""" + outFile.writelines(routine["preRoutine"]) + outFile.writelines(routine["begin"]) + outFile.writelines(routine["declarations"]) + outFile.writelines(routine["core"]) + outFile.writelines(routine["end"]) + outFile.writelines(routine["postRoutine"]) + +def writeInCols(dLine,indentCol,maxCol,indentAtt,file): + """writes out the strings (trying not to cut them) in dLine up to maxCol + indenting each newline with indentCol. + The '&' of the continuation line is at maxCol. + indentAtt is the actual intent, and the new indent is returned""" + strRe=re.compile(r"('[^'\n]*'|\"[^\"\n]*\")") + nonWordRe=re.compile(r"(\W)") + maxSize=maxCol-indentCol-1 + tol=min(maxSize/6,6)+indentCol + for fragment in dLine: + if indentAtt+len(fragment)0: + dLine.append(" "+d['type']) + if d['parameters']: # do not drop empty parameter lists? + dLine.append(d['parameters']) + if d['attributes']: + for a in d['attributes']: + dLine[-1:]=[dLine[-1]+", "] + dLine.append(a) + dLine[-1:]=[dLine[-1]+" :: "] + for var in d['vars'][:-1]: + dLine.append(var+", ") + dLine.append(d['vars'][-1]) + + writeInCols(dLine,6,79,0,file) + file.write("\n") + +def writeExtendedDeclaration(declaration,file): + """Writes a declaration in a nicer way (using more space)""" + d=declaration + if len(d['vars'])==0: return + if d.has_key('iroutine'): + file.writelines(d['istart']) + writeRoutine(d['iroutine'],file) + file.writelines(d['iend']) + else: + dLine=[] + dLine.append(" "+d['type']) + if d['parameters']: # do not drop empty parameter lists? + dLine.append(d['parameters']) + if d['attributes']: + for a in d['attributes']: + dLine[-1:]=[dLine[-1]+", "] + dLine.append(a) + + indentAtt=writeInCols(dLine,6,45,0,file) + file.write(" "*(44-indentAtt)) + file.write(" :: ") + indentAtt=48 + + dLine=[] + for var in d['vars'][:-1]: + dLine.append(var+", ") + dLine.append(d['vars'][-1]) + + writeInCols(dLine,48,79,indentAtt,file) + file.write("\n") + +def writeDeclarations(parsedDeclarations,file): + """Writes the declarations to the given file""" + for d in parsedDeclarations: + maxLenVar=0 + totalLen=0 + for v in d['vars']: + maxLenVar=max(maxLenVar,len(v)) + totalLen+=len(v) + if maxLenVar>30 or totalLen>75: + writeCompactDeclaration(d,file) + else: + writeExtendedDeclaration(d,file) + +def cleanDeclarations(routine): + """cleans up the declaration part of the given parsed routine + removes unused variables""" + commentToRemoveRe=re.compile(r" *! *(?:interface|arguments|parameters|locals?|\** *local +variables *\**|\** *local +parameters *\**) *$",re.IGNORECASE) + + if not routine['kind']: return + if (routine['core'] and + re.match(" *type *[a-zA-Z_]+ *$",routine['core'][0],re.IGNORECASE)): + print "*** routine %s contains local types, not fully cleaned ***"%( + routine['name']) + if re.search("^#","".join(routine['declarations']),re.MULTILINE): + print "*** routine %s declarations contain preprocessor directives ***\n*** declarations not cleaned ***"%( + routine['name']) + return + try: + rest="".join(routine['strippedCore']).lower() + paramDecl=[] + decls=[] + for d in routine['parsedDeclarations']: + d['normalizedType']=d['type'] + if d['parameters']: + d['normalizedType']+=d['parameters'] + if (d["attributes"]): + d['attributes'].sort(lambda x,y:cmp(x.lower(),y.lower())) + d['normalizedType']+=', ' + d['normalizedType']+=', '.join(d['attributes']) + if "parameter" in map(str.lower,d['attributes']): + paramDecl.append(d) + else: + decls.append(d) + + sortDeclarations(paramDecl) + sortDeclarations(decls) + + if routine['arguments']: + routine['lowercaseArguments']=map(lambda x:x.lower(),routine['arguments']) + else: + routine['lowercaseArguments']=[] + if routine['result']: routine['lowercaseArguments'].append(routine['result'].lower()) + argDeclDict={} + localDecl=[] + for d in decls: + localD={} + localD.update(d) + localD['vars']=[] + argD=None + for v in d['vars']: + lowerV=varRe.match(v).group("var").lower() + if lowerV in routine['lowercaseArguments']: + argD={} + argD.update(d) + argD['vars']=[v] + if argDeclDict.has_key(lowerV): + raise SyntaxError( + "multiple declarations not supported. var="+v+ + " declaration="+str(d)+"routine="+routine['name']) + argDeclDict[lowerV]=argD + else: + pos=findWord(lowerV,rest) + if (pos!=-1): + localD['vars'].append(v) + if (len(localD['vars'])): + localDecl.append(localD) + argDecl=[] + for arg in routine['lowercaseArguments']: + argDecl.append(argDeclDict[arg]) + enforceDeclDependecies(argDecl) + + newDecl=StringIO() + newDecl.writelines(routine['use']) + writeDeclarations(argDecl,newDecl) + if argDecl and paramDecl: + newDecl.write("\n") + writeDeclarations(paramDecl,newDecl) + if (argDecl or paramDecl) and localDecl: + newDecl.write("\n") + writeDeclarations(localDecl,newDecl) + if argDecl or paramDecl or localDecl: + newDecl.write("\n") + for comment in routine['declComments']: + if not commentToRemoveRe.match(comment): + newDecl.write(comment) + routine['declarations']=[newDecl.getvalue()] + except: + if routine.has_key('name'): + print "**** exception cleaning routine "+routine['name']+" ****" + print "parsedDeclartions=",routine['parsedDeclarations'] + raise + +def parseUse(inFile): + """Parses the use statements in inFile + The parsing stops at the first non use statement. + Returns something like: + ([{'module':'module1','only':['el1','el2=>el3']},...], + '! comment1\\n!comment2...\\n', + 'last line (the line that stopped the parsing)') + """ + lineNr=0 + preComments=[] + modules=[] + origLines=[] + while 1: + (jline,comments,lines)=readFortranLine(inFile) + lineNr=lineNr+len(lines) + if not lines: break + origLines.append("".join(lines)) + # parse use + m=useParseRe.match(jline) + if m: + useAtt={'module':m.group('module'),'comments':[]} + + if m.group('only'): + useAtt['only']=map(string.strip, + string.split(m.group('imports'),',')) + else: + useAtt['renames']=map(string.strip, + string.split(m.group('imports'),',')) + if useAtt['renames']==[""]: del useAtt['renames'] + if comments : useAtt['comments'].append(comments) + # add use to modules + modules.append(useAtt) + elif jline and not jline.isspace(): + break + else: + if len(modules)==0: + preComments.append(("".join(lines))) + elif comments: + modules[-1]['comments'].append(comments) + + return {'modules':modules,'preComments':preComments, + 'postLine':"".join(lines),'origLines':origLines[:-1]} + +def normalizeModules(modules): + """Sorts the modules and their export and removes duplicates. + renames aren't sorted correctly""" + # orders modules + modules.sort(lambda x,y:cmp(x['module'],y['module']) ) + for i in range(len(modules)-1,0,-1): + if modules[i]['module']==modules[i-1]['module']: + if not (modules[i-1].has_key('only') and + modules[i].has_key('only')): + raise SyntaxError('rejoining of module '+ + str(modules[i]['module'])+ + ' failed as at least one of the use is not a use ...,only:') + modules[i-1]['only'].extend(modules[i]['only']) + del modules[i] + # orders imports + for m in modules: + if m.has_key('only'): + m['only'].sort() + for i in range(len(m['only'])-1,0,-1): + if m['only'][i-1]==m['only'][i]: del m['only'][i] + +def writeUseLong(modules,outFile): + for m in modules: + if m.has_key('only'): + outFile.write(" USE "+m['module']+","+ + string.rjust('ONLY: ',38-len(m['module']))) + if m['only']: outFile.write(m['only'][0]) + for i in range(1,len(m['only'])): + outFile.write(",&\n"+string.ljust("",45)+m['only'][i]) + else: + outFile.write(" USE "+m['module']) + if m.has_key('renames') and m['renames']: + outFile.write(","+string.ljust("",38)+ + m['renames'][0]) + for i in range(1,len(m['renames'])): + outFile.write(",&\n"+string.ljust("",45)+m['renames'][i]) + if m['comments']: + outFile.write("\n") + outFile.write('\n'.join(m['comments'])) + outFile.write("\n") + +def cleanUse(modulesDict,rest): + """Removes the unneded modules (the ones that are not used in rest)""" + exceptions={"cp_a_l":1,"cp_to_string":1,"cp_error_type":1,"cp_assert":1, + "cp_failure_level":1,"cp_warning_level":1,"cp_note_level":1, + "cp_fatal_level":1,"cp_logger_type":1,"timeset":1,"timestop":1, + "dp":1,"cp_error_get_logger":1, "cp_error_message":1} + localNameRe=re.compile(" *(?P[a-zA-Z_0-9]+)(?: *= *> *[a-zA-Z_0-9]+)? *$") + modules=modulesDict['modules'] + rest=rest.lower() + for i in range(len(modules)-1,-1,-1): + if modules[i].has_key("only"): + els=modules[i]['only'] + for j in range(len(els)-1,-1,-1): + m=localNameRe.match(els[j]) + if not m: + raise SyntaxError('could not parse use only:'+repr(els[j])) + impAtt=m.group('localName').lower() + if not exceptions.has_key(impAtt): + if findWord(impAtt,rest)==-1: + del els[j] + if len(modules[i]['only'])==0: + if modules[i]['comments']: + modulesDict['preComments'].extend(modules[i]['comments']) + del modules[i] + +def rewriteFortranFile(inFile,outFile,logFile=sys.stdout): + """rewrites the use statements and declarations of inFile to outFile. + It sorts them and removes the repetitions.""" + import os.path + moduleRe=re.compile(r" *module (?P[a-zA-Z_][a-zA-Z_0-9]*) *(?:!.*)?$", + flags=re.IGNORECASE) + coreLines=[] + while 1: + line=inFile.readline() + if not line: break + if line[0]=='#': + coreLines.append(line) + outFile.write(line) + m=moduleRe.match(line) + if m: + if (m.group('moduleName')!=os.path.basename(inFile.name)[0:-2]) : + raise SyntaxError("Module name is different from filename ("+ + m.group('moduleName')+ + "!="+os.path.basename(inFile.name)[0:-2]+")") + break + try: + modulesDict=parseUse(inFile) + routines=[] + coreLines.append(modulesDict['postLine']) + routine=parseRoutine(inFile) + coreLines.extend(routine['preRoutine']) + routines.append(routine) + while routine['kind']: + routine=parseRoutine(inFile) + routines.append(routine) + map(cleanDeclarations,routines) + for routine in routines: + coreLines.extend(routine['declarations']) + coreLines.extend(routine['strippedCore']) + rest="".join(coreLines) + if re.search('^#',"".join(modulesDict['origLines']),re.MULTILINE): + print "*** use statements contains preprocessor directives, not cleaning ***" + outFile.writelines(modulesDict['origLines']) + else: + cleanUse(modulesDict,rest) + normalizeModules(modulesDict['modules']) + outFile.writelines(modulesDict['preComments']) + writeUseLong(modulesDict['modules'],outFile) + if modulesDict['modules']: + outFile.write('\n') + outFile.write(modulesDict['postLine']) + for routine in routines: + writeRoutine(routine,outFile) + except: + import traceback + logFile.write('-'*60+"\n") + traceback.print_exc(file=logFile) + logFile.write('-'*60+"\n") + + logFile.write("Processing file '"+inFile.name+"'\n") + +if __name__ == '__main__': + import os.path + if len(sys.argv)<2: + print "usage:", sys.argv[0]," out_dir file1 [file2 ...]" + else: + outDir=sys.argv[1] + if not os.path.isdir(outDir): + print "out_dir must be a directory" + print "usage:", sys.argv[0]," out_dir file1 [file2 ...]" + else: + for fileName in sys.argv[2:]: + print "normalizing",fileName + infile=open(fileName,'r') + outfile=open(os.path.join(outDir, + os.path.basename(fileName)),'w') + rewriteFortranFile(infile,outfile) + infile.close() + outfile.close() + # print "done" diff --git a/tools/normalizeUse.py b/tools/normalizeUse.py deleted file mode 100755 index 11296ad684..0000000000 --- a/tools/normalizeUse.py +++ /dev/null @@ -1,178 +0,0 @@ -#! /usr/bin/env python - -import sys -import re -import string -from sys import argv - -def parseUse(inFile): - """Parses the use statements in inFile - The parsing stops at the first non use statement. - Returns something like: - ([{'module':'module1','only':['el1',el2=>el3']},...], - '! comment1\\n!comment2...\\n', - 'last line (the line that stopped the parsing)') - """ - useStartRe=re.compile( - r" *(?Puse[^&!]*)(?P&?) *(?P!.*)?$", - flags=re.IGNORECASE) - commentRe=re.compile(r" *!.*$") - contLineRe=re.compile( - r"(?P[^&!]*)(?P&?) *(?P!.*)?$") - useParseRe=re.compile( - r" *use +(?P[a-zA-Z_][a-zA-Z_0-9]*)(?P *, *only *:)? *(?P.*)$", - flags=re.IGNORECASE) - lineNr=0 - comments="" - modules=[] - line="" - while 1: - line=inFile.readline() - lineNr=lineNr+1 - if not line: break - - m=useStartRe.match(line) - if m: - # read whole use - compactedUse=m.group('use') - useComments="" - if m.group('comment'): useComments=m.group('comment')+'\n' - while m.group('continue'): - lineNr=lineNr+1 - m=contLineRe.match(inFile.readline()) - compactedUse=compactedUse+m.group('contLine') - if m.group('comment'): - useComments=useComments+m.group('comment')+'\n' - # parse use - m=useParseRe.match(compactedUse) - if not m: - raise SyntaxError("could not parse use ending at line "+ - str(lineNr)+" (compactedUse="+compactedUse+ - ")") - useAtt={'module':m.group('module')} - if m.group('only'): - useAtt['only']=map(string.strip, - string.split(m.group('imports'),',')) - else: - useAtt['renames']=map(string.strip, - string.split(m.group('imports'),',')) - if useAtt['renames']==[""]: del useAtt['renames'] - if useComments : useAtt['comments']=useComments - # add use to modules - modules.append(useAtt) - elif commentRe.match(line): - comments=comments+line - elif line and not line.isspace(): - break - return (modules,comments,line) - -def normalizeModules(modules): - """Sorts the modules and their export and removes duplicates. - renames aren't sorted correctly""" - # orders modules - modules.sort(lambda x,y:cmp(x['module'],y['module']) ) - for i in range(len(modules)-1,0,-1): - if modules[i]['module']==modules[i-1]['module']: - if not (modules[i-1].has_key('only') and - modules[i].has_key('only')): - raise SyntaxError('rejoining of module '+ - str(modules[i]['module'])+ - ' failed as at least one of the use is not a use ...,only:') - modules[i-1]['only'].extend(modules[i]['only']) - del modules[i] - # orders imports - for m in modules: - if m.has_key('only'): - m['only'].sort() - for i in range(len(m['only'])-1,0,-1): - if m['only'][i-1]==m['only'][i]: del m['only'][i] - -def writeUseLong(modules,outFile): - for m in modules: - if m.has_key('only'): - outFile.write(" USE "+m['module']+","+ - string.rjust('ONLY: ',38-len(m['module']))) - if m['only']: outFile.write(m['only'][0]) - for i in range(1,len(m['only'])): - outFile.write(",&\n"+string.ljust("",45)+m['only'][i]) - else: - outFile.write(" USE "+m['module']) - if m.has_key('renames') and m['renames']: - outFile.write(","+string.ljust("",38)+ - m['renames'][0]) - for i in range(1,len(m['renames'])): - outFile.write(",&\n"+string.ljust("",45)+m['renames'][i]) - if m.has_key('comments') and m['comments']: - comments=m['comments'].splitlines() - outFile.write("&") - for i in range(0,len(comments)-1): - outFile.write("\n&"+comments[i]) - outFile.write("\n"+comments[-1]) - outFile.write("\n") - -def cleanUse(modules,rest): - """Removes the unneded modules (the ones that are not used in rest)""" - exceptions={"cp_a_l":1,"cp_to_string":1,"cp_error_type":1,"cp_assert":1, - "cp_failure_level":1,"cp_warning_level":1,"cp_note_level":1, - "cp_fatal_level":1,"cp_logger_type":1,"timeset":1,"timestop":1, - "dp":1,"cp_error_get_logger":1, "cp_error_message":1} - rest=rest.lower() - for i in range(len(modules)-1,-1,-1): - if modules[i].has_key("only"): - els=modules[i]['only'] - for j in range(len(els)-1,-1,-1): - if not exceptions.has_key(els[j].lower()): - if rest.find(els[j].lower())==-1: - del els[j] - if len(modules[i]['only'])==0: - del modules[i] - -def rewriteUse(inFile,outFile,logFile=sys.stdout): - """rewrites the use statements of in file to outFile. - It sorts them and removes the repetitions.""" - import os.path - moduleRe=re.compile(r" *module (?P[a-zA-Z_][a-zA-Z_0-9]*) *(?:!.*)?$", - flags=re.IGNORECASE) - while 1: - line=inFile.readline() - if not line: break - outFile.write(line) - m=moduleRe.match(line) - if m: - if (m.group('moduleName')!=os.path.basename(inFile.name)[0:-2]) : - raise SyntaxError("Module name is different from filename ("+ - m.group('moduleName')+ - "!="+os.path.basename(inFile.name)[0:-2]+")") - break - try: - (modules,comments,line)=parseUse(inFile) - rest=line+inFile.read() - cleanUse(modules,rest) - outFile.write(comments) - normalizeModules(modules) - writeUseLong(modules,outFile) - outFile.write(rest) - except: - import traceback - logFile.write('-'*60+"\n") - traceback.print_exc(file=logFile) - logFile.write('-'*60+"\n") - - logFile.write("Processing file '"+inFile.name+"'\n") - - -if __name__ == '__main__': - import os.path - if len(sys.argv)<2: - print "usage:", sys.argv[0]," out_dir file1 [file2 ...]" - else: - outDir=sys.argv[1] - if not os.path.isdir(outDir): - print "out_dir must be a directory" - print "usage:", sys.argv[0]," out_dir file1 [file2 ...]" - else: - for fileName in sys.argv[2:]: - infile=open(fileName,'r') - outfile=open(os.path.join(outDir, - os.path.basename(fileName)),'w') - rewriteUse(infile,outfile)