195640e3a20adea634b4df4ccf8c93f411184c438joi@chromium.org#!/usr/bin/env python 295640e3a20adea634b4df4ccf8c93f411184c438joi@chromium.org# Copyright (c) 2012 The Chromium Authors. All rights reserved. 301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org# Use of this source code is governed by a BSD-style license that can be 401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org# found in the LICENSE file. 501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 6eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org"""Miscellaneous node types. 7eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org""" 801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgimport os.path 1001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgimport re 11abf28c9e0d607e293a9d790300090e557be6b41ejoi@chromium.orgimport sys 1201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 1301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit import constants 14b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.orgfrom grit import exception 1501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit import util 1601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgimport grit.format.rc_header 17eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.orgfrom grit.node import base 18eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.orgfrom grit.node import io 19b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.orgfrom grit.node import message 2001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2277cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org# RTL languages 2377cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org# TODO(jennyz): remove this fixed set of RTL language array 2477cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org# now that generic expand_variable code exists. 2577cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org_RTL_LANGS = ( 2677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'ar', # Arabic 2777cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'fa', # Farsi 2877cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'iw', # Hebrew 2977cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'ks', # Kashmiri 3077cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'ku', # Kurdish 3177cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'ps', # Pashto 3277cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'ur', # Urdu 3377cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'yi', # Yiddish 3477cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org) 3577cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 3677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 3701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgdef _ReadFirstIdsFromFile(filename, defines): 38eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Read the starting resource id values from |filename|. We also 3901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org expand variables of the form <(FOO) based on defines passed in on 4001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org the command line. 4101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 4201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Returns a tuple, the absolute path of SRCDIR followed by the 4301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org first_ids dictionary. 44eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 45b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org first_ids_dict = eval(util.ReadFile(filename, util.RAW_TEXT)) 4601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org src_root_dir = os.path.abspath(os.path.join(os.path.dirname(filename), 4701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org first_ids_dict['SRCDIR'])) 4801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 4901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def ReplaceVariable(matchobj): 5001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for key, value in defines.iteritems(): 5101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if matchobj.group(1) == key: 5201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return value 5301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return '' 5401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 5501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org renames = [] 5601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for grd_filename in first_ids_dict: 5701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org new_grd_filename = re.sub(r'<\(([A-Za-z_]+)\)', ReplaceVariable, 5801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org grd_filename) 5901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if new_grd_filename != grd_filename: 606740fffb81bff917e8f43523e922baaed7929824joi@chromium.org abs_grd_filename = os.path.abspath(new_grd_filename) 616740fffb81bff917e8f43523e922baaed7929824joi@chromium.org if abs_grd_filename[:len(src_root_dir)] != src_root_dir: 626740fffb81bff917e8f43523e922baaed7929824joi@chromium.org new_grd_filename = os.path.basename(abs_grd_filename) 636740fffb81bff917e8f43523e922baaed7929824joi@chromium.org else: 646740fffb81bff917e8f43523e922baaed7929824joi@chromium.org new_grd_filename = abs_grd_filename[len(src_root_dir) + 1:] 656740fffb81bff917e8f43523e922baaed7929824joi@chromium.org new_grd_filename = new_grd_filename.replace('\\', '/') 6601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org renames.append((grd_filename, new_grd_filename)) 6701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 6801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for grd_filename, new_grd_filename in renames: 6901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org first_ids_dict[new_grd_filename] = first_ids_dict[grd_filename] 7001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org del(first_ids_dict[grd_filename]) 7101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 7201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return (src_root_dir, first_ids_dict) 7301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 7401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 7583717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.orgclass SplicingNode(base.Node): 7683717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org """A node whose children should be considered to be at the same level as 7783717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org its siblings for most purposes. This includes <if> and <part> nodes. 78eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 7901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 8001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def _IsValidChild(self, child): 8183717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org assert self.parent, '<%s> node should never be root.' % self.name 8283717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org if isinstance(child, SplicingNode): 8383717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org return True # avoid O(n^2) behavior 8483717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org return self.parent._IsValidChild(child) 8583717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org 8683717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org 8783717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.orgclass IfNode(SplicingNode): 8883717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org """A node for conditional inclusion of resources. 8983717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org """ 9001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 9101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def MandatoryAttributes(self): 9201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return ['expr'] 9301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 940b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org def _IsValidChild(self, child): 950b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org return (isinstance(child, (ThenNode, ElseNode)) or 960b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org super(IfNode, self)._IsValidChild(child)) 970b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org 980b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org def EndParsing(self): 990b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org children = self.children 1000b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org self.if_then_else = False 1010b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org if any(isinstance(node, (ThenNode, ElseNode)) for node in children): 1020b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org if (len(children) != 2 or not isinstance(children[0], ThenNode) or 1030b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org not isinstance(children[1], ElseNode)): 1040b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org raise exception.UnexpectedChild( 1050b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org '<if> element must be <if><then>...</then><else>...</else></if>') 1060b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org self.if_then_else = True 1070b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org 108ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org def ActiveChildren(self): 1090b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org cond = self.EvaluateCondition(self.attrs['expr']) 1100b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org if self.if_then_else: 1110b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org return self.children[0 if cond else 1].ActiveChildren() 1120b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org else: 1130b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org # Equivalent to having all children inside <then> with an empty <else> 1140b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org return super(IfNode, self).ActiveChildren() if cond else [] 1150b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org 1160b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org 1170b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.orgclass ThenNode(SplicingNode): 1180b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org """A <then> node. Can only appear directly inside an <if> node.""" 1190b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org pass 1200b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org 1210b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org 1220b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.orgclass ElseNode(SplicingNode): 1230b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org """An <else> node. Can only appear directly inside an <if> node.""" 1240b961d0af2fe00a650a882b13752e46c8aef3710benrg@chromium.org pass 12577cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 12601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 12783717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.orgclass PartNode(SplicingNode): 12883717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org """A node for inclusion of sub-grd (*.grp) files. 12983717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org """ 13083717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org 13183717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org def __init__(self): 13283717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org super(PartNode, self).__init__() 13383717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org self.started_inclusion = False 13483717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org 13583717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org def MandatoryAttributes(self): 13683717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org return ['file'] 13783717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org 13883717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org def _IsValidChild(self, child): 13983717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org return self.started_inclusion and super(PartNode, self)._IsValidChild(child) 14083717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org 14183717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org 14201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass ReleaseNode(base.Node): 143eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """The <release> element.""" 14401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 14501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def _IsValidChild(self, child): 14601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org from grit.node import empty 14701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return isinstance(child, (empty.IncludesNode, empty.MessagesNode, 14801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org empty.StructuresNode, empty.IdentifiersNode)) 14901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 15001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def _IsValidAttribute(self, name, value): 15101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return ( 15201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org (name == 'seq' and int(value) <= self.GetRoot().GetCurrentRelease()) or 15301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org name == 'allow_pseudo' 15401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ) 15501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 15601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def MandatoryAttributes(self): 15701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return ['seq'] 15801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 15901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def DefaultAttributes(self): 16001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return { 'allow_pseudo' : 'true' } 16101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 16201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetReleaseNumber(): 163eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the sequence number of this release.""" 16401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.attribs['seq'] 16501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 16601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass GritNode(base.Node): 167eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """The <grit> root element.""" 16801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 16901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def __init__(self): 170b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org super(GritNode, self).__init__() 17101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.output_language = '' 17201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.defines = {} 173783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org self.substituter = None 174abf28c9e0d607e293a9d790300090e557be6b41ejoi@chromium.org self.target_platform = sys.platform 17501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 17601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def _IsValidChild(self, child): 17701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org from grit.node import empty 17801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return isinstance(child, (ReleaseNode, empty.TranslationsNode, 17901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org empty.OutputsNode)) 18001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 18101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def _IsValidAttribute(self, name, value): 1820dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org if name not in ['base_dir', 'first_ids_file', 'source_lang_id', 18301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'latest_public_release', 'current_release', 184bd79a1642abbe801db78778a59cdafc10e70bcccjoi@chromium.org 'enc_check', 'tc_project', 'grit_version', 185db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org 'output_all_resource_defines', 'rc_header_format']: 18601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return False 18701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if name in ['latest_public_release', 'current_release'] and value.strip( 18801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '0123456789') != '': 18901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return False 19001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return True 19101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 19201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def MandatoryAttributes(self): 19301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return ['latest_public_release', 'current_release'] 19401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 19501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def DefaultAttributes(self): 19601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return { 19701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'base_dir' : '.', 1980dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org 'first_ids_file': '', 19977cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'grit_version': 1, 20001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'source_lang_id' : 'en', 20101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'enc_check' : constants.ENCODING_CHECK, 20201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'tc_project' : 'NEED_TO_SET_tc_project_ATTRIBUTE', 203db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org 'output_all_resource_defines': 'true', 204db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org 'rc_header_format': None 20501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org } 20601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 20701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def EndParsing(self): 208b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org super(GritNode, self).EndParsing() 20901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (int(self.attrs['latest_public_release']) 21001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org > int(self.attrs['current_release'])): 21101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org raise exception.Parsing('latest_public_release cannot have a greater ' 21201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'value than current_release') 21301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 21401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.ValidateUniqueIds() 21501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 21601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Add the encoding check if it's not present (should ensure that it's always 21701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # present in all .grd files generated by GRIT). If it's present, assert if 21801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # it's not correct. 21901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if 'enc_check' not in self.attrs or self.attrs['enc_check'] == '': 22001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.attrs['enc_check'] = constants.ENCODING_CHECK 22101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 22201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assert self.attrs['enc_check'] == constants.ENCODING_CHECK, ( 22301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'Are you sure your .grd file is in the correct encoding (UTF-8)?') 22401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 22501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def ValidateUniqueIds(self): 226eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Validate that 'name' attribute is unique in all nodes in this tree 22701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org except for nodes that are children of <if> nodes. 228eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 22901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org unique_names = {} 23001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org duplicate_names = [] 231ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org # To avoid false positives from mutually exclusive <if> clauses, check 232ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org # against whatever the output condition happens to be right now. 233ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org # TODO(benrg): do something better. 234ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org for node in self.ActiveDescendants(): 235cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org if node.attrs.get('generateid', 'true') == 'false': 236cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org continue # Duplication not relevant in that case 237ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org 238ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org for node_id in node.GetTextualIds(): 239ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org if util.SYSTEM_IDENTIFIERS.match(node_id): 240ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org continue # predefined IDs are sometimes used more than once 241ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org 242ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org if node_id in unique_names and node_id not in duplicate_names: 243ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org duplicate_names.append(node_id) 244ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org unique_names[node_id] = 1 24501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 24601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if len(duplicate_names): 24701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org raise exception.DuplicateKey(', '.join(duplicate_names)) 24801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 24901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 25001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetCurrentRelease(self): 251eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the current release number.""" 25201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return int(self.attrs['current_release']) 25301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 25401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetLatestPublicRelease(self): 255eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the latest public release number.""" 25601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return int(self.attrs['latest_public_release']) 25701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 25801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetSourceLanguage(self): 259eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the language code of the source language.""" 26001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.attrs['source_lang_id'] 26101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 26201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetTcProject(self): 263eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the name of this project in the TranslationConsole, or 264eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org 'NEED_TO_SET_tc_project_ATTRIBUTE' if it is not defined.""" 26501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.attrs['tc_project'] 26601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 26701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def SetOwnDir(self, dir): 268eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Informs the 'grit' element of the directory the file it is in resides. 26901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org This allows it to calculate relative paths from the input file, which is 27001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org what we desire (rather than from the current path). 27101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 27201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Args: 27301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org dir: r'c:\bla' 27401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 27501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Return: 27601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org None 277eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 27801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assert dir 27901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.base_dir = os.path.normpath(os.path.join(dir, self.attrs['base_dir'])) 28001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 28101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetBaseDir(self): 282eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the base directory, relative to the working directory. To get 28301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org the base directory as set in the .grd file, use GetOriginalBaseDir() 284eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 28501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if hasattr(self, 'base_dir'): 28601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.base_dir 28701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 28801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.GetOriginalBaseDir() 28901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 29001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetOriginalBaseDir(self): 291eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the base directory, as set in the .grd file. 292eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 29301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.attrs['base_dir'] 29401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 295bd79a1642abbe801db78778a59cdafc10e70bcccjoi@chromium.org def ShouldOutputAllResourceDefines(self): 296bd79a1642abbe801db78778a59cdafc10e70bcccjoi@chromium.org """Returns true if all resource defines should be output, false if 297bd79a1642abbe801db78778a59cdafc10e70bcccjoi@chromium.org defines for resources not emitted to resource files should be 298bd79a1642abbe801db78778a59cdafc10e70bcccjoi@chromium.org skipped. 299bd79a1642abbe801db78778a59cdafc10e70bcccjoi@chromium.org """ 300bd79a1642abbe801db78778a59cdafc10e70bcccjoi@chromium.org return self.attrs['output_all_resource_defines'] == 'true' 301bd79a1642abbe801db78778a59cdafc10e70bcccjoi@chromium.org 302db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org def GetRcHeaderFormat(self): 303db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org return self.attrs['rc_header_format'] 304db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org 305db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org def AssignRcHeaderFormat(self, rc_header_format): 306db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org self.attrs['rc_header_format'] = rc_header_format 307db2e077842c311c22eb33a13cc9eb9fadb7def5ajoi@chromium.org 308eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org def GetInputFiles(self): 309eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the list of files that are read to produce the output.""" 310eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org 311eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org # Importing this here avoids a circular dependency in the imports. 312eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org # pylint: disable-msg=C6204 313eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org from grit.node import include 31483717e82a9b5e0c629ff4f1078d50503ffd2ae75benrg@chromium.org from grit.node import misc 315eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org from grit.node import structure 316eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org from grit.node import variant 317eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org 318ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org # Check if the input is required for any output configuration. 319ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org input_files = set() 320c5a84104bae5837c1be2e879b343af5140baea35benrg@chromium.org old_output_language = self.output_language 321ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org for lang, ctx in self.GetConfigurations(): 322ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org self.SetOutputLanguage(lang or self.GetSourceLanguage()) 323ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org self.SetOutputContext(ctx) 324ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org for node in self.ActiveDescendants(): 325ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org if isinstance(node, (io.FileNode, include.IncludeNode, misc.PartNode, 326ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org structure.StructureNode, variant.SkeletonNode)): 327ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org input_files.add(node.GetInputPath()) 328c5a84104bae5837c1be2e879b343af5140baea35benrg@chromium.org self.SetOutputLanguage(old_output_language) 329ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org return sorted(map(self.ToRealPath, input_files)) 330eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org 3310dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org def GetFirstIdsFile(self): 332eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns a usable path to the first_ids file, if set, otherwise 3330dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org returns None. 3340dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org 3350dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org The first_ids_file attribute is by default relative to the 3360dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org base_dir of the .grd file, but may be prefixed by GRIT_DIR/, 3370dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org which makes it relative to the directory of grit.py 3380dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org (e.g. GRIT_DIR/../gritsettings/resource_ids). 339eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 3400dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org if not self.attrs['first_ids_file']: 3410dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org return None 3420dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org 3430dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org path = self.attrs['first_ids_file'] 3445a132756a9c06c4242c1b2a678435fc618a92dcbsergeyu@chromium.org GRIT_DIR_PREFIX = 'GRIT_DIR' 3455a132756a9c06c4242c1b2a678435fc618a92dcbsergeyu@chromium.org if (path.startswith(GRIT_DIR_PREFIX) 3465a132756a9c06c4242c1b2a678435fc618a92dcbsergeyu@chromium.org and path[len(GRIT_DIR_PREFIX)] in ['/', '\\']): 3475a132756a9c06c4242c1b2a678435fc618a92dcbsergeyu@chromium.org return util.PathFromRoot(path[len(GRIT_DIR_PREFIX) + 1:]) 3480dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org else: 3490dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org return self.ToRealPath(path) 3500dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org 35101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetOutputFiles(self): 352eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the list of <output> nodes that are descendants of this node's 35301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org <outputs> child and are not enclosed by unsatisfied <if> conditionals. 354eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 35501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for child in self.children: 35601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if child.name == 'outputs': 357ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org return [node for node in child.ActiveDescendants() 358ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org if node.name == 'output'] 35901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org raise exception.MissingElement() 36001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 361ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org def GetConfigurations(self): 362ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org """Returns the distinct (language, context) pairs from the output nodes. 363ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org """ 364ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org return set((n.GetLanguage(), n.GetContext()) for n in self.GetOutputFiles()) 365ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org 36677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org def GetSubstitutionMessages(self): 367eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the list of <message sub_variable="true"> nodes.""" 368ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org return [n for n in self.ActiveDescendants() 369ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org if isinstance(n, message.MessageNode) 370ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org and n.attrs['sub_variable'] == 'true'] 37101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 372783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org def SetOutputLanguage(self, output_language): 373ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org """Set the output language. Prepares substitutions. 37477cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 375ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org The substitutions are reset every time the language is changed. 37677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org They include messages designated as variables, and language codes for html 37777cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org and rc files. 37877cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 37977cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org Args: 380cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org output_language: a two-letter language code (eg: 'en', 'ar'...) or '' 381eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 382783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org if not output_language: 383783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org # We do not specify the output language for .grh files, 384783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org # so we get an empty string as the default. 385783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org # The value should match grit.clique.MessageClique.source_language. 386783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org output_language = self.GetSourceLanguage() 387783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org if output_language != self.output_language: 388783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org self.output_language = output_language 389783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org self.substituter = None # force recalculate 390ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org 391ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org def SetOutputContext(self, output_context): 392ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org self.output_context = output_context 393ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org self.substituter = None # force recalculate 39401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 39501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def SetDefines(self, defines): 39601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.defines = defines 397783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org self.substituter = None # force recalculate 398783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org 399abf28c9e0d607e293a9d790300090e557be6b41ejoi@chromium.org def SetTargetPlatform(self, target_platform): 400abf28c9e0d607e293a9d790300090e557be6b41ejoi@chromium.org self.target_platform = target_platform 401abf28c9e0d607e293a9d790300090e557be6b41ejoi@chromium.org 402783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org def GetSubstituter(self): 403783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org if self.substituter is None: 404783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org self.substituter = util.Substituter() 405783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org self.substituter.AddMessages(self.GetSubstitutionMessages(), 406783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org self.output_language) 407783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org if self.output_language in _RTL_LANGS: 408783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org direction = 'dir="RTL"' 409783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org else: 410783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org direction = 'dir="LTR"' 411783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org self.substituter.AddSubstitutions({ 412783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org 'GRITLANGCODE': self.output_language, 413783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org 'GRITDIR': direction, 414783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org }) 415783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org from grit.format import rc # avoid circular dep 416783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org rc.RcSubstitutions(self.substituter, self.output_language) 417783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org return self.substituter 41801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 4190dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org def AssignFirstIds(self, filename_or_stream, defines): 420eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Assign first ids to each grouping node based on values from the 4210dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org first_ids file (if specified on the <grit> node). 422eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 42301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # If the input is a stream, then we're probably in a unit test and 42401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # should skip this step. 42501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if type(filename_or_stream) not in (str, unicode): 42601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return 42701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 4280dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org # Nothing to do if the first_ids_filename attribute isn't set. 4290dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org first_ids_filename = self.GetFirstIdsFile() 4300dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org if not first_ids_filename: 4310dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org return 4320dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org 4330dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org src_root_dir, first_ids = _ReadFirstIdsFromFile(first_ids_filename, 4340dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org defines) 43501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org from grit.node import empty 436ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org for node in self.Preorder(): 43701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if isinstance(node, empty.GroupingNode): 438625ae8faf7992cf919dfc6323d18dc4b6aed04fdjochen@chromium.org abs_filename = os.path.abspath(filename_or_stream) 439625ae8faf7992cf919dfc6323d18dc4b6aed04fdjochen@chromium.org if abs_filename[:len(src_root_dir)] != src_root_dir: 440625ae8faf7992cf919dfc6323d18dc4b6aed04fdjochen@chromium.org filename = os.path.basename(filename_or_stream) 441625ae8faf7992cf919dfc6323d18dc4b6aed04fdjochen@chromium.org else: 442625ae8faf7992cf919dfc6323d18dc4b6aed04fdjochen@chromium.org filename = abs_filename[len(src_root_dir) + 1:] 443625ae8faf7992cf919dfc6323d18dc4b6aed04fdjochen@chromium.org filename = filename.replace('\\', '/') 44401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 44501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if node.attrs['first_id'] != '': 4460dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org raise Exception( 4470dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org "Don't set the first_id attribute when using the first_ids_file " 4480dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org "attribute on the <grit> node, update %s instead." % 4490dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org first_ids_filename) 45001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 45101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org try: 45201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org id_list = first_ids[filename][node.name] 45301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org except KeyError, e: 45401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org print '-' * 78 45501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org print 'Resource id not set for %s (%s)!' % (filename, node.name) 45601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org print ('Please update %s to include an entry for %s. See the ' 4570dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org 'comments in resource_ids for information on why you need to ' 4580dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org 'update that file.' % (first_ids_filename, filename)) 45901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org print '-' * 78 46001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org raise e 46101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 46201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org try: 46301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.attrs['first_id'] = str(id_list.pop(0)) 46401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org except IndexError, e: 46501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org raise Exception('Please update %s and add a first id for %s (%s).' 4660dc1eef9854b5a4102aee7b7acae978eec2e4df9joi@chromium.org % (first_ids_filename, filename, node.name)) 46701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 468ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org def RunGatherers(self, debug=False): 469ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org '''Call RunPreSubstitutionGatherer() on every node of the tree, then apply 470ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org substitutions, then call RunPostSubstitutionGatherer() on every node. 47177cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 472ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org The substitutions step requires that the output language has been set. 473ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org Locally, get the Substitution messages and add them to the substituter. 474ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org Also add substitutions for language codes in the Rc. 4751eddb32f808ac5930f24b1954b5c949b273a3869joi@chromium.org 47677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org Args: 47777cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org debug: will print information while running gatherers. 478ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org ''' 479ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org for node in self.ActiveDescendants(): 480ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org if hasattr(node, 'RunPreSubstitutionGatherer'): 481ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org with node: 482ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org node.RunPreSubstitutionGatherer(debug=debug) 4831eddb32f808ac5930f24b1954b5c949b273a3869joi@chromium.org 484ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org assert self.output_language 485ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org self.SubstituteMessages(self.GetSubstituter()) 4861eddb32f808ac5930f24b1954b5c949b273a3869joi@chromium.org 487ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org for node in self.ActiveDescendants(): 488ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org if hasattr(node, 'RunPostSubstitutionGatherer'): 489ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org with node: 490ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org node.RunPostSubstitutionGatherer(debug=debug) 49177cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 49201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 49301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass IdentifierNode(base.Node): 494eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """A node for specifying identifiers that should appear in the resource 49501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org header file, and be unique amongst all other resource identifiers, but don't 49601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org have any other attributes or reference any resources. 497eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 49801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 49901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def MandatoryAttributes(self): 50001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return ['name'] 50101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 50201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def DefaultAttributes(self): 503cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org return { 'comment' : '', 'id' : '', 'systemid': 'false' } 50401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 50501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetId(self): 506eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Returns the id of this identifier if it has one, None otherwise 507eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 50801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if 'id' in self.attrs: 50901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.attrs['id'] 51001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return None 51101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 512cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org def EndParsing(self): 513eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Handles system identifiers.""" 514b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org super(IdentifierNode, self).EndParsing() 515cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org if self.attrs['systemid'] == 'true': 516cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org util.SetupSystemIdentifiers((self.attrs['name'],)) 517cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org 518cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org @staticmethod 519cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org def Construct(parent, name, id, comment, systemid='false'): 520eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """Creates a new node which is a child of 'parent', with attributes set 52101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org by parameters of the same name. 522eda8d69f7c49419eef6e96a1cd42af26a864d794joi@chromium.org """ 52301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node = IdentifierNode() 52401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.StartParsing('identifier', parent) 52501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.HandleAttribute('name', name) 52601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.HandleAttribute('id', id) 52701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.HandleAttribute('comment', comment) 528cb59a41015e4a21a5bd865f5646e19d99a3d03aajoi@chromium.org node.HandleAttribute('systemid', systemid) 52901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.EndParsing() 53001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return node 531