rubysl-dl 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +0 -1
- data/.travis.yml +8 -0
- data/README.md +2 -2
- data/Rakefile +0 -1
- data/ext/rubysl/dl/depend +46 -0
- data/ext/rubysl/dl/dl.c +742 -0
- data/ext/rubysl/dl/dl.def +59 -0
- data/ext/rubysl/dl/dl.h +313 -0
- data/ext/rubysl/dl/extconf.rb +193 -0
- data/ext/rubysl/dl/h2rb +500 -0
- data/ext/rubysl/dl/handle.c +215 -0
- data/ext/rubysl/dl/install.rb +49 -0
- data/ext/rubysl/dl/lib/dl/import.rb +225 -0
- data/ext/rubysl/dl/lib/dl/struct.rb +149 -0
- data/ext/rubysl/dl/lib/dl/types.rb +245 -0
- data/ext/rubysl/dl/lib/dl/win32.rb +25 -0
- data/ext/rubysl/dl/mkcall.rb +69 -0
- data/ext/rubysl/dl/mkcallback.rb +63 -0
- data/ext/rubysl/dl/mkcbtable.rb +25 -0
- data/ext/rubysl/dl/ptr.c +1062 -0
- data/ext/rubysl/dl/sample/c++sample.C +35 -0
- data/ext/rubysl/dl/sample/c++sample.rb +60 -0
- data/ext/rubysl/dl/sample/drives.rb +70 -0
- data/ext/rubysl/dl/sample/getch.rb +5 -0
- data/ext/rubysl/dl/sample/libc.rb +69 -0
- data/ext/rubysl/dl/sample/msgbox.rb +19 -0
- data/ext/rubysl/dl/sample/msgbox2.rb +18 -0
- data/ext/rubysl/dl/sample/stream.rb +87 -0
- data/ext/rubysl/dl/sym.c +993 -0
- data/ext/rubysl/dl/test/libtest.def +28 -0
- data/ext/rubysl/dl/test/test.c +247 -0
- data/ext/rubysl/dl/test/test.rb +306 -0
- data/ext/rubysl/dl/type.rb +115 -0
- data/lib/dl.rb +1 -0
- data/lib/rubysl/dl.rb +2 -0
- data/lib/rubysl/dl/version.rb +5 -0
- data/rubysl-dl.gemspec +20 -18
- metadata +109 -87
- data/lib/rubysl-dl.rb +0 -7
- data/lib/rubysl-dl/version.rb +0 -5
@@ -0,0 +1,149 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'dl'
|
4
|
+
require 'dl/import'
|
5
|
+
|
6
|
+
module DL
|
7
|
+
module Importable
|
8
|
+
module Internal
|
9
|
+
def define_struct(contents)
|
10
|
+
init_types()
|
11
|
+
Struct.new(@types, contents)
|
12
|
+
end
|
13
|
+
alias struct define_struct
|
14
|
+
|
15
|
+
def define_union(contents)
|
16
|
+
init_types()
|
17
|
+
Union.new(@types, contents)
|
18
|
+
end
|
19
|
+
alias union define_union
|
20
|
+
|
21
|
+
class Memory
|
22
|
+
def initialize(ptr, names, ty, len, enc, dec)
|
23
|
+
@ptr = ptr
|
24
|
+
@names = names
|
25
|
+
@ty = ty
|
26
|
+
@len = len
|
27
|
+
@enc = enc
|
28
|
+
@dec = dec
|
29
|
+
|
30
|
+
# define methods
|
31
|
+
@names.each{|name|
|
32
|
+
instance_eval [
|
33
|
+
"def #{name}",
|
34
|
+
" v = @ptr[\"#{name}\"]",
|
35
|
+
" if( @len[\"#{name}\"] )",
|
36
|
+
" v = v.collect{|x| @dec[\"#{name}\"] ? @dec[\"#{name}\"].call(x) : x }",
|
37
|
+
" else",
|
38
|
+
" v = @dec[\"#{name}\"].call(v) if @dec[\"#{name}\"]",
|
39
|
+
" end",
|
40
|
+
" return v",
|
41
|
+
"end",
|
42
|
+
"def #{name}=(v)",
|
43
|
+
" if( @len[\"#{name}\"] )",
|
44
|
+
" v = v.collect{|x| @enc[\"#{name}\"] ? @enc[\"#{name}\"].call(x) : x }",
|
45
|
+
" else",
|
46
|
+
" v = @enc[\"#{name}\"].call(v) if @enc[\"#{name}\"]",
|
47
|
+
" end",
|
48
|
+
" @ptr[\"#{name}\"] = v",
|
49
|
+
" return v",
|
50
|
+
"end",
|
51
|
+
].join("\n")
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_ptr
|
56
|
+
return @ptr
|
57
|
+
end
|
58
|
+
|
59
|
+
def size
|
60
|
+
return @ptr.size
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Struct
|
65
|
+
def initialize(types, contents)
|
66
|
+
@names = []
|
67
|
+
@ty = {}
|
68
|
+
@len = {}
|
69
|
+
@enc = {}
|
70
|
+
@dec = {}
|
71
|
+
@size = 0
|
72
|
+
@tys = ""
|
73
|
+
@types = types
|
74
|
+
parse(contents)
|
75
|
+
end
|
76
|
+
|
77
|
+
def size
|
78
|
+
return @size
|
79
|
+
end
|
80
|
+
|
81
|
+
def members
|
82
|
+
return @names
|
83
|
+
end
|
84
|
+
|
85
|
+
# ptr must be a PtrData object.
|
86
|
+
def new(ptr)
|
87
|
+
ptr.struct!(@tys, *@names)
|
88
|
+
mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
|
89
|
+
return mem
|
90
|
+
end
|
91
|
+
|
92
|
+
def malloc(size = nil)
|
93
|
+
if( !size )
|
94
|
+
size = @size
|
95
|
+
end
|
96
|
+
ptr = DL::malloc(size)
|
97
|
+
return new(ptr)
|
98
|
+
end
|
99
|
+
|
100
|
+
def parse(contents)
|
101
|
+
contents.each{|elem|
|
102
|
+
name,ty,num,enc,dec = parse_elem(elem)
|
103
|
+
@names.push(name)
|
104
|
+
@ty[name] = ty
|
105
|
+
@len[name] = num
|
106
|
+
@enc[name] = enc
|
107
|
+
@dec[name] = dec
|
108
|
+
if( num )
|
109
|
+
@tys += "#{ty}#{num}"
|
110
|
+
else
|
111
|
+
@tys += ty
|
112
|
+
end
|
113
|
+
}
|
114
|
+
@size = DL.sizeof(@tys)
|
115
|
+
end
|
116
|
+
|
117
|
+
def parse_elem(elem)
|
118
|
+
elem.strip!
|
119
|
+
case elem
|
120
|
+
when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)$/
|
121
|
+
ty = ($1 + $2).strip
|
122
|
+
name = $3
|
123
|
+
num = nil;
|
124
|
+
when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)\[(\d+)\]$/
|
125
|
+
ty = ($1 + $2).strip
|
126
|
+
name = $3
|
127
|
+
num = $4.to_i
|
128
|
+
else
|
129
|
+
raise(RuntimeError, "invalid element: #{elem}")
|
130
|
+
end
|
131
|
+
ty,enc,dec = @types.encode_struct_type(ty)
|
132
|
+
if( !ty )
|
133
|
+
raise(TypeError, "unsupported type: #{ty}")
|
134
|
+
end
|
135
|
+
return [name,ty,num,enc,dec]
|
136
|
+
end
|
137
|
+
end # class Struct
|
138
|
+
|
139
|
+
class Union < Struct
|
140
|
+
def new
|
141
|
+
ptr = DL::malloc(@size)
|
142
|
+
ptr.union!(@tys, *@names)
|
143
|
+
mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
|
144
|
+
return mem
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end # module Internal
|
148
|
+
end # module Importable
|
149
|
+
end # module DL
|
@@ -0,0 +1,245 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'dl'
|
4
|
+
|
5
|
+
module DL
|
6
|
+
class Types
|
7
|
+
TYPES = [
|
8
|
+
# FORMAT:
|
9
|
+
# ["alias name",
|
10
|
+
# "type name", encoding_method, decoding_method, for function prototypes
|
11
|
+
# "type name", encoding_method, decoding_method] for structures (not implemented)
|
12
|
+
|
13
|
+
# for Windows
|
14
|
+
["DWORD", "unsigned long", nil, nil,
|
15
|
+
"unsigned long", nil, nil],
|
16
|
+
["PDWORD", "unsigned long *", nil, nil,
|
17
|
+
"unsigned long *", nil, nil],
|
18
|
+
["WORD", "unsigned short", nil, nil,
|
19
|
+
"unsigned short", nil, nil],
|
20
|
+
["PWORD", "unsigned int *", nil, nil,
|
21
|
+
"unsigned int *", nil, nil],
|
22
|
+
["BYTE", "unsigned char", nil, nil,
|
23
|
+
"unsigned char", nil, nil],
|
24
|
+
["PBYTE", "unsigned char *", nil, nil,
|
25
|
+
"unsigned char *", nil, nil],
|
26
|
+
["BOOL", "ibool", nil, nil,
|
27
|
+
"ibool", nil, nil],
|
28
|
+
["ATOM", "int", nil, nil,
|
29
|
+
"int", nil, nil],
|
30
|
+
["BYTE", "unsigned char", nil, nil,
|
31
|
+
"unsigned char", nil, nil],
|
32
|
+
["PBYTE", "unsigned char *", nil, nil,
|
33
|
+
"unsigned char *", nil, nil],
|
34
|
+
["UINT", "unsigned int", nil, nil,
|
35
|
+
"unsigned int", nil, nil],
|
36
|
+
["ULONG", "unsigned long", nil, nil,
|
37
|
+
"unsigned long", nil, nil],
|
38
|
+
["UCHAR", "unsigned char", nil, nil,
|
39
|
+
"unsigned char", nil, nil],
|
40
|
+
["HANDLE", "unsigned long", nil, nil,
|
41
|
+
"unsigned long", nil, nil],
|
42
|
+
["PHANDLE","void*", nil, nil,
|
43
|
+
"void*", nil, nil],
|
44
|
+
["PVOID", "void*", nil, nil,
|
45
|
+
"void*", nil, nil],
|
46
|
+
["LPCSTR", "char*", nil, nil,
|
47
|
+
"char*", nil, nil],
|
48
|
+
["HDC", "unsigned int", nil, nil,
|
49
|
+
"unsigned int", nil, nil],
|
50
|
+
["HWND", "unsigned int", nil, nil,
|
51
|
+
"unsigned int", nil, nil],
|
52
|
+
|
53
|
+
# Others
|
54
|
+
["uint", "unsigned int", nil, nil,
|
55
|
+
"unsigned int", nil, nil],
|
56
|
+
["u_int", "unsigned int", nil, nil,
|
57
|
+
"unsigned int", nil, nil],
|
58
|
+
["ulong", "unsigned long", nil, nil,
|
59
|
+
"unsigned long", nil, nil],
|
60
|
+
["u_long", "unsigned long", nil, nil,
|
61
|
+
"unsigned long", nil, nil],
|
62
|
+
|
63
|
+
# DL::Importable primitive types
|
64
|
+
["ibool",
|
65
|
+
"I",
|
66
|
+
proc{|v| v ? 1 : 0},
|
67
|
+
proc{|v| (v != 0) ? true : false},
|
68
|
+
"I",
|
69
|
+
proc{|v| v ? 1 : 0 },
|
70
|
+
proc{|v| (v != 0) ? true : false} ],
|
71
|
+
["cbool",
|
72
|
+
"C",
|
73
|
+
proc{|v| v ? 1 : 0},
|
74
|
+
proc{|v| (v != 0) ? true : false},
|
75
|
+
"C",
|
76
|
+
proc{|v,len| v ? 1 : 0},
|
77
|
+
proc{|v,len| (v != 0) ? true : false}],
|
78
|
+
["lbool",
|
79
|
+
"L",
|
80
|
+
proc{|v| v ? 1 : 0},
|
81
|
+
proc{|v| (v != 0) ? true : false},
|
82
|
+
"L",
|
83
|
+
proc{|v,len| v ? 1 : 0},
|
84
|
+
proc{|v,len| (v != 0) ? true : false}],
|
85
|
+
["unsigned char",
|
86
|
+
"C",
|
87
|
+
proc{|v| [v].pack("C").unpack("c")[0]},
|
88
|
+
proc{|v| [v].pack("c").unpack("C")[0]},
|
89
|
+
"C",
|
90
|
+
proc{|v| [v].pack("C").unpack("c")[0]},
|
91
|
+
proc{|v| [v].pack("c").unpack("C")[0]}],
|
92
|
+
["unsigned short",
|
93
|
+
"H",
|
94
|
+
proc{|v| [v].pack("S").unpack("s")[0]},
|
95
|
+
proc{|v| [v].pack("s").unpack("S")[0]},
|
96
|
+
"H",
|
97
|
+
proc{|v| [v].pack("S").unpack("s")[0]},
|
98
|
+
proc{|v| [v].pack("s").unpack("S")[0]}],
|
99
|
+
["unsigned int",
|
100
|
+
"I",
|
101
|
+
proc{|v| [v].pack("I").unpack("i")[0]},
|
102
|
+
proc{|v| [v].pack("i").unpack("I")[0]},
|
103
|
+
"I",
|
104
|
+
proc{|v| [v].pack("I").unpack("i")[0]},
|
105
|
+
proc{|v| [v].pack("i").unpack("I")[0]}],
|
106
|
+
["unsigned long",
|
107
|
+
"L",
|
108
|
+
proc{|v| [v].pack("L").unpack("l")[0]},
|
109
|
+
proc{|v| [v].pack("l").unpack("L")[0]},
|
110
|
+
"L",
|
111
|
+
proc{|v| [v].pack("L").unpack("l")[0]},
|
112
|
+
proc{|v| [v].pack("l").unpack("L")[0]}],
|
113
|
+
["unsigned char ref",
|
114
|
+
"c",
|
115
|
+
proc{|v| [v].pack("C").unpack("c")[0]},
|
116
|
+
proc{|v| [v].pack("c").unpack("C")[0]},
|
117
|
+
nil, nil, nil],
|
118
|
+
["unsigned int ref",
|
119
|
+
"i",
|
120
|
+
proc{|v| [v].pack("I").unpack("i")[0]},
|
121
|
+
proc{|v| [v].pack("i").unpack("I")[0]},
|
122
|
+
nil, nil, nil],
|
123
|
+
["unsigned long ref",
|
124
|
+
"l",
|
125
|
+
proc{|v| [v].pack("L").unpack("l")[0]},
|
126
|
+
proc{|v| [v].pack("l").unpack("L")[0]},
|
127
|
+
nil, nil, nil],
|
128
|
+
["char ref", "c", nil, nil,
|
129
|
+
nil, nil, nil],
|
130
|
+
["short ref", "h", nil, nil,
|
131
|
+
nil, nil, nil],
|
132
|
+
["int ref", "i", nil, nil,
|
133
|
+
nil, nil, nil],
|
134
|
+
["long ref", "l", nil, nil,
|
135
|
+
nil, nil, nil],
|
136
|
+
["float ref", "f", nil, nil,
|
137
|
+
nil, nil, nil],
|
138
|
+
["double ref","d", nil, nil,
|
139
|
+
nil, nil, nil],
|
140
|
+
["char", "C", nil, nil,
|
141
|
+
"C", nil, nil],
|
142
|
+
["short", "H", nil, nil,
|
143
|
+
"H", nil, nil],
|
144
|
+
["int", "I", nil, nil,
|
145
|
+
"I", nil, nil],
|
146
|
+
["long", "L", nil, nil,
|
147
|
+
"L", nil, nil],
|
148
|
+
["float", "F", nil, nil,
|
149
|
+
"F", nil, nil],
|
150
|
+
["double", "D", nil, nil,
|
151
|
+
"D", nil, nil],
|
152
|
+
[/^char\s*\*$/,"s",nil, nil,
|
153
|
+
"S",nil, nil],
|
154
|
+
[/^const char\s*\*$/,"S",nil, nil,
|
155
|
+
"S",nil, nil],
|
156
|
+
[/^.+\*$/, "P", nil, nil,
|
157
|
+
"P", nil, nil],
|
158
|
+
[/^.+\[\]$/, "a", nil, nil,
|
159
|
+
"a", nil, nil],
|
160
|
+
["void", "0", nil, nil,
|
161
|
+
nil, nil, nil],
|
162
|
+
]
|
163
|
+
|
164
|
+
def initialize
|
165
|
+
init_types()
|
166
|
+
end
|
167
|
+
|
168
|
+
def typealias(ty1, ty2, enc=nil, dec=nil, ty3=nil, senc=nil, sdec=nil)
|
169
|
+
@TYDEFS.unshift([ty1, ty2, enc, dec, ty3, senc, sdec])
|
170
|
+
end
|
171
|
+
|
172
|
+
def init_types
|
173
|
+
@TYDEFS = TYPES.dup
|
174
|
+
end
|
175
|
+
|
176
|
+
def encode_argument_type(alias_type)
|
177
|
+
proc_encode = nil
|
178
|
+
proc_decode = nil
|
179
|
+
@TYDEFS.each{|aty,ty,enc,dec,_,_,_|
|
180
|
+
if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
|
181
|
+
alias_type = alias_type.gsub(aty,ty) if ty
|
182
|
+
alias_type.strip! if alias_type
|
183
|
+
if( proc_encode )
|
184
|
+
if( enc )
|
185
|
+
conv1 = proc_encode
|
186
|
+
proc_encode = proc{|v| enc.call(conv1.call(v))}
|
187
|
+
end
|
188
|
+
else
|
189
|
+
if( enc )
|
190
|
+
proc_encode = enc
|
191
|
+
end
|
192
|
+
end
|
193
|
+
if( proc_decode )
|
194
|
+
if( dec )
|
195
|
+
conv2 = proc_decode
|
196
|
+
proc_decode = proc{|v| dec.call(conv2.call(v))}
|
197
|
+
end
|
198
|
+
else
|
199
|
+
if( dec )
|
200
|
+
proc_decode = dec
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
}
|
205
|
+
return [alias_type, proc_encode, proc_decode]
|
206
|
+
end
|
207
|
+
|
208
|
+
def encode_return_type(ty)
|
209
|
+
ty, enc, dec = encode_argument_type(ty)
|
210
|
+
return [ty, enc, dec]
|
211
|
+
end
|
212
|
+
|
213
|
+
def encode_struct_type(alias_type)
|
214
|
+
proc_encode = nil
|
215
|
+
proc_decode = nil
|
216
|
+
@TYDEFS.each{|aty,_,_,_,ty,enc,dec|
|
217
|
+
if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
|
218
|
+
alias_type = alias_type.gsub(aty,ty) if ty
|
219
|
+
alias_type.strip! if alias_type
|
220
|
+
if( proc_encode )
|
221
|
+
if( enc )
|
222
|
+
conv1 = proc_encode
|
223
|
+
proc_encode = proc{|v| enc.call(conv1.call(v))}
|
224
|
+
end
|
225
|
+
else
|
226
|
+
if( enc )
|
227
|
+
proc_encode = enc
|
228
|
+
end
|
229
|
+
end
|
230
|
+
if( proc_decode )
|
231
|
+
if( dec )
|
232
|
+
conv2 = proc_decode
|
233
|
+
proc_decode = proc{|v| dec.call(conv2.call(v))}
|
234
|
+
end
|
235
|
+
else
|
236
|
+
if( dec )
|
237
|
+
proc_decode = dec
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
}
|
242
|
+
return [alias_type, proc_encode, proc_decode]
|
243
|
+
end
|
244
|
+
end # end of Types
|
245
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'dl'
|
4
|
+
|
5
|
+
class Win32API
|
6
|
+
DLL = {}
|
7
|
+
|
8
|
+
def initialize(dllname, func, import, export = "0")
|
9
|
+
prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI").sub(/^(.)0*$/, '\1')
|
10
|
+
handle = DLL[dllname] ||= DL::Handle.new(dllname)
|
11
|
+
@sym = handle.sym(func, prototype)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(*args)
|
15
|
+
import = @sym.proto.split("", 2)[1]
|
16
|
+
args.each_with_index do |x, i|
|
17
|
+
args[i] = nil if x == 0 and import[i] == ?S
|
18
|
+
args[i], = [x].pack("I").unpack("i") if import[i] == ?I
|
19
|
+
end
|
20
|
+
ret, = @sym.call(*args)
|
21
|
+
return ret || 0
|
22
|
+
end
|
23
|
+
|
24
|
+
alias Call call
|
25
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
$:.unshift File.dirname(__FILE__)
|
5
|
+
require 'type'
|
6
|
+
require 'dlconfig'
|
7
|
+
|
8
|
+
if name = ARGV.shift
|
9
|
+
OUTPUT = File.open name, "wb"
|
10
|
+
at_exit { OUTPUT.close }
|
11
|
+
else
|
12
|
+
OUTPUT = STDOUT
|
13
|
+
end
|
14
|
+
|
15
|
+
def output_arg(x,i)
|
16
|
+
"args[#{i}].#{DLTYPE[x][:stmem]}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def output_args(types)
|
20
|
+
t = []
|
21
|
+
types[1..-1].each_with_index{|x,i| t.push(output_arg(x,i))}
|
22
|
+
t.join(",")
|
23
|
+
end
|
24
|
+
|
25
|
+
def output_callfunc(types)
|
26
|
+
t = types[0]
|
27
|
+
stmem = DLTYPE[t][:stmem]
|
28
|
+
ctypes = types2ctypes(types)
|
29
|
+
if( t == VOID )
|
30
|
+
callstm = "(*f)(#{output_args(types)})"
|
31
|
+
else
|
32
|
+
callstm = "ret.#{stmem} = (*f)(#{output_args(types)})"
|
33
|
+
end
|
34
|
+
[ "{",
|
35
|
+
"#{ctypes[0]} (*f)(#{ctypes[1..-1].join(',')}) = func;",
|
36
|
+
"#{callstm};",
|
37
|
+
"}"].join(" ")
|
38
|
+
end
|
39
|
+
|
40
|
+
def output_case(types)
|
41
|
+
num = types2num(types)
|
42
|
+
callfunc_stm = output_callfunc(types)
|
43
|
+
<<EOF
|
44
|
+
case #{num}:
|
45
|
+
#ifdef DEBUG
|
46
|
+
OUTPUT.printf("#{callfunc_stm}\\n");
|
47
|
+
#endif
|
48
|
+
#{callfunc_stm};
|
49
|
+
break;
|
50
|
+
EOF
|
51
|
+
end
|
52
|
+
|
53
|
+
def rec_output(types = [VOID])
|
54
|
+
OUTPUT.print output_case(types)
|
55
|
+
if( types.length <= MAX_ARG )
|
56
|
+
DLTYPE.keys.sort.each{|t|
|
57
|
+
if( t != VOID && DLTYPE[t][:sym] )
|
58
|
+
rec_output(types + [t])
|
59
|
+
end
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
DLTYPE.keys.sort.each{|t|
|
65
|
+
if( DLTYPE[t][:sym] )
|
66
|
+
$stderr.printf(" #{DLTYPE[t][:ctype]}\n")
|
67
|
+
rec_output([t])
|
68
|
+
end
|
69
|
+
}
|