redsnow 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +34 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +20 -0
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +21 -0
  8. data/README.md +62 -0
  9. data/Rakefile +36 -0
  10. data/Vagrantfile +20 -0
  11. data/ext/snowcrash/Makefile +64 -0
  12. data/ext/snowcrash/Vagrantfile +20 -0
  13. data/ext/snowcrash/bin/snowcrash +0 -0
  14. data/ext/snowcrash/common.gypi +163 -0
  15. data/ext/snowcrash/config.gypi +10 -0
  16. data/ext/snowcrash/config.mk +5 -0
  17. data/ext/snowcrash/configure +213 -0
  18. data/ext/snowcrash/provisioning.sh +15 -0
  19. data/ext/snowcrash/snowcrash.gyp +141 -0
  20. data/ext/snowcrash/src/ActionParser.h +503 -0
  21. data/ext/snowcrash/src/AssetParser.h +215 -0
  22. data/ext/snowcrash/src/BlockUtility.h +186 -0
  23. data/ext/snowcrash/src/Blueprint.h +283 -0
  24. data/ext/snowcrash/src/BlueprintParser.h +347 -0
  25. data/ext/snowcrash/src/BlueprintParserCore.h +190 -0
  26. data/ext/snowcrash/src/BlueprintSection.h +140 -0
  27. data/ext/snowcrash/src/BlueprintUtility.h +126 -0
  28. data/ext/snowcrash/src/CBlueprint.cc +600 -0
  29. data/ext/snowcrash/src/CBlueprint.h +354 -0
  30. data/ext/snowcrash/src/CSourceAnnotation.cc +140 -0
  31. data/ext/snowcrash/src/CSourceAnnotation.h +106 -0
  32. data/ext/snowcrash/src/CodeBlockUtility.h +189 -0
  33. data/ext/snowcrash/src/DescriptionSectionUtility.h +156 -0
  34. data/ext/snowcrash/src/HTTP.cc +46 -0
  35. data/ext/snowcrash/src/HTTP.h +105 -0
  36. data/ext/snowcrash/src/HeaderParser.h +289 -0
  37. data/ext/snowcrash/src/ListBlockUtility.h +273 -0
  38. data/ext/snowcrash/src/ListUtility.h +95 -0
  39. data/ext/snowcrash/src/MarkdownBlock.cc +176 -0
  40. data/ext/snowcrash/src/MarkdownBlock.h +93 -0
  41. data/ext/snowcrash/src/MarkdownParser.cc +266 -0
  42. data/ext/snowcrash/src/MarkdownParser.h +88 -0
  43. data/ext/snowcrash/src/ParameterDefinitonParser.h +570 -0
  44. data/ext/snowcrash/src/ParametersParser.h +252 -0
  45. data/ext/snowcrash/src/Parser.cc +71 -0
  46. data/ext/snowcrash/src/Parser.h +29 -0
  47. data/ext/snowcrash/src/ParserCore.cc +120 -0
  48. data/ext/snowcrash/src/ParserCore.h +82 -0
  49. data/ext/snowcrash/src/PayloadParser.h +672 -0
  50. data/ext/snowcrash/src/Platform.h +54 -0
  51. data/ext/snowcrash/src/RegexMatch.h +32 -0
  52. data/ext/snowcrash/src/ResourceGroupParser.h +195 -0
  53. data/ext/snowcrash/src/ResourceParser.h +584 -0
  54. data/ext/snowcrash/src/SectionUtility.h +142 -0
  55. data/ext/snowcrash/src/Serialize.cc +52 -0
  56. data/ext/snowcrash/src/Serialize.h +69 -0
  57. data/ext/snowcrash/src/SerializeJSON.cc +601 -0
  58. data/ext/snowcrash/src/SerializeJSON.h +21 -0
  59. data/ext/snowcrash/src/SerializeYAML.cc +336 -0
  60. data/ext/snowcrash/src/SerializeYAML.h +21 -0
  61. data/ext/snowcrash/src/SourceAnnotation.h +177 -0
  62. data/ext/snowcrash/src/StringUtility.h +109 -0
  63. data/ext/snowcrash/src/SymbolTable.h +83 -0
  64. data/ext/snowcrash/src/UriTemplateParser.cc +195 -0
  65. data/ext/snowcrash/src/UriTemplateParser.h +243 -0
  66. data/ext/snowcrash/src/Version.h +39 -0
  67. data/ext/snowcrash/src/csnowcrash.cc +23 -0
  68. data/ext/snowcrash/src/csnowcrash.h +38 -0
  69. data/ext/snowcrash/src/posix/RegexMatch.cc +99 -0
  70. data/ext/snowcrash/src/snowcrash.cc +18 -0
  71. data/ext/snowcrash/src/snowcrash.h +41 -0
  72. data/ext/snowcrash/src/snowcrash/snowcrash.cc +170 -0
  73. data/ext/snowcrash/src/win/RegexMatch.cc +78 -0
  74. data/ext/snowcrash/sundown/CONTRIBUTING.md +10 -0
  75. data/ext/snowcrash/sundown/Makefile +83 -0
  76. data/ext/snowcrash/sundown/Makefile.win +33 -0
  77. data/ext/snowcrash/sundown/examples/smartypants.c +72 -0
  78. data/ext/snowcrash/sundown/examples/sundown.c +80 -0
  79. data/ext/snowcrash/sundown/html/houdini.h +37 -0
  80. data/ext/snowcrash/sundown/html/houdini_href_e.c +108 -0
  81. data/ext/snowcrash/sundown/html/houdini_html_e.c +84 -0
  82. data/ext/snowcrash/sundown/html/html.c +647 -0
  83. data/ext/snowcrash/sundown/html/html.h +77 -0
  84. data/ext/snowcrash/sundown/html/html_smartypants.c +389 -0
  85. data/ext/snowcrash/sundown/html_block_names.txt +25 -0
  86. data/ext/snowcrash/sundown/src/autolink.c +297 -0
  87. data/ext/snowcrash/sundown/src/autolink.h +51 -0
  88. data/ext/snowcrash/sundown/src/buffer.c +225 -0
  89. data/ext/snowcrash/sundown/src/buffer.h +96 -0
  90. data/ext/snowcrash/sundown/src/html_blocks.h +206 -0
  91. data/ext/snowcrash/sundown/src/markdown.c +2701 -0
  92. data/ext/snowcrash/sundown/src/markdown.h +147 -0
  93. data/ext/snowcrash/sundown/src/src_map.c +200 -0
  94. data/ext/snowcrash/sundown/src/src_map.h +58 -0
  95. data/ext/snowcrash/sundown/src/stack.c +81 -0
  96. data/ext/snowcrash/sundown/src/stack.h +29 -0
  97. data/ext/snowcrash/sundown/sundown.def +20 -0
  98. data/ext/snowcrash/tools/gyp/AUTHORS +11 -0
  99. data/ext/snowcrash/tools/gyp/DEPS +24 -0
  100. data/ext/snowcrash/tools/gyp/OWNERS +1 -0
  101. data/ext/snowcrash/tools/gyp/PRESUBMIT.py +120 -0
  102. data/ext/snowcrash/tools/gyp/buildbot/buildbot_run.py +190 -0
  103. data/ext/snowcrash/tools/gyp/codereview.settings +10 -0
  104. data/ext/snowcrash/tools/gyp/data/win/large-pdb-shim.cc +12 -0
  105. data/ext/snowcrash/tools/gyp/gyp +8 -0
  106. data/ext/snowcrash/tools/gyp/gyp.bat +5 -0
  107. data/ext/snowcrash/tools/gyp/gyp_main.py +18 -0
  108. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSNew.py +340 -0
  109. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSProject.py +208 -0
  110. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSSettings.py +1063 -0
  111. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSToolFile.py +58 -0
  112. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUserFile.py +147 -0
  113. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUtil.py +267 -0
  114. data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSVersion.py +409 -0
  115. data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.py +537 -0
  116. data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
  117. data/ext/snowcrash/tools/gyp/pylib/gyp/common.py +521 -0
  118. data/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
  119. data/ext/snowcrash/tools/gyp/pylib/gyp/easy_xml.py +157 -0
  120. data/ext/snowcrash/tools/gyp/pylib/gyp/flock_tool.py +49 -0
  121. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.py +0 -0
  122. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
  123. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/android.py +1069 -0
  124. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/cmake.py +1143 -0
  125. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +81 -0
  126. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/eclipse.py +335 -0
  127. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypd.py +87 -0
  128. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypsh.py +56 -0
  129. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.py +2181 -0
  130. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
  131. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/msvs.py +3335 -0
  132. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/ninja.py +2156 -0
  133. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.py +1224 -0
  134. data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
  135. data/ext/snowcrash/tools/gyp/pylib/gyp/input.py +2809 -0
  136. data/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
  137. data/ext/snowcrash/tools/gyp/pylib/gyp/mac_tool.py +510 -0
  138. data/ext/snowcrash/tools/gyp/pylib/gyp/msvs_emulation.py +972 -0
  139. data/ext/snowcrash/tools/gyp/pylib/gyp/ninja_syntax.py +160 -0
  140. data/ext/snowcrash/tools/gyp/pylib/gyp/ordered_dict.py +289 -0
  141. data/ext/snowcrash/tools/gyp/pylib/gyp/win_tool.py +292 -0
  142. data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.py +1440 -0
  143. data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
  144. data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.py +2889 -0
  145. data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
  146. data/ext/snowcrash/tools/gyp/pylib/gyp/xml_fix.py +69 -0
  147. data/ext/snowcrash/tools/gyp/pylintrc +307 -0
  148. data/ext/snowcrash/tools/gyp/samples/samples +81 -0
  149. data/ext/snowcrash/tools/gyp/samples/samples.bat +5 -0
  150. data/ext/snowcrash/tools/gyp/setup.py +19 -0
  151. data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec +27 -0
  152. data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec +226 -0
  153. data/ext/snowcrash/tools/gyp/tools/emacs/gyp.el +252 -0
  154. data/ext/snowcrash/tools/gyp/tools/graphviz.py +100 -0
  155. data/ext/snowcrash/tools/gyp/tools/pretty_gyp.py +155 -0
  156. data/ext/snowcrash/tools/gyp/tools/pretty_sln.py +168 -0
  157. data/ext/snowcrash/tools/gyp/tools/pretty_vcproj.py +329 -0
  158. data/ext/snowcrash/tools/homebrew/snowcrash.rb +11 -0
  159. data/ext/snowcrash/vcbuild.bat +184 -0
  160. data/lib/redsnow.rb +31 -0
  161. data/lib/redsnow/binding.rb +132 -0
  162. data/lib/redsnow/blueprint.rb +365 -0
  163. data/lib/redsnow/object.rb +18 -0
  164. data/lib/redsnow/parseresult.rb +107 -0
  165. data/lib/redsnow/version.rb +4 -0
  166. data/provisioning.sh +20 -0
  167. data/redsnow.gemspec +35 -0
  168. data/test/_helper.rb +15 -0
  169. data/test/fixtures/sample-api-ast.json +97 -0
  170. data/test/fixtures/sample-api.apib +20 -0
  171. data/test/redsnow_binding_test.rb +35 -0
  172. data/test/redsnow_parseresult_test.rb +50 -0
  173. data/test/redsnow_test.rb +285 -0
  174. metadata +358 -0
@@ -0,0 +1,160 @@
1
+ # This file comes from
2
+ # https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py
3
+ # Do not edit! Edit the upstream one instead.
4
+
5
+ """Python module for generating .ninja files.
6
+
7
+ Note that this is emphatically not a required piece of Ninja; it's
8
+ just a helpful utility for build-file-generation systems that already
9
+ use Python.
10
+ """
11
+
12
+ import textwrap
13
+ import re
14
+
15
+ def escape_path(word):
16
+ return word.replace('$ ','$$ ').replace(' ','$ ').replace(':', '$:')
17
+
18
+ class Writer(object):
19
+ def __init__(self, output, width=78):
20
+ self.output = output
21
+ self.width = width
22
+
23
+ def newline(self):
24
+ self.output.write('\n')
25
+
26
+ def comment(self, text):
27
+ for line in textwrap.wrap(text, self.width - 2):
28
+ self.output.write('# ' + line + '\n')
29
+
30
+ def variable(self, key, value, indent=0):
31
+ if value is None:
32
+ return
33
+ if isinstance(value, list):
34
+ value = ' '.join(filter(None, value)) # Filter out empty strings.
35
+ self._line('%s = %s' % (key, value), indent)
36
+
37
+ def pool(self, name, depth):
38
+ self._line('pool %s' % name)
39
+ self.variable('depth', depth, indent=1)
40
+
41
+ def rule(self, name, command, description=None, depfile=None,
42
+ generator=False, pool=None, restat=False, rspfile=None,
43
+ rspfile_content=None, deps=None):
44
+ self._line('rule %s' % name)
45
+ self.variable('command', command, indent=1)
46
+ if description:
47
+ self.variable('description', description, indent=1)
48
+ if depfile:
49
+ self.variable('depfile', depfile, indent=1)
50
+ if generator:
51
+ self.variable('generator', '1', indent=1)
52
+ if pool:
53
+ self.variable('pool', pool, indent=1)
54
+ if restat:
55
+ self.variable('restat', '1', indent=1)
56
+ if rspfile:
57
+ self.variable('rspfile', rspfile, indent=1)
58
+ if rspfile_content:
59
+ self.variable('rspfile_content', rspfile_content, indent=1)
60
+ if deps:
61
+ self.variable('deps', deps, indent=1)
62
+
63
+ def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
64
+ variables=None):
65
+ outputs = self._as_list(outputs)
66
+ all_inputs = self._as_list(inputs)[:]
67
+ out_outputs = list(map(escape_path, outputs))
68
+ all_inputs = list(map(escape_path, all_inputs))
69
+
70
+ if implicit:
71
+ implicit = map(escape_path, self._as_list(implicit))
72
+ all_inputs.append('|')
73
+ all_inputs.extend(implicit)
74
+ if order_only:
75
+ order_only = map(escape_path, self._as_list(order_only))
76
+ all_inputs.append('||')
77
+ all_inputs.extend(order_only)
78
+
79
+ self._line('build %s: %s' % (' '.join(out_outputs),
80
+ ' '.join([rule] + all_inputs)))
81
+
82
+ if variables:
83
+ if isinstance(variables, dict):
84
+ iterator = iter(variables.items())
85
+ else:
86
+ iterator = iter(variables)
87
+
88
+ for key, val in iterator:
89
+ self.variable(key, val, indent=1)
90
+
91
+ return outputs
92
+
93
+ def include(self, path):
94
+ self._line('include %s' % path)
95
+
96
+ def subninja(self, path):
97
+ self._line('subninja %s' % path)
98
+
99
+ def default(self, paths):
100
+ self._line('default %s' % ' '.join(self._as_list(paths)))
101
+
102
+ def _count_dollars_before_index(self, s, i):
103
+ """Returns the number of '$' characters right in front of s[i]."""
104
+ dollar_count = 0
105
+ dollar_index = i - 1
106
+ while dollar_index > 0 and s[dollar_index] == '$':
107
+ dollar_count += 1
108
+ dollar_index -= 1
109
+ return dollar_count
110
+
111
+ def _line(self, text, indent=0):
112
+ """Write 'text' word-wrapped at self.width characters."""
113
+ leading_space = ' ' * indent
114
+ while len(leading_space) + len(text) > self.width:
115
+ # The text is too wide; wrap if possible.
116
+
117
+ # Find the rightmost space that would obey our width constraint and
118
+ # that's not an escaped space.
119
+ available_space = self.width - len(leading_space) - len(' $')
120
+ space = available_space
121
+ while True:
122
+ space = text.rfind(' ', 0, space)
123
+ if space < 0 or \
124
+ self._count_dollars_before_index(text, space) % 2 == 0:
125
+ break
126
+
127
+ if space < 0:
128
+ # No such space; just use the first unescaped space we can find.
129
+ space = available_space - 1
130
+ while True:
131
+ space = text.find(' ', space + 1)
132
+ if space < 0 or \
133
+ self._count_dollars_before_index(text, space) % 2 == 0:
134
+ break
135
+ if space < 0:
136
+ # Give up on breaking.
137
+ break
138
+
139
+ self.output.write(leading_space + text[0:space] + ' $\n')
140
+ text = text[space+1:]
141
+
142
+ # Subsequent lines are continuations, so indent them.
143
+ leading_space = ' ' * (indent+2)
144
+
145
+ self.output.write(leading_space + text + '\n')
146
+
147
+ def _as_list(self, input):
148
+ if input is None:
149
+ return []
150
+ if isinstance(input, list):
151
+ return input
152
+ return [input]
153
+
154
+
155
+ def escape(string):
156
+ """Escape a string such that it can be embedded into a Ninja file without
157
+ further interpretation."""
158
+ assert '\n' not in string, 'Ninja syntax does not allow newlines'
159
+ # We only have one special metacharacter: '$'.
160
+ return string.replace('$', '$$')
@@ -0,0 +1,289 @@
1
+ # Unmodified from http://code.activestate.com/recipes/576693/
2
+ # other than to add MIT license header (as specified on page, but not in code).
3
+ # Linked from Python documentation here:
4
+ # http://docs.python.org/2/library/collections.html#collections.OrderedDict
5
+ #
6
+ # This should be deleted once Py2.7 is available on all bots, see
7
+ # http://crbug.com/241769.
8
+ #
9
+ # Copyright (c) 2009 Raymond Hettinger.
10
+ #
11
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ # of this software and associated documentation files (the "Software"), to deal
13
+ # in the Software without restriction, including without limitation the rights
14
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ # copies of the Software, and to permit persons to whom the Software is
16
+ # furnished to do so, subject to the following conditions:
17
+ #
18
+ # The above copyright notice and this permission notice shall be included in
19
+ # all copies or substantial portions of the Software.
20
+ #
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
+ # THE SOFTWARE.
28
+
29
+ # Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
30
+ # Passes Python2.7's test suite and incorporates all the latest updates.
31
+
32
+ try:
33
+ from thread import get_ident as _get_ident
34
+ except ImportError:
35
+ from dummy_thread import get_ident as _get_ident
36
+
37
+ try:
38
+ from _abcoll import KeysView, ValuesView, ItemsView
39
+ except ImportError:
40
+ pass
41
+
42
+
43
+ class OrderedDict(dict):
44
+ 'Dictionary that remembers insertion order'
45
+ # An inherited dict maps keys to values.
46
+ # The inherited dict provides __getitem__, __len__, __contains__, and get.
47
+ # The remaining methods are order-aware.
48
+ # Big-O running times for all methods are the same as for regular dictionaries.
49
+
50
+ # The internal self.__map dictionary maps keys to links in a doubly linked list.
51
+ # The circular doubly linked list starts and ends with a sentinel element.
52
+ # The sentinel element never gets deleted (this simplifies the algorithm).
53
+ # Each link is stored as a list of length three: [PREV, NEXT, KEY].
54
+
55
+ def __init__(self, *args, **kwds):
56
+ '''Initialize an ordered dictionary. Signature is the same as for
57
+ regular dictionaries, but keyword arguments are not recommended
58
+ because their insertion order is arbitrary.
59
+
60
+ '''
61
+ if len(args) > 1:
62
+ raise TypeError('expected at most 1 arguments, got %d' % len(args))
63
+ try:
64
+ self.__root
65
+ except AttributeError:
66
+ self.__root = root = [] # sentinel node
67
+ root[:] = [root, root, None]
68
+ self.__map = {}
69
+ self.__update(*args, **kwds)
70
+
71
+ def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
72
+ 'od.__setitem__(i, y) <==> od[i]=y'
73
+ # Setting a new item creates a new link which goes at the end of the linked
74
+ # list, and the inherited dictionary is updated with the new key/value pair.
75
+ if key not in self:
76
+ root = self.__root
77
+ last = root[0]
78
+ last[1] = root[0] = self.__map[key] = [last, root, key]
79
+ dict_setitem(self, key, value)
80
+
81
+ def __delitem__(self, key, dict_delitem=dict.__delitem__):
82
+ 'od.__delitem__(y) <==> del od[y]'
83
+ # Deleting an existing item uses self.__map to find the link which is
84
+ # then removed by updating the links in the predecessor and successor nodes.
85
+ dict_delitem(self, key)
86
+ link_prev, link_next, key = self.__map.pop(key)
87
+ link_prev[1] = link_next
88
+ link_next[0] = link_prev
89
+
90
+ def __iter__(self):
91
+ 'od.__iter__() <==> iter(od)'
92
+ root = self.__root
93
+ curr = root[1]
94
+ while curr is not root:
95
+ yield curr[2]
96
+ curr = curr[1]
97
+
98
+ def __reversed__(self):
99
+ 'od.__reversed__() <==> reversed(od)'
100
+ root = self.__root
101
+ curr = root[0]
102
+ while curr is not root:
103
+ yield curr[2]
104
+ curr = curr[0]
105
+
106
+ def clear(self):
107
+ 'od.clear() -> None. Remove all items from od.'
108
+ try:
109
+ for node in self.__map.itervalues():
110
+ del node[:]
111
+ root = self.__root
112
+ root[:] = [root, root, None]
113
+ self.__map.clear()
114
+ except AttributeError:
115
+ pass
116
+ dict.clear(self)
117
+
118
+ def popitem(self, last=True):
119
+ '''od.popitem() -> (k, v), return and remove a (key, value) pair.
120
+ Pairs are returned in LIFO order if last is true or FIFO order if false.
121
+
122
+ '''
123
+ if not self:
124
+ raise KeyError('dictionary is empty')
125
+ root = self.__root
126
+ if last:
127
+ link = root[0]
128
+ link_prev = link[0]
129
+ link_prev[1] = root
130
+ root[0] = link_prev
131
+ else:
132
+ link = root[1]
133
+ link_next = link[1]
134
+ root[1] = link_next
135
+ link_next[0] = root
136
+ key = link[2]
137
+ del self.__map[key]
138
+ value = dict.pop(self, key)
139
+ return key, value
140
+
141
+ # -- the following methods do not depend on the internal structure --
142
+
143
+ def keys(self):
144
+ 'od.keys() -> list of keys in od'
145
+ return list(self)
146
+
147
+ def values(self):
148
+ 'od.values() -> list of values in od'
149
+ return [self[key] for key in self]
150
+
151
+ def items(self):
152
+ 'od.items() -> list of (key, value) pairs in od'
153
+ return [(key, self[key]) for key in self]
154
+
155
+ def iterkeys(self):
156
+ 'od.iterkeys() -> an iterator over the keys in od'
157
+ return iter(self)
158
+
159
+ def itervalues(self):
160
+ 'od.itervalues -> an iterator over the values in od'
161
+ for k in self:
162
+ yield self[k]
163
+
164
+ def iteritems(self):
165
+ 'od.iteritems -> an iterator over the (key, value) items in od'
166
+ for k in self:
167
+ yield (k, self[k])
168
+
169
+ # Suppress 'OrderedDict.update: Method has no argument':
170
+ # pylint: disable=E0211
171
+ def update(*args, **kwds):
172
+ '''od.update(E, **F) -> None. Update od from dict/iterable E and F.
173
+
174
+ If E is a dict instance, does: for k in E: od[k] = E[k]
175
+ If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
176
+ Or if E is an iterable of items, does: for k, v in E: od[k] = v
177
+ In either case, this is followed by: for k, v in F.items(): od[k] = v
178
+
179
+ '''
180
+ if len(args) > 2:
181
+ raise TypeError('update() takes at most 2 positional '
182
+ 'arguments (%d given)' % (len(args),))
183
+ elif not args:
184
+ raise TypeError('update() takes at least 1 argument (0 given)')
185
+ self = args[0]
186
+ # Make progressively weaker assumptions about "other"
187
+ other = ()
188
+ if len(args) == 2:
189
+ other = args[1]
190
+ if isinstance(other, dict):
191
+ for key in other:
192
+ self[key] = other[key]
193
+ elif hasattr(other, 'keys'):
194
+ for key in other.keys():
195
+ self[key] = other[key]
196
+ else:
197
+ for key, value in other:
198
+ self[key] = value
199
+ for key, value in kwds.items():
200
+ self[key] = value
201
+
202
+ __update = update # let subclasses override update without breaking __init__
203
+
204
+ __marker = object()
205
+
206
+ def pop(self, key, default=__marker):
207
+ '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
208
+ If key is not found, d is returned if given, otherwise KeyError is raised.
209
+
210
+ '''
211
+ if key in self:
212
+ result = self[key]
213
+ del self[key]
214
+ return result
215
+ if default is self.__marker:
216
+ raise KeyError(key)
217
+ return default
218
+
219
+ def setdefault(self, key, default=None):
220
+ 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
221
+ if key in self:
222
+ return self[key]
223
+ self[key] = default
224
+ return default
225
+
226
+ def __repr__(self, _repr_running={}):
227
+ 'od.__repr__() <==> repr(od)'
228
+ call_key = id(self), _get_ident()
229
+ if call_key in _repr_running:
230
+ return '...'
231
+ _repr_running[call_key] = 1
232
+ try:
233
+ if not self:
234
+ return '%s()' % (self.__class__.__name__,)
235
+ return '%s(%r)' % (self.__class__.__name__, self.items())
236
+ finally:
237
+ del _repr_running[call_key]
238
+
239
+ def __reduce__(self):
240
+ 'Return state information for pickling'
241
+ items = [[k, self[k]] for k in self]
242
+ inst_dict = vars(self).copy()
243
+ for k in vars(OrderedDict()):
244
+ inst_dict.pop(k, None)
245
+ if inst_dict:
246
+ return (self.__class__, (items,), inst_dict)
247
+ return self.__class__, (items,)
248
+
249
+ def copy(self):
250
+ 'od.copy() -> a shallow copy of od'
251
+ return self.__class__(self)
252
+
253
+ @classmethod
254
+ def fromkeys(cls, iterable, value=None):
255
+ '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
256
+ and values equal to v (which defaults to None).
257
+
258
+ '''
259
+ d = cls()
260
+ for key in iterable:
261
+ d[key] = value
262
+ return d
263
+
264
+ def __eq__(self, other):
265
+ '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
266
+ while comparison to a regular mapping is order-insensitive.
267
+
268
+ '''
269
+ if isinstance(other, OrderedDict):
270
+ return len(self)==len(other) and self.items() == other.items()
271
+ return dict.__eq__(self, other)
272
+
273
+ def __ne__(self, other):
274
+ return not self == other
275
+
276
+ # -- the following methods are only used in Python 2.7 --
277
+
278
+ def viewkeys(self):
279
+ "od.viewkeys() -> a set-like object providing a view on od's keys"
280
+ return KeysView(self)
281
+
282
+ def viewvalues(self):
283
+ "od.viewvalues() -> an object providing a view on od's values"
284
+ return ValuesView(self)
285
+
286
+ def viewitems(self):
287
+ "od.viewitems() -> a set-like object providing a view on od's items"
288
+ return ItemsView(self)
289
+
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env python
2
+
3
+ # Copyright (c) 2012 Google Inc. All rights reserved.
4
+ # Use of this source code is governed by a BSD-style license that can be
5
+ # found in the LICENSE file.
6
+
7
+ """Utility functions for Windows builds.
8
+
9
+ These functions are executed via gyp-win-tool when using the ninja generator.
10
+ """
11
+
12
+ import os
13
+ import re
14
+ import shutil
15
+ import subprocess
16
+ import string
17
+ import sys
18
+
19
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
20
+
21
+ # A regex matching an argument corresponding to the output filename passed to
22
+ # link.exe.
23
+ _LINK_EXE_OUT_ARG = re.compile('/OUT:(?P<out>.+)$', re.IGNORECASE)
24
+
25
+ def main(args):
26
+ executor = WinTool()
27
+ exit_code = executor.Dispatch(args)
28
+ if exit_code is not None:
29
+ sys.exit(exit_code)
30
+
31
+
32
+ class WinTool(object):
33
+ """This class performs all the Windows tooling steps. The methods can either
34
+ be executed directly, or dispatched from an argument list."""
35
+
36
+ def _UseSeparateMspdbsrv(self, env, args):
37
+ """Allows to use a unique instance of mspdbsrv.exe per linker instead of a
38
+ shared one."""
39
+ if len(args) < 1:
40
+ raise Exception("Not enough arguments")
41
+
42
+ if args[0] != 'link.exe':
43
+ return
44
+
45
+ # Use the output filename passed to the linker to generate an endpoint name
46
+ # for mspdbsrv.exe.
47
+ endpoint_name = None
48
+ for arg in args:
49
+ m = _LINK_EXE_OUT_ARG.match(arg)
50
+ if m:
51
+ endpoint_name = re.sub(r'\W+', '',
52
+ '%s_%d' % (m.group('out'), os.getpid()))
53
+ break
54
+
55
+ if endpoint_name is None:
56
+ return
57
+
58
+ # Adds the appropriate environment variable. This will be read by link.exe
59
+ # to know which instance of mspdbsrv.exe it should connect to (if it's
60
+ # not set then the default endpoint is used).
61
+ env['_MSPDBSRV_ENDPOINT_'] = endpoint_name
62
+
63
+ def Dispatch(self, args):
64
+ """Dispatches a string command to a method."""
65
+ if len(args) < 1:
66
+ raise Exception("Not enough arguments")
67
+
68
+ method = "Exec%s" % self._CommandifyName(args[0])
69
+ return getattr(self, method)(*args[1:])
70
+
71
+ def _CommandifyName(self, name_string):
72
+ """Transforms a tool name like recursive-mirror to RecursiveMirror."""
73
+ return name_string.title().replace('-', '')
74
+
75
+ def _GetEnv(self, arch):
76
+ """Gets the saved environment from a file for a given architecture."""
77
+ # The environment is saved as an "environment block" (see CreateProcess
78
+ # and msvs_emulation for details). We convert to a dict here.
79
+ # Drop last 2 NULs, one for list terminator, one for trailing vs. separator.
80
+ pairs = open(arch).read()[:-2].split('\0')
81
+ kvs = [item.split('=', 1) for item in pairs]
82
+ return dict(kvs)
83
+
84
+ def ExecStamp(self, path):
85
+ """Simple stamp command."""
86
+ open(path, 'w').close()
87
+
88
+ def ExecRecursiveMirror(self, source, dest):
89
+ """Emulation of rm -rf out && cp -af in out."""
90
+ if os.path.exists(dest):
91
+ if os.path.isdir(dest):
92
+ shutil.rmtree(dest)
93
+ else:
94
+ os.unlink(dest)
95
+ if os.path.isdir(source):
96
+ shutil.copytree(source, dest)
97
+ else:
98
+ shutil.copy2(source, dest)
99
+
100
+ def ExecLinkWrapper(self, arch, use_separate_mspdbsrv, *args):
101
+ """Filter diagnostic output from link that looks like:
102
+ ' Creating library ui.dll.lib and object ui.dll.exp'
103
+ This happens when there are exports from the dll or exe.
104
+ """
105
+ env = self._GetEnv(arch)
106
+ if use_separate_mspdbsrv == 'True':
107
+ self._UseSeparateMspdbsrv(env, args)
108
+ link = subprocess.Popen(args,
109
+ shell=True,
110
+ env=env,
111
+ stdout=subprocess.PIPE,
112
+ stderr=subprocess.STDOUT)
113
+ out, _ = link.communicate()
114
+ for line in out.splitlines():
115
+ if not line.startswith(' Creating library '):
116
+ print line
117
+ return link.returncode
118
+
119
+ def ExecLinkWithManifests(self, arch, embed_manifest, out, ldcmd, resname,
120
+ mt, rc, intermediate_manifest, *manifests):
121
+ """A wrapper for handling creating a manifest resource and then executing
122
+ a link command."""
123
+ # The 'normal' way to do manifests is to have link generate a manifest
124
+ # based on gathering dependencies from the object files, then merge that
125
+ # manifest with other manifests supplied as sources, convert the merged
126
+ # manifest to a resource, and then *relink*, including the compiled
127
+ # version of the manifest resource. This breaks incremental linking, and
128
+ # is generally overly complicated. Instead, we merge all the manifests
129
+ # provided (along with one that includes what would normally be in the
130
+ # linker-generated one, see msvs_emulation.py), and include that into the
131
+ # first and only link. We still tell link to generate a manifest, but we
132
+ # only use that to assert that our simpler process did not miss anything.
133
+ variables = {
134
+ 'python': sys.executable,
135
+ 'arch': arch,
136
+ 'out': out,
137
+ 'ldcmd': ldcmd,
138
+ 'resname': resname,
139
+ 'mt': mt,
140
+ 'rc': rc,
141
+ 'intermediate_manifest': intermediate_manifest,
142
+ 'manifests': ' '.join(manifests),
143
+ }
144
+ add_to_ld = ''
145
+ if manifests:
146
+ subprocess.check_call(
147
+ '%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo '
148
+ '-manifest %(manifests)s -out:%(out)s.manifest' % variables)
149
+ if embed_manifest == 'True':
150
+ subprocess.check_call(
151
+ '%(python)s gyp-win-tool manifest-to-rc %(arch)s %(out)s.manifest'
152
+ ' %(out)s.manifest.rc %(resname)s' % variables)
153
+ subprocess.check_call(
154
+ '%(python)s gyp-win-tool rc-wrapper %(arch)s %(rc)s '
155
+ '%(out)s.manifest.rc' % variables)
156
+ add_to_ld = ' %(out)s.manifest.res' % variables
157
+ subprocess.check_call(ldcmd + add_to_ld)
158
+
159
+ # Run mt.exe on the theoretically complete manifest we generated, merging
160
+ # it with the one the linker generated to confirm that the linker
161
+ # generated one does not add anything. This is strictly unnecessary for
162
+ # correctness, it's only to verify that e.g. /MANIFESTDEPENDENCY was not
163
+ # used in a #pragma comment.
164
+ if manifests:
165
+ # Merge the intermediate one with ours to .assert.manifest, then check
166
+ # that .assert.manifest is identical to ours.
167
+ subprocess.check_call(
168
+ '%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo '
169
+ '-manifest %(out)s.manifest %(intermediate_manifest)s '
170
+ '-out:%(out)s.assert.manifest' % variables)
171
+ assert_manifest = '%(out)s.assert.manifest' % variables
172
+ our_manifest = '%(out)s.manifest' % variables
173
+ # Load and normalize the manifests. mt.exe sometimes removes whitespace,
174
+ # and sometimes doesn't unfortunately.
175
+ with open(our_manifest, 'rb') as our_f:
176
+ with open(assert_manifest, 'rb') as assert_f:
177
+ our_data = our_f.read().translate(None, string.whitespace)
178
+ assert_data = assert_f.read().translate(None, string.whitespace)
179
+ if our_data != assert_data:
180
+ os.unlink(out)
181
+ def dump(filename):
182
+ sys.stderr.write('%s\n-----\n' % filename)
183
+ with open(filename, 'rb') as f:
184
+ sys.stderr.write(f.read() + '\n-----\n')
185
+ dump(intermediate_manifest)
186
+ dump(our_manifest)
187
+ dump(assert_manifest)
188
+ sys.stderr.write(
189
+ 'Linker generated manifest "%s" added to final manifest "%s" '
190
+ '(result in "%s"). '
191
+ 'Were /MANIFEST switches used in #pragma statements? ' % (
192
+ intermediate_manifest, our_manifest, assert_manifest))
193
+ return 1
194
+
195
+ def ExecManifestWrapper(self, arch, *args):
196
+ """Run manifest tool with environment set. Strip out undesirable warning
197
+ (some XML blocks are recognized by the OS loader, but not the manifest
198
+ tool)."""
199
+ env = self._GetEnv(arch)
200
+ popen = subprocess.Popen(args, shell=True, env=env,
201
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
202
+ out, _ = popen.communicate()
203
+ for line in out.splitlines():
204
+ if line and 'manifest authoring warning 81010002' not in line:
205
+ print line
206
+ return popen.returncode
207
+
208
+ def ExecManifestToRc(self, arch, *args):
209
+ """Creates a resource file pointing a SxS assembly manifest.
210
+ |args| is tuple containing path to resource file, path to manifest file
211
+ and resource name which can be "1" (for executables) or "2" (for DLLs)."""
212
+ manifest_path, resource_path, resource_name = args
213
+ with open(resource_path, 'wb') as output:
214
+ output.write('#include <windows.h>\n%s RT_MANIFEST "%s"' % (
215
+ resource_name,
216
+ os.path.abspath(manifest_path).replace('\\', '/')))
217
+
218
+ def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl,
219
+ *flags):
220
+ """Filter noisy filenames output from MIDL compile step that isn't
221
+ quietable via command line flags.
222
+ """
223
+ args = ['midl', '/nologo'] + list(flags) + [
224
+ '/out', outdir,
225
+ '/tlb', tlb,
226
+ '/h', h,
227
+ '/dlldata', dlldata,
228
+ '/iid', iid,
229
+ '/proxy', proxy,
230
+ idl]
231
+ env = self._GetEnv(arch)
232
+ popen = subprocess.Popen(args, shell=True, env=env,
233
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
234
+ out, _ = popen.communicate()
235
+ # Filter junk out of stdout, and write filtered versions. Output we want
236
+ # to filter is pairs of lines that look like this:
237
+ # Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl
238
+ # objidl.idl
239
+ lines = out.splitlines()
240
+ prefix = 'Processing '
241
+ processing = set(os.path.basename(x) for x in lines if x.startswith(prefix))
242
+ for line in lines:
243
+ if not line.startswith(prefix) and line not in processing:
244
+ print line
245
+ return popen.returncode
246
+
247
+ def ExecAsmWrapper(self, arch, *args):
248
+ """Filter logo banner from invocations of asm.exe."""
249
+ env = self._GetEnv(arch)
250
+ # MSVS doesn't assemble x64 asm files.
251
+ if arch == 'environment.x64':
252
+ return 0
253
+ popen = subprocess.Popen(args, shell=True, env=env,
254
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
255
+ out, _ = popen.communicate()
256
+ for line in out.splitlines():
257
+ if (not line.startswith('Copyright (C) Microsoft Corporation') and
258
+ not line.startswith('Microsoft (R) Macro Assembler') and
259
+ not line.startswith(' Assembling: ') and
260
+ line):
261
+ print line
262
+ return popen.returncode
263
+
264
+ def ExecRcWrapper(self, arch, *args):
265
+ """Filter logo banner from invocations of rc.exe. Older versions of RC
266
+ don't support the /nologo flag."""
267
+ env = self._GetEnv(arch)
268
+ popen = subprocess.Popen(args, shell=True, env=env,
269
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
270
+ out, _ = popen.communicate()
271
+ for line in out.splitlines():
272
+ if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler') and
273
+ not line.startswith('Copyright (C) Microsoft Corporation') and
274
+ line):
275
+ print line
276
+ return popen.returncode
277
+
278
+ def ExecActionWrapper(self, arch, rspfile, *dir):
279
+ """Runs an action command line from a response file using the environment
280
+ for |arch|. If |dir| is supplied, use that as the working directory."""
281
+ env = self._GetEnv(arch)
282
+ # TODO(scottmg): This is a temporary hack to get some specific variables
283
+ # through to actions that are set after gyp-time. http://crbug.com/333738.
284
+ for k, v in os.environ.iteritems():
285
+ if k not in env:
286
+ env[k] = v
287
+ args = open(rspfile).read()
288
+ dir = dir[0] if dir else None
289
+ return subprocess.call(args, shell=True, env=env, cwd=dir)
290
+
291
+ if __name__ == '__main__':
292
+ sys.exit(main(sys.argv[1:]))