OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Formats as a .C file for compilation. | |
7 """ | |
8 | |
9 import os | |
10 import re | |
11 import types | |
12 | |
13 from grit import util | |
14 | |
15 | |
16 def _FormatHeader(root, output_dir): | |
17 """Returns the required preamble for C files.""" | |
18 # Find the location of the resource header file, so that we can include | |
19 # it. | |
20 resource_header = 'resource.h' # fall back to this | |
21 for output in root.GetOutputFiles(): | |
22 if output.attrs['type'] == 'rc_header': | |
23 resource_header = os.path.abspath(output.GetOutputFilename()) | |
24 resource_header = util.MakeRelativePath(output_dir, resource_header) | |
25 return """// This file is automatically generated by GRIT. Do not edit. | |
26 | |
27 #include "%s" | |
28 | |
29 // All strings are UTF-8 | |
30 """ % (resource_header) | |
31 # end _FormatHeader() function | |
32 | |
33 | |
34 def Format(root, lang='en', output_dir='.'): | |
35 """Outputs a C switch statement representing the string table.""" | |
36 from grit.node import message | |
37 assert isinstance(lang, types.StringTypes) | |
38 | |
39 yield _FormatHeader(root, output_dir) | |
40 | |
41 yield 'const char* GetString(int id) {\n switch (id) {' | |
42 | |
43 for item in root.ActiveDescendants(): | |
44 with item: | |
45 if isinstance(item, message.MessageNode): | |
46 yield _FormatMessage(item, lang) | |
47 | |
48 yield '\n default:\n return 0;\n }\n}' | |
49 | |
50 | |
51 def _HexToOct(match): | |
52 "Return the octal form of the hex numbers" | |
53 hex = match.group("hex") | |
54 result = "" | |
55 while len(hex): | |
56 next_num = int(hex[2:4], 16) | |
57 result += "\\" + '%03d' % int(oct(next_num), 10) | |
58 hex = hex[4:] | |
59 return match.group("escaped_backslashes") + result | |
60 | |
61 | |
62 def _FormatMessage(item, lang): | |
63 """Format a single <message> element.""" | |
64 | |
65 message = item.ws_at_start + item.Translate(lang) + item.ws_at_end | |
66 # output message with non-ascii chars escaped as octal numbers | |
67 # C's grammar allows escaped hexadecimal numbers to be infinite, | |
68 # but octal is always of the form \OOO | |
69 message = message.encode('utf-8').encode('string_escape') | |
70 # an escaped char is (\xHH)+ but only if the initial | |
71 # backslash is not escaped. | |
72 not_a_backslash = r"(^|[^\\])" # beginning of line or a non-backslash char | |
73 escaped_backslashes = not_a_backslash + r"(\\\\)*" | |
74 hex_digits = r"((\\x)[0-9a-f]{2})+" | |
75 two_digit_hex_num = re.compile( | |
76 r"(?P<escaped_backslashes>%s)(?P<hex>%s)" | |
77 % (escaped_backslashes, hex_digits)) | |
78 message = two_digit_hex_num.sub(_HexToOct, message) | |
79 # unescape \ (convert \\ back to \) | |
80 message = message.replace('\\\\', '\\') | |
81 message = message.replace('"', '\\"') | |
82 message = util.LINEBREAKS.sub(r'\\n', message) | |
83 | |
84 name_attr = item.GetTextualIds()[0] | |
85 | |
86 return '\n case %s:\n return "%s";' % (name_attr, message) | |
OLD | NEW |