passenger 5.0.28 → 5.0.29
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.editorconfig +5 -0
- data/CHANGELOG +13 -0
- data/build/apache2.rb +3 -3
- data/build/common_library.rb +3 -3
- data/build/nginx.rb +4 -4
- data/build/packaging.rb +9 -8
- data/build/support/cxx_dependency_map.rb +9 -7
- data/build/support/general.rb +39 -0
- data/build/support/vendor/cxxcodebuilder/CxxCodeBuilder.sublime-project +8 -0
- data/build/support/vendor/cxxcodebuilder/Gemfile +4 -0
- data/build/support/vendor/cxxcodebuilder/Gemfile.lock +28 -0
- data/build/support/vendor/cxxcodebuilder/LICENSE.md +19 -0
- data/build/support/vendor/cxxcodebuilder/README.md +98 -0
- data/build/support/vendor/cxxcodebuilder/Rakefile +4 -0
- data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder.rb +23 -0
- data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/builder.rb +574 -0
- data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/initializer_builder.rb +166 -0
- data/build/test_basics.rb +2 -1
- data/resources/templates/standalone/server.erb +6 -4
- data/src/agent/Core/Controller/ForwardResponse.cpp +5 -5
- data/src/agent/Watchdog/WatchdogMain.cpp +0 -10
- data/src/apache2_module/ConfigurationCommands.cpp +181 -248
- data/src/apache2_module/ConfigurationCommands.cpp.cxxcodebuilder +127 -0
- data/src/apache2_module/ConfigurationFields.hpp +135 -51
- data/src/apache2_module/ConfigurationFields.hpp.cxxcodebuilder +113 -0
- data/src/apache2_module/ConfigurationSetters.cpp +414 -459
- data/src/apache2_module/ConfigurationSetters.cpp.cxxcodebuilder +144 -0
- data/src/apache2_module/CreateDirConfig.cpp +49 -52
- data/src/apache2_module/CreateDirConfig.cpp.cxxcodebuilder +81 -0
- data/src/apache2_module/Hooks.cpp +0 -14
- data/src/apache2_module/MergeDirConfig.cpp +136 -226
- data/src/apache2_module/MergeDirConfig.cpp.cxxcodebuilder +97 -0
- data/src/apache2_module/SetHeaders.cpp +92 -143
- data/src/apache2_module/SetHeaders.cpp.cxxcodebuilder +106 -0
- data/src/cxx_supportlib/Constants.h +86 -146
- data/src/cxx_supportlib/Constants.h.cxxcodebuilder +43 -0
- data/src/cxx_supportlib/DataStructures/LString.h +40 -23
- data/src/cxx_supportlib/MemoryKit/mbuf.cpp +60 -25
- data/src/cxx_supportlib/MemoryKit/mbuf.h +50 -25
- data/src/cxx_supportlib/ServerKit/CookieUtils.h +36 -3
- data/src/cxx_supportlib/ServerKit/HeaderTable.h +2 -8
- data/src/cxx_supportlib/ServerKit/HttpServer.h +6 -15
- data/src/cxx_supportlib/WatchdogLauncher.cpp +4 -4
- data/src/cxx_supportlib/WatchdogLauncher.h +2 -3
- data/src/nginx_module/CacheLocationConfig.c +623 -780
- data/src/nginx_module/CacheLocationConfig.c.cxxcodebuilder +214 -0
- data/src/nginx_module/Configuration.h +1 -1
- data/src/nginx_module/ConfigurationCommands.c +404 -535
- data/src/nginx_module/ConfigurationCommands.c.cxxcodebuilder +157 -0
- data/src/nginx_module/CreateLocationConfig.c +82 -206
- data/src/nginx_module/CreateLocationConfig.c.cxxcodebuilder +98 -0
- data/src/nginx_module/LocationConfig.h +97 -0
- data/src/nginx_module/LocationConfig.h.cxxcodebuilder +131 -0
- data/src/nginx_module/MergeLocationConfig.c +157 -278
- data/src/nginx_module/MergeLocationConfig.c.cxxcodebuilder +144 -0
- data/src/nginx_module/ngx_http_passenger_module.c +4 -10
- data/src/ruby_supportlib/phusion_passenger.rb +4 -4
- data/src/ruby_supportlib/phusion_passenger/config/validate_install_command.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/packaging.rb +2 -0
- data/src/ruby_supportlib/phusion_passenger/platform_info/compiler.rb +6 -0
- data/src/ruby_supportlib/phusion_passenger/platform_info/cxx_portability.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +27 -8
- data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller.rb +120 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/lock_file.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/spawn.rb +4 -4
- data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/version.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +5 -5
- metadata +24 -15
- data/src/apache2_module/ConfigurationCommands.cpp.erb +0 -109
- data/src/apache2_module/ConfigurationFields.hpp.erb +0 -98
- data/src/apache2_module/ConfigurationSetters.cpp.erb +0 -128
- data/src/apache2_module/CreateDirConfig.cpp.erb +0 -72
- data/src/apache2_module/MergeDirConfig.cpp.erb +0 -82
- data/src/apache2_module/SetHeaders.cpp.erb +0 -91
- data/src/cxx_supportlib/Constants.h.erb +0 -41
- data/src/nginx_module/CacheLocationConfig.c.erb +0 -171
- data/src/nginx_module/ConfigurationCommands.c.erb +0 -144
- data/src/nginx_module/ConfigurationFields.h +0 -145
- data/src/nginx_module/ConfigurationFields.h.erb +0 -112
- data/src/nginx_module/CreateLocationConfig.c.erb +0 -78
- data/src/nginx_module/MergeLocationConfig.c.erb +0 -118
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright (c) 2016 Phusion Holding B.V.
|
2
|
+
#
|
3
|
+
# "Union Station" and "Passenger" are trademarks of Phusion Holding B.V.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
require File.expand_path(File.dirname(__FILE__) + '/cxxcodebuilder/builder')
|
@@ -0,0 +1,574 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2016 Phusion Holding B.V.
|
4
|
+
#
|
5
|
+
# "Union Station" and "Passenger" are trademarks of Phusion Holding B.V.
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
15
|
+
# all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
# THE SOFTWARE.
|
24
|
+
|
25
|
+
require File.expand_path(File.dirname(__FILE__) + '/initializer_builder')
|
26
|
+
|
27
|
+
module CxxCodeBuilder
|
28
|
+
# Builds C/C++ code. Use it as follows:
|
29
|
+
#
|
30
|
+
# 1. Create a CxxCodeBuilder::Builder object.
|
31
|
+
# 2. Call API methods in the Builder object to generate C/C++ code.
|
32
|
+
# 3. When done, call `#to_s` to obtain the generated code.
|
33
|
+
#
|
34
|
+
# There are two ways to use CxxCodeBuilder::Builder:
|
35
|
+
#
|
36
|
+
# 1. By passing a block to the constructor. The block is evaluated in
|
37
|
+
# the context of the builder object, so inside the block you have
|
38
|
+
# access to all the API methods of the Builder class. See README.md
|
39
|
+
# for an example of this usage.
|
40
|
+
# 2. By calling the API methods of the Builder class, without passing
|
41
|
+
# a block to the constructor.
|
42
|
+
#
|
43
|
+
# ## Internal buffer
|
44
|
+
#
|
45
|
+
# Builder has an internal buffer containing the code generated so far.
|
46
|
+
# Most API methods, such as `#function` and `#field`, generate new code
|
47
|
+
# and append to this internal buffer. `#to_s` returns the contents of
|
48
|
+
# the buffer.
|
49
|
+
#
|
50
|
+
# ## Indentation
|
51
|
+
#
|
52
|
+
# Builder keeps track of the current indentation level and generates
|
53
|
+
# code accordingly. You can temporarily increase it with the `indent`
|
54
|
+
# method. Builder generates tabs for indentation.
|
55
|
+
class Builder
|
56
|
+
def initialize(&block)
|
57
|
+
@indent_string = "\t"
|
58
|
+
@indent_level = 0
|
59
|
+
@code = ""
|
60
|
+
|
61
|
+
if block
|
62
|
+
instance_eval(&block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Customizes the indentation string. The default is a tab,
|
67
|
+
# but you can use this to set it to e.g. 4 spaces. You should
|
68
|
+
# call this method as early as possible because it won't
|
69
|
+
# affect the indentation of already generated code.
|
70
|
+
def set_indent_string(str)
|
71
|
+
@indent_string = str
|
72
|
+
end
|
73
|
+
|
74
|
+
# Adds some code to the internal buffer. Before adding to the internal
|
75
|
+
# buffer, extraneous indentation and leading and trailing empty lines in
|
76
|
+
# `code` are removed, and new indentation is added based on the current
|
77
|
+
# indentation level. The code is suffixed with a newline.
|
78
|
+
#
|
79
|
+
#
|
80
|
+
# Example 1:
|
81
|
+
#
|
82
|
+
# add_code 'foo();'
|
83
|
+
#
|
84
|
+
# Output 1:
|
85
|
+
#
|
86
|
+
# foo();
|
87
|
+
#
|
88
|
+
#
|
89
|
+
# Example 2:
|
90
|
+
#
|
91
|
+
# # The argument contains extraneous leading and trailing empty lines,
|
92
|
+
# # as well as extraneous indenting.
|
93
|
+
# add_code %q{
|
94
|
+
# foo();
|
95
|
+
# if (true) {
|
96
|
+
# bar();
|
97
|
+
# }
|
98
|
+
# }
|
99
|
+
#
|
100
|
+
# Output 2 (extraneous leading/trailing newlines and extraneous indenting removed):
|
101
|
+
#
|
102
|
+
# foo();
|
103
|
+
# if (true) {
|
104
|
+
# bar();
|
105
|
+
# }
|
106
|
+
def add_code(code)
|
107
|
+
add_code_without_newline(code)
|
108
|
+
newline
|
109
|
+
end
|
110
|
+
|
111
|
+
# Like `#add_code`, but does not suffix the generated code with a newline.
|
112
|
+
def add_code_without_newline(code)
|
113
|
+
@code << reindent(unindent(code.to_s), @indent_string * @indent_level, true)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Adds some raw code to the internal buffer. Unlike `#add_code`, no
|
117
|
+
# preprocessing is performed to remove extraneous newlines or indenting.
|
118
|
+
def add_raw_code(code)
|
119
|
+
@code << code
|
120
|
+
end
|
121
|
+
|
122
|
+
# Temporarily increase the indentation level by 1. This new indentation
|
123
|
+
# level is only active inside the given block.
|
124
|
+
#
|
125
|
+
# Example:
|
126
|
+
#
|
127
|
+
# add_code 'foo();'
|
128
|
+
#
|
129
|
+
# indent do
|
130
|
+
# add_code 'bar();'
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# Output:
|
134
|
+
#
|
135
|
+
# foo();
|
136
|
+
# bar();
|
137
|
+
def indent
|
138
|
+
@indent_level += 1
|
139
|
+
begin
|
140
|
+
yield
|
141
|
+
ensure
|
142
|
+
@indent_level -= 1
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Adds a newline to the internal buffer.
|
147
|
+
def separator
|
148
|
+
@code << "\n"
|
149
|
+
end
|
150
|
+
|
151
|
+
alias newline separator
|
152
|
+
|
153
|
+
# Adds an `#include` statement to the internal buffer.
|
154
|
+
# `header_name` is verbatim added to the statement, so you
|
155
|
+
# need to pass either `"<header_name.h>"` or `'"header_name.h"'`
|
156
|
+
# as argument.
|
157
|
+
#
|
158
|
+
# Example:
|
159
|
+
#
|
160
|
+
# include '<stdio.h>'
|
161
|
+
# include '"Config.h"'
|
162
|
+
#
|
163
|
+
# Output:
|
164
|
+
#
|
165
|
+
# #include <stdio.h>
|
166
|
+
# #include "Config.h"
|
167
|
+
def include(header_name)
|
168
|
+
add_code("#include #{header_name}")
|
169
|
+
end
|
170
|
+
|
171
|
+
# Adds a `#define` statement to the internal buffer.
|
172
|
+
# `macro` is verbatim added to the statement. If you want
|
173
|
+
# to #define a string constant then you should use the
|
174
|
+
# `#define_string` method.
|
175
|
+
#
|
176
|
+
# Example:
|
177
|
+
#
|
178
|
+
# define 'HAVE_STDINT_H'
|
179
|
+
# define 'FOO bar'
|
180
|
+
# define 'TWO 1 + 2'
|
181
|
+
#
|
182
|
+
# Output:
|
183
|
+
#
|
184
|
+
# #define HAVE_STDINT_H
|
185
|
+
# #define FOO bar
|
186
|
+
# #define TWO 1 + 2
|
187
|
+
def define(macro)
|
188
|
+
add_code("#define #{macro}")
|
189
|
+
end
|
190
|
+
|
191
|
+
# Adds a `#define` statement to the internal buffer for defining
|
192
|
+
# a string macro.
|
193
|
+
#
|
194
|
+
# Example:
|
195
|
+
#
|
196
|
+
# define 'NAME', 'Joe Dalton'
|
197
|
+
#
|
198
|
+
# Output:
|
199
|
+
#
|
200
|
+
# #define NAME "Joe Dalton"
|
201
|
+
def define_string(name, value)
|
202
|
+
define("#{name} #{str_val(value)}")
|
203
|
+
end
|
204
|
+
|
205
|
+
# Adds header guard macros to the internal buffer. Expects
|
206
|
+
# a block which generates the code to insert inside the guard.
|
207
|
+
#
|
208
|
+
# Example:
|
209
|
+
#
|
210
|
+
# guard_macros 'MY_HEADER_H' do
|
211
|
+
# field 'int foo'
|
212
|
+
# end
|
213
|
+
#
|
214
|
+
# Output:
|
215
|
+
#
|
216
|
+
# #ifndef MY_HEADER_H
|
217
|
+
# #define MY_HEADER_H
|
218
|
+
#
|
219
|
+
# int foo;
|
220
|
+
#
|
221
|
+
# #endif /* MY_HEADER_H */
|
222
|
+
def guard_macros(name)
|
223
|
+
add_code("#ifndef #{name}")
|
224
|
+
define(name)
|
225
|
+
separator
|
226
|
+
yield
|
227
|
+
separator
|
228
|
+
add_code("#endif /* #{name} */")
|
229
|
+
end
|
230
|
+
|
231
|
+
# Adds a comment to the internal buffer. Before adding to the internal
|
232
|
+
# buffer, extraneous indentation and leading and trailing empty lines in
|
233
|
+
# `text` are removed, and new indentation is added based on the current
|
234
|
+
# indentation level. The text is also prefixed with the '*' character.
|
235
|
+
#
|
236
|
+
# Example:
|
237
|
+
#
|
238
|
+
# comment "hello\nworld"
|
239
|
+
# comment %q{
|
240
|
+
# foo
|
241
|
+
# bar
|
242
|
+
# }
|
243
|
+
#
|
244
|
+
# Output:
|
245
|
+
#
|
246
|
+
# /*
|
247
|
+
# * hello
|
248
|
+
# * world
|
249
|
+
# */
|
250
|
+
# /*
|
251
|
+
# * foo
|
252
|
+
# * bar
|
253
|
+
# */
|
254
|
+
def comment(text)
|
255
|
+
add_code '/*'
|
256
|
+
prefix = @indent_string * @indent_level
|
257
|
+
prefix << ' * '
|
258
|
+
@code << reindent(unindent(text.to_s), prefix, false)
|
259
|
+
@code << "\n"
|
260
|
+
add_code_without_newline '-'
|
261
|
+
@code.gsub!(/-\Z/, ' ')
|
262
|
+
add_raw_code "*/\n"
|
263
|
+
end
|
264
|
+
|
265
|
+
# Adds a struct definition to the internal buffer. Expects a block
|
266
|
+
# in which you must define the struct's contents. Inside the block
|
267
|
+
# you can use any Builder API methods, but you are most likely
|
268
|
+
# interested in `#member`, `#comment`, `#separator` and `#function`.
|
269
|
+
#
|
270
|
+
# Example:
|
271
|
+
#
|
272
|
+
# struct 'Car' do
|
273
|
+
# comment "The car's name"
|
274
|
+
# member 'string name'
|
275
|
+
#
|
276
|
+
# separator
|
277
|
+
# member 'unsigned int seats'
|
278
|
+
# end
|
279
|
+
#
|
280
|
+
# Outputs:
|
281
|
+
#
|
282
|
+
# struct Car {
|
283
|
+
# /*
|
284
|
+
# * The car's name.
|
285
|
+
# */
|
286
|
+
# string name;
|
287
|
+
#
|
288
|
+
# unsigned int seats;
|
289
|
+
# };
|
290
|
+
def struct(name)
|
291
|
+
add_code "struct #{name} {"
|
292
|
+
indent do
|
293
|
+
yield
|
294
|
+
end
|
295
|
+
add_code '};'
|
296
|
+
end
|
297
|
+
|
298
|
+
# Adds a struct typedef definition to the internal buffer. This works
|
299
|
+
# like the `#struct` method, but outputs a typedef struct instead.
|
300
|
+
#
|
301
|
+
# Example:
|
302
|
+
#
|
303
|
+
# typedef_struct 'Car' do
|
304
|
+
# comment "The car's name"
|
305
|
+
# member 'string name'
|
306
|
+
#
|
307
|
+
# separator
|
308
|
+
# member 'unsigned int seats'
|
309
|
+
# end
|
310
|
+
#
|
311
|
+
# Outputs:
|
312
|
+
#
|
313
|
+
# typedef struct {
|
314
|
+
# /*
|
315
|
+
# * The car's name.
|
316
|
+
# */
|
317
|
+
# string name;
|
318
|
+
#
|
319
|
+
# unsigned int seats;
|
320
|
+
# } Car;
|
321
|
+
def typedef_struct(name)
|
322
|
+
add_code 'typedef struct {'
|
323
|
+
indent do
|
324
|
+
yield
|
325
|
+
end
|
326
|
+
add_code "} #{name};"
|
327
|
+
end
|
328
|
+
|
329
|
+
# Adds a function definition to the internal buffer. There are two ways to
|
330
|
+
# supply the function body. The first is by passing a string. The second is
|
331
|
+
# by passing a block, which is expected to use Builder API methods to
|
332
|
+
# generate code for the body.
|
333
|
+
#
|
334
|
+
# If a string is passed, then extraneous indentation and leading and trailing
|
335
|
+
# empty lines inside it are removed.
|
336
|
+
#
|
337
|
+
# No matter how the body is body is supplied, the generated body is indented.
|
338
|
+
#
|
339
|
+
# Example:
|
340
|
+
#
|
341
|
+
# function 'static void foo(int x)', %q{
|
342
|
+
# printf("x = %d\n", x);
|
343
|
+
# }
|
344
|
+
#
|
345
|
+
# function 'static void bar(int x)' do
|
346
|
+
# add_code 'printf("x = %d\n", x);'
|
347
|
+
# end
|
348
|
+
#
|
349
|
+
# Output:
|
350
|
+
#
|
351
|
+
# static void
|
352
|
+
# foo(int x) {
|
353
|
+
# printf("x = %d\n", x);
|
354
|
+
# }
|
355
|
+
#
|
356
|
+
# static void
|
357
|
+
# bar(int x) {
|
358
|
+
# printf("x = %d\n", x);
|
359
|
+
# }
|
360
|
+
def function(declaration, body = nil)
|
361
|
+
declaration =~ /(.*?)([a-z0-9_:]+)\s*\((.*)\s*(const)?/mi
|
362
|
+
return_type_and_attributes = $1
|
363
|
+
name_and_params = "#{$2}(#{$3} #{$4}".strip
|
364
|
+
|
365
|
+
add_code return_type_and_attributes.strip
|
366
|
+
add_code "#{name_and_params.strip} {"
|
367
|
+
indent do
|
368
|
+
if block_given?
|
369
|
+
yield
|
370
|
+
else
|
371
|
+
add_code body
|
372
|
+
end
|
373
|
+
end
|
374
|
+
add_code '}'
|
375
|
+
separator
|
376
|
+
end
|
377
|
+
|
378
|
+
# Adds a field/member/variable definition to the internal buffer.
|
379
|
+
# You can optionally supply a value, either by passing it directly as
|
380
|
+
# an argument, or by passing a block which will generate the code for
|
381
|
+
# the value.
|
382
|
+
#
|
383
|
+
# When supplying an argument, the argument is added verbatim to the
|
384
|
+
# internal buffer, so you can even supply an expression. If you want to
|
385
|
+
# set the value to a string, then you should use the `#str_val` helper
|
386
|
+
# method. See the example below.
|
387
|
+
#
|
388
|
+
# The block form is especially useful for generating
|
389
|
+
# array/struct initializer code (see also `#array_initializer` and
|
390
|
+
# `#struct_initializer` in that case).
|
391
|
+
#
|
392
|
+
# Example:
|
393
|
+
#
|
394
|
+
# field('int a')
|
395
|
+
# field('int b', 123);
|
396
|
+
# field('int c', '1 + 2')
|
397
|
+
# field('const char *str', str_val("hello world"));
|
398
|
+
#
|
399
|
+
# separator
|
400
|
+
#
|
401
|
+
# field('int magicNumbers[]') do
|
402
|
+
# array_initializer do
|
403
|
+
# element 1
|
404
|
+
# element 2
|
405
|
+
# end
|
406
|
+
# end
|
407
|
+
#
|
408
|
+
# separator
|
409
|
+
#
|
410
|
+
# field('const char *magicStrings[]') do
|
411
|
+
# array_initializer do
|
412
|
+
# string_element "foo"
|
413
|
+
# # Equivalent:
|
414
|
+
# element str_val("foo")
|
415
|
+
# end
|
416
|
+
# end
|
417
|
+
#
|
418
|
+
# Output:
|
419
|
+
#
|
420
|
+
# int a;
|
421
|
+
# int b = 123;
|
422
|
+
# int c = 1 + 2;
|
423
|
+
# const char *str = "hello world";
|
424
|
+
#
|
425
|
+
# int magicNumbers[] = [
|
426
|
+
# 1,
|
427
|
+
# 2
|
428
|
+
# ];
|
429
|
+
#
|
430
|
+
# const char *magicStrings[] = [
|
431
|
+
# "foo",
|
432
|
+
# "foo"
|
433
|
+
# ];
|
434
|
+
#
|
435
|
+
def field(declaration, value = nil)
|
436
|
+
if block_given?
|
437
|
+
add_code_without_newline "#{declaration} ="
|
438
|
+
add_raw_code ' '
|
439
|
+
yield
|
440
|
+
@code.gsub!(/\n*\Z/m, '')
|
441
|
+
add_raw_code ';'
|
442
|
+
newline
|
443
|
+
elsif value
|
444
|
+
add_code "#{declaration} = #{value};"
|
445
|
+
else
|
446
|
+
add_code "#{declaration};"
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
alias variable field
|
451
|
+
alias member field
|
452
|
+
|
453
|
+
# Adds an array initializer (in the form of `[x, y, z]`) to the internal
|
454
|
+
# buffer. Expects a block which defines the elements inside the array.
|
455
|
+
# The block does not expose the Builder API methods, but exposes the
|
456
|
+
# InitializerBuilder API methods instead. See the comments in
|
457
|
+
# initializer_builder.rb for an example and to learn what API methods
|
458
|
+
# are available.
|
459
|
+
#
|
460
|
+
# Does not add a trailing newline.
|
461
|
+
#
|
462
|
+
# Example:
|
463
|
+
#
|
464
|
+
# array_initializer do
|
465
|
+
# element 1
|
466
|
+
# element 2
|
467
|
+
# end
|
468
|
+
#
|
469
|
+
# separator
|
470
|
+
#
|
471
|
+
# array_initializer do
|
472
|
+
# string_element "foo"
|
473
|
+
# # Equivalent:
|
474
|
+
# element str_val("foo")
|
475
|
+
# end
|
476
|
+
#
|
477
|
+
# Output:
|
478
|
+
#
|
479
|
+
# [
|
480
|
+
# 1,
|
481
|
+
# 2
|
482
|
+
# ]
|
483
|
+
#
|
484
|
+
# [
|
485
|
+
# "foo",
|
486
|
+
# "foo"
|
487
|
+
# ]
|
488
|
+
def array_initializer(&block)
|
489
|
+
subbuilder = InitializerBuilder.new(self, '[', ']')
|
490
|
+
subbuilder.instance_eval(&block)
|
491
|
+
subbuilder.write_code_without_newline
|
492
|
+
end
|
493
|
+
|
494
|
+
# Adds a struct initializer (in the form of `{x, y, z}`) to the internal
|
495
|
+
# buffer. Expects a block which defines the elements inside the array.
|
496
|
+
# The block does not expose the Builder API methods, but exposes the
|
497
|
+
# InitializerBuilder API methods instead. See the comments in
|
498
|
+
# initializer_builder.rb for an example and to learn what API methods
|
499
|
+
# are available.
|
500
|
+
#
|
501
|
+
# Does not add a trailing newline.
|
502
|
+
#
|
503
|
+
# Example:
|
504
|
+
#
|
505
|
+
# struct_initializer do
|
506
|
+
# element 1
|
507
|
+
# element 2
|
508
|
+
# end
|
509
|
+
#
|
510
|
+
# separator
|
511
|
+
#
|
512
|
+
# struct_initializer do
|
513
|
+
# string_element "foo"
|
514
|
+
# # Equivalent:
|
515
|
+
# element str_val("foo")
|
516
|
+
# end
|
517
|
+
#
|
518
|
+
# Output:
|
519
|
+
#
|
520
|
+
# {
|
521
|
+
# 1,
|
522
|
+
# 2
|
523
|
+
# }
|
524
|
+
#
|
525
|
+
# {
|
526
|
+
# "foo",
|
527
|
+
# "foo"
|
528
|
+
# }
|
529
|
+
def struct_initializer(&block)
|
530
|
+
subbuilder = InitializerBuilder.new(self, '{', '}')
|
531
|
+
subbuilder.instance_eval(&block)
|
532
|
+
subbuilder.write_code_without_newline
|
533
|
+
end
|
534
|
+
|
535
|
+
# Returns (and does not modify the internal buffer!) a C string representation
|
536
|
+
# of `str`. This is especially useful for supplying a string value to `#field`.
|
537
|
+
def str_val(str)
|
538
|
+
str.to_s.inspect
|
539
|
+
end
|
540
|
+
|
541
|
+
def to_s
|
542
|
+
@code
|
543
|
+
end
|
544
|
+
|
545
|
+
private
|
546
|
+
def unindent(str)
|
547
|
+
str = str.dup
|
548
|
+
str.gsub!(/\A([\s\t]*\n)+/, '')
|
549
|
+
str.gsub!(/[\s\t\n]+\Z/, '')
|
550
|
+
indent = str.split("\n").select{ |line| !line.strip.empty? }.map{ |line| line.index(/[^\s]/) }.compact.min || 0
|
551
|
+
str.gsub!(/^[[:blank:]]{#{indent}}/, '')
|
552
|
+
str
|
553
|
+
end
|
554
|
+
|
555
|
+
def reindent(str, prefix, convert_ruby_indentation)
|
556
|
+
str = unindent(str)
|
557
|
+
|
558
|
+
# Convert Ruby two-space indentation to our own indentation format
|
559
|
+
if convert_ruby_indentation
|
560
|
+
str.gsub!(/^( )+/) do |match|
|
561
|
+
@indent_string * (match.size / 2)
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
# Prepend supplied prefix to each line
|
566
|
+
str.gsub!(/^/, prefix)
|
567
|
+
|
568
|
+
# Remove trailing whitespaces
|
569
|
+
str.gsub!(/[ \t]+$/, '')
|
570
|
+
|
571
|
+
str
|
572
|
+
end
|
573
|
+
end
|
574
|
+
end
|