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