diff -r be27ed110b50 -r e1eecf4d390d sbsv2/raptor/python/plugins/filter_terminal.py --- a/sbsv2/raptor/python/plugins/filter_terminal.py Wed Oct 28 14:39:48 2009 +0000 +++ b/sbsv2/raptor/python/plugins/filter_terminal.py Mon Nov 16 09:46:46 2009 +0000 @@ -1,422 +1,422 @@ -# -# Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). -# All rights reserved. -# This component and the accompanying materials are made available -# under the terms of the License "Eclipse Public License v1.0" -# which accompanies this distribution, and is available -# at the URL "http://www.eclipse.org/legal/epl-v10.html". -# -# Initial Contributors: -# Nokia Corporation - initial contribution. -# -# Contributors: -# -# Description: -# Filter class for filtering XML logs and generating reports -# Prints errors and warnings to stdout -# - -import sys -import raptor -import filter_interface -import generic_path -import os -import os.path -import re - -class Recipe(object): - """State machine that parses a recipe - """ - - suppress = [] - warningRE = re.compile("^.*((Warning:)|(MAKEDEF WARNING:)) .*$", re.DOTALL | re.M | re.I) - infoRE = None - name = [ "default" ] - recipes = [] - - def __init__(self, text): - self.suppress = self.__class__.suppress - self.text = text - self.warningRE = Recipe.warningRE - - def warnings(self): - return self.warningRE.findall(self.text) - - def info(self): - if self.infoRE: - return self.infoRE.findall(self.text) - else: - return [] - - @classmethod - def factory(cls, name, text): - for r in Recipe.recipes: - if name in r.name: - return r(text) - return Recipe(text) - - -class MwLinkerRecipe(Recipe): - suppress = [ - re.compile( -r"^mwldsym2: warning: Cannot locate library \"MSL_All_Static_MSE_Symbian\" specified in #pragma comment\(lib,...\)$" -r"[\n\r]*mwldsym2: warning: referenced from.*$" -r"[\n\r]*mwldsym2: warning: Option 'Use default libraries' is enabled but linker used.*$" -r"[\n\r]*mwldsym2: warning: runtime library from MW\[...\]LibraryFiles \(msl_all_static_mse_symbian_d.lib\);$" -r"[\n\r]*mwldsym2: warning: this indicates a potential settings/libraries mismatch.*$" - , re.M) - , re.compile( -r"^mwldsym2.exe: warning: Multiply defined symbol: ___get_MSL_init_count in.*$" -r"[\n\r]*mwldsym2.exe: warning: files uc_cwhelp.obj \(.*\), startup.win32.c.obj \(msl_all_static_mse_symbian_d.lib\),.*$" -r"[\n\r]*mwldsym2.exe: warning: keeping definition in startup.win32.c.obj.*$" - , re.M ) - , re.compile( -r"^mwldsym2.exe: warning: Option 'Use default libraries' is enabled but linker used.*$" -r"[\n\r]*mwldsym2.exe: warning: runtime library from MW\[...\]LibraryFiles \(msl_all_static_mse_symbian_d.lib\);.*$" -r"[\n\r]*mwldsym2.exe: warning: this indicates a potential settings/libraries mismatch.*$" - , re.M) - ] - name = [ "win32stagetwolink", "win32simplelink" ] - - def warnings(self): - edited = self.text - for s in MwLinkerRecipe.suppress: - edited = s.sub("", edited) - return Recipe.warningRE.findall(edited) - -Recipe.recipes.append(MwLinkerRecipe) - - -class FreezeRecipe(Recipe): - name = [ "freeze" ] - warningRE = re.compile("^(WARNING:) .*$", re.DOTALL | re.M | re.I) - infoRE = re.compile("^(EFREEZE:) .*$", re.DOTALL | re.M | re.I) - - def __init__(self, text): - Recipe.__init__(self, text) - self.warningRE = FreezeRecipe.warningRE - self.infoRE = FreezeRecipe.infoRE - -Recipe.recipes.append(FreezeRecipe) - - - -class FilterTerminal(filter_interface.Filter): - - attribute_re = re.compile("([a-z][a-z0-9]*)='([^']*)'",re.I) - maxdots = 40 # if one prints dots then don't print masses - recipelinelimit = 200 # don't scan ultra-long recipes in case we run out of memory - - # recipes that we think most users are interested in - # and the mapping that we will use to output them as - docare = { - "asmcompile" : "asmcompile" , - "compile" : "compile" , - "postlink" : "target", - "resourcecompile" : "resource", - "genstringtable" : "strtable", - "tem" : "tem", - "bitmapcompile" : "bitmap", - "bitmapcopy" : "bitmapcopy", - "win32compile2object" : "compile", - "win32stagetwolink" : "target", - "win32simplelink" : "target", - "tools2install" : "target", - "compile2object" : "compile", - "msvctoolsinstall" : "target", - "msvctoolscompile" : "compile", - "freeze" : "freeze", - "win32archive" : "target" - } - - # Determine the width of the largest mapped recipe name - recipewidth = 0 - for i in docare: - l = len(docare[i]) - if l > recipewidth: - recipewidth = l # justification for printing out recipes. - recipewidth+=1 - - def __init__(self): - self.analyseonly = False - self.quiet = False - # defaults can use EPOCROOT - if "EPOCROOT" in os.environ: - self.epocroot = str(generic_path.Path(os.environ["EPOCROOT"])) - else: - self.epocroot = str(generic_path.Path('/')) - self.current_recipe_logged = False - self.cleaned = 0 # cleaned files - self.dotcount = 0 # progress dots printed so far - # list of strings to catch make errors (must be lowercase) - self.make_error_expr = set([ - "error:", - ": ***", - "make: interrupt/exception caught (code =", - "make.exe: interrupt/exception caught (code =" - ]) - # list of strings to catch make warnings (must be lowercase) - self.make_warning_expr = ["warning:"] - - # list of strings to catch recipe warnings (must be lowercase) - self.recipe_warning_expr = ["warning:"] - - def isMakeWarning(self, text): - """A simple test for warnings. - Can be extended do to more comprehensive checking.""" - # generic warnings checked - # array of make_warning_expr holds all the possible values - for warn in self.make_warning_expr: - if warn in text.lower(): - return True - - return False - - - def isMakeError(self, text): - """A simple test for errors. - Can be extended to do more comprehensive checking.""" - - # make, emake and pvmgmake spit out things like - # make: *** No rule to make target X, needed by Y. Stop. - # - # array of make_error_expr holds all the possible values - for err in self.make_error_expr: - if err in text.lower(): - return True - - return False - - - def open(self, raptor_instance): - """Set output to stdout for the various I/O methods to write to.""" - self.raptor = raptor_instance - - # Be totally silent? - if self.raptor.logFileName is None: - self.analyseonly = True - - # Only print errors and warnings? - if self.raptor.quiet: - self.quiet = True - - # keep count of errors and warnings - self.err_count = 0 - self.warn_count = 0 - self.suppressed_warn_count = 0 - self.inBody = False - self.inRecipe = False - return True - - def write(self, text): - """Write errors and warnings to stdout""" - - if text.startswith("") - end = text.rfind("<") - self.err_count += 1 - if not self.analyseonly: - sys.stderr.write(str(raptor.name) + ": error: %s\n" \ - % text[(start + 1):end]) - elif text.startswith("") - end = text.rfind("<") - self.warn_count += 1 - if not self.analyseonly: - sys.stdout.write(str(raptor.name) + ": warning: %s\n" \ - % text[(start + 1):end]) - elif text.startswith(""): - # detect the end of a recipe - if not self.inRecipe: - sys.stdout.flush() - sys.stderr.write(self.formatError("Closing recipe tag found " \ - + "before opening recipe tag:\nUnable to print " \ - + "recipe data (Possible logfile corruption)")) - sys.stderr.flush() - else: - self.inRecipe = False - - if self.failed == True: - if not self.analyseonly: - sys.stderr.write("\n FAILED %s for %s: %s\n" % \ - (self.recipe_dict['name'], - self.recipe_dict['config'], - self.recipe_dict['name_to_user'])) - - mmppath = generic_path.Path(self.recipe_dict['mmp']).From(generic_path.CurrentDir()).GetShellPath() - sys.stderr.write(" mmp: %s\n" % mmppath) - for L in self.recipeBody: - if not L.startswith('+'): - sys.stdout.write(" %s\n" % L.rstrip()) - self.err_count += 1 - else: - r = Recipe.factory(self.recipe_dict['name'], "".join(self.recipeBody)) - warnings = r.warnings() - info = r.info() - if len(warnings) > 0: - if not self.analyseonly: - for L in self.recipeBody: - if not L.startswith('+'): - sys.stdout.write(" %s\n" % L.rstrip()) - self.warn_count += len(warnings) - - self.recipeBody = [] - return - elif not self.inRecipe and self.isMakeError(text): - # these two statements pick up errors coming from make - self.err_count += 1 - sys.stderr.write(" %s\n" % text.rstrip()) - return - elif not self.inRecipe and self.isMakeWarning(text): - self.warn_count += 1 - sys.stdout.write(" %s\n" % text.rstrip()) - return - elif text.startswith(""): - if self.inRecipe: - self.inBody = False - elif text.startswith("Copied"): - if not self.analyseonly and not self.quiet: - start = text.find(" to ") + 4 - end = text.find("",start) - short_target = text[start:end] - if short_target.startswith(self.epocroot): - short_target = short_target.replace(self.epocroot,"")[1:] - short_target = generic_path.Path(short_target).GetShellPath() - sys.stdout.write(" %s: %s\n" % ("export".ljust(FilterTerminal.recipewidth), short_target)) - return - elif text.find(" 0 or self.err_count > 0: - sys.stdout.write("\n%s : warnings: %s\n" % (raptor.name, - self.warn_count)) - sys.stdout.write("%s : errors: %s\n" % (raptor.name, - self.err_count)) - else: - sys.stdout.write("\nno warnings or errors\n") - - sys.stdout.write("\nRun time %d seconds\n" % self.raptor.runtime); - sys.stdout.write("\n") - return True - - def close(self): - """Tell raptor that there were errors.""" - if self.err_count > 0: - return False - return True - +# +# Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of the License "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# Filter class for filtering XML logs and generating reports +# Prints errors and warnings to stdout +# + +import sys +import raptor +import filter_interface +import generic_path +import os +import os.path +import re + +class Recipe(object): + """State machine that parses a recipe + """ + + suppress = [] + warningRE = re.compile("^.*((Warning:)|(MAKEDEF WARNING:)) .*$", re.DOTALL | re.M | re.I) + infoRE = None + name = [ "default" ] + recipes = [] + + def __init__(self, text): + self.suppress = self.__class__.suppress + self.text = text + self.warningRE = Recipe.warningRE + + def warnings(self): + return self.warningRE.findall(self.text) + + def info(self): + if self.infoRE: + return self.infoRE.findall(self.text) + else: + return [] + + @classmethod + def factory(cls, name, text): + for r in Recipe.recipes: + if name in r.name: + return r(text) + return Recipe(text) + + +class MwLinkerRecipe(Recipe): + suppress = [ + re.compile( +r"^mwldsym2: warning: Cannot locate library \"MSL_All_Static_MSE_Symbian\" specified in #pragma comment\(lib,...\)$" +r"[\n\r]*mwldsym2: warning: referenced from.*$" +r"[\n\r]*mwldsym2: warning: Option 'Use default libraries' is enabled but linker used.*$" +r"[\n\r]*mwldsym2: warning: runtime library from MW\[...\]LibraryFiles \(msl_all_static_mse_symbian_d.lib\);$" +r"[\n\r]*mwldsym2: warning: this indicates a potential settings/libraries mismatch.*$" + , re.M) + , re.compile( +r"^mwldsym2.exe: warning: Multiply defined symbol: ___get_MSL_init_count in.*$" +r"[\n\r]*mwldsym2.exe: warning: files uc_cwhelp.obj \(.*\), startup.win32.c.obj \(msl_all_static_mse_symbian_d.lib\),.*$" +r"[\n\r]*mwldsym2.exe: warning: keeping definition in startup.win32.c.obj.*$" + , re.M ) + , re.compile( +r"^mwldsym2.exe: warning: Option 'Use default libraries' is enabled but linker used.*$" +r"[\n\r]*mwldsym2.exe: warning: runtime library from MW\[...\]LibraryFiles \(msl_all_static_mse_symbian_d.lib\);.*$" +r"[\n\r]*mwldsym2.exe: warning: this indicates a potential settings/libraries mismatch.*$" + , re.M) + ] + name = [ "win32stagetwolink", "win32simplelink" ] + + def warnings(self): + edited = self.text + for s in MwLinkerRecipe.suppress: + edited = s.sub("", edited) + return Recipe.warningRE.findall(edited) + +Recipe.recipes.append(MwLinkerRecipe) + + +class FreezeRecipe(Recipe): + name = [ "freeze" ] + warningRE = re.compile("^(WARNING:) .*$", re.DOTALL | re.M | re.I) + infoRE = re.compile("^(EFREEZE:) .*$", re.DOTALL | re.M | re.I) + + def __init__(self, text): + Recipe.__init__(self, text) + self.warningRE = FreezeRecipe.warningRE + self.infoRE = FreezeRecipe.infoRE + +Recipe.recipes.append(FreezeRecipe) + + + +class FilterTerminal(filter_interface.Filter): + + attribute_re = re.compile("([a-z][a-z0-9]*)='([^']*)'",re.I) + maxdots = 40 # if one prints dots then don't print masses + recipelinelimit = 200 # don't scan ultra-long recipes in case we run out of memory + + # recipes that we think most users are interested in + # and the mapping that we will use to output them as + docare = { + "asmcompile" : "asmcompile" , + "compile" : "compile" , + "postlink" : "target", + "resourcecompile" : "resource", + "genstringtable" : "strtable", + "tem" : "tem", + "bitmapcompile" : "bitmap", + "bitmapcopy" : "bitmapcopy", + "win32compile2object" : "compile", + "win32stagetwolink" : "target", + "win32simplelink" : "target", + "tools2install" : "target", + "compile2object" : "compile", + "msvctoolsinstall" : "target", + "msvctoolscompile" : "compile", + "freeze" : "freeze", + "win32archive" : "target" + } + + # Determine the width of the largest mapped recipe name + recipewidth = 0 + for i in docare: + l = len(docare[i]) + if l > recipewidth: + recipewidth = l # justification for printing out recipes. + recipewidth+=1 + + def __init__(self): + self.analyseonly = False + self.quiet = False + # defaults can use EPOCROOT + if "EPOCROOT" in os.environ: + self.epocroot = str(generic_path.Path(os.environ["EPOCROOT"])) + else: + self.epocroot = str(generic_path.Path('/')) + self.current_recipe_logged = False + self.cleaned = 0 # cleaned files + self.dotcount = 0 # progress dots printed so far + # list of strings to catch make errors (must be lowercase) + self.make_error_expr = set([ + "error:", + ": ***", + "make: interrupt/exception caught (code =", + "make.exe: interrupt/exception caught (code =" + ]) + # list of strings to catch make warnings (must be lowercase) + self.make_warning_expr = ["warning:"] + + # list of strings to catch recipe warnings (must be lowercase) + self.recipe_warning_expr = ["warning:"] + + def isMakeWarning(self, text): + """A simple test for warnings. + Can be extended do to more comprehensive checking.""" + # generic warnings checked + # array of make_warning_expr holds all the possible values + for warn in self.make_warning_expr: + if warn in text.lower(): + return True + + return False + + + def isMakeError(self, text): + """A simple test for errors. + Can be extended to do more comprehensive checking.""" + + # make, emake and pvmgmake spit out things like + # make: *** No rule to make target X, needed by Y. Stop. + # + # array of make_error_expr holds all the possible values + for err in self.make_error_expr: + if err in text.lower(): + return True + + return False + + + def open(self, raptor_instance): + """Set output to stdout for the various I/O methods to write to.""" + self.raptor = raptor_instance + + # Be totally silent? + if self.raptor.logFileName is None: + self.analyseonly = True + + # Only print errors and warnings? + if self.raptor.quiet: + self.quiet = True + + # keep count of errors and warnings + self.err_count = 0 + self.warn_count = 0 + self.suppressed_warn_count = 0 + self.inBody = False + self.inRecipe = False + return True + + def write(self, text): + """Write errors and warnings to stdout""" + + if text.startswith("") + end = text.rfind("<") + self.err_count += 1 + if not self.analyseonly: + sys.stderr.write(str(raptor.name) + ": error: %s\n" \ + % text[(start + 1):end]) + elif text.startswith("") + end = text.rfind("<") + self.warn_count += 1 + if not self.analyseonly: + sys.stdout.write(str(raptor.name) + ": warning: %s\n" \ + % text[(start + 1):end]) + elif text.startswith(""): + # detect the end of a recipe + if not self.inRecipe: + sys.stdout.flush() + sys.stderr.write(self.formatError("Closing recipe tag found " \ + + "before opening recipe tag:\nUnable to print " \ + + "recipe data (Possible logfile corruption)")) + sys.stderr.flush() + else: + self.inRecipe = False + + if self.failed == True: + if not self.analyseonly: + sys.stderr.write("\n FAILED %s for %s: %s\n" % \ + (self.recipe_dict['name'], + self.recipe_dict['config'], + self.recipe_dict['name_to_user'])) + + mmppath = generic_path.Path(self.recipe_dict['mmp']).From(generic_path.CurrentDir()).GetShellPath() + sys.stderr.write(" mmp: %s\n" % mmppath) + for L in self.recipeBody: + if not L.startswith('+'): + sys.stdout.write(" %s\n" % L.rstrip()) + self.err_count += 1 + else: + r = Recipe.factory(self.recipe_dict['name'], "".join(self.recipeBody)) + warnings = r.warnings() + info = r.info() + if len(warnings) > 0: + if not self.analyseonly: + for L in self.recipeBody: + if not L.startswith('+'): + sys.stdout.write(" %s\n" % L.rstrip()) + self.warn_count += len(warnings) + + self.recipeBody = [] + return + elif not self.inRecipe and self.isMakeError(text): + # these two statements pick up errors coming from make + self.err_count += 1 + sys.stderr.write(" %s\n" % text.rstrip()) + return + elif not self.inRecipe and self.isMakeWarning(text): + self.warn_count += 1 + sys.stdout.write(" %s\n" % text.rstrip()) + return + elif text.startswith(""): + if self.inRecipe: + self.inBody = False + elif text.startswith("Copied"): + if not self.analyseonly and not self.quiet: + start = text.find(" to ") + 4 + end = text.find("",start) + short_target = text[start:end] + if short_target.startswith(self.epocroot): + short_target = short_target.replace(self.epocroot,"")[1:] + short_target = generic_path.Path(short_target).GetShellPath() + sys.stdout.write(" %s: %s\n" % ("export".ljust(FilterTerminal.recipewidth), short_target)) + return + elif text.find(" 0 or self.err_count > 0: + sys.stdout.write("\n%s : warnings: %s\n" % (raptor.name, + self.warn_count)) + sys.stdout.write("%s : errors: %s\n" % (raptor.name, + self.err_count)) + else: + sys.stdout.write("\nno warnings or errors\n") + + sys.stdout.write("\nRun time %d seconds\n" % self.raptor.runtime); + sys.stdout.write("\n") + return True + + def close(self): + """Tell raptor that there were errors.""" + if self.err_count > 0: + return False + return True +