Ejemplo n.º 1
0
    def getSymbolAnalysisFor(self,
                             routineName,
                             symbolAnalysis=None,
                             symbolAnalysisByNameAndSource=None,
                             call=None,
                             analysisWarningsByCalleeName=None):
        if symbolAnalysis == None:
            symbolAnalysis = {}
        if symbolAnalysisByNameAndSource == None:
            symbolAnalysisByNameAndSource = {}
        if analysisWarningsByCalleeName == None:
            analysisWarningsByCalleeName = {}
        routine = self.routinesByName.get(routineName)
        if not routine:
            return symbolAnalysis, symbolAnalysisByNameAndSource
        routineArguments = getArguments(routine)
        callArguments = []
        if call != None:
            callArguments = getArguments(call)
            if call.getAttribute("callee") != routineName:
                raise Exception(
                    "call passed to analysis of %s is not a call to this routine: %s"
                    % (routineName, prettyprint(call)))
            if len(callArguments) != len(routineArguments):
                warnings = analysisWarningsByCalleeName.get(routineName, [])
                warnings.append(
                    (call.getAttribute("caller"), len(callArguments),
                     len(routineArguments), str(callArguments)))
                analysisWarningsByCalleeName[routineName] = warnings
                return symbolAnalysis, symbolAnalysisByNameAndSource

        templates_and_entries = getDomainDependantTemplatesAndEntries(
            self.doc, routine)
        analysisToAdd = {}

        #check arguments to this routine - temporarily remove previous calls from the analysis.
        #we don't want to overwrite information from previous calls.
        temporarilyStoredAnalysisByArgumentName = {}
        for argIndex, _ in enumerate(callArguments):
            localArgumentName = routineArguments[argIndex]
            if not (routineName, localArgumentName) in symbolAnalysis:
                continue
            temporarilyStoredAnalysisByArgumentName[
                localArgumentName] = symbolAnalysis[(routineName,
                                                     localArgumentName)]
            del symbolAnalysis[(routineName, localArgumentName)]

        #Symbol Analysis based on local information
        for (_, entry) in templates_and_entries:
            analysis = SymbolAnalysis()
            analysis.name = entry.firstChild.nodeValue
            analysis.sourceModule = entry.getAttribute("sourceModule")
            analysis.sourceSymbol = entry.getAttribute("sourceSymbol")
            analysis.aliasNamesByRoutineName[routineName] = analysis.name
            argIndex = -1
            try:
                argIndex = routineArguments.index(analysis.name)
            except Exception:
                pass
            if argIndex > -1:
                analysis.argumentIndexByRoutineName[routineName] = argIndex
            if argIndex > -1:
                analysis.symbolType = SymbolType.ARGUMENT_WITH_DOMAIN_DEPENDANT_SPEC
            elif type(analysis.sourceModule) in [
                    unicode, str
            ] and analysis.sourceModule != "":
                analysis.symbolType = SymbolType.MODULE_DATA_WITH_DOMAIN_DEPENDANT_SPEC
            else:
                analysis.symbolType = SymbolType.DOMAIN_DEPENDANT
            analysisToAdd[analysis.name] = analysis
        for argIndex, argument in enumerate(routineArguments):
            if argument in analysisToAdd:
                continue
            analysis = SymbolAnalysis()
            analysis.name = argument
            analysis.symbolType = SymbolType.ARGUMENT
            analysis.argumentIndexByRoutineName[routineName] = argIndex
            analysisToAdd[analysis.name] = analysis

        #Symbol Analysis based on caller
        #--> check whether an analysis has already been done, update that and add it under the current routine, symbolName tuple
        for symbolName in analysisToAdd.keys():
            currentAnalysis = analysisToAdd[symbolName]
            argIndex = currentAnalysis.argumentIndexByRoutineName.get(
                routineName, -1)
            existingSymbolAnalysis = None
            if argIndex > -1 and len(callArguments) > 0:
                symbolNameInCaller = callArguments[argIndex]
                callerName = call.getAttribute("caller")
                existingSymbolAnalysis = symbolAnalysis.get(
                    (callerName, symbolNameInCaller), [])
            elif currentAnalysis.isModuleSymbol:
                existingModuleSymbolAnalysis = symbolAnalysisByNameAndSource.get(
                    (currentAnalysis.sourceSymbol,
                     currentAnalysis.sourceModule))
                if existingModuleSymbolAnalysis:
                    existingSymbolAnalysis = [existingModuleSymbolAnalysis]
                else:
                    existingSymbolAnalysis = []
            else:
                existingSymbolAnalysis = [currentAnalysis]
            for analysis in existingSymbolAnalysis:
                if not isinstance(analysis, SymbolAnalysis):
                    raise Exception(
                        "unexpected error in routine %s: current analysis list contains unexpected objects: %s"
                        % (routineName, str(existingSymbolAnalysis)))

            if len(existingSymbolAnalysis) == 0 or (
                    len(existingSymbolAnalysis) == 1
                    and existingSymbolAnalysis[0] == currentAnalysis):
                symbolAnalysis[(routineName, symbolName)] = [currentAnalysis]
                if currentAnalysis.isModuleSymbol:
                    symbolAnalysisByNameAndSource[(
                        currentAnalysis.sourceSymbol,
                        currentAnalysis.sourceModule)] = currentAnalysis
            else:
                for analysis in existingSymbolAnalysis:
                    analysis.updateWith(currentAnalysis, routineName)
                symbolAnalysis[(routineName,
                                symbolName)] = existingSymbolAnalysis

        #Analyse callgraph downstream from here
        for call in self.callsByCallerName.get(routineName, []):
            if call.getAttribute("caller") != routineName:
                raise Exception(
                    "unexpected error when constructing callgraph for symbol aliases"
                )
            calleeName = call.getAttribute("callee")
            symbolAnalysis, symbolAnalysisByNameAndSource = self.getSymbolAnalysisFor(
                calleeName,
                symbolAnalysis=symbolAnalysis,
                symbolAnalysisByNameAndSource=symbolAnalysisByNameAndSource,
                call=call,
                analysisWarningsByCalleeName=analysisWarningsByCalleeName)
        for argumentName in temporarilyStoredAnalysisByArgumentName.keys():
            symbolAnalysis[(
                routineName,
                argumentName)] = temporarilyStoredAnalysisByArgumentName[
                    argumentName] + symbolAnalysis.get(
                        (routineName, argumentName), [])

        return symbolAnalysis, symbolAnalysisByNameAndSource
            # 	]))
            # ] +
            symbolRows  #symbols
        ))


#read in working xml
srcFile = openFile(str(options.source), 'r')
data = srcFile.read()
srcFile.close()
doc = parseString(data)

analyzer = SymbolDependencyAnalyzer(doc)
if options.debug:
    print "=== calls by calleename ==="
    prettyprint(analyzer.callsByCalleeName)
    print "=== calls by callsByCallerName ==="
    prettyprint(analyzer.callsByCallerName)
    print "=== callGraphEdgesByCallerName ==="
    prettyprint(analyzer.callGraphEdgesByCallerName)
    print "=== routines by name ==="
    prettyprint(analyzer.routinesByName)

analysis = None
if options.symbolGraphRootRoutine:
    analysis = analyzer.getSymbolAnalysisByRoutine(
        options.symbolGraphRootRoutine)
elif options.allSymbols:
    analysis = analyzer.getSymbolAnalysisByRoutine()
if options.debug and analysis != None:
    print "=== analysis ==="
Ejemplo n.º 3
0
    def getSymbolAnalysisFor(self, routineName, symbolAnalysis=None, symbolAnalysisByNameAndSource=None, call=None, analysisWarningsByCalleeName=None):
        if symbolAnalysis == None:
            symbolAnalysis = {}
        if symbolAnalysisByNameAndSource == None:
            symbolAnalysisByNameAndSource = {}
        if analysisWarningsByCalleeName == None:
            analysisWarningsByCalleeName = {}
        routine = self.routinesByName.get(routineName)
        if not routine:
            return symbolAnalysis, symbolAnalysisByNameAndSource
        routineArguments = getArguments(routine)
        callArguments = []
        if call != None:
            callArguments = getArguments(call)
            if call.getAttribute("callee") != routineName:
                raise Exception("call passed to analysis of %s is not a call to this routine: %s" %(
                    routineName,
                    prettyprint(call)
                ))
            if len(callArguments) != len(routineArguments):
                warnings = analysisWarningsByCalleeName.get(routineName, [])
                warnings.append((call.getAttribute("caller"), len(callArguments), len(routineArguments), str(callArguments)))
                analysisWarningsByCalleeName[routineName] = warnings
                return symbolAnalysis, symbolAnalysisByNameAndSource

        templates_and_entries = getDomainDependantTemplatesAndEntries(
            self.doc,
            routine
        )
        analysisToAdd = {}

        #check arguments to this routine - temporarily remove previous calls from the analysis.
        #we don't want to overwrite information from previous calls.
        temporarilyStoredAnalysisByArgumentName = {}
        for argIndex, _ in enumerate(callArguments):
            localArgumentName = routineArguments[argIndex]
            if not (routineName, localArgumentName) in symbolAnalysis:
                continue
            temporarilyStoredAnalysisByArgumentName[localArgumentName] = symbolAnalysis[(routineName, localArgumentName)]
            del symbolAnalysis[(routineName, localArgumentName)]

        #Symbol Analysis based on local information
        for (_, entry) in templates_and_entries:
            analysis = SymbolAnalysis()
            analysis.name = entry.firstChild.nodeValue
            analysis.sourceModule = entry.getAttribute("sourceModule")
            analysis.sourceSymbol = entry.getAttribute("sourceSymbol")
            analysis.aliasNamesByRoutineName[routineName] = analysis.name
            argIndex = -1
            try:
                argIndex = routineArguments.index(analysis.name)
            except Exception:
                pass
            if argIndex > -1:
                analysis.argumentIndexByRoutineName[routineName] = argIndex
            if argIndex > -1:
                analysis.symbolType = SymbolType.ARGUMENT_WITH_DOMAIN_DEPENDANT_SPEC
            elif type(analysis.sourceModule) in [unicode, str] and analysis.sourceModule != "":
                analysis.symbolType = SymbolType.MODULE_DATA_WITH_DOMAIN_DEPENDANT_SPEC
            else:
                analysis.symbolType = SymbolType.DOMAIN_DEPENDANT
            analysisToAdd[analysis.name] = analysis
        for argIndex, argument in enumerate(routineArguments):
            if argument in analysisToAdd:
                continue
            analysis = SymbolAnalysis()
            analysis.name = argument
            analysis.symbolType = SymbolType.ARGUMENT
            analysis.argumentIndexByRoutineName[routineName] = argIndex
            analysisToAdd[analysis.name] = analysis

        #Symbol Analysis based on caller
        #--> check whether an analysis has already been done, update that and add it under the current routine, symbolName tuple
        for symbolName in analysisToAdd.keys():
            currentAnalysis = analysisToAdd[symbolName]
            argIndex = currentAnalysis.argumentIndexByRoutineName.get(routineName, -1)
            existingSymbolAnalysis = None
            if argIndex > -1 and len(callArguments) > 0:
                symbolNameInCaller = callArguments[argIndex]
                callerName = call.getAttribute("caller")
                existingSymbolAnalysis = symbolAnalysis.get((callerName, symbolNameInCaller), [])
            elif currentAnalysis.isModuleSymbol:
                existingModuleSymbolAnalysis = symbolAnalysisByNameAndSource.get((currentAnalysis.sourceSymbol, currentAnalysis.sourceModule))
                if existingModuleSymbolAnalysis:
                    existingSymbolAnalysis = [existingModuleSymbolAnalysis]
                else:
                    existingSymbolAnalysis = []
            else:
                existingSymbolAnalysis = [currentAnalysis]
            for analysis in existingSymbolAnalysis:
                if not isinstance(analysis, SymbolAnalysis):
                    raise Exception("unexpected error in routine %s: current analysis list contains unexpected objects: %s" %(
                        routineName,
                        str(existingSymbolAnalysis)
                    ))

            if len(existingSymbolAnalysis) == 0 or (len(existingSymbolAnalysis) == 1 and existingSymbolAnalysis[0] == currentAnalysis):
                symbolAnalysis[(routineName, symbolName)] = [currentAnalysis]
                if currentAnalysis.isModuleSymbol:
                    symbolAnalysisByNameAndSource[(currentAnalysis.sourceSymbol, currentAnalysis.sourceModule)] = currentAnalysis
            else:
                for analysis in existingSymbolAnalysis:
                    analysis.updateWith(currentAnalysis, routineName)
                symbolAnalysis[(routineName, symbolName)] = existingSymbolAnalysis

        #Analyse callgraph downstream from here
        for call in self.callsByCallerName.get(routineName, []):
            if call.getAttribute("caller") != routineName:
                raise Exception(
                    "unexpected error when constructing callgraph for symbol aliases"
                )
            calleeName = call.getAttribute("callee")
            symbolAnalysis, symbolAnalysisByNameAndSource = self.getSymbolAnalysisFor(
                calleeName,
                symbolAnalysis=symbolAnalysis,
                symbolAnalysisByNameAndSource=symbolAnalysisByNameAndSource,
                call=call,
                analysisWarningsByCalleeName=analysisWarningsByCalleeName
            )
        for argumentName in temporarilyStoredAnalysisByArgumentName.keys():
            symbolAnalysis[(routineName, argumentName)] = temporarilyStoredAnalysisByArgumentName[argumentName] + symbolAnalysis.get((routineName, argumentName), [])

        return symbolAnalysis, symbolAnalysisByNameAndSource
            # ] +
            symbolRows  # symbols
        )
    )


# read in working xml
srcFile = openFile(str(options.source), "r")
data = srcFile.read()
srcFile.close()
doc = parseString(data)

analyzer = SymbolDependencyAnalyzer(doc)
if options.debug:
    print "=== calls by calleename ==="
    prettyprint(analyzer.callsByCalleeName)
    print "=== calls by callsByCallerName ==="
    prettyprint(analyzer.callsByCallerName)
    print "=== callGraphEdgesByCallerName ==="
    prettyprint(analyzer.callGraphEdgesByCallerName)
    print "=== routines by name ==="
    prettyprint(analyzer.routinesByName)

analysis = None
if options.symbolGraphRootRoutine:
    analysis = analyzer.getSymbolAnalysisByRoutine(options.symbolGraphRootRoutine)
elif options.allSymbols:
    analysis = analyzer.getSymbolAnalysisByRoutine()
if options.debug and analysis != None:
    print "=== analysis ==="
    prettyprint(analysis)