def _detect_routine_start(self, line): ''' Detect the start of a routine in a line using either list from config file with positive and negative searches, or default regex. ''' if self._positiveSearches: # Do the negative searches first, since for many scenarios it will be faster return self._first_match(line, self._positiveSearches, self._negativeSearches, negativeFirst=True) else: match = self.reDefaultRoutine.search(line) if match: # Make tuple rv like _first_match return utils.get_match_pattern(match), match
def _search(self, lines, configEntry, measurements, analysis): ''' Loop through the lines, comparing each aginst both the positve and negative list of search strings provided. ''' positiveSearches, negativeSearches = self._setup_search_strings( configEntry.paramsProcessed) val_TotalHits = 0 val_TotalLines = 0 try: for rawLine in lines: line = utils.strip_null_chars(rawLine) val_TotalLines += 1 matchTuple = self._first_match(line, positiveSearches, negativeSearches) if matchTuple: origPatternStr, match = matchTuple val_TotalHits += 1 # May search binaries, so take some steps to clean up exported string cleanSearchLine = line.strip() cleanSearchLine = cleanSearchLine[:self.MAX_STR_LEN] cleanSearchLine = utils.safe_string(cleanSearchLine) cleanSearchLine = utils.strip_annoying_chars( cleanSearchLine) # Export the findings analysisItem = {} analysisItem[ self.SEARCH_LINE] = cleanSearchLine[:self.MAX_STR_LEN] analysisItem[self.SEARCH_LINENUM] = val_TotalLines analysisItem[self.SEARCH_CONFIG_RE] = origPatternStr analysisItem[self.SEARCH_REGEXP] = utils.get_match_pattern( match)[:self.MAX_STR_LEN] analysisItem[self.SEARCH_MATCH] = utils.get_match_string( match)[:self.MAX_STR_LEN] analysis.append(analysisItem) except Exception as e: raise utils.CsModuleException( "Error {}\n...searching line: {}".format( str(e), str(val_TotalLines))) # Populate the measurement results with fixed totals if val_TotalHits > 0: measurements[self.LINES_TOTAL] = val_TotalLines measurements[self.SEARCH_TOTAL] = val_TotalHits
def _search_line_impl(self, line, analysis): ''' Delegate search functionality to searchMixin ''' searchLine = line if not self._includeStringContent: searchLine = self._strip_blanks_and_strings(searchLine) if not self._includeComments: searchLine = self._strip_inlines(searchLine) matchTuple = self._first_match(searchLine, self._positiveSearches, self._negativeSearches) if matchTuple: origPatternStr, match = matchTuple searchData = {} searchData[ self.SEARCH_LINE ] = line.strip()[:self.MAX_STR_LEN] searchData[ self.SEARCH_LINENUM ] = str(sum(self.counts['RawLines'])) searchData[ self.SEARCH_MATCH ] = utils.get_match_string(match).strip()[:self.MAX_STR_LEN] searchData[ self.SEARCH_REGEXP ] = utils.get_match_pattern(match).strip()[:self.MAX_STR_LEN] searchData[ self.SEARCH_CONFIG_RE ] = str(origPatternStr) analysis.append(searchData)
def _search_multi(self, lines, configEntry, measurements, analysis): ''' Use multi-line searches ''' # Make sure lines represents the text of the file try: lines = lines.read() except AttributeError: pass lines = utils.strip_null_chars(lines) positiveSearches, negativeSearches = self._setup_search_strings( configEntry.paramsProcessed) matchTuple = self._first_match(lines, positiveSearches, negativeSearches) if matchTuple: origPatternStr, match = matchTuple analysisItem = {} analysisItem[self.SEARCH_CONFIG_RE] = origPatternStr analysisItem[self.SEARCH_REGEXP] = utils.get_match_pattern( match)[:self.MAX_STR_LEN] analysisItem[self.SEARCH_MATCH] = utils.get_match_string(match) analysis.append(analysisItem)
def _routine_analyze_impl(self, line, analysis): ''' Identify routine begining by searching for the regular expressions provided in the config file. Assume the current routine ends when the next one is found, while collecting information on a line-by-line basis ''' # Create expanded line and estimate line nesting expandedLine = line.expandtabs(self.routineAvgIndent) indentDepth = len(expandedLine) - len(expandedLine.lstrip()) nestingApprox = int(indentDepth / self.routineAvgIndent) routineNest = nestingApprox - self.currentRoutine['LineIndent'] # Strip literals and assembly comments to avoid mistaken hits strippedLine = self._strip_blanks_and_strings(line) strippedLine = self._strip_inlines(strippedLine) # Is this line the start of a routine? routineStartMatch = self._detect_routine_start(line) if self._current_routine_ended(line, routineStartMatch, indentDepth): self._save_routine_info(analysis, self._activeBlock) self._foundFirstRoutineSinceTransition = True self._reset_routine_counts() # Cache information about this new routine definition self.currentRoutine['Line'] = line self.currentRoutine['LineNum'] = sum(self.counts['RawLines']) self.currentRoutine['LineCol'] = indentDepth self.currentRoutine['LineIndent'] = nestingApprox if routineStartMatch: origPatternStr, match = routineStartMatch self.currentRoutine['Name'] = utils.get_match_string(match) self.currentRoutine['RegEx'] = (origPatternStr, utils.get_match_pattern(match)) self.counts['Routines'][self._activeBlock] += 1 if self._logLevel: log.code(1, "RoutineStart({})=> {}".format( self.currentRoutine['LineNum'], self.currentRoutine['Line'])) log.search(3, " re: {} => name: {}".format( self.currentRoutine['RegEx'][0][:40], self.currentRoutine['Name'])) else: if self._logLevel: log.code(1, "RoutineEnd({})=> {}".format( self.currentRoutine['LineNum'], self.currentRoutine['Line'])) # If there are decision matches for the line complexLine = line if self._includeStringContent else strippedLine if self.reDecision.search(complexLine): if self._logLevel: log.search(2, "decision: {}".format( utils.get_match_string(self.reDecision.search(complexLine)))) self.counts['Decisions'][self._activeBlock] += 1 self.currentRoutine['Decisions'] +=1 # Check for the maximum indentation (as an indication of nesting depth) if routineNest > self.currentRoutine['MaxIndent']: self.currentRoutine['MaxIndent'] = routineNest if self.reEscapes.search(complexLine): if self._logLevel: log.search(3, "escape: {}".format( utils.get_match_string(self.reEscapes.search(complexLine)))) self.currentRoutine['Escapes'] +=1 if self.reCases.search(complexLine): if self._logLevel: log.search(3, "case: {}".format( utils.get_match_string(self.reCases.search(complexLine)))) self.currentRoutine['Cases'] +=1 if self.reBooleans.search(complexLine): if self._logLevel: log.search(3, "boolean: {}".format( utils.get_match_string(self.reBooleans.search(complexLine)))) self.currentRoutine['Booleans'] +=1