exerb 6.0.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.
Files changed (179) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/ChangeLog.ja.rd +305 -0
  4. data/README.en.txt +12 -0
  5. data/README.ja.html +143 -0
  6. data/README.ja.txt +6 -0
  7. data/README.md +50 -0
  8. data/Rakefile +205 -0
  9. data/bin/exerb +185 -0
  10. data/bin/mkexy +47 -0
  11. data/doc/LGPL +513 -0
  12. data/doc/class.ja.html +92 -0
  13. data/doc/command.ja.html +109 -0
  14. data/doc/core.ja.html +72 -0
  15. data/doc/example.ja.html +89 -0
  16. data/doc/faq.ja.html +59 -0
  17. data/doc/inside.ja.rd +404 -0
  18. data/doc/license.ja.html +62 -0
  19. data/doc/logo.gif +0 -0
  20. data/doc/misc.ja.html +72 -0
  21. data/doc/navi.gif +0 -0
  22. data/doc/recipe.ja.html +317 -0
  23. data/doc/style.css +187 -0
  24. data/doc/tutorial.ja.html +182 -0
  25. data/example/Makefile +54 -0
  26. data/example/cat_n.rb +14 -0
  27. data/example/exception.rb +9 -0
  28. data/example/ext/Win32API.so +0 -0
  29. data/example/ext/swin.so +0 -0
  30. data/example/msgbox.rb +14 -0
  31. data/example/rubytk.rb +22 -0
  32. data/example/runtime.ico +0 -0
  33. data/example/runtime.rb +19 -0
  34. data/example/vr/clipboard.rb +106 -0
  35. data/example/vr/compat/rubycompat.rb +18 -0
  36. data/example/vr/compat/vrcomctl.rb +12 -0
  37. data/example/vr/compat/vrcontrol.rb +50 -0
  38. data/example/vr/compat/vrmmedia.rb +24 -0
  39. data/example/vr/contrib/inifile.rb +116 -0
  40. data/example/vr/contrib/msgboxconst.rb +55 -0
  41. data/example/vr/contrib/toolbar.rb +371 -0
  42. data/example/vr/contrib/vrctlcolor.rb +110 -0
  43. data/example/vr/contrib/vrhotkey.rb +35 -0
  44. data/example/vr/contrib/vrlistviewex.rb +71 -0
  45. data/example/vr/contrib/vrstdscrollbar.rb +414 -0
  46. data/example/vr/contrib/vrwincomponent.rb +54 -0
  47. data/example/vr/dragdropformat.rb +209 -0
  48. data/example/vr/rscutil.rb +168 -0
  49. data/example/vr/sysmod.rb +249 -0
  50. data/example/vr/vractivex.rb +56 -0
  51. data/example/vr/vrclipboard.rb +53 -0
  52. data/example/vr/vrcomctl.rb +1819 -0
  53. data/example/vr/vrcontrol.rb +1374 -0
  54. data/example/vr/vrdde.rb +623 -0
  55. data/example/vr/vrddrop.rb +190 -0
  56. data/example/vr/vrdialog.rb +406 -0
  57. data/example/vr/vrhandler.rb +195 -0
  58. data/example/vr/vrlayout.old.rb +209 -0
  59. data/example/vr/vrlayout.rb +173 -0
  60. data/example/vr/vrlayout2.rb +340 -0
  61. data/example/vr/vrmargin.rb +141 -0
  62. data/example/vr/vrmgdlayout.rb +381 -0
  63. data/example/vr/vrmmedia.rb +287 -0
  64. data/example/vr/vrolednd.rb +192 -0
  65. data/example/vr/vrowndraw.rb +108 -0
  66. data/example/vr/vrrichedit.rb +366 -0
  67. data/example/vr/vrtimer.rb +148 -0
  68. data/example/vr/vrtooltip.rb +273 -0
  69. data/example/vr/vrtray.rb +143 -0
  70. data/example/vr/vrtvitem.rb +118 -0
  71. data/example/vr/vrtwopane.rb +223 -0
  72. data/example/vr/vruby.rb +1051 -0
  73. data/example/vr/winconst.rb +158 -0
  74. data/example/vruby.rb +38 -0
  75. data/exerb.gemspec +26 -0
  76. data/extconf.rb +7 -0
  77. data/lib/exerb/archive.rb +143 -0
  78. data/lib/exerb/config.rb +51 -0
  79. data/lib/exerb/error.rb +15 -0
  80. data/lib/exerb/executable.rb +68 -0
  81. data/lib/exerb/file_table.rb +189 -0
  82. data/lib/exerb/mkexy.rb +81 -0
  83. data/lib/exerb/name_table.rb +120 -0
  84. data/lib/exerb/recipe.rb +465 -0
  85. data/lib/exerb/resource.rb +190 -0
  86. data/lib/exerb/resource/base.rb +29 -0
  87. data/lib/exerb/resource/binary.rb +31 -0
  88. data/lib/exerb/resource/dialog.rb +30 -0
  89. data/lib/exerb/resource/group_icon.rb +85 -0
  90. data/lib/exerb/resource/icon.rb +52 -0
  91. data/lib/exerb/resource/version_info.rb +155 -0
  92. data/lib/exerb/resource_library.rb +120 -0
  93. data/lib/exerb/utility.rb +95 -0
  94. data/lib/exerb/utility2.rb +122 -0
  95. data/lib/exerb/version.rb +13 -0
  96. data/lib/exerb/win32/const/resource.rb +51 -0
  97. data/lib/exerb/win32/icon_file.rb +78 -0
  98. data/lib/exerb/win32/pe_file.rb +59 -0
  99. data/lib/exerb/win32/resource_directory.rb +105 -0
  100. data/lib/exerb/win32/resource_directory_root.rb +67 -0
  101. data/lib/exerb/win32/resource_entry.rb +98 -0
  102. data/lib/exerb/win32/struct/base.rb +43 -0
  103. data/lib/exerb/win32/struct/icon_dir_entry.rb +83 -0
  104. data/lib/exerb/win32/struct/icon_header.rb +43 -0
  105. data/lib/exerb/win32/struct/icon_res_entry.rb +48 -0
  106. data/lib/exerb/win32/struct/image_dos_header.rb +73 -0
  107. data/lib/exerb/win32/struct/image_file_header.rb +47 -0
  108. data/lib/exerb/win32/struct/image_nt_headers32.rb +53 -0
  109. data/lib/exerb/win32/struct/image_optional_header32.rb +107 -0
  110. data/lib/exerb/win32/struct/image_resource_data_entry.rb +45 -0
  111. data/lib/exerb/win32/struct/image_resource_directory.rb +47 -0
  112. data/lib/exerb/win32/struct/image_resource_directory_entry.rb +72 -0
  113. data/lib/exerb/win32/struct/image_section_header.rb +53 -0
  114. data/lib/exerb/win32/struct/version_info_block.rb +75 -0
  115. data/lib/exerb/win32/struct/vs_fixed_file_info.rb +62 -0
  116. data/src/exerb/cui.c +48 -0
  117. data/src/exerb/default.rb +1 -0
  118. data/src/exerb/exerb.c +877 -0
  119. data/src/exerb/exerb.h +92 -0
  120. data/src/exerb/gui.c +176 -0
  121. data/src/exerb/module.c +138 -0
  122. data/src/exerb/module.h +7 -0
  123. data/src/exerb/patch.c +27 -0
  124. data/src/exerb/resource.h +22 -0
  125. data/src/exerb/resource.rc +121 -0
  126. data/src/exerb/ruby.ico +0 -0
  127. data/src/exerb/utility.c +263 -0
  128. data/src/exerb/utility.h +33 -0
  129. data/test/alltests.rb +16 -0
  130. data/test/test-argv.rb +26 -0
  131. data/test/test-argv/test-argv.rb +9 -0
  132. data/test/test-argv/test-argv.ret +1 -0
  133. data/test/test-dollarzero.rb +26 -0
  134. data/test/test-dollarzero/test-dollarzero.rb +10 -0
  135. data/test/test-dollarzero/test-dollarzero.ret +2 -0
  136. data/test/test-dot.rb +26 -0
  137. data/test/test-dot/dot.dot.dot.rb +9 -0
  138. data/test/test-dot/dot.dot.rb +9 -0
  139. data/test/test-dot/test-dot.rb +13 -0
  140. data/test/test-dot/test-dot.ret +5 -0
  141. data/test/test-exitcode.rb +28 -0
  142. data/test/test-exitcode/test-exitcode.rb +9 -0
  143. data/test/test-kcode.rb +43 -0
  144. data/test/test-kcode/euc.rb +10 -0
  145. data/test/test-kcode/euc.ret +2 -0
  146. data/test/test-kcode/none.rb +10 -0
  147. data/test/test-kcode/none.ret +2 -0
  148. data/test/test-kcode/sjis.rb +10 -0
  149. data/test/test-kcode/sjis.ret +2 -0
  150. data/test/test-kcode/utf8.rb +10 -0
  151. data/test/test-kcode/utf8.ret +2 -0
  152. data/test/test-loadpath.rb +24 -0
  153. data/test/test-loadpath/test-loadpath.rb +9 -0
  154. data/test/test-nest.rb +18 -0
  155. data/test/test-nest/foo.rb +1 -0
  156. data/test/test-nest/foo/bar.rb +2 -0
  157. data/test/test-nest/foo/foo.rb +1 -0
  158. data/test/test-nest/test-nest.rb +1 -0
  159. data/test/test-nest/test-nest.ret +1 -0
  160. data/test/test-preload.rb +24 -0
  161. data/test/test-preload/test-preload.rb +9 -0
  162. data/test/test-regexp.rb +26 -0
  163. data/test/test-regexp/test-regexp.rb +23 -0
  164. data/test/test-regexp/test-regexp.ret +13 -0
  165. data/test/test-require1.rb +26 -0
  166. data/test/test-require1/require1.rb +9 -0
  167. data/test/test-require1/require2.rb +9 -0
  168. data/test/test-require1/require3.rb +9 -0
  169. data/test/test-require1/require4.rb +9 -0
  170. data/test/test-require1/require5.rb +9 -0
  171. data/test/test-require1/require6.rb +9 -0
  172. data/test/test-require1/test-require1.rb +41 -0
  173. data/test/test-require1/test-require1.ret +27 -0
  174. data/test/test-socket.rb +26 -0
  175. data/test/test-socket/test-socket.rb +7 -0
  176. data/test/test-socket/test-socket.ret +1 -0
  177. data/test/testcase.rb +66 -0
  178. data/vendor/mkexports.rb +167 -0
  179. metadata +352 -0
@@ -0,0 +1,189 @@
1
+
2
+ #==============================================================================#
3
+ # $Id: file_table.rb,v 1.15 2007/02/26 10:20:44 yuya Exp $
4
+ #==============================================================================#
5
+
6
+ require 'exerb/utility'
7
+ require 'zlib'
8
+
9
+ #==============================================================================#
10
+
11
+ module Exerb
12
+ end # Exerb
13
+
14
+ #==============================================================================#
15
+
16
+ class Exerb::FileTable
17
+
18
+ def initialize
19
+ @entries = []
20
+ end
21
+
22
+ def add(id, data, flag, zipd = 0)
23
+ @entries << Exerb::FileTable::Entry.new(id, data, flag, zipd)
24
+ return @entries.last
25
+ end
26
+
27
+ def add_from_file(id, path, flag)
28
+ return File.open(path, 'rb') { |file|
29
+ if ENV['exy_zipd'] && /\.rbw?$/i =~ path
30
+ data = Zlib.deflate(file.read, 9)
31
+ self.add(id, data, flag, 1)
32
+ else
33
+ self.add(id, file.read, flag)
34
+ end
35
+ }
36
+ end
37
+
38
+ def add_ruby_script(id, data, flag = 0)
39
+ return self.add(id, data, Entry::FLAG_TYPE_RUBY_SCRIPT | flag)
40
+ end
41
+
42
+ def add_ruby_script_from_file(id, path, flag = 0)
43
+ return self.add_from_file(id, path, Entry::FLAG_TYPE_RUBY_SCRIPT | flag)
44
+ end
45
+
46
+ def add_extension_library(id, data, flag = 0)
47
+ return self.add(id, data, Entry::FLAG_TYPE_EXTENSION_LIBRARY | flag)
48
+ end
49
+
50
+ def add_extension_library_from_file(id, path, flag = 0)
51
+ return self.add_from_file(id, path, Entry::FLAG_TYPE_EXTENSION_LIBRARY | flag)
52
+ end
53
+
54
+ def add_dynamic_library(id, data, flag = 0)
55
+ return self.add(id, data, Entry::FLAG_TYPE_DYNAMIC_LIBRARY | flag)
56
+ end
57
+
58
+ def add_dynamic_library_from_file(id, path, flag = 0)
59
+ return self.add_from_file(id, path, Entry::FLAG_TYPE_DYNAMIC_LIBRARY | flag)
60
+ end
61
+
62
+ def add_resource_library(id, data, flag = 0)
63
+ return self.add(id, data, Entry::FLAG_TYPE_RESOURCE_LIBRARY | flag)
64
+ end
65
+
66
+ def add_resource_library_from_file(id, path, flag = 0)
67
+ return self.add_from_file(id, path, Entry::FLAG_TYPE_RESOURCE_LIBRARY | flag)
68
+ end
69
+
70
+ def add_data_binary(id, data, flag = 0)
71
+ return self.add(id, data, Entry::FLAG_TYPE_DATA_BINARY | flag)
72
+ end
73
+
74
+ def add_data_binary_from_file(id, path, flag = 0)
75
+ return self.add_from_file(id, path, Entry::FLAG_TYPE_DATA_BINARY | flag)
76
+ end
77
+
78
+ def add_compiled_script(id, data, flag = 0)
79
+ return self.add(id, data, Entry::FLAG_TYPE_COMPILED_SCRIPT | flag)
80
+ end
81
+
82
+ def add_compiled_script_from_file(id, path, flag = 0)
83
+ return self.add_from_file(id, path, Entry::FLAG_TYPE_COMPILED_SCRIPT | flag)
84
+ end
85
+
86
+ def pack
87
+ headers = ''
88
+ pool = ''
89
+
90
+ @entries.each { |entry|
91
+ headers << entry.pack_header(pool)
92
+ pool << entry.pack_pool
93
+ }
94
+
95
+ packed_headers = Exerb::Utility.alignment16(headers)
96
+ packed_pool = Exerb::Utility.alignment16(pool)
97
+
98
+ table_header = Exerb::FileTable::Header.new
99
+ table_header.signature = Exerb::FileTable::Header::SIGNATURE
100
+ table_header.number_of_headers = @entries.size
101
+ table_header.offset_of_headers = Exerb::Utility.alignment16(table_header.pack).size
102
+ table_header.offset_of_pool = table_header.offset_of_headers + packed_headers.size
103
+
104
+ return Exerb::Utility.alignment16(table_header.pack) + packed_headers + packed_pool
105
+ end
106
+
107
+ end # Exerb::FileTabel
108
+
109
+ #==============================================================================#
110
+
111
+ class Exerb::FileTable::Header
112
+
113
+ SIGNATURE = 0x04005446
114
+
115
+ def initialize
116
+ @signature = 0
117
+ @number_of_headers = 0
118
+ @offset_of_headers = 0
119
+ @offset_of_pool = 0
120
+ end
121
+
122
+ attr_accessor :signature, :number_of_headers, :offset_of_headers, :offset_of_pool
123
+
124
+ def pack
125
+ return [@signature, @number_of_headers, @offset_of_headers, @offset_of_pool].pack('LSLL')
126
+ end
127
+
128
+ end # Exerb::FileTable::Header
129
+
130
+ #==============================================================================#
131
+
132
+ class Exerb::FileTable::Entry
133
+
134
+ FLAG_TYPE_RUBY_SCRIPT = 0x01
135
+ FLAG_TYPE_EXTENSION_LIBRARY = 0x02
136
+ FLAG_TYPE_DYNAMIC_LIBRARY = 0x03
137
+ FLAG_TYPE_RESOURCE_LIBRARY = 0x04
138
+ FLAG_TYPE_DATA_BINARY = 0x05
139
+ FLAG_TYPE_COMPILED_SCRIPT = 0x06
140
+ FLAG_NO_REPLACE_FUNCTION = 0x08
141
+
142
+ def initialize(id, data, flag, zipd)
143
+ @id = id
144
+ @data = data
145
+ @flag = flag
146
+ @zipd = zipd
147
+ end
148
+
149
+ attr_reader :id, :data, :flag
150
+
151
+ def pack_header(pool)
152
+ entry_header = Exerb::FileTable::Entry::Header.new
153
+ entry_header.id = @id
154
+ entry_header.offset_of_file = pool.size
155
+ entry_header.size_of_file = @data.size
156
+ entry_header.flag_of_file = @flag
157
+ entry_header.zipd = @zipd
158
+
159
+ return entry_header.pack
160
+ end
161
+
162
+ def pack_pool
163
+ return Exerb::Utility.alignment16(@data)
164
+ end
165
+
166
+ end # Exerb::FileTable::Entry
167
+
168
+ #==============================================================================#
169
+
170
+ class Exerb::FileTable::Entry::Header
171
+
172
+ def initialize
173
+ @id = 0
174
+ @offset_of_file = 0
175
+ @size_of_file = 0
176
+ @flag_of_file = 0
177
+ @zipd = 0
178
+ end
179
+
180
+ attr_accessor :id, :offset_of_file, :size_of_file, :flag_of_file, :zipd
181
+
182
+ def pack
183
+ return [@id, @offset_of_file, @size_of_file, @flag_of_file, @zipd].pack('SLLCC')
184
+ end
185
+
186
+ end # Exerb::FileTable::Entry::Header
187
+
188
+ #==============================================================================#
189
+ #==============================================================================#
@@ -0,0 +1,81 @@
1
+
2
+ #==============================================================================#
3
+ # $Id: mkexy.rb,v 1.2 2004/03/25 09:35:25 yuya Exp $
4
+ #==============================================================================#
5
+
6
+ require 'exerb/utility2'
7
+
8
+ #==============================================================================#
9
+
10
+ BEGIN {
11
+ $exerb_pwd = Dir.pwd
12
+ }
13
+
14
+ END {
15
+ Dir.chdir($exerb_pwd)
16
+ if ENV['exy_zipd']
17
+ require 'zlib'
18
+ zipd = true
19
+ else
20
+ zipd = false
21
+ end
22
+
23
+ reject_list = [File.expand_path(__FILE__)]
24
+ file_list = [['script', $0, $0]] + Exerb::Utility2.loaded_features(reject_list)
25
+ recipe_file = File.expand_path($0).sub(/(\.rbw?$|$)/i, '.exy')
26
+ core = $0 =~ /\.rbw$/i ? "gui" : "cui"
27
+
28
+ old_resource = nil
29
+ old_path = nil
30
+ old_recipe_file = ENV['old_exy'] || recipe_file
31
+ if File.exists?(old_recipe_file)
32
+ require 'yaml'
33
+ oldcfg = YAML.load(File.read(old_recipe_file))
34
+ msg = "# from old exy file"
35
+ if oldcfg['general'] && oldcfg['general']['core'] && core != oldcfg['general']['core']
36
+ core = oldcfg['general']['core'] + ' ' + msg
37
+ end
38
+ s_r = oldcfg['resource']
39
+ if s_r && !s_r.empty?
40
+ old_resource = ["", msg, "resource:"]
41
+ s_r.to_yaml.split("\n")[1..-1].each do |x|
42
+ old_resource << ' ' + x.chomp
43
+ end
44
+ end
45
+
46
+ s_p = oldcfg['path']
47
+ if s_p && !s_p.empty?
48
+ old_path = ["", msg, "path:"]
49
+ s_p.to_yaml.split("\n")[1..-1].each do |x|
50
+ old_path << ' ' + x.chomp
51
+ end
52
+ end
53
+ end
54
+
55
+ File.open(recipe_file, 'w') { |file|
56
+ file.puts("# Generated by mkexy")
57
+ file.puts("# on #{Time.now.strftime('%Y-%m-%d %H:%M')}")
58
+ file.puts("")
59
+ file.puts("general:")
60
+ file.puts(" startup: #{$0}")
61
+ file.puts(" core: #{core}")
62
+ file.puts(" zipd: #{zipd}")
63
+ if RUBY_VERSION < "1.9"
64
+ file.puts(" kcode: #{$KCODE.downcase}")
65
+ else
66
+ file.puts(" kcode: none") #no KCODE in 1.9
67
+ end
68
+ file.puts(old_resource) if old_resource
69
+ file.puts(old_path) if old_path
70
+ file.puts("")
71
+ file.puts("file:")
72
+ file_list.each { |type, filename, filepath|
73
+ file.puts(" #{filename}:")
74
+ file.puts(" file: #{filepath}") if filename != filepath
75
+ file.puts(" type: #{type}") if type != "script"
76
+ }
77
+ }
78
+ }
79
+
80
+ #==============================================================================#
81
+ #==============================================================================#
@@ -0,0 +1,120 @@
1
+
2
+ #==============================================================================#
3
+ # $Id: name_table.rb,v 1.4 2005/04/17 15:17:26 yuya Exp $
4
+ #==============================================================================#
5
+
6
+ require 'exerb/utility'
7
+
8
+ #==============================================================================#
9
+
10
+ module Exerb
11
+ end # Exerb
12
+
13
+ #==============================================================================#
14
+
15
+ class Exerb::NameTable
16
+
17
+ def initialize
18
+ @entries = []
19
+ end
20
+
21
+ def add(name)
22
+ @entries.find { |entry|
23
+ if entry.name == name
24
+ return entry.id
25
+ end
26
+ }
27
+
28
+ @entries << Exerb::NameTable::Entry.new(@entries.size + 1, name)
29
+
30
+ return @entries.last.id
31
+ end
32
+
33
+ def pack
34
+ headers = ''
35
+ pool = ''
36
+
37
+ @entries.each { |entry|
38
+ headers << entry.pack_header(pool)
39
+ pool << entry.pack_pool
40
+ }
41
+
42
+ packed_headers = Exerb::Utility.alignment16(headers)
43
+ packed_pool = Exerb::Utility.alignment16(pool)
44
+
45
+ table_header = Exerb::NameTable::Header.new
46
+ table_header.signature = Exerb::NameTable::Header::SIGNATURE
47
+ table_header.number_of_headers = @entries.size
48
+ table_header.offset_of_headers = Exerb::Utility.alignment16(table_header.pack).size
49
+ table_header.offset_of_pool = table_header.offset_of_headers + packed_headers.size
50
+
51
+ return Exerb::Utility.alignment16(table_header.pack) + packed_headers + packed_pool
52
+ end
53
+
54
+ end # Exerb::NameTable
55
+
56
+ #==============================================================================#
57
+
58
+ class Exerb::NameTable::Header
59
+
60
+ SIGNATURE = 0x0100544E
61
+
62
+ def initialize
63
+ @signature = 0
64
+ @number_of_headers = 0
65
+ @offset_of_headers = 0
66
+ @offset_of_pool = 0
67
+ end
68
+
69
+ attr_accessor :signature, :number_of_headers, :offset_of_headers, :offset_of_pool
70
+
71
+ def pack
72
+ return [@signature, @number_of_headers, @offset_of_headers, @offset_of_pool].pack('LSLL')
73
+ end
74
+
75
+ end # Exerb::NameTable::Header
76
+
77
+ #==============================================================================#
78
+
79
+ class Exerb::NameTable::Entry
80
+
81
+ def initialize(id, name)
82
+ @id = id
83
+ @name = name
84
+ end
85
+
86
+ attr_reader :id, :name
87
+
88
+ def pack_header(pool)
89
+ entry_header = Exerb::NameTable::Entry::Header.new
90
+ entry_header.id = @id
91
+ entry_header.offset_of_name = pool.size
92
+
93
+ return entry_header.pack
94
+ end
95
+
96
+ def pack_pool
97
+ return @name + "\0"
98
+ end
99
+
100
+ end # Exerb::NameTable::Entry
101
+
102
+ #==============================================================================#
103
+
104
+ class Exerb::NameTable::Entry::Header
105
+
106
+ def initialize
107
+ @id = 0
108
+ @offset_of_name = 0
109
+ end
110
+
111
+ attr_accessor :id, :offset_of_name
112
+
113
+ def pack
114
+ return [@id, @offset_of_name].pack('SL')
115
+ end
116
+
117
+ end # Exerb::NameTable::Entry::Header
118
+
119
+ #==============================================================================#
120
+ #==============================================================================#
@@ -0,0 +1,465 @@
1
+ #! /usr/bin/ruby
2
+
3
+ #==============================================================================#
4
+ # $Id: recipe.rb,v 1.24 2007/02/26 10:59:31 yuya Exp $
5
+ #==============================================================================#
6
+
7
+ require 'yaml'
8
+ require 'exerb/error'
9
+ require 'exerb/utility'
10
+ require 'exerb/archive'
11
+
12
+ #==============================================================================#
13
+
14
+ module Exerb
15
+ end # Exerb
16
+
17
+ #==============================================================================#
18
+
19
+ class Exerb::Recipe
20
+
21
+ def initialize(blocks, basedir = Dir.pwd, filename = '-')
22
+ @basedir = basedir
23
+ @filename = filename
24
+ @general = Exerb::Recipe::GeneralBlock.analyze(blocks, @filename)
25
+ @path = Exerb::Recipe::PathBlock.analyze(blocks, @filename)
26
+ @resource = Exerb::Recipe::ResourceBlock.analyze(blocks, @filename)
27
+ @file = Exerb::Recipe::FileBlock.analyze(blocks, @filename)
28
+ raise(Exerb::ExerbError, "#{@filename}: found unknown field in the recipe -- #{blocks.keys.join(', ')}") unless blocks.empty?
29
+ end
30
+
31
+ def self.load(filepath)
32
+ basedir = File.dirname(File.expand_path(filepath))
33
+ filename = File.basename(filepath)
34
+
35
+ begin
36
+ blocks = YAML.load(File.read(filepath))
37
+ rescue Errno::ENOENT => e
38
+ raise(Exerb::ExerbError, "no such file -- #{filepath}")
39
+ rescue ArgumentError => e
40
+ msg = e.message.gsub(/\n/, '\n')
41
+ msg.gsub!(/\r/, '\r')
42
+ msg.gsub!(/\t/, '\t')
43
+ raise(Exerb::ExerbError, format('%s: %s', @filename, msg))
44
+ end
45
+
46
+ return self.new(blocks, basedir, filename)
47
+ end
48
+
49
+ def archive_filepath(filename = nil)
50
+ return self.output_filepath(filename).sub(/(\.exe)?$/i, '.exa')
51
+ end
52
+
53
+ def output_filepath(filename = nil)
54
+ filename ||= @general.output
55
+ filename ||= @filename.sub(/(\.exy)?$/i, '.exe')
56
+
57
+ return File.expand_path(filename, @basedir)
58
+ end
59
+
60
+ def core_filepath(filepath = nil)
61
+ unless @general.core.nil?
62
+ core = Exerb::Utility.find_core_by_filepath(File.expand_path(@general.core, @basedir))
63
+ core ||= Exerb::Utility.find_core_by_filename(@general.core)
64
+ core ||= Exerb::Utility.find_core_by_name(@general.core)
65
+ raise(Exerb::ExerbError, "#{@filename}: specified core isn't found -- #{@general.core}") if core.nil?
66
+ end
67
+
68
+ filepath ||= core
69
+ filepath ||= Exerb::Utility.find_core_by_name('cui', true)
70
+
71
+ return filepath
72
+ end
73
+
74
+ def create_archive(kcode = nil)
75
+ archive = Exerb::Archive.new(kcode || @general.kcode)
76
+
77
+ search_path = [@basedir]
78
+ search_path += @path.path.collect { |dir| File.expand_path(dir, @basedir) } if @path
79
+ search_path += $:
80
+
81
+ startup_entry = @file.delete(@general.startup)
82
+ raise(Exerb::ExerbError, "#{@filename}: specified startup script isn't found in the file block -- #{@general.startup}") if startup_entry.nil?
83
+ add_file_entry(archive, search_path, @general.startup, startup_entry)
84
+
85
+ @file.keys.sort.each { |internal_name|
86
+ add_file_entry(archive, search_path, internal_name, @file[internal_name])
87
+ }
88
+
89
+ return archive
90
+ end
91
+
92
+ def update_resource(rsrc)
93
+ if @resource
94
+ if @resource.icon
95
+ rsrc.remove(Exerb::Win32::Const::RT_ICON)
96
+ rsrc.remove(Exerb::Win32::Const::RT_GROUP_ICON)
97
+
98
+ group_icon = Exerb::Resource::GroupIcon.new
99
+
100
+ @resource.icon.entries.each_with_index { |entry, index|
101
+ id = index + 1
102
+ icon = Exerb::Resource::Icon.read(entry.file, entry.width, entry.height, entry.color)
103
+ rsrc.add(Exerb::Win32::Const::RT_ICON, id, icon)
104
+ group_icon.add(id, icon)
105
+ }
106
+
107
+ rsrc.add(Exerb::Win32::Const::RT_GROUP_ICON, 1, group_icon)
108
+ end
109
+
110
+ if @resource.version
111
+ fv = (0..3).collect { |i| @resource.version.file_version_number[i] || 0 }
112
+ pv = (0..3).collect { |i| @resource.version.product_version_number[i] || 0 }
113
+
114
+ ver = Exerb::Resource::VersionInfo.new
115
+ ver.file_version_number = Exerb::Resource::VersionInfo.make_version(*fv)
116
+ ver.product_version_number = Exerb::Resource::VersionInfo.make_version(*pv)
117
+ ver.comments = @resource.version.comments
118
+ ver.company_name = @resource.version.company_name
119
+ ver.legal_copyright = @resource.version.legal_copyright
120
+ ver.legal_trademarks = @resource.version.legal_trademarks
121
+ ver.file_version = @resource.version.file_version
122
+ ver.product_version = @resource.version.product_version
123
+ ver.product_name = @resource.version.product_name
124
+ ver.file_description = @resource.version.file_description
125
+ ver.internal_name = @resource.version.internal_name
126
+ ver.original_filename = @resource.version.original_filename
127
+ ver.private_build = @resource.version.private_build
128
+ ver.special_build = @resource.version.special_build
129
+
130
+ rsrc.remove(Exerb::Win32::Const::RT_VERSION)
131
+ rsrc.add(Exerb::Win32::Const::RT_VERSION, 1, ver)
132
+ end
133
+ end
134
+ end
135
+
136
+ def add_file_entry(archive, search_path, internal_name, entry)
137
+ if entry.file
138
+ filepath = File.expand_path(entry.file, @basedir)
139
+ raise("#{@filename}: no such file -- #{entry.file}") unless File.exist?(filepath)
140
+ else
141
+ filepath = search_path.collect { |dir|
142
+ File.join(dir, internal_name)
143
+ }.find { |path|
144
+ File.exist?(path)
145
+ }
146
+ raise("#{@filename}: no such file -- #{internal_name}") unless filepath
147
+ end
148
+
149
+ flag = ([entry.type] + entry.flag).inject(0) { |a, b| a | b }
150
+
151
+ if entry.type == Exerb::FileTable::Entry::FLAG_TYPE_COMPILED_SCRIPT
152
+ src = File.binread(filepath)
153
+ iseq = RubyVM::InstructionSequence.compile(src, internal_name)
154
+ bin = Marshal.dump(iseq.to_a)
155
+ archive.add(internal_name, bin, flag)
156
+ else
157
+ archive.add_from_file(internal_name, filepath, flag)
158
+ end
159
+ end
160
+ protected :add_file_entry
161
+
162
+ end # Exerb::Recipe
163
+
164
+ #==============================================================================#
165
+
166
+ class Exerb::Recipe::GeneralBlock
167
+
168
+ KCODE = ['none', 'euc', 'sjis', 'utf8']
169
+
170
+ def initialize(block, filename)
171
+ @startup = block.delete('startup') || ""
172
+ @output = block.delete('output') || ""
173
+ @core = block.delete('core') || ""
174
+ @kcode = block.delete('kcode') || "none"
175
+ @zipd = block.delete('zipd') || nil
176
+
177
+ @startup = nil if @startup.empty?
178
+ @output = nil if @output.empty?
179
+ @core = nil if @core.empty?
180
+ @kcode.downcase!
181
+ if @zipd
182
+ ENV['exy_zipd'] = 'true'
183
+ else
184
+ ENV['exy_zipd'] = nil
185
+ end
186
+
187
+ raise(Exerb::ExerbError, "#{filename}: unknown field at general block -- #{block.keys.join(', ')}") unless block.empty?
188
+ raise(Exerb::ExerbError, "#{filename}: startup field isn't specified at general block") if @startup.nil?
189
+ raise(Exerb::ExerbError, "#{filename}: unknown kcode at general block -- #{@kcode}") unless KCODE.include?(@kcode)
190
+ end
191
+
192
+ attr_reader :startup, :output, :core, :kcode
193
+
194
+ def self.analyze(blocks, filename)
195
+ block = blocks.delete("general")
196
+ raise(Exerb::ExerbError, "#{filename}: general block not found") if block.nil?
197
+ raise(Exerb::ExerbError, "#{filename}: general block must be Hash object -- #{block.class}") unless block.kind_of?(Hash)
198
+ return self.new(block, filename)
199
+ end
200
+
201
+ end # Exerb::Recipe::GeneralBlock
202
+
203
+ #==============================================================================#
204
+
205
+ class Exerb::Recipe::PathBlock
206
+
207
+ def initialize(block, filename)
208
+ @path = block.collect { |entry|
209
+ raise(Exerb::ExerbError, "#{filename}: path block entries must be String object -- #{entry.type}") unless entry.kind_of?(String)
210
+ entry.strip
211
+ }
212
+ end
213
+
214
+ attr_reader :path
215
+
216
+ def self.analyze(blocks, filename)
217
+ block = blocks.delete("path")
218
+ return nil if block.nil?
219
+ raise(Exerb::ExerbError, "#{filename}: path block must be Array object -- #{block.class}") unless block.kind_of?(Array)
220
+ return self.new(block, filename)
221
+ end
222
+
223
+ end # Exerb::Recipe::PathBlock
224
+
225
+ #==============================================================================#
226
+
227
+ class Exerb::Recipe::ResourceBlock
228
+
229
+ def initialize(block, filename)
230
+ @icon = IconBlock.analyze(block, filename)
231
+ @version = VersionBlock.analyze(block, filename)
232
+ raise(Exerb::ExerbError, "#{filename}: unknown field at resource block -- #{block.keys.join(', ')}") unless block.empty?
233
+ end
234
+
235
+ attr_reader :icon, :version
236
+
237
+ def self.analyze(blocks, filename)
238
+ block = blocks.delete("resource")
239
+ return nil if block.nil?
240
+ raise(Exerb::ExerbError, "#{filename}: resource block must be Hash object -- #{block.type}") unless block.kind_of?(Hash)
241
+ return self.new(block, filename)
242
+ end
243
+
244
+ class IconBlock
245
+
246
+ def initialize(block, filename)
247
+ @entries = block.collect { |hash| Entry.analyze(hash, filename) }
248
+ end
249
+
250
+ attr_reader :entries
251
+
252
+ def self.analyze(blocks, filename)
253
+ block = blocks.delete("icon")
254
+ return nil if block.nil?
255
+ raise(Exerb::ExerbError, "#{filename}: icon block must be Array object -- #{block.type}") unless block.kind_of?(Array)
256
+ return self.new(block, filename)
257
+ end
258
+
259
+ class Entry
260
+
261
+ def initialize(block, filename)
262
+ @width = block.delete("width")
263
+ @height = block.delete("height")
264
+ @color = block.delete("color")
265
+ @file = block.delete("file")
266
+
267
+ raise(Exerb::ExerbError, "#{filename}: unknown field at icon block entry -- #{block.keys.join(', ')}") unless block.empty?
268
+ end
269
+
270
+ attr_reader :width, :height, :color, :file
271
+
272
+ def self.analyze(block, filename)
273
+ raise(Exerb::ExerbError, "#{filename}: icon block entry must be Hash object -- #{block.type}") unless block.kind_of?(Hash)
274
+ return self.new(block, filename)
275
+ end
276
+
277
+ end # Entry
278
+ end # IconBlock
279
+
280
+ class VersionBlock
281
+
282
+ def initialize(block, filename)
283
+ @file_version_number = self.parse_version((block.delete('file_version_number') || "0.0.0.0"), filename)
284
+ @product_version_number = self.parse_version((block.delete('product_version_number') || "0.0.0.0"), filename)
285
+ @comments = block.delete('comments') || ""
286
+ @company_name = block.delete('company_name') || ""
287
+ @legal_copyright = block.delete('legal_copyright') || ""
288
+ @legal_trademarks = block.delete('legal_trademarks') || ""
289
+ @file_version = block.delete('file_version') || ""
290
+ @product_version = block.delete('product_version') || ""
291
+ @product_name = block.delete('product_name') || ""
292
+ @file_description = block.delete('file_description') || ""
293
+ @internal_name = block.delete('internal_name') || ""
294
+ @original_filename = block.delete('original_filename') || ""
295
+ @private_build = block.delete('private_build') || ""
296
+ @special_build = block.delete('special_build') || ""
297
+
298
+ raise(Exerb::ExerbError, "#{filename}: unknown field in version block -- #{block.keys.join(', ')}") unless block.empty?
299
+ end
300
+
301
+ attr_reader :file_version_number, :product_version_number,
302
+ :comments, :company_name, :legal_copyright, :legal_trademarks, :file_version,
303
+ :product_version, :product_name, :file_description, :internal_name, :original_filename,
304
+ :private_build, :special_build
305
+
306
+ def self.analyze(blocks, filename)
307
+ block = blocks.delete("version")
308
+ return nil if block.nil?
309
+ raise(Exerb::ExerbError, "#{filename}: version block must be Hash object -- #{block.class}") unless block.kind_of?(Hash)
310
+ return self.new(block, filename)
311
+ end
312
+
313
+ def parse_version(version, filename)
314
+ case version.delete(" ").tr(",", ".")
315
+ when /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ then return [$1.to_i, $2.to_i, $3.to_i, $4.to_i]
316
+ when /^(\d+)\.(\d+)\.(\d+)$/ then return [$1.to_i, $2.to_i, $3.to_i, 0]
317
+ when /^(\d+)\.(\d+)$/ then return [$1.to_i, $2.to_i, 0, 0]
318
+ when /^(\d+)$/ then return [$1.to_i, 0, 0, 0]
319
+ when "" then return [0, 0, 0, 0]
320
+ else raise(Exerb::ExerbError, "#{filename}: invalid version format in version block -- #{version}")
321
+ end
322
+ end
323
+
324
+ end # VersionBlock
325
+
326
+ end # Exerb::Recipe::ResourceBlock
327
+
328
+ #==============================================================================#
329
+
330
+ class Exerb::Recipe::FileBlock
331
+
332
+ include Enumerable
333
+
334
+ def initialize(block, filename)
335
+ @file = {}
336
+
337
+ block.each { |internal_name, options|
338
+ @file[internal_name] = FileEntry.new(internal_name, options, filename)
339
+ }
340
+ end
341
+
342
+ def self.analyze(blocks, filename)
343
+ block = blocks.delete("file")
344
+ raise(Exerb::ExerbError, "#{filename}: file block not found") if block.nil?
345
+ raise(Exerb::ExerbError, "#{filename}: file block must be Hash object -- #{block.class}") unless block.kind_of?(Hash)
346
+ return self.new(block, filename)
347
+ end
348
+
349
+ def [](key)
350
+ return @file[key]
351
+ end
352
+
353
+ def each(&block)
354
+ return @file.each(&block)
355
+ end
356
+
357
+ def keys
358
+ return @file.keys
359
+ end
360
+
361
+ def delete(key)
362
+ return @file.delete(key)
363
+ end
364
+
365
+ end # Exerb::Recipe::FileBlock
366
+
367
+ #==============================================================================#
368
+
369
+ class Exerb::Recipe::FileBlock::FileEntry
370
+
371
+ def initialize(internal_name, options, filename)
372
+ @file = nil
373
+ @type = Exerb::FileTable::Entry::FLAG_TYPE_RUBY_SCRIPT
374
+ @flag = []
375
+ self.analyze_options(internal_name, options || {}, filename)
376
+ end
377
+
378
+ attr_reader :file, :type, :flag
379
+
380
+ def analyze_options(internal_name, options, filename)
381
+ raise(Exerb::ExerbError, "#{filename}: file entry must be Hash object -- #{options.class}") unless options.kind_of?(Hash)
382
+ @file = self.analyze_option_file(options, filename)
383
+ @type = self.analyze_option_type(internal_name, options, filename)
384
+ @flag = self.analyze_option_flag(options, filename, @type)
385
+ end
386
+ protected :analyze_options
387
+
388
+ def analyze_option_file(options, filename)
389
+ return options['file']
390
+ end
391
+ protected :analyze_option_file
392
+
393
+ def analyze_option_type(internal_name, options, filename)
394
+ default_type =
395
+ case internal_name
396
+ when /\.rb/i then Exerb::FileTable::Entry::FLAG_TYPE_RUBY_SCRIPT
397
+ when /\.so/i then Exerb::FileTable::Entry::FLAG_TYPE_EXTENSION_LIBRARY
398
+ when /\.dll/i then Exerb::FileTable::Entry::FLAG_TYPE_DYNAMIC_LIBRARY
399
+ when /\.res/i then Exerb::FileTable::Entry::FLAG_TYPE_RESOURCE_LIBRARY
400
+ when /\.dat/i then Exerb::FileTable::Entry::FLAG_TYPE_DATA_BINARY
401
+ else Exerb::FileTable::Entry::FLAG_TYPE_RUBY_SCRIPT
402
+ end
403
+
404
+ type = options['type'].to_s.downcase
405
+
406
+ case type
407
+ when '' then return default_type
408
+ when 'script' then return Exerb::FileTable::Entry::FLAG_TYPE_RUBY_SCRIPT
409
+ when 'extension-library' then return Exerb::FileTable::Entry::FLAG_TYPE_EXTENSION_LIBRARY
410
+ when 'dynamic-library' then return Exerb::FileTable::Entry::FLAG_TYPE_DYNAMIC_LIBRARY
411
+ when 'resource-library' then return Exerb::FileTable::Entry::FLAG_TYPE_RESOURCE_LIBRARY
412
+ when 'data' then return Exerb::FileTable::Entry::FLAG_TYPE_DATA_BINARY
413
+ when 'compiled-script' then return Exerb::FileTable::Entry::FLAG_TYPE_COMPILED_SCRIPT
414
+ else raise(Exerb::ExerbError, "#{filename}: [#{type}] is unknown type at file entry")
415
+ end
416
+ end
417
+ protected :analyze_option_type
418
+
419
+ def analyze_option_flag(options, filename, type)
420
+ case options['flag']
421
+ when nil then flag = []
422
+ when String then flag = [options['flag']]
423
+ when Array then flag = options['flag']
424
+ else raise(Exerb::ExerbError, "#{filename}: flag field of file entry must be String or Array object")
425
+ end
426
+
427
+ known_flags =
428
+ case type
429
+ when Exerb::FileTable::Entry::FLAG_TYPE_RUBY_SCRIPT then {} # {'compile_by_bruby' => ...}
430
+ when Exerb::FileTable::Entry::FLAG_TYPE_EXTENSION_LIBRARY then {'no_replace_function' => Exerb::FileTable::Entry::FLAG_NO_REPLACE_FUNCTION}
431
+ when Exerb::FileTable::Entry::FLAG_TYPE_DYNAMIC_LIBRARY then {}
432
+ when Exerb::FileTable::Entry::FLAG_TYPE_RESOURCE_LIBRARY then {}
433
+ when Exerb::FileTable::Entry::FLAG_TYPE_DATA_BINARY then {}
434
+ when Exerb::FileTable::Entry::FLAG_TYPE_COMPILED_SCRIPT then {}
435
+ end
436
+
437
+ selected_flags = known_flags.keys.select { |name|
438
+ flag.delete(name)
439
+ }.collect { |name|
440
+ known_flags[name]
441
+ }
442
+
443
+ unless flag.empty?
444
+ raise(Exerb::ExerbError, "#{filename}: found unknown flag in file entry -- #{flag.join(', ')}")
445
+ end
446
+
447
+ return selected_flags
448
+ end
449
+ protected :analyze_option_flag
450
+
451
+ end # Exerb::Recipe::FileBlock::FileEntry
452
+
453
+ #==============================================================================#
454
+
455
+ if $0 == __FILE__
456
+ recipe = Exerb::Recipe.load(ARGV.shift)
457
+ p(recipe)
458
+ p(recipe.archive_filepath)
459
+ p(recipe.output_filepath)
460
+ p(recipe.core_filepath)
461
+ recipe.create_archive.write_to_file('tmp.exa')
462
+ end
463
+
464
+ #==============================================================================#
465
+ #==============================================================================#