exerb 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ #==============================================================================#