ridl 2.5.6 → 2.7.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.
@@ -8,7 +8,6 @@
8
8
  # included with this program.
9
9
  #
10
10
  # Copyright (c) Remedy IT Expertise BV
11
- # Chamber of commerce Rotterdam nr.276339, The Netherlands
12
11
  #--------------------------------------------------------------------
13
12
  require 'optparse'
14
13
 
@@ -2620,13 +2620,13 @@ module_eval(<<'.,.,', 'parser.ry', 316)
2620
2620
 
2621
2621
  module_eval(<<'.,.,', 'parser.ry', 318)
2622
2622
  def _reduce_174(val, _values)
2623
- [FALSE, [val[0]]]
2623
+ [false, [val[0]]]
2624
2624
  end
2625
2625
  .,.,
2626
2626
 
2627
2627
  module_eval(<<'.,.,', 'parser.ry', 319)
2628
2628
  def _reduce_175(val, _values)
2629
- [TRUE, [val[1]]]
2629
+ [true, [val[1]]]
2630
2630
  end
2631
2631
  .,.,
2632
2632
 
@@ -3102,13 +3102,13 @@ module_eval(<<'.,.,', 'parser.ry', 512)
3102
3102
 
3103
3103
  module_eval(<<'.,.,', 'parser.ry', 514)
3104
3104
  def _reduce_275(val, _values)
3105
- TRUE
3105
+ true
3106
3106
  end
3107
3107
  .,.,
3108
3108
 
3109
3109
  module_eval(<<'.,.,', 'parser.ry', 515)
3110
3110
  def _reduce_276(val, _values)
3111
- FALSE
3111
+ false
3112
3112
  end
3113
3113
  .,.,
3114
3114
 
@@ -8,7 +8,6 @@
8
8
  # included with this program.
9
9
  #
10
10
  # Copyright (c) Remedy IT Expertise BV
11
- # Chamber of commerce Rotterdam nr.276339, The Netherlands
12
11
  #--------------------------------------------------------------------
13
12
 
14
13
  class Parser
@@ -52,7 +51,7 @@ rule
52
51
  { @d.register_template_module_name(val[1]) }
53
52
 
54
53
  template_module_parameters : template_module_parameter
55
- | template_module_parameters "," template_module_parameter
54
+ | template_module_parameters "," template_module_parameter
56
55
 
57
56
  template_module_parameter : "typename" identifier
58
57
  { @d.define_template_parameter(val[1], IDL::Type::Any.new) }
@@ -78,7 +77,7 @@ rule
78
77
  { @d.define_template_parameter(val[1], val[0]) }
79
78
 
80
79
  template_module_body : template_module_definition
81
- | template_module_body template_module_definition
80
+ | template_module_body template_module_definition
82
81
 
83
82
  template_module_definition : type_dcl ";"
84
83
  | const_dcl ";"
@@ -117,11 +116,11 @@ rule
117
116
 
118
117
  template_module_inst : template_module_header "<" template_module_inst_parameters ">" identifier
119
118
  { @d.instantiate_template_module(val[4], val[2]) }
120
-
119
+
121
120
  template_module_inst_parameters : template_module_inst_parameter
122
121
  { [val[0]] }
123
122
  | template_module_inst_parameters "," template_module_inst_parameter
124
- { val[0] << val[2]; val[0] }
123
+ { val[0] << val[2]; val[0] }
125
124
 
126
125
  template_module_inst_parameter : base_type_spec
127
126
  { val[0] }
@@ -132,7 +131,7 @@ rule
132
131
 
133
132
  template_module_reference : "alias" scoped_name "<" _scoped_name_list ">" identifier
134
133
  { @d.declare_template_reference(val[5], val[1], val[3]) }
135
-
134
+
136
135
  interface : interface_dcl
137
136
  | forward_dcl
138
137
 
@@ -194,7 +193,7 @@ rule
194
193
 
195
194
  home : home_header "{" home_body "}"
196
195
  { @d.end_home(val[0]) }
197
-
196
+
198
197
  home_header : "home" identifier ":" home_inheritance_spec "supports" home_supports_spec "manages" scoped_name "primarykey" home_primarykey_spec
199
198
  { @d.define_home(val[1], val[3], val[7], val[9], val[5]) }
200
199
  | "home" identifier ":" home_inheritance_spec "supports" home_supports_spec "manages" scoped_name
@@ -211,11 +210,11 @@ rule
211
210
  { @d.define_home(val[1], nil, val[3], val[5], nil) }
212
211
  | "home" identifier "manages" scoped_name
213
212
  { @d.define_home(val[1], nil, val[3], nil, nil) }
214
-
215
- home_inheritance_spec : scoped_name
216
-
213
+
214
+ home_inheritance_spec : scoped_name
215
+
217
216
  home_supports_spec : _interface_name_list
218
-
217
+
219
218
  home_primarykey_spec : scoped_name
220
219
 
221
220
  home_body : home_export
@@ -227,26 +226,26 @@ rule
227
226
 
228
227
  porttype : porttype_header "{" porttype_body "}"
229
228
  { @d.end_porttype(val[0]) }
230
-
229
+
231
230
  porttype_header : "porttype" identifier
232
231
  { @d.define_porttype(val[1]) }
233
-
232
+
234
233
  porttype_body : porttype_export
235
234
  | porttype_body porttype_export
236
235
 
237
236
  porttype_export : provides_dcl ";"
238
237
  | uses_dcl ";"
239
238
  | attr_dcl ";"
240
-
239
+
241
240
  component : component_dcl
242
241
  | component_forward_dcl
243
-
242
+
244
243
  component_forward_dcl : "component" identifier
245
244
  { @d.declare_component(val[1]) }
246
-
245
+
247
246
  component_dcl : component_header "{" component_body "}"
248
247
  { @d.end_component(val[0]) }
249
-
248
+
250
249
  component_header : "component" identifier ":" component_inheritance_spec "supports" component_supports_spec
251
250
  { @d.define_component(val[1], val[3], val[5]) }
252
251
  | "component" identifier ":" component_inheritance_spec
@@ -255,11 +254,11 @@ rule
255
254
  { @d.define_component(val[1], nil, val[3]) }
256
255
  | "component" identifier
257
256
  { @d.define_component(val[1], nil, nil) }
258
-
257
+
259
258
  component_inheritance_spec : scoped_name
260
-
259
+
261
260
  component_supports_spec : _interface_name_list
262
-
261
+
263
262
  component_body : component_export
264
263
  | component_body component_export
265
264
 
@@ -274,7 +273,7 @@ rule
274
273
 
275
274
  connector : connector_header "{" connector_body "}"
276
275
  { @d.end_connector(val[0]) }
277
-
276
+
278
277
  connector_header : "connector" identifier ":" scoped_name
279
278
  { @d.define_connector(val[1], val[3]) }
280
279
  | "connector" identifier
@@ -291,33 +290,33 @@ rule
291
290
 
292
291
  provides_dcl : "provides" interface_type identifier
293
292
  { @d.declare_port(val[2], :facet, val[1]) }
294
-
293
+
295
294
  uses_dcl : "uses" "multiple" interface_type identifier
296
295
  { @d.declare_port(val[3], :receptacle, val[2], true) }
297
296
  | "uses" interface_type identifier
298
297
  { @d.declare_port(val[2], :receptacle, val[1], false) }
299
-
298
+
300
299
  publishes_dcl : "publishes" scoped_name identifier
301
300
  { @d.declare_port(val[2], :publisher, val[1]) }
302
-
301
+
303
302
  emits_dcl : "emits" scoped_name identifier
304
303
  { @d.declare_port(val[2], :emitter, val[1]) }
305
-
304
+
306
305
  consumes_dcl : "consumes" scoped_name identifier
307
306
  { @d.declare_port(val[2], :consumer, val[1]) }
308
-
307
+
309
308
  port_dcl : "port" scoped_name identifier
310
309
  { @d.declare_port(val[2], :port, val[1]) }
311
310
  | "mirrorport" scoped_name identifier
312
311
  { @d.declare_port(val[2], :mirrorport, val[1]) }
313
-
312
+
314
313
  interface_type : scoped_name
315
- | object_type
314
+ | object_type
316
315
 
317
316
  scoped_name : scoped_name_0 { @d.parse_scopedname(*val[0]) }
318
317
 
319
- scoped_name_0 : identifier { [FALSE, [val[0]]] }
320
- | "::" identifier { [TRUE, [val[1]]] }
318
+ scoped_name_0 : identifier { [false, [val[0]]] }
319
+ | "::" identifier { [true, [val[1]]] }
321
320
  | scoped_name_0 "::" identifier
322
321
  { val[0][1] << val[2]; val[0] }
323
322
 
@@ -396,8 +395,8 @@ rule
396
395
 
397
396
  value_name : scoped_name
398
397
 
399
- value_element : export
400
- | state_member ";"
398
+ value_element : export
399
+ | state_member ";"
401
400
  | init_dcl ";"
402
401
 
403
402
  state_member : "public" type_spec declarators
@@ -460,7 +459,7 @@ rule
460
459
  const_exp : or_expr
461
460
 
462
461
  or_expr : xor_expr
463
- | or_expr "|" xor_expr
462
+ | or_expr "|" xor_expr
464
463
  { Expression::Operation::Or.new(val[0], val[2]) }
465
464
 
466
465
  xor_expr : and_expr
@@ -512,8 +511,8 @@ rule
512
511
  | floating_pt_literal { @d.parse_literal(:float, val[0]) }
513
512
  | boolean_literal { @d.parse_literal(:boolean, val[0]) }
514
513
 
515
- boolean_literal : "TRUE" { TRUE }
516
- | "FALSE" { FALSE }
514
+ boolean_literal : "TRUE" { true }
515
+ | "FALSE" { false }
517
516
 
518
517
  positive_int_const : const_exp { @d.parse_positive_int(val[0]) }
519
518
 
@@ -525,7 +524,7 @@ rule
525
524
  | enum_type
526
525
  | "native" native_declarator
527
526
 
528
- type_declarator : type_spec declarators
527
+ type_declarator : type_spec declarators
529
528
  {
530
529
  dcls = parse_type_declarator(val[0], val[1])
531
530
  dcls.each do |d|
@@ -624,7 +623,7 @@ rule
624
623
  member_list : member
625
624
  | member_list member
626
625
 
627
- member : type_spec declarators ";"
626
+ member : type_spec declarators ";"
628
627
  {
629
628
  dcls = parse_type_declarator(val[0], val[1])
630
629
  dcls.each do |d|
@@ -659,10 +658,10 @@ rule
659
658
  | union_body union_case
660
659
 
661
660
  union_case : _case_label_1 element_spec ";"
662
- {
661
+ {
663
662
  dcls = parse_type_declarator(val[1][0], [val[1][1]])
664
663
  dcls.each do |d|
665
- @d.define_case(val[0], d[0], d[1])
664
+ @d.define_case(val[0], d[0], d[1])
666
665
  end
667
666
  }
668
667
 
@@ -684,7 +683,7 @@ rule
684
683
  _enumerator_list : enumerator
685
684
  | _enumerator_list "," enumerator
686
685
 
687
- enumerator : identifier
686
+ enumerator : identifier
688
687
  {
689
688
  @d.declare_enumerator(val[0])
690
689
  }
@@ -746,7 +745,7 @@ rule
746
745
  attr_no_raises_expr : { [[], []] }
747
746
 
748
747
  attr_declarator_list : simple_declarator "," _simple_declarator_list
749
- { [val[0]].concat(val[2]) }
748
+ { [val[0]].concat(val[2]) }
750
749
 
751
750
  readonly_attr_declarator : simple_declarator raises_expr
752
751
  { [[val[0]], val[1]] }
@@ -8,7 +8,6 @@
8
8
  # included with this program.
9
9
  #
10
10
  # Copyright (c) Remedy IT Expertise BV
11
- # Chamber of commerce Rotterdam nr.276339, The Netherlands
12
11
  #--------------------------------------------------------------------
13
12
  require 'ridl/version'
14
13
  require 'ridl/scanner'
@@ -13,7 +13,6 @@
13
13
  # included with this program.
14
14
  #
15
15
  # Copyright (c) Remedy IT Expertise BV
16
- # Chamber of commerce Rotterdam nr.276339, The Netherlands
17
16
  #--------------------------------------------------------------------
18
17
  require 'ridl/require'
19
18
 
@@ -8,12 +8,12 @@
8
8
  # included with this program.
9
9
  #
10
10
  # Copyright (c) Remedy IT Expertise BV
11
- # Chamber of commerce Rotterdam nr.276339, The Netherlands
12
11
  #--------------------------------------------------------------------
13
12
  require 'stringio'
14
13
  require 'ridl/optparse_ext'
15
14
  require 'ridl/genfile'
16
15
  require 'ridl/backend'
16
+ require 'ridl/options'
17
17
 
18
18
  # -----------------------------------------------------------------------
19
19
 
@@ -24,7 +24,7 @@ module IDL
24
24
  @@embedded = false unless class_variable_defined?(:@@embedded)
25
25
  @@be_name = nil unless class_variable_defined?(:@@be_name)
26
26
 
27
- OPTIONS = {
27
+ OPTIONS = Options.new({
28
28
  :outputdir => nil,
29
29
  :includepaths => [],
30
30
  :xincludepaths => [],
@@ -34,11 +34,9 @@ module IDL
34
34
  :search_incpath => false,
35
35
  :backend => nil,
36
36
  :macros => {
37
- :__RIDL__ => "#{RIDL_VERSION}",
38
- :__RIDLBE__ => nil,
39
- :__RIDLBE_VER__ => nil
40
37
  }
41
- }
38
+ })
39
+ CORE_OPTIONS = OPTIONS.keys
42
40
 
43
41
  class Engine
44
42
  def initialize(backend, options)
@@ -46,12 +44,15 @@ module IDL
46
44
  @initopts = options.merge({
47
45
  backend: @backend.name,
48
46
  macros: options[:macros].merge({
47
+ __RIDL__: "#{RIDL_VERSION}",
49
48
  __RIDLBE__: @backend.name.to_s,
50
49
  __RIDLBE_VER__: @backend.version
51
50
  })
52
51
  })
53
52
  @optparser = init_optparser
54
53
  @inputstack = []
54
+ @productionbatch = {}
55
+ @productionstack = []
55
56
  @options = nil
56
57
  end
57
58
 
@@ -63,6 +64,8 @@ module IDL
63
64
  @options || @initopts
64
65
  end
65
66
 
67
+ # Input management
68
+
66
69
  def push_input(idlfile, opts)
67
70
  @inputstack << [idlfile, opts]
68
71
  end
@@ -79,6 +82,48 @@ module IDL
79
82
  !@inputstack.empty?
80
83
  end
81
84
 
85
+ # Production management
86
+
87
+ def push_production(id, producer)
88
+ raise RuntimeError, "Producer #{id} already queued" if @productionbatch.has_key?(id.to_sym)
89
+ @productionbatch[id.to_sym] = @productionstack.size
90
+ @productionstack << [id.to_sym, producer]
91
+ end
92
+
93
+ def pop_production
94
+ return nil unless has_productions?
95
+ id, producer = @productionstack.shift
96
+ @productionbatch.delete(id)
97
+ producer
98
+ end
99
+
100
+ def peek_production
101
+ return nil unless has_productions?
102
+ id, _ = @productionstack.first
103
+ id
104
+ end
105
+
106
+ def remove_production(id)
107
+ return nil unless has_production?(id)
108
+ i = @productionbatch.delete(id.to_sym)
109
+ _, producer = @productionstack.delete(i)
110
+ producer
111
+ end
112
+
113
+ def has_productions?
114
+ !@productionstack.empty?
115
+ end
116
+
117
+ def has_production?(id)
118
+ @productionbatch.has_key?(id.to_sym)
119
+ end
120
+
121
+ def production(id)
122
+ @productionstack[@productionbatch[id.to_sym]].last
123
+ end
124
+
125
+ # Verbosity control
126
+
82
127
  def verbose_level
83
128
  options[:verbose]
84
129
  end
@@ -92,6 +137,9 @@ module IDL
92
137
  # initialize options
93
138
  @options = @initopts.merge(runopts)
94
139
 
140
+ # mark current (clean) state
141
+ @options.mark
142
+
95
143
  # backup current engine (if any)
96
144
  cur_engine = Thread.current[:ridl_engine]
97
145
  # store currently running engine for current thread
@@ -118,7 +166,7 @@ module IDL
118
166
  options[:output] = o
119
167
 
120
168
  input_base = File.basename(argv.first)
121
- if (input_base != argv.first)
169
+ if input_base != argv.first
122
170
  options[:xincludepaths] << (File.dirname(argv.first)+'/')
123
171
  end
124
172
 
@@ -147,13 +195,31 @@ module IDL
147
195
  end
148
196
 
149
197
  # process parse result -> code generation
150
- IDL.log(2, 'RIDL - starting code generation')
198
+ IDL.log(2, 'RIDL - processing input')
151
199
 
152
200
  GenFile.transaction do
153
201
  begin
202
+
154
203
  backend.process_input(_parser, _opts)
204
+
205
+ # handle productions
206
+ while has_productions?
207
+ IDL.log(2, "RIDL - running production #{peek_production}")
208
+
209
+ # get next-in-line producer
210
+ producer = pop_production
211
+
212
+ # execute the producer
213
+ producer.run(_parser)
214
+ end
215
+
155
216
  rescue Backend::ProcessStop
156
217
  IDL.log(2, "RIDL - processing #{IO === _idlfile ? 'from STDIN': (StringIO === _idlfile ? 'from string' : _idlfile)} stopped with \"#{$!.message}\"")
218
+
219
+ rescue => ex
220
+ IDL.error(ex)
221
+ IDL.error(ex.backtrace.join("\n")) unless ex.is_a? IDL::ParseError
222
+ return false
157
223
  end
158
224
  end
159
225
  end
@@ -190,22 +256,28 @@ module IDL
190
256
  _opts = options.dup
191
257
 
192
258
  _opts[:idlfile] = _arg
193
- if _opts[:search_incpath]
194
- _fname = _arg
195
- _fpath = if File.file?(_fname) && File.readable?(_fname)
196
- _fname
197
- else
198
- _fp = _opts[:includepaths].find do |_p|
199
- _f = _p + _fname
200
- File.file?(_f) && File.readable?(_f)
259
+ if _opts[:no_input]
260
+ # do not parse specified file (only used as template for output names)
261
+ # instead push an empty StringIO object
262
+ _arg = StringIO.new('')
263
+ else
264
+ if _opts[:search_incpath]
265
+ _fname = _arg
266
+ _fpath = if File.file?(_fname) && File.readable?(_fname)
267
+ _fname
268
+ else
269
+ _fp = _opts[:includepaths].find do |_p|
270
+ _f = _p + _fname
271
+ File.file?(_f) && File.readable?(_f)
272
+ end
273
+ _opts[:outputdir] = _fp unless _fp.nil? || !_opts[:outputdir].nil?
274
+ _fp += '/' + _fname unless _fp.nil?
275
+ _fp
201
276
  end
202
- _opts[:outputdir] = _fp unless _fp.nil? || !_opts[:outputdir].nil?
203
- _fp += '/' + _fname unless _fp.nil?
204
- _fp
205
- end
206
- _arg = _fpath unless _fpath.nil?
277
+ _arg = _fpath unless _fpath.nil?
278
+ end
279
+ _opts[:xincludepaths] << (File.dirname(_arg)+'/')
207
280
  end
208
- _opts[:xincludepaths] << (File.dirname(_arg)+'/')
209
281
 
210
282
  _opts[:outputdir] ||= '.'
211
283
 
@@ -232,35 +304,47 @@ module IDL
232
304
  " backend\t\tSpecifies the IDL language mapping backend to use.\n"+
233
305
  " \t\tDefault = :null\n\n"+
234
306
  " Active language mapping = :#{backend.name}"
235
- opts.separator ""
236
- opts.on("-I PATH", "--include=PATH", String,
237
- "Adds include searchpath.",
238
- "Default: none") { |v| @options[:includepaths] << (v.end_with?('\\','/') ? v : v+'/') }
307
+ opts.separator ''
308
+ opts.on('-I PATH', '--include=PATH', String,
309
+ 'Adds include searchpath.',
310
+ 'Default: none') { |v|
311
+ self.options[:includepaths] << (v.end_with?('\\','/') ? v : v+'/')
312
+ }
239
313
  opts.on('-Dmacro=[value]', String, 'defines preprocessor macro') { |v|
240
314
  name, value = v.split('=')
241
- @options[:macros][name] = (value ? value : true)
315
+ self.options[:macros][name] = (value ? value : true)
316
+ }
317
+ opts.on('-n NAMESPACE', '--namespace=NAMESPACE', String,
318
+ 'Defines rootlevel enclosing namespace.',
319
+ 'Default: nil') { |v|
320
+ self.options[:namespace] = v
321
+ }
322
+ opts.on('-v', '--verbose',
323
+ 'Set verbosity level. Repeat to increment.',
324
+ 'Default: 0') { |_|
325
+ self.options[:verbose] += 1
326
+ }
327
+ opts.on('--debug',
328
+ 'Set parser debug mode. Do NOT do this at home!',
329
+ 'Default: off') { |_|
330
+ self.options[:debug] = true
242
331
  }
243
- opts.on("-n NAMESPACE", "--namespace=NAMESPACE", String,
244
- "Defines rootlevel enclosing namespace.",
245
- "Default: nil") { |v| @options[:namespace]=v }
246
- opts.on("-v", "--verbose",
247
- "Set verbosity level. Repeat to increment.",
248
- "Default: 0") { |v| @options[:verbose] += 1 }
249
- opts.on("--debug",
250
- "Set parser debug mode. Don't do this at home!",
251
- "Default: off") { |v| @options[:debug] = true }
252
- opts.on('--stdidl',
253
- 'Adds include path to standard IDL files provided with RIDL.',
254
- 'Default: not set') { |v|
255
- @options[:includepaths] << (File.expand_path(File.join(File.dirname(__FILE__), '..', 'idl'))+'/')
332
+ opts.on('--search-includepath',
333
+ 'Use include paths to find main IDL source.',
334
+ 'Default: off') { |_|
335
+ self.options[:search_incpath] = true
336
+ }
337
+ opts.on('--no-input',
338
+ 'Do not parse specified file(s) as input IDL.',
339
+ 'Default: off') { |_|
340
+ self.options[:no_input] = true
256
341
  }
257
- opts.on("--search-includepath",
258
- "Use include paths to find main IDL source.",
259
- "Default: off") { |v| @options[:search_incpath]=v }
260
342
  if @initopts[:preprocess]
261
- opts.on("--output=FILE", String,
262
- "Specifies filename to generate output in.",
263
- "Default: basename(idlfile)-'.idl'+<postfix>+<ext>") { |v| @options[:output]=v }
343
+ opts.on('--output=FILE', String,
344
+ 'Specifies filename to generate output in.',
345
+ 'Default: basename(idlfile)-\'.idl\'+<postfix>+<ext>') { |v|
346
+ self.options[:output] = v
347
+ }
264
348
  end
265
349
 
266
350
  # setup language mapping specific options
@@ -270,7 +354,7 @@ module IDL
270
354
 
271
355
  opts.on('-V', '--version',
272
356
  'Show version information and exit.') {
273
- puts "RIDL compiler #{@options[:macros][:__RIDL__]}"
357
+ puts "RIDL compiler #{RIDL_VERSION}"
274
358
  puts RIDL_COPYRIGHT
275
359
  puts '---'
276
360
  @backend.print_version
@@ -287,24 +371,57 @@ module IDL
287
371
 
288
372
  end
289
373
 
374
+ def IDL.engine?
375
+ !Thread.current[:ridl_engine].nil?
376
+ end
377
+
290
378
  def IDL.backend
291
379
  Thread.current[:ridl_engine] ? Thread.current[:ridl_engine].backend : nil
292
380
  end
293
381
 
294
382
  def IDL.push_input(idlfile, opts)
295
- Thread.current[:ridl_engine].push_input(idlfile, opts) if Thread.current[:ridl_engine]
383
+ Thread.current[:ridl_engine].push_input(idlfile, opts) if engine?
296
384
  end
297
385
 
298
386
  def IDL.pop_input
299
- Thread.current[:ridl_engine].pop_input if Thread.current[:ridl_engine]
387
+ return nil unless engine?
388
+ Thread.current[:ridl_engine].pop_input
300
389
  end
301
390
 
302
391
  def IDL.peek_input
303
- Thread.current[:ridl_engine].peek_input if Thread.current[:ridl_engine]
392
+ return nil unless engine?
393
+ Thread.current[:ridl_engine].peek_input
304
394
  end
305
395
 
306
396
  def IDL.has_input?
307
- Thread.current[:ridl_engine].has_input? if Thread.current[:ridl_engine]
397
+ engine? && Thread.current[:ridl_engine].has_input?
398
+ end
399
+
400
+ def IDL.push_production(id, producer)
401
+ Thread.current[:ridl_engine].push_production(id, producer) if engine?
402
+ end
403
+
404
+ def IDL.pop_production
405
+ return nil unless engine?
406
+ Thread.current[:ridl_engine].pop_production
407
+ end
408
+
409
+ def IDL.remove_production(id)
410
+ return nil unless engine?
411
+ Thread.current[:ridl_engine].remove_production(id)
412
+ end
413
+
414
+ def IDL.has_productions?
415
+ engine? && Thread.current[:ridl_engine].has_productions?
416
+ end
417
+
418
+ def IDL.has_production?(id)
419
+ engine? && Thread.current[:ridl_engine].has_production?(id)
420
+ end
421
+
422
+ def IDL.production(id)
423
+ return nil unless engine?
424
+ Thread.current[:ridl_engine].production(id)
308
425
  end
309
426
 
310
427
  def IDL.verbose_level
@@ -327,19 +444,34 @@ module IDL
327
444
  STDERR.puts(message)
328
445
  end
329
446
 
447
+ def IDL.fatal(message)
448
+ STDERR.puts(message, 'Exiting.')
449
+ exit 1
450
+ end
451
+
330
452
  def IDL.init(argv = ARGV)
331
453
  options = OPTIONS.dup
332
454
 
333
455
  unless @@embedded
456
+ # load config file(s) if any
457
+ Options.load_config(options)
458
+
459
+ IDL.log(2, "Configuration [#{options}]")
460
+
334
461
  # check commandline args for explicit language mapping backend
335
462
  if argv.first =~ /^:\S+/
336
463
  @@be_name = argv.shift.reverse.chop.reverse.to_sym
337
464
  elsif ENV['RIDL_BE_SELECT'] # or from environment
338
465
  @@be_name = ENV['RIDL_BE_SELECT'].to_sym
466
+ elsif options[:backend] # or from configuration
467
+ @@be_name = options[:backend].to_sym
339
468
  end
340
469
 
341
470
  # add optional search paths for RIDL backends
342
- $:.concat(ENV['RIDL_BE_PATH'].split(/:|;/)) if ENV['RIDL_BE_PATH']
471
+ options[:be_path] ||= []
472
+ options[:be_path].unshift(*ENV['RIDL_BE_PATH'].split(/#{File::PATH_SEPARATOR}/)) if ENV['RIDL_BE_PATH']
473
+ options[:be_path].collect! {|p| p.gsub('\\', '/') } # cleanup to prevent mixed path separators
474
+ $:.concat(options[:be_path]) unless options[:be_path].empty?
343
475
 
344
476
  # check for special bootstrapping switches
345
477
  if argv.first == '--preprocess'