gap50 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ module Gap
2
+ class DLLFunction
3
+ def initialize(path, name)
4
+ @path = path
5
+ @name = name
6
+ end
7
+
8
+ def call(*args)
9
+ param = args.map do |x|
10
+ case x
11
+ when Integer
12
+ "L"
13
+ else
14
+ "p"
15
+ end
16
+ end
17
+ begin
18
+ Win32API.new(@path, @name, param, "L").call(*args)
19
+ rescue LoadError
20
+ Win32API.new(File.expand_path(@path), @name, param, "L").call(*args)
21
+ end
22
+ end
23
+ end
24
+
25
+ class DLL
26
+ def initialize(filename, sam = Gap::Main, &block)
27
+ @sam = sam
28
+ @filename = filename
29
+ @realpath = @sam.genfile(@filename, &block).tr("/", "\\")
30
+ end
31
+
32
+ def [](name)
33
+ DLLFunction.new @realpath, name
34
+ end
35
+
36
+ def method_missing(sym, *args)
37
+ self[sym.to_s].call(*args)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,39 @@
1
+ module Gap
2
+ class Exec
3
+ def initialize(sam = Gap::Main)
4
+ @sam = sam
5
+ end
6
+
7
+ def exec(cmdline, input)
8
+ md5 = MD5.hexdigest(cmdline) + MD5.hexdigest(input)
9
+ inputfile = _file md5, ".input"
10
+ outputfile = _file md5, ".output"
11
+ outf = md5 + ".output"
12
+ key = [Samsara::Meta.new(:Exec), outf]
13
+ @sam.gen key do
14
+ @sam.writefile inputfile, input
15
+ system "#{cmdline} < #{inputfile} > #{outputfile}"
16
+ @sam.readfile outputfile
17
+ end
18
+ end
19
+
20
+ def marshal(cmdline, input)
21
+ Marshal.load exec(cmdline, input)
22
+ end
23
+
24
+ DEFAULT_EXEC = Exec.new
25
+ def self.exec(*a)
26
+ DEFAULT_EXEC.exec(*a)
27
+ end
28
+
29
+ def self.marshal(*a)
30
+ DEFAULT_EXEC.marshal(*a)
31
+ end
32
+
33
+ private
34
+ def _file(name, ext = "")
35
+ "temp/exec_" << name << ext
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module Gap
2
+ Main = Samsara.new "main.sam"
3
+ end
@@ -0,0 +1,96 @@
1
+ module Gap
2
+ class Require
3
+ def initialize(sam = Gap::Main, strict = true)
4
+ @strict = strict
5
+ @sam = sam
6
+ end
7
+
8
+ def require(*args)
9
+ if @strict
10
+ args.each{|x|
11
+ _require_strict x
12
+ }
13
+ else
14
+ args.each{|x|
15
+ _require x
16
+ }
17
+ end
18
+ ensure
19
+ $@.replace caller if $@
20
+ end
21
+
22
+ ORIGIN = Kernel.method(:require)
23
+ INSTANCE_ORIGIN = Kernel.instance_method(:require)
24
+ DEFAULT_REQUIRE = Require.new
25
+ REQUIRE_STACK = [[INSTANCE_ORIGIN, Kernel]]
26
+
27
+
28
+ def replace_kernel!
29
+ that = self
30
+ REQUIRE_STACK.push [self.class.instance_method(:require), self]
31
+ _fix_kernel
32
+ ensure
33
+ $@.replace caller if $@
34
+ end
35
+
36
+ def back_require!
37
+ REQUIRE_STACK.pop
38
+ _fix_kernel
39
+ ensure
40
+ $@.replace caller if $@
41
+ end
42
+
43
+ def use_kernel!
44
+ Kernel.send :define_method, INSTANCE_ORIGIN
45
+ ensure
46
+ $@.replace caller if $@
47
+ end
48
+
49
+ private
50
+ def _require(a)
51
+ ORIGIN.call a
52
+ rescue
53
+ if ex.to_s =~ /^LoadError: .*? -- (.*)$/
54
+ file = $1
55
+ path = "./" + @sam.genfile(file)
56
+ ORIGIN.call path
57
+ else
58
+ raise ArgumentError, "Can't load #{a}"
59
+ end
60
+ end
61
+
62
+ def _require_strict(file)
63
+ [file, file + ".rb"].each{|x|
64
+ begin
65
+ if @sam.has_file_in?(x)
66
+ path = "./" + @sam.genfile(x)
67
+ return ORIGIN.call path
68
+ end
69
+ rescue LoadError
70
+ ensure
71
+ $@.replace caller if $@
72
+ end
73
+ }
74
+ ORIGIN.call file
75
+ ensure
76
+ $@.replace caller if $@
77
+ end
78
+
79
+ def _fix_kernel
80
+ if REQUIRE_STACK[-1]
81
+ m, o = REQUIRE_STACK[-1]
82
+ if o == Kernel
83
+ use_kernel!
84
+ else
85
+ Kernel.send :define_method, :require do |*args|
86
+ m.bind(o).call(*args)
87
+ end
88
+ end
89
+ else
90
+ use_kernel!
91
+ end
92
+ ensure
93
+ $@.replace caller if $@
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,9 @@
1
+ require "gap50/version"
2
+ require 'gap50/preload'
3
+ require 'gap50/cache'
4
+ require 'gap50/samsara'
5
+ require 'gap50/gap'
6
+ require 'gap50/ext'
7
+ module Gap50
8
+ # Your code goes here...
9
+ end
@@ -0,0 +1,12 @@
1
+ begin
2
+ Win32API
3
+ rescue NameError
4
+ require 'win32api'
5
+ end
6
+
7
+ begin
8
+ Zlib
9
+ rescue NameError
10
+ require 'zlib'
11
+ end
12
+
@@ -0,0 +1,4 @@
1
+ require 'gap50/samsara/md5.rb'
2
+ require 'gap50/samsara/random.rb'
3
+ require 'gap50/samsara/maker.rb'
4
+ require 'gap50/samsara/samsara.rb'
@@ -0,0 +1,113 @@
1
+ module Gap
2
+ class Maker
3
+ RND = Random.new
4
+ attr_accessor :temp, :sam
5
+
6
+
7
+ def initialize(sam = nil, temp = genname, &block)
8
+ @sam = sam
9
+ @temp = temp
10
+ if defined? instance_exec
11
+ transaction do |m|
12
+ instance_exec &block
13
+ end
14
+ else
15
+ transaction do |m|
16
+ instance_eval &block
17
+ end
18
+ end
19
+ end
20
+
21
+ def path(name)
22
+ @temp + "/" + name
23
+ end
24
+
25
+ def readfile(name)
26
+ @sam.readfile path(name)
27
+ end
28
+
29
+ def writefile(name, value)
30
+ @sam.writefile path(name), value
31
+ end
32
+
33
+ def copyfile(src, dest)
34
+ writefile dest, @sam.readfile(src)
35
+ end
36
+
37
+ def exec(cmd)
38
+ system "cd #{@temp} && #{cmd}"
39
+ end
40
+
41
+ def transaction
42
+ _create
43
+ ret = yield self
44
+ _import_all
45
+ _cleanup
46
+ ret
47
+ end
48
+
49
+ def asBase64
50
+ _import_all
51
+ @sam.toBase64
52
+ end
53
+
54
+ def asMarshal
55
+ _import_all
56
+ @sam.toMarshal
57
+ end
58
+
59
+ def genlib(name, text)
60
+ writefile "cpp/#{name}.cpp", %{#define GAPI(type) extern "C" type __stdcall
61
+ #{text}
62
+ }
63
+ exec "g++ cpp/#{name}.cpp -o cpp/#{name}.dll -static -s -shared -m32 -Wl,-add-stdcall-alias"
64
+ end
65
+
66
+ def from(name)
67
+ @sam = Samsara.new name
68
+ _export_all
69
+ end
70
+
71
+ alias COPY copyfile
72
+ alias WRITE writefile
73
+ alias READ readfile
74
+ alias RUN exec
75
+ alias FROM from
76
+ alias CXX genlib
77
+ private
78
+ def _export_all
79
+ @sam.each{|k, v|
80
+ if k[0] == Samsara::MetaFile
81
+ @sam.export k[1], @temp
82
+ end
83
+ }
84
+ end
85
+
86
+ def _import_all
87
+ len = @temp.length + 1
88
+ Dir.glob(@temp + "/**/*") do |f|
89
+ next if FileTest.directory?(f)
90
+ name = f[len..-1]
91
+ @sam.import name, @temp
92
+ end
93
+ end
94
+
95
+ def _cleanup
96
+ @sam.rmdir_p(@temp)
97
+ end
98
+
99
+ def _create
100
+ if !FileTest.directory?(temp)
101
+ Dir.mkdir temp
102
+ end
103
+ end
104
+
105
+ def genname
106
+ while 0
107
+ name = "temp-#{RND.hex(16)}"
108
+ return name if !FileTest.exists?(name)
109
+ end
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,44 @@
1
+ module Gap
2
+ MD5_INIT = Win32API.new("ADVAPI32", "MD5Init", "p", "L")
3
+ MD5_UPDATE = Win32API.new("ADVAPI32", "MD5Update", "ppL", "L")
4
+ MD5_FINAL = Win32API.new("ADVAPI32", "MD5Final", "p", "L")
5
+ class MD5
6
+ def initialize
7
+ @ctx = "\0" * 128 # buf
8
+ MD5_INIT.call(@ctx)
9
+ end
10
+
11
+ def update(str)
12
+ MD5_UPDATE.call(@ctx, str, str.unpack("C*").size)
13
+ end
14
+
15
+ def digest
16
+ MD5_FINAL.call(@ctx)
17
+ @ctx[88, 16]
18
+ end
19
+
20
+ def self.digest(a)
21
+ x = MD5.new
22
+ x.update a
23
+ x.digest
24
+ end
25
+
26
+ def self.hexdigest(a)
27
+ digest(a).unpack("H*").first
28
+ end
29
+
30
+ def self.file(fn)
31
+ open(fn, 'rb') do |f|
32
+ x = MD5.new
33
+ while (r = f.read(10240))
34
+ x.update(r)
35
+ end
36
+ x.digest
37
+ end
38
+ end
39
+
40
+ def self.filehex(fn)
41
+ file(fn).unpack("H*").first
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,53 @@
1
+ module Gap
2
+ CR_ACQUIRE = Win32API.new("ADVAPI32", "CryptAcquireContext", "pLLLL", "L")
3
+ CR_GENRANDOM = Win32API.new("ADVAPI32", "CryptGenRandom", "LLp", "L")
4
+ CR_RELEASE = Win32API.new("ADVAPI32", "CryptReleaseContext", "LL", "L")
5
+ class Random
6
+ REG = {}
7
+ def self.auto_release_proc
8
+ proc{|id|
9
+ if REG.include? id
10
+ _dispose REG[id]
11
+ REG.delete id
12
+ end
13
+ }
14
+ end
15
+
16
+ def self.register_auto_release(id, ptr)
17
+ REG[object_id] = ptr
18
+ ObjectSpace.define_finalizer self, auto_release_proc
19
+ end
20
+
21
+ def initialize
22
+ buf = "\0" * 4
23
+ CR_ACQUIRE.call buf, 0, 0, 1, -268435456
24
+ @ptr, = buf.unpack("L")
25
+ self.class.register_auto_release object_id, @ptr
26
+ end
27
+
28
+ def bytes(len = 16)
29
+ buf = "\0" * len
30
+ CR_GENRANDOM.call @ptr, len, buf
31
+ buf
32
+ end
33
+
34
+ def hex(len = 16)
35
+ bytes(len).unpack("H*").first
36
+ end
37
+
38
+ def next_int
39
+ bytes(4).unpack("L").first
40
+ end
41
+
42
+ def self._dispose(ptr)
43
+ if ptr
44
+ CR_RELEASE.call ptr, 0
45
+ end
46
+ end
47
+
48
+ def dispose
49
+ self.class._dispose @ptr
50
+ @ptr = nil
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,195 @@
1
+ module Gap
2
+ class Samsara
3
+ Meta = Struct.new :meta
4
+ MetaFile = Meta.new :file
5
+ MetaMD5 = Meta.new :filemd5
6
+ attr_accessor :filepath
7
+ def initialize(name, filepath = "samfile")
8
+ @cache = Gap::Cache.new name
9
+ @filepath = filepath
10
+ end
11
+
12
+ def fromBase64(b64)
13
+ @cache.fromBase64 b64
14
+ end
15
+
16
+ def toBase64
17
+ @cache.toBase64
18
+ end
19
+
20
+ def fromMarshal(text)
21
+ @cache.fromMarshal text
22
+ end
23
+
24
+ def toMarshal
25
+ @cache.toMarshal
26
+ end
27
+
28
+ def each(&block)
29
+ @cache.each(&block)
30
+ end
31
+
32
+ def export(file, dir)
33
+ _export file, dir
34
+ end
35
+
36
+ def import(file, dir)
37
+ _import file, dir
38
+ end
39
+ #
40
+ # gen : [Any] -> ([Any] -> Any) -> Any
41
+ #
42
+ def gen(*path)
43
+ if @cache.has?(path)
44
+ @cache[path]
45
+ else
46
+ @cache.transaction do |db|
47
+ db[path] = yield path
48
+ db[path]
49
+ end
50
+ end
51
+ end
52
+
53
+ #
54
+ # genfile : filename -> [Any] -> (filename -> [Any] -> Any) -> Any
55
+ #
56
+ def genfile(filename, args = nil, &block)
57
+ realpath = file(filename)
58
+ md5key = [MetaMD5, filename]
59
+ filekey = [MetaFile, filename]
60
+ if @cache.has?(md5key) &&
61
+ @cache.has?(filekey) &&
62
+ FileTest.file?(realpath) &&
63
+ MD5.filehex(realpath) == @cache[md5key]
64
+ elsif @cache.has?(filekey)
65
+ _writefile realpath, @cache[filekey]
66
+ else
67
+ u = yield filekey
68
+ @cache.transaction do |db|
69
+ db[md5key] = MD5.hexdigest u
70
+ db[filekey] = u
71
+ _writefile realpath, @cache[filekey]
72
+ end
73
+ end
74
+ realpath
75
+ end
76
+
77
+ def has_file_in?(filename)
78
+ md5key = [MetaMD5, filename]
79
+ filekey = [MetaFile, filename]
80
+ @cache.has?(md5key) &&
81
+ @cache.has?(filekey) &&
82
+ @cache[md5key] != nil &&
83
+ MD5.hexdigest(@cache[filekey]) == @cache[md5key]
84
+ end
85
+
86
+ def need_update_file?(filename, realfile)
87
+ if has_file_in?(filename)
88
+ md5key = [MetaMD5, filename]
89
+ MD5.filehex(realfile) != @cache[md5key]
90
+ else
91
+ true
92
+ end
93
+ end
94
+
95
+ def file(name)
96
+ _file(name)
97
+ end
98
+
99
+ def writefile(a, b)
100
+ _writefile a, b
101
+ end
102
+
103
+ def readfile(a)
104
+ _readfile a
105
+ end
106
+
107
+ def mangle(name)
108
+ _mangle(name)
109
+ end
110
+
111
+ def rmdir_p(name)
112
+ _rmdir_p(name)
113
+ end
114
+
115
+
116
+ private
117
+ def _file(name)
118
+ File.join(@filepath, _mangle(name))
119
+ end
120
+
121
+ def _mangle(name)
122
+ name.gsub("://", "$SEP$/").gsub(/[:"']/){ "$#{$&.unpack("H")}$" }
123
+ end
124
+
125
+ def _demangle(name)
126
+ name.gsub("$SEP$/", "://").gsub(/\$([a-f0-9]+)\$/) { [$1].pack("H") }
127
+ end
128
+
129
+ def _mkdirp(name)
130
+ names = name.tr("\\", "/").split("/")[0..-2]
131
+ names.inject(""){|a, b|
132
+ if a == ""
133
+ path = b
134
+ else
135
+ path = a + "/" + b
136
+ end
137
+ if !FileTest.directory?(path)
138
+ Dir.mkdir(path)
139
+ end
140
+ path
141
+ }
142
+ end
143
+
144
+ def _readfile(name)
145
+ open(name, 'rb') do |f|
146
+ f.read
147
+ end
148
+ end
149
+ def _writefile(name, val)
150
+ _mkdirp(name)
151
+ open(name, "wb") do |f|
152
+ f.write val
153
+ end
154
+ end
155
+
156
+ def _export(file, dir)
157
+ if has_file_in?(file)
158
+ name = _mangle(dir + "/" + file)
159
+ filekey = [MetaFile, file]
160
+ _writefile(name, @cache[filekey])
161
+ else
162
+ raise "File not found #{file}"
163
+ end
164
+ end
165
+
166
+ def _import(file, dir)
167
+ name = _mangle(dir + "/" + file)
168
+ @cache.transaction do |db|
169
+ filekey = [MetaFile, file]
170
+ md5key = [MetaMD5, file]
171
+ db.remove filekey
172
+ db.remove md5key
173
+ content = _readfile name
174
+ db[md5key] = MD5.hexdigest(content)
175
+ db[filekey] = content
176
+ end
177
+ end
178
+
179
+ def _rmdir_p(name)
180
+ raise if name == nil || name[0] == "/"
181
+ files = [name]
182
+ Dir.glob(name + "/**/*") do |f|
183
+ files << f
184
+ end
185
+ files.sort!{|a, b| b.length <=> a.length}
186
+ files.each{|x|
187
+ if FileTest.file?(x)
188
+ File.delete x
189
+ else
190
+ Dir.delete x
191
+ end
192
+ }
193
+ end
194
+ end
195
+ end