def loadHooks(self): target = self.target config = self.target.config lib = self.target.library platform = self.target.project.platform # Collect hooks in various locations for fileName in config.get("hooks", []): Log.notice("Parsing hooks from '%s'." % fileName) source = self.readSource(fileName) functions = Parser.parseSource(source).functions.values() if not functions: Log.warn("No hooks found.") for f in functions: Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) for function in functions: if not function.body: Log.warn("Hook function '%s' has no body." % function.name) continue if function.name.startswith("@"): lib.hooks[function.name] = function.body continue else: try: name, hookName = function.name.split(".", 1) if not name in lib.functions: target.fail("Function '%s' referred by hook function '%s' does not exist." % (name, function.name)) if not hookName.startswith("@") and not hookName in lib.functions[name].parameters: target.fail("Parameter '%s' referred by hook function '%s' does not exist." % (hookName, function.name)) lib.functions[name].hooks[hookName] = function.body except ValueError: target.fail("Hook function name '%s' is not valid." % function.name)
def validate(self): lib = self.library # Validate the target for function in lib.functions.values(): if function.ordinal is None and function.staticLinkage and self.project.platform.requireOrdinals: Log.warn("Function '%s' does not have a valid ordinal." % function.name)
def readEvents(self): tokenHandlers = { DefineToken: self._handleDefineToken, EventToken: self._handleEventToken, ValueToken: self._handleValueToken, DurationToken: self._handleDurationToken, ApiToken: self._handleApiToken, BeginObjectToken: self._handleBeginObjectToken, EndObjectToken: self._handleEndObjectToken, } while 1: try: token = Token.read(self.file) except ValueError, e: Log.warn("Error reading token: %s" % e) continue if not token: break try: event = tokenHandlers[token.__class__](token) except Exception, e: Log.warn("Error decoding token %s: %s" % (token.__class__.__name__, e)) continue
def __init__(self, project, options): Analyzer.__init__(self, project) self.commands = {} self.commandHelp = {} self.options = options self.parser = ScriptParser() self.done = False self.colorizer = Console.colorizer self.taskMonitor = Task.RateLimitedTaskMonitor(self) self.profiling = False self.plugins = [] self.traceFiles = {} self.customSyntaxCommands = set() if not self.project.targets: Log.warn("Using empty project file.") if not self.projectHasApiDescription(): Log.warn("Project file does not contain an API description.") # Register internal commands self.registerCommand("quit", self.quit) # Start receiving task notifications Task.setMonitor(self.taskMonitor) # Load all plugins self._loadPlugins()
def readEvents(self): tokenHandlers = { DefineToken: self._handleDefineToken, EventToken: self._handleEventToken, ValueToken: self._handleValueToken, DurationToken: self._handleDurationToken, ApiToken: self._handleApiToken, BeginObjectToken: self._handleBeginObjectToken, EndObjectToken: self._handleEndObjectToken, } while 1: try: token = Token.read(self.file) except ValueError, e: Log.warn("Error reading token: %s" % e) break if not token: break event = tokenHandlers[token.__class__](token) if event: yield event
def parseConfig(config, template = None): """ Parses the given tracer configuration and returns a tree of configuration symbols. @param config Config file text @param template Optional configuration to use a template. @return: A dictionary tree of configuration values """ if not template: template = Config.Config() items = template for itemName, item in configFile.parseString(config): if not item: Log.warn("Empty top-level item '%s'." % itemName) if itemName in items and isinstance(item, Config.Group): items[itemName].update(item) elif itemName in items and isinstance(item, Config.List): items[itemName] += item else: items[itemName] = item return items
def generate(self, projectName, targetPath): tempPath = tempfile.mkdtemp() try: # Create a build build = self.project.platform.createBuild(self.config, self.library, projectName, self.name) # If there is at least one C++ function, generate only C++ code if "c++" in self.getLanguages() or self.config.get("language", "c") == "c++": playerSourceName = "player_gen.cpp" else: playerSourceName = "player_gen.c" self.library.language = "c" # Generate the player playerSourcePath = os.path.join(tempPath, playerSourceName) g = Generator.CSourcePlayerGenerator(self.config, self.project.platform, [self.library], templatePath = Resource.getPath("templates")) output = open(playerSourcePath, "w") g.generate(outputFile = output) output.close() # Add the generated source file to the configuration self.addSourceFile(playerSourcePath) # Finalize the build build.compile(targetPath = targetPath) finally: try: shutil.rmtree(tempPath) except: Log.warn("Unable to clean up temporary directory '%s'" % tempPath)
def parseConfig(config, template=None): """ Parses the given tracer configuration and returns a tree of configuration symbols. @param config Config file text @param template Optional configuration to use a template. @return: A dictionary tree of configuration values """ if not template: template = Config.Config() items = template for itemName, item in configFile.parseString(config): if not item: Log.warn("Empty top-level item '%s'." % itemName) if itemName in items and isinstance(item, Config.Group): items[itemName].update(item) elif itemName in items and isinstance(item, Config.List): items[itemName] += item else: items[itemName] = item return items
def validate(self): lib = self.library # Validate the target for function in lib.functions.values(): if function.ordinal is None and function.staticLinkage and self.project.platform.requireOrdinals: Log.warn("Function '%s' does not have a valid ordinal." % function.name) for parameter in function.parameters.values(): if lib.getNativeType(parameter.type) == "pointer" \ and not parameter.name in lib.functions[function.name].hooks \ and not parameter.metaType \ and lib.functions[function.name].generate: Log.warn("Saving naked pointer '%s' of type '%s' in function '%s'." % (parameter.name, parameter.type, function.name))
def getPath(*name, **args): """ Get a path to an existing resource. @param *name Resource path segments @param required If True, a warning is logged if the resource is not found. """ for path in paths: p = os.path.join(path, *name) if os.path.exists(p): return p if args.get("required", True) == True: Log.warn("Resource '%s' not found." % os.sep.join(name))
def load(self): # Determine the trace file size try: self.file.seek(0, 2) fileSize = self.file.tell() self.file.seek(0) except: fileSize = 0 task = Task.startTask("load", "Loading trace", steps = fileSize) # Read and verify version magic version = self.file.read(4) if version != FORMAT_VERSION: raise RuntimeError("Unsupported file format version: %s (%s)" % (version, binascii.hexlify(version))) # First pass: read all the events for i, event in enumerate(self.readEvents()): self.trace.events.append(event) if fileSize: task.updateProgress(self.file.tell()) elif (i & 0xff) == 0: task.step() task.finish() task = Task.startTask("resolve", "Resolving data", len(self.trace.events)) # Second pass: resolve any unknown phrases for event in self.trace.events: if isinstance(event.name, Trace.UnknownPhrase): Log.warn("Event %d name is undefined, trace is probably corrupted." % event.seq) self.trace.events.remove(event) continue for key, value in event.values.items(): if isinstance(key, Trace.UnknownPhrase): Log.warn("Event %d parameter name is undefined, trace is probably corrupted." % event.seq) self.trace.events.remove(event) continue if isinstance(value, Trace.UnknownPhrase): v2 = value value = self.decoder.getPhrase(value.id) if isinstance(value, Trace.UnknownPhrase): #Log.warn("Unable to resolve unknown phrase %s.%s = %s." % (event.name, key, value)) pass else: event.values[key] = value if not value in event.modifiedArrays: event.modifiedArrays.append(value) task.step()
def getNativeType(self, library, type): """ Get the native equivalent of a Type instance. @param library: Library from which the type is searched @param type: Type instance to convert to native type @returns the name of the matching native type or None """ t = library.getNativeType(type) if not t: Log.warn("Type '%s' has no mapping to a native equivalent; defaulting to 'int'." % type.declaration) t = "int" return t
def setPhrase(self, id, data): # Check that this definition is really necessary if verbose and name in self.phrasebook: oldData = self.phrasebook[name] if data == oldData: Log.warn("%d bytes of redundant phrase data for phrase 0x%x" % (len(data), name)) elif len(oldData) < len(data): for v1, v2 in zip(oldData, data): if v1 != v2: break else: Log.warn("%d bytes of partially redundant phrase data for phrase 0x%x" % (len(data), name)) self.phrasebook[id] = data
def validate(self): lib = self.library # Validate the target for function in lib.functions.values(): if function.ordinal is None and function.staticLinkage and self.project.platform.requireOrdinals: Log.warn("Function '%s' does not have a valid ordinal." % function.name) for parameter in function.parameters.values(): if lib.getNativeType(parameter.type) == "pointer" \ and not parameter.name in lib.functions[function.name].hooks \ and not parameter.metaType \ and lib.functions[function.name].generate: Log.warn( "Saving naked pointer '%s' of type '%s' in function '%s'." % (parameter.name, parameter.type, function.name))
def getNativeType(self, library, type): """ Get the native equivalent of a Type instance. @param library: Library from which the type is searched @param type: Type instance to convert to native type @returns the name of the matching native type or None """ t = library.getNativeType(type) if not t: Log.warn( "Type '%s' has no mapping to a native equivalent; defaulting to 'int'." % type.declaration) t = "int" return t
def image_upload(cls, file, width=0, height=0, thumbnail=False): if not cls.allowed_file(file.filename): Log.warn("Filename's suffix was not allowed.") raise Exception("Filename's suffix was not allowed.") if file: filename, url = cls.generate_image_path_info(file.filename) file.save(filename) pillow_image = PillowImage.open(filename).convert('RGB') if width != 0 and height != 0: if width != pillow_image.width or height != pillow_image.height: Log.warn("Invalid image size.") os.remove(filename) raise Exception('Invalid image size.') if pillow_image: if thumbnail: # 生成缩略图 if pillow_image.height > pillow_image.width: # 竖图 pos = (pillow_image.height - pillow_image.width) // 2 crop_image = pillow_image.crop( (0, pos, pillow_image.width, pillow_image.height - pos)) thumb_img = crop_image.resize( (current_app.config['APP']['thumb_height'], current_app.config['APP']['thumb_width']), PillowImage.ANTIALIAS) elif pillow_image.height < pillow_image.width: # 横图 pos = (pillow_image.width - pillow_image.height) // 2 crop_image = pillow_image.crop( (pos, 0, pillow_image.width - pos, pillow_image.height)) thumb_img = crop_image.resize( (current_app.config['APP']['thumb_height'], current_app.config['APP']['thumb_width']), PillowImage.ANTIALIAS) else: thumb_img = pillow_image.resize( (current_app.config['APP']['thumb_height'], current_app.config['APP']['thumb_width']), PillowImage.ANTIALIAS) thumb_img.save(filename + '_thumb.jpg', format='jpeg', quality=80) image = Image(filename=filename, url=url, size=op.getsize(filename), height=pillow_image.height, width=pillow_image.width).save() Log.info('Success upload file: {}.'.format(filename)) return image else: Log.warn('Can not open image file.') raise Exception('Can not open image file.') else: Log.warn('Invalid file data.') raise Exception('Invalid file data.')
def setPhrase(self, id, type, data): newData = self._decodeValueArray(id, type, data) # Check that this definition is really necessary if verbose and name in self.phrasebook: oldData = self.phrasebook[name] if newData == oldData: Log.warn("%d bytes of redundant phrase data for phrase 0x%x" % (len(data), name)) elif len(oldData) < len(newData): for v1, v2 in zip(oldData, newData): if v1 != v2: break else: Log.warn( "%d bytes of partially redundant phrase data for phrase 0x%x" % (len(data), name)) self.phrasebook[id] = newData
def loadHooks(self): target = self.target config = self.target.config lib = self.target.library platform = self.target.project.platform # Collect hooks in various locations for fileName in config.get("hooks", []): Log.notice("Parsing hooks from '%s'." % fileName) source = self.readSource(fileName) functions = Parser.parseSource(source).functions.values() if not functions: Log.warn("No hooks found.") for f in functions: Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join( ["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) for function in functions: if not function.body: Log.warn("Hook function '%s' has no body." % function.name) continue if function.name.startswith("@"): lib.hooks[function.name] = function.body continue else: try: name, hookName = function.name.split(".", 1) if not name in lib.functions: target.fail( "Function '%s' referred by hook function '%s' does not exist." % (name, function.name)) if not hookName.startswith( "@" ) and not hookName in lib.functions[name].parameters: target.fail( "Parameter '%s' referred by hook function '%s' does not exist." % (hookName, function.name)) lib.functions[name].hooks[hookName] = function.body except ValueError: target.fail("Hook function name '%s' is not valid." % function.name)
def generate(self, projectName, targetPath): tempPath = tempfile.mkdtemp() try: # Create a build build = self.project.platform.createBuild(self.config, self.library, projectName, self.name) # If there is at least one C++ function, generate only C++ code if "c++" in self.getLanguages() or self.config.get( "language", "c") == "c++": playerSourceName = "player_gen.cpp" else: playerSourceName = "player_gen.c" self.library.language = "c" # Generate the player playerSourcePath = os.path.join(tempPath, playerSourceName) g = Generator.CSourcePlayerGenerator( self.config, self.project.platform, [self.library], templatePath=Resource.getPath("templates")) output = open(playerSourcePath, "w") g.generate(outputFile=output) output.close() # Add the generated source file to the configuration self.addSourceFile(playerSourcePath) # Finalize the build build.compile(targetPath=targetPath) finally: try: shutil.rmtree(tempPath) except: Log.warn("Unable to clean up temporary directory '%s'" % tempPath)
def reportWarning(self, msg): for line in str(msg).rstrip().split("\n"): Log.warn(line)
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import Common from common import Log # Try to import matplotlib for charting try: import matplotlib matplotlib.use("Agg") import pylab except ImportError, e: matplotlib = None pylab = None Log.warn( "Matplotlib or one of it's dependencies not found (%s). Charts will not be generated." % e) def slicePlot(x, y, sliceLength=100, style="line", *args, **kwargs): assert len(x) == len(y) if style == "line": plotFunc = pylab.plot elif style == "bar": plotFunc = pylab.bar else: raise RuntimeError("Unknown plotting style: %s" % style) if len(x) < sliceLength: plotFunc(x, y, *args, **kwargs)
def prepare(self): # Shorthand for various objects config = self.config lib = self.library # Parse the sources for fileName in config.get("apiheaders", []): Log.notice("Parsing functions from '%s'." % fileName) source = self.parserTool.readSource(fileName) newLib = Parser.parseSource(source) for f in newLib.functions.values(): f.headerName = fileName for f in newLib.functions.values(): Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) if not newLib.functions: Log.warn("No new functions found.") else: Log.notice("%d functions found." % len(newLib.functions)) lib.merge(newLib) # Load the hooks self.parserTool.loadHooks() def parseBool(s): return bool(int(s)) # Read the typemap for typeDecl, mapping in self.config.types.items(): attrs = self.config.types[typeDecl].attrs name, type = Parser.parseVariableDeclaration(typeDecl + " dummy") assert name == "dummy" # If this is a class mapping, create the class if it doesn't already exist if mapping == "object": if not mapping in self.library.classes: cls = Library.Class(type) if "namespace" in attrs: cls.namespacePath = attrs["namespace"].split(".") self.library.classes[type] = cls # Patch the default decoration hint into all matching types if "decorationhint" in attrs: for function in self.library.functions.values(): for t in [p.type for p in function.parameters.values()] + [function.type]: if t == type: t.decorationHint = attrs["decorationhint"] self.library.typeMap[type] = str(mapping) # Patch in some function-specific attributes for function in config.functions.keys(): if not function in lib.functions: self.fail("Attributes specified for non-existent function '%s'." % function) attrs = config.functions[function].attrs if "terminator" in attrs: lib.functions[function].isTerminator = parseBool(attrs["terminator"]) if "generate" in attrs: lib.functions[function].generate = parseBool(attrs["generate"]) if "runtimestate" in attrs: lib.functions[function].runtimeStateTracking = parseBool(attrs["runtimestate"]) if "framemarker" in attrs: lib.functions[function].isFrameMarker = parseBool(attrs["framemarker"]) if "staticlinkage" in attrs: lib.functions[function].staticLinkage = parseBool(attrs["staticlinkage"]) if "rendercall" in attrs: lib.functions[function].isRenderCall = parseBool(attrs["rendercall"]) if "passthrough" in attrs: lib.functions[function].passthrough = parseBool(attrs["passthrough"]) if not isinstance(config.functions[function], Config.Group): self.fail("Syntax error: State map definition for function '%s' is missing braces." % function) # Argument to state mapping reservedNames = ["@return", "@modify", "@set", "@get", "@copy"] funcAttrs = attrs for arg, parameter in config.functions[function].items(): # Check that this is a valid parameter if not arg in reservedNames and not arg in lib.functions[function].parameters: self.fail("State mapping for nonexistent parameter '%s' of function '%s' specified." % (arg, function)) if arg in ["@copy"] and parseBool(funcAttrs.get("runtimestate", "0")): Log.warn("Function %s state relation %s not implemented for runtime state tracking." % (function, arg)) # Read the parameter-specific attributes attrs = config.functions[function][arg].attrs if "decoration" in attrs: lib.functions[function].parameters[arg].decoration = attrs["decoration"] if "decorationhint" in attrs: lib.functions[function].parameters[arg].decorationHint = attrs["decorationhint"] if "out" in attrs: lib.functions[function].parameters[arg].isOut = parseBool(attrs["out"]) if "object_class" in attrs: # Create a function-local type so that this parameter type is an object only for this function if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # Override the type's name so that it will refer to the new object class # while still using the original C type under the hood newType = copy.deepcopy(type) newType.isObject = True newType.name = attrs["object_class"] if arg == "@return": lib.functions[function].type = newType else: lib.functions[function].parameters[arg].type = newType # Check that this class exists classType = Library.Type(attrs["object_class"]) if not classType in self.library.classes: self.fail("Undefined object class '%s'." % classType) # Do we have a meta type? if "metatype" in config.functions[function][arg]: metaGroup = config.functions[function][arg].metatype try: metaType = Library.MetaType(metaGroup.attrs["class"]) except KeyError: self.fail("Meta type for parameter '%s' does not define class." % arg) # Is this an array parameter? if metaType.name == "array": metaType.values["size"] = Library.MetaValue("size", metaGroup.attrs.get("size", 1)) if "type" in metaGroup.attrs: metaType.values["type"] = Library.MetaValue("type", metaGroup.attrs["type"]) if metaGroup.attrs["type"] == "object": if not "object_class" in metaGroup.attrs: self.fail("Required metatype attribute object_class missing") metaType.values["object_class"] = Library.MetaValue("object_class", metaGroup.attrs["object_class"]) # How about an image parameter? elif metaType.name == "image": metaType.values["stride"] = Library.MetaValue("stride", metaGroup.attrs.get("stride", "width")) metaType.values["height"] = Library.MetaValue("height", metaGroup.attrs.get("height", "height")) metaType.values["components"] = Library.MetaValue("components", metaGroup.attrs.get("components", "1")) metaType.values["type"] = Library.MetaValue("type", metaGroup.attrs.get("type", "byte")) else: self.fail("Unknown meta type class '%s'." % metaclass) Log.debug("Meta type: %s.%s: %s" % (function, arg, metaType.name)) # Get the conditions for different meta values if isinstance(metaGroup, Config.List): for item in metaGroup: predicate = item.attrs["condition"] predicateValue = item.attrs["value"] result = item.attrs["result"] metaType.values[item].addPredicate(predicate, predicateValue, result) Log.debug("Meta type condition: If %s is %s, then %s = %s" % (predicate, predicateValue, item, result)) elif isinstance(metaGroup, Config.Group): Log.error("Meta type variations for parameter '%s' represented in a group instead of a list." % arg) # Record the meta type lib.functions[function].parameters[arg].metaType = metaType # Is this a short-hand state mapping? try: path = parameter.split(".") except AttributeError: # Try the expanded form of a nested attribute set try: path = (config.functions[function][arg].state).split(".") except AttributeError: path = [] # Check that we even have a state structure if path and not "state" in config: Log.warn("State structure not defined.") continue # Parse special state mapping relations relation = None checkPaths = [] if arg == "@copy": relation = Library.StateRelationCopy(attrs["src"].split("."), attrs["dest"].split(".")) checkPaths = [relation.sourcePath, relation.destPath] elif arg == "@get": relation = Library.StateRelationGet(path) checkPaths = [relation.path] elif arg == "@set": relation = Library.StateRelationSet(path) checkPaths = [relation.path] elif arg == "@modify": relation = Library.StateRelationModify(path) checkPaths = [relation.path] # Empty mapping? elif not "".join(path): continue if relation: for path in checkPaths: if traverseStatePath(config, path) is None: self.fail("Relation state path '%s' for function '%s' does not exist." % (".".join(path), function)) Log.debug("State relation: %s %s" % (function, relation)) lib.functions[function].stateRelations.append(relation) continue Log.debug("State mapping: %s.%s -> %s" % (function, arg, ".".join(path))) # Determine the parameter type type = None if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # If this is a runtime mapping, check that the parameter is of a supported type if lib.functions[function].runtimeStateTracking and type and \ lib.getNativeType(type) in ["float", "double"]: self.fail("Values of type '%s' can not be saved to the runtime state tree" % type) continue node = traverseStatePath(config, path) if node is None: self.fail("State path '%s' for function '%s' does not exist." % (".".join(path), function)) # Save the mapping if arg == "@return": lib.functions[function].retStateRelation = Library.StateRelationSet(path) else: lib.functions[function].parameters[arg].stateRelation = Library.StateRelationSet(path)
def prepare(self): # Shorthand for various objects config = self.config lib = self.library # Parse the sources for fileName in config.get("apiheaders", []): Log.notice("Parsing functions from '%s'." % fileName) source = self.parserTool.readSource(fileName) newLib = Parser.parseSource(source) for f in newLib.functions.values(): f.headerName = fileName for f in newLib.functions.values(): Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join( ["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) if not newLib.functions: Log.warn("No new functions found.") else: Log.notice("%d functions found." % len(newLib.functions)) lib.merge(newLib) # Load the hooks self.parserTool.loadHooks() def parseBool(s): return bool(int(s)) # Read the typemap for typeDecl, mapping in self.config.types.items(): attrs = self.config.types[typeDecl].attrs name, type = Parser.parseVariableDeclaration(typeDecl + " dummy") assert name == "dummy" # If this is a class mapping, create the class if it doesn't already exist if mapping == "object": if not mapping in self.library.classes: cls = Library.Class(type) if "namespace" in attrs: cls.namespacePath = attrs["namespace"].split(".") self.library.classes[type] = cls # Patch the default decoration hint into all matching types if "decorationhint" in attrs: for function in self.library.functions.values(): for t in [p.type for p in function.parameters.values() ] + [function.type]: if t == type: t.decorationHint = attrs["decorationhint"] self.library.typeMap[type] = str(mapping) # Patch in some function-specific attributes for function in config.functions.keys(): if not function in lib.functions: self.fail( "Attributes specified for non-existent function '%s'." % function) attrs = config.functions[function].attrs if "terminator" in attrs: lib.functions[function].isTerminator = parseBool( attrs["terminator"]) if "generate" in attrs: lib.functions[function].generate = parseBool(attrs["generate"]) if "runtimestate" in attrs: lib.functions[function].runtimeStateTracking = parseBool( attrs["runtimestate"]) if "framemarker" in attrs: lib.functions[function].isFrameMarker = parseBool( attrs["framemarker"]) if "staticlinkage" in attrs: lib.functions[function].staticLinkage = parseBool( attrs["staticlinkage"]) if "rendercall" in attrs: lib.functions[function].isRenderCall = parseBool( attrs["rendercall"]) if "passthrough" in attrs: lib.functions[function].passthrough = parseBool( attrs["passthrough"]) if not isinstance(config.functions[function], Config.Group): self.fail( "Syntax error: State map definition for function '%s' is missing braces." % function) # Argument to state mapping reservedNames = ["@return", "@modify", "@set", "@get", "@copy"] funcAttrs = attrs for arg, parameter in config.functions[function].items(): # Check that this is a valid parameter if not arg in reservedNames and not arg in lib.functions[ function].parameters: self.fail( "State mapping for nonexistent parameter '%s' of function '%s' specified." % (arg, function)) if arg in ["@copy"] and parseBool( funcAttrs.get("runtimestate", "0")): Log.warn( "Function %s state relation %s not implemented for runtime state tracking." % (function, arg)) # Read the parameter-specific attributes attrs = config.functions[function][arg].attrs if "decoration" in attrs: lib.functions[function].parameters[arg].decoration = attrs[ "decoration"] if "decorationhint" in attrs: lib.functions[function].parameters[ arg].decorationHint = attrs["decorationhint"] if "out" in attrs: lib.functions[function].parameters[arg].isOut = parseBool( attrs["out"]) if "object_class" in attrs: # Create a function-local type so that this parameter type is an object only for this function if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # Override the type's name so that it will refer to the new object class # while still using the original C type under the hood newType = copy.deepcopy(type) newType.isObject = True newType.name = attrs["object_class"] if arg == "@return": lib.functions[function].type = newType else: lib.functions[function].parameters[arg].type = newType # Check that this class exists classType = Library.Type(attrs["object_class"]) if not classType in self.library.classes: self.fail("Undefined object class '%s'." % classType) # Do we have a meta type? if "metatype" in config.functions[function][arg]: metaGroup = config.functions[function][arg].metatype try: metaType = Library.MetaType(metaGroup.attrs["class"]) except KeyError: self.fail( "Meta type for parameter '%s' does not define class." % arg) # Is this an array parameter? if metaType.name == "array": metaType.values["size"] = Library.MetaValue( "size", metaGroup.attrs.get("size", 1)) if "type" in metaGroup.attrs: metaType.values["type"] = Library.MetaValue( "type", metaGroup.attrs["type"]) if metaGroup.attrs["type"] == "object": if not "object_class" in metaGroup.attrs: self.fail( "Required metatype attribute object_class missing" ) metaType.values[ "object_class"] = Library.MetaValue( "object_class", metaGroup.attrs["object_class"]) # How about an image parameter? elif metaType.name == "image": metaType.values["stride"] = Library.MetaValue( "stride", metaGroup.attrs.get("stride", "width")) metaType.values["height"] = Library.MetaValue( "height", metaGroup.attrs.get("height", "height")) metaType.values["components"] = Library.MetaValue( "components", metaGroup.attrs.get("components", "1")) metaType.values["type"] = Library.MetaValue( "type", metaGroup.attrs.get("type", "byte")) else: self.fail("Unknown meta type class '%s'." % metaclass) Log.debug("Meta type: %s.%s: %s" % (function, arg, metaType.name)) # Get the conditions for different meta values if isinstance(metaGroup, Config.List): for item in metaGroup: predicate = item.attrs["condition"] predicateValue = item.attrs["value"] result = item.attrs["result"] metaType.values[item].addPredicate( predicate, predicateValue, result) Log.debug( "Meta type condition: If %s is %s, then %s = %s" % (predicate, predicateValue, item, result)) elif isinstance(metaGroup, Config.Group): Log.error( "Meta type variations for parameter '%s' represented in a group instead of a list." % arg) # Record the meta type lib.functions[function].parameters[arg].metaType = metaType # Is this a short-hand state mapping? try: path = parameter.split(".") except AttributeError: # Try the expanded form of a nested attribute set try: path = ( config.functions[function][arg].state).split(".") except AttributeError: path = [] # Check that we even have a state structure if path and not "state" in config: Log.warn("State structure not defined.") continue # Parse special state mapping relations relation = None checkPaths = [] if arg == "@copy": relation = Library.StateRelationCopy( attrs["src"].split("."), attrs["dest"].split(".")) checkPaths = [relation.sourcePath, relation.destPath] elif arg == "@get": relation = Library.StateRelationGet(path) checkPaths = [relation.path] elif arg == "@set": relation = Library.StateRelationSet(path) checkPaths = [relation.path] elif arg == "@modify": relation = Library.StateRelationModify(path) checkPaths = [relation.path] # Empty mapping? elif not "".join(path): continue if relation: for path in checkPaths: if traverseStatePath(config, path) is None: self.fail( "Relation state path '%s' for function '%s' does not exist." % (".".join(path), function)) Log.debug("State relation: %s %s" % (function, relation)) lib.functions[function].stateRelations.append(relation) continue Log.debug("State mapping: %s.%s -> %s" % (function, arg, ".".join(path))) # Determine the parameter type type = None if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # If this is a runtime mapping, check that the parameter is of a supported type if lib.functions[function].runtimeStateTracking and type and \ lib.getNativeType(type) in ["float", "double"]: self.fail( "Values of type '%s' can not be saved to the runtime state tree" % type) continue node = traverseStatePath(config, path) if node is None: self.fail( "State path '%s' for function '%s' does not exist." % (".".join(path), function)) # Save the mapping if arg == "@return": lib.functions[ function].retStateRelation = Library.StateRelationSet( path) else: lib.functions[function].parameters[ arg].stateRelation = Library.StateRelationSet(path)
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import Common from common import Log # Try to import matplotlib for charting try: import matplotlib matplotlib.use("Agg") import pylab except ImportError, e: matplotlib = None pylab = None Log.warn("Matplotlib or one of it's dependencies not found (%s). Charts will not be generated." % e) def slicePlot(x, y, sliceLength = 100, style = "line", *args, **kwargs): assert len(x) == len(y) if style == "line": plotFunc = pylab.plot elif style == "bar": plotFunc = pylab.bar else: raise RuntimeError("Unknown plotting style: %s" % style) if len(x) < sliceLength: plotFunc(x, y, *args, **kwargs) return