Chromium Code Reviews| Index: tools/grit/grit/format/gen_predetermined_ids.py |
| diff --git a/tools/grit/grit/format/gen_predetermined_ids.py b/tools/grit/grit/format/gen_predetermined_ids.py |
| new file mode 100755 |
| index 0000000000000000000000000000000000000000..9de019b95572bc8973f167e6f68464ada34a1cf2 |
| --- /dev/null |
| +++ b/tools/grit/grit/format/gen_predetermined_ids.py |
| @@ -0,0 +1,153 @@ |
| +#!/usr/bin/env python |
| +# Copyright 2017 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +""" |
| +A tool to generate a predetermined resource ids file that can be used as an |
| +input to grit via the -p option. See tools/gritsettings/README.md for details. |
|
Nico
2017/02/17 21:49:28
Maybe mention that the idea is to run this manuall
Alexei Svitkine (slow)
2017/02/17 21:56:55
Done.
|
| +""" |
| + |
| +import fnmatch |
| +import os |
| +import re |
| +import sys |
| + |
| +# Regular expressions for parsing the #define macro format. Separate regular |
| +# expressions are used for parsing lines with pragma (for builds with |
| +# enable_resource_whitelist_generation flag) in windows and non-windows, and for |
| +# lines without pragma, For example, |
| +# Without generate whitelist flag: |
| +# #define IDS_FOO_MESSAGE 1234 |
| +# With generate whitelist flag in non-windows: |
| +# #define IDS_FOO_MESSAGE _Pragma("whitelisted_resource_1234") 1234 |
| +# With generate whitelist flag in windows: |
| +# #define IDS_FOO_MESSAGE __pragma(message("whitelisted_resource_1234")) 1234 |
| +RESOURCE_EXTRACT_REGEX = re.compile('^#define (\S*) (\d*)$', re.MULTILINE) |
| +RESOURCE_EXTRACT_REGEX_PRAGMA = re.compile( |
| + '^#define (\S*) _Pragma\("whitelisted_resource_\d*"\) (\d*)$', |
| + re.MULTILINE) |
| +RESOURCE_EXTRACT_REGEX_PRAGMA_WINDOWS = re.compile( |
| + '^#define (\S*) __pragma\(message\("whitelisted_resource_\d*"\)\) (\d*)$', |
| + re.MULTILINE) |
| + |
| +ORDERED_RESOURCE_IDS_REGEX = re.compile('^Resource=(\d*)$', re.MULTILINE) |
| + |
| + |
| +def _GetResourceNameIdPairsIter(string_to_scan): |
| + """Gets an iterator of the resource name and id pairs of the given string. |
| + |
| + Scans the input string for lines of the form "#define NAME ID" and returns |
| + an iterator over all matching (NAME, ID) pairs. |
| + |
| + Args: |
| + string_to_scan: The input string to scan. |
| + |
| + Yields: |
| + A tuple of name and id. |
| + """ |
| + for match in RESOURCE_EXTRACT_REGEX.finditer(string_to_scan): |
| + yield match.group(1, 2) |
| + for match in RESOURCE_EXTRACT_REGEX_PRAGMA.finditer(string_to_scan): |
| + yield match.group(1, 2) |
| + for match in RESOURCE_EXTRACT_REGEX_PRAGMA_WINDOWS.finditer(string_to_scan): |
| + yield match.group(1, 2) |
| + |
|
Nico
2017/02/17 21:49:28
2 empty lines between toplevel things again
Alexei Svitkine (slow)
2017/02/17 21:56:55
Done.
|
| +def _ReadOrderedResourceIds(path): |
| + """Reads ordered resource ids from the given file. |
| + |
| + The resources are expected to be of the format produced by running Chrome |
| + with --print-resource-ids command line. |
| + |
| + Args: |
| + path: File path to read resource ids from. |
| + |
| + Returns: |
| + An array of ordered resource ids. |
| + """ |
| + ordered_resource_ids = [] |
| + with open(path, "r") as f: |
| + for match in ORDERED_RESOURCE_IDS_REGEX.finditer(f.read()): |
| + ordered_resource_ids.append(int(match.group(1))) |
| + return ordered_resource_ids |
| + |
| +def GenerateResourceMapping(original_resources, ordered_resource_ids): |
| + """Generates a resource mapping from the ordered ids and the original mapping. |
| + |
| + The returned dict will assign new ids to ordered_resource_ids numerically |
| + increasing from 101. |
| + |
| + Args: |
| + original_resources: A dict of original resource ids to resource names. |
| + ordered_resource_ids: An array of ordered resource ids. |
| + |
| + Returns: |
| + A dict of resource ids to resource names. |
| + """ |
| + output_resource_map = {} |
| + # 101 is used as the starting value since other parts of GRIT require it to be |
| + # the minimum (e.g. rc_header.py) based on Windows resource numbering. |
| + next_id = 101 |
| + for original_id in ordered_resource_ids: |
| + resource_name = original_resources[original_id] |
| + output_resource_map[next_id] = resource_name |
| + next_id += 1 |
| + return output_resource_map |
| + |
| +def ReadResourceIdsFromFile(file, original_resources): |
| + """Reads resource ids from a GRIT-produced header file. |
| + |
| + Args: |
| + file: File to a GRIT-produced header file to read from. |
| + original_resources: Dict of resource ids to resource names to add to. |
| + """ |
| + for resource_name, resource_id in _GetResourceNameIdPairsIter(file.read()): |
| + original_resources[int(resource_id)] = resource_name |
| + |
| +def _ReadOriginalResourceIds(out_dir): |
| + """Reads resource ids from GRIT header files in the specified directory. |
| + |
| + Args: |
| + out_dir: A Chrome build output directory (e.g. out/gn) to scan. |
| + |
| + Returns: |
| + A dict of resource ids to resource names. |
| + """ |
| + original_resources = {} |
| + for root, dirnames, filenames in os.walk(out_dir + '/gen'): |
| + for filename in filenames: |
| + if filename.endswith(('_resources.h', '_settings.h', '_strings.h')): |
| + with open(os.path.join(root, filename), "r") as f: |
| + ReadResourceIdsFromFile(f, original_resources) |
| + return original_resources |
| + |
| +def _GeneratePredeterminedIdsFile(ordered_resources_file, out_dir): |
| + """Generates a predetermined ids file. |
| + |
| + Args: |
| + ordered_resources_file: File path to read ordered resource ids from. |
| + out_dir: A Chrome build output directory (e.g. out/gn) to scan. |
| + |
| + Returns: |
| + A dict of resource ids to resource names. |
| + """ |
| + original_resources = _ReadOriginalResourceIds(out_dir) |
| + ordered_resource_ids = _ReadOrderedResourceIds(ordered_resources_file) |
| + output_resource_map = GenerateResourceMapping(original_resources, |
| + ordered_resource_ids) |
| + for res_id in sorted(output_resource_map.keys()): |
| + print "{} {}".format(output_resource_map[res_id], res_id) |
| + |
| + |
| +def main(argv): |
| + if len(argv) != 2: |
| + print("usage: gen_predetermined_ids.py <ordered_resources_file> <out_dir>") |
| + sys.exit(1) |
| + ordered_resources_file, out_dir = argv[0], argv[1] |
| + _GeneratePredeterminedIdsFile(ordered_resources_file, out_dir) |
| + |
| + |
| +if '__main__' == __name__: |
| + main(sys.argv[1:]) |
| + |
| + |
|
Nico
2017/02/17 21:49:28
nit: no trailing empty lines
Alexei Svitkine (slow)
2017/02/17 21:56:55
Done.
|