ridl 2.5.6 → 2.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/ridl/parser.ry CHANGED
@@ -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,22 +116,20 @@ 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
- template_module_inst_parameter : base_type_spec
127
- { val[0] }
128
- | template_type_spec
125
+ template_module_inst_parameter : simple_type_spec
129
126
  { val[0] }
130
127
  | const_exp
131
128
  { val[0] }
132
129
 
133
130
  template_module_reference : "alias" scoped_name "<" _scoped_name_list ">" identifier
134
131
  { @d.declare_template_reference(val[5], val[1], val[3]) }
135
-
132
+
136
133
  interface : interface_dcl
137
134
  | forward_dcl
138
135
 
@@ -194,7 +191,7 @@ rule
194
191
 
195
192
  home : home_header "{" home_body "}"
196
193
  { @d.end_home(val[0]) }
197
-
194
+
198
195
  home_header : "home" identifier ":" home_inheritance_spec "supports" home_supports_spec "manages" scoped_name "primarykey" home_primarykey_spec
199
196
  { @d.define_home(val[1], val[3], val[7], val[9], val[5]) }
200
197
  | "home" identifier ":" home_inheritance_spec "supports" home_supports_spec "manages" scoped_name
@@ -211,11 +208,11 @@ rule
211
208
  { @d.define_home(val[1], nil, val[3], val[5], nil) }
212
209
  | "home" identifier "manages" scoped_name
213
210
  { @d.define_home(val[1], nil, val[3], nil, nil) }
214
-
215
- home_inheritance_spec : scoped_name
216
-
211
+
212
+ home_inheritance_spec : scoped_name
213
+
217
214
  home_supports_spec : _interface_name_list
218
-
215
+
219
216
  home_primarykey_spec : scoped_name
220
217
 
221
218
  home_body : home_export
@@ -227,26 +224,26 @@ rule
227
224
 
228
225
  porttype : porttype_header "{" porttype_body "}"
229
226
  { @d.end_porttype(val[0]) }
230
-
227
+
231
228
  porttype_header : "porttype" identifier
232
229
  { @d.define_porttype(val[1]) }
233
-
230
+
234
231
  porttype_body : porttype_export
235
232
  | porttype_body porttype_export
236
233
 
237
234
  porttype_export : provides_dcl ";"
238
235
  | uses_dcl ";"
239
236
  | attr_dcl ";"
240
-
237
+
241
238
  component : component_dcl
242
239
  | component_forward_dcl
243
-
240
+
244
241
  component_forward_dcl : "component" identifier
245
242
  { @d.declare_component(val[1]) }
246
-
243
+
247
244
  component_dcl : component_header "{" component_body "}"
248
245
  { @d.end_component(val[0]) }
249
-
246
+
250
247
  component_header : "component" identifier ":" component_inheritance_spec "supports" component_supports_spec
251
248
  { @d.define_component(val[1], val[3], val[5]) }
252
249
  | "component" identifier ":" component_inheritance_spec
@@ -255,11 +252,11 @@ rule
255
252
  { @d.define_component(val[1], nil, val[3]) }
256
253
  | "component" identifier
257
254
  { @d.define_component(val[1], nil, nil) }
258
-
255
+
259
256
  component_inheritance_spec : scoped_name
260
-
257
+
261
258
  component_supports_spec : _interface_name_list
262
-
259
+
263
260
  component_body : component_export
264
261
  | component_body component_export
265
262
 
@@ -274,7 +271,7 @@ rule
274
271
 
275
272
  connector : connector_header "{" connector_body "}"
276
273
  { @d.end_connector(val[0]) }
277
-
274
+
278
275
  connector_header : "connector" identifier ":" scoped_name
279
276
  { @d.define_connector(val[1], val[3]) }
280
277
  | "connector" identifier
@@ -291,33 +288,33 @@ rule
291
288
 
292
289
  provides_dcl : "provides" interface_type identifier
293
290
  { @d.declare_port(val[2], :facet, val[1]) }
294
-
291
+
295
292
  uses_dcl : "uses" "multiple" interface_type identifier
296
293
  { @d.declare_port(val[3], :receptacle, val[2], true) }
297
294
  | "uses" interface_type identifier
298
295
  { @d.declare_port(val[2], :receptacle, val[1], false) }
299
-
296
+
300
297
  publishes_dcl : "publishes" scoped_name identifier
301
298
  { @d.declare_port(val[2], :publisher, val[1]) }
302
-
299
+
303
300
  emits_dcl : "emits" scoped_name identifier
304
301
  { @d.declare_port(val[2], :emitter, val[1]) }
305
-
302
+
306
303
  consumes_dcl : "consumes" scoped_name identifier
307
304
  { @d.declare_port(val[2], :consumer, val[1]) }
308
-
305
+
309
306
  port_dcl : "port" scoped_name identifier
310
307
  { @d.declare_port(val[2], :port, val[1]) }
311
308
  | "mirrorport" scoped_name identifier
312
309
  { @d.declare_port(val[2], :mirrorport, val[1]) }
313
-
310
+
314
311
  interface_type : scoped_name
315
- | object_type
312
+ | object_type
316
313
 
317
314
  scoped_name : scoped_name_0 { @d.parse_scopedname(*val[0]) }
318
315
 
319
- scoped_name_0 : identifier { [FALSE, [val[0]]] }
320
- | "::" identifier { [TRUE, [val[1]]] }
316
+ scoped_name_0 : identifier { [false, [val[0]]] }
317
+ | "::" identifier { [true, [val[1]]] }
321
318
  | scoped_name_0 "::" identifier
322
319
  { val[0][1] << val[2]; val[0] }
323
320
 
@@ -396,8 +393,8 @@ rule
396
393
 
397
394
  value_name : scoped_name
398
395
 
399
- value_element : export
400
- | state_member ";"
396
+ value_element : export
397
+ | state_member ";"
401
398
  | init_dcl ";"
402
399
 
403
400
  state_member : "public" type_spec declarators
@@ -460,7 +457,7 @@ rule
460
457
  const_exp : or_expr
461
458
 
462
459
  or_expr : xor_expr
463
- | or_expr "|" xor_expr
460
+ | or_expr "|" xor_expr
464
461
  { Expression::Operation::Or.new(val[0], val[2]) }
465
462
 
466
463
  xor_expr : and_expr
@@ -512,8 +509,8 @@ rule
512
509
  | floating_pt_literal { @d.parse_literal(:float, val[0]) }
513
510
  | boolean_literal { @d.parse_literal(:boolean, val[0]) }
514
511
 
515
- boolean_literal : "TRUE" { TRUE }
516
- | "FALSE" { FALSE }
512
+ boolean_literal : "TRUE" { true }
513
+ | "FALSE" { false }
517
514
 
518
515
  positive_int_const : const_exp { @d.parse_positive_int(val[0]) }
519
516
 
@@ -525,7 +522,7 @@ rule
525
522
  | enum_type
526
523
  | "native" native_declarator
527
524
 
528
- type_declarator : type_spec declarators
525
+ type_declarator : type_spec declarators
529
526
  {
530
527
  dcls = parse_type_declarator(val[0], val[1])
531
528
  dcls.each do |d|
@@ -624,7 +621,7 @@ rule
624
621
  member_list : member
625
622
  | member_list member
626
623
 
627
- member : type_spec declarators ";"
624
+ member : type_spec declarators ";"
628
625
  {
629
626
  dcls = parse_type_declarator(val[0], val[1])
630
627
  dcls.each do |d|
@@ -659,10 +656,10 @@ rule
659
656
  | union_body union_case
660
657
 
661
658
  union_case : _case_label_1 element_spec ";"
662
- {
659
+ {
663
660
  dcls = parse_type_declarator(val[1][0], [val[1][1]])
664
661
  dcls.each do |d|
665
- @d.define_case(val[0], d[0], d[1])
662
+ @d.define_case(val[0], d[0], d[1])
666
663
  end
667
664
  }
668
665
 
@@ -684,7 +681,7 @@ rule
684
681
  _enumerator_list : enumerator
685
682
  | _enumerator_list "," enumerator
686
683
 
687
- enumerator : identifier
684
+ enumerator : identifier
688
685
  {
689
686
  @d.declare_enumerator(val[0])
690
687
  }
@@ -746,7 +743,7 @@ rule
746
743
  attr_no_raises_expr : { [[], []] }
747
744
 
748
745
  attr_declarator_list : simple_declarator "," _simple_declarator_list
749
- { [val[0]].concat(val[2]) }
746
+ { [val[0]].concat(val[2]) }
750
747
 
751
748
  readonly_attr_declarator : simple_declarator raises_expr
752
749
  { [[val[0]], val[1]] }
data/lib/ridl/require.rb CHANGED
@@ -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'
data/lib/ridl/ridl.rb CHANGED
@@ -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
 
data/lib/ridl/runner.rb CHANGED
@@ -8,23 +8,18 @@
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
 
20
20
  module IDL
21
21
 
22
- # TODO : LEGACY solution for R2CORBA; to be removed when R2CORBA has been updated
23
- # See also IDL#init
24
- @@embedded = false unless class_variable_defined?(:@@embedded)
25
- @@be_name = nil unless class_variable_defined?(:@@be_name)
26
-
27
- OPTIONS = {
22
+ OPTIONS = Options.new({
28
23
  :outputdir => nil,
29
24
  :includepaths => [],
30
25
  :xincludepaths => [],
@@ -34,24 +29,73 @@ module IDL
34
29
  :search_incpath => false,
35
30
  :backend => nil,
36
31
  :macros => {
37
- :__RIDL__ => "#{RIDL_VERSION}",
38
- :__RIDLBE__ => nil,
39
- :__RIDLBE_VER__ => nil
40
32
  }
41
- }
33
+ })
34
+ CORE_OPTIONS = OPTIONS.keys
42
35
 
43
36
  class Engine
37
+
38
+ class ProductionStack
39
+ def initialize
40
+ @stack = []
41
+ @index = {}
42
+ end
43
+
44
+ def size
45
+ @stack.size
46
+ end
47
+
48
+ def empty?
49
+ @stack.empty?
50
+ end
51
+
52
+ def push(id, prod)
53
+ @index[id.to_sym] = @stack.size
54
+ @stack << [id.to_sym, prod]
55
+ end
56
+
57
+ def pop
58
+ return nil if empty?
59
+ id, prod = @stack.shift
60
+ @index.delete(id)
61
+ prod
62
+ end
63
+
64
+ def peek
65
+ return nil if empty?
66
+ id, _ = @stack.first
67
+ id
68
+ end
69
+
70
+ def remove(id)
71
+ return nil unless has?(id)
72
+ i = @index.delete(id.to_sym)
73
+ _, producer = @productionstack.delete(i)
74
+ producer
75
+ end
76
+
77
+ def has?(id)
78
+ @index.has_key?(id.to_sym)
79
+ end
80
+
81
+ def [](id)
82
+ @stack[@index[id.to_sym]].last
83
+ end
84
+ end
85
+
44
86
  def initialize(backend, options)
45
87
  @backend = backend ? Backend.load(backend) : Backend.null_be
46
88
  @initopts = options.merge({
47
89
  backend: @backend.name,
48
90
  macros: options[:macros].merge({
91
+ __RIDL__: "#{RIDL_VERSION}",
49
92
  __RIDLBE__: @backend.name.to_s,
50
93
  __RIDLBE_VER__: @backend.version
51
94
  })
52
95
  })
53
96
  @optparser = init_optparser
54
97
  @inputstack = []
98
+ @productionstack = ProductionStack.new
55
99
  @options = nil
56
100
  end
57
101
 
@@ -63,6 +107,8 @@ module IDL
63
107
  @options || @initopts
64
108
  end
65
109
 
110
+ # Input management
111
+
66
112
  def push_input(idlfile, opts)
67
113
  @inputstack << [idlfile, opts]
68
114
  end
@@ -79,6 +125,39 @@ module IDL
79
125
  !@inputstack.empty?
80
126
  end
81
127
 
128
+ # Production management
129
+
130
+ def push_production(id, producer)
131
+ raise "Producer #{id} already queued" if @productionstack.has?(id)
132
+ @productionstack.push(id, producer)
133
+ end
134
+
135
+ def pop_production
136
+ @productionstack.pop
137
+ end
138
+
139
+ def peek_production
140
+ @productionstack.peek
141
+ end
142
+
143
+ def remove_production(id)
144
+ @productionstack.remove(id)
145
+ end
146
+
147
+ def has_productions?
148
+ !@productionstack.empty?
149
+ end
150
+
151
+ def has_production?(id)
152
+ @productionstack.has?(id)
153
+ end
154
+
155
+ def production(id)
156
+ @productionstack[id]
157
+ end
158
+
159
+ # Verbosity control
160
+
82
161
  def verbose_level
83
162
  options[:verbose]
84
163
  end
@@ -92,6 +171,9 @@ module IDL
92
171
  # initialize options
93
172
  @options = @initopts.merge(runopts)
94
173
 
174
+ # mark current (clean) state
175
+ @options.mark
176
+
95
177
  # backup current engine (if any)
96
178
  cur_engine = Thread.current[:ridl_engine]
97
179
  # store currently running engine for current thread
@@ -103,7 +185,7 @@ module IDL
103
185
  @optparser.parse!(argv)
104
186
  rescue ArgumentError => ex
105
187
  IDL.error(ex.inspect)
106
- IDL.error(ex.backtrace.join("\n")) if IDL.verbose_level>0
188
+ IDL.error(ex.backtrace.join("\n")) if IDL.verbose_level > 0
107
189
  return false
108
190
  end
109
191
 
@@ -118,8 +200,8 @@ module IDL
118
200
  options[:output] = o
119
201
 
120
202
  input_base = File.basename(argv.first)
121
- if (input_base != argv.first)
122
- options[:xincludepaths] << (File.dirname(argv.first)+'/')
203
+ if input_base != argv.first
204
+ options[:xincludepaths] << (File.dirname(argv.first) + '/')
123
205
  end
124
206
 
125
207
  return !parse("#include \"#{input_base}\"", options).nil?
@@ -137,23 +219,41 @@ module IDL
137
219
  else
138
220
  File.open(_idlfile, 'r')
139
221
  end
140
- raise RuntimeError, 'cannot read from STDOUT' if $stdout == _fio
222
+ raise 'cannot read from STDOUT' if $stdout == _fio
141
223
 
142
224
  # parse IDL source
143
- IDL.log(1, "RIDL - parsing #{IO === _idlfile ? 'from STDIN': (StringIO === _idlfile ? 'from string' : _idlfile)}")
225
+ IDL.log(1, "RIDL - parsing #{IO === _idlfile ? 'from STDIN' : (StringIO === _idlfile ? 'from string' : _idlfile)}")
144
226
 
145
227
  unless _parser = parse(_fio, _opts)
146
228
  return false
147
229
  end
148
230
 
149
231
  # process parse result -> code generation
150
- IDL.log(2, 'RIDL - starting code generation')
232
+ IDL.log(2, 'RIDL - processing input')
151
233
 
152
234
  GenFile.transaction do
153
235
  begin
236
+
154
237
  backend.process_input(_parser, _opts)
238
+
239
+ # handle productions
240
+ while has_productions?
241
+ IDL.log(2, "RIDL - running production #{peek_production}")
242
+
243
+ # get next-in-line producer
244
+ producer = pop_production
245
+
246
+ # execute the producer
247
+ producer.run(_parser)
248
+ end
249
+
155
250
  rescue Backend::ProcessStop
156
- IDL.log(2, "RIDL - processing #{IO === _idlfile ? 'from STDIN': (StringIO === _idlfile ? 'from string' : _idlfile)} stopped with \"#{$!.message}\"")
251
+ IDL.log(2, "RIDL - processing #{IO === _idlfile ? 'from STDIN' : (StringIO === _idlfile ? 'from string' : _idlfile)} stopped with \"#{$!.message}\"")
252
+
253
+ rescue => ex
254
+ IDL.error(ex)
255
+ IDL.error(ex.backtrace.join("\n")) unless ex.is_a? IDL::ParseError
256
+ return false
157
257
  end
158
258
  end
159
259
  end
@@ -190,22 +290,28 @@ module IDL
190
290
  _opts = options.dup
191
291
 
192
292
  _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)
293
+ if _opts[:no_input]
294
+ # do not parse specified file (only used as template for output names)
295
+ # instead push an empty StringIO object
296
+ _arg = StringIO.new('')
297
+ else
298
+ if _opts[:search_incpath]
299
+ _fname = _arg
300
+ _fpath = if File.file?(_fname) && File.readable?(_fname)
301
+ _fname
302
+ else
303
+ _fp = _opts[:includepaths].find do |_p|
304
+ _f = _p + _fname
305
+ File.file?(_f) && File.readable?(_f)
306
+ end
307
+ _opts[:outputdir] = _fp unless _fp.nil? || !_opts[:outputdir].nil?
308
+ _fp += '/' + _fname unless _fp.nil?
309
+ _fp
201
310
  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?
311
+ _arg = _fpath unless _fpath.nil?
312
+ end
313
+ _opts[:xincludepaths] << (File.dirname(_arg) + '/')
207
314
  end
208
- _opts[:xincludepaths] << (File.dirname(_arg)+'/')
209
315
 
210
316
  _opts[:outputdir] ||= '.'
211
317
 
@@ -223,44 +329,56 @@ module IDL
223
329
  def init_optparser
224
330
  script_name = File.basename($0, '.*')
225
331
  if not script_name =~ /ridlc/
226
- script_name = 'ruby '+$0
332
+ script_name = 'ruby ' + $0
227
333
  end
228
334
 
229
335
  # set up option parser with common options
230
336
  opts = OptionParser.new
231
337
  opts.banner = "Usage: #{script_name} [:backend] [options] [<idlfile> [<idlfile> ...]]\n\n" +
232
- " backend\t\tSpecifies the IDL language mapping backend to use.\n"+
233
- " \t\tDefault = :null\n\n"+
338
+ " backend\t\tSpecifies the IDL language mapping backend to use.\n" +
339
+ " \t\tDefault = :null\n\n" +
234
340
  " 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+'/') }
341
+ opts.separator ''
342
+ opts.on('-I PATH', '--include=PATH', String,
343
+ 'Adds include searchpath.',
344
+ 'Default: none') { |v|
345
+ self.options[:includepaths] << (v.end_with?('\\', '/') ? v : v + '/')
346
+ }
239
347
  opts.on('-Dmacro=[value]', String, 'defines preprocessor macro') { |v|
240
348
  name, value = v.split('=')
241
- @options[:macros][name] = (value ? value : true)
349
+ self.options[:macros][name] = (value ? value : true)
350
+ }
351
+ opts.on('-n NAMESPACE', '--namespace=NAMESPACE', String,
352
+ 'Defines rootlevel enclosing namespace.',
353
+ 'Default: nil') { |v|
354
+ self.options[:namespace] = v
355
+ }
356
+ opts.on('-v', '--verbose',
357
+ 'Set verbosity level. Repeat to increment.',
358
+ 'Default: 0') { |_|
359
+ self.options[:verbose] += 1
242
360
  }
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'))+'/')
361
+ opts.on('--debug',
362
+ 'Set parser debug mode. Do NOT do this at home!',
363
+ 'Default: off') { |_|
364
+ self.options[:debug] = true
365
+ }
366
+ opts.on('--search-includepath',
367
+ 'Use include paths to find main IDL source.',
368
+ 'Default: off') { |_|
369
+ self.options[:search_incpath] = true
370
+ }
371
+ opts.on('--no-input',
372
+ 'Do not parse specified file(s) as input IDL.',
373
+ 'Default: off') { |_|
374
+ self.options[:no_input] = true
256
375
  }
257
- opts.on("--search-includepath",
258
- "Use include paths to find main IDL source.",
259
- "Default: off") { |v| @options[:search_incpath]=v }
260
376
  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 }
377
+ opts.on('--output=FILE', String,
378
+ 'Specifies filename to generate output in.',
379
+ 'Default: basename(idlfile)-\'.idl\'+<postfix>+<ext>') { |v|
380
+ self.options[:output] = v
381
+ }
264
382
  end
265
383
 
266
384
  # setup language mapping specific options
@@ -270,7 +388,7 @@ module IDL
270
388
 
271
389
  opts.on('-V', '--version',
272
390
  'Show version information and exit.') {
273
- puts "RIDL compiler #{@options[:macros][:__RIDL__]}"
391
+ puts "RIDL compiler #{RIDL_VERSION}"
274
392
  puts RIDL_COPYRIGHT
275
393
  puts '---'
276
394
  @backend.print_version
@@ -287,24 +405,57 @@ module IDL
287
405
 
288
406
  end
289
407
 
408
+ def IDL.engine?
409
+ !Thread.current[:ridl_engine].nil?
410
+ end
411
+
290
412
  def IDL.backend
291
413
  Thread.current[:ridl_engine] ? Thread.current[:ridl_engine].backend : nil
292
414
  end
293
415
 
294
416
  def IDL.push_input(idlfile, opts)
295
- Thread.current[:ridl_engine].push_input(idlfile, opts) if Thread.current[:ridl_engine]
417
+ Thread.current[:ridl_engine].push_input(idlfile, opts) if engine?
296
418
  end
297
419
 
298
420
  def IDL.pop_input
299
- Thread.current[:ridl_engine].pop_input if Thread.current[:ridl_engine]
421
+ return nil unless engine?
422
+ Thread.current[:ridl_engine].pop_input
300
423
  end
301
424
 
302
425
  def IDL.peek_input
303
- Thread.current[:ridl_engine].peek_input if Thread.current[:ridl_engine]
426
+ return nil unless engine?
427
+ Thread.current[:ridl_engine].peek_input
304
428
  end
305
429
 
306
430
  def IDL.has_input?
307
- Thread.current[:ridl_engine].has_input? if Thread.current[:ridl_engine]
431
+ engine? && Thread.current[:ridl_engine].has_input?
432
+ end
433
+
434
+ def IDL.push_production(id, producer)
435
+ Thread.current[:ridl_engine].push_production(id, producer) if engine?
436
+ end
437
+
438
+ def IDL.pop_production
439
+ return nil unless engine?
440
+ Thread.current[:ridl_engine].pop_production
441
+ end
442
+
443
+ def IDL.remove_production(id)
444
+ return nil unless engine?
445
+ Thread.current[:ridl_engine].remove_production(id)
446
+ end
447
+
448
+ def IDL.has_productions?
449
+ engine? && Thread.current[:ridl_engine].has_productions?
450
+ end
451
+
452
+ def IDL.has_production?(id)
453
+ engine? && Thread.current[:ridl_engine].has_production?(id)
454
+ end
455
+
456
+ def IDL.production(id)
457
+ return nil unless engine?
458
+ Thread.current[:ridl_engine].production(id)
308
459
  end
309
460
 
310
461
  def IDL.verbose_level
@@ -327,32 +478,45 @@ module IDL
327
478
  STDERR.puts(message)
328
479
  end
329
480
 
481
+ def IDL.fatal(message)
482
+ STDERR.puts(message, 'Exiting.')
483
+ exit 1
484
+ end
485
+
330
486
  def IDL.init(argv = ARGV)
331
487
  options = OPTIONS.dup
332
488
 
333
- unless @@embedded
334
- # check commandline args for explicit language mapping backend
335
- if argv.first =~ /^:\S+/
336
- @@be_name = argv.shift.reverse.chop.reverse.to_sym
337
- elsif ENV['RIDL_BE_SELECT'] # or from environment
338
- @@be_name = ENV['RIDL_BE_SELECT'].to_sym
339
- end
489
+ # load config file(s) if any
490
+ Options.load_config(options)
340
491
 
341
- # add optional search paths for RIDL backends
342
- $:.concat(ENV['RIDL_BE_PATH'].split(/:|;/)) if ENV['RIDL_BE_PATH']
492
+ IDL.log(2, "Configuration [#{options}]")
343
493
 
344
- # check for special bootstrapping switches
345
- if argv.first == '--preprocess'
346
- options[:preprocess] = true
347
- argv.shift
348
- elsif argv.first == '--ignore-pidl'
349
- options[:ignore_pidl] = true
350
- argv.shift
351
- end
494
+ # check commandline args for explicit language mapping backend
495
+ if argv.first =~ /^:\S+/
496
+ be_name = argv.shift.reverse.chop.reverse.to_sym
497
+ elsif ENV['RIDL_BE_SELECT'] # or from environment
498
+ be_name = ENV['RIDL_BE_SELECT'].to_sym
499
+ elsif options[:backend] # or from configuration
500
+ be_name = options[:backend].to_sym
501
+ end
502
+
503
+ # add optional search paths for RIDL backends
504
+ options[:be_path] ||= []
505
+ options[:be_path].unshift(*ENV['RIDL_BE_PATH'].split(/#{File::PATH_SEPARATOR}/)) if ENV['RIDL_BE_PATH']
506
+ options[:be_path].collect! {|p| p.gsub('\\', '/') } # cleanup to prevent mixed path separators
507
+ $:.concat(options[:be_path]) unless options[:be_path].empty?
508
+
509
+ # check for special bootstrapping switches
510
+ if argv.first == '--preprocess'
511
+ options[:preprocess] = true
512
+ argv.shift
513
+ elsif argv.first == '--ignore-pidl'
514
+ options[:ignore_pidl] = true
515
+ argv.shift
352
516
  end
353
517
 
354
518
  # create RIDL engine
355
- Thread.current[:ridl_engine] = Engine.new(@@be_name, options)
519
+ Thread.current[:ridl_engine] = Engine.new(be_name, options)
356
520
  end
357
521
 
358
522
  # main run method