def writeOperaSetup(self, sourceRoot, outputRoot): """ Writes a small header file with the current time to {outputRoot}/modules/hardcore/base/operasetup.h That file's sole purpose is to help dependency resolving. If the platform needs it, it should be included from a platform-specific header file. If outputRoot equals sourceRoot, then modules/hardcore/module.generated is updated with the name of the generated file: "base/operasetup.h". """ if outputRoot is None: outputRoot = sourceRoot opera_setup_h = os.path.join(outputRoot, 'modules', 'hardcore', 'base', 'operasetup.h') util.makedirs(os.path.dirname(opera_setup_h)) f = None try: f = open(opera_setup_h, "w") print >>f, "#ifndef MODULES_HARDCORE_OPERA_OPERASETUP_H" print >>f, "#define MODULES_HARDCORE_OPERA_OPERASETUP_H" print >>f, "// Modified by operasetup.py %s" % time.ctime() print >>f, "#endif // !MODULES_HARDCORE_OPERA_OPERASETUP_H" finally: if f: f.close() if outputRoot == sourceRoot: util.updateModuleGenerated(os.path.join(sourceRoot, 'modules', 'hardcore'), ["base/operasetup.h"])
def writeOutputFiles(self, sourceRoot, outputRoot=None): import util hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') actionsDir = os.path.join(hardcoreDir, 'actions') if outputRoot is None: targetDir = actionsDir else: targetDir = os.path.join(outputRoot, 'modules', 'hardcore', 'actions') util.makedirs(targetDir) changed = util.readTemplate(os.path.join(actionsDir, 'actions_template.h'), os.path.join(targetDir, 'generated_actions.h'), HandleTemplateAction(self)) changed = util.readTemplate(os.path.join(actionsDir, 'actions_enum_template.h'), os.path.join(targetDir, 'generated_actions_enum.h'), HandleTemplateAction(self)) or changed changed = util.readTemplate(os.path.join(actionsDir, 'actions_strings_template.h'), os.path.join(targetDir, 'generated_actions_strings.h'), HandleTemplateAction(self)) or changed # Ignore changes in this; this is just a template for a # platforms' actions.h and not used when building Opera: util.readTemplate(os.path.join(actionsDir, 'actions_template_template.h'), os.path.join(targetDir, 'generated_actions_template.h'), HandleTemplateAction(self)) if targetDir == actionsDir: util.updateModuleGenerated( hardcoreDir, ['actions/generated_actions.h', 'actions/generated_actions_enum.h', 'actions/generated_actions_strings.h', 'actions/generated_actions_template.h']) return changed
def __call__(self, sourceRoot, outputRoot=None, quiet=True, show_all=False): """ Calling this instance will generate the source files from the modules/viewers/module.viewers file. @param sourceRoot is the root directory of the source tree that was parsed. Some of the output files are always generated relative to the sourceRoot. @param outputRoot root of the tree for generated files, defaults to sourceRoot @param quiet if False, print a message if no files were changed. @param show_all controls whether to show only modified files or all files which are inspected. Default is False. @return The convention of the "system-functions" are that the return value should be - 0 to indicate success - 1 to indicate an error - 2 to indicate that output files have changed. """ self.startTiming() import viewers if outputRoot == None: outputRoot = sourceRoot modulepath = os.path.join(sourceRoot, "modules", "viewers") viewersfile = os.path.join(modulepath, "module.viewers") destpath = os.path.join(outputRoot, "modules", "viewers", "src") enumfile = os.path.join(destpath, "generated_viewers_enum.h") datafile = os.path.join(destpath, "generated_viewers_data.inc") result = 0 util.fileTracker.addInput(viewersfile) if not os.path.exists(enumfile) or not os.path.exists(datafile) or \ max(os.path.getmtime(viewersfile), os.path.getmtime(viewers.__file__)) > min(os.path.getmtime(enumfile), os.path.getmtime(datafile)): util.makedirs(destpath) viewers.BuildViewers(viewersfile, enumfile, datafile) result = 2 # List the generated files in module.generated if outputRoot == sourceRoot: util.updateModuleGenerated(modulepath, [enumfile[len(modulepath) + 1:], datafile[len(modulepath) + 1:]]) return self.endTiming(result, quiet=quiet)
def __call__(self, sourceRoot, outputRoot=None, quiet=True, show_all=False): """ Calling this instance will generate the source files from the modules/viewers/module.viewers file. @param sourceRoot is the root directory of the source tree that was parsed. Some of the output files are always generated relative to the sourceRoot. @param outputRoot root of the tree for generated files, defaults to sourceRoot @param quiet if False, print a message if no files were changed. @param show_all controls whether to show only modified files or all files which are inspected. Default is False. @return The convention of the "system-functions" are that the return value should be - 0 to indicate success - 1 to indicate an error - 2 to indicate that output files have changed. """ self.startTiming() import viewers if outputRoot == None: outputRoot = sourceRoot modulepath = os.path.join(sourceRoot, "modules", "viewers") viewersfile = os.path.join(modulepath, "module.viewers") destpath = os.path.join(outputRoot, "modules", "viewers", "src") enumfile = os.path.join(destpath, "generated_viewers_enum.h") datafile = os.path.join(destpath, "generated_viewers_data.inc") result = 0 util.fileTracker.addInput(viewersfile) if not os.path.exists(enumfile) or not os.path.exists(datafile) or \ max(os.path.getmtime(viewersfile), os.path.getmtime(viewers.__file__)) > min(os.path.getmtime(enumfile), os.path.getmtime(datafile)): util.makedirs(destpath) viewers.BuildViewers(viewersfile, enumfile, datafile) result = 2 # List the generated files in module.generated if outputRoot == sourceRoot: util.updateModuleGenerated(modulepath, [enumfile[len(modulepath) + 1:], datafile[len(modulepath) + 1:]]) return self.endTiming(result, quiet=quiet)
def create_opera_h(self, sourceRoot, outputRoot=None): """ Creates modules/hardcore/opera/opera.h from the corresponding template file modules/hardcore/opera/opera_template.h. The file is generate relative to the specified outputRoot. If the outputRoot is not specified, sourceRoot is used. If outputRoot == sourceRoot then hardcore's module.generated is updated with the line "opera/opera.h". Returns true if the generated file was changed. """ if outputRoot is None: outputRoot = sourceRoot hardcoreDir = os.path.join(sourceRoot, "modules", "hardcore") template = os.path.join(hardcoreDir, "opera", "opera_template.h") opera_h = os.path.join(outputRoot, "modules", "hardcore", "opera", "opera.h") changed = util.readTemplate(template, opera_h, self.getTemplateActionHandler(sourceRoot)) if sourceRoot == outputRoot: util.updateModuleGenerated(hardcoreDir, ["opera/opera.h"]) return changed
def create_opera_h(self, sourceRoot, outputRoot=None): """ Creates modules/hardcore/opera/opera.h from the corresponding template file modules/hardcore/opera/opera_template.h. The file is generate relative to the specified outputRoot. If the outputRoot is not specified, sourceRoot is used. If outputRoot == sourceRoot then hardcore's module.generated is updated with the line "opera/opera.h". Returns true if the generated file was changed. """ if outputRoot is None: outputRoot = sourceRoot hardcoreDir = os.path.join(sourceRoot, "modules", "hardcore") template = os.path.join(hardcoreDir, "opera", "opera_template.h") opera_h = os.path.join(outputRoot, "modules", "hardcore", "opera", "opera.h") changed = util.readTemplate(template, opera_h, self.getTemplateActionHandler(sourceRoot)) if sourceRoot == outputRoot: util.updateModuleGenerated(hardcoreDir, ["opera/opera.h"]) return changed
def create_components_h(self, sourceRoot, outputRoot=None): """ Creates modules/hardcore/opera/components.h from the template file modules/hardcore/opera/components_template.h and the module.components file from all modules. The file is generated relative to the specified outputRoot. If the outputRoot is not specified, sourceRoot is used. If outputRoot == sourceRoot then hardcore's module.generated is updated with the line 'opera/components.h'. Returns true if the generated file was changed. """ if outputRoot is None: outputRoot = sourceRoot hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') operaDir = os.path.join(hardcoreDir, 'opera') changed = util.readTemplate(os.path.join(operaDir, 'components_template.h'), os.path.join(outputRoot, 'modules', 'hardcore', 'opera', 'components.h'), ComponentTemplateActionHandler(self.components())) if sourceRoot == outputRoot: util.updateModuleGenerated(hardcoreDir, ["opera/components.h"]) return changed
def writeOutputFiles(self, sourceRoot, outputRoot): hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') mhDir = os.path.join(hardcoreDir, 'mh') if outputRoot is None: targetDir = mhDir else: targetDir = os.path.join(outputRoot, 'modules', 'hardcore', 'mh') util.makedirs(targetDir) changed = util.readTemplate(os.path.join(mhDir, 'messages_template.h'), os.path.join(targetDir, 'generated_messages.h'), HandleTemplateAction(self)) changed = util.readTemplate(os.path.join(mhDir, 'message_strings_template.inc'), os.path.join(targetDir, 'generated_message_strings.inc'), HandleTemplateAction(self)) or changed if targetDir == mhDir: util.updateModuleGenerated(hardcoreDir, ['mh/generated_messages.h', 'mh/generated_message_strings.inc']) return changed
def generateSourcesSetup(self, verify_sources=True): """ Generates the files sources.all, sources.nopch, sources.pch, sources.pch_system_includes and sources.pch_jumbo in both modules/hardcore/setup/plain/sources and modules/hardcore/setup/jumbo/sources. It also generates the jumbo compile units of all modules. @return True if any of the generated files has changed and False if none has changed. """ changed = False self.__plain_sources = module_sources.SourcesSet() self.__jumbo_sources = module_sources.SourcesSet() for module in self.__modules: if util.fileTracker.addInput(module.getSourcesFile()): sources = module.getModuleSources() changed = sources.generateJumboCompileUnits(self.__sourceRoot, self.__outputRoot) or changed self.__plain_sources.extend(sources.plain_sources(), module.type(), module.name()) self.__jumbo_sources.extend(sources.jumbo_sources(), module.type(), module.name()) # verify that all files exist: if verify_sources: for filename in set(self.__plain_sources.all()) | set(self.__jumbo_sources.all()): if not os.path.exists(os.path.join(self.__sourceRoot, filename)) and not os.path.exists(os.path.join(self.__outputRoot, filename)): self.addError(util.Line("", 0), "file '%s' not found" % filename) hardcoreDir = os.path.join(self.__outputRoot, 'modules', 'hardcore') plainDir = os.path.join(hardcoreDir, 'setup', 'plain', 'sources') jumboDir = os.path.join(hardcoreDir, 'setup', 'jumbo', 'sources') sources = ['all', 'nocph', 'pch', 'pch_system_includes', 'pch_jumbo'] changed = self.__plain_sources.generateSourcesListFiles(plainDir) or changed util.updateModuleGenerated(hardcoreDir, map(lambda s: '/'.join(['setup', 'plain', 'sources', "sources.%s" % s]), sources)) changed = self.__jumbo_sources.generateSourcesListFiles(jumboDir) or changed util.updateModuleGenerated(hardcoreDir, map(lambda s: '/'.join(['setup', 'jumbo', 'sources', "sources.%s" % s]), sources)) return changed
def generateSourcesSetup(self, verify_sources=True): """ Generates the files sources.all, sources.nopch, sources.pch, sources.pch_system_includes and sources.pch_jumbo in both modules/hardcore/setup/plain/sources and modules/hardcore/setup/jumbo/sources. It also generates the jumbo compile units of all modules. @return True if any of the generated files has changed and False if none has changed. """ changed = False self.__plain_sources = module_sources.SourcesSet() self.__jumbo_sources = module_sources.SourcesSet() for module in self.__modules: if util.fileTracker.addInput(module.getSourcesFile()): sources = module.getModuleSources() changed = sources.generateJumboCompileUnits(self.__sourceRoot, self.__outputRoot) or changed self.__plain_sources.extend(sources.plain_sources(), module.type(), module.name()) self.__jumbo_sources.extend(sources.jumbo_sources(), module.type(), module.name()) # verify that all files exist: if verify_sources: for filename in set(self.__plain_sources.all()) | set(self.__jumbo_sources.all()): if not os.path.exists(os.path.join(self.__sourceRoot, filename)) and not os.path.exists(os.path.join(self.__outputRoot, filename)): self.addError(util.Line("", 0), "file '%s' not found" % filename) hardcoreDir = os.path.join(self.__outputRoot, 'modules', 'hardcore') plainDir = os.path.join(hardcoreDir, 'setup', 'plain', 'sources') jumboDir = os.path.join(hardcoreDir, 'setup', 'jumbo', 'sources') sources = ['all', 'nocph', 'pch', 'pch_system_includes', 'pch_jumbo'] changed = self.__plain_sources.generateSourcesListFiles(plainDir) or changed util.updateModuleGenerated(hardcoreDir, map(lambda s: '/'.join(['setup', 'plain', 'sources', "sources.%s" % s]), sources)) changed = self.__jumbo_sources.generateSourcesListFiles(jumboDir) or changed util.updateModuleGenerated(hardcoreDir, map(lambda s: '/'.join(['setup', 'jumbo', 'sources', "sources.%s" % s]), sources)) return changed
def create_components_h(self, sourceRoot, outputRoot=None): """ Creates modules/hardcore/opera/components.h from the template file modules/hardcore/opera/components_template.h and the module.components file from all modules. The file is generated relative to the specified outputRoot. If the outputRoot is not specified, sourceRoot is used. If outputRoot == sourceRoot then hardcore's module.generated is updated with the line 'opera/components.h'. Returns true if the generated file was changed. """ if outputRoot is None: outputRoot = sourceRoot hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') operaDir = os.path.join(hardcoreDir, 'opera') changed = util.readTemplate( os.path.join(operaDir, 'components_template.h'), os.path.join(outputRoot, 'modules', 'hardcore', 'opera', 'components.h'), ComponentTemplateActionHandler(self.components())) if sourceRoot == outputRoot: util.updateModuleGenerated(hardcoreDir, ["opera/components.h"]) return changed
def writeOutputFiles(self, sourceRoot, outputRoot=None): import util hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') actionsDir = os.path.join(hardcoreDir, 'actions') if outputRoot is None: targetDir = actionsDir else: targetDir = os.path.join(outputRoot, 'modules', 'hardcore', 'actions') util.makedirs(targetDir) changed = util.readTemplate( os.path.join(actionsDir, 'actions_template.h'), os.path.join(targetDir, 'generated_actions.h'), HandleTemplateAction(self)) changed = util.readTemplate( os.path.join(actionsDir, 'actions_enum_template.h'), os.path.join(targetDir, 'generated_actions_enum.h'), HandleTemplateAction(self)) or changed changed = util.readTemplate( os.path.join(actionsDir, 'actions_strings_template.h'), os.path.join(targetDir, 'generated_actions_strings.h'), HandleTemplateAction(self)) or changed # Ignore changes in this; this is just a template for a # platforms' actions.h and not used when building Opera: util.readTemplate( os.path.join(actionsDir, 'actions_template_template.h'), os.path.join(targetDir, 'generated_actions_template.h'), HandleTemplateAction(self)) if targetDir == actionsDir: util.updateModuleGenerated(hardcoreDir, [ 'actions/generated_actions.h', 'actions/generated_actions_enum.h', 'actions/generated_actions_strings.h', 'actions/generated_actions_template.h' ]) return changed
def __call__(self, sourceRoot, outputRoot=None, quiet=True, show_all=False): """ Calling this instance will generate the source files from all prefs .txt files. @param sourceRoot is the root directory of the source tree that was parsed. Some of the output files are always generated relative to the sourceRoot. @param outputRoot root of the tree for generated files, defaults to sourceRoot @param quiet if False, print some log messages about executing the perl script. @param show_all controls whether to show only modified files or all files which are inspected. Default is False. @return The convention of the "system-functions" are that the return value should be - 0 to indicate success - 1 to indicate an error - 2 to indicate that output files have changed. """ self.startTiming() if outputRoot == None: outputRoot = sourceRoot perl = self.findPerl(quiet) if perl is None: return self.endTiming(1, quiet=quiet) # Now perl should be the path to a perl executable # Scan for modules and prefs files and build the structure allfiles = [] changed = False for module, files in find_prefs_files(sourceRoot): modfiles = [] for filename in files: self.logmessage(quiet, "Creating prefs enum for %s" % (filename)) parser = PrefsCollectionParser() parser.parse("%s.txt" % filename) if not quiet: parser.printParserWarnings() if parser.printParserErrors(): return self.endTiming(1, quiet=quiet) handler = PrefsCollectionTemplateActionHandler( parser.header(), parser.items()) stem = os.path.relpath(filename, sourceRoot) outdir = os.path.dirname(os.path.join(outputRoot, stem)) basename = os.path.basename(filename) prefs_collection_dir = os.path.join("modules", "prefs", "prefsmanager", "collections") pc_template_h = os.path.join(sourceRoot, prefs_collection_dir, "pc_template.h") output_h = os.path.join(outdir, "%s_h.inl" % basename) changed = util.readTemplate(pc_template_h, output_h, handler) or changed pc_template_c = os.path.join(sourceRoot, prefs_collection_dir, "pc_template.cpp") output_c = os.path.join(outdir, "%s_c.inl" % basename) changed = util.readTemplate(pc_template_c, output_c, handler) or changed modfiles += [output_c, output_h] allfiles.append(stem) util.fileTracker.addInput(stem + ".cpp") # Will be used by extract-documentation.pl # List the generated files in module.generated if outputRoot == sourceRoot: util.updateModuleGenerated(module.fullPath(), modfiles) # Update documentation for f in ('modules/prefs/prefsmanager/opprefscollection.cpp', 'modules/prefs/prefsmanager/opprefscollection.h', 'modules/prefs/module.tweaks', 'modules/prefs/prefsmanager/collections/erasettings.h', 'modules/pi/OpSystemInfo.h'): util.fileTracker.addInput(f) # Will be used by extract-documentation.pl if changed: documentation_dir = os.path.join(sourceRoot, "modules", "prefs") documentation_output_dir = os.path.join(outputRoot, "modules", "prefs") documentation_path = os.path.join(documentation_dir, "extract-documentation.pl") util.makedirs(os.path.join(documentation_output_dir, "documentation")) self.logmessage(quiet, "calling script %s" % (documentation_path)) subprocess.call([perl, documentation_path, "-o", outputRoot] + allfiles, cwd=sourceRoot) if outputRoot == sourceRoot: util.updateModuleGenerated(documentation_output_dir, ["documentation/settings.html"]) if changed: result = 2 else: result = 0 return self.endTiming(result, quiet=quiet)
def __call__(self, sourceRoot, outputRoot=None, quiet=True, show_all=False): """ Calling this instance will generate the source files from all prefs .txt files. @param sourceRoot is the root directory of the source tree that was parsed. Some of the output files are always generated relative to the sourceRoot. @param outputRoot root of the tree for generated files, defaults to sourceRoot @param quiet if False, print some log messages about executing the perl script. @param show_all controls whether to show only modified files or all files which are inspected. Default is False. @return The convention of the "system-functions" are that the return value should be - 0 to indicate success - 1 to indicate an error - 2 to indicate that output files have changed. """ self.startTiming() if outputRoot == None: outputRoot = sourceRoot perl = self.findPerl(quiet) if perl is None: return self.endTiming(1, quiet=quiet) # Now perl should be the path to a perl executable # Scan for modules and prefs files and build the structure allfiles = [] changed = False for module, files in find_prefs_files(sourceRoot): modfiles = [] for filename in files: self.logmessage(quiet, "Creating prefs enum for %s" % (filename)) parser = PrefsCollectionParser() parser.parse("%s.txt" % filename) if not quiet: parser.printParserWarnings() if parser.printParserErrors(): return self.endTiming(1, quiet=quiet) handler = PrefsCollectionTemplateActionHandler( parser.header(), parser.items()) stem = os.path.relpath(filename, sourceRoot) outdir = os.path.dirname(os.path.join(outputRoot, stem)) basename = os.path.basename(filename) prefs_collection_dir = os.path.join("modules", "prefs", "prefsmanager", "collections") pc_template_h = os.path.join(sourceRoot, prefs_collection_dir, "pc_template.h") output_h = os.path.join(outdir, "%s_h.inl" % basename) changed = util.readTemplate(pc_template_h, output_h, handler) or changed pc_template_c = os.path.join(sourceRoot, prefs_collection_dir, "pc_template.cpp") output_c = os.path.join(outdir, "%s_c.inl" % basename) changed = util.readTemplate(pc_template_c, output_c, handler) or changed modfiles += [output_c, output_h] allfiles.append(stem) util.fileTracker.addInput( stem + ".cpp") # Will be used by extract-documentation.pl # List the generated files in module.generated if outputRoot == sourceRoot: util.updateModuleGenerated(module.fullPath(), modfiles) # Update documentation for f in ('modules/prefs/prefsmanager/opprefscollection.cpp', 'modules/prefs/prefsmanager/opprefscollection.h', 'modules/prefs/module.tweaks', 'modules/prefs/prefsmanager/collections/erasettings.h', 'modules/pi/OpSystemInfo.h'): util.fileTracker.addInput( f) # Will be used by extract-documentation.pl if changed: documentation_dir = os.path.join(sourceRoot, "modules", "prefs") documentation_output_dir = os.path.join(outputRoot, "modules", "prefs") documentation_path = os.path.join(documentation_dir, "extract-documentation.pl") util.makedirs( os.path.join(documentation_output_dir, "documentation")) self.logmessage(quiet, "calling script %s" % (documentation_path)) subprocess.call([perl, documentation_path, "-o", outputRoot] + allfiles, cwd=sourceRoot) if outputRoot == sourceRoot: util.updateModuleGenerated(documentation_output_dir, ["documentation/settings.html"]) if changed: result = 2 else: result = 0 return self.endTiming(result, quiet=quiet)
def generate(sourceRoot, outputRoot): class File: def __init__(self, path, root=outputRoot): self.__path = os.path.join(root, *path.split("/")) self.__file = StringIO() self.__updated = False def __getattr__(self, name): return getattr(self.__file, name) def close(self): written = self.__file.getvalue() try: existing = open(self.__path).read() except: existing = None if written != existing: self.__updated = True util.makedirs(os.path.dirname(self.__path)) open(self.__path, "w").write(written) def updated(self): return self.__updated def __str__(self): return self.__path atoms_txt_path = os.path.join(sourceRoot, "modules/dom/src/atoms.txt") opatom_h_path = "modules/dom/src/opatom.h" opatom_cpp_path = "modules/dom/src/opatom.cpp.inc" opatom_ot_path = "modules/dom/selftest/opatom.ot" errors = [] warnings = [] informational = [] util.fileTracker.addInput(atoms_txt_path) atoms_txt = open(atoms_txt_path, "r") atoms = {} def addAtom(name, css_property, html_attribute, svg_attribute, condition): atom = atoms.get(name) if atom: errors.append("modules/dom/src/atoms.txt:%d: atom defined twice, previously defined at line %d" % (line_nr, atom['line_nr'])) else: atoms[name] = dict(line_nr=line_nr, name=name, css_property=css_property, html_attribute=html_attribute, svg_attribute=svg_attribute, condition=condition) re_comment = re.compile(r"^\s*#.*$") re_condition = r"(?:{(.*)})?" re_simple_atom = re.compile(r"^\s*([a-zA-Z0-9_]+)\s*" + re_condition + "\s*$") re_complex_atom = re.compile(r"^\s*([a-zA-Z0-9_]+)\s*=\s\[(.*)\]\s*" + re_condition + "\s*$") line_nr = 0 in_header = True atoms_txt_header = [] for line in atoms_txt: line_nr += 1 line = line.strip() if in_header: if line.startswith("#"): atoms_txt_header.append(line) else: in_header = False if not line: continue match = re_comment.match(line) if match: continue match = re_simple_atom.match(line) if match: condition = match.group(2) if condition: condition = condition.strip(); addAtom(match.group(1), None, None, None, condition) continue def is_html(d): return d.startswith("ATTR_") or d.startswith("Markup::HA_") def is_svg(d): return d.startswith("SVG_SA_") or d.startswith("Markup::SVGA_") match = re_complex_atom.match(line) if match: data = match.group(2).split(",") css_property = [datum.strip() for datum in data if datum.strip().startswith("CSS_PROPERTY_")] html_attribute = [datum.strip() for datum in data if is_html(datum.strip())] svg_attribute = [datum.strip() for datum in data if is_svg(datum.strip())] unknown = [datum.strip() for datum in data if not datum.strip().startswith("CSS_PROPERTY_") and not is_html(datum.strip()) and not is_svg(datum.strip())] if css_property: css_property = css_property[0] else: css_property = None if html_attribute: html_attribute = html_attribute[0] else: html_attribute = None if svg_attribute: svg_attribute = svg_attribute[0] else: svg_attribute = None if unknown: errors.append("modules/dom/src/atoms.txt:%d: unknown token(s): %s" % (line_nr, ", ".join(unknown))) condition = match.group(3); if condition: condition = condition.strip(); addAtom(match.group(1), css_property, html_attribute, svg_attribute, condition) continue errors.append("modules/dom/src/atoms.txt:%d: parse error" % line_nr) atoms_txt.close() atom_names = atoms.keys() atom_names.sort() if errors: print >>sys.stderr, "Errors:" for error in errors: print >>sys.stderr, error return 1 if "--grep-for-uses" in sys.argv: for atom_name in atom_names: atom = atoms[atom_name] if not atom["css_property"]: result = os.system("grep -R OP_ATOM_%s `find modules/dom/src -name '*.cpp' -print` >/dev/null" % atom_name) if os.WIFEXITED(result) and os.WEXITSTATUS(result) == 1: warnings.append("%s:%d: OP_ATOM_%s appears to be unused." % (atoms_txt_path, atom["line_nr"], atom_name)) if warnings: print >>sys.stderr, "Warnings:" for warning in warnings: print >>sys.stderr, warning last_atom_name = None last_line_nr = 0 reorder = False for atom_name in atom_names: if atoms[atom_name]["line_nr"] < last_line_nr: reorder = True break last_atom_name = atom_name last_line_nr = atoms[atom_name]["line_nr"] if reorder: print >>sys.stderr, """ WARNING: Reordering atoms in modules/dom/src/atoms.txt. This file is tracked by Git! You should commit the updated (reordered) version of the file, or everyone will get this message when building. """ atoms_txt = open(atoms_txt_path, "w") for line in atoms_txt_header: print >>atoms_txt, line print >>atoms_txt for atom_name in atom_names: atom = atoms[atom_name] data = [] condition = "" if atom["svg_attribute"]: data.append(atom["svg_attribute"]) if atom["html_attribute"]: data.append(atom["html_attribute"]) if atom["css_property"]: data.append(atom["css_property"]) if atom["condition"]: condition = " {%s}" % atom["condition"] if data: print >>atoms_txt, "%s = [%s]%s" % (atom_name, ", ".join(data), condition) else: print >>atoms_txt, "%s%s" % (atom_name, condition) atoms_txt.close() opatom_h = File(opatom_h_path) print >>opatom_h, "/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */" print >>opatom_h print >>opatom_h, "#ifndef DOM_OPATOM_H" print >>opatom_h, "#define DOM_OPATOM_H" print >>opatom_h print >>opatom_h, "#include \"modules/dom/src/domdefines.h\"" print >>opatom_h print >>opatom_h, "enum OpAtom" print >>opatom_h, "{" print >>opatom_h, "\tOP_ATOM_UNASSIGNED = -1," print >>opatom_h re_exclude_from_format = re.compile(r"ifdef|ifndef|if|\(|\)|defined") re_whitespace = re.compile(r"\s+") def formatCondition(condition): condition = re_exclude_from_format.sub("", condition) condition = re_whitespace.sub(" ", condition) return condition.strip() last_condition = None for index in range(len(atom_names)): atom_name = atom_names[index] atom = atoms[atom_name] if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_h, "#%s" % atom["condition"] last_condition = atom["condition"] print >>opatom_h, "\tOP_ATOM_%s," % atom_name if atom["condition"]: if index < len(atom_names) - 1: next_condition = atoms[atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_h, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_h print >>opatom_h, "\tOP_ATOM_ABSOLUTELY_LAST_ENUM" print >>opatom_h, "};" print >>opatom_h print >>opatom_h, "extern const unsigned g_DOM_atomData[OP_ATOM_ABSOLUTELY_LAST_ENUM];" print >>opatom_h, "extern const unsigned short g_DOM_SVG_atomData[OP_ATOM_ABSOLUTELY_LAST_ENUM];" print >>opatom_h print >>opatom_h, "OpAtom DOM_StringToAtom(const uni_char *string);" print >>opatom_h, "const char *DOM_AtomToString(OpAtom atom);" print >>opatom_h print >>opatom_h, "Markup::AttrType DOM_AtomToHtmlAttribute(OpAtom atom);" print >>opatom_h, "int DOM_AtomToCssProperty(OpAtom atom);" print >>opatom_h, "Markup::AttrType DOM_AtomToSvgAttribute(OpAtom atom);" print >>opatom_h print >>opatom_h, "#endif // DOM_OPATOM_H" opatom_h.close() opatom_cpp = File(opatom_cpp_path) print >>opatom_cpp, "/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */" print >>opatom_cpp print >>opatom_cpp, "#ifdef DOM_NO_COMPLEX_GLOBALS" print >>opatom_cpp, "# define DOM_ATOM_NAMES_START() void DOM_atomNames_Init(DOM_GlobalData *global_data) { const char **names = global_data->atomNames;" print >>opatom_cpp, "# define DOM_ATOM_NAMES_ITEM(name) *names = name; ++names;" print >>opatom_cpp, "# define DOM_ATOM_NAMES_ITEM_LAST(name) *names = name;" print >>opatom_cpp, "# define DOM_ATOM_NAMES_END() }" print >>opatom_cpp, "#else // DOM_NO_COMPLEX_GLOBALS" print >>opatom_cpp, "# define DOM_ATOM_NAMES_START() const char *const g_DOM_atomNames[] = {" print >>opatom_cpp, "# define DOM_ATOM_NAMES_ITEM(name) name," print >>opatom_cpp, "# define DOM_ATOM_NAMES_ITEM_LAST(name) name" print >>opatom_cpp, "# define DOM_ATOM_NAMES_END() };" print >>opatom_cpp, "#endif // DOM_NO_COMPLEX_GLOBALS" print >>opatom_cpp print >>opatom_cpp, "DOM_ATOM_NAMES_START()" last_atom_name = atom_names[-1] comma = "" last_condition = None for index in range(len(atom_names)): atom_name = atom_names[index] atom = atoms[atom_name] if atom_name == last_atom_name: comma = "_LAST" if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_cpp, "#%s" % atom["condition"] last_condition = atom["condition"] print >>opatom_cpp, "\tDOM_ATOM_NAMES_ITEM%s(\"%s\")" % (comma, atom_name) if atom["condition"]: if index < len(atom_names) - 1: next_condition = atoms[atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_cpp, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_cpp, "DOM_ATOM_NAMES_END()" print >>opatom_cpp print >>opatom_cpp, "const unsigned g_DOM_atomData[] =" print >>opatom_cpp, "{" comma = "," last_condition = None for index in range(len(atom_names)): atom_name = atom_names[index] atom = atoms[atom_name] if atom_name == last_atom_name: comma = "" if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_cpp, "#%s" % atom["condition"] last_condition = atom["condition"] html_attribute = atom["html_attribute"] css_property = atom["css_property"] if html_attribute is None and css_property is None: print >>opatom_cpp, "\tUINT_MAX%s // %s" % (comma, atom_name) else: if html_attribute is None: html_attribute = "USHRT_MAX" if css_property is None: css_property = "USHRT_MAX" print >>opatom_cpp, "\tstatic_cast<unsigned>(%s << 16 | %s)%s // %s" % (html_attribute, css_property, comma, atom_name) if atom["condition"]: if index < len(atom_names) - 1: next_condition = atoms[atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_cpp, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_cpp, "};" print >>opatom_cpp print >>opatom_cpp, "#ifdef SVG_DOM" print >>opatom_cpp, "const unsigned short g_DOM_SVG_atomData[] =" print >>opatom_cpp, "{" comma = "," last_condition = None for index in range(len(atom_names)): atom_name = atom_names[index] atom = atoms[atom_name] if atom_name == last_atom_name: comma = "" if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_cpp, "#%s" % atom["condition"] last_condition = atom["condition"] svg_attribute = atom["svg_attribute"] if svg_attribute is None: print >>opatom_cpp, "\tUSHRT_MAX%s // %s" % (comma, atom_name) else: print >>opatom_cpp, "\t%s%s // %s" % (svg_attribute, comma, atom_name) if atom["condition"]: if index < len(atom_names) - 1: next_condition = atoms[atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_cpp, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_cpp, "};" print >>opatom_cpp print >>opatom_cpp, "#endif // SVG_DOM" opatom_cpp.close() opatom_ot = File(opatom_ot_path) print >>opatom_ot, "/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */" print >>opatom_ot print >>opatom_ot, "group \"DOM.OpAtom.simple\";" print >>opatom_ot print >>opatom_ot, "include \"modules/dom/src/opatomdata.h\";" print >>opatom_ot, "include \"modules/util/tempbuf.h\";" print >>opatom_ot, "include \"modules/doc/frm_doc.h\";" print >>opatom_ot print >>opatom_ot, "test(\"Sequenciality\")" print >>opatom_ot, "{" print >>opatom_ot, " /* If this test fails, chances are someone has modified the OpAtom" print >>opatom_ot, " declaration manually and not updated this file correctly. */" print >>opatom_ot print >>opatom_ot, " int index = -1;" print >>opatom_ot print >>opatom_ot, " verify(OP_ATOM_UNASSIGNED == index++);" last_condition = None for index in range(len(atom_names)): atom_name = atom_names[index] atom = atoms[atom_name] if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_ot, "#%s" % atom["condition"] last_condition = atom["condition"] print >>opatom_ot, " verify(OP_ATOM_%s == index++);" % atom_names[index] if atom["condition"]: if index < len(atom_names) - 1: next_condition = atoms[atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_ot, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_ot, " verify(OP_ATOM_ABSOLUTELY_LAST_ENUM == index);" print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "test(\"Atom to string conversion\")" print >>opatom_ot, "{" last_condition = None for index in range(len(atom_names)): atom_name = atom_names[index] atom = atoms[atom_name] if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_ot, "#%s" % atom["condition"] last_condition = atom["condition"] print >>opatom_ot, " verify(op_strcmp(DOM_AtomToString(OP_ATOM_%s), \"%s\") == 0);" % (atom_name, atom_name) if atom["condition"] or last_condition: if index < len(atom_names) - 1: next_condition = atoms[atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_ot, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "test(\"String to atom conversion\")" print >>opatom_ot, "{" print >>opatom_ot, " verify(DOM_StringToAtom(UNI_L(\"aaaaaa\")) == OP_ATOM_UNASSIGNED);" last_condition = None for index in range(len(atom_names)): atom_name = atom_names[index] atom = atoms[atom_name] if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_ot, "#%s" % atom["condition"] last_condition = atom["condition"] print >>opatom_ot, " verify(DOM_StringToAtom(UNI_L(\"%s\")) == OP_ATOM_%s);" % (atom_name, atom_name) print >>opatom_ot, " verify(DOM_StringToAtom(UNI_L(\"%sA\")) == OP_ATOM_UNASSIGNED);" % atom_name if atom["condition"] or last_condition: if index < len(atom_names) - 1: next_condition = atoms[atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_ot, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_ot, " verify(DOM_StringToAtom(UNI_L(\"zzzzzz\")) == OP_ATOM_UNASSIGNED);" print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "test(\"Atom to HTML attribute conversion\")" print >>opatom_ot, "{" last_condition = None html_atom_names = [atom_name for atom_name in atom_names if atoms[atom_name]["html_attribute"]] for index in range(len(html_atom_names)): atom_name = html_atom_names[index] atom = atoms[atom_name] html_attribute = atoms[atom_name]["html_attribute"] if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_ot, "#%s" % atom["condition"] last_condition = atom["condition"] print >>opatom_ot, " verify(DOM_AtomToHtmlAttribute(OP_ATOM_%s) == %s || %s == USHRT_MAX);" % (atom_name, html_attribute, html_attribute) if atom["condition"] or last_condition: if index < len(html_atom_names) - 1: next_condition = atoms[html_atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_ot, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "test(\"Atom to SVG attribute conversion\")" print >>opatom_ot, "\trequire SVG_SUPPORT;" print >>opatom_ot, "\trequire SVG_DOM;" print >>opatom_ot, "{" last_condition = None svg_atom_names = [atom_name for atom_name in atom_names if atoms[atom_name]["svg_attribute"]] for index in range(len(svg_atom_names)): atom_name = svg_atom_names[index] atom = atoms[atom_name] svg_attribute = atoms[atom_name]["svg_attribute"] if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_ot, "#%s" % atom["condition"] last_condition = atom["condition"] print >>opatom_ot, " verify(DOM_AtomToSvgAttribute(OP_ATOM_%s) == %s || %s == USHRT_MAX);" % (atom_name, svg_attribute, svg_attribute) if atom["condition"] or last_condition: if index < len(svg_atom_names) - 1: next_condition = atoms[svg_atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_ot, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "test(\"Atom to CSS property conversion\")" print >>opatom_ot, "{" last_condition = None css_atom_names = [atom_name for atom_name in atom_names if atoms[atom_name]["css_property"]] for index in range(len(css_atom_names)): atom_name = css_atom_names[index] atom = atoms[atom_name] css_property = atoms[atom_name]["css_property"] if css_property is not None: if atom["condition"]: if atom["condition"] != last_condition: print >>opatom_ot, "#%s" % atom["condition"] last_condition = atom["condition"] print >>opatom_ot, " verify(DOM_AtomToCssProperty(OP_ATOM_%s) == %s);" % (atom_name, css_property) if atom["condition"] or last_condition: if index < len(css_atom_names) - 1: next_condition = atoms[css_atom_names[index + 1]]["condition"] else: next_condition = None if next_condition != atom["condition"]: print >>opatom_ot, "#endif // %s" % formatCondition(atom["condition"]) last_condition = None print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "group \"DOM.OpAtom.complicated\";" print >>opatom_ot, "require init;" print >>opatom_ot print >>opatom_ot, "include \"modules/dom/src/domenvironmentimpl.h\";" print >>opatom_ot, "include \"modules/dom/src/domobj.h\";" print >>opatom_ot print >>opatom_ot, "global" print >>opatom_ot, "{" print >>opatom_ot, " class AtomsTester : public DOM_Object" print >>opatom_ot, " {" print >>opatom_ot, " private:" print >>opatom_ot, " OpAtom expected, got;" print >>opatom_ot, " BOOL result, called;" print >>opatom_ot print >>opatom_ot, " public:" print >>opatom_ot, " AtomsTester()" print >>opatom_ot, " : expected(OP_ATOM_UNASSIGNED), got(OP_ATOM_UNASSIGNED), result(FALSE), called(FALSE)" print >>opatom_ot, " {" print >>opatom_ot, " }" print >>opatom_ot print >>opatom_ot, " virtual ES_GetState GetIndex(int property_index, ES_Value *value, ES_Runtime *)" print >>opatom_ot, " {" print >>opatom_ot, " expected = (OpAtom) property_index;" print >>opatom_ot, " DOMSetUndefined(value);" print >>opatom_ot, " return GET_SUCCESS;" print >>opatom_ot, " }" print >>opatom_ot print >>opatom_ot, " virtual ES_GetState GetName(OpAtom property_name, ES_Value *value, ES_Runtime *)" print >>opatom_ot, " {" print >>opatom_ot, " result = (got = property_name) == expected;" print >>opatom_ot, " called = TRUE;" print >>opatom_ot, " DOMSetUndefined(value);" print >>opatom_ot, " return GET_SUCCESS;" print >>opatom_ot, " }" print >>opatom_ot print >>opatom_ot, " virtual ES_PutState PutName(OpAtom property_name, ES_Value *, ES_Runtime *)" print >>opatom_ot, " {" print >>opatom_ot, " result = property_name == expected;" print >>opatom_ot, " called = TRUE;" print >>opatom_ot, " return PUT_SUCCESS;" print >>opatom_ot, " }" print >>opatom_ot print >>opatom_ot, " virtual int Call(ES_Object *, ES_Value *, int, ES_Value *return_value, ES_Runtime *)" print >>opatom_ot, " {" print >>opatom_ot, " if (result)" print >>opatom_ot, " DOMSetBoolean(return_value, TRUE);" print >>opatom_ot, " else" print >>opatom_ot, " {" print >>opatom_ot, " TempBuffer *buffer = GetEmptyTempBuf();" print >>opatom_ot, " char expected_int[14]; /* ARRAY OK 2009-04-24 jl */" print >>opatom_ot, " char got_int[14]; /* ARRAY OK 2009-04-24 jl */" print >>opatom_ot, " const char *expected_string, *got_string;" print >>opatom_ot print >>opatom_ot, " op_sprintf(expected_int, \"%d\", (int) expected);" print >>opatom_ot, " op_sprintf(got_int, \"%d\", (int) got);" print >>opatom_ot print >>opatom_ot, " expected_string = (expected > OP_ATOM_UNASSIGNED && expected < OP_ATOM_ABSOLUTELY_LAST_ENUM) ? DOM_AtomToString(expected) : \"<invalid>\";" print >>opatom_ot, " got_string = (got > OP_ATOM_UNASSIGNED && got < OP_ATOM_ABSOLUTELY_LAST_ENUM) ? DOM_AtomToString(got) : \"<invalid>\";" print >>opatom_ot print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(\"Expected \"));" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(expected_int));" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(\" (\"));" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(expected_string));" print >>opatom_ot, " if (called)" print >>opatom_ot, " {" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(\"), got \"));" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(got_int));" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(\" (\"));" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(got_string));" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(\")\"));" print >>opatom_ot, " }" print >>opatom_ot, " else" print >>opatom_ot, " CALL_FAILED_IF_ERROR(buffer->Append(\"), got nothing\"));" print >>opatom_ot print >>opatom_ot, " DOMSetString(return_value, buffer->GetStorage());" print >>opatom_ot, " }" print >>opatom_ot print >>opatom_ot, " result = FALSE;" print >>opatom_ot, " called = FALSE;" print >>opatom_ot print >>opatom_ot, " return ES_VALUE;" print >>opatom_ot, " }" print >>opatom_ot, " };" print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "html \"\";" print >>opatom_ot print >>opatom_ot, "test(\"Setup (c++)\")" print >>opatom_ot, "{" print >>opatom_ot, " verify(state.doc);" print >>opatom_ot, " verify(state.doc->ConstructDOMEnvironment() == OpStatus::OK);" print >>opatom_ot, " verify(state.doc->GetDOMEnvironment());" print >>opatom_ot, " verify(state.doc->GetDOMEnvironment()->IsEnabled());" print >>opatom_ot print >>opatom_ot, " DOM_Environment *env = state.doc->GetDOMEnvironment();" print >>opatom_ot print >>opatom_ot, " DOM_Object *atomstester = OP_NEW(AtomsTester, ());" print >>opatom_ot, " verify(atomstester != NULL);" print >>opatom_ot, " verify(atomstester->SetFunctionRuntime(env->GetRuntime(), UNI_L(\"atomsTester\"), NULL, NULL) == OpStatus::OK);" print >>opatom_ot, " verify(env->GetWindow()->Put(UNI_L(\"atomsTester\"), *atomstester) == OpStatus::OK);" print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "language ecmascript;" print >>opatom_ot print >>opatom_ot, "test(\"Setup (ecmascript)\")" print >>opatom_ot, " disabled;" print >>opatom_ot, "{" print >>opatom_ot, " atoms = [" for atom_name in atom_names: print >>opatom_ot, " \"%s\"," % atom_name print >>opatom_ot, " null" print >>opatom_ot, " ];" print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "test(\"GetName conversion\")" print >>opatom_ot, " disabled;" print >>opatom_ot, "{" print >>opatom_ot, " var index = 0;" print >>opatom_ot, " while (atoms[index])" print >>opatom_ot, " {" print >>opatom_ot, " var x = atomsTester[index];" print >>opatom_ot, " var y = atomsTester[atoms[index]];" print >>opatom_ot, " var result = atomsTester();" print >>opatom_ot, " if (result != true)" print >>opatom_ot, " throw result;" print >>opatom_ot, " ++index;" print >>opatom_ot, " }" print >>opatom_ot, "}" print >>opatom_ot print >>opatom_ot, "test(\"PutName conversion\")" print >>opatom_ot, " disabled;" print >>opatom_ot, "{" print >>opatom_ot, " var index = 0;" print >>opatom_ot, " while (atoms[index])" print >>opatom_ot, " {" print >>opatom_ot, " var x = atomsTester[index];" print >>opatom_ot, " atomsTester[atoms[index]] = true;" print >>opatom_ot, " var result = atomsTester();" print >>opatom_ot, " if (result != true)" print >>opatom_ot, " throw result;" print >>opatom_ot, " ++index;" print >>opatom_ot, " }" print >>opatom_ot, "}" opatom_ot.close() if outputRoot == sourceRoot: util.updateModuleGenerated(os.path.join(sourceRoot, "modules", "dom"), ["src/opatom.h", "src/opatom.cpp.inc", "selftest/opatom.ot"]) if reorder: return 1 elif opatom_h.updated() or opatom_cpp.updated() or opatom_ot.updated(): return 2 else: return 0
def __call__(self, sourceRoot, feature_def, outputRoot=None, quiet=True): """ Generates the following files in the specified output root: - modules/hardcore/features/features.h - modules/hardcore/features/features-thirdparty_attributions.inl - modules/hardcore/features/profile_{profile}.h for all profiles Generates the following files in the specified source root: - modules/hardcore/opera/setupinfo_features.cpp - modules/hardcore/documentation/features.{core_version}.xml for the core_version as given by the specified feature_def. @param sourceRoot is the path to the Opera source tree @param feature_def specifies a loaded instance of the class util.FeatureDefinition @param outputRoot is the path in which to generate the output files modules/hardcore/features/features.h modules/hardcore/features/profile_{profile}.h If this argument is None, then {sourceRoot}/modules/hardcore/features/ is used. """ self.startTiming() if feature_def is None or not feature_def.isLoaded(): error( "the argument feature_def must be a loaded util.FeatureDefinition instance" ) result = 1 else: hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') featuresDir = os.path.join(hardcoreDir, 'features') if outputRoot is None: targetDir = featuresDir else: targetDir = os.path.join(outputRoot, 'modules', 'hardcore', 'features') changed = util.makedirs(targetDir) # TODO: instead of creating a copy of "features.h" for each # profile in # opera/profiles/{profile}.[next]/include/modules/hardcore/features/ # with the same content, try to find a place for that include file # which only depends on "current" or "next" mainline-configuration: changed = util.readTemplate( os.path.join(featuresDir, 'features_template.h'), os.path.join(targetDir, 'features.h'), HandleTemplateAction(feature_def)) or changed changed = util.readTemplate( os.path.join(featuresDir, 'features-thirdparty_attributions_template.inl'), os.path.join(targetDir, 'features-thirdparty_attributions.inl'), LegalTemplateActionHandler(feature_def)) or changed # TODO: instead of creating profile_XXX.h for all profiles XXX in # opera/profile/{profile}.[next]/include/modules/hardcore/features/, # only create profile_{profile}.h for the one profile that is # needed: for profile in util.PROFILES: changed = util.readTemplate( os.path.join(featuresDir, 'profile_template.h'), os.path.join(targetDir, 'profile_%s.h' % profile), ProfileTemplateActionHandler( profile, feature_def.featuresWithDefault())) or changed if targetDir == featuresDir: util.updateModuleGenerated(hardcoreDir, [ 'features/features.h', 'features/features-thirdparty_attributions.inl' ] + [ 'features/profile_%s.h' % profile for profile in util.PROFILES ]) # Ignore changes in setupinfo_features.cpp and documentation files: setupinfoDir = os.path.join(hardcoreDir, 'opera') documentationDir = os.path.join(hardcoreDir, 'documentation') if outputRoot is None: setupinfoOutputDir = setupInfoDir documentationOutputDir = documentationDir else: setupinfoOutputDir = os.path.join(outputRoot, 'modules', 'hardcore', 'opera') documentationOutputDir = os.path.join(outputRoot, 'modules', 'hardcore', 'documentation') # TODO: create a different output file # setupinfo_features.{core_version}.cpp for different # core-versions - note: this is only required if new features are # added or the documentation of a feature is changed. util.readTemplate( os.path.join(setupinfoDir, 'setupinfo_features_template.cpp'), os.path.join(setupinfoOutputDir, 'setupinfo_features_generated.inl'), HandleTemplateAction(feature_def), hardcoreDir if setupinfoDir == setupinfoOutputDir else None, 'opera/setupinfo_features.cpp') if feature_def.coreVersion() is None: features_xml = 'features.xml' else: features_xml = 'features.%s.xml' % feature_def.coreVersion() util.readTemplate( os.path.join(featuresDir, 'features_template.xml'), os.path.join(documentationOutputDir, features_xml), HandleTemplateAction(feature_def), hardcoreDir if documentationDir == documentationOutputDir else None, 'documentation/%s' % features_xml) if changed: result = 2 else: result = 0 return self.endTiming(result, sourceRoot=sourceRoot, outputRoot=outputRoot, quiet=quiet)
def generatePchFiles(sourceRoot, outputRoot, platform_product_config=None, pch_template=None): """ Generates from modules/hardcore/base/pch_template.h the header files core/pch.h, core/pch_jumbo.h, core/pch_system_includes.h @param sourceRoot is the path to the Opera source tree. @param outputRoot is the output directory in which to generate the header files. If outputRoot is None, the header files are generated relative to the specified sourceRoot. @param platform_product_config is the platform's config file that #defines the PRODUCT_* macros. That file is included by the generated pch header files. If no config file is specified, an #error statement is generated to indicate that these macros are needed on compiling the sources. @param pch_template is the template file that should be used when generating pch files @return True if any of the generated files was updated and False if none of the files were changed. """ class CreatePchFromTemplate: """ Creates a core/pch...h file frome the template file modules/hardcore/base/pch_template.h. """ def __init__(self, filename, platform_product_config=None): """ @param filename is the name of the header file to create. This name is used to generate the #ifndef...#define...#endif statements. @param platform_product_config is the path to the platform's config file which #defines the PRODUCT_* macros. If no config file is specified, an #error statement is generated to indicate that these macros are needed on compiling the sources. """ self.__define = "_CORE_%s_" % filename.replace('.', '_').upper() self.__platform_product_config = platform_product_config if filename == "pch_system_includes.h": # only core/pch_system_includes.h should add a # #define ALLOW_SYSTEM_INCLUDES self.__allow_system_includes = True else: self.__allow_system_includes = False def __call__(self, action, output): if action == "ifndef file_h": output.write("#ifndef %s\n" % self.__define) return True elif action == "define file_h": output.write("#define %s\n" % self.__define) return True elif action == "define ALLOW_SYSTEM_INCLUDES": if self.__allow_system_includes: # enclose in ifndef, because sometimes it's defined globally # (in Opera.vcxproj generated by vcxproj_update.py) # and in this case redefinition gives a lot of compilation warnings output.write("#ifndef ALLOW_SYSTEM_INCLUDES\n") output.write("#define ALLOW_SYSTEM_INCLUDES\n") output.write("#endif // ALLOW_SYSTEM_INCLUDES\n\n") return True elif action == "endif file_h": output.write("#endif // %s\n" % self.__define) return True elif action == "include platform config": if self.__platform_product_config: output.write("#include \"%s\"\n" % self.__platform_product_config) else: output.write("#ifdef PRODUCT_CONFIG_FILE\n") output.write("// The platform may define a command line define PRODUCT_CONFIG_FILE:\n") output.write("// 'PRODUCT_CONFIG_FILE=\"platforms/my_platform/product_config.h\"' which\n") output.write("// defines a header file that is included here. The header file has the\n") output.write("// possibility to define the PRODUCT_*_FILE macros e.g. like\n") output.write("// #define PRODUCT_FEATURE_FILE \"platforms/my_platform/features.h\"\n") output.write("// #define PRODUCT_SYSTEM_FILE \"platforms/my_platform/system.h\"\n") output.write("// #define PRODUCT_OPKEY_FILE \"platforms/my_platform/opkey.h\"\n") output.write("// #define PRODUCT_ACTIONS_FILE \"platforms/my_platform/actions.h\"\n") output.write("// #define PRODUCT_TWEAKS_FILE \"platforms/my_platform/tweaks.h\"\n") output.write("# include PRODUCT_CONFIG_FILE\n") output.write("#endif // PRODUCT_CONFIG_FILE\n") return True changed = False hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') if not pch_template: baseDir = os.path.join(hardcoreDir, 'base') pch_template = os.path.join(baseDir, 'pch_template.h') elif not os.path.isabs(pch_template): pch_template = os.path.join(sourceRoot, pch_template) if not os.path.exists(pch_template): raise IOError(errno.ENOENT, "Template file '%s' (passed with --pch_template) not found" % pch_template) for pch in ('pch.h', 'pch_jumbo.h', 'pch_system_includes.h'): changed = util.readTemplate( pch_template, os.path.join(outputRoot, 'core', pch), CreatePchFromTemplate(pch, platform_product_config)) or changed # if the pch files are generated relative to the modules/hardcore # dir, update hardcore's module.generated: match = re.match("^%s(.*)$" % re.escape(hardcoreDir+os.sep), outputRoot) if match: base = match.group(1).replace(os.sep, '/') util.updateModuleGenerated(os.path.join(sourceRoot, 'modules', 'hardcore'), map(lambda h: '/'.join([base, 'core', h]), ['pch.h', 'pch_jumbo.h', 'pch_system_includes.h'])) return changed
def generate(sourceRoot, outputRoot): all_prototypes = {} groups = [] re_exclude_from_format = re.compile(r"ifdef|ifndef|if|\(|\)|defined") re_whitespace = re.compile(r"\s+") def formatCondition(condition): condition = re_exclude_from_format.sub("", condition) condition = re_whitespace.sub(" ", condition) return condition.strip() class File: def __init__(self, path, root=outputRoot): self.__path = os.path.join(root, *path.split("/")) self.__file = StringIO() self.__updated = False def __getattr__(self, name): return getattr(self.__file, name) def close(self): written = self.__file.getvalue() try: existing = open(self.__path).read() except: existing = None if written != existing: self.__updated = True util.makedirs(os.path.dirname(self.__path)) open(self.__path, "w").write(written) def updated(self): return self.__updated def __str__(self): return self.__path class Group: def __init__(self, title, condition): self.__title = title self.__condition = condition self.__prototypes = [] def addPrototype(self, prototype): self.__prototypes.append(prototype) def getTitle(self): return self.__title def getLines(self, for_file): lines = ["\t/* %s */\n" % self.__title] if self.__condition: lines.append("#%s\n" % self.__condition) actual_lines = 0 current_condition = None for index, prototype in enumerate(self.__prototypes): prototype_lines = prototype.getLines(for_file) if prototype_lines: if prototype.getCondition() != current_condition: if current_condition: lines.append("#endif // %s\n" % formatCondition(current_condition)) current_condition = prototype.getCondition() if current_condition: lines.append("#%s\n" % current_condition) lines.extend(prototype_lines) actual_lines += len(prototype_lines) if actual_lines == 0: return [] if current_condition: lines.append("#endif // %s\n" % formatCondition(current_condition)) if self.__condition: lines.append("#endif // %s\n" % formatCondition(self.__condition)) lines.append("\n") return lines class Prototype: def __init__(self, name, classname, displayname, functions, functions_with_data, prepare_prototype_function, baseprototype, condition): self.__displayname = displayname self.__name = name self.__classname = classname self.__functions = functions self.__functions_with_data = functions_with_data self.__prepare_prototype_function = prepare_prototype_function self.__condition = condition if baseprototype: if baseprototype == "(ERROR)": self.__baseprototype = -2 else: self.__baseprototype = "DOM_Runtime::%s_PROTOTYPE" % baseprototype else: self.__baseprototype = -1 def getCondition(self): return self.__condition def getLines(self, for_file): if self.__name.startswith("(") and self.__name.endswith(")") and for_file in ("domruntime.h", "domruntime.cpp", "domruntime.cpp-constructor-name", "domprototypes.cpp"): return None if for_file == "domruntime.h": return ["\t%s_PROTOTYPE,\n" % self.__name] elif for_file == "domruntime.cpp": return ["\tDOM_PROTOTYPE_CLASSNAMES_ITEM(\"%s\")\n" % (self.__displayname)]; elif for_file == "domruntime.cpp-constructor-name": return ["\tDOM_CONSTRUCTOR_NAMES_ITEM(\"%s\")\n" % (self.__displayname)]; elif for_file == "domprototypes.cpp": if self.__functions and self.__functions_with_data: return ["\tDOM_PROTOTYPES_ITEM3(%s_PROTOTYPE, %s_functions, %s_functions_with_data, %s)\n" % (self.__name, self.__classname, self.__classname, self.__baseprototype)] elif self.__functions: return ["\tDOM_PROTOTYPES_ITEM1(%s_PROTOTYPE, %s_functions, %s)\n" % (self.__name, self.__classname, self.__baseprototype)] elif self.__functions_with_data: return ["\tDOM_PROTOTYPES_ITEM2(%s_PROTOTYPE, %s_functions_with_data, %s)\n" % (self.__name, self.__classname, self.__baseprototype)] else: return ["\tDOM_PROTOTYPES_ITEM0(%s_PROTOTYPE, %s)\n" % (self.__name, self.__baseprototype)] elif for_file == "domprototypes.cpp-prepare-prototype": if self.__prepare_prototype_function: return ["\tcase %s_PROTOTYPE:\n" % self.__name, "\t\t%s::%s(object, this);\n" % (self.__classname, self.__prepare_prototype_function), "\t\treturn;\n"] else: return None else: if self.__functions and self.__functions_with_data: return ["\tDOM_FUNCTIONS3(%s)\n" % self.__classname] elif self.__functions: return ["\tDOM_FUNCTIONS1(%s)\n" % self.__classname] elif self.__functions_with_data: return ["\tDOM_FUNCTIONS2(%s)\n" % self.__classname] group_decl = re.compile("^group\\s+\"([^)]+)\"(\\s+{([^}]*)})?$") group_start = re.compile("^{$") prototype_decl = re.compile("^(\\(?[A-Z0-9_]+\\)?):\\s+([A-Za-z0-9_]+)\\((\S+(?:,\s*\S+)*)?\\)(?:\\s+base=([A-Z0-9_]+|\([A-Z0-9_]+\)))?(?:\\s+{([^}]*)})?$") group_end = re.compile(r"^}$") pending_group = None current_group = None def fatal(message): print >>sys.stderr, message return 1 prototypes_txt_path = os.path.join(sourceRoot, "modules/dom/src/prototypes.txt") util.fileTracker.addInput(prototypes_txt_path) for line in open(prototypes_txt_path): line = line.strip() if not line or line[0] == "#": continue match = group_decl.match(line) if match: title = match.group(1) condition = match.group(3) if current_group: return fatal("Nested group (\"%s\" inside \"%s\")" % (title, current_group.getTitle())) if pending_group: return fatal("Parse error: %s" % line) pending_group = Group(title, condition) continue match = group_start.match(line) if match: if not pending_group: return fatal("Unexpected {") current_group = pending_group pending_group = None continue match = prototype_decl.match(line) if match: name = match.group(1) classname = match.group(2) functions_decl = match.group(3) baseprototype = match.group(4) condition = match.group(5) if all_prototypes.has_key(name): return fatal("Duplicate prototype: %s" % name) if current_group is None: return fatal("Prototype outside group: %s" % name) displayname = None functions = False functions_with_data = False prepare_prototype_function = None if functions_decl is not None: items = [item.strip() for item in functions_decl.split(",")] for item in items: if displayname is None: displayname = item elif item == "functions_with_data": functions_with_data = True elif item == "functions": functions = True elif prepare_prototype_function is None: prepare_prototype_function = item else: return fatal("Failed to grok functions declaration for prototype: %s" % name) if not displayname: return fatal("Missing display name for prototype: %s" % name) current_group.addPrototype(Prototype(name, classname, displayname, functions, functions_with_data, prepare_prototype_function, baseprototype, condition)) continue match = group_end.match(line) if match: groups.append(current_group) current_group = None continue return fatal("Parse error: %s" % line) domruntime_h = File("modules/dom/src/domruntime.h.inc") domruntime_h.write("""/* -*- Mode: c++; indent-tabs-mode: t; tab-width: 4 -*- */ enum Prototype { """) for group in groups: domruntime_h.writelines(group.getLines("domruntime.h")) domruntime_h.write("""\tPROTOTYPES_COUNT }; """) domruntime_h.close() domruntime_cpp = File("modules/dom/src/domruntime.cpp.inc") domruntime_cpp.write("""/* -*- Mode: c++; indent-tabs-mode: t; tab-width: 4 -*- */ DOM_PROTOTYPE_CLASSNAMES_START() """) for group in groups: domruntime_cpp.writelines(group.getLines("domruntime.cpp")) domruntime_cpp.write("\tDOM_PROTOTYPE_CLASSNAMES_ITEM_LAST(\"\")\n\nDOM_PROTOTYPE_CLASSNAMES_END()\n\nDOM_CONSTRUCTOR_NAMES_START()\n\n") for group in groups: domruntime_cpp.writelines(group.getLines("domruntime.cpp-constructor-name")) domruntime_cpp.write("\tDOM_CONSTRUCTOR_NAMES_ITEM_LAST(\"\")\n\nDOM_CONSTRUCTOR_NAMES_END()\n") domruntime_cpp.close() domprototypes_cpp = File("modules/dom/src/domprototypes.cpp.inc") domprototypes_cpp.write("""/* -*- Mode: c++; indent-tabs-mode: t; tab-width: 4 -*- */ DOM_PROTOTYPES_START() """) for group in groups: domprototypes_cpp.writelines(group.getLines("domprototypes.cpp")) domprototypes_cpp.write("""DOM_PROTOTYPES_END() void DOM_Runtime::PreparePrototypeL(ES_Object *object, Prototype type) { \tswitch (type) \t{ """) for group in groups: domprototypes_cpp.writelines(group.getLines("domprototypes.cpp-prepare-prototype")) domprototypes_cpp.write("""\tdefault: \t\tstatic_cast<void>(object); \t\t/* No preparation necessary. */ \t\treturn; \t} } """) domprototypes_cpp.close() domglobaldata = File("modules/dom/src/domglobaldata.inc") domglobaldata.write("""/* -*- Mode: c++; indent-tabs-mode: t; tab-width: 4 -*- */ """) written = set() for group in groups: for line in group.getLines("domglobaldata"): if line not in written: domglobaldata.write(line) if line.strip() and not line.startswith("#"): written.add(line) domglobaldata.close() if outputRoot == sourceRoot: util.updateModuleGenerated(os.path.join(sourceRoot, "modules", "dom"), ["src/domruntime.h.inc", "src/domruntime.cpp.inc", "src/domprototypes.cpp.inc", "src/domglobaldata.inc"]) if domruntime_h.updated() or domruntime_cpp.updated() or domprototypes_cpp.updated() or domglobaldata.updated(): return 2 else: return 0
def generatePchFiles(sourceRoot, outputRoot, platform_product_config=None, pch_template=None): """ Generates from modules/hardcore/base/pch_template.h the header files core/pch.h, core/pch_jumbo.h, core/pch_system_includes.h @param sourceRoot is the path to the Opera source tree. @param outputRoot is the output directory in which to generate the header files. If outputRoot is None, the header files are generated relative to the specified sourceRoot. @param platform_product_config is the platform's config file that #defines the PRODUCT_* macros. That file is included by the generated pch header files. If no config file is specified, an #error statement is generated to indicate that these macros are needed on compiling the sources. @param pch_template is the template file that should be used when generating pch files @return True if any of the generated files was updated and False if none of the files were changed. """ class CreatePchFromTemplate: """ Creates a core/pch...h file frome the template file modules/hardcore/base/pch_template.h. """ def __init__(self, filename, platform_product_config=None): """ @param filename is the name of the header file to create. This name is used to generate the #ifndef...#define...#endif statements. @param platform_product_config is the path to the platform's config file which #defines the PRODUCT_* macros. If no config file is specified, an #error statement is generated to indicate that these macros are needed on compiling the sources. """ self.__define = "_CORE_%s_" % filename.replace('.', '_').upper() self.__platform_product_config = platform_product_config if filename == "pch_system_includes.h": # only core/pch_system_includes.h should add a # #define ALLOW_SYSTEM_INCLUDES self.__allow_system_includes = True else: self.__allow_system_includes = False def __call__(self, action, output): if action == "ifndef file_h": output.write("#ifndef %s\n" % self.__define) return True elif action == "define file_h": output.write("#define %s\n" % self.__define) return True elif action == "define ALLOW_SYSTEM_INCLUDES": if self.__allow_system_includes: # enclose in ifndef, because sometimes it's defined globally # (in Opera.vcxproj generated by vcxproj_update.py) # and in this case redefinition gives a lot of compilation warnings output.write("#ifndef ALLOW_SYSTEM_INCLUDES\n") output.write("#define ALLOW_SYSTEM_INCLUDES\n") output.write("#endif // ALLOW_SYSTEM_INCLUDES\n\n") return True elif action == "endif file_h": output.write("#endif // %s\n" % self.__define) return True elif action == "include platform config": if self.__platform_product_config: output.write("#include \"%s\"\n" % self.__platform_product_config) else: output.write("#ifdef PRODUCT_CONFIG_FILE\n") output.write("// The platform may define a command line define PRODUCT_CONFIG_FILE:\n") output.write("// 'PRODUCT_CONFIG_FILE=\"platforms/my_platform/product_config.h\"' which\n") output.write("// defines a header file that is included here. The header file has the\n") output.write("// possibility to define the PRODUCT_*_FILE macros e.g. like\n") output.write("// #define PRODUCT_FEATURE_FILE \"platforms/my_platform/features.h\"\n") output.write("// #define PRODUCT_SYSTEM_FILE \"platforms/my_platform/system.h\"\n") output.write("// #define PRODUCT_OPKEY_FILE \"platforms/my_platform/opkey.h\"\n") output.write("// #define PRODUCT_ACTIONS_FILE \"platforms/my_platform/actions.h\"\n") output.write("// #define PRODUCT_TWEAKS_FILE \"platforms/my_platform/tweaks.h\"\n") output.write("# include PRODUCT_CONFIG_FILE\n") output.write("#endif // PRODUCT_CONFIG_FILE\n") return True changed = False hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') if not pch_template: baseDir = os.path.join(hardcoreDir, 'base') pch_template = os.path.join(baseDir, 'pch_template.h') elif not os.path.isabs(pch_template): pch_template = os.path.join(sourceRoot, pch_template) if not os.path.exists(pch_template): raise IOError(errno.ENOENT, "Template file '%s' (passed with --pch_template) not found" % pch_template) for pch in ('pch.h', 'pch_jumbo.h', 'pch_system_includes.h'): changed = util.readTemplate( pch_template, os.path.join(outputRoot, 'core', pch), CreatePchFromTemplate(pch, platform_product_config)) or changed # if the pch files are generated relative to the modules/hardcore # dir, update hardcore's module.generated: match = re.match("^%s(.*)$" % re.escape(hardcoreDir+os.sep), outputRoot) if match: base = match.group(1).replace(os.sep, '/') util.updateModuleGenerated(os.path.join(sourceRoot, 'modules', 'hardcore'), map(lambda h: '/'.join([base, 'core', h]), ['pch.h', 'pch_jumbo.h', 'pch_system_includes.h'])) return changed
def __call__(self, sourceRoot, feature_def, outputRoot=None, quiet=True): """ Generates the following files in the specified output root: - modules/hardcore/features/features.h - modules/hardcore/features/features-thirdparty_attributions.inl - modules/hardcore/features/profile_{profile}.h for all profiles Generates the following files in the specified source root: - modules/hardcore/opera/setupinfo_features.cpp - modules/hardcore/documentation/features.{core_version}.xml for the core_version as given by the specified feature_def. @param sourceRoot is the path to the Opera source tree @param feature_def specifies a loaded instance of the class util.FeatureDefinition @param outputRoot is the path in which to generate the output files modules/hardcore/features/features.h modules/hardcore/features/profile_{profile}.h If this argument is None, then {sourceRoot}/modules/hardcore/features/ is used. """ self.startTiming() if feature_def is None or not feature_def.isLoaded(): error("the argument feature_def must be a loaded util.FeatureDefinition instance") result = 1 else: hardcoreDir = os.path.join(sourceRoot, 'modules', 'hardcore') featuresDir = os.path.join(hardcoreDir, 'features') if outputRoot is None: targetDir = featuresDir else: targetDir = os.path.join(outputRoot, 'modules', 'hardcore', 'features') changed = util.makedirs(targetDir) # TODO: instead of creating a copy of "features.h" for each # profile in # opera/profiles/{profile}.[next]/include/modules/hardcore/features/ # with the same content, try to find a place for that include file # which only depends on "current" or "next" mainline-configuration: changed = util.readTemplate( os.path.join(featuresDir, 'features_template.h'), os.path.join(targetDir, 'features.h'), HandleTemplateAction(feature_def)) or changed changed = util.readTemplate(os.path.join(featuresDir, 'features-thirdparty_attributions_template.inl'), os.path.join(targetDir, 'features-thirdparty_attributions.inl'), LegalTemplateActionHandler(feature_def)) or changed # TODO: instead of creating profile_XXX.h for all profiles XXX in # opera/profile/{profile}.[next]/include/modules/hardcore/features/, # only create profile_{profile}.h for the one profile that is # needed: for profile in util.PROFILES: changed = util.readTemplate( os.path.join(featuresDir, 'profile_template.h'), os.path.join(targetDir, 'profile_%s.h' % profile), ProfileTemplateActionHandler(profile, feature_def.featuresWithDefault())) or changed if targetDir == featuresDir: util.updateModuleGenerated(hardcoreDir, ['features/features.h', 'features/features-thirdparty_attributions.inl'] + ['features/profile_%s.h' % profile for profile in util.PROFILES]) # Ignore changes in setupinfo_features.cpp and documentation files: setupinfoDir = os.path.join(hardcoreDir, 'opera') documentationDir = os.path.join(hardcoreDir, 'documentation') if outputRoot is None: setupinfoOutputDir = setupInfoDir documentationOutputDir = documentationDir else: setupinfoOutputDir = os.path.join(outputRoot, 'modules', 'hardcore', 'opera') documentationOutputDir = os.path.join(outputRoot, 'modules', 'hardcore', 'documentation') # TODO: create a different output file # setupinfo_features.{core_version}.cpp for different # core-versions - note: this is only required if new features are # added or the documentation of a feature is changed. util.readTemplate( os.path.join(setupinfoDir, 'setupinfo_features_template.cpp'), os.path.join(setupinfoOutputDir, 'setupinfo_features_generated.inl'), HandleTemplateAction(feature_def), hardcoreDir if setupinfoDir == setupinfoOutputDir else None, 'opera/setupinfo_features.cpp') if feature_def.coreVersion() is None: features_xml = 'features.xml' else: features_xml = 'features.%s.xml' % feature_def.coreVersion() util.readTemplate( os.path.join(featuresDir, 'features_template.xml'), os.path.join(documentationOutputDir, features_xml), HandleTemplateAction(feature_def), hardcoreDir if documentationDir == documentationOutputDir else None, 'documentation/%s' % features_xml) if changed: result = 2 else: result = 0 return self.endTiming(result, sourceRoot=sourceRoot, outputRoot=outputRoot, quiet=quiet)