excel_to_code 0.2.30 → 0.3.1
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 +4 -4
- data/bin/excel_to_c +16 -0
- data/src/commands/excel_to_c.rb +104 -44
- data/src/excel_to_code.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf2febec784c194d3e592c78776f535a15458009
|
4
|
+
data.tar.gz: 9e9a0c83fe42ba73acc0d0b579197194a0ee786b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b141c54fa32c28b2d320885323c7ebf77f941758d07996e5fe435354c1f1d8c1cc3928ebc22f27c2051e31f46a28f6bc86a576696651704a39f6206b429f79c9
|
7
|
+
data.tar.gz: 7eaac74f6bb96cb5c00537b018d80b925f72704545be91e0d83c7e03e9e3cf8c6996cfa1efd8174871d26fe7fa311b293c4bbcb83feb38e6235f327a3b028cbd
|
data/bin/excel_to_c
CHANGED
@@ -57,7 +57,23 @@ END
|
|
57
57
|
command.should_inline_formulae_that_are_only_used_once = false
|
58
58
|
command.extract_repeated_parts_of_formulae = false
|
59
59
|
end
|
60
|
+
|
61
|
+
opts.on('--makefile', 'Generate a makefile') do
|
62
|
+
command.create_makefile = true
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on('--no-makefile', 'Do not generate a makefile (default)') do
|
66
|
+
command.create_makefile = false
|
67
|
+
end
|
60
68
|
|
69
|
+
opts.on('--rakefile', 'Generate a rakefile (default)') do
|
70
|
+
command.create_rakefile = true
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on('--no-rakefile', 'Do not generate a rakefile') do
|
74
|
+
command.create_rakefile = false
|
75
|
+
end
|
76
|
+
|
61
77
|
opts.on("-h", "--help", "Show this message") do
|
62
78
|
puts opts
|
63
79
|
exit
|
data/src/commands/excel_to_c.rb
CHANGED
@@ -3,7 +3,18 @@ require_relative 'excel_to_x'
|
|
3
3
|
require 'ffi'
|
4
4
|
|
5
5
|
class ExcelToC < ExcelToX
|
6
|
+
|
7
|
+
# If true, creates a Rakefile, if false, doesn't (default true)
|
8
|
+
attr_accessor :create_rakefile
|
9
|
+
# If true, creates a Makefile, if false, doesn't (default false)
|
10
|
+
attr_accessor :create_makefile
|
6
11
|
|
12
|
+
def set_defaults
|
13
|
+
super
|
14
|
+
@create_rakefile = true if @create_rakefile == nil
|
15
|
+
@create_makefile = false if @create_makefile == nil
|
16
|
+
end
|
17
|
+
|
7
18
|
def language
|
8
19
|
"c"
|
9
20
|
end
|
@@ -98,28 +109,75 @@ class ExcelToC < ExcelToX
|
|
98
109
|
# is set properly
|
99
110
|
def write_build_script
|
100
111
|
log.info "Writing Build script"
|
112
|
+
write_makefile if create_makefile
|
113
|
+
write_rakefile if create_rakefile
|
114
|
+
end
|
115
|
+
|
116
|
+
def write_makefile
|
117
|
+
log.info "Writing Makefile"
|
101
118
|
|
102
|
-
o = output("Makefile")
|
103
119
|
name = output_name.downcase
|
104
|
-
|
120
|
+
o = output("Makefile")
|
121
|
+
|
105
122
|
# Target for shared library
|
106
123
|
shared_library_name = FFI.map_library_name(name)
|
107
124
|
o.puts "#{shared_library_name}: #{name}.o"
|
108
125
|
o.puts "\tgcc -shared -o #{shared_library_name} #{name}.o"
|
109
126
|
o.puts
|
110
|
-
|
127
|
+
|
111
128
|
# Target for compiled version
|
112
129
|
o.puts "#{name}.o:"
|
113
130
|
o.puts "\tgcc -fPIC -c #{name}.c"
|
114
131
|
o.puts
|
115
|
-
|
132
|
+
|
116
133
|
# Target for cleaning
|
117
134
|
o.puts "clean:"
|
118
135
|
o.puts "\trm #{name}.o"
|
119
136
|
o.puts "\trm #{shared_library_name}"
|
120
|
-
|
137
|
+
|
121
138
|
close(o)
|
122
139
|
end
|
140
|
+
|
141
|
+
def write_rakefile
|
142
|
+
log.info "Writing Rakefile"
|
143
|
+
|
144
|
+
o = output("Rakefile")
|
145
|
+
name = output_name.downcase
|
146
|
+
o.puts "require 'ffi'"
|
147
|
+
o.puts
|
148
|
+
|
149
|
+
o.puts "this_directory = File.dirname(__FILE__)"
|
150
|
+
o.puts
|
151
|
+
o.puts "COMPILER = 'gcc'"
|
152
|
+
o.puts "COMPILE_FLAGS = '-fPIC'"
|
153
|
+
o.puts "SHARED_LIBRARY_FLAGS = '-shared -fPIC'"
|
154
|
+
o.puts
|
155
|
+
|
156
|
+
o.puts "OUTPUT = FFI.map_library_name '#{name}'"
|
157
|
+
o.puts "OUTPUT_DIR = this_directory"
|
158
|
+
o.puts "SOURCE = '#{name}.c'"
|
159
|
+
o.puts "OBJECT = '#{name}.o'"
|
160
|
+
o.puts
|
161
|
+
|
162
|
+
o.puts "task :default => [:build]"
|
163
|
+
o.puts
|
164
|
+
o.puts "desc 'Build the 2050 model, then install it'"
|
165
|
+
o.puts "task :build => [OUTPUT]"
|
166
|
+
o.puts
|
167
|
+
|
168
|
+
o.puts "file OUTPUT => OBJECT do"
|
169
|
+
o.puts ' puts "Turning #{OBJECT} and putting it in #{OUTPUT_DIR} as #{OUTPUT}"'
|
170
|
+
o.puts ' puts "Note that this is a really large c file, it may take tens of minutes to compile."'
|
171
|
+
o.puts ' sh "#{COMPILER} #{SHARED_LIBRARY_FLAGS} -o #{File.join(OUTPUT_DIR,OUTPUT)} #{OBJECT}"'
|
172
|
+
o.puts 'end'
|
173
|
+
o.puts
|
174
|
+
|
175
|
+
o.puts 'file OBJECT => SOURCE do'
|
176
|
+
o.puts ' puts "Building #{SOURCE}"'
|
177
|
+
o.puts ' puts "Note that this is a really large c file, it may take tens of minutes to compile."'
|
178
|
+
o.puts ' sh "#{COMPILER} #{COMPILE_FLAGS} -o #{OBJECT} -c #{SOURCE}"'
|
179
|
+
o.puts 'end'
|
180
|
+
end
|
123
181
|
|
124
182
|
def write_fuby_ffi_interface
|
125
183
|
log.info "Writing ruby FFI code"
|
@@ -131,7 +189,7 @@ class ExcelToC < ExcelToX
|
|
131
189
|
require 'ffi'
|
132
190
|
require 'singleton'
|
133
191
|
|
134
|
-
class #{ruby_module_name}
|
192
|
+
class #{ruby_module_name}
|
135
193
|
|
136
194
|
# WARNING: this is not thread safe
|
137
195
|
def initialize
|
@@ -139,7 +197,7 @@ class #{ruby_module_name}Shim
|
|
139
197
|
end
|
140
198
|
|
141
199
|
def reset
|
142
|
-
|
200
|
+
C.reset
|
143
201
|
end
|
144
202
|
|
145
203
|
def method_missing(name, *arguments)
|
@@ -153,8 +211,8 @@ class #{ruby_module_name}Shim
|
|
153
211
|
end
|
154
212
|
|
155
213
|
def get(name)
|
156
|
-
return 0 unless
|
157
|
-
ruby_value_from_excel_value(
|
214
|
+
return 0 unless C.respond_to?(name)
|
215
|
+
ruby_value_from_excel_value(C.send(name))
|
158
216
|
end
|
159
217
|
|
160
218
|
def ruby_value_from_excel_value(excel_value)
|
@@ -167,11 +225,11 @@ class #{ruby_module_name}Shim
|
|
167
225
|
r = excel_value[:rows]
|
168
226
|
c = excel_value[:columns]
|
169
227
|
p = excel_value[:array]
|
170
|
-
s =
|
228
|
+
s = C::ExcelValue.size
|
171
229
|
a = Array.new(r) { Array.new(c) }
|
172
230
|
(0...r).each do |row|
|
173
231
|
(0...c).each do |column|
|
174
|
-
a[row][column] = ruby_value_from_excel_value(
|
232
|
+
a[row][column] = ruby_value_from_excel_value(C::ExcelValue.new(p + (((row*c)+column)*s)))
|
175
233
|
end
|
176
234
|
end
|
177
235
|
return a
|
@@ -184,11 +242,11 @@ class #{ruby_module_name}Shim
|
|
184
242
|
def set(name, ruby_value)
|
185
243
|
name = name.to_s
|
186
244
|
name = "set_\#{name[0..-2]}" if name.end_with?('=')
|
187
|
-
return false unless
|
188
|
-
|
245
|
+
return false unless C.respond_to?(name)
|
246
|
+
C.send(name, excel_value_from_ruby_value(ruby_value))
|
189
247
|
end
|
190
248
|
|
191
|
-
def excel_value_from_ruby_value(ruby_value, excel_value =
|
249
|
+
def excel_value_from_ruby_value(ruby_value, excel_value = C::ExcelValue.new)
|
192
250
|
case ruby_value
|
193
251
|
when Numeric
|
194
252
|
excel_value[:type] = :ExcelNumber
|
@@ -212,10 +270,10 @@ class #{ruby_module_name}Shim
|
|
212
270
|
excel_value[:columns] = ruby_value.size
|
213
271
|
end
|
214
272
|
ruby_values = ruby_value.flatten
|
215
|
-
pointer = FFI::MemoryPointer.new(
|
273
|
+
pointer = FFI::MemoryPointer.new(C::ExcelValue, ruby_values.size)
|
216
274
|
excel_value[:array] = pointer
|
217
275
|
ruby_values.each.with_index do |v,i|
|
218
|
-
excel_value_from_ruby_value(v,
|
276
|
+
excel_value_from_ruby_value(v, C::ExcelValue.new(pointer[i]))
|
219
277
|
end
|
220
278
|
when Symbol
|
221
279
|
excel_value[:type] = :ExcelError
|
@@ -226,28 +284,26 @@ class #{ruby_module_name}Shim
|
|
226
284
|
excel_value
|
227
285
|
end
|
228
286
|
|
229
|
-
end
|
230
|
-
|
231
287
|
|
232
|
-
module
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
288
|
+
module C
|
289
|
+
extend FFI::Library
|
290
|
+
ffi_lib File.join(File.dirname(__FILE__),FFI.map_library_name('#{name}'))
|
291
|
+
ExcelType = enum :ExcelEmpty, :ExcelNumber, :ExcelString, :ExcelBoolean, :ExcelError, :ExcelRange
|
292
|
+
|
293
|
+
class ExcelValue < FFI::Struct
|
294
|
+
layout :type, ExcelType,
|
295
|
+
:number, :double,
|
296
|
+
:string, :pointer,
|
297
|
+
:array, :pointer,
|
298
|
+
:rows, :int,
|
299
|
+
:columns, :int
|
300
|
+
end
|
245
301
|
|
246
302
|
END
|
247
303
|
o.puts code
|
248
304
|
o.puts
|
249
|
-
o.puts "
|
250
|
-
o.puts "
|
305
|
+
o.puts " # use this function to reset all cell values"
|
306
|
+
o.puts " attach_function 'reset', [], :void"
|
251
307
|
|
252
308
|
|
253
309
|
worksheets do |name, xml_filename|
|
@@ -258,7 +314,7 @@ END
|
|
258
314
|
if settable_refs
|
259
315
|
settable_refs = @formulae.keys.select { |k| k.first == name }.map { |k| k.last } if settable_refs == :all
|
260
316
|
settable_refs.each do |ref|
|
261
|
-
o.puts "
|
317
|
+
o.puts " attach_function 'set_#{c_name}_#{ref.downcase}', [ExcelValue.by_value], :void"
|
262
318
|
end
|
263
319
|
end
|
264
320
|
|
@@ -272,26 +328,27 @@ END
|
|
272
328
|
end
|
273
329
|
|
274
330
|
getable_refs.each do |ref|
|
275
|
-
o.puts "
|
331
|
+
o.puts " attach_function '#{c_name}_#{ref.downcase}', [], ExcelValue.by_value"
|
276
332
|
end
|
277
333
|
|
278
|
-
o.puts "
|
334
|
+
o.puts " # end of #{name}"
|
279
335
|
end
|
280
336
|
|
281
|
-
o.puts "
|
337
|
+
o.puts " # Start of named references"
|
282
338
|
# Getters
|
283
339
|
@named_references_to_keep.each do |name|
|
284
|
-
o.puts "
|
340
|
+
o.puts " attach_function '#{c_name_for(name)}', [], ExcelValue.by_value"
|
285
341
|
end
|
286
342
|
|
287
343
|
# Setters
|
288
344
|
@named_references_that_can_be_set_at_runtime.each do |name|
|
289
|
-
o.puts "
|
345
|
+
o.puts " attach_function 'set_#{c_name_for(name)}', [ExcelValue.by_value], :void"
|
290
346
|
end
|
291
347
|
|
292
|
-
o.puts "
|
348
|
+
o.puts " # End of named references"
|
293
349
|
|
294
|
-
o.puts "end"
|
350
|
+
o.puts " end # C module"
|
351
|
+
o.puts "end # #{ruby_module_name}"
|
295
352
|
close(o)
|
296
353
|
end
|
297
354
|
|
@@ -311,7 +368,7 @@ END
|
|
311
368
|
o.puts " methods = methods_matching(/^test_/)"
|
312
369
|
o.puts " end"
|
313
370
|
o.puts " def worksheet; @worksheet ||= init_spreadsheet; end"
|
314
|
-
o.puts " def init_spreadsheet; #{ruby_module_name}
|
371
|
+
o.puts " def init_spreadsheet; #{ruby_module_name}.new end"
|
315
372
|
|
316
373
|
CompileToCUnitTest.rewrite(Hash[@references_to_test_array], sloppy_tests, @worksheet_c_names, @constants, o)
|
317
374
|
o.puts "end"
|
@@ -321,8 +378,11 @@ END
|
|
321
378
|
|
322
379
|
def compile_code
|
323
380
|
return unless actually_compile_code || actually_run_tests
|
324
|
-
|
325
|
-
|
381
|
+
name = output_name.downcase
|
382
|
+
log.info "Compiling"
|
383
|
+
puts `cd #{output_directory}`
|
384
|
+
puts `gcc -fPIC -o #{name}.o -c #{name}.c`
|
385
|
+
puts `gcc -shared -fPIC -o #{FFI.map_library_name(name)} #{name}.o`
|
326
386
|
end
|
327
387
|
|
328
388
|
def run_tests
|
data/src/excel_to_code.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: excel_to_code
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Counsell, Green on Black Ltd
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubypeg
|