NCPrePatcher 0.2.0-x86_64-darwin-24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +674 -0
- data/README.md +66 -0
- data/example/README.md +3 -0
- data/example/disasm.rb +34 -0
- data/exe/ncpp +4 -0
- data/lib/ncpp/commands.rb +903 -0
- data/lib/ncpp/interpreter.rb +919 -0
- data/lib/ncpp/parser.rb +249 -0
- data/lib/ncpp/types.rb +68 -0
- data/lib/ncpp/utils.rb +700 -0
- data/lib/ncpp/version.rb +4 -0
- data/lib/ncpp.rb +478 -0
- data/lib/nitro/nitro.dylib +0 -0
- data/lib/nitro/nitro.rb +440 -0
- data/lib/unarm/unarm.dylib +0 -0
- data/lib/unarm/unarm.rb +836 -0
- metadata +91 -0
data/lib/ncpp.rb
ADDED
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
require_relative 'nitro/nitro.rb'
|
|
2
|
+
require_relative 'unarm/unarm.rb'
|
|
3
|
+
require_relative 'ncpp/interpreter.rb'
|
|
4
|
+
|
|
5
|
+
require 'json'
|
|
6
|
+
require 'optparse'
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
require 'pathname'
|
|
9
|
+
|
|
10
|
+
module NCPP
|
|
11
|
+
|
|
12
|
+
# TODO: MUST move away from globals
|
|
13
|
+
$clean_rom = nil
|
|
14
|
+
$target_rom = nil
|
|
15
|
+
|
|
16
|
+
alias $rom $clean_rom # In most cases the clean rom will be desired
|
|
17
|
+
|
|
18
|
+
$config = nil
|
|
19
|
+
|
|
20
|
+
NCP_CONFIG_FILE_PATH = 'ncpatcher.json'
|
|
21
|
+
CONFIG_FILE_PATH = 'ncpp_config.json'
|
|
22
|
+
NCPP_DEFS_FILENAME = 'ncpp_defs'
|
|
23
|
+
NCPP_GLB_DEFS_FILENAME = 'ncpp_global'
|
|
24
|
+
|
|
25
|
+
CONFIG_TEMPLATE = {
|
|
26
|
+
clean_rom: '', target_rom: '',
|
|
27
|
+
sources: [], source_file_types: %w[cpp hpp inl c h s],
|
|
28
|
+
symbols9: '', symbols7: '',
|
|
29
|
+
gen_path: 'ncpp-gen',
|
|
30
|
+
command_prefix: 'ncpp_'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
REQUIRED_CONFIG_FIELDS = [:clean_rom, :sources].freeze
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def self.glean_from_arm_config(cfg, arm_cfg, cpu: 9)
|
|
37
|
+
cfg[('symbols'+cpu.to_s).to_sym] = arm_cfg['symbols']
|
|
38
|
+
arm_cfg['regions'].each do |region|
|
|
39
|
+
if region['sources'][0].is_a? Array
|
|
40
|
+
cfg[:sources].concat(region['sources'].map {|src,glb| "#{src}#{glb ? '/*' : ''}" })
|
|
41
|
+
else
|
|
42
|
+
cfg[:sources].concat(region['sources'])
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
cfg
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.update_ncp_configs(ncp_cfg, arm9_cfg, arm7_cfg = nil, revert: false)
|
|
49
|
+
if revert
|
|
50
|
+
ncp_cfg['pre-build']&.delete('ncpp')
|
|
51
|
+
ncp_cfg['pre-build']&.delete('ncpp.bat')
|
|
52
|
+
else
|
|
53
|
+
ncp_cfg['pre-build'] |= [(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil ? 'ncpp.bat' : 'ncpp']
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
gen_path = ($config || CONFIG_TEMPLATE)[:gen_path]
|
|
57
|
+
prefix = "#{gen_path}/"
|
|
58
|
+
|
|
59
|
+
[arm9_cfg, arm7_cfg].compact.each do |cfg|
|
|
60
|
+
|
|
61
|
+
[['source', File.join(gen_path, 'source')], ['source7', File.join(gen_path, 'source7')]].each do |name, path|
|
|
62
|
+
entry = cfg['includes'].find { it[0] == (revert ? path : name) }
|
|
63
|
+
entry[0] = (revert ? name : path) if entry
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
cfg['regions'].each do |region|
|
|
67
|
+
region['sources'].map! do |src|
|
|
68
|
+
if src.is_a?(Array)
|
|
69
|
+
src[0] =
|
|
70
|
+
if revert
|
|
71
|
+
src[0].sub(/^#{Regexp.escape(prefix)}/, '')
|
|
72
|
+
else
|
|
73
|
+
File.join(gen_path, src[0].to_s)
|
|
74
|
+
end
|
|
75
|
+
src
|
|
76
|
+
else
|
|
77
|
+
if revert
|
|
78
|
+
src.sub(/^#{Regexp.escape(prefix)}/, '')
|
|
79
|
+
else
|
|
80
|
+
File.join(gen_path, src.to_s)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
File.write(NCP_CONFIG_FILE_PATH, JSON.pretty_generate(ncp_cfg))
|
|
88
|
+
File.write(ncp_cfg['arm9']['target'], JSON.pretty_generate(arm9_cfg))
|
|
89
|
+
File.write(ncp_cfg['arm7']['target'], JSON.pretty_generate(arm7_cfg)) if arm7_cfg
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.get_missing_config_reqs(cfg)
|
|
93
|
+
missing_fields = []
|
|
94
|
+
|
|
95
|
+
cfg.each do |field, value|
|
|
96
|
+
next unless REQUIRED_CONFIG_FIELDS.include? field.to_sym
|
|
97
|
+
missing_fields << field if value.empty? || value.nil?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
missing_fields
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.list_missing_config_fields(missing, cfg_path)
|
|
104
|
+
plural = missing.length > 1
|
|
105
|
+
puts "Please fill #{plural ? 'out' : 'in'} the following field#{plural ? 's' : ''} in #{cfg_path.bold_red}:"
|
|
106
|
+
missing.each {|field| puts " * ".purple + field.to_s}
|
|
107
|
+
exit
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def self.init(cfg_path = CONFIG_FILE_PATH, verbose: true)
|
|
111
|
+
|
|
112
|
+
if !File.exist?(cfg_path)
|
|
113
|
+
ncp_cfg = JSON.load_file(NCP_CONFIG_FILE_PATH)
|
|
114
|
+
arm9_cfg = arm7_cfg = nil
|
|
115
|
+
|
|
116
|
+
arm9_cfg = JSON.load_file(ncp_cfg['arm9']['target'])
|
|
117
|
+
cfg = glean_from_arm_config(CONFIG_TEMPLATE, arm9_cfg, cpu: 9)
|
|
118
|
+
|
|
119
|
+
if !ncp_cfg['arm7'].empty?
|
|
120
|
+
arm7_cfg = JSON.load_file(ncp_cfg['arm7']['target'])
|
|
121
|
+
cfg = glean_from_arm_config(cfg, arm7_cfg, cpu: 7)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
update_ncp_configs(ncp_cfg,arm9_cfg,arm7_cfg)
|
|
125
|
+
|
|
126
|
+
File.write(cfg_path, JSON.pretty_generate(cfg))
|
|
127
|
+
puts "Created #{cfg_path} in current directory.".cyan if verbose
|
|
128
|
+
|
|
129
|
+
missing = get_missing_config_reqs(cfg)
|
|
130
|
+
list_missing_config_fields(missing, cfg_path) unless missing.empty?
|
|
131
|
+
|
|
132
|
+
else
|
|
133
|
+
cfg = JSON.load_file(cfg_path)
|
|
134
|
+
missing = get_missing_config_reqs(cfg)
|
|
135
|
+
list_missing_config_fields(missing, cfg_path) unless missing.empty?
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
$config = cfg
|
|
139
|
+
$clean_rom = Nitro::Rom.new(cfg['clean_rom'].gsub(/\$\{env:([^}]+)\}/) { ENV[$1] })
|
|
140
|
+
$target_rom = Nitro::Rom.new(cfg['target_rom'].gsub(/\$\{env:([^}]+)\}/) { ENV[$1]}) unless cfg['target_rom'].empty?
|
|
141
|
+
|
|
142
|
+
Unarm.load_symbols9(cfg['symbols9'].gsub(/\$\{env:([^}]+)\}/) { ENV[$1] }) unless cfg['symbols9'].empty?
|
|
143
|
+
Unarm.load_symbols7(cfg['symbols7'].gsub(/\$\{env:([^}]+)\}/) { ENV[$1] }) unless cfg['symbols7'].empty?
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def self.uninstall(cfg_path = CONFIG_FILE_PATH)
|
|
147
|
+
ncp_cfg = JSON.load_file(NCP_CONFIG_FILE_PATH)
|
|
148
|
+
|
|
149
|
+
arm9_cfg = ncp_cfg['arm9'].empty? ? nil : JSON.load_file(ncp_cfg['arm9']['target'])
|
|
150
|
+
arm7_cfg = ncp_cfg['arm7'].empty? ? nil : JSON.load_file(ncp_cfg['arm7']['target'])
|
|
151
|
+
|
|
152
|
+
update_ncp_configs(ncp_cfg, arm9_cfg, arm7_cfg, revert: true)
|
|
153
|
+
|
|
154
|
+
return if !File.exist?(cfg_path)
|
|
155
|
+
|
|
156
|
+
cfg = JSON.load_file(cfg_path)
|
|
157
|
+
FileUtils.rm_rf(cfg['gen_path']) unless cfg['gen_path'].empty?
|
|
158
|
+
File.delete(cfg_path)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def self.show_rom_info(rom)
|
|
162
|
+
puts "Game title: #{rom.header.game_title}\n" \
|
|
163
|
+
"Game code: #{rom.header.game_code}\n" \
|
|
164
|
+
"Maker code: #{rom.header.maker_code}\n" \
|
|
165
|
+
"Size: #{(rom.size / 1024.0 / 1024.0).round(2)} MB\n" \
|
|
166
|
+
"Overlay count: #{rom.overlay_count}"
|
|
167
|
+
puts "Arm9 symbol count: #{Unarm.symbols9.count}" unless Unarm.symbols9.nil?
|
|
168
|
+
puts "Arm7 symbol count: #{Unarm.symbols7.count}" unless Unarm.symbols7.nil?
|
|
169
|
+
puts
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# update timestamp cache entry and returns whether it has been modified
|
|
173
|
+
def self.update_ts_cache_entry(ts_cache, entry_file)
|
|
174
|
+
last_modified = File.mtime(entry_file).to_s
|
|
175
|
+
modified = !ts_cache[entry_file].eql?(last_modified)
|
|
176
|
+
ts_cache[entry_file] = last_modified
|
|
177
|
+
modified
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# evaluates the given rb file as a module and returns: { commands: COMMANDS, variables: VARIABLES }
|
|
181
|
+
def self.eval_rb_defs(file_path)
|
|
182
|
+
mod = Module.new
|
|
183
|
+
mod.module_eval(File.read(file_path), file_path)
|
|
184
|
+
{
|
|
185
|
+
commands: mod.const_defined?(:COMMANDS) ? mod.const_get(:COMMANDS) : {},
|
|
186
|
+
variables: mod.const_defined?(:VARIABLES) ? mod.const_get(:VARIABLES) : {}
|
|
187
|
+
}
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# evaluates the given ncpp file and returns: { commands: COMMANDS, variables: VARIABLES }
|
|
191
|
+
def self.eval_ncpp_defs(file_path, extra_cmds, extra_vars, safe)
|
|
192
|
+
interpreter = NCPPFileInterpreter.new($config['command_prefix'], extra_cmds, extra_vars, safe: safe)
|
|
193
|
+
interpreter.run(file_path)
|
|
194
|
+
{ commands: interpreter.get_new_commands, variables: interpreter.get_new_variables }
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def self.run(args)
|
|
198
|
+
ncpp_filename = nil
|
|
199
|
+
config_filename = nil
|
|
200
|
+
interactive = false
|
|
201
|
+
ncpp_script = false
|
|
202
|
+
quiet = false
|
|
203
|
+
debug = false
|
|
204
|
+
show_rom_info = false
|
|
205
|
+
safe_mode = false
|
|
206
|
+
puritan_mode = false
|
|
207
|
+
no_cache = false
|
|
208
|
+
no_cache_pass = false
|
|
209
|
+
clear_gen = false
|
|
210
|
+
|
|
211
|
+
OptionParser.new do |opts|
|
|
212
|
+
opts.on('--run FILE', 'Specify an NCPP script file to run') do |f|
|
|
213
|
+
ncpp_filename = f
|
|
214
|
+
ncpp_script = true
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
opts.on('--config FILE', 'Specify a config file (defaults to ncpp_config.json)') do |f|
|
|
218
|
+
config_filename = f
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
opts.on('--interactive', '--repl', 'Run the Read-Eval-Print Loop interpreter') do
|
|
222
|
+
interactive = true
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
opts.on('-q', '--quiet', '--sybau', 'Don\'t print parsing info') do
|
|
226
|
+
quiet = true
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
opts.on('-d', '--debug', 'Enable debug info printing') do
|
|
230
|
+
debug = true
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
opts.on('--safe', 'Run interpreter in safe mode to disable the execution of inline Ruby code') do
|
|
234
|
+
safe_mode = true
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
opts.on('--puritanism', 'Run interpreter in puritan mode to disable the execution of impure expressions') do
|
|
238
|
+
puritan_mode = true
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
opts.on('--no-cache', 'Disable interpreter runtime command caching') do
|
|
242
|
+
no_cache = true
|
|
243
|
+
no_cache_pass = true
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
opts.on('--no-cache-pass', 'Disable the passing of command cache between preprocessor interpreter instances') do
|
|
247
|
+
no_cache_pass = true
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
opts.on('--clear-gen', 'Force all preprocessed files in gen folder to be regenerated') do
|
|
251
|
+
clear_gen = true
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
opts.on('--show-rom-info', 'Show ROM info on startup') do
|
|
255
|
+
show_rom_info = true
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
opts.on('--remove', 'Removes NCPrePatcher from your project') do
|
|
259
|
+
uninstall
|
|
260
|
+
exit
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
opts.on('-v', '--version', 'Show NCPrePatcher version') do
|
|
264
|
+
puts VERSION
|
|
265
|
+
exit
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
opts.on('-h', '--help', 'Show this help message') do
|
|
269
|
+
puts opts
|
|
270
|
+
exit
|
|
271
|
+
end
|
|
272
|
+
end.parse!(args)
|
|
273
|
+
|
|
274
|
+
ncp_project = File.exist? NCP_CONFIG_FILE_PATH
|
|
275
|
+
|
|
276
|
+
if !ncp_project && !interactive && !ncpp_script
|
|
277
|
+
puts "In preprocessor mode, NCPrePatcher must be run in a directory with an #{NCP_CONFIG_FILE_PATH.bold_red} "\
|
|
278
|
+
"file."
|
|
279
|
+
exit(1)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
if config_filename
|
|
283
|
+
init(config_filename)
|
|
284
|
+
elsif ncp_project
|
|
285
|
+
init
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
show_rom_info($rom) if show_rom_info && !$rom.nil?
|
|
289
|
+
|
|
290
|
+
if ncpp_script
|
|
291
|
+
interpreter = NCPPFileInterpreter.new($config.nil? ? COMMAND_PREFIX : $config['command_prefix'], safe: safe_mode,
|
|
292
|
+
no_cache: no_cache)
|
|
293
|
+
exit_code = interpreter.run(ncpp_filename, debug: debug)
|
|
294
|
+
exit(exit_code)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
if interactive
|
|
298
|
+
REPL.new(safe: safe_mode, puritan: puritan_mode, no_cache: no_cache).run(debug: debug)
|
|
299
|
+
exit
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
ncp_cfg = JSON.load_file(NCP_CONFIG_FILE_PATH)
|
|
303
|
+
root_dir = Pathname.new(File.dirname(NCP_CONFIG_FILE_PATH))
|
|
304
|
+
code_root_dir = Pathname.new(File.dirname(ncp_cfg['arm9']['target']))
|
|
305
|
+
|
|
306
|
+
Dir.chdir(code_root_dir.relative_path_from(root_dir))
|
|
307
|
+
|
|
308
|
+
timestamp_cache_path = File.join($config['gen_path'], 'timestamp_cache.json')
|
|
309
|
+
cache_exists = File.exist?(timestamp_cache_path)
|
|
310
|
+
|
|
311
|
+
if clear_gen && cache_exists
|
|
312
|
+
File.delete(timestamp_cache_path)
|
|
313
|
+
cache_exists = false
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
timestamp_cache = cache_exists ? JSON.load_file(timestamp_cache_path) : {}
|
|
317
|
+
|
|
318
|
+
if timestamp_cache['NCPP_VERSION'] != VERSION
|
|
319
|
+
timestamp_cache = {}
|
|
320
|
+
else
|
|
321
|
+
timestamp_cache.delete('NCPP_VERSION')
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
exts = $config['source_file_types'].join(',')
|
|
325
|
+
|
|
326
|
+
success = true
|
|
327
|
+
parsed_file_count = 0
|
|
328
|
+
lines_parsed = 0
|
|
329
|
+
start_time = Time.now
|
|
330
|
+
|
|
331
|
+
$config['sources'].each do |src|
|
|
332
|
+
extra_commands = {}
|
|
333
|
+
extra_variables = {}
|
|
334
|
+
command_cache = {}
|
|
335
|
+
|
|
336
|
+
defs_modified = false
|
|
337
|
+
|
|
338
|
+
unless puritan_mode # read ncpp_global/defs files
|
|
339
|
+
|
|
340
|
+
rb_def_files = [
|
|
341
|
+
File.join(src.sub(/^\/|\/$/, '').split('/').first, NCPP_GLB_DEFS_FILENAME+'.rb'),
|
|
342
|
+
File.join(src.sub('*', ''), NCPP_DEFS_FILENAME+'.rb'),
|
|
343
|
+
]
|
|
344
|
+
|
|
345
|
+
if !safe_mode
|
|
346
|
+
rb_def_files.each do |file|
|
|
347
|
+
next unless File.exist?(file)
|
|
348
|
+
defs_modified = update_ts_cache_entry(timestamp_cache, file)
|
|
349
|
+
defs = eval_rb_defs(file)
|
|
350
|
+
extra_commands.merge!(defs[:commands])
|
|
351
|
+
extra_variables.merge!(defs[:variables])
|
|
352
|
+
end
|
|
353
|
+
else
|
|
354
|
+
rb_def_files.each do |file|
|
|
355
|
+
next unless File.exist?(file)
|
|
356
|
+
Utils.print_warning "'#{file}' is ignored in safe mode"
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
ncpp_def_files = rb_def_files.map { "#{it[..-4]}.ncpp" }
|
|
361
|
+
ncpp_def_files.each do |file|
|
|
362
|
+
next unless File.exist?(file)
|
|
363
|
+
defs_modified = update_ts_cache_entry(timestamp_cache, file)
|
|
364
|
+
defs = eval_ncpp_defs(file, extra_commands, extra_variables, safe_mode)
|
|
365
|
+
extra_commands.merge!(defs[:commands])
|
|
366
|
+
extra_variables.merge!(defs[:variables])
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
if File.file?(src)
|
|
372
|
+
files = [src]
|
|
373
|
+
else
|
|
374
|
+
if src.end_with?('/*')
|
|
375
|
+
base = src[0...-2] # drop trailing "/*"
|
|
376
|
+
pattern = File.join(base, '**', "*.{#{exts}}") # recursive directory search
|
|
377
|
+
else
|
|
378
|
+
base = src
|
|
379
|
+
pattern = File.join(base, "*.{#{exts}}")
|
|
380
|
+
end
|
|
381
|
+
files = Dir.glob(pattern)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
timestamp_cache.delete_if do |file, _mtime|
|
|
385
|
+
if !File.exist?(file)
|
|
386
|
+
File.delete(File.join($config['gen_path'], file))
|
|
387
|
+
true
|
|
388
|
+
else
|
|
389
|
+
false
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
files.delete_if do |file|
|
|
394
|
+
last_modified = File.mtime(file).to_s
|
|
395
|
+
modified = !timestamp_cache[file]&.eql?(last_modified)
|
|
396
|
+
timestamp_cache[file] = last_modified
|
|
397
|
+
if file.end_with?('.s')
|
|
398
|
+
if modified || modified.nil?
|
|
399
|
+
dest = File.join($config['gen_path'], file)
|
|
400
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
|
401
|
+
FileUtils.cp(file, dest)
|
|
402
|
+
end
|
|
403
|
+
true
|
|
404
|
+
elsif !modified && !defs_modified
|
|
405
|
+
true
|
|
406
|
+
else
|
|
407
|
+
false
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
parsed_file_count += files.count
|
|
412
|
+
|
|
413
|
+
files.each do |file|
|
|
414
|
+
interpreter = CFileInterpreter.new(
|
|
415
|
+
file, $config['gen_path'], $config['command_prefix'], extra_commands, extra_variables,
|
|
416
|
+
safe: safe_mode, puritan: puritan_mode, no_cache: no_cache, cmd_cache: no_cache_pass ? {} : command_cache
|
|
417
|
+
)
|
|
418
|
+
interpreter.run(verbose: !quiet, debug: debug)
|
|
419
|
+
lines_parsed += interpreter.lines_parsed
|
|
420
|
+
|
|
421
|
+
command_cache.merge!(interpreter.get_cacheable_cache) unless no_cache_pass
|
|
422
|
+
|
|
423
|
+
unless interpreter.incomplete_files.empty?
|
|
424
|
+
timestamp_cache.delete(file)
|
|
425
|
+
success = false
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# interpreter = CFileInterpreter.new(
|
|
430
|
+
# files, $config['gen_path'], $config['command_prefix'], extra_commands, extra_variables,
|
|
431
|
+
# safe: safe_mode, puritan: puritan_mode
|
|
432
|
+
# )
|
|
433
|
+
# interpreter.run(verbose: !quiet)
|
|
434
|
+
# lines_parsed += interpreter.lines_parsed
|
|
435
|
+
|
|
436
|
+
# unless interpreter.incomplete_files.empty?
|
|
437
|
+
# interpreter.incomplete_files.each do |file|
|
|
438
|
+
# timestamp_cache.delete(file)
|
|
439
|
+
# success = false
|
|
440
|
+
# end
|
|
441
|
+
# end
|
|
442
|
+
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
timestamp_cache['NCPP_VERSION'] = VERSION
|
|
446
|
+
|
|
447
|
+
FileUtils.mkdir_p(File.dirname(timestamp_cache_path))
|
|
448
|
+
File.write(timestamp_cache_path, JSON.generate(timestamp_cache))
|
|
449
|
+
|
|
450
|
+
# FileUtils.mkdir_p(File.dirname(cmd_cache_path))
|
|
451
|
+
# File.write(cmd_cache_path, JSON.generate(command_cache))
|
|
452
|
+
|
|
453
|
+
unless quiet
|
|
454
|
+
if lines_parsed > 0
|
|
455
|
+
msg = "\nParsed #{lines_parsed} line#{'s' if lines_parsed != 1} across " \
|
|
456
|
+
"#{parsed_file_count} file#{'s' if parsed_file_count != 1}."
|
|
457
|
+
puts (success ? msg.green : msg.yellow)
|
|
458
|
+
if success
|
|
459
|
+
puts "Took ".green + String(Time.now - start_time).underline_green + " seconds.".green
|
|
460
|
+
else
|
|
461
|
+
puts "Took ".yellow + String(Time.now - start_time).underline_yellow + " seconds.".yellow
|
|
462
|
+
end
|
|
463
|
+
else
|
|
464
|
+
puts "Nothing to parse.".green
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
puts
|
|
469
|
+
ARGV.clear
|
|
470
|
+
|
|
471
|
+
unless success
|
|
472
|
+
puts 'NCPrePatcher execution was not successful.'.bold_red
|
|
473
|
+
exit(1)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
end
|
|
Binary file
|