cddlc 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c0fb30da3097b44521e7c3fe12d6e061f7d4f64d9faa3c1239c22a8e76b629e5
4
- data.tar.gz: 7cc5c141bd3833d11efb95ab25dd7649666ee6398efb3c01d95dc7cd8a220802
3
+ metadata.gz: aa1feed69996a1e91c43877cfbe3e68c6b935039976ae95db312fef99a0e8bbd
4
+ data.tar.gz: 746c4b175cb78c502ab731e43672841663cfb4a4159bcf387f8f69c9f34e347a
5
5
  SHA512:
6
- metadata.gz: d119b506cf51407c66e882df9bcc59e2019926c3843d8ad5acb0a5dede020f6ecb099284eded1a6cae912db42347edafabb3be79a789d4afd2153015258abe6c
7
- data.tar.gz: b30fb2251c6daaba6fe3c20a85800b64af61a1908a4ab80596891bf88687f7ec2e441649d9f05d4268e24c9a77c0818cd188a8deada0642ba20fc75961445abd
6
+ metadata.gz: c9b58614695995f0336496734a3684992ddd6f7a1be0dfcbc0451f45afde7e78eb2a2f89ce60e9c5e0c09a1c0e7e8856cc5e5658fe3fe78bc22bc08c4897c4d4
7
+ data.tar.gz: d19ca545ca39eb87af227651438755c13475dd75bd29ef11a6a6327aac42e9c4a69fe0e5322a291e7819903d89c4de1296e1605934bce9b154dcb7ef6563c151
data/bin/cddlc CHANGED
@@ -44,7 +44,7 @@ require 'ostruct'
44
44
  $options = OpenStruct.new
45
45
  begin
46
46
  op = OptionParser.new do |opts|
47
- opts.banner = "Usage: cddlc.rb [options] file.cddl"
47
+ opts.banner = "Usage: cddlc.rb [options] [file.cddl... | -]"
48
48
 
49
49
  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
50
50
  $options.verbose = v
@@ -64,6 +64,17 @@ begin
64
64
  opts.on("-tFMT", "--to=FMT", [:basic, :neat, :json, :yaml, :enum, :cddl], "Target format") do |v|
65
65
  $options.target = v
66
66
  end
67
+ opts.on("-sRULE", "--start=RULE", String, "Start rule name") do |v|
68
+ $options.start = v
69
+ end
70
+ opts.on("-iIMPORT", "--import=IMPORT", String, "Import [namespace=]reference") do |v|
71
+ $options.import ||= []
72
+ $options.import << v
73
+ end
74
+ opts.on("-IINCLUDE", "--include=INCLUDE", String, "Include [namespace=]reference") do |v|
75
+ $options.include ||= []
76
+ $options.include << v
77
+ end
67
78
  end
68
79
  op.parse!
69
80
  rescue Exception => e
@@ -71,11 +82,40 @@ rescue Exception => e
71
82
  exit 1
72
83
  end
73
84
 
85
+ cddl_file = ""
86
+ if $options.start
87
+ cddl_file << "$.start.$ = #{$options.start}\n"
88
+ end
89
+
90
+ [[$options.include, "include"], [$options.import, "import"]].each do |arr, directive|
91
+ if arr
92
+ arr.each do |ref|
93
+ asname, refname = ref.split("=", 2)
94
+ unless refname
95
+ refname = asname
96
+ asname = nil
97
+ end
98
+ cddl_file << ";# #{directive} #{refname}"
99
+ cddl_file << " as #{asname}" if asname
100
+ cddl_file << "\n"
101
+ end
102
+ end
103
+ end
104
+
105
+ if $options.verbose
106
+ warn "::: generated from options:"
107
+ warn cddl_file
108
+ warn ":::\n\n"
109
+ end
110
+
74
111
  if ARGV == []
75
- puts op
76
- exit 1
112
+ if cddl_file == ""
113
+ puts op
114
+ exit 1
115
+ end
116
+ else
117
+ cddl_file << ARGF.read
77
118
  end
78
- cddl_file = ARGF.read
79
119
 
80
120
  cddl = CDDL.from_cddl(cddl_file)
81
121
  result = if $options.rules
data/cddlc.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cddlc"
3
- s.version = "0.1.3"
3
+ s.version = "0.1.5"
4
4
  s.summary = "CDDL (Concise Data Definition Language) converters and miscellaneous tools"
5
5
  s.description = %q{cddlc implements converters and miscellaneous tools for CDDL, RFC 8610}
6
6
  s.author = "Carsten Bormann"
@@ -15,6 +15,6 @@ Gem::Specification.new do |s|
15
15
 
16
16
  s.add_development_dependency 'bundler', '~>1'
17
17
  s.add_dependency 'treetop', '~>1'
18
- s.add_dependency 'json'
19
- s.add_dependency 'neatjson'
18
+ s.add_dependency 'json', '~>2'
19
+ s.add_dependency 'neatjson', '~>0.10'
20
20
  end
@@ -0,0 +1,213 @@
1
+
2
+ grasp-message = (message .within message-structure) / noop-message
3
+
4
+ message-structure = [MESSAGE_TYPE, session-id, ?initiator,
5
+ *grasp-option]
6
+
7
+ MESSAGE_TYPE = 0..255
8
+ session-id = 0..4294967295 ; up to 32 bits
9
+ grasp-option = any
10
+
11
+
12
+ discovery-message = [M_DISCOVERY, session-id, initiator, objective]
13
+
14
+
15
+ response-message = [M_RESPONSE, session-id, initiator, ttl,
16
+ (+locator-option // divert-option), ?objective]
17
+
18
+ ttl = 0..4294967295 ; in milliseconds
19
+
20
+
21
+ request-negotiation-message = [M_REQ_NEG, session-id, objective]
22
+
23
+ request-synchronization-message = [M_REQ_SYN, session-id, objective]
24
+
25
+
26
+ negotiation-message = [M_NEGOTIATE, session-id, objective]
27
+
28
+
29
+ end-message = [M_END, session-id, accept-option / decline-option]
30
+
31
+
32
+ wait-message = [M_WAIT, session-id, waiting-time]
33
+ waiting-time = 0..4294967295 ; in milliseconds
34
+
35
+
36
+ synch-message = [M_SYNCH, session-id, objective]
37
+
38
+
39
+ flood-message = [M_FLOOD, session-id, initiator, ttl,
40
+ +[objective, (locator-option / [])]]
41
+
42
+ ttl = 0..4294967295 ; in milliseconds
43
+
44
+
45
+ invalid-message = [M_INVALID, session-id, ?any]
46
+
47
+
48
+ noop-message = [M_NOOP]
49
+
50
+
51
+ divert-option = [O_DIVERT, +locator-option]
52
+
53
+
54
+ accept-option = [O_ACCEPT]
55
+
56
+
57
+ decline-option = [O_DECLINE, ?reason]
58
+ reason = text ; optional UTF-8 error message
59
+
60
+
61
+ ipv6-locator-option = [O_IPv6_LOCATOR, ipv6-address,
62
+ transport-proto, port-number]
63
+ ipv6-address = bytes .size 16
64
+
65
+ transport-proto = IPPROTO_TCP / IPPROTO_UDP
66
+ IPPROTO_TCP = 6
67
+ IPPROTO_UDP = 17
68
+ port-number = 0..65535
69
+
70
+
71
+ ipv4-locator-option = [O_IPv4_LOCATOR, ipv4-address,
72
+ transport-proto, port-number]
73
+ ipv4-address = bytes .size 4
74
+
75
+
76
+ fqdn-locator-option = [O_FQDN_LOCATOR, text,
77
+ transport-proto, port-number]
78
+
79
+
80
+ uri-locator-option = [O_URI_LOCATOR, text,
81
+ transport-proto / null, port-number / null]
82
+
83
+
84
+ objective = [objective-name, objective-flags,
85
+ loop-count, ?objective-value]
86
+
87
+ objective-name = text
88
+ objective-value = any
89
+ loop-count = 0..255
90
+
91
+
92
+ objective-flags = uint .bits objective-flag
93
+ objective-flag = &(
94
+ F_DISC: 0 ; valid for discovery
95
+ F_NEG: 1 ; valid for negotiation
96
+ F_SYNCH: 2 ; valid for synchronization
97
+ F_NEG_DRY: 3 ; negotiation is a dry run
98
+ )
99
+
100
+
101
+ grasp-message = (message .within message-structure) / noop-message
102
+
103
+ message-structure = [MESSAGE_TYPE, session-id, ?initiator,
104
+ *grasp-option]
105
+
106
+ MESSAGE_TYPE = 0..255
107
+ session-id = 0..4294967295 ; up to 32 bits
108
+ grasp-option = any
109
+
110
+ message /= discovery-message
111
+ discovery-message = [M_DISCOVERY, session-id, initiator, objective]
112
+
113
+ message /= response-message ; response to Discovery
114
+ response-message = [M_RESPONSE, session-id, initiator, ttl,
115
+ (+locator-option // divert-option), ?objective]
116
+
117
+ message /= synch-message ; response to Synchronization request
118
+ synch-message = [M_SYNCH, session-id, objective]
119
+
120
+ message /= flood-message
121
+ flood-message = [M_FLOOD, session-id, initiator, ttl,
122
+ +[objective, (locator-option / [])]]
123
+
124
+ message /= request-negotiation-message
125
+ request-negotiation-message = [M_REQ_NEG, session-id, objective]
126
+
127
+ message /= request-synchronization-message
128
+ request-synchronization-message = [M_REQ_SYN, session-id, objective]
129
+
130
+ message /= negotiation-message
131
+ negotiation-message = [M_NEGOTIATE, session-id, objective]
132
+
133
+ message /= end-message
134
+ end-message = [M_END, session-id, accept-option / decline-option]
135
+
136
+ message /= wait-message
137
+ wait-message = [M_WAIT, session-id, waiting-time]
138
+
139
+ message /= invalid-message
140
+ invalid-message = [M_INVALID, session-id, ?any]
141
+
142
+ noop-message = [M_NOOP]
143
+
144
+ divert-option = [O_DIVERT, +locator-option]
145
+
146
+ accept-option = [O_ACCEPT]
147
+
148
+ decline-option = [O_DECLINE, ?reason]
149
+ reason = text ; optional UTF-8 error message
150
+
151
+ waiting-time = 0..4294967295 ; in milliseconds
152
+ ttl = 0..4294967295 ; in milliseconds
153
+
154
+ locator-option /= [O_IPv4_LOCATOR, ipv4-address,
155
+ transport-proto, port-number]
156
+ ipv4-address = bytes .size 4
157
+
158
+ locator-option /= [O_IPv6_LOCATOR, ipv6-address,
159
+ transport-proto, port-number]
160
+ ipv6-address = bytes .size 16
161
+
162
+ locator-option /= [O_FQDN_LOCATOR, text, transport-proto,
163
+ port-number]
164
+
165
+ locator-option /= [O_URI_LOCATOR, text,
166
+ transport-proto / null, port-number / null]
167
+
168
+ transport-proto = IPPROTO_TCP / IPPROTO_UDP
169
+ IPPROTO_TCP = 6
170
+ IPPROTO_UDP = 17
171
+ port-number = 0..65535
172
+
173
+ initiator = ipv4-address / ipv6-address
174
+
175
+ objective-flags = uint .bits objective-flag
176
+
177
+ objective-flag = &(
178
+ F_DISC: 0 ; valid for discovery
179
+ F_NEG: 1 ; valid for negotiation
180
+ F_SYNCH: 2 ; valid for synchronization
181
+ F_NEG_DRY: 3 ; negotiation is a dry run
182
+ )
183
+
184
+ objective = [objective-name, objective-flags,
185
+ loop-count, ?objective-value]
186
+
187
+ objective-name = text ; see section "Format of Objective Options"
188
+
189
+ objective-value = any
190
+
191
+ loop-count = 0..255
192
+
193
+ ; Constants for message types and option types
194
+
195
+ M_NOOP = 0
196
+ M_DISCOVERY = 1
197
+ M_RESPONSE = 2
198
+ M_REQ_NEG = 3
199
+ M_REQ_SYN = 4
200
+ M_NEGOTIATE = 5
201
+ M_END = 6
202
+ M_WAIT = 7
203
+ M_SYNCH = 8
204
+ M_FLOOD = 9
205
+ M_INVALID = 99
206
+
207
+ O_DIVERT = 100
208
+ O_ACCEPT = 101
209
+ O_DECLINE = 102
210
+ O_IPv6_LOCATOR = 103
211
+ O_IPv4_LOCATOR = 104
212
+ O_FQDN_LOCATOR = 105
213
+ O_URI_LOCATOR = 106
data/lib/cddlc.rb CHANGED
@@ -39,7 +39,22 @@ class CDDL
39
39
  end])
40
40
  end
41
41
 
42
+ def self.read_from_include_path(fn)
43
+ io = nil
44
+ CDDL::cddl_include_path.each do |path|
45
+ begin
46
+ io = (path + fn).open
47
+ break
48
+ rescue Errno::ENOENT
49
+ next
50
+ end
51
+ end
52
+ io
53
+ end
54
+
42
55
  SAFE_FN = /\A[-._a-zA-Z0-9]+\z/
56
+ IMPINC = /\A(?:import|include)\z/
57
+ IDENTIFIER_RE = /\A[A-Za-z@_$]([-.]*[A-Za-z@_$0-9])*\z/
43
58
 
44
59
  def self.from_cddl(s)
45
60
  ast = @@parser.parse s
@@ -50,92 +65,146 @@ class CDDL
50
65
  directives = s.lines.grep(/^;# /).map(&:chomp).map{|l| l.sub(/^;#\s+/, '').split(/\s+/)}
51
66
  # puts directives.to_yaml
52
67
  end
68
+
53
69
  ret = CDDL.new(ast, directives)
54
70
 
55
71
  if $options.cddl2
56
- ret.directives.each do |di|
57
- preferred_tag = nil
58
- case di
59
- in ["include" => dir, docref]
60
- in ["include" => dir, docref, "as", preferred_tag]
61
- in ["import" => dir, docref]
62
- in ["import" => dir, docref, "as", preferred_tag]
63
- else
64
- warn "** Can't parse include directive #{di.inspect}"
65
- next
66
- end
67
- unless docref =~ SAFE_FN
68
- warn "** skipping unsafe filename #{docref}"
69
- next
70
- end
71
- puts "PREFERRED_TAG #{preferred_tag}" if $options.verbose
72
- puts "DOCREF #{docref}" if $options.verbose
73
- fn = docref.downcase << ".cddl"
74
-
75
- io = nil
76
- CDDL::cddl_include_path.each do |path|
77
- begin
78
- io = (path + fn).open
79
- break
80
- rescue Errno::ENOENT
81
- next
72
+ ret.perform_directives
73
+ end
74
+ ret
75
+ end
76
+
77
+ def perform_directives
78
+ directives.each do |di|
79
+ preferred_tag = nil
80
+ from = nil
81
+ case di
82
+ in [IMPINC => dir, SAFE_FN => docref, "as", SAFE_FN => preferred_tag]
83
+ in [IMPINC => dir, SAFE_FN => docref]
84
+ in [IMPINC => dir, *from, "from", SAFE_FN => docref, "as", SAFE_FN => preferred_tag]
85
+ in [IMPINC => dir, *from, "from", SAFE_FN => docref]
86
+ else
87
+ warn "** Can't parse directive »#{di.join(" ")}«"
88
+ next
89
+ end
90
+ if from
91
+ from = from.map do |name|
92
+ name.chomp!(",")
93
+ if IDENTIFIER_RE === name
94
+ name
95
+ else
96
+ warn "*** invalid identifier #{name.inspect} ignored in »#{di.join(' ')}«"
97
+ nil
82
98
  end
83
- end
84
- unless io
85
- warn "** include file #{fn} not found in #{CDDL::cddl_include_path.map(&:to_s)}"
86
- next
87
- end
99
+ end.compact
100
+ end
101
+ puts "FROM #{from.inspect}" if $options.verbose
102
+ puts "PREFERRED_TAG #{preferred_tag.inspect}" if $options.verbose
103
+ puts "DOCREF #{docref.inspect}" if $options.verbose
88
104
 
89
- include_file = io.read
90
- included_cddl = CDDL.from_cddl(include_file)
91
- if preferred_tag
92
- included_cddl = included_cddl.deep_clone # needed?
93
- renamed_names = included_cddl.rules.keys
94
- name_rename = Hash[
95
- renamed_names.map { |o|
96
- n = "#{preferred_tag}.#{o}"
97
- warn "** Warning: renamed name #{n} already in #{fn}" if included_cddl.rules[n]
98
- [o, n]}]
99
- included_cddl.rename(name_rename)
100
- end
105
+ fn = docref.downcase << ".cddl"
106
+ io = CDDL.read_from_include_path(fn)
107
+ unless io
108
+ warn "** #{dir} file #{fn} not found in #{CDDL::cddl_include_path.map(&:to_s)}"
109
+ next
110
+ end
101
111
 
102
- case dir
103
- in "import"
104
- warn "** IMPORTING #{fn}" if $options.verbose
105
- undef_rule = nil
106
- loop do
107
- undef_rule = ret.cddl_undefined # XXX square...
108
- # p undef_rule
109
- got_more = false
110
- undef_rule.each do |name|
111
- if rule = included_cddl.rules[name]
112
- ret.rules[name] = rule
113
- warn "IMPORTED #{name} from #{fn}" if $options.verbose
114
- got_more = true
115
- end
112
+ include_file = io.read
113
+ included_cddl = CDDL.from_cddl(include_file)
114
+ if preferred_tag
115
+ included_cddl = included_cddl.deep_clone # needed?
116
+ renamed_names = included_cddl.rules.keys
117
+ name_rename = Hash[
118
+ renamed_names.map { |o|
119
+ n = "#{preferred_tag}.#{o}"
120
+ warn "** Warning: renamed name #{n} already in #{fn}" if included_cddl.rules[n]
121
+ [o, n]}]
122
+ included_cddl.rename(name_rename)
123
+ end
124
+
125
+ case dir
126
+ in "import"
127
+ warn "** IMPORTING #{from && from.join(", ") << " from "}#{fn}" if $options.verbose
128
+
129
+ must_be_found = false
130
+ to_be_imported = if from
131
+ if preferred_tag
132
+ from.map{ |k|
133
+ if k =~ /\A#{preferred_tag}[.]/
134
+ k
135
+ elsif nn = name_rename[k]
136
+ if old = store_rule(k, v = ["name", nn])
137
+ warn "*** autogenerated rule #{k} = #{v} would overwrite #{old}"
138
+ end
139
+ nn
140
+ else
141
+ warn_error "*** imported rule #{k.inspect} not in #{fn}"
142
+ end
143
+ }.compact
144
+ else
145
+ must_be_found = true
146
+ from
147
+ end
148
+ else
149
+ cddl_undefined
150
+ end
151
+ loop do
152
+ # p to_be_imported
153
+ got_more = false
154
+ to_be_imported.each do |name|
155
+ if rule = included_cddl.rules[name]
156
+ rules[name] = rule
157
+ warn "IMPORTED #{name} from #{fn}" if $options.verbose
158
+ got_more = true
159
+ elsif must_be_found
160
+ warn_error "*** imported rule #{name.inspect} not in #{fn}"
116
161
  end
117
- break unless got_more
118
162
  end
119
- if preferred_tag
120
- undef_rule.each do |name|
121
- warn "** Warning: undefined reference #{name} without namespace prefix is defined in namespaced imported module #{fn}" if name_rename[name]
122
- end
163
+ break unless got_more
164
+ to_be_imported = cddl_undefined # XXX square...
165
+ must_be_found = false
166
+ end
167
+ if preferred_tag
168
+ to_be_imported.each do |name|
169
+ warn "** Warning: undefined reference #{name} without namespace prefix is defined in namespaced imported module #{fn}" if name_rename[name]
170
+ ### instead just add rule...
123
171
  end
124
- in "include"
125
- warn "** INCLUDING #{fn}" if $options.verbose
126
- included_cddl.rules.each do |k, v|
127
- if old = ret.rules[k]
128
- if old != v
129
- warn "** included rule #{k} = #{v} would overwrite #{old}"
130
- end
131
- else
132
- ret.rules[k] = v
133
- end
172
+ end
173
+ in "include"
174
+ if from
175
+ from = Set[*from]
176
+ end
177
+ warn "** INCLUDING #{from && from.join(", ") << " from "}#{fn}" if $options.verbose
178
+ included_cddl.rules.each do |k, v|
179
+ if from
180
+ next unless from.include?(k)
181
+ from.delete(k)
134
182
  end
183
+ if old = store_rule(k, v)
184
+ warn "*** included rule #{k} = #{v} would overwrite #{old}"
185
+ end
186
+ end
187
+ if from && !from.empty?
188
+ warn "*** could not find #{from.join(", ")} in #{fn}"
135
189
  end
136
190
  end
137
191
  end
138
- ret
192
+ end
193
+
194
+ def store_rule(k, v)
195
+ if old = rules[k]
196
+ if old != v
197
+ return old # error
198
+ end
199
+ else
200
+ rules[k] = v
201
+ end
202
+ nil # OK
203
+ end
204
+
205
+ def warn_error(s)
206
+ warn s
207
+ @error = true
139
208
  end
140
209
 
141
210
  attr_accessor :ast, :tree, :directives
@@ -69,12 +69,7 @@ module CDDLGRAMMAR
69
69
  break
70
70
  end
71
71
  end
72
- if s2.empty?
73
- @index = i2
74
- r2 = nil
75
- else
76
- r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
77
- end
72
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
78
73
  s0 << r2
79
74
  end
80
75
  if s0.last
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cddlc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-06 00:00:00.000000000 Z
11
+ date: 2023-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -42,30 +42,30 @@ dependencies:
42
42
  name: json
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: neatjson
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.10'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '0.10'
69
69
  description: cddlc implements converters and miscellaneous tools for CDDL, RFC 8610
70
70
  email: cabo@tzi.org
71
71
  executables:
@@ -78,6 +78,7 @@ files:
78
78
  - data/prelude.cddl
79
79
  - data/rfc8727.cddl
80
80
  - data/rfc8927.cddl
81
+ - data/rfc8990-cleaned.cddl
81
82
  - data/rfc8990.cddl
82
83
  - data/rfc9052.cddl
83
84
  - data/rfc9053.cddl
@@ -122,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
123
  - !ruby/object:Gem::Version
123
124
  version: '0'
124
125
  requirements: []
125
- rubygems_version: 3.4.2
126
+ rubygems_version: 3.4.6
126
127
  signing_key:
127
128
  specification_version: 4
128
129
  summary: CDDL (Concise Data Definition Language) converters and miscellaneous tools